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