Commit | Line | Data |
---|---|---|
f5039631 | 1 | /* vfs_lookup.c 4.9 82/02/26 */ |
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 | |
f5039631 | 14 | * a locked inode. |
10873320 BJ |
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 | |
f5039631 | 22 | * follow = 1 if links are to be followed at the end of the name |
10873320 BJ |
23 | */ |
24 | struct inode * | |
f5039631 BJ |
25 | namei(func, flag, follow) |
26 | int (*func)(), flag, follow; | |
10873320 BJ |
27 | { |
28 | register struct inode *dp; | |
10873320 | 29 | register char *cp; |
f5039631 | 30 | register struct buf *bp, *nbp; |
cee4ba58 | 31 | register struct direct *ep; |
f5039631 | 32 | int i, nlink; |
10873320 | 33 | dev_t d; |
f5039631 | 34 | ino_t ino; |
10873320 BJ |
35 | off_t eo; |
36 | ||
f5039631 BJ |
37 | /* |
38 | * allocate name buffer; copy name | |
39 | */ | |
40 | nbp = geteblk(); | |
41 | nlink = 0; | |
42 | for (i=0, cp = nbp->b_un.b_addr; *cp = (*func)(); i++) { | |
43 | if (*cp++&0200 && flag==1 || cp >= nbp->b_un.b_addr+BSIZE) { | |
44 | u.u_error = ENOENT; | |
45 | break; | |
46 | } | |
47 | } | |
48 | if (u.u_error) { | |
49 | dp = NULL; | |
50 | goto out1; | |
51 | } | |
52 | cp = nbp->b_un.b_addr; | |
10873320 BJ |
53 | /* |
54 | * If name starts with '/' start from | |
55 | * root; otherwise start from current dir. | |
56 | */ | |
10873320 | 57 | dp = u.u_cdir; |
f5039631 BJ |
58 | if (*cp == '/') { |
59 | while (*cp == '/') | |
60 | cp++; | |
10873320 BJ |
61 | if ((dp = u.u_rdir) == NULL) |
62 | dp = rootdir; | |
10873320 | 63 | } |
f5039631 BJ |
64 | ilock(dp); |
65 | dp->i_count++; | |
10873320 | 66 | |
10873320 BJ |
67 | /* |
68 | * dp must be a directory and | |
69 | * must have X permission. | |
f5039631 | 70 | * cp is a path name relative to that directory. |
10873320 BJ |
71 | */ |
72 | ||
f5039631 | 73 | dirloop: |
aa064819 | 74 | if ((dp->i_mode&IFMT) != IFDIR) |
10873320 | 75 | u.u_error = ENOTDIR; |
cee4ba58 | 76 | (void) access(dp, IEXEC); |
f5039631 BJ |
77 | for (i=0; *cp!='\0' && *cp!='/'; i++) { |
78 | if (i >= DIRSIZ) { | |
79 | u.u_error = ENOENT; | |
80 | break; | |
81 | } | |
82 | u.u_dbuf[i] = *cp++; | |
83 | } | |
aa064819 | 84 | if (u.u_error) |
10873320 | 85 | goto out; |
f5039631 BJ |
86 | while (i < DIRSIZ) |
87 | u.u_dbuf[i++] = '\0'; | |
88 | if (u.u_dbuf[0] == '\0') { /* null name, e.g. "/" or "" */ | |
89 | if (flag) { | |
90 | u.u_error = ENOENT; | |
91 | goto out; | |
92 | } | |
93 | goto out1; | |
94 | } | |
10873320 | 95 | u.u_segflg = 1; |
f5039631 | 96 | eo = -1; |
10873320 BJ |
97 | bp = NULL; |
98 | ||
f5039631 BJ |
99 | for (u.u_offset=0; u.u_offset < dp->i_size; |
100 | u.u_offset += sizeof(struct direct), ep++) { | |
101 | /* | |
102 | * If offset is on a block boundary, | |
103 | * read the next directory block. | |
104 | * Release previous if it exists. | |
105 | */ | |
106 | if ((u.u_offset&BMASK) == 0) { | |
107 | if (bp != NULL) | |
108 | brelse(bp); | |
109 | bp = bread(dp->i_dev, | |
110 | bmap(dp,(daddr_t)(u.u_offset>>BSHIFT), B_READ)); | |
111 | if (bp->b_flags & B_ERROR) { | |
112 | brelse(bp); | |
113 | goto out; | |
114 | } | |
115 | ep = (struct direct *)bp->b_un.b_addr; | |
116 | } | |
117 | /* | |
118 | * Note first empty directory slot | |
119 | * in eo for possible creat. | |
120 | * String compare the directory entry | |
121 | * and the current component. | |
122 | */ | |
123 | if (ep->d_ino == 0) { | |
124 | if (eo < 0) | |
125 | eo = u.u_offset; | |
126 | continue; | |
127 | } | |
128 | if (strncmp(u.u_dbuf, ep->d_name, DIRSIZ) != 0) | |
129 | continue; | |
130 | /* | |
131 | * Here a component matched in a directory. | |
132 | * If there is more pathname, go back to | |
133 | * dirloop, otherwise return. | |
134 | */ | |
135 | bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct)); | |
136 | brelse(bp); | |
137 | if (flag==2 && *cp=='\0') { | |
aa064819 | 138 | if (access(dp, IWRITE)) |
10873320 | 139 | goto out; |
f5039631 BJ |
140 | /* should fix unlink */ |
141 | u.u_offset += sizeof(struct direct); | |
142 | goto out1; | |
10873320 | 143 | } |
f5039631 BJ |
144 | /* |
145 | * Special handling for ".." | |
146 | */ | |
147 | if (u.u_dent.d_name[0]=='.' && u.u_dent.d_name[1]=='.' && | |
148 | u.u_dent.d_name[2]=='\0') { | |
149 | if (dp == u.u_rdir) | |
150 | u.u_dent.d_ino = dp->i_number; | |
151 | else if (u.u_dent.d_ino==ROOTINO && | |
152 | dp->i_number == ROOTINO) { | |
153 | for(i=1; i<NMOUNT; i++) | |
154 | if (mount[i].m_bufp != NULL && | |
155 | mount[i].m_dev == dp->i_dev) { | |
156 | iput(dp); | |
157 | dp = mount[i].m_inodp; | |
158 | ilock(dp); | |
159 | dp->i_count++; | |
160 | cp -= 2; /* back over .. */ | |
161 | goto dirloop; | |
162 | } | |
163 | } | |
164 | } | |
165 | d = dp->i_dev; | |
166 | ino = dp->i_number; | |
167 | iput(dp); | |
168 | dp = iget(d, u.u_dent.d_ino); | |
169 | if (dp == NULL) | |
170 | goto out1; | |
171 | /* | |
172 | * Check for symbolic link | |
173 | */ | |
174 | if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp=='/')) { | |
175 | char *ocp; | |
10873320 | 176 | |
f5039631 BJ |
177 | ocp = cp; |
178 | while (*cp++) | |
179 | ; | |
180 | if (dp->i_size + (cp-ocp) >= BSIZE-1 || ++nlink>8) { | |
181 | u.u_error = ELOOP; | |
182 | goto out; | |
183 | } | |
184 | bcopy(ocp, nbp->b_un.b_addr+dp->i_size, cp-ocp); | |
185 | bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ)); | |
186 | if (bp->b_flags & B_ERROR) { | |
187 | brelse(bp); | |
188 | goto out; | |
189 | } | |
190 | bcopy(bp->b_un.b_addr, nbp->b_un.b_addr, dp->i_size); | |
10873320 | 191 | brelse(bp); |
f5039631 BJ |
192 | cp = nbp->b_un.b_addr; |
193 | iput(dp); | |
194 | if (*cp == '/') { | |
195 | while (*cp == '/') | |
196 | cp++; | |
197 | if ((dp = u.u_rdir) == NULL) | |
198 | dp = rootdir; | |
199 | ilock(dp); | |
200 | dp->i_count++; | |
201 | } else { | |
202 | dp = iget(d, ino); /* retrieve directory */ | |
203 | if (dp == NULL) | |
204 | goto out1; | |
205 | } | |
206 | goto dirloop; | |
10873320 | 207 | } |
f5039631 BJ |
208 | if (*cp == '/') { |
209 | while (*cp == '/') | |
210 | cp++; | |
211 | goto dirloop; | |
212 | } | |
213 | goto out1; | |
10873320 | 214 | } |
10873320 | 215 | /* |
f5039631 | 216 | * Search failed. |
10873320 | 217 | */ |
aa064819 | 218 | if (bp != NULL) |
10873320 | 219 | brelse(bp); |
f5039631 | 220 | if (flag==1 && *cp=='\0' && dp->i_nlink) { |
aa064819 | 221 | if (access(dp, IWRITE)) |
10873320 | 222 | goto out; |
f5039631 BJ |
223 | u.u_pdir = dp; |
224 | if (eo>=0) | |
225 | u.u_offset = eo; | |
226 | dp->i_flag |= IUPD|ICHG; | |
227 | dp = NULL; | |
228 | goto out1; | |
10873320 | 229 | } |
f5039631 | 230 | u.u_error = ENOENT; |
10873320 BJ |
231 | out: |
232 | iput(dp); | |
f5039631 BJ |
233 | dp = NULL; |
234 | out1: | |
235 | brelse(nbp); | |
236 | return (dp); | |
10873320 BJ |
237 | } |
238 | ||
239 | /* | |
240 | * Return the next character from the | |
241 | * kernel string pointed at by dirp. | |
242 | */ | |
243 | schar() | |
244 | { | |
245 | ||
f5039631 | 246 | return (*u.u_dirp++ & 0377); |
10873320 BJ |
247 | } |
248 | ||
249 | /* | |
250 | * Return the next character from the | |
251 | * user string pointed at by dirp. | |
252 | */ | |
253 | uchar() | |
254 | { | |
255 | register c; | |
256 | ||
257 | c = fubyte(u.u_dirp++); | |
f5039631 | 258 | if (c == -1) { |
10873320 | 259 | u.u_error = EFAULT; |
f5039631 BJ |
260 | c = 0; |
261 | } | |
262 | return (c); | |
263 | } | |
264 | ||
265 | #ifndef vax | |
266 | strncmp(s1, s2, len) | |
267 | register char *s1, *s2; | |
268 | register len; | |
269 | { | |
270 | ||
271 | do { | |
272 | if (*s1 != *s2++) | |
273 | return (1); | |
274 | if (*s1++ == '\0') | |
275 | return (0); | |
276 | } while (--len); | |
277 | return (0); | |
10873320 | 278 | } |
f5039631 | 279 | #endif |