The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/fs/open.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  *  linux/fs/open.c
    3  *
    4  *  Copyright (C) 1991, 1992  Linus Torvalds
    5  */
    6 
    7 #include <linux/string.h>
    8 #include <linux/mm.h>
    9 #include <linux/utime.h>
   10 #include <linux/file.h>
   11 #include <linux/smp_lock.h>
   12 #include <linux/quotaops.h>
   13 #include <linux/dnotify.h>
   14 #include <linux/module.h>
   15 #include <linux/slab.h>
   16 #include <linux/tty.h>
   17 #include <linux/iobuf.h>
   18 
   19 #include <asm/uaccess.h>
   20 
   21 #define special_file(m) (S_ISCHR(m)||S_ISBLK(m)||S_ISFIFO(m)||S_ISSOCK(m))
   22 
   23 int vfs_statfs(struct super_block *sb, struct statfs *buf)
   24 {
   25         int retval = -ENODEV;
   26 
   27         if (sb) {
   28                 retval = -ENOSYS;
   29                 if (sb->s_op && sb->s_op->statfs) {
   30                         memset(buf, 0, sizeof(struct statfs));
   31                         lock_kernel();
   32                         retval = sb->s_op->statfs(sb, buf);
   33                         unlock_kernel();
   34                 }
   35         }
   36         return retval;
   37 }
   38 
   39 
   40 asmlinkage long sys_statfs(const char * path, struct statfs * buf)
   41 {
   42         struct nameidata nd;
   43         int error;
   44 
   45         error = user_path_walk(path, &nd);
   46         if (!error) {
   47                 struct statfs tmp;
   48                 error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp);
   49                 if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
   50                         error = -EFAULT;
   51                 path_release(&nd);
   52         }
   53         return error;
   54 }
   55 
   56 asmlinkage long sys_fstatfs(unsigned int fd, struct statfs * buf)
   57 {
   58         struct file * file;
   59         struct statfs tmp;
   60         int error;
   61 
   62         error = -EBADF;
   63         file = fget(fd);
   64         if (!file)
   65                 goto out;
   66         error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp);
   67         if (!error && copy_to_user(buf, &tmp, sizeof(struct statfs)))
   68                 error = -EFAULT;
   69         fput(file);
   70 out:
   71         return error;
   72 }
   73 
   74 /*
   75  * Install a file pointer in the fd array.  
   76  *
   77  * The VFS is full of places where we drop the files lock between
   78  * setting the open_fds bitmap and installing the file in the file
   79  * array.  At any such point, we are vulnerable to a dup2() race
   80  * installing a file in the array before us.  We need to detect this and
   81  * fput() the struct file we are about to overwrite in this case.
   82  *
   83  * It should never happen - if we allow dup2() do it, _really_ bad things
   84  * will follow.
   85  */
   86 
   87 void fd_install(unsigned int fd, struct file * file)
   88 {
   89         struct files_struct *files = current->files;
   90         
   91         write_lock(&files->file_lock);
   92         if (files->fd[fd])
   93                 BUG();
   94         files->fd[fd] = file;
   95         write_unlock(&files->file_lock);
   96 }
   97 
   98 int do_truncate(struct dentry *dentry, loff_t length)
   99 {
  100         struct inode *inode = dentry->d_inode;
  101         int error;
  102         struct iattr newattrs;
  103 
  104         /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
  105         if (length < 0)
  106                 return -EINVAL;
  107 
  108         down_write(&inode->i_alloc_sem);
  109         down(&inode->i_sem);
  110         newattrs.ia_size = length;
  111         newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  112         error = notify_change(dentry, &newattrs);
  113         up(&inode->i_sem);
  114         up_write(&inode->i_alloc_sem);
  115         return error;
  116 }
  117 
  118 static inline long do_sys_truncate(const char * path, loff_t length)
  119 {
  120         struct nameidata nd;
  121         struct inode * inode;
  122         int error;
  123 
  124         error = -EINVAL;
  125         if (length < 0) /* sorry, but loff_t says... */
  126                 goto out;
  127 
  128         error = user_path_walk(path, &nd);
  129         if (error)
  130                 goto out;
  131         inode = nd.dentry->d_inode;
  132 
  133         /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
  134         error = -EISDIR;
  135         if (S_ISDIR(inode->i_mode))
  136                 goto dput_and_out;
  137 
  138         error = -EINVAL;
  139         if (!S_ISREG(inode->i_mode))
  140                 goto dput_and_out;
  141 
  142         error = permission(inode,MAY_WRITE);
  143         if (error)
  144                 goto dput_and_out;
  145 
  146         error = -EROFS;
  147         if (IS_RDONLY(inode))
  148                 goto dput_and_out;
  149 
  150         error = -EPERM;
  151         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  152                 goto dput_and_out;
  153 
  154         /*
  155          * Make sure that there are no leases.
  156          */
  157         error = get_lease(inode, FMODE_WRITE);
  158         if (error)
  159                 goto dput_and_out;
  160 
  161         error = get_write_access(inode);
  162         if (error)
  163                 goto dput_and_out;
  164 
  165         error = locks_verify_truncate(inode, NULL, length);
  166         if (!error) {
  167                 DQUOT_INIT(inode);
  168                 error = do_truncate(nd.dentry, length);
  169         }
  170         put_write_access(inode);
  171 
  172 dput_and_out:
  173         path_release(&nd);
  174 out:
  175         return error;
  176 }
  177 
  178 asmlinkage long sys_truncate(const char * path, unsigned long length)
  179 {
  180         /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */
  181         return do_sys_truncate(path, (long)length);
  182 }
  183 
  184 static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
  185 {
  186         struct inode * inode;
  187         struct dentry *dentry;
  188         struct file * file;
  189         int error;
  190 
  191         error = -EINVAL;
  192         if (length < 0)
  193                 goto out;
  194         error = -EBADF;
  195         file = fget(fd);
  196         if (!file)
  197                 goto out;
  198 
  199         /* explicitly opened as large or we are on 64-bit box */
  200         if (file->f_flags & O_LARGEFILE)
  201                 small = 0;
  202 
  203         dentry = file->f_dentry;
  204         inode = dentry->d_inode;
  205         error = -EINVAL;
  206         if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
  207                 goto out_putf;
  208 
  209         error = -EINVAL;
  210         /* Cannot ftruncate over 2^31 bytes without large file support */
  211         if (small && length > MAX_NON_LFS)
  212                 goto out_putf;
  213 
  214         error = -EPERM;
  215         if (IS_APPEND(inode))
  216                 goto out_putf;
  217 
  218         error = locks_verify_truncate(inode, file, length);
  219         if (!error)
  220                 error = do_truncate(dentry, length);
  221 out_putf:
  222         fput(file);
  223 out:
  224         return error;
  225 }
  226 
  227 asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
  228 {
  229         return do_sys_ftruncate(fd, length, 1);
  230 }
  231 
  232 /* LFS versions of truncate are only needed on 32 bit machines */
  233 #if BITS_PER_LONG == 32
  234 asmlinkage long sys_truncate64(const char * path, loff_t length)
  235 {
  236         return do_sys_truncate(path, length);
  237 }
  238 
  239 asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
  240 {
  241         return do_sys_ftruncate(fd, length, 0);
  242 }
  243 #endif
  244 
  245 #if !(defined(__alpha__) || defined(__ia64__))
  246 
  247 /*
  248  * sys_utime() can be implemented in user-level using sys_utimes().
  249  * Is this for backwards compatibility?  If so, why not move it
  250  * into the appropriate arch directory (for those architectures that
  251  * need it).
  252  */
  253 
  254 /* If times==NULL, set access and modification to current time,
  255  * must be owner or have write permission.
  256  * Else, update from *times, must be owner or super user.
  257  */
  258 asmlinkage long sys_utime(char * filename, struct utimbuf * times)
  259 {
  260         int error;
  261         struct nameidata nd;
  262         struct inode * inode;
  263         struct iattr newattrs;
  264 
  265         error = user_path_walk(filename, &nd);
  266         if (error)
  267                 goto out;
  268         inode = nd.dentry->d_inode;
  269 
  270         error = -EROFS;
  271         if (IS_RDONLY(inode))
  272                 goto dput_and_out;
  273 
  274         /* Don't worry, the checks are done in inode_change_ok() */
  275         newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  276         if (times) {
  277                 error = get_user(newattrs.ia_atime, &times->actime);
  278                 if (!error) 
  279                         error = get_user(newattrs.ia_mtime, &times->modtime);
  280                 if (error)
  281                         goto dput_and_out;
  282 
  283                 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  284         } else {
  285                 if (current->fsuid != inode->i_uid &&
  286                     (error = permission(inode,MAY_WRITE)) != 0)
  287                         goto dput_and_out;
  288         }
  289         error = notify_change(nd.dentry, &newattrs);
  290 dput_and_out:
  291         path_release(&nd);
  292 out:
  293         return error;
  294 }
  295 
  296 #endif
  297 
  298 /* If times==NULL, set access and modification to current time,
  299  * must be owner or have write permission.
  300  * Else, update from *times, must be owner or super user.
  301  */
  302 asmlinkage long sys_utimes(char * filename, struct timeval * utimes)
  303 {
  304         int error;
  305         struct nameidata nd;
  306         struct inode * inode;
  307         struct iattr newattrs;
  308 
  309         error = user_path_walk(filename, &nd);
  310 
  311         if (error)
  312                 goto out;
  313         inode = nd.dentry->d_inode;
  314 
  315         error = -EROFS;
  316         if (IS_RDONLY(inode))
  317                 goto dput_and_out;
  318 
  319         /* Don't worry, the checks are done in inode_change_ok() */
  320         newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
  321         if (utimes) {
  322                 struct timeval times[2];
  323                 error = -EFAULT;
  324                 if (copy_from_user(&times, utimes, sizeof(times)))
  325                         goto dput_and_out;
  326                 newattrs.ia_atime = times[0].tv_sec;
  327                 newattrs.ia_mtime = times[1].tv_sec;
  328                 newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
  329         } else {
  330                 if (current->fsuid != inode->i_uid &&
  331                     (error = permission(inode,MAY_WRITE)) != 0)
  332                         goto dput_and_out;
  333         }
  334         error = notify_change(nd.dentry, &newattrs);
  335 dput_and_out:
  336         path_release(&nd);
  337 out:
  338         return error;
  339 }
  340 
  341 /*
  342  * access() needs to use the real uid/gid, not the effective uid/gid.
  343  * We do this by temporarily clearing all FS-related capabilities and
  344  * switching the fsuid/fsgid around to the real ones.
  345  */
  346 asmlinkage long sys_access(const char * filename, int mode)
  347 {
  348         struct nameidata nd;
  349         int old_fsuid, old_fsgid;
  350         kernel_cap_t old_cap;
  351         int res;
  352 
  353         if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
  354                 return -EINVAL;
  355 
  356         old_fsuid = current->fsuid;
  357         old_fsgid = current->fsgid;
  358         old_cap = current->cap_effective;
  359 
  360         current->fsuid = current->uid;
  361         current->fsgid = current->gid;
  362 
  363         /* Clear the capabilities if we switch to a non-root user */
  364         if (current->uid)
  365                 cap_clear(current->cap_effective);
  366         else
  367                 current->cap_effective = current->cap_permitted;
  368 
  369         res = user_path_walk(filename, &nd);
  370         if (!res) {
  371                 res = permission(nd.dentry->d_inode, mode);
  372                 /* SuS v2 requires we report a read only fs too */
  373                 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
  374                    && !special_file(nd.dentry->d_inode->i_mode))
  375                         res = -EROFS;
  376                 path_release(&nd);
  377         }
  378 
  379         current->fsuid = old_fsuid;
  380         current->fsgid = old_fsgid;
  381         current->cap_effective = old_cap;
  382 
  383         return res;
  384 }
  385 
  386 asmlinkage long sys_chdir(const char * filename)
  387 {
  388         int error;
  389         struct nameidata nd;
  390 
  391         error = __user_walk(filename,LOOKUP_POSITIVE|LOOKUP_FOLLOW|LOOKUP_DIRECTORY,&nd);
  392         if (error)
  393                 goto out;
  394 
  395         error = permission(nd.dentry->d_inode,MAY_EXEC);
  396         if (error)
  397                 goto dput_and_out;
  398 
  399         set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  400 
  401 dput_and_out:
  402         path_release(&nd);
  403 out:
  404         return error;
  405 }
  406 
  407 asmlinkage long sys_fchdir(unsigned int fd)
  408 {
  409         struct file *file;
  410         struct dentry *dentry;
  411         struct inode *inode;
  412         struct vfsmount *mnt;
  413         int error;
  414 
  415         error = -EBADF;
  416         file = fget(fd);
  417         if (!file)
  418                 goto out;
  419 
  420         dentry = file->f_dentry;
  421         mnt = file->f_vfsmnt;
  422         inode = dentry->d_inode;
  423 
  424         error = -ENOTDIR;
  425         if (!S_ISDIR(inode->i_mode))
  426                 goto out_putf;
  427 
  428         error = permission(inode, MAY_EXEC);
  429         if (!error)
  430                 set_fs_pwd(current->fs, mnt, dentry);
  431 out_putf:
  432         fput(file);
  433 out:
  434         return error;
  435 }
  436 
  437 asmlinkage long sys_chroot(const char * filename)
  438 {
  439         int error;
  440         struct nameidata nd;
  441 
  442         error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW |
  443                       LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
  444         if (error)
  445                 goto out;
  446 
  447         error = permission(nd.dentry->d_inode,MAY_EXEC);
  448         if (error)
  449                 goto dput_and_out;
  450 
  451         error = -EPERM;
  452         if (!capable(CAP_SYS_CHROOT))
  453                 goto dput_and_out;
  454 
  455         set_fs_root(current->fs, nd.mnt, nd.dentry);
  456         set_fs_altroot();
  457         error = 0;
  458 dput_and_out:
  459         path_release(&nd);
  460 out:
  461         return error;
  462 }
  463 
  464 asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
  465 {
  466         struct inode * inode;
  467         struct dentry * dentry;
  468         struct file * file;
  469         int err = -EBADF;
  470         struct iattr newattrs;
  471 
  472         file = fget(fd);
  473         if (!file)
  474                 goto out;
  475 
  476         dentry = file->f_dentry;
  477         inode = dentry->d_inode;
  478 
  479         err = -EROFS;
  480         if (IS_RDONLY(inode))
  481                 goto out_putf;
  482         err = -EPERM;
  483         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  484                 goto out_putf;
  485         if (mode == (mode_t) -1)
  486                 mode = inode->i_mode;
  487         newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  488         newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  489         err = notify_change(dentry, &newattrs);
  490 
  491 out_putf:
  492         fput(file);
  493 out:
  494         return err;
  495 }
  496 
  497 asmlinkage long sys_chmod(const char * filename, mode_t mode)
  498 {
  499         struct nameidata nd;
  500         struct inode * inode;
  501         int error;
  502         struct iattr newattrs;
  503 
  504         error = user_path_walk(filename, &nd);
  505         if (error)
  506                 goto out;
  507         inode = nd.dentry->d_inode;
  508 
  509         error = -EROFS;
  510         if (IS_RDONLY(inode))
  511                 goto dput_and_out;
  512 
  513         error = -EPERM;
  514         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  515                 goto dput_and_out;
  516 
  517         if (mode == (mode_t) -1)
  518                 mode = inode->i_mode;
  519         newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
  520         newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
  521         error = notify_change(nd.dentry, &newattrs);
  522 
  523 dput_and_out:
  524         path_release(&nd);
  525 out:
  526         return error;
  527 }
  528 
  529 static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
  530 {
  531         struct inode * inode;
  532         int error;
  533         struct iattr newattrs;
  534 
  535         error = -ENOENT;
  536         if (!(inode = dentry->d_inode)) {
  537                 printk(KERN_ERR "chown_common: NULL inode\n");
  538                 goto out;
  539         }
  540         error = -EROFS;
  541         if (IS_RDONLY(inode))
  542                 goto out;
  543         error = -EPERM;
  544         if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  545                 goto out;
  546         if (user == (uid_t) -1)
  547                 user = inode->i_uid;
  548         if (group == (gid_t) -1)
  549                 group = inode->i_gid;
  550         newattrs.ia_mode = inode->i_mode;
  551         newattrs.ia_uid = user;
  552         newattrs.ia_gid = group;
  553         newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
  554         /*
  555          * If the user or group of a non-directory has been changed by a
  556          * non-root user, remove the setuid bit.
  557          * 19981026     David C Niemi <niemi@tux.org>
  558          *
  559          * Changed this to apply to all users, including root, to avoid
  560          * some races. This is the behavior we had in 2.0. The check for
  561          * non-root was definitely wrong for 2.2 anyway, as it should
  562          * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
  563          */
  564         if ((inode->i_mode & S_ISUID) == S_ISUID &&
  565                 !S_ISDIR(inode->i_mode))
  566         {
  567                 newattrs.ia_mode &= ~S_ISUID;
  568                 newattrs.ia_valid |= ATTR_MODE;
  569         }
  570         /*
  571          * Likewise, if the user or group of a non-directory has been changed
  572          * by a non-root user, remove the setgid bit UNLESS there is no group
  573          * execute bit (this would be a file marked for mandatory locking).
  574          * 19981026     David C Niemi <niemi@tux.org>
  575          *
  576          * Removed the fsuid check (see the comment above) -- 19990830 SD.
  577          */
  578         if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) 
  579                 && !S_ISDIR(inode->i_mode))
  580         {
  581                 newattrs.ia_mode &= ~S_ISGID;
  582                 newattrs.ia_valid |= ATTR_MODE;
  583         }
  584         error = notify_change(dentry, &newattrs);
  585 out:
  586         return error;
  587 }
  588 
  589 asmlinkage long sys_chown(const char * filename, uid_t user, gid_t group)
  590 {
  591         struct nameidata nd;
  592         int error;
  593 
  594         error = user_path_walk(filename, &nd);
  595         if (!error) {
  596                 error = chown_common(nd.dentry, user, group);
  597                 path_release(&nd);
  598         }
  599         return error;
  600 }
  601 
  602 asmlinkage long sys_lchown(const char * filename, uid_t user, gid_t group)
  603 {
  604         struct nameidata nd;
  605         int error;
  606 
  607         error = user_path_walk_link(filename, &nd);
  608         if (!error) {
  609                 error = chown_common(nd.dentry, user, group);
  610                 path_release(&nd);
  611         }
  612         return error;
  613 }
  614 
  615 
  616 asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
  617 {
  618         struct file * file;
  619         int error = -EBADF;
  620 
  621         file = fget(fd);
  622         if (file) {
  623                 error = chown_common(file->f_dentry, user, group);
  624                 fput(file);
  625         }
  626         return error;
  627 }
  628 
  629 /*
  630  * Note that while the flag value (low two bits) for sys_open means:
  631  *      00 - read-only
  632  *      01 - write-only
  633  *      10 - read-write
  634  *      11 - special
  635  * it is changed into
  636  *      00 - no permissions needed
  637  *      01 - read-permission
  638  *      10 - write-permission
  639  *      11 - read-write
  640  * for the internal routines (ie open_namei()/follow_link() etc). 00 is
  641  * used by symlinks.
  642  */
  643 struct file *filp_open(const char * filename, int flags, int mode)
  644 {
  645         int namei_flags, error;
  646         struct nameidata nd;
  647 
  648         namei_flags = flags;
  649         if ((namei_flags+1) & O_ACCMODE)
  650                 namei_flags++;
  651         if (namei_flags & O_TRUNC)
  652                 namei_flags |= 2;
  653 
  654         error = open_namei(filename, namei_flags, mode, &nd);
  655         if (!error)
  656                 return dentry_open(nd.dentry, nd.mnt, flags);
  657 
  658         return ERR_PTR(error);
  659 }
  660 
  661 struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
  662 {
  663         struct file * f;
  664         struct inode *inode;
  665         static LIST_HEAD(kill_list);
  666         int error;
  667 
  668         error = -ENFILE;
  669         f = get_empty_filp();
  670         if (!f)
  671                 goto cleanup_dentry;
  672         f->f_flags = flags;
  673         f->f_mode = (flags+1) & O_ACCMODE;
  674         inode = dentry->d_inode;
  675         if (f->f_mode & FMODE_WRITE) {
  676                 error = get_write_access(inode);
  677                 if (error)
  678                         goto cleanup_file;
  679         }
  680 
  681         f->f_dentry = dentry;
  682         f->f_vfsmnt = mnt;
  683         f->f_pos = 0;
  684         f->f_reada = 0;
  685         f->f_op = fops_get(inode->i_fop);
  686         file_move(f, &inode->i_sb->s_files);
  687 
  688         /* preallocate kiobuf for O_DIRECT */
  689         f->f_iobuf = NULL;
  690         f->f_iobuf_lock = 0;
  691         if (f->f_flags & O_DIRECT) {
  692                 error = alloc_kiovec(1, &f->f_iobuf);
  693                 if (error)
  694                         goto cleanup_all;
  695         }
  696 
  697         if (f->f_op && f->f_op->open) {
  698                 error = f->f_op->open(inode,f);
  699                 if (error)
  700                         goto cleanup_all;
  701         }
  702         f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  703 
  704         return f;
  705 
  706 cleanup_all:
  707         if (f->f_iobuf)
  708                 free_kiovec(1, &f->f_iobuf);
  709         fops_put(f->f_op);
  710         if (f->f_mode & FMODE_WRITE)
  711                 put_write_access(inode);
  712         file_move(f, &kill_list); /* out of the way.. */
  713         f->f_dentry = NULL;
  714         f->f_vfsmnt = NULL;
  715 cleanup_file:
  716         put_filp(f);
  717 cleanup_dentry:
  718         dput(dentry);
  719         mntput(mnt);
  720         return ERR_PTR(error);
  721 }
  722 
  723 /*
  724  * Find an empty file descriptor entry, and mark it busy.
  725  */
  726 int get_unused_fd(void)
  727 {
  728         struct files_struct * files = current->files;
  729         int fd, error;
  730 
  731         error = -EMFILE;
  732         write_lock(&files->file_lock);
  733 
  734 repeat:
  735         fd = find_next_zero_bit(files->open_fds, 
  736                                 files->max_fdset, 
  737                                 files->next_fd);
  738 
  739         /*
  740          * N.B. For clone tasks sharing a files structure, this test
  741          * will limit the total number of files that can be opened.
  742          */
  743         if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
  744                 goto out;
  745 
  746         /* Do we need to expand the fdset array? */
  747         if (fd >= files->max_fdset) {
  748                 error = expand_fdset(files, fd);
  749                 if (!error) {
  750                         error = -EMFILE;
  751                         goto repeat;
  752                 }
  753                 goto out;
  754         }
  755         
  756         /* 
  757          * Check whether we need to expand the fd array.
  758          */
  759         if (fd >= files->max_fds) {
  760                 error = expand_fd_array(files, fd);
  761                 if (!error) {
  762                         error = -EMFILE;
  763                         goto repeat;
  764                 }
  765                 goto out;
  766         }
  767 
  768         FD_SET(fd, files->open_fds);
  769         FD_CLR(fd, files->close_on_exec);
  770         files->next_fd = fd + 1;
  771 #if 1
  772         /* Sanity check */
  773         if (files->fd[fd] != NULL) {
  774                 printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
  775                 files->fd[fd] = NULL;
  776         }
  777 #endif
  778         error = fd;
  779 
  780 out:
  781         write_unlock(&files->file_lock);
  782         return error;
  783 }
  784 
  785 asmlinkage long sys_open(const char * filename, int flags, int mode)
  786 {
  787         char * tmp;
  788         int fd, error;
  789 
  790 #if BITS_PER_LONG != 32
  791         flags |= O_LARGEFILE;
  792 #endif
  793         tmp = getname(filename);
  794         fd = PTR_ERR(tmp);
  795         if (!IS_ERR(tmp)) {
  796                 fd = get_unused_fd();
  797                 if (fd >= 0) {
  798                         struct file *f = filp_open(tmp, flags, mode);
  799                         error = PTR_ERR(f);
  800                         if (IS_ERR(f))
  801                                 goto out_error;
  802                         fd_install(fd, f);
  803                 }
  804 out:
  805                 putname(tmp);
  806         }
  807         return fd;
  808 
  809 out_error:
  810         put_unused_fd(fd);
  811         fd = error;
  812         goto out;
  813 }
  814 
  815 #ifndef __alpha__
  816 
  817 /*
  818  * For backward compatibility?  Maybe this should be moved
  819  * into arch/i386 instead?
  820  */
  821 asmlinkage long sys_creat(const char * pathname, int mode)
  822 {
  823         return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
  824 }
  825 
  826 #endif
  827 
  828 /*
  829  * "id" is the POSIX thread ID. We use the
  830  * files pointer for this..
  831  */
  832 int filp_close(struct file *filp, fl_owner_t id)
  833 {
  834         int retval;
  835 
  836         if (!file_count(filp)) {
  837                 printk(KERN_ERR "VFS: Close: file count is 0\n");
  838                 return 0;
  839         }
  840         retval = 0;
  841         if (filp->f_op && filp->f_op->flush) {
  842                 lock_kernel();
  843                 retval = filp->f_op->flush(filp);
  844                 unlock_kernel();
  845         }
  846         dnotify_flush(filp, id);
  847         locks_remove_posix(filp, id);
  848         fput(filp);
  849         return retval;
  850 }
  851 
  852 /*
  853  * Careful here! We test whether the file pointer is NULL before
  854  * releasing the fd. This ensures that one clone task can't release
  855  * an fd while another clone is opening it.
  856  */
  857 asmlinkage long sys_close(unsigned int fd)
  858 {
  859         struct file * filp;
  860         struct files_struct *files = current->files;
  861 
  862         write_lock(&files->file_lock);
  863         if (fd >= files->max_fds)
  864                 goto out_unlock;
  865         filp = files->fd[fd];
  866         if (!filp)
  867                 goto out_unlock;
  868         files->fd[fd] = NULL;
  869         FD_CLR(fd, files->close_on_exec);
  870         __put_unused_fd(files, fd);
  871         write_unlock(&files->file_lock);
  872         return filp_close(filp, files);
  873 
  874 out_unlock:
  875         write_unlock(&files->file_lock);
  876         return -EBADF;
  877 }
  878 
  879 /*
  880  * This routine simulates a hangup on the tty, to arrange that users
  881  * are given clean terminals at login time.
  882  */
  883 asmlinkage long sys_vhangup(void)
  884 {
  885         if (capable(CAP_SYS_TTY_CONFIG)) {
  886                 tty_vhangup(current->tty);
  887                 return 0;
  888         }
  889         return -EPERM;
  890 }
  891 
  892 /*
  893  * Called when an inode is about to be open.
  894  * We use this to disallow opening RW large files on 32bit systems if
  895  * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
  896  * on this flag in sys_open.
  897  */
  898 int generic_file_open(struct inode * inode, struct file * filp)
  899 {
  900         if (!(filp->f_flags & O_LARGEFILE) && inode->i_size > MAX_NON_LFS)
  901                 return -EFBIG;
  902         return 0;
  903 }
  904 
  905 EXPORT_SYMBOL(generic_file_open);

Cache object: 5f8327b1193cdaf668869d527f67dacc


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.