Annotation of linux/fs/namei.c, revision 1.1.1.2

1.1.1.2 ! root        1: /*
        !             2:  *  linux/fs/namei.c
        !             3:  *
        !             4:  *  (C) 1991  Linus Torvalds
        !             5:  */
        !             6: 
1.1       root        7: #include <linux/sched.h>
                      8: #include <linux/kernel.h>
                      9: #include <asm/segment.h>
                     10: 
                     11: #include <string.h>
                     12: #include <fcntl.h>
                     13: #include <errno.h>
                     14: #include <const.h>
                     15: #include <sys/stat.h>
                     16: 
                     17: #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
                     18: 
                     19: /*
                     20:  * comment out this line if you want names > NAME_LEN chars to be
                     21:  * truncated. Else they will be disallowed.
                     22:  */
                     23: /* #define NO_TRUNCATE */
                     24: 
                     25: #define MAY_EXEC 1
                     26: #define MAY_WRITE 2
                     27: #define MAY_READ 4
                     28: 
                     29: /*
                     30:  *     permission()
                     31:  *
                     32:  * is used to check for read/write/execute permissions on a file.
                     33:  * I don't know if we should look at just the euid or both euid and
                     34:  * uid, but that should be easily changed.
                     35:  */
                     36: static int permission(struct m_inode * inode,int mask)
                     37: {
                     38:        int mode = inode->i_mode;
                     39: 
                     40: /* special case: not even root can read/write a deleted file */
                     41:        if (inode->i_dev && !inode->i_nlinks)
                     42:                return 0;
1.1.1.2 ! root       43:        else if (current->euid==inode->i_uid)
1.1       root       44:                mode >>= 6;
1.1.1.2 ! root       45:        else if (current->egid==inode->i_gid)
1.1       root       46:                mode >>= 3;
1.1.1.2 ! root       47:        if (((mode & mask & 0007) == mask) || suser())
        !            48:                return 1;
        !            49:        return 0;
1.1       root       50: }
                     51: 
                     52: /*
                     53:  * ok, we cannot use strncmp, as the name is not in our data space.
                     54:  * Thus we'll have to use match. No big problem. Match also makes
                     55:  * some sanity tests.
                     56:  *
                     57:  * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
                     58:  */
                     59: static int match(int len,const char * name,struct dir_entry * de)
                     60: {
                     61:        register int same __asm__("ax");
                     62: 
                     63:        if (!de || !de->inode || len > NAME_LEN)
                     64:                return 0;
                     65:        if (len < NAME_LEN && de->name[len])
                     66:                return 0;
                     67:        __asm__("cld\n\t"
                     68:                "fs ; repe ; cmpsb\n\t"
                     69:                "setz %%al"
                     70:                :"=a" (same)
                     71:                :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
                     72:                :"cx","di","si");
                     73:        return same;
                     74: }
                     75: 
                     76: /*
                     77:  *     find_entry()
                     78:  *
                     79:  * finds and entry in the specified directory with the wanted name. It
                     80:  * returns the cache buffer in which the entry was found, and the entry
                     81:  * itself (as a parameter - res_dir). It does NOT read the inode of the
                     82:  * entry - you'll have to do that yourself if you want to.
1.1.1.2 ! root       83:  *
        !            84:  * This also takes care of the few special cases due to '..'-traversal
        !            85:  * over a pseudo-root and a mount point.
1.1       root       86:  */
1.1.1.2 ! root       87: static struct buffer_head * find_entry(struct m_inode ** dir,
1.1       root       88:        const char * name, int namelen, struct dir_entry ** res_dir)
                     89: {
                     90:        int entries;
                     91:        int block,i;
                     92:        struct buffer_head * bh;
                     93:        struct dir_entry * de;
1.1.1.2 ! root       94:        struct super_block * sb;
1.1       root       95: 
                     96: #ifdef NO_TRUNCATE
                     97:        if (namelen > NAME_LEN)
                     98:                return NULL;
                     99: #else
                    100:        if (namelen > NAME_LEN)
                    101:                namelen = NAME_LEN;
                    102: #endif
1.1.1.2 ! root      103:        entries = (*dir)->i_size / (sizeof (struct dir_entry));
1.1       root      104:        *res_dir = NULL;
                    105:        if (!namelen)
                    106:                return NULL;
1.1.1.2 ! root      107: /* check for '..', as we might have to do some "magic" for it */
        !           108:        if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
        !           109: /* '..' in a pseudo-root results in a faked '.' (just change namelen) */
        !           110:                if ((*dir) == current->root)
        !           111:                        namelen=1;
        !           112:                else if ((*dir)->i_num == ROOT_INO) {
        !           113: /* '..' over a mount-point results in 'dir' being exchanged for the mounted
        !           114:    directory-inode. NOTE! We set mounted, so that we can iput the new dir */
        !           115:                        sb=get_super((*dir)->i_dev);
        !           116:                        if (sb->s_imount) {
        !           117:                                iput(*dir);
        !           118:                                (*dir)=sb->s_imount;
        !           119:                                (*dir)->i_count++;
        !           120:                        }
        !           121:                }
        !           122:        }
        !           123:        if (!(block = (*dir)->i_zone[0]))
