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

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

unix.superglobalmegacorp.com

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