Annotation of linux/fs/open.c, revision 1.1.1.10

1.1.1.2   root        1: /*
                      2:  *  linux/fs/open.c
                      3:  *
1.1.1.9   root        4:  *  Copyright (C) 1991, 1992  Linus Torvalds
1.1.1.2   root        5:  */
                      6: 
1.1.1.9   root        7: #include <linux/vfs.h>
                      8: #include <linux/types.h>
                      9: #include <linux/utime.h>
                     10: #include <linux/errno.h>
1.1.1.8   root       11: #include <linux/fcntl.h>
1.1.1.7   root       12: #include <linux/stat.h>
1.1.1.6   root       13: #include <linux/string.h>
1.1       root       14: #include <linux/sched.h>
                     15: #include <linux/kernel.h>
1.1.1.9   root       16: #include <linux/signal.h>
1.1.1.10! root       17: #include <linux/tty.h>
1.1       root       18: #include <asm/segment.h>
                     19: 
1.1.1.10! root       20: extern void fcntl_remove_locks(struct task_struct *, struct file *);
        !            21: 
1.1.1.6   root       22: struct file_operations * chrdev_fops[MAX_CHRDEV] = {
                     23:        NULL,
                     24: };
                     25: 
                     26: struct file_operations * blkdev_fops[MAX_BLKDEV] = {
                     27:        NULL,
                     28: };
                     29: 
1.1.1.2   root       30: int sys_ustat(int dev, struct ustat * ubuf)
                     31: {
                     32:        return -ENOSYS;
                     33: }
                     34: 
1.1.1.6   root       35: int sys_statfs(const char * path, struct statfs * buf)
                     36: {
1.1.1.7   root       37:        struct inode * inode;
1.1.1.10! root       38:        int error;
1.1.1.7   root       39: 
                     40:        verify_area(buf, sizeof(struct statfs));
1.1.1.10! root       41:        error = namei(path,&inode);
        !            42:        if (error)
        !            43:                return error;
1.1.1.7   root       44:        if (!inode->i_sb->s_op->statfs) {
                     45:                iput(inode);
                     46:                return -ENOSYS;
                     47:        }
                     48:        inode->i_sb->s_op->statfs(inode->i_sb, buf);
                     49:        iput(inode);
                     50:        return 0;
1.1.1.6   root       51: }
                     52: 
                     53: int sys_fstatfs(unsigned int fd, struct statfs * buf)
                     54: {
1.1.1.7   root       55:        struct inode * inode;
                     56:        struct file * file;
                     57: 
                     58:        verify_area(buf, sizeof(struct statfs));
                     59:        if (fd >= NR_OPEN || !(file = current->filp[fd]))
                     60:                return -EBADF;
                     61:        if (!(inode = file->f_inode))
                     62:                return -ENOENT;
                     63:        if (!inode->i_sb->s_op->statfs)
                     64:                return -ENOSYS;
                     65:        inode->i_sb->s_op->statfs(inode->i_sb, buf);
                     66:        return 0;
1.1.1.6   root       67: }
                     68: 
                     69: int sys_truncate(const char * path, unsigned int length)
                     70: {
                     71:        struct inode * inode;
1.1.1.10! root       72:        int error;
1.1.1.6   root       73: 
1.1.1.10! root       74:        error = namei(path,&inode);
        !            75:        if (error)
        !            76:                return error;
1.1.1.6   root       77:        if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
                     78:                iput(inode);
                     79:                return -EACCES;
                     80:        }
1.1.1.9   root       81:        if (IS_RDONLY(inode)) {
                     82:                iput(inode);
                     83:                return -EROFS;
                     84:        }
1.1.1.6   root       85:        inode->i_size = length;
                     86:        if (inode->i_op && inode->i_op->truncate)
                     87:                inode->i_op->truncate(inode);
                     88:        inode->i_atime = inode->i_mtime = CURRENT_TIME;
                     89:        inode->i_dirt = 1;
                     90:        iput(inode);
                     91:        return 0;
                     92: }
                     93: 
                     94: int sys_ftruncate(unsigned int fd, unsigned int length)
                     95: {
                     96:        struct inode * inode;
                     97:        struct file * file;
                     98: 
                     99:        if (fd >= NR_OPEN || !(file = current->filp[fd]))
                    100:                return -EBADF;
                    101:        if (!(inode = file->f_inode))
                    102:                return -ENOENT;
1.1.1.9   root      103:        if (S_ISDIR(inode->i_mode) || !(file->f_mode & 2))
1.1.1.6   root      104:                return -EACCES;
                    105:        inode->i_size = length;
                    106:        if (inode->i_op && inode->i_op->truncate)
                    107:                inode->i_op->truncate(inode);
                    108:        inode->i_atime = inode->i_mtime = CURRENT_TIME;
                    109:        inode->i_dirt = 1;
                    110:        return 0;
                    111: }
                    112: 
1.1.1.8   root      113: /* If times==NULL, set access and modification to current time,
                    114:  * must be owner or have write permission.
                    115:  * Else, update from *times, must be owner or super user.
                    116:  */
1.1       root      117: int sys_utime(char * filename, struct utimbuf * times)
                    118: {
1.1.1.4   root      119:        struct inode * inode;
1.1       root      120:        long actime,modtime;
1.1.1.10! root      121:        int error;
1.1       root      122: 
1.1.1.10! root      123:        error = namei(filename,&inode);
        !           124:        if (error)
        !           125:                return error;
1.1.1.9   root      126:        if (IS_RDONLY(inode)) {
                    127:                iput(inode);
                    128:                return -EROFS;
                    129:        }
1.1       root      130:        if (times) {
1.1.1.8   root      131:                if ((current->euid != inode->i_uid) && !suser()) {
1.1.1.5   root      132:                        iput(inode);
1.1.1.8   root      133:                        return -EPERM;
1.1.1.5   root      134:                }
1.1       root      135:                actime = get_fs_long((unsigned long *) &times->actime);
                    136:                modtime = get_fs_long((unsigned long *) &times->modtime);
1.1.1.8   root      137:        } else {
                    138:                if ((current->euid != inode->i_uid) &&
                    139:                    !permission(inode,MAY_WRITE)) {
                    140:                        iput(inode);
                    141:                        return -EACCES;
                    142:                }
1.1       root      143:                actime = modtime = CURRENT_TIME;
1.1.1.8   root      144:        }
1.1       root      145:        inode->i_atime = actime;
                    146:        inode->i_mtime = modtime;
                    147:        inode->i_dirt = 1;
                    148:        iput(inode);
                    149:        return 0;
                    150: }
                    151: 
1.1.1.2   root      152: /*
                    153:  * XXX should we use the real or effective uid?  BSD uses the real uid,
                    154:  * so as to make this call useful to setuid programs.
                    155:  */
1.1       root      156: int sys_access(const char * filename,int mode)
                    157: {
1.1.1.4   root      158:        struct inode * inode;
1.1.1.2   root      159:        int res, i_mode;
1.1       root      160: 
                    161:        mode &= 0007;
1.1.1.10! root      162:        res = namei(filename,&inode);
        !           163:        if (res)
        !           164:                return res;
1.1.1.2   root      165:        i_mode = res = inode->i_mode & 0777;
1.1       root      166:        iput(inode);
1.1.1.2   root      167:        if (current->uid == inode->i_uid)
1.1       root      168:                res >>= 6;
1.1.1.7   root      169:        else if (in_group_p(inode->i_gid))
                    170:                res >>= 3;
1.1       root      171:        if ((res & 0007 & mode) == mode)
                    172:                return 0;
1.1.1.2   root      173:        /*
                    174:         * XXX we are doing this test last because we really should be
                    175:         * swapping the effective with the real user id (temporarily),
                    176:         * and then calling suser() routine.  If we do call the
                    177:         * suser() routine, it needs to be called last. 
                    178:         */
                    179:        if ((!current->uid) &&
                    180:            (!(mode & 1) || (i_mode & 0111)))
                    181:                return 0;
1.1       root      182:        return -EACCES;
                    183: }
                    184: 
                    185: int sys_chdir(const char * filename)
                    186: {
1.1.1.4   root      187:        struct inode * inode;
1.1.1.10! root      188:        int error;
1.1       root      189: 
1.1.1.10! root      190:        error = namei(filename,&inode);
        !           191:        if (error)
        !           192:                return error;
1.1       root      193:        if (!S_ISDIR(inode->i_mode)) {
                    194:                iput(inode);
                    195:                return -ENOTDIR;
                    196:        }
1.1.1.6   root      197:        if (!permission(inode,MAY_EXEC)) {
                    198:                iput(inode);
                    199:                return -EACCES;
                    200:        }
1.1       root      201:        iput(current->pwd);
                    202:        current->pwd = inode;
                    203:        return (0);
                    204: }
                    205: 
                    206: int sys_chroot(const char * filename)
                    207: {
1.1.1.4   root      208:        struct inode * inode;
1.1.1.10! root      209:        int error;
1.1       root      210: 
1.1.1.10! root      211:        error = namei(filename,&inode);
        !           212:        if (error)
        !           213:                return error;
1.1       root      214:        if (!S_ISDIR(inode->i_mode)) {
                    215:                iput(inode);
                    216:                return -ENOTDIR;
                    217:        }
1.1.1.6   root      218:        if (!suser()) {
                    219:                iput(inode);
                    220:                return -EPERM;
                    221:        }
1.1       root      222:        iput(current->root);
                    223:        current->root = inode;
                    224:        return (0);
                    225: }
                    226: 
1.1.1.6   root      227: int sys_fchmod(unsigned int fd, mode_t mode)
1.1       root      228: {
1.1.1.4   root      229:        struct inode * inode;
1.1.1.6   root      230:        struct file * file;
1.1       root      231: 
1.1.1.6   root      232:        if (fd >= NR_OPEN || !(file = current->filp[fd]))
                    233:                return -EBADF;
                    234:        if (!(inode = file->f_inode))
                    235:                return -ENOENT;
                    236:        if ((current->euid != inode->i_uid) && !suser())
                    237:                return -EPERM;
1.1.1.9   root      238:        if (IS_RDONLY(inode))
                    239:                return -EROFS;
1.1.1.6   root      240:        inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
                    241:        inode->i_dirt = 1;
                    242:        return 0;
                    243: }
                    244: 
                    245: int sys_chmod(const char * filename, mode_t mode)
                    246: {
                    247:        struct inode * inode;
1.1.1.10! root      248:        int error;
1.1.1.6   root      249: 
1.1.1.10! root      250:        error = namei(filename,&inode);
        !           251:        if (error)
        !           252:                return error;
1.1.1.2   root      253:        if ((current->euid != inode->i_uid) && !suser()) {
                    254:                iput(inode);
1.1.1.6   root      255:                return -EPERM;
1.1.1.2   root      256:        }
1.1.1.9   root      257:        if (IS_RDONLY(inode)) {
                    258:                iput(inode);
                    259:                return -EROFS;
                    260:        }
1.1       root      261:        inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
                    262:        inode->i_dirt = 1;
                    263:        iput(inode);
                    264:        return 0;
                    265: }
                    266: 
1.1.1.6   root      267: int sys_fchown(unsigned int fd, uid_t user, gid_t group)
1.1       root      268: {
1.1.1.4   root      269:        struct inode * inode;
1.1.1.6   root      270:        struct file * file;
1.1       root      271: 
1.1.1.6   root      272:        if (fd >= NR_OPEN || !(file = current->filp[fd]))
                    273:                return -EBADF;
                    274:        if (!(inode = file->f_inode))
1.1       root      275:                return -ENOENT;
1.1.1.9   root      276:        if (IS_RDONLY(inode))
                    277:                return -EROFS;
1.1.1.6   root      278:        if ((current->euid == inode->i_uid && user == inode->i_uid &&
                    279:             (in_group_p(group) || group == inode->i_gid)) ||
                    280:            suser()) {
                    281:                inode->i_uid = user;
                    282:                inode->i_gid = group;
                    283:                inode->i_dirt=1;
                    284:                return 0;
                    285:        }
                    286:        return -EPERM;
                    287: }
                    288: 
                    289: int sys_chown(const char * filename, uid_t user, gid_t group)
                    290: {
                    291:        struct inode * inode;
1.1.1.10! root      292:        int error;
1.1.1.6   root      293: 
1.1.1.10! root      294:        error = lnamei(filename,&inode);
        !           295:        if (error)
        !           296:                return error;
1.1.1.9   root      297:        if (IS_RDONLY(inode)) {
                    298:                iput(inode);
                    299:                return -EROFS;
                    300:        }
1.1.1.6   root      301:        if ((current->euid == inode->i_uid && user == inode->i_uid &&
                    302:             (in_group_p(group) || group == inode->i_gid)) ||
                    303:            suser()) {
                    304:                inode->i_uid = user;
                    305:                inode->i_gid = group;
                    306:                inode->i_dirt=1;
1.1       root      307:                iput(inode);
1.1.1.6   root      308:                return 0;
1.1       root      309:        }
                    310:        iput(inode);
1.1.1.6   root      311:        return -EPERM;
1.1       root      312: }
                    313: 
1.1.1.10! root      314: /*
        !           315:  * Note that while the flag value (low two bits) for sys_open means:
        !           316:  *     00 - read-only
        !           317:  *     01 - write-only
        !           318:  *     10 - read-write
        !           319:  *     11 - special
        !           320:  * it is changed into
        !           321:  *     00 - no permissions needed
        !           322:  *     01 - read-permission
        !           323:  *     10 - write-permission
        !           324:  *     11 - read-write
        !           325:  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
        !           326:  * used by symlinks.
        !           327:  */
1.1       root      328: int sys_open(const char * filename,int flag,int mode)
                    329: {
1.1.1.4   root      330:        struct inode * inode;
1.1       root      331:        struct file * f;
                    332:        int i,fd;
                    333: 
                    334:        for(fd=0 ; fd<NR_OPEN ; fd++)
                    335:                if (!current->filp[fd])
                    336:                        break;
                    337:        if (fd>=NR_OPEN)
1.1.1.7   root      338:                return -EMFILE;
1.1       root      339:        current->close_on_exec &= ~(1<<fd);
1.1.1.9   root      340:        f = get_empty_filp();
                    341:        if (!f)
1.1.1.7   root      342:                return -ENFILE;
1.1.1.9   root      343:        current->filp[fd] = f;
1.1.1.10! root      344:        f->f_flags = flag;
        !           345:        if (f->f_mode = (flag+1) & O_ACCMODE)
        !           346:                flag++;
        !           347:        if (flag & (O_TRUNC | O_CREAT))
        !           348:                flag |= 2;
        !           349:        i = open_namei(filename,flag,mode,&inode,NULL);
        !           350:        if (i) {
1.1       root      351:                current->filp[fd]=NULL;
1.1.1.9   root      352:                f->f_count--;
1.1       root      353:                return i;
                    354:        }
1.1.1.10! root      355:        if (flag & O_TRUNC)
        !           356:                if (inode->i_op && inode->i_op->truncate) {
        !           357:                        inode->i_size = 0;
        !           358:                        inode->i_op->truncate(inode);
        !           359:                }
        !           360:        if (!IS_RDONLY(inode)) {
        !           361:                inode->i_atime = CURRENT_TIME;
        !           362:                inode->i_dirt = 1;
        !           363:        }
1.1       root      364:        f->f_inode = inode;
                    365:        f->f_pos = 0;
1.1.1.6   root      366:        f->f_reada = 0;
                    367:        f->f_op = NULL;
                    368:        if (inode->i_op)
                    369:                f->f_op = inode->i_op->default_file_ops;
                    370:        if (f->f_op && f->f_op->open)
                    371:                if (i = f->f_op->open(inode,f)) {
1.1.1.4   root      372:                        iput(inode);
1.1.1.9   root      373:                        f->f_count--;
1.1.1.4   root      374:                        current->filp[fd]=NULL;
                    375:                        return i;
                    376:                }
1.1       root      377:        return (fd);
                    378: }
                    379: 
                    380: int sys_creat(const char * pathname, int mode)
                    381: {
1.1.1.4   root      382:        return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
1.1       root      383: }
                    384: 
1.1.1.10! root      385: static int close_fp(struct file *filp)
        !           386: {
        !           387:        struct inode *inode;
1.1       root      388: 
1.1.1.6   root      389:        if (filp->f_count == 0) {
                    390:                printk("Close: file count is 0\n");
                    391:                return 0;
                    392:        }
1.1.1.10! root      393:        inode = filp->f_inode;
        !           394:        if (S_ISREG(inode->i_mode))
        !           395:                fcntl_remove_locks(current, filp);
1.1.1.6   root      396:        if (filp->f_count > 1) {
                    397:                filp->f_count--;
                    398:                return 0;
                    399:        }
                    400:        if (filp->f_op && filp->f_op->release)
1.1.1.9   root      401:                filp->f_op->release(inode,filp);
1.1.1.6   root      402:        filp->f_count--;
1.1.1.9   root      403:        filp->f_inode = NULL;
                    404:        iput(inode);
1.1.1.6   root      405:        return 0;
1.1       root      406: }
1.1.1.9   root      407: 
1.1.1.10! root      408: int sys_close(unsigned int fd)
        !           409: {      
        !           410:        struct file * filp;
        !           411: 
        !           412:        if (fd >= NR_OPEN)
        !           413:                return -EINVAL;
        !           414:        current->close_on_exec &= ~(1<<fd);
        !           415:        if (!(filp = current->filp[fd]))
        !           416:                return -EINVAL;
        !           417:        current->filp[fd] = NULL;
        !           418:        return (close_fp (filp));
        !           419: }
        !           420: 
        !           421: /*
        !           422:  * This routine looks through all the process's and closes any
        !           423:  * references to the current processes tty.  To avoid problems with
        !           424:  * process sleeping on an inode which has already been iput, anyprocess
        !           425:  * which is sleeping on the tty is sent a sigkill (It's probably a rogue
        !           426:  * process.)  Also no process should ever have /dev/console as it's
        !           427:  * controlling tty, or have it open for reading.  So we don't have to
        !           428:  * worry about messing with all the daemons abilities to write messages
        !           429:  * to the console.  (Besides they should be using syslog.)
        !           430:  */
1.1.1.9   root      431: int sys_vhangup(void)
                    432: {
1.1.1.10! root      433:        int i,j;
        !           434:        struct file *filep;
        !           435:        struct tty_struct *tty;
        !           436:        extern void kill_wait (struct wait_queue **q, int signal);
        !           437:        extern int kill_pg (int pgrp, int sig, int priv);
        !           438: 
        !           439:        if (!suser())
        !           440:                return -EPERM;
        !           441:        /* send the SIGHUP signal. */
        !           442:        kill_pg(current->pgrp, SIGHUP, 0);
        !           443:        /* See if there is a controlling tty. */
        !           444:        if (current->tty < 0)
        !           445:                return 0;
        !           446: 
        !           447:        for (i = 0; i < NR_TASKS; i++) {
        !           448:                if (task[i] == NULL)
        !           449:                        continue;
        !           450:                for (j = 0; j < NR_OPEN; j++) {
        !           451:                        filep = task[i]->filp[j];
        !           452:                        if (!filep)
        !           453:                                continue;
        !           454:                        if (!S_ISCHR(filep->f_inode->i_mode))
        !           455:                                continue;
        !           456:                        if ((MAJOR(filep->f_inode->i_rdev) == 5 ||
        !           457:                             MAJOR(filep->f_inode->i_rdev) == 4 ) &&
        !           458:                            (MAJOR(filep->f_rdev) == 4 &&
        !           459:                             MINOR(filep->f_rdev) == MINOR (current->tty))) {
        !           460:                  /* so now we have found something to close.  We
        !           461:                     need to kill every process waiting on the
        !           462:                     inode. */
        !           463:                                task[i]->filp[j] = NULL;
        !           464:                                kill_wait (&filep->f_inode->i_wait, SIGKILL);
        !           465: 
        !           466:                  /* now make sure they are awake before we close the
        !           467:                     file. */
        !           468: 
        !           469:                                wake_up (&filep->f_inode->i_wait);
        !           470: 
        !           471:                  /* finally close the file. */
        !           472: 
        !           473:                                current->close_on_exec &= ~(1<<j);
        !           474:                                close_fp (filep);
        !           475:                        }
        !           476:                }
        !           477:        /* can't let them keep a reference to it around.
        !           478:           But we can't touch current->tty until after the
        !           479:           loop is complete. */
        !           480: 
        !           481:                if (task[i]->tty == current->tty && task[i] != current) {
        !           482:                        task[i]->tty = -1;
        !           483:                }
        !           484:        }
        !           485:    /* need to do tty->session = 0 */
        !           486:        tty = TTY_TABLE(MINOR(current->tty));
        !           487:        tty->session = 0;
        !           488:        tty->pgrp = -1;
        !           489:        current->tty = -1;
        !           490:        return 0;
1.1.1.9   root      491: }
1.1.1.10! root      492: 

unix.superglobalmegacorp.com

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