1.1       root      124:                return NULL;
1.1.1.2 ! root      125:        if (!(bh = bread((*dir)->i_dev,block)))
1.1       root      126:                return NULL;
                    127:        i = 0;
                    128:        de = (struct dir_entry *) bh->b_data;
                    129:        while (i < entries) {
                    130:                if ((char *)de >= BLOCK_SIZE+bh->b_data) {
                    131:                        brelse(bh);
                    132:                        bh = NULL;
1.1.1.2 ! root      133:                        if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
        !           134:                            !(bh = bread((*dir)->i_dev,block))) {
1.1       root      135:                                i += DIR_ENTRIES_PER_BLOCK;
                    136:                                continue;
                    137:                        }
                    138:                        de = (struct dir_entry *) bh->b_data;
                    139:                }
                    140:                if (match(namelen,name,de)) {
                    141:                        *res_dir = de;
                    142:                        return bh;
                    143:                }
                    144:                de++;
                    145:                i++;
                    146:        }
                    147:        brelse(bh);
                    148:        return NULL;
                    149: }
                    150: 
                    151: /*
                    152:  *     add_entry()
                    153:  *
                    154:  * adds a file entry to the specified directory, using the same
                    155:  * semantics as find_entry(). It returns NULL if it failed.
                    156:  *
                    157:  * NOTE!! The inode part of 'de' is left at 0 - which means you
                    158:  * may not sleep between calling this and putting something into
                    159:  * the entry, as someone else might have used it while you slept.
                    160:  */
                    161: static struct buffer_head * add_entry(struct m_inode * dir,
                    162:        const char * name, int namelen, struct dir_entry ** res_dir)
                    163: {
                    164:        int block,i;
                    165:        struct buffer_head * bh;
                    166:        struct dir_entry * de;
                    167: 
                    168:        *res_dir = NULL;
                    169: #ifdef NO_TRUNCATE
                    170:        if (namelen > NAME_LEN)
                    171:                return NULL;
                    172: #else
                    173:        if (namelen > NAME_LEN)
                    174:                namelen = NAME_LEN;
                    175: #endif
                    176:        if (!namelen)
                    177:                return NULL;
                    178:        if (!(block = dir->i_zone[0]))
                    179:                return NULL;
                    180:        if (!(bh = bread(dir->i_dev,block)))
                    181:                return NULL;
                    182:        i = 0;
                    183:        de = (struct dir_entry *) bh->b_data;
                    184:        while (1) {
                    185:                if ((char *)de >= BLOCK_SIZE+bh->b_data) {
                    186:                        brelse(bh);
                    187:                        bh = NULL;
                    188:                        block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
                    189:                        if (!block)
                    190:                                return NULL;
                    191:                        if (!(bh = bread(dir->i_dev,block))) {
                    192:                                i += DIR_ENTRIES_PER_BLOCK;
                    193:                                continue;
                    194:                        }
                    195:                        de = (struct dir_entry *) bh->b_data;
                    196:                }
                    197:                if (i*sizeof(struct dir_entry) >= dir->i_size) {
                    198:                        de->inode=0;
                    199:                        dir->i_size = (i+1)*sizeof(struct dir_entry);
                    200:                        dir->i_dirt = 1;
                    201:                        dir->i_ctime = CURRENT_TIME;
                    202:                }
                    203:                if (!de->inode) {
                    204:                        dir->i_mtime = CURRENT_TIME;
                    205:                        for (i=0; i < NAME_LEN ; i++)
                    206:                                de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
                    207:                        bh->b_dirt = 1;
                    208:                        *res_dir = de;
                    209:                        return bh;
                    210:                }
                    211:                de++;
                    212:                i++;
                    213:        }
                    214:        brelse(bh);
                    215:        return NULL;
                    216: }
                    217: 
                    218: /*
                    219:  *     get_dir()
                    220:  *
                    221:  * Getdir traverses the pathname until it hits the topmost directory.
                    222:  * It returns NULL on failure.
                    223:  */
                    224: static struct m_inode * get_dir(const char * pathname)
                    225: {
                    226:        char c;
                    227:        const char * thisname;
                    228:        struct m_inode * inode;
                    229:        struct buffer_head * bh;
                    230:        int namelen,inr,idev;
                    231:        struct dir_entry * de;
                    232: 
                    233:        if (!current->root || !current->root->i_count)
                    234:                panic("No root inode");
                    235:        if (!current->pwd || !current->pwd->i_count)
                    236:                panic("No cwd inode");
                    237:        if ((c=get_fs_byte(pathname))=='/') {
                    238:                inode = current->root;
                    239:                pathname++;
                    240:        } else if (c)
                    241:                inode = current->pwd;
                    242:        else
                    243:                return NULL;    /* empty name is bad */
                    244:        inode->i_count++;
                    245:        while (1) {
                    246:                thisname = pathname;
                    247:                if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
                    248:                        iput(inode);
                    249:                        return NULL;
                    250:                }
                    251:                for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
                    252:                        /* nothing */ ;
                    253:                if (!c)
                    254:                        return inode;
1.1.1.2 ! root      255:                if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
1.1       root      256:                        iput(inode);
                    257:                        return NULL;
                    258:                }
                    259:                inr = de->inode;
                    260:                idev = inode->i_dev;
                    261:                brelse(bh);
                    262:                iput(inode);
                    263:                if (!(inode = iget(idev,inr)))
                    264:                        return NULL;
                    265:        }
                    266: }
                    267: 
                    268: /*
                    269:  *     dir_namei()
                    270:  *
                    271:  * dir_namei() returns the inode of the directory of the
                    272:  * specified name, and the name within that directory.
                    273:  */
                    274: static struct m_inode * dir_namei(const char * pathname,
                    275:        int * namelen, const char ** name)
                    276: {
                    277:        char c;
                    278:        const char * basename;
                    279:        struct m_inode * dir;
                    280: 
                    281:        if (!(dir = get_dir(pathname)))
                    282:                return NULL;
                    283:        basename = pathname;
                    284:        while (c=get_fs_byte(pathname++))
                    285:                if (c=='/')
                    286:                        basename=pathname;
                    287:        *namelen = pathname-basename-1;
                    288:        *name = basename;
                    289:        return dir;
                    290: }
                    291: 
                    292: /*
                    293:  *     namei()
                    294:  *
                    295:  * is used by most simple commands to get the inode of a specified name.
                    296:  * Open, link etc use their own routines, but this is enough for things
                    297:  * like 'chmod' etc.
                    298:  */
                    299: struct m_inode * namei(const char * pathname)
                    300: {
                    301:        const char * basename;
                    302:        int inr,dev,namelen;
                    303:        struct m_inode * dir;
                    304:        struct buffer_head * bh;
                    305:        struct dir_entry * de;
                    306: 
                    307:        if (!(dir = dir_namei(pathname,&namelen,&basename)))
                    308:                return NULL;
                    309:        if (!namelen)                   /* special case: '/usr/' etc */
                    310:                return dir;
1.1.1.2 ! root      311:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      312:        if (!bh) {
                    313:                iput(dir);
                    314:                return NULL;
                    315:        }
                    316:        inr = de->inode;
                    317:        dev = dir->i_dev;
                    318:        brelse(bh);
                    319:        iput(dir);
                    320:        dir=iget(dev,inr);
                    321:        if (dir) {
                    322:                dir->i_atime=CURRENT_TIME;
                    323:                dir->i_dirt=1;
                    324:        }
                    325:        return dir;
                    326: }
                    327: 
                    328: /*
                    329:  *     open_namei()
                    330:  *
                    331:  * namei for open - this is in fact almost the whole open-routine.
                    332:  */
                    333: int open_namei(const char * pathname, int flag, int mode,
                    334:        struct m_inode ** res_inode)
                    335: {
                    336:        const char * basename;
                    337:        int inr,dev,namelen;
                    338:        struct m_inode * dir, *inode;
                    339:        struct buffer_head * bh;
                    340:        struct dir_entry * de;
                    341: 
                    342:        if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
                    343:                flag |= O_WRONLY;
                    344:        mode &= 0777 & ~current->umask;
                    345:        mode |= I_REGULAR;
                    346:        if (!(dir = dir_namei(pathname,&namelen,&basename)))
                    347:                return -ENOENT;
                    348:        if (!namelen) {                 /* special case: '/usr/' etc */
                    349:                if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
                    350:                        *res_inode=dir;
                    351:                        return 0;
                    352:                }
                    353:                iput(dir);
                    354:                return -EISDIR;
                    355:        }
