multiplexore fix
[unix-history] / usr / src / sys / kern / vfs_lookup.c
CommitLineData
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 */
22struct inode *
23namei(func, flag)
24int (*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
50cloop:
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
90seloop:
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
110eloop:
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
207out:
208 iput(dp);
209 return(NULL);
210}
211
212/*
213 * Return the next character from the
214 * kernel string pointed at by dirp.
215 */
216schar()
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 */
226uchar()
227{
228 register c;
229
230 c = fubyte(u.u_dirp++);
231 if(c == -1)
232 u.u_error = EFAULT;
233 return(c);
234}