Annotation of researchv10dc/sys/fs/fsnami.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * namei code for fs filesystem
        !             3:  */
        !             4: 
        !             5: #include "sys/param.h"
        !             6: #include "sys/systm.h"
        !             7: #include "sys/inode.h"
        !             8: #include "sys/buf.h"
        !             9: #include "sys/filsys.h"
        !            10: #include "sys/dir.h"
        !            11: #include "sys/user.h"
        !            12: 
        !            13: struct dent {
        !            14:        struct direct dir;
        !            15:        off_t   off;
        !            16:        int     nentry;
        !            17: };
        !            18: 
        !            19: fsnami(p, flagp, follow)
        !            20: struct nx *p;
        !            21: register struct argnamei *flagp;
        !            22: {
        !            23:        register struct inode *dp;
        !            24:        register char *cp;
        !            25:        register struct buf *bp;
        !            26:        register struct inode *dip;
        !            27:        register int i;
        !            28:        struct dent dent;
        !            29:        struct inode *domkfile();
        !            30:        ino_t dsearch();
        !            31: 
        !            32:        cp = p->cp;
        !            33:        dp = p->dp;
        !            34: 
        !            35:        /*
        !            36:         * dp is the inode to search; cp is the pathname to find.
        !            37:         * dp must be a directory, with execute permissions.
        !            38:         * (this test is done too early; it forbids a filesystem
        !            39:         * consisting of a single file with i-number ROOTINO)
        !            40:         */
        !            41: dirloop:
        !            42:        if((dp->i_mode&IFMT) != IFDIR) {
        !            43:                u.u_error = ENOTDIR;
        !            44:                goto outnull;
        !            45:        }
        !            46:        if (access(dp, IEXEC))
        !            47:                goto outnull;
        !            48:        for (i=0; *cp!='\0' && *cp!='/'; i++) {
        !            49:                if (i >= DIRSIZ) {
        !            50:                        u.u_error = ENOENT;
        !            51:                        goto outnull;
        !            52:                }
        !            53:                dent.dir.d_name[i] = *cp++;
        !            54:        }
        !            55:        while (i < DIRSIZ)
        !            56:                dent.dir.d_name[i++] = '\0';
        !            57:        while (*cp == '/')
        !            58:                cp++;
        !            59:        if (dent.dir.d_name[0] == '\0') {       /* null name, e.g. "/" or "" */
        !            60:                if (flagp->flag != NI_SEARCH) {
        !            61:                        u.u_error = ENOENT;
        !            62:                        goto outnull;
        !            63:                }
        !            64:                /*
        !            65:                 * should pass NI_CREAT too, but dp is known to be a directory
        !            66:                 */
        !            67:                goto out;
        !            68:        }
        !            69:        u.u_segflg = SEGSYS;    /* for various routines that write directories */
        !            70:        if (dsearch(dp, &dent) == 0) {
        !            71:                if (u.u_error)
        !            72:                        goto outnull;
        !            73:                /*
        !            74:                 * name not found
        !            75:                 * if we wanted to create or link, that's OK
        !            76:                 */
        !            77:                if (*cp == 0) switch (flagp->flag) {
        !            78:                case NI_CREAT:
        !            79:                case NI_NXCREAT:
        !            80:                case NI_MKDIR:
        !            81:                case NI_LINK:
        !            82:                        dip = dp;
        !            83:                        dp = domkfile(dip, flagp, &dent);
        !            84:                        iput(dip);
        !            85:                        goto out;
        !            86:                }
        !            87:                u.u_error = ENOENT;
        !            88:                goto outnull;
        !            89:        }
        !            90:        /*
        !            91:         * name found
        !            92:         * did we want to remove it?
        !            93:         * (do before ".." check)
        !            94:         */
        !            95:        if(flagp->flag == NI_DEL && *cp == 0) {
        !            96:                dormfile(dp, &dent);
        !            97:                goto outnull;
        !            98:        }
        !            99:        if(flagp->flag == NI_RMDIR && *cp == 0) {
        !           100:                dormdir(dp, &dent);
        !           101:                goto outnull;
        !           102:        }
        !           103:        /*
        !           104:         * special code for ".." in a root directory
        !           105:         */
        !           106:        if (dent.dir.d_name[0] == '.'
        !           107:        &&  dent.dir.d_name[1] == '.'
        !           108:        &&  dent.dir.d_name[2] == '\0') {
        !           109:                if (dp == rootdir || dp == u.u_rdir)
        !           110:                        goto dirloop;
        !           111:                if (dent.dir.d_ino == ROOTINO && dp->i_number == ROOTINO) {
        !           112:                        dip = dp->i_mpoint;
        !           113:                        i = dp->i_fstyp;
        !           114:                        iput(dp);
        !           115:                        dp = dip;
        !           116:                        plock(dp);
        !           117:                        dp->i_count++;
        !           118:                        while (*--cp == '/')
        !           119:                                ;
        !           120:                        cp--;           /* skip over ".." and / */
        !           121:                        if (dp->i_fstyp != i)
        !           122:                                goto outmore;
        !           123:                        goto dirloop;
        !           124:                }
        !           125:        }
        !           126:        /*
        !           127:         * fetch the inode for the filename we found
        !           128:         */
        !           129:        dip = dp;
        !           130:        prele(dip);
        !           131:        dp = iget(dip, dip->i_dev, dent.dir.d_ino);
        !           132:        if (dp == NULL) {
        !           133:                idec(dip);
        !           134:                goto out;       /* sic */
        !           135:        }
        !           136:        if (dp->i_count == 1 && fsiread(dip, dp) < 0) {
        !           137:                idec(dip);
        !           138:                dp = NULL;      /* fsiread iput it */
        !           139:                goto out;
        !           140:        }
        !           141:        if(dip->i_fstyp != dp->i_fstyp) {
        !           142:                idec(dip);
        !           143:                goto outmore;
        !           144:        }
        !           145:        /*
        !           146:         * symlink?  If so and if wanted, follow.
        !           147:         */
        !           148:        if ((dp->i_mode&IFMT)==IFLNK && (follow || *cp!='\0')) {
        !           149:                char *ocp;
        !           150: 
        !           151:                ocp = cp;
        !           152:                while (*cp++)
        !           153:                        ;
        !           154:                i = cp - ocp;           /* strlen(ocp) + 1 for NUL */
        !           155:                if (dp->i_size > BSIZE(dp->i_dev)
        !           156:                ||  dp->i_size + 1 + i > p->nlen        /* +1 for '/' */
        !           157:                ||  ++p->nlink>8) {
        !           158:                        u.u_error = ELOOP;
        !           159:                        idec(dip);
        !           160:                        goto outnull;
        !           161:                }
        !           162:                cp = p->nbuf;
        !           163:                if (i == 1)     /* empty pathname, just put NUL there */
        !           164:                        cp[dp->i_size] = 0;
        !           165:                else {
        !           166:                        bcopy(ocp, cp + dp->i_size + 1, i);     /* remaining pathname */
        !           167:                        cp[dp->i_size] = '/';
        !           168:                }
        !           169:                bp = bread(dp->i_dev, bmap(dp, (daddr_t)0, B_READ));
        !           170:                if (bp->b_flags & B_ERROR) {
        !           171:                        brelse(bp);
        !           172:                        idec(dip);
        !           173:                        goto outnull;
        !           174:                }
        !           175:                bcopy(bp->b_un.b_addr, cp, dp->i_size); /* new prefix */
        !           176:                brelse(bp);
        !           177:                i = dp->i_fstyp;
        !           178:                iput(dp);
        !           179:                if (*cp != '/')
        !           180:                        dp = dip;
        !           181:                else {
        !           182:                        idec(dip);
        !           183:                        while (*cp == '/')
        !           184:                                cp++;
        !           185:                        if ((dp = u.u_rdir) == NULL)
        !           186:                                dp = rootdir;
        !           187:                        plock(dp);
        !           188:                        dp->i_count++;
        !           189:                }
        !           190:                if (i != dp->i_fstyp)
        !           191:                        goto outmore;
        !           192:                goto dirloop;
        !           193:        }
        !           194:        idec(dip);
        !           195:        /*
        !           196:         * more pathname to walk?
        !           197:         */
        !           198:        if (*cp)
        !           199:                goto dirloop;
        !           200:        /*
        !           201:         * final checks before returning:
        !           202:         * -- some operations are in error if filename exists
        !           203:         * -- save last piece of filename for accounting
        !           204:         */
        !           205:        if (flagp->flag == NI_LINK || flagp->flag == NI_NXCREAT
        !           206:        ||  flagp->flag == NI_MKDIR) {
        !           207:                u.u_error = EEXIST;
        !           208:                goto outnull;
        !           209:        }
        !           210:        if(flagp->flag == NI_SEARCH && flagp->un.buf)
        !           211:                bcopy(dent.dir.d_name, flagp->un.buf,
        !           212:                        MIN(flagp->len, sizeof(dent.dir.d_name)));
        !           213: 
        !           214:        /*
        !           215:         * here to return the inode in dp
        !           216:         */
        !           217: out:
        !           218:        p->dp = dp;
        !           219:        return(0);
        !           220: 
        !           221:        /*
        !           222:         * here to discard dp and return NULL
        !           223:         */
        !           224: outnull:
        !           225:        iput(dp);
        !           226:        p->dp = NULL;
        !           227:        return (0);
        !           228: 
        !           229:        /*
        !           230:         * here if we crossed into another filesystem's domain:
        !           231:         * return dp (the first inode in that filesystem)
        !           232:         * and cp (the remainder of the pathname)
        !           233:         * and value 1, so namei knows it should continue
        !           234:         */
        !           235: outmore:
        !           236:        p->cp = cp;
        !           237:        p->dp = dp;
        !           238:        return (1);
        !           239: }
        !           240: 
        !           241: /*
        !           242:  * create a new file of some sort in directory dp
        !           243:  *   name is in dent->d_name
        !           244:  *   offset is in dent->d_off
        !           245:  *   return inode if it is needed
        !           246:  */
        !           247: struct inode *
        !           248: domkfile(dp, flagp, dent)
        !           249: register struct inode *dp;
        !           250: struct argnamei *flagp;
        !           251: struct dent *dent;
        !           252: {
        !           253:        register struct inode *dip;
        !           254:        struct direct x[2];
        !           255:        register i;
        !           256: 
        !           257:        if(access(dp, IWRITE))
        !           258:                return(NULL);
        !           259:        if (dp->i_nlink == 0) {
        !           260:                u.u_error = EINVAL;
        !           261:                return (NULL);
        !           262:        }
        !           263:        u.u_count = sizeof(struct direct);
        !           264:        u.u_base = (caddr_t)&dent->dir;
        !           265:        u.u_offset = ltoL(dent->off);
        !           266:        switch(flagp->flag) {
        !           267: 
        !           268:        case NI_CREAT:  /* create a new file */
        !           269:        case NI_NXCREAT:
        !           270:                dip = ialloc(dp);
        !           271:                if(dip == NULL)
        !           272:                        return(NULL);
        !           273:                dip->i_flag |= IACC|IUPD|ICHG;
        !           274:                dip->i_mode = flagp->un.mode;
        !           275:                if((dip->i_mode & IFMT) == 0)
        !           276:                        dip->i_mode |= IFREG;
        !           277:                dip->i_nlink = 1;
        !           278:                dip->i_uid = u.u_uid;
        !           279:                dip->i_gid = dp->i_mode & ISGID ? u.u_gid : dp->i_gid;
        !           280:                if (u.u_uid && !groupmember(dip->i_gid))
        !           281:                        dip->i_mode &= ~ISGID;
        !           282:                fsiupdat(dip, &time, &time, 1);
        !           283:                dent->dir.d_ino = dip->i_number;
        !           284:                flagp->un.mode = ~flagp->un.mode;
        !           285:                writei(dp);
        !           286:                return(dip);
        !           287: 
        !           288:        case NI_MKDIR:  /* make a new directory */
        !           289:                dip = ialloc(dp);
        !           290:                if(dip == NULL)
        !           291:                        return(NULL);
        !           292:                dent->dir.d_ino = dip->i_number;
        !           293:                dip->i_mode = flagp->un.mode;
        !           294:                dip->i_nlink = 1;
        !           295:                dip->i_uid = u.u_uid;
        !           296:                dip->i_gid = dp->i_gid;
        !           297:                dip->i_flag |= IACC|IUPD|ICHG;
        !           298:                x[0].d_ino = dip->i_number;
        !           299:                x[1].d_ino = dp->i_number;
        !           300:                for(i = 0; i < DIRSIZ; i++)
        !           301:                        x[0].d_name[i] = x[1].d_name[i] = 0;
        !           302:                x[0].d_name[0] = x[1].d_name[0] = x[1].d_name[1] = '.';
        !           303:                u.u_count = sizeof(x);
        !           304:                u.u_base = (caddr_t)x;
        !           305:                u.u_offset = ltoL(0);
        !           306:                u.u_segflg = SEGSYS;
        !           307:                writei(dip);
        !           308:                if (u.u_error) {
        !           309:                        dip->i_nlink--;
        !           310:                        iput(dip);
        !           311:                        return(NULL);
        !           312:                }
        !           313:                dip->i_nlink++;
        !           314:                dp->i_nlink++;
        !           315:                fsiupdat(dip, &time, &time, 1);
        !           316:                u.u_count = sizeof(struct direct);
        !           317:                u.u_base = (caddr_t)&dent->dir;
        !           318:                u.u_offset = ltoL(dent->off);
        !           319:                writei(dp);
        !           320:                iput(dip);
        !           321:                return(NULL);
        !           322: 
        !           323:        case NI_LINK:   /* make a link */
        !           324:                if(dp->i_dev != flagp->un.il->i_dev) {
        !           325:                        u.u_error = EXDEV;
        !           326:                        return(NULL);
        !           327:                }
        !           328:                dent->dir.d_ino = flagp->un.il->i_number;
        !           329:                writei(dp);
        !           330:                return(NULL);
        !           331:        }
        !           332:        panic("domkfile");
        !           333: }
        !           334: 
        !           335: /*
        !           336:  * delete a non-directory file
        !           337:  */
        !           338: dormfile(dp, dent)
        !           339: register struct inode *dp;
        !           340: register struct dent *dent;
        !           341: {
        !           342:        register struct inode *dip;
        !           343: 
        !           344:        if(access(dp, IWRITE))
        !           345:                return;
        !           346:        if(dp->i_number == dent->dir.d_ino) {   /* for '.' */
        !           347:                dip = dp;
        !           348:                dp->i_count++;
        !           349:        } else {
        !           350:                dip = iget(dp, dp->i_dev, dent->dir.d_ino);
        !           351:                if (dip == NULL)
        !           352:                        return;
        !           353:                if (dip->i_count == 1 && fsiread(dp, dip) < 0)
        !           354:                        return;
        !           355:        }
        !           356:        if(dip->i_mpoint != dp->i_mpoint) {
        !           357:                u.u_error = EBUSY;
        !           358:                iput(dip);
        !           359:                return;
        !           360:        }
        !           361:        if((dip->i_mode&IFMT) == IFDIR && !suser()) {
        !           362:                iput(dip);
        !           363:                return;
        !           364:        }
        !           365:        if(dip->i_flag&ITEXT)
        !           366:                xrele(dip);             /* free busy text */
        !           367:        u.u_base = (caddr_t)&dent->dir;
        !           368:        u.u_count = sizeof(struct direct);
        !           369:        u.u_offset = ltoL(dent->off);
        !           370:        dent->dir.d_ino = 0;
        !           371:        writei(dp);             /* segflg already set*/
        !           372:        dip->i_nlink--;
        !           373:        dip->i_flag |= ICHG;
        !           374:        iput(dip);
        !           375: }
        !           376: 
        !           377: /*
        !           378:  * remove a directory (fsnami)
        !           379:  * dp is inode of containing directory
        !           380:  * dent->dir is the entry (which exists)
        !           381:  * u.u_offset is the offset in containing directory of this entry
        !           382:  */
        !           383: dormdir(dp, dent)
        !           384: register struct inode *dp;
        !           385: register struct dent *dent;
        !           386: {
        !           387:        register struct inode *dip;
        !           388:        register int nentry;
        !           389:        struct dent tdent;
        !           390:        ino_t dotino, dotdotino;
        !           391:        ino_t dsearch();
        !           392: 
        !           393:        if(access(dp, IWRITE))
        !           394:                return;
        !           395:        if(dp->i_number == dent->dir.d_ino
        !           396:         || strncmp(dent->dir.d_name, "..", DIRSIZ)==0) { /* gets "." and "" */
        !           397:                u.u_error = EINVAL;
        !           398:                return;
        !           399:        }
        !           400:        if((dip = iget(dp, dp->i_dev, dent->dir.d_ino)) == NULL)
        !           401:                return;
        !           402:        if(dip->i_number == ROOTINO) {
        !           403:                u.u_error = EINVAL;
        !           404:                iput(dip);
        !           405:                return;
        !           406:        }
        !           407:        if(dip->i_mpoint != dp->i_mpoint) {
        !           408:                u.u_error = EBUSY;
        !           409:                iput(dip);
        !           410:                return;
        !           411:        }
        !           412:        if (dip->i_count == 1 && fsiread(dp, dip) < 0)
        !           413:                return;
        !           414:        if((dip->i_mode & IFMT) != IFDIR) {
        !           415:                u.u_error = ENOTDIR;
        !           416:                iput(dip);
        !           417:                return;
        !           418:        }
        !           419:        /* search for ., .., other entries in dir */
        !           420:        cpdirent("/", &tdent);          /* cannot be found; just count entries */
        !           421:        dsearch(dip, &tdent);
        !           422:        nentry = tdent.nentry;
        !           423:        tdent.dir.d_name[0] = '.';
        !           424:        if (dotino = dsearch(dip, &tdent))
        !           425:                nentry--;
        !           426:        tdent.dir.d_name[1] = '.';
        !           427:        if(dotdotino = dsearch(dip, &tdent))
        !           428:                nentry--;
        !           429:        if (nentry > 0) {
        !           430:                u.u_error = EHASF;      /* removing nonempty directory */
        !           431:                iput(dip);
        !           432:                return;
        !           433:        }
        !           434:        if (dotino) {
        !           435:                if (dip->i_number == dotino)
        !           436:                        dip->i_nlink--;
        !           437:                /* else error? */
        !           438:        }
        !           439:        if (dotdotino) {
        !           440:                if (dp->i_number == dotdotino)
        !           441:                        dp->i_nlink--;
        !           442:                /* else error? */
        !           443:        }
        !           444:        u.u_base = (caddr_t)&dent->dir;
        !           445:        u.u_count = sizeof(struct direct);
        !           446:        u.u_offset = ltoL(dent->off);
        !           447:        dent->dir.d_ino = 0;
        !           448:        writei(dp);
        !           449:        dp->i_flag |= ICHG;
        !           450:        fsiupdat(dp, &time, &time, 1);
        !           451:        dip->i_nlink--;
        !           452:        dip->i_flag |= ICHG;
        !           453:        iput(dip);
        !           454: }
        !           455: 
        !           456: cpdirent(s, dent)
        !           457: register char *s;
        !           458: register struct dent *dent;
        !           459: {
        !           460:        register char *dp = dent->dir.d_name;
        !           461: 
        !           462:        while (dp < &dent->dir.d_name[DIRSIZ]) {
        !           463:                *dp++ = *s;
        !           464:                if (*s)
        !           465:                        s++;
        !           466:        }
        !           467: }
        !           468: 
        !           469: /*
        !           470:  * search directory ip for entry dent->dir.d_name
        !           471:  *  success: return ino, leave dent->dir with copy of entry,
        !           472:  *           dent->off pointing at entry
        !           473:  *          dent->nentry with count of entries
        !           474:  *  fail:    return 0, leave dent->off pointing at empty slot
        !           475:  */
        !           476: ino_t
        !           477: dsearch(ip, dent)
        !           478: struct inode *ip;
        !           479: struct dent *dent;
        !           480: {
        !           481:        register struct direct *dp, *dpe;
        !           482:        register char *nm;
        !           483:        register off_t off;
        !           484:        struct buf *bp;
        !           485:        register int bsize;
        !           486:        register daddr_t n, nblock;
        !           487: 
        !           488:        dent->dir.d_ino = 0;
        !           489:        nm = dent->dir.d_name;
        !           490:        bsize = BSIZE(ip->i_dev);
        !           491:        dent->nentry = 0;
        !           492:        bp = NULL;
        !           493:        dent->off = -1;
        !           494:        nblock = (ip->i_size+bsize-1) / bsize;
        !           495: 
        !           496:        for (n=0, off=0; n<nblock; n++) {
        !           497:                if (bp)
        !           498:                        brelse(bp);
        !           499:                bp = bread(ip->i_dev, bmap(ip, n, B_READ));
        !           500:                if (bp->b_flags & B_ERROR) {
        !           501:                        u.u_error = EIO;
        !           502:                        goto out;
        !           503:                }
        !           504:                dp = (struct direct *)bp->b_un.b_addr;
        !           505:                dpe = &dp[min(bsize, ip->i_size-off) / sizeof(struct direct)];
        !           506:                for (; dp < dpe; dp++, off+=sizeof(struct direct)) {
        !           507:                        if (dp->d_ino == 0) {
        !           508:                                if (dent->off<0)
        !           509:                                        dent->off = off;
        !           510:                                continue;
        !           511:                        }
        !           512:                        dent->nentry++;
        !           513:                        if (nm[2]==dp->d_name[2]        /* hash */
        !           514:                         && strncmp(nm, dp->d_name, DIRSIZ) == 0) {
        !           515:                                dent->off = off;
        !           516:                                dent->dir.d_ino = dp->d_ino;
        !           517:                                goto out;
        !           518:                        }
        !           519:                }
        !           520:        }
        !           521: out:
        !           522:        if (dent->off<0)
        !           523:                dent->off = off;
        !           524:        if (bp)
        !           525:                brelse(bp);
        !           526:        return(dent->dir.d_ino);
        !           527: }
        !           528: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.