xref: /csrg-svn/sys/kern/vfs_lookup.c (revision 30)
1*30Sbill /*	vfs_lookup.c	3.1	10/14/12	*/
2*30Sbill 
3*30Sbill #include "../h/param.h"
4*30Sbill #include "../h/systm.h"
5*30Sbill #include "../h/inode.h"
6*30Sbill #include "../h/mount.h"
7*30Sbill #include "../h/dir.h"
8*30Sbill #include "../h/user.h"
9*30Sbill #include "../h/buf.h"
10*30Sbill 
11*30Sbill /*
12*30Sbill  * Convert a pathname into a pointer to
13*30Sbill  * an inode. Note that the inode is locked.
14*30Sbill  *
15*30Sbill  * func = function called to get next char of name
16*30Sbill  *	&uchar if name is in user space
17*30Sbill  *	&schar if name is in system space
18*30Sbill  * flag = 0 if name is sought
19*30Sbill  *	1 if name is to be created
20*30Sbill  *	2 if name is to be deleted
21*30Sbill  */
22*30Sbill struct inode *
23*30Sbill namei(func, flag)
24*30Sbill int (*func)();
25*30Sbill {
26*30Sbill 	register struct inode *dp;
27*30Sbill 	register c;
28*30Sbill 	register char *cp;
29*30Sbill 	struct buf *bp;
30*30Sbill 	int i;
31*30Sbill 	dev_t d;
32*30Sbill 	off_t eo;
33*30Sbill 
34*30Sbill 	/*
35*30Sbill 	 * If name starts with '/' start from
36*30Sbill 	 * root; otherwise start from current dir.
37*30Sbill 	 */
38*30Sbill 
39*30Sbill 	dp = u.u_cdir;
40*30Sbill 	if((c=(*func)()) == '/')
41*30Sbill 		if ((dp = u.u_rdir) == NULL)
42*30Sbill 			dp = rootdir;
43*30Sbill 	VOID iget(dp->i_dev, dp->i_number);
44*30Sbill 	while(c == '/')
45*30Sbill 		c = (*func)();
46*30Sbill 	if(c == '\0' && flag != 0)
47*30Sbill 		u.u_error = ENOENT;
48*30Sbill 
49*30Sbill cloop:
50*30Sbill 	/*
51*30Sbill 	 * Here dp contains pointer
52*30Sbill 	 * to last component matched.
53*30Sbill 	 */
54*30Sbill 
55*30Sbill 	if(u.u_error)
56*30Sbill 		goto out;
57*30Sbill 	if(c == '\0')
58*30Sbill 		return(dp);
59*30Sbill 
60*30Sbill 	/*
61*30Sbill 	 * If there is another component,
62*30Sbill 	 * Gather up name into
63*30Sbill 	 * users' dir buffer.
64*30Sbill 	 */
65*30Sbill 
66*30Sbill 	cp = &u.u_dbuf[0];
67*30Sbill 	while (c != '/' && c != '\0' && u.u_error == 0 ) {
68*30Sbill 		if (mpxip!=NULL && c=='!')
69*30Sbill 			break;
70*30Sbill 		if(cp < &u.u_dbuf[DIRSIZ])
71*30Sbill 			*cp++ = c;
72*30Sbill 		c = (*func)();
73*30Sbill 	}
74*30Sbill 	while(cp < &u.u_dbuf[DIRSIZ])
75*30Sbill 		*cp++ = '\0';
76*30Sbill 	while(c == '/')
77*30Sbill 		c = (*func)();
78*30Sbill 	if (c == '!' && mpxip != NULL) {
79*30Sbill 		iput(dp);
80*30Sbill 		plock(mpxip);
81*30Sbill 		mpxip->i_count++;
82*30Sbill 		return(mpxip);
83*30Sbill 	}
84*30Sbill 
85*30Sbill seloop:
86*30Sbill 	/*
87*30Sbill 	 * dp must be a directory and
88*30Sbill 	 * must have X permission.
89*30Sbill 	 */
90*30Sbill 
91*30Sbill 	if((dp->i_mode&IFMT) != IFDIR)
92*30Sbill 		u.u_error = ENOTDIR;
93*30Sbill 	VOID access(dp, IEXEC);
94*30Sbill 	if(u.u_error)
95*30Sbill 		goto out;
96*30Sbill 
97*30Sbill 	/*
98*30Sbill 	 * set up to search a directory
99*30Sbill 	 */
100*30Sbill 	u.u_offset = 0;
101*30Sbill 	u.u_segflg = 1;
102*30Sbill 	eo = 0;
103*30Sbill 	bp = NULL;
104*30Sbill 
105*30Sbill eloop:
106*30Sbill 
107*30Sbill 	/*
108*30Sbill 	 * If at the end of the directory,
109*30Sbill 	 * the search failed. Report what
110*30Sbill 	 * is appropriate as per flag.
111*30Sbill 	 */
112*30Sbill 
113*30Sbill 	if(u.u_offset >= dp->i_size) {
114*30Sbill 		if(bp != NULL)
115*30Sbill 			brelse(bp);
116*30Sbill 		if(flag==1 && c=='\0') {
117*30Sbill 			if(access(dp, IWRITE))
118*30Sbill 				goto out;
119*30Sbill 			u.u_pdir = dp;
120*30Sbill 			if(eo)
121*30Sbill 				u.u_offset = eo-sizeof(struct direct);
122*30Sbill 			else
123*30Sbill 				dp->i_flag |= IUPD|ICHG;
124*30Sbill 			return(NULL);
125*30Sbill 		}
126*30Sbill 		u.u_error = ENOENT;
127*30Sbill 		goto out;
128*30Sbill 	}
129*30Sbill 
130*30Sbill 	/*
131*30Sbill 	 * If offset is on a block boundary,
132*30Sbill 	 * read the next directory block.
133*30Sbill 	 * Release previous if it exists.
134*30Sbill 	 */
135*30Sbill 
136*30Sbill 	if((u.u_offset&BMASK) == 0) {
137*30Sbill 		if(bp != NULL)
138*30Sbill 			brelse(bp);
139*30Sbill 		bp = bread(dp->i_dev,
140*30Sbill 			bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
141*30Sbill 		if (bp->b_flags & B_ERROR) {
142*30Sbill 			brelse(bp);
143*30Sbill 			goto out;
144*30Sbill 		}
145*30Sbill 	}
146*30Sbill 
147*30Sbill 	/*
148*30Sbill 	 * Note first empty directory slot
149*30Sbill 	 * in eo for possible creat.
150*30Sbill 	 * String compare the directory entry
151*30Sbill 	 * and the current component.
152*30Sbill 	 * If they do not match, go back to eloop.
153*30Sbill 	 */
154*30Sbill 
155*30Sbill 	bcopy(bp->b_un.b_addr+(u.u_offset&BMASK), (caddr_t)&u.u_dent,
156*30Sbill 		sizeof(struct direct));
157*30Sbill 	u.u_offset += sizeof(struct direct);
158*30Sbill 	if(u.u_dent.d_ino == 0) {
159*30Sbill 		if(eo == 0)
160*30Sbill 			eo = u.u_offset;
161*30Sbill 		goto eloop;
162*30Sbill 	}
163*30Sbill 	for(i=0; i<DIRSIZ; i++) {
164*30Sbill 		if(u.u_dbuf[i] != u.u_dent.d_name[i])
165*30Sbill 			goto eloop;
166*30Sbill 		if(u.u_dbuf[i] == 0)
167*30Sbill 			break;
168*30Sbill 	}
169*30Sbill 
170*30Sbill 	/*
171*30Sbill 	 * Here a component matched in a directory.
172*30Sbill 	 * If there is more pathname, go back to
173*30Sbill 	 * cloop, otherwise return.
174*30Sbill 	 */
175*30Sbill 
176*30Sbill 	if(bp != NULL)
177*30Sbill 		brelse(bp);
178*30Sbill 	if(flag==2 && c=='\0') {
179*30Sbill 		if(access(dp, IWRITE))
180*30Sbill 			goto out;
181*30Sbill 		return(dp);
182*30Sbill 	}
183*30Sbill 	d = dp->i_dev;
184*30Sbill 	if(u.u_dent.d_ino == ROOTINO)
185*30Sbill 	if(dp->i_number == ROOTINO)
186*30Sbill 	if(u.u_dent.d_name[1] == '.')
187*30Sbill 		for(i=1; i<NMOUNT; i++)
188*30Sbill 			if(mount[i].m_bufp != NULL)
189*30Sbill 			if(mount[i].m_dev == d) {
190*30Sbill 				iput(dp);
191*30Sbill 				dp = mount[i].m_inodp;
192*30Sbill 				dp->i_count++;
193*30Sbill 				plock(dp);
194*30Sbill 				goto seloop;
195*30Sbill 			}
196*30Sbill 	iput(dp);
197*30Sbill 	dp = iget(d, u.u_dent.d_ino);
198*30Sbill 	if(dp == NULL)
199*30Sbill 		return(NULL);
200*30Sbill 	goto cloop;
201*30Sbill 
202*30Sbill out:
203*30Sbill 	iput(dp);
204*30Sbill 	return(NULL);
205*30Sbill }
206*30Sbill 
207*30Sbill /*
208*30Sbill  * Return the next character from the
209*30Sbill  * kernel string pointed at by dirp.
210*30Sbill  */
211*30Sbill schar()
212*30Sbill {
213*30Sbill 
214*30Sbill 	return(*u.u_dirp++ & 0377);
215*30Sbill }
216*30Sbill 
217*30Sbill /*
218*30Sbill  * Return the next character from the
219*30Sbill  * user string pointed at by dirp.
220*30Sbill  */
221*30Sbill uchar()
222*30Sbill {
223*30Sbill 	register c;
224*30Sbill 
225*30Sbill 	c = fubyte(u.u_dirp++);
226*30Sbill 	if(c == -1)
227*30Sbill 		u.u_error = EFAULT;
228*30Sbill 	return(c);
229*30Sbill }
230