get rid of #ifdef CHAOS stuff
[unix-history] / usr / src / sys / kern / vfs_lookup.c
CommitLineData
65a9722c 1/* vfs_lookup.c 4.4 %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"
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;
110
111eloop:
112
113 /*
114 * If at the end of the directory,
115 * the search failed. Report what
116 * is appropriate as per flag.
117 */
118
119 if(u.u_offset >= dp->i_size) {
120 if(bp != NULL)
121 brelse(bp);
7f606d19 122 if(flag==1 && c=='\0' && dp->i_nlink) {
10873320
BJ
123 if(access(dp, IWRITE))
124 goto out;
125 u.u_pdir = dp;
126 if(eo)
127 u.u_offset = eo-sizeof(struct direct);
128 else
129 dp->i_flag |= IUPD|ICHG;
130 return(NULL);
131 }
132 u.u_error = ENOENT;
133 goto out;
134 }
135
136 /*
137 * If offset is on a block boundary,
138 * read the next directory block.
139 * Release previous if it exists.
140 */
141
142 if((u.u_offset&BMASK) == 0) {
143 if(bp != NULL)
144 brelse(bp);
145 bp = bread(dp->i_dev,
146 bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
147 if (bp->b_flags & B_ERROR) {
148 brelse(bp);
149 goto out;
150 }
cee4ba58
BJ
151 ep = (struct direct *)bp->b_un.b_addr;
152 } else
153 ep++;
10873320
BJ
154
155 /*
156 * Note first empty directory slot
157 * in eo for possible creat.
158 * String compare the directory entry
159 * and the current component.
160 * If they do not match, go back to eloop.
161 */
162
10873320 163 u.u_offset += sizeof(struct direct);
cee4ba58 164 if(ep->d_ino == 0) {
10873320
BJ
165 if(eo == 0)
166 eo = u.u_offset;
167 goto eloop;
168 }
169 for(i=0; i<DIRSIZ; i++) {
cee4ba58 170 if(u.u_dbuf[i] != ep->d_name[i])
10873320
BJ
171 goto eloop;
172 if(u.u_dbuf[i] == 0)
173 break;
174 }
175
176 /*
177 * Here a component matched in a directory.
178 * If there is more pathname, go back to
179 * cloop, otherwise return.
180 */
cee4ba58 181 bcopy((caddr_t)ep, (caddr_t)&u.u_dent, sizeof(struct direct));
10873320
BJ
182 if(bp != NULL)
183 brelse(bp);
184 if(flag==2 && c=='\0') {
185 if(access(dp, IWRITE))
186 goto out;
187 return(dp);
188 }
189 d = dp->i_dev;
190 if(u.u_dent.d_ino == ROOTINO)
191 if(dp->i_number == ROOTINO)
192 if(u.u_dent.d_name[1] == '.')
193 for(i=1; i<NMOUNT; i++)
194 if(mount[i].m_bufp != NULL)
195 if(mount[i].m_dev == d) {
196 iput(dp);
197 dp = mount[i].m_inodp;
198 dp->i_count++;
199 plock(dp);
200 goto seloop;
201 }
202 iput(dp);
203 dp = iget(d, u.u_dent.d_ino);
204 if(dp == NULL)
205 return(NULL);
206 goto cloop;
207
208out:
209 iput(dp);
210 return(NULL);
211}
212
213/*
214 * Return the next character from the
215 * kernel string pointed at by dirp.
216 */
217schar()
218{
219
220 return(*u.u_dirp++ & 0377);
221}
222
223/*
224 * Return the next character from the
225 * user string pointed at by dirp.
226 */
227uchar()
228{
229 register c;
230
231 c = fubyte(u.u_dirp++);
232 if(c == -1)
233 u.u_error = EFAULT;
234 return(c);
235}