xref: /netbsd/sys/fs/adosfs/adutil.c (revision 6550d01e)
1 /*	$NetBSD: adutil.c,v 1.13 2010/07/21 17:52:09 hannken Exp $	*/
2 
3 /*
4  * Copyright (c) 1994 Christian E. Hopps
5  * Copyright (c) 1996 Matthias Scheler
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Christian E. Hopps.
19  * 4. The name of the author may not be used to endorse or promote products
20  *    derived from this software without specific prior written permission
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: adutil.c,v 1.13 2010/07/21 17:52:09 hannken Exp $");
36 
37 #include <sys/param.h>
38 #include <sys/vnode.h>
39 #include <sys/mount.h>
40 #include <sys/proc.h>
41 #include <sys/systm.h>
42 #include <sys/malloc.h>
43 #include <sys/time.h>
44 #include <sys/queue.h>
45 #include <sys/buf.h>
46 #include <sys/simplelock.h>
47 #include <fs/adosfs/adosfs.h>
48 
49 /*
50  * look for anode in the mount's hash table, return locked.
51  */
52 #define AHASH(an) ((an) & (ANODEHASHSZ - 1))
53 static int CapitalChar(int, int);
54 
55 extern struct simplelock adosfs_hashlock;
56 
57 struct vnode *
58 adosfs_ahashget(struct mount *mp, ino_t an)
59 {
60 	struct anodechain *hp;
61 	struct anode *ap;
62 	struct vnode *vp;
63 
64 	hp = &VFSTOADOSFS(mp)->anodetab[AHASH(an)];
65 
66 start_over:
67 	simple_lock(&adosfs_hashlock);
68 	for (ap = hp->lh_first; ap != NULL; ap = ap->link.le_next) {
69 		if (ap->block == an) {
70 			vp = ATOV(ap);
71 			mutex_enter(&vp->v_interlock);
72 			simple_unlock(&adosfs_hashlock);
73 			if (vget(vp, LK_EXCLUSIVE))
74 				goto start_over;
75 			return (ATOV(ap));
76 		}
77 	}
78 	simple_unlock(&adosfs_hashlock);
79 	return (NULL);
80 }
81 
82 /*
83  * insert in hash table and lock
84  *
85  * ap->vp must have been initialized before this call.
86  */
87 void
88 adosfs_ainshash(struct adosfsmount *amp, struct anode *ap)
89 {
90 	VOP_LOCK(ATOV(ap), LK_EXCLUSIVE);
91 
92 	simple_lock(&adosfs_hashlock);
93 	LIST_INSERT_HEAD(&amp->anodetab[AHASH(ap->block)], ap, link);
94 	simple_unlock(&adosfs_hashlock);
95 }
96 
97 void
98 adosfs_aremhash(struct anode *ap)
99 {
100 	simple_lock(&adosfs_hashlock);
101 	LIST_REMOVE(ap, link);
102 	simple_unlock(&adosfs_hashlock);
103 }
104 
105 int
106 adosfs_getblktype(struct adosfsmount *amp, struct buf *bp)
107 {
108 	if (adoscksum(bp, amp->nwords)) {
109 #ifdef DIAGNOSTIC
110 		printf("adosfs: aget: cksum of blk %" PRId64 " failed\n",
111 		    bp->b_blkno / (amp->bsize / DEV_BSIZE));
112 #endif
113 		return (-1);
114 	}
115 
116 	/*
117 	 * check primary block type
118 	 */
119 	if (adoswordn(bp, 0) != BPT_SHORT) {
120 #ifdef DIAGNOSTIC
121 		printf("adosfs: aget: bad primary type blk %" PRId64 " (type = %d)\n",
122 		    bp->b_blkno / (amp->bsize / DEV_BSIZE), adoswordn(bp,0));
123 #endif
124 		return (-1);
125 	}
126 
127 	/*
128 	 * Check secondary block type.
129 	 */
130 	switch (adoswordn(bp, amp->nwords - 1)) {
131 	case BST_RDIR:		/* root block */
132 		return (AROOT);
133 	case BST_LDIR:		/* hard link to dir */
134 		return (ALDIR);
135 	case BST_UDIR:		/* user dir */
136 		return (ADIR);
137 	case BST_LFILE:		/* hard link to file */
138 		return (ALFILE);
139 	case BST_FILE:		/* file header */
140 		return (AFILE);
141 	case BST_SLINK:		/* soft link */
142 		return (ASLINK);
143 	}
144 
145 #ifdef DIAGNOSTIC
146 	printf("adosfs: aget: bad secondary type blk %" PRId64 " (type = %d)\n",
147 	    bp->b_blkno / (amp->bsize / DEV_BSIZE), adoswordn(bp, amp->nwords - 1));
148 #endif
149 
150 	return (-1);
151 }
152 
153 int
154 adunixprot(int adprot)
155 {
156 	if (adprot & 0xc000ee00) {
157 		adprot = (adprot & 0xee0e) >> 1;
158 		return (((adprot & 0x7) << 6) |
159 			((adprot & 0x700) >> 5) |
160 			((adprot & 0x7000) >> 12));
161 	}
162 	else {
163 		adprot = (adprot >> 1) & 0x7;
164 		return((adprot << 6) | (adprot << 3) | adprot);
165 	}
166 }
167 
168 static int
169 CapitalChar(int ch, int inter)
170 {
171 	if ((ch >= 'a' && ch <= 'z') ||
172 	    (inter && ch >= 0xe0 && ch <= 0xfe && ch != 0xf7))
173 		return(ch - ('a' - 'A'));
174 	return(ch);
175 }
176 
177 u_int32_t
178 adoscksum(struct buf *bp, int n)
179 {
180 	u_int32_t sum, *lp;
181 
182 	lp = (u_int32_t *)bp->b_data;
183 	sum = 0;
184 
185 	while (n--)
186 		sum += ntohl(*lp++);
187 	return(sum);
188 }
189 
190 int
191 adoscaseequ(const u_char *name1, const u_char *name2, int len, int inter)
192 {
193 	while (len-- > 0)
194 		if (CapitalChar(*name1++, inter) !=
195 		    CapitalChar(*name2++, inter))
196 			return 0;
197 
198 	return 1;
199 }
200 
201 int
202 adoshash(const u_char *nam, int namlen, int nelt, int inter)
203 {
204 	int val;
205 
206 	val = namlen;
207 	while (namlen--)
208 		val = ((val * 13) + CapitalChar(*nam++, inter)) & 0x7ff;
209 	return(val % nelt);
210 }
211 
212 #ifdef notyet
213 /*
214  * datestamp is local time, tv is to be UTC
215  */
216 int
217 dstotv(struct datestamp *dsp, struct timeval *tvp)
218 {
219 }
220 
221 /*
222  * tv is UTC, datestamp is to be local time
223  */
224 int
225 tvtods(struct timeval *tvp, struct datestamp *dsp)
226 {
227 }
228 #endif
229 
230 #if BYTE_ORDER != BIG_ENDIAN
231 u_int32_t
232 adoswordn(struct buf *bp, int wn)
233 {
234 	/*
235 	 * ados stored in network (big endian) order
236 	 */
237 	return(ntohl(*((u_int32_t *)bp->b_data + wn)));
238 }
239 #endif
240