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