Annotation of researchv10no/sys/fs/fsnami.c, revision 1.1.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.