1.1.1.2 ! root      356:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      357:        if (!bh) {
                    358:                if (!(flag & O_CREAT)) {
                    359:                        iput(dir);
                    360:                        return -ENOENT;
                    361:                }
                    362:                if (!permission(dir,MAY_WRITE)) {
                    363:                        iput(dir);
                    364:                        return -EACCES;
                    365:                }
                    366:                inode = new_inode(dir->i_dev);
                    367:                if (!inode) {
                    368:                        iput(dir);
                    369:                        return -ENOSPC;
                    370:                }
1.1.1.2 ! root      371:                inode->i_uid = current->euid;
1.1       root      372:                inode->i_mode = mode;
                    373:                inode->i_dirt = 1;
                    374:                bh = add_entry(dir,basename,namelen,&de);
                    375:                if (!bh) {
                    376:                        inode->i_nlinks--;
                    377:                        iput(inode);
                    378:                        iput(dir);
                    379:                        return -ENOSPC;
                    380:                }
                    381:                de->inode = inode->i_num;
                    382:                bh->b_dirt = 1;
                    383:                brelse(bh);
                    384:                iput(dir);
                    385:                *res_inode = inode;
                    386:                return 0;
                    387:        }
                    388:        inr = de->inode;
                    389:        dev = dir->i_dev;
                    390:        brelse(bh);
                    391:        iput(dir);
                    392:        if (flag & O_EXCL)
                    393:                return -EEXIST;
                    394:        if (!(inode=iget(dev,inr)))
                    395:                return -EACCES;
                    396:        if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
