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