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