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

qcopy defined in line 409; used 3 times
schar defined in line 429; used 9 times
symchar defined in line 470; used 2 times
uchar defined in line 447; used 6 times
Last modified: 1983-08-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1092
Valid CSS Valid XHTML 1.0 Strict