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

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

unix.superglobalmegacorp.com

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