root/fs/fcntl.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. dupfd
  2. sys_dup2
  3. sys_dup
  4. sys_fcntl
  5. kill_fasync

   1 /*
   2  *  linux/fs/fcntl.c
   3  *
   4  *  Copyright (C) 1991, 1992  Linus Torvalds
   5  */
   6 
   7 #include <asm/segment.h>
   8 
   9 #include <linux/sched.h>
  10 #include <linux/kernel.h>
  11 #include <linux/errno.h>
  12 #include <linux/stat.h>
  13 #include <linux/fcntl.h>
  14 #include <linux/string.h>
  15 
  16 extern int fcntl_getlk(unsigned int, struct flock *);
  17 extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
  18 extern int sock_fcntl (struct file *, unsigned int cmd, unsigned long arg);
  19 
  20 static int dupfd(unsigned int fd, unsigned int arg)
     /* [previous][next][first][last][top][bottom][index][help] */
  21 {
  22         if (fd >= NR_OPEN || !current->files->fd[fd])
  23                 return -EBADF;
  24         if (arg >= NR_OPEN)
  25                 return -EINVAL;
  26         while (arg < NR_OPEN)
  27                 if (current->files->fd[arg])
  28                         arg++;
  29                 else
  30                         break;
  31         if (arg >= NR_OPEN)
  32                 return -EMFILE;
  33         FD_CLR(arg, &current->files->close_on_exec);
  34         (current->files->fd[arg] = current->files->fd[fd])->f_count++;
  35         return arg;
  36 }
  37 
  38 asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
     /* [previous][next][first][last][top][bottom][index][help] */
  39 {
  40         if (oldfd >= NR_OPEN || !current->files->fd[oldfd])
  41                 return -EBADF;
  42         if (newfd == oldfd)
  43                 return newfd;
  44         /*
  45          * errno's for dup2() are slightly different than for fcntl(F_DUPFD)
  46          * for historical reasons.
  47          */
  48         if (newfd > NR_OPEN)    /* historical botch - should have been >= */
  49                 return -EBADF;  /* dupfd() would return -EINVAL */
  50 #if 1
  51         if (newfd == NR_OPEN)
  52                 return -EBADF;  /* dupfd() does return -EINVAL and that may
  53                                  * even be the standard!  But that is too
  54                                  * weird for now.
  55                                  */
  56 #endif
  57         sys_close(newfd);
  58         return dupfd(oldfd,newfd);
  59 }
  60 
  61 asmlinkage int sys_dup(unsigned int fildes)
     /* [previous][next][first][last][top][bottom][index][help] */
  62 {
  63         return dupfd(fildes,0);
  64 }
  65 
  66 asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
     /* [previous][next][first][last][top][bottom][index][help] */
  67 {       
  68         struct file * filp;
  69 
  70         if (fd >= NR_OPEN || !(filp = current->files->fd[fd]))
  71                 return -EBADF;
  72         switch (cmd) {
  73                 case F_DUPFD:
  74                         return dupfd(fd,arg);
  75                 case F_GETFD:
  76                         return FD_ISSET(fd, &current->files->close_on_exec);
  77                 case F_SETFD:
  78                         if (arg&1)
  79                                 FD_SET(fd, &current->files->close_on_exec);
  80                         else
  81                                 FD_CLR(fd, &current->files->close_on_exec);
  82                         return 0;
  83                 case F_GETFL:
  84                         return filp->f_flags;
  85                 case F_SETFL:
  86                         /*
  87                          * In the case of an append-only file, O_APPEND
  88                          * cannot be cleared
  89                          */
  90                         if (IS_APPEND(filp->f_inode) && !(arg & O_APPEND))
  91                                 return -EPERM;
  92                         if ((arg & FASYNC) && !(filp->f_flags & FASYNC) &&
  93                             filp->f_op->fasync)
  94                                 filp->f_op->fasync(filp->f_inode, filp, 1);
  95                         if (!(arg & FASYNC) && (filp->f_flags & FASYNC) &&
  96                             filp->f_op->fasync)
  97                                 filp->f_op->fasync(filp->f_inode, filp, 0);
  98                         filp->f_flags &= ~(O_APPEND | O_NONBLOCK | FASYNC);
  99                         filp->f_flags |= arg & (O_APPEND | O_NONBLOCK |
 100                                                 FASYNC);
 101                         return 0;
 102                 case F_GETLK:
 103                         return fcntl_getlk(fd, (struct flock *) arg);
 104                 case F_SETLK:
 105                         return fcntl_setlk(fd, cmd, (struct flock *) arg);
 106                 case F_SETLKW:
 107                         return fcntl_setlk(fd, cmd, (struct flock *) arg);
 108                 case F_GETOWN:
 109                         /*
 110                          * XXX If f_owner is a process group, the
 111                          * negative return value will get converted
 112                          * into an error.  Oops.  If we keep the the
 113                          * current syscall conventions, the only way
 114                          * to fix this will be in libc.
 115                          */
 116                         return filp->f_owner;
 117                 case F_SETOWN:
 118                         filp->f_owner = arg; /* XXX security implications? */
 119                         if (S_ISSOCK (filp->f_inode->i_mode))
 120                                 sock_fcntl (filp, F_SETOWN, arg);
 121                         return 0;
 122                 default:
 123                         /* sockets need a few special fcntls. */
 124                         if (S_ISSOCK (filp->f_inode->i_mode))
 125                           {
 126                              return (sock_fcntl (filp, cmd, arg));
 127                           }
 128                         return -EINVAL;
 129         }
 130 }
 131 
 132 void kill_fasync(struct fasync_struct *fa, int sig)
     /* [previous][next][first][last][top][bottom][index][help] */
 133 {
 134         while (fa) {
 135                 if (fa->magic != FASYNC_MAGIC) {
 136                         printk("kill_fasync: bad magic number in "
 137                                "fasync_struct!\n");
 138                         return;
 139                 }
 140                 if (fa->fa_file->f_owner > 0)
 141                         kill_proc(fa->fa_file->f_owner, sig, 1);
 142                 else
 143                         kill_pg(-fa->fa_file->f_owner, sig, 1);
 144                 fa = fa->fa_next;
 145         }
 146 }

/* [previous][next][first][last][top][bottom][index][help] */