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: /* ---------------------------       */