1.1.1.2 ! root      397:            !permission(inode,ACC_MODE(flag))) {
1.1       root      398:                iput(inode);
                    399:                return -EPERM;
                    400:        }
                    401:        inode->i_atime = CURRENT_TIME;
                    402:        if (flag & O_TRUNC)
                    403:                truncate(inode);
                    404:        *res_inode = inode;
                    405:        return 0;
                    406: }
                    407: 
1.1.1.2 ! root      408: int sys_mknod(const char * filename, int mode, int dev)
        !           409: {
        !           410:        const char * basename;
        !           411:        int namelen;
        !           412:        struct m_inode * dir, * inode;
        !           413:        struct buffer_head * bh;
        !           414:        struct dir_entry * de;
        !           415:        
        !           416:        if (!suser())
        !           417:                return -EPERM;
        !           418:        if (!(dir = dir_namei(filename,&namelen,&basename)))
        !           419:                return -ENOENT;
        !           420:        if (!namelen) {
        !           421:                iput(dir);
        !           422:                return -ENOENT;
        !           423:        }
        !           424:        if (!permission(dir,MAY_WRITE)) {
        !           425:                iput(dir);
        !           426:                return -EPERM;
        !           427:        }
        !           428:        bh = find_entry(&dir,basename,namelen,&de);
        !           429:        if (bh) {
        !           430:                brelse(bh);
        !           431:                iput(dir);
        !           432:                return -EEXIST;
        !           433:        }
        !           434:        inode = new_inode(dir->i_dev);
        !           435:        if (!inode) {
        !           436:                iput(dir);
        !           437:                return -ENOSPC;
        !           438:        }
        !           439:        inode->i_mode = mode;
        !           440:        if (S_ISBLK(mode) || S_ISCHR(mode))
        !           441:                inode->i_zone[0] = dev;
        !           442:        inode->i_mtime = inode->i_atime = CURRENT_TIME;
        !           443:        inode->i_dirt = 1;
        !           444:        bh = add_entry(dir,basename,namelen,&de);
        !           445:        if (!bh) {
        !           446:                iput(dir);
        !           447:                inode->i_nlinks=0;
        !           448:                iput(inode);
        !           449:                return -ENOSPC;
        !           450:        }
        !           451:        de->inode = inode->i_num;
        !           452:        bh->b_dirt = 1;
        !           453:        iput(dir);
        !           454:        iput(inode);
        !           455:        brelse(bh);
        !           456:        return 0;
        !           457: }
        !           458: 
