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