7500: #
7501: #include "../param.h"
7502: #include "../inode.h"
7503: #include "../user.h"
7504: #include "../systm.h"
7505: #include "../buf.h"
7506:
7507: /*
7508: * Convert a pathname into a pointer to
7509: * an inode. Note that the inode is locked.
7510: *
7511: * func = function called to get next char of name
7512: * &uchar if name is in user space
7513: * &schar if name is in system space
7514: * flag = 0 if name is sought
7515: * 1 if name is to be created
7516: * 2 if name is to be deleted
7517: */
7518: namei(func, flag)
7519: int (*func)();
7520: {
7521: register struct inode *dp;
7522: register c;
7523: register char *cp;
7524: int eo, *bp;
7525:
7526: /*
7527: * If name starts with '/' start from
7528: * root; otherwise start from current dir.
7529: */
7530:
7531: dp = u.u_cdir;
7532: if((c=(*func)()) == '/')
7533: dp = rootdir;
7534: iget(dp->i_dev, dp->i_number);
7535: while(c == '/')
7536: c = (*func)();
7537: if(c == '\0' && flag != 0) {
7538: u.u_error = ENOENT;
7539: goto out;
7540: }
7541:
7542: cloop:
7543: /*
7544: * Here dp contains pointer
7545: * to last component matched.
7546: */
7547:
7548: if(u.u_error)
7549: goto out;
7550: if(c == '\0')
7551: return(dp);
7552:
7553: /*
7554: * If there is another component,
7555: * dp must be a directory and
7556: * must have x permission.
7557: */
7558:
7559: if((dp->i_mode&IFMT) != IFDIR) {
7560: u.u_error = ENOTDIR;
7561: goto out;
7562: }
7563: if(access(dp, IEXEC))
7564: goto out;
7565:
7566: /* Gather up name into
7567: * users' dir buffer.
7568: */
7569:
7570: cp = &u.u_dbuf[0];
7571: while(c!='/' && c!='\0' && u.u_error==0) {
7572: if(cp < &u.u_dbuf[DIRSIZ])
7573: *cp++ = c;
7574: c = (*func)();
7575: }
7576: while(cp < &u.u_dbuf[DIRSIZ])
7577: *cp++ = '\0';
7578: while(c == '/')
7579: c = (*func)();
7580: if(u.u_error)
7581: goto out;
7582:
7583: /* Set up to search a directory. */
7584:
7585: u.u_offset[1] = 0;
7586: u.u_offset[0] = 0;
7587: u.u_segflg = 1;
7588: eo = 0;
7589: u.u_count = ldiv(dp->i_size1, DIRSIZ+2);
7590: bp = NULL;
7591:
7592: eloop:
7593:
7594: /*
7595: * If at the end of the directory,
7596: * the search failed. Report what
7597: * is appropriate as per flag.
7598: */
7599:
7600: if(u.u_count == 0) {
7601: if(bp != NULL)
7602: brelse(bp);
7603: if(flag==1 && c=='\0') {
7604: if(access(dp, IWRITE))
7605: goto out;
7606: u.u_pdir = dp;
7607: if(eo)
7608: u.u_offset[1] = eo-DIRSIZ-2; else
7609: dp->i_flag =| IUPD;
7610: return(NULL);
7611: }
7612: u.u_error = ENOENT;
7613: goto out;
7614: }
7615:
7616: /*
7617: * If offset is on a block boundary,
7618: * read the next directory block.
7619: * Release previous if it exists.
7620: */
7621:
7622: if((u.u_offset[1]&0777) == 0) {
7623: if(bp != NULL)
7624: brelse(bp);
7625: bp = bread(dp->i_dev,
7626: bmap(dp, ldiv(u.u_offset[1], 512)));
7627: }
7628:
7629: /* Note first empty directory slot
7630: * in eo for possible creat.
7631: * String compare the directory entry
7632: * and the current component.
7633: * If they do not match, go back to eloop.
7634: */
7635:
7636: bcopy(bp->b_addr+(u.u_offset[1]&0777), &u.u_dent, (DIRSIZ+2)/2);
7637:
7638: u.u_offset[1] =+ DIRSIZ+2;
7639: u.u_count--;
7640: if(u.u_dent.u_ino == 0) {
7641: if(eo == 0)
7642: eo = u.u_offset[1];
7643: goto eloop;
7644: }
7645: for(cp = &u.u_dbuf[0]; cp < &u.u_dbuf[DIRSIZ]; cp++)
7646: if(*cp != cp[u.u_dent.u_name - u.u_dbuf])
7647: goto eloop;
7648:
7649:
7650: /* Here a component matched in a directory.
7651: * If there is more pathname, go back to
7652: * cloop, otherwise return.
7653: */
7654:
7655: if(bp != NULL)
7656: brelse(bp);
7657: if(flag==2 && c=='\0') {
7658: if(access(dp, IWRITE))
7659: goto out;
7660: return(dp);
7661: }
7662: bp = dp->i_dev;
7663: iput(dp);
7664: dp = iget(bp, u.u_dent.u_ino);
7665: if(dp == NULL)
7666: return(NULL);
7667: goto cloop;
7668:
7669: out:
7670: iput(dp);
7671: return(NULL);
7672: }
7673: /* --------------------------- */
7674:
7675: /*
7676: * Return the next character from the
7677: * kernel string pointed at by dirp.
7678: */
7679: schar()
7680: {
7681:
7682: return(*u.u_dirp++ & 0377);
7683: }
7684: /* --------------------------- */
7685:
7686: /* Return the next character from the
7687: * user string pointed at by dirp.
7688: */
7689: uchar()
7690: {
7691: register c;
7692:
7693: c = fubyte(u.u_dirp++);
7694: if(c == -1)
7695: u.u_error = EFAULT;
7696: return(c);
7697: }
7698: /* --------------------------- */