conversion of ino_t from u_short to u_long (making dir entries 32 bytes each)
[unix-history] / usr / src / sys / ufs / ffs / ufs_lookup.c
CommitLineData
aa064819 1/* ufs_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 */
23struct inode *
24namei(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
51cloop:
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
83seloop:
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
106eloop:
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
203out:
204 iput(dp);
205 return(NULL);
206}
207
208/*
209 * Return the next character from the
210 * kernel string pointed at by dirp.
211 */
212schar()
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 */
222uchar()
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}