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