root/fs/open.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_ustat
  2. sys_utime
  3. sys_access
  4. sys_chdir
  5. sys_chroot
  6. sys_chmod
  7. sys_chown
  8. sys_open
  9. sys_creat
  10. sys_close

   1 /*
   2  *  linux/fs/open.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 #include <string.h>
   8 #include <errno.h>
   9 #include <fcntl.h>
  10 #include <sys/types.h>
  11 #include <utime.h>
  12 #include <sys/stat.h>
  13 
  14 #include <linux/sched.h>
  15 #include <linux/tty.h>
  16 #include <linux/kernel.h>
  17 #include <asm/segment.h>
  18 
  19 int sys_ustat(int dev, struct ustat * ubuf)
     /* [previous][next][first][last][top][bottom][index][help] */
  20 {
  21         return -ENOSYS;
  22 }
  23 
  24 int sys_utime(char * filename, struct utimbuf * times)
     /* [previous][next][first][last][top][bottom][index][help] */
  25 {
  26         struct m_inode * inode;
  27         long actime,modtime;
  28 
  29         if (!(inode=namei(filename)))
  30                 return -ENOENT;
  31         if (times) {
  32                 actime = get_fs_long((unsigned long *) &times->actime);
  33                 modtime = get_fs_long((unsigned long *) &times->modtime);
  34         } else
  35                 actime = modtime = CURRENT_TIME;
  36         inode->i_atime = actime;
  37         inode->i_mtime = modtime;
  38         inode->i_dirt = 1;
  39         iput(inode);
  40         return 0;
  41 }
  42 
  43 /*
  44  * XXX should we use the real or effective uid?  BSD uses the real uid,
  45  * so as to make this call useful to setuid programs.
  46  */
  47 int sys_access(const char * filename,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
  48 {
  49         struct m_inode * inode;
  50         int res, i_mode;
  51 
  52         mode &= 0007;
  53         if (!(inode=namei(filename)))
  54                 return -EACCES;
  55         i_mode = res = inode->i_mode & 0777;
  56         iput(inode);
  57         if (current->uid == inode->i_uid)
  58                 res >>= 6;
  59         else if (current->gid == inode->i_gid)
  60                 res >>= 6;
  61         if ((res & 0007 & mode) == mode)
  62                 return 0;
  63         /*
  64          * XXX we are doing this test last because we really should be
  65          * swapping the effective with the real user id (temporarily),
  66          * and then calling suser() routine.  If we do call the
  67          * suser() routine, it needs to be called last. 
  68          */
  69         if ((!current->uid) &&
  70             (!(mode & 1) || (i_mode & 0111)))
  71                 return 0;
  72         return -EACCES;
  73 }
  74 
  75 int sys_chdir(const char * filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  76 {
  77         struct m_inode * inode;
  78 
  79         if (!(inode = namei(filename)))
  80                 return -ENOENT;
  81         if (!S_ISDIR(inode->i_mode)) {
  82                 iput(inode);
  83                 return -ENOTDIR;
  84         }
  85         iput(current->pwd);
  86         current->pwd = inode;
  87         return (0);
  88 }
  89 
  90 int sys_chroot(const char * filename)
     /* [previous][next][first][last][top][bottom][index][help] */
  91 {
  92         struct m_inode * inode;
  93 
  94         if (!(inode=namei(filename)))
  95                 return -ENOENT;
  96         if (!S_ISDIR(inode->i_mode)) {
  97                 iput(inode);
  98                 return -ENOTDIR;
  99         }
 100         iput(current->root);
 101         current->root = inode;
 102         return (0);
 103 }
 104 
 105 int sys_chmod(const char * filename,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 106 {
 107         struct m_inode * inode;
 108 
 109         if (!(inode=namei(filename)))
 110                 return -ENOENT;
 111         if ((current->euid != inode->i_uid) && !suser()) {
 112                 iput(inode);
 113                 return -EACCES;
 114         }
 115         inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
 116         inode->i_dirt = 1;
 117         iput(inode);
 118         return 0;
 119 }
 120 
 121 int sys_chown(const char * filename,int uid,int gid)
     /* [previous][next][first][last][top][bottom][index][help] */
 122 {
 123         struct m_inode * inode;
 124 
 125         if (!(inode=namei(filename)))
 126                 return -ENOENT;
 127         if (!suser()) {
 128                 iput(inode);
 129                 return -EACCES;
 130         }
 131         inode->i_uid=uid;
 132         inode->i_gid=gid;
 133         inode->i_dirt=1;
 134         iput(inode);
 135         return 0;
 136 }
 137 
 138 int sys_open(const char * filename,int flag,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 139 {
 140         struct m_inode * inode;
 141         struct file * f;
 142         int i,fd;
 143 
 144         mode &= 0777 & ~current->umask;
 145         for(fd=0 ; fd<NR_OPEN ; fd++)
 146                 if (!current->filp[fd])
 147                         break;
 148         if (fd>=NR_OPEN)
 149                 return -EINVAL;
 150         current->close_on_exec &= ~(1<<fd);
 151         f=0+file_table;
 152         for (i=0 ; i<NR_FILE ; i++,f++)
 153                 if (!f->f_count) break;
 154         if (i>=NR_FILE)
 155                 return -EINVAL;
 156         (current->filp[fd]=f)->f_count++;
 157         if ((i=open_namei(filename,flag,mode,&inode))<0) {
 158                 current->filp[fd]=NULL;
 159                 f->f_count=0;
 160                 return i;
 161         }
 162 /* ttys are somewhat special (ttyxx major==4, tty major==5) */
 163         if (S_ISCHR(inode->i_mode))
 164                 if (MAJOR(inode->i_zone[0])==4) {
 165                         if (current->leader && current->tty<0) {
 166                                 current->tty = MINOR(inode->i_zone[0]);
 167                                 tty_table[current->tty].pgrp = current->pgrp;
 168                         }
 169                 } else if (MAJOR(inode->i_zone[0])==5)
 170                         if (current->tty<0) {
 171                                 iput(inode);
 172                                 current->filp[fd]=NULL;
 173                                 f->f_count=0;
 174                                 return -EPERM;
 175                         }
 176 /* Likewise with block-devices: check for floppy_change */
 177         if (S_ISBLK(inode->i_mode))
 178                 check_disk_change(inode->i_zone[0]);
 179         f->f_mode = inode->i_mode;
 180         f->f_flags = flag;
 181         f->f_count = 1;
 182         f->f_inode = inode;
 183         f->f_pos = 0;
 184         return (fd);
 185 }
 186 
 187 int sys_creat(const char * pathname, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 188 {
 189         return sys_open(pathname, O_CREAT | O_TRUNC, mode);
 190 }
 191 
 192 int sys_close(unsigned int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {       
 194         struct file * filp;
 195 
 196         if (fd >= NR_OPEN)
 197                 return -EINVAL;
 198         current->close_on_exec &= ~(1<<fd);
 199         if (!(filp = current->filp[fd]))
 200                 return -EINVAL;
 201         current->filp[fd] = NULL;
 202         if (filp->f_count == 0)
 203                 panic("Close: file count is 0");
 204         if (--filp->f_count)
 205                 return (0);
 206         iput(filp->f_inode);
 207         return (0);
 208 }

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