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