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