1: /*
2: * SCCS id @(#)nami.c 2.1 (Berkeley) 8/21/83
3: */
4:
5: #include "param.h"
6: #include <sys/systm.h>
7: #include <sys/inode.h>
8: #include <sys/filsys.h>
9: #include <sys/mount.h>
10: #include <sys/dir.h>
11: #include <sys/user.h>
12: #include <sys/buf.h>
13: #include <sys/quota.h>
14:
15: #ifdef UCB_SYMLINKS
16: #ifndef saveseg5
17: #include <sys/seg.h>
18: #endif
19: #endif
20:
21: /*
22: * Convert a pathname into a pointer to
23: * an inode. Note that the inode is locked.
24: *
25: * func = function called to get next char of name
26: * &uchar if name is in user space
27: * &schar if name is in system space
28: * flag = LOOKUP if name is sought
29: * CREATE if name is to be created
30: * DELETE if name is to be deleted
31: #ifdef UCB_SYMLINKS
32: * follow = 1 if to follow links at end of name
33: #endif
34: */
35: struct inode *
36: #ifdef UCB_SYMLINKS
37: namei(func, flag, follow)
38: #else
39: namei(func, flag)
40: #endif
41: int (*func)();
42: {
43: register struct direct *dirp;
44: struct inode *dp;
45: register c;
46: register char *cp;
47: struct buf *bp;
48: #if defined(UCB_QUOTAS) || defined(UCB_SYMLINKS)
49: struct buf *temp;
50: #endif
51: #ifdef UCB_SYMLINKS
52: int nlink;
53: #endif
54: int i;
55: dev_t d;
56: off_t eo;
57:
58: #ifdef UCB_SYMLINKS
59: nlink = 0;
60: u.u_sbuf = 0;
61: #endif
62: /*
63: * If name starts with '/' start from
64: * root; otherwise start from current dir.
65: */
66:
67: dp = u.u_cdir;
68: if((c=(*func)()) == '/')
69: if ((dp = u.u_rdir) == NULL)
70: dp = rootdir;
71: iget(dp->i_dev, dp->i_number);
72: while(c == '/')
73: c = (*func)();
74: if(c == '\0' && flag != LOOKUP)
75: u.u_error = ENOENT;
76:
77: cloop:
78: /*
79: * Here dp contains pointer
80: * to last component matched.
81: */
82:
83: if(u.u_error)
84: goto out;
85: if(c == '\0')
86: return(dp);
87:
88: /*
89: * If there is another component,
90: * Gather up name into
91: * users' dir buffer.
92: */
93:
94: cp = &u.u_dbuf[0];
95: while (c != '/' && c != '\0' && u.u_error == 0 ) {
96: #ifdef MPX_FILS
97: if (mpxip!=NULL && c=='!')
98: break;
99: #endif
100: if(cp < &u.u_dbuf[DIRSIZ])
101: *cp++ = c;
102: c = (*func)();
103: }
104: while(cp < &u.u_dbuf[DIRSIZ])
105: *cp++ = '\0';
106: while(c == '/')
107: c = (*func)();
108: #ifdef MPX_FILS
109: if (c == '!' && mpxip != NULL) {
110: iput(dp);
111: plock(mpxip);
112: mpxip->i_count++;
113: return(mpxip);
114: }
115: #endif
116:
117: /*
118: * dp must be a directory and
119: * must have X permission.
120: */
121:
122: access(dp, IEXEC);
123: seloop:
124: if((dp->i_mode&IFMT) != IFDIR)
125: u.u_error = ENOTDIR;
126: if(u.u_error)
127: goto out;
128:
129: /*
130: * set up to search a directory
131: */
132: u.u_offset = 0;
133: u.u_segflg = 1;
134: eo = 0;
135: bp = NULL;
136:
137: if (dp == u.u_rdir && u.u_dbuf[0] == '.' &&
138: u.u_dbuf[1] == '.' && u.u_dbuf[2] == 0)
139: goto cloop;
140: eloop:
141:
142: /*
143: * If at the end of the directory,
144: * the search failed. Report what
145: * is appropriate as per flag.
146: */
147:
148: if(u.u_offset >= dp->i_size) {
149: if(bp != NULL) {
150: mapout(bp);
151: brelse(bp);
152: }
153: if(flag==CREATE && c=='\0') {
154: if(access(dp, IWRITE))
155: goto out;
156: u.u_pdir = dp;
157: if(eo)
158: u.u_offset = eo-sizeof(struct direct);
159: else
160: dp->i_flag |= IUPD|ICHG;
161: goto out1;
162: }
163: u.u_error = ENOENT;
164: goto out;
165: }
166:
167: /*
168: * If offset is on a block boundary,
169: * read the next directory block.
170: * Release previous if it exists.
171: */
172:
173: if((u.u_offset&BMASK) == 0) {
174: if(bp != NULL) {
175: mapout(bp);
176: brelse(bp);
177: }
178: bp = bread(dp->i_dev,
179: bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
180: if (bp->b_flags & B_ERROR) {
181: brelse(bp);
182: goto out;
183: }
184: dirp = (struct direct *)mapin(bp);
185: }
186:
187: /*
188: * Note first empty directory slot
189: * in eo for possible creat.
190: * String compare the directory entry
191: * and the current component.
192: * If they do not match, go back to eloop.
193: */
194:
195: u.u_offset += sizeof(struct direct);
196: if(dirp->d_ino == 0) {
197: dirp++;
198: if(eo == 0)
199: eo = u.u_offset;
200: goto eloop;
201: }
202: #ifdef UCB_QUOTAS
203: /*
204: * See if this could be a quota node.
205: */
206: if((dirp->d_name[0] == '.') &&
207: (dirp->d_name[1] == 'q') &&
208: (dirp->d_name[2] == '\0'))
209: {
210: cp = dp->i_quot;
211: /*
212: * If no quota is associated yet or a new quot is
213: * around, then . . .
214: */
215: if (cp == NULL || cp->i_number != dirp->d_ino) {
216: u.u_dent.d_ino = dirp->d_ino;
217: mapout(bp);
218: cp = iget(dp->i_dev, u.u_dent.d_ino);
219: if (cp != NULL) {
220: prele(cp);
221: /*
222: * If not really a quota node then just put away
223: */
224: if (!isquot(cp)) {
225: iput(cp);
226: cp = NULL;
227: }
228: }
229: /*
230: * The value of dirp is still valid because
231: * the buffer can not have been released
232: * between the mapout() above and here,
233: * and there is a static relationship between
234: * buffer headers and the buffers proper.
235: */
236: mapin(bp);
237: if (cp != NULL) {
238: /*
239: * set up hierarchical inode chains
240: * NOTE: this is done wrong since this may
241: * overwrite an inode which has not
242: * been put away yet
243: */
244: cp->i_quot = dp->i_quot;
245: dp->i_quot = cp;
246: }
247: }
248: if (cp != NULL) {
249: /*
250: * Mark the directory as being the original
251: * owner of the quota. This is necessary so
252: * that quotas do not get copied up the tree.
253: */
254: dp->i_flag |= IQUOT;
255:
256: }
257: }
258: #endif
259: for(i=0; i<DIRSIZ; i++) {
260: if(u.u_dbuf[i] != dirp->d_name[i])
261: {
262: dirp++;
263: goto eloop;
264: }
265: if (u.u_dbuf[i] == '\0')
266: break;
267: }
268: u.u_dent = *dirp;
269: /*
270: * Here a component matched in a directory.
271: * If there is more pathname, go back to
272: * cloop, otherwise return.
273: */
274:
275: if(bp != NULL) {
276: mapout(bp);
277: brelse(bp);
278: }
279: if(flag==DELETE && c=='\0') {
280: if(access(dp, IWRITE))
281: goto out;
282: return(dp);
283: }
284: d = dp->i_dev;
285: if ((u.u_dent.d_ino == ROOTINO) && (dp->i_number == ROOTINO)
286: && (u.u_dent.d_name[1] == '.'))
287: for(i=1; i<nmount; i++)
288: if ((mount[i].m_inodp != NULL)
289: && (mount[i].m_dev == d)) {
290: iput(dp);
291: dp = mount[i].m_inodp;
292: dp->i_count++;
293: plock(dp);
294: /*
295: * Note: permission for ROOTINO already checked.
296: */
297: goto seloop;
298: }
299: #if defined(UCB_QUOTAS) || defined(UCB_SYMLINKS)
300: prele(dp);
301: temp = cp = iget(d, u.u_dent.d_ino);
302: if (cp == NULL) {
303: if (dp->i_flag & ILOCK)
304: dp->i_count--;
305: else
306: iput(dp);
307: goto out1;
308: }
309: #ifdef UCB_SYMLINKS
310: if ((((struct inode *)temp)->i_mode&IFMT)==IFLNK && (follow || c)) {
311: struct inode *pdp;
312:
313: pdp = (struct inode *)temp;
314: if (pdp->i_size >= BSIZE-2 || ++nlink>8 || u.u_sbuf || !pdp->i_size) {
315: u.u_error = ELOOP;
316: iput(pdp);
317: goto out;
318: }
319: u.u_sbuf = bread(pdp->i_dev, bmap(pdp, (daddr_t)0, B_READ));
320: if (u.u_sbuf->b_flags & B_ERROR) {
321: brelse(u.u_sbuf);
322: iput(pdp);
323: u.u_sbuf = 0;
324: goto out;
325: }
326: /* Save our readahead chars at end of buffer, get first */
327: /* symbolic link character */
328: {
329: segm save5;
330: char *cp;
331:
332: if (c) /* space for readahead chars */
333: u.u_slength = pdp->i_size+2;
334: else u.u_slength = pdp->i_size+1;
335: u.u_soffset = 0;
336: saveseg5(save5);
337: mapin(u.u_sbuf);
338: cp = (char *)SEG5;
339: if (c)
340: cp[u.u_slength-2] = '/';
341: cp[u.u_slength-1] = c;
342: c = cp[u.u_soffset++];
343: mapout(u.u_sbuf);
344: restorseg5(save5);
345: }
346:
347: /* Grab the top-level inode for the new path */
348: iput(pdp);
349: if (c == '/') {
350: iput(dp);
351: if ((dp = u.u_rdir) == NULL)
352: dp = rootdir;
353: while (c == '/')
354: c = (*func)();
355: iget(dp->i_dev, dp->i_number);
356: }
357: else plock(dp);
358: goto cloop;
359: }
360: #ifndef UCB_QUOTAS
361: else {
362: iput(dp);
363: dp = (struct inode *)temp;
364: }
365: #endif
366: #endif UCB_SYMLINKS
367: #ifdef UCB_QUOTAS
368: /*
369: * Make sure not to copy the quota node up the tree past
370: * the original height.
371: */
372: if ((dp->i_flag & IQUOT) && u.u_dent.d_name[0] == '.'
373: && u.u_dent.d_name[1] == '.' && u.u_dent.d_name[2] == '\0')
374: cp = dp->i_quot;
375: /*
376: * Copy quota to new inode
377: */
378: qcopy(dp, cp);
379: if (dp->i_flag & ILOCK)
380: dp->i_count--;
381: else
382: iput(dp);
383: dp = temp;
384: #endif
385: #else
386: iput(dp);
387: dp = iget(d, u.u_dent.d_ino);
388: if(dp == NULL)
389: goto out1;
390: #endif
391: goto cloop;
392:
393: out:
394: iput(dp);
395: out1:
396: #ifdef UCB_SYMLINKS
397: if (u.u_sbuf) {
398: brelse(u.u_sbuf);
399: u.u_sbuf = u.u_slength = u.u_soffset = 0;
400: }
401: #endif
402: return(NULL);
403: }
404:
405: #ifdef UCB_QUOTAS
406: /*
407: * Copy quota from dp to ip if certain conditions hold.
408: */
409: qcopy(dp, ip)
410: register struct inode *dp, *ip;
411: {
412: register struct inode *qp;
413:
414: qp = dp->i_quot;
415: if (qp == NULL || qp == ip)
416: return;
417: if (ip->i_quot != NULL)
418: return;
419: ip->i_quot = qp;
420: if (++(qp->i_count) == 0)
421: panic ("qcopy");
422: }
423: #endif
424:
425: /*
426: * Return the next character from the
427: * kernel string pointed at by dirp.
428: */
429: schar()
430: {
431: #ifdef UCB_SYMLINKS
432: register c;
433:
434: if (u.u_sbuf) {
435: c = symchar();
436: if (c >= 0)
437: return(c);
438: }
439: #endif UCB_SYMLINKS
440: return(*u.u_dirp++ & 0377);
441: }
442:
443: /*
444: * Return the next character from the
445: * user string pointed at by dirp.
446: */
447: uchar()
448: {
449: register c;
450:
451: #ifdef UCB_SYMLINKS
452: if (u.u_sbuf) {
453: c = symchar();
454: if (c >= 0)
455: return(c);
456: }
457: #endif UCB_SYMLINKS
458: c = fubyte(u.u_dirp++);
459: if(c == -1)
460: u.u_error = EFAULT;
461: else if (c&0200)
462: u.u_error = EINVAL;
463: return(c);
464: }
465:
466: #ifdef UCB_SYMLINKS
467: /*
468: * Get a character from the symbolic name buffer
469: */
470: symchar()
471: {
472: segm save5;
473: register char c;
474: register char *cp;
475:
476: if (!u.u_sbuf) /* Protect ourselves */
477: return(-1);
478: if (u.u_soffset > u.u_slength) {
479: brelse(u.u_sbuf);
480: u.u_soffset = u.u_slength = u.u_sbuf = 0;
481: return(-1);
482: }
483:
484: /* Get next character from symbolic link buffer */
485: saveseg5(save5);
486: mapin(u.u_sbuf);
487: cp = (char *)SEG5;
488: c = cp[u.u_soffset++];
489: mapout(u.u_sbuf);
490: restorseg5(save5);
491: if (u.u_soffset >= u.u_slength) {
492: brelse(u.u_sbuf);
493: u.u_soffset = u.u_slength = u.u_sbuf = 0;
494: }
495: return(c);
496: }; /* end of symchar */
497: #endif UCB_SYMLINKS
Defined functions
namei
defined in line
35; used 44 times
- in /usr/src/sys/dev/Others/mx1.c line
200
- in /usr/src/sys/sys/acct.c line
42-44(2)
- in /usr/src/sys/sys/fio.c line
250-252(2)
- in /usr/src/sys/sys/sigjcl.c line
545-547(2)
- in /usr/src/sys/sys/signojcl.c line
255-257(2)
- in /usr/src/sys/sys/sys1.c line
51-53(2),
101-103(2)
- in /usr/src/sys/sys/sys2.c line
124-126(2),
146-148(2),
288-290(2),
311-313(2),
352-354(2),
394-396(2)
- in /usr/src/sys/sys/sys3.c line
57-59(2),
80,
197-199(2),
311-313(2),
339,
382
- in /usr/src/sys/sys/sys4.c line
151-153(2),
233-235(2),
292-294(2)
- in /usr/src/sys/sys/syslocal.c line
98-100(2),
156-158(2)