1.1       root      459: int sys_mkdir(const char * pathname, int mode)
                    460: {
                    461:        const char * basename;
                    462:        int namelen;
                    463:        struct m_inode * dir, * inode;
                    464:        struct buffer_head * bh, *dir_block;
                    465:        struct dir_entry * de;
                    466: 
1.1.1.2 ! root      467:        if (!suser())
1.1       root      468:                return -EPERM;
                    469:        if (!(dir = dir_namei(pathname,&namelen,&basename)))
                    470:                return -ENOENT;
                    471:        if (!namelen) {
                    472:                iput(dir);
                    473:                return -ENOENT;
                    474:        }
                    475:        if (!permission(dir,MAY_WRITE)) {
                    476:                iput(dir);
                    477:                return -EPERM;
                    478:        }
1.1.1.2 ! root      479:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      480:        if (bh) {
                    481:                brelse(bh);
                    482:                iput(dir);
                    483:                return -EEXIST;
                    484:        }
                    485:        inode = new_inode(dir->i_dev);
                    486:        if (!inode) {
                    487:                iput(dir);
                    488:                return -ENOSPC;
                    489:        }
                    490:        inode->i_size = 32;
                    491:        inode->i_dirt = 1;
                    492:        inode->i_mtime = inode->i_atime = CURRENT_TIME;
                    493:        if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
                    494:                iput(dir);
                    495:                inode->i_nlinks--;
                    496:                iput(inode);
                    497:                return -ENOSPC;
                    498:        }
                    499:        inode->i_dirt = 1;
                    500:        if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
                    501:                iput(dir);
                    502:                free_block(inode->i_dev,inode->i_zone[0]);
                    503:                inode->i_nlinks--;
                    504:                iput(inode);
                    505:                return -ERROR;
                    506:        }
                    507:        de = (struct dir_entry *) dir_block->b_data;
                    508:        de->inode=inode->i_num;
                    509:        strcpy(de->name,".");
                    510:        de++;
                    511:        de->inode = dir->i_num;
                    512:        strcpy(de->name,"..");
                    513:        inode->i_nlinks = 2;
                    514:        dir_block->b_dirt = 1;
                    515:        brelse(dir_block);
                    516:        inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
                    517:        inode->i_dirt = 1;
                    518:        bh = add_entry(dir,basename,namelen,&de);
                    519:        if (!bh) {
                    520:                iput(dir);
                    521:                free_block(inode->i_dev,inode->i_zone[0]);
                    522:                inode->i_nlinks=0;
                    523:                iput(inode);
                    524:                return -ENOSPC;
                    525:        }
                    526:        de->inode = inode->i_num;
                    527:        bh->b_dirt = 1;
                    528:        dir->i_nlinks++;
                    529:        dir->i_dirt = 1;
                    530:        iput(dir);
                    531:        iput(inode);
                    532:        brelse(bh);
                    533:        return 0;
                    534: }
                    535: 
                    536: /*
                    537:  * routine to check that the specified directory is empty (for rmdir)
                    538:  */
                    539: static int empty_dir(struct m_inode * inode)
                    540: {
                    541:        int nr,block;
                    542:        int len;
                    543:        struct buffer_head * bh;
                    544:        struct dir_entry * de;
                    545: 
                    546:        len = inode->i_size / sizeof (struct dir_entry);
                    547:        if (len<2 || !inode->i_zone[0] ||
                    548:            !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
                    549:                printk("warning - bad directory on dev %04x\n",inode->i_dev);
                    550:                return 0;
                    551:        }
                    552:        de = (struct dir_entry *) bh->b_data;
                    553:        if (de[0].inode != inode->i_num || !de[1].inode || 
                    554:            strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
                    555:                printk("warning - bad directory on dev %04x\n",inode->i_dev);
                    556:                return 0;
                    557:        }
                    558:        nr = 2;
                    559:        de += 2;
                    560:        while (nr<len) {
                    561:                if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
                    562:                        brelse(bh);
                    563:                        block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
                    564:                        if (!block) {
                    565:                                nr += DIR_ENTRIES_PER_BLOCK;
                    566:                                continue;
                    567:                        }
                    568:                        if (!(bh=bread(inode->i_dev,block)))
                    569:                                return 0;
                    570:                        de = (struct dir_entry *) bh->b_data;
                    571:                }
                    572:                if (de->inode) {
                    573:                        brelse(bh);
                    574:                        return 0;
                    575:                }
                    576:                de++;
                    577:                nr++;
                    578:        }
                    579:        brelse(bh);
                    580:        return 1;
                    581: }
                    582: 
                    583: int sys_rmdir(const char * name)
                    584: {
                    585:        const char * basename;
                    586:        int namelen;
                    587:        struct m_inode * dir, * inode;
                    588:        struct buffer_head * bh;
                    589:        struct dir_entry * de;
                    590: 
1.1.1.2 ! root      591:        if (!suser())
1.1       root      592:                return -EPERM;
                    593:        if (!(dir = dir_namei(name,&namelen,&basename)))
                    594:                return -ENOENT;
                    595:        if (!namelen) {
                    596:                iput(dir);
                    597:                return -ENOENT;
                    598:        }
1.1.1.2 ! root      599:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      600:        if (!bh) {
                    601:                iput(dir);
                    602:                return -ENOENT;
                    603:        }
                    604:        if (!permission(dir,MAY_WRITE)) {
                    605:                iput(dir);
                    606:                brelse(bh);
                    607:                return -EPERM;
                    608:        }
                    609:        if (!(inode = iget(dir->i_dev, de->inode))) {
                    610:                iput(dir);
                    611:                brelse(bh);
                    612:                return -EPERM;
                    613:        }
                    614:        if (inode == dir) {     /* we may not delete ".", but "../dir" is ok */
                    615:                iput(inode);
                    616:                iput(dir);
                    617:                brelse(bh);
                    618:                return -EPERM;
                    619:        }
                    620:        if (!S_ISDIR(inode->i_mode)) {
                    621:                iput(inode);
                    622:                iput(dir);
                    623:                brelse(bh);
                    624:                return -ENOTDIR;
                    625:        }
                    626:        if (!empty_dir(inode)) {
                    627:                iput(inode);
                    628:                iput(dir);
                    629:                brelse(bh);
                    630:                return -ENOTEMPTY;
                    631:        }
                    632:        if (inode->i_nlinks != 2)
                    633:                printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
                    634:        de->inode = 0;
                    635:        bh->b_dirt = 1;
                    636:        brelse(bh);
                    637:        inode->i_nlinks=0;
                    638:        inode->i_dirt=1;
                    639:        dir->i_nlinks--;
                    640:        dir->i_ctime = dir->i_mtime = CURRENT_TIME;
                    641:        dir->i_dirt=1;
                    642:        iput(dir);
                    643:        iput(inode);
                    644:        return 0;
                    645: }
                    646: 
                    647: int sys_unlink(const char * name)
                    648: {
                    649:        const char * basename;
                    650:        int namelen;
                    651:        struct m_inode * dir, * inode;
                    652:        struct buffer_head * bh;
                    653:        struct dir_entry * de;
                    654: 
                    655:        if (!(dir = dir_namei(name,&namelen,&basename)))
                    656:                return -ENOENT;
                    657:        if (!namelen) {
                    658:                iput(dir);
                    659:                return -ENOENT;
                    660:        }
                    661:        if (!permission(dir,MAY_WRITE)) {
                    662:                iput(dir);
                    663:                return -EPERM;
                    664:        }
1.1.1.2 ! root      665:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      666:        if (!bh) {
                    667:                iput(dir);
                    668:                return -ENOENT;
                    669:        }
                    670:        inode = iget(dir->i_dev, de->inode);
                    671:        if (!inode) {
                    672:                printk("iget failed in delete (%04x:%d)",dir->i_dev,de->inode);
                    673:                iput(dir);
                    674:                brelse(bh);
                    675:                return -ENOENT;
                    676:        }
1.1.1.2 ! root      677:        if (S_ISDIR(inode->i_mode)) {
1.1       root      678:                iput(inode);
                    679:                iput(dir);
                    680:                brelse(bh);
                    681:                return -EPERM;
                    682:        }
1.1.1.2 ! root      683:        /*
        !           684:         * If the directory has the sticky bit, the user must either
        !           685:         * own the file or own the directory or be the superuser to 
        !           686:         * delete a file in that directory.  This is typically used 
        !           687:         * for /tmp and /usr/tmp.
        !           688:         */
        !           689:        if ((dir->i_mode & S_ISVTX) && (current->euid != inode->i_uid) &&
        !           690:            (current->euid != dir->i_uid) && !suser()) {
        !           691:                iput(inode);
        !           692:                iput(dir);
        !           693:                brelse(bh);
        !           694:                return -EPERM;
        !           695:        }               
1.1       root      696:        if (!inode->i_nlinks) {
                    697:                printk("Deleting nonexistent file (%04x:%d), %d\n",
                    698:                        inode->i_dev,inode->i_num,inode->i_nlinks);
                    699:                inode->i_nlinks=1;
                    700:        }
                    701:        de->inode = 0;
                    702:        bh->b_dirt = 1;
                    703:        brelse(bh);
                    704:        inode->i_nlinks--;
                    705:        inode->i_dirt = 1;
                    706:        inode->i_ctime = CURRENT_TIME;
                    707:        iput(inode);
                    708:        iput(dir);
                    709:        return 0;
                    710: }
                    711: 
                    712: int sys_link(const char * oldname, const char * newname)
                    713: {
                    714:        struct dir_entry * de;
                    715:        struct m_inode * oldinode, * dir;
                    716:        struct buffer_head * bh;
                    717:        const char * basename;
                    718:        int namelen;
                    719: 
                    720:        oldinode=namei(oldname);
                    721:        if (!oldinode)
                    722:                return -ENOENT;
1.1.1.2 ! root      723:        if (S_ISDIR(oldinode->i_mode)) {
1.1       root      724:                iput(oldinode);
                    725:                return -EPERM;
                    726:        }
                    727:        dir = dir_namei(newname,&namelen,&basename);
                    728:        if (!dir) {
                    729:                iput(oldinode);
                    730:                return -EACCES;
                    731:        }
                    732:        if (!namelen) {
                    733:                iput(oldinode);
                    734:                iput(dir);
                    735:                return -EPERM;
                    736:        }
                    737:        if (dir->i_dev != oldinode->i_dev) {
                    738:                iput(dir);
                    739:                iput(oldinode);
                    740:                return -EXDEV;
                    741:        }
                    742:        if (!permission(dir,MAY_WRITE)) {
                    743:                iput(dir);
                    744:                iput(oldinode);
                    745:                return -EACCES;
                    746:        }
1.1.1.2 ! root      747:        bh = find_entry(&dir,basename,namelen,&de);
1.1       root      748:        if (bh) {
                    749:                brelse(bh);
                    750:                iput(dir);
                    751:                iput(oldinode);
                    752:                return -EEXIST;
                    753:        }
                    754:        bh = add_entry(dir,basename,namelen,&de);
                    755:        if (!bh) {
                    756:                iput(dir);
                    757:                iput(oldinode);
                    758:                return -ENOSPC;
                    759:        }
                    760:        de->inode = oldinode->i_num;
                    761:        bh->b_dirt = 1;
                    762:        brelse(bh);
                    763:        iput(dir);
                    764:        oldinode->i_nlinks++;
                    765:        oldinode->i_ctime = CURRENT_TIME;
                    766:        oldinode->i_dirt = 1;
                    767:        iput(oldinode);
                    768:        return 0;
                    769: }

unix.superglobalmegacorp.com

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