home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / KERNEL-S / V1.0 / LINUX-1.0 / LINUX-1 / linux / fs / fcntl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-01  |  2.4 KB  |  104 lines

  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)
  21. {
  22.     if (fd >= NR_OPEN || !current->filp[fd])
  23.         return -EBADF;
  24.     if (arg >= NR_OPEN)
  25.         return -EINVAL;
  26.     while (arg < NR_OPEN)
  27.         if (current->filp[arg])
  28.             arg++;
  29.         else
  30.             break;
  31.     if (arg >= NR_OPEN)
  32.         return -EMFILE;
  33.     FD_CLR(arg, ¤t->close_on_exec);
  34.     (current->filp[arg] = current->filp[fd])->f_count++;
  35.     return arg;
  36. }
  37.  
  38. asmlinkage int sys_dup2(unsigned int oldfd, unsigned int newfd)
  39. {
  40.     if (oldfd >= NR_OPEN || !current->filp[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)
  62. {
  63.     return dupfd(fildes,0);
  64. }
  65.  
  66. asmlinkage int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
  67. {    
  68.     struct file * filp;
  69.  
  70.     if (fd >= NR_OPEN || !(filp = current->filp[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, ¤t->close_on_exec);
  77.         case F_SETFD:
  78.             if (arg&1)
  79.                 FD_SET(fd, ¤t->close_on_exec);
  80.             else
  81.                 FD_CLR(fd, ¤t->close_on_exec);
  82.             return 0;
  83.         case F_GETFL:
  84.             return filp->f_flags;
  85.         case F_SETFL:
  86.             filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
  87.             filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
  88.             return 0;
  89.         case F_GETLK:
  90.             return fcntl_getlk(fd, (struct flock *) arg);
  91.         case F_SETLK:
  92.             return fcntl_setlk(fd, cmd, (struct flock *) arg);
  93.         case F_SETLKW:
  94.             return fcntl_setlk(fd, cmd, (struct flock *) arg);
  95.         default:
  96.             /* sockets need a few special fcntls. */
  97.             if (S_ISSOCK (filp->f_inode->i_mode))
  98.               {
  99.                  return (sock_fcntl (filp, cmd, arg));
  100.               }
  101.             return -EINVAL;
  102.     }
  103. }
  104.