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

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

unix.superglobalmegacorp.com

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