root/fs/open.c

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

DEFINITIONS

This source file includes following definitions.
  1. sys_ustat
  2. sys_statfs
  3. sys_fstatfs
  4. sys_truncate
  5. sys_ftruncate
  6. sys_utime
  7. sys_access
  8. sys_chdir
  9. sys_chroot
  10. sys_fchmod
  11. sys_chmod
  12. sys_fchown
  13. sys_chown
  14. sys_open
  15. sys_creat
  16. sys_close

   1 /*
   2  *  linux/fs/open.c
   3  *
   4  *  (C) 1991  Linus Torvalds
   5  */
   6 
   7 #include <errno.h>
   8 #include <fcntl.h>
   9 #include <sys/types.h>
  10 #include <utime.h>
  11 
  12 #include <sys/stat.h>
  13 #include <sys/vfs.h>
  14 
  15 #include <linux/string.h>
  16 #include <linux/sched.h>
  17 #include <linux/kernel.h>
  18 
  19 #include <asm/segment.h>
  20 
  21 struct file_operations * chrdev_fops[MAX_CHRDEV] = {
  22         NULL,
  23 };
  24 
  25 struct file_operations * blkdev_fops[MAX_BLKDEV] = {
  26         NULL,
  27 };
  28 
  29 int sys_ustat(int dev, struct ustat * ubuf)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         return -ENOSYS;
  32 }
  33 
  34 int sys_statfs(const char * path, struct statfs * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36         printk("statfs not implemented\n");
  37         return -ENOSYS;
  38 }
  39 
  40 int sys_fstatfs(unsigned int fd, struct statfs * buf)
     /* [previous][next][first][last][top][bottom][index][help] */
  41 {
  42         printk("fstatfs not implemented\n");
  43         return -ENOSYS;
  44 }
  45 
  46 int sys_truncate(const char * path, unsigned int length)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         struct inode * inode;
  49 
  50         if (!(inode = namei(path)))
  51                 return -ENOENT;
  52         if (S_ISDIR(inode->i_mode) || !permission(inode,MAY_WRITE)) {
  53                 iput(inode);
  54                 return -EACCES;
  55         }
  56         inode->i_size = length;
  57         if (inode->i_op && inode->i_op->truncate)
  58                 inode->i_op->truncate(inode);
  59         inode->i_atime = inode->i_mtime = CURRENT_TIME;
  60         inode->i_dirt = 1;
  61         iput(inode);
  62         return 0;
  63 }
  64 
  65 int sys_ftruncate(unsigned int fd, unsigned int length)
     /* [previous][next][first][last][top][bottom][index][help] */
  66 {
  67         struct inode * inode;
  68         struct file * file;
  69 
  70         if (fd >= NR_OPEN || !(file = current->filp[fd]))
  71                 return -EBADF;
  72         if (!(inode = file->f_inode))
  73                 return -ENOENT;
  74         if (S_ISDIR(inode->i_mode) || !(file->f_flags & 2))
  75                 return -EACCES;
  76         inode->i_size = length;
  77         if (inode->i_op && inode->i_op->truncate)
  78                 inode->i_op->truncate(inode);
  79         inode->i_atime = inode->i_mtime = CURRENT_TIME;
  80         inode->i_dirt = 1;
  81         return 0;
  82 }
  83 
  84 int sys_utime(char * filename, struct utimbuf * times)
     /* [previous][next][first][last][top][bottom][index][help] */
  85 {
  86         struct inode * inode;
  87         long actime,modtime;
  88 
  89         if (!(inode=namei(filename)))
  90                 return -ENOENT;
  91         if (times) {
  92                 if (current->euid != inode->i_uid &&
  93                     !permission(inode,MAY_WRITE)) {
  94                         iput(inode);
  95                         return -EACCES;
  96                 }
  97                 actime = get_fs_long((unsigned long *) &times->actime);
  98                 modtime = get_fs_long((unsigned long *) &times->modtime);
  99         } else
 100                 actime = modtime = CURRENT_TIME;
 101         inode->i_atime = actime;
 102         inode->i_mtime = modtime;
 103         inode->i_dirt = 1;
 104         iput(inode);
 105         return 0;
 106 }
 107 
 108 /*
 109  * XXX should we use the real or effective uid?  BSD uses the real uid,
 110  * so as to make this call useful to setuid programs.
 111  */
 112 int sys_access(const char * filename,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 113 {
 114         struct inode * inode;
 115         int res, i_mode;
 116 
 117         mode &= 0007;
 118         if (!(inode=namei(filename)))
 119                 return -EACCES;
 120         i_mode = res = inode->i_mode & 0777;
 121         iput(inode);
 122         if (current->uid == inode->i_uid)
 123                 res >>= 6;
 124         else if (current->gid == inode->i_gid)
 125                 res >>= 6;
 126         if ((res & 0007 & mode) == mode)
 127                 return 0;
 128         /*
 129          * XXX we are doing this test last because we really should be
 130          * swapping the effective with the real user id (temporarily),
 131          * and then calling suser() routine.  If we do call the
 132          * suser() routine, it needs to be called last. 
 133          */
 134         if ((!current->uid) &&
 135             (!(mode & 1) || (i_mode & 0111)))
 136                 return 0;
 137         return -EACCES;
 138 }
 139 
 140 int sys_chdir(const char * filename)
     /* [previous][next][first][last][top][bottom][index][help] */
 141 {
 142         struct inode * inode;
 143 
 144         if (!(inode = namei(filename)))
 145                 return -ENOENT;
 146         if (!S_ISDIR(inode->i_mode)) {
 147                 iput(inode);
 148                 return -ENOTDIR;
 149         }
 150         if (!permission(inode,MAY_EXEC)) {
 151                 iput(inode);
 152                 return -EACCES;
 153         }
 154         iput(current->pwd);
 155         current->pwd = inode;
 156         return (0);
 157 }
 158 
 159 int sys_chroot(const char * filename)
     /* [previous][next][first][last][top][bottom][index][help] */
 160 {
 161         struct inode * inode;
 162 
 163         if (!(inode=namei(filename)))
 164                 return -ENOENT;
 165         if (!S_ISDIR(inode->i_mode)) {
 166                 iput(inode);
 167                 return -ENOTDIR;
 168         }
 169         if (!suser()) {
 170                 iput(inode);
 171                 return -EPERM;
 172         }
 173         iput(current->root);
 174         current->root = inode;
 175         return (0);
 176 }
 177 
 178 int sys_fchmod(unsigned int fd, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 179 {
 180         struct inode * inode;
 181         struct file * file;
 182 
 183         if (fd >= NR_OPEN || !(file = current->filp[fd]))
 184                 return -EBADF;
 185         if (!(inode = file->f_inode))
 186                 return -ENOENT;
 187         if ((current->euid != inode->i_uid) && !suser())
 188                 return -EPERM;
 189         inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
 190         inode->i_dirt = 1;
 191         return 0;
 192 }
 193 
 194 int sys_chmod(const char * filename, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 195 {
 196         struct inode * inode;
 197 
 198         if (!(inode = namei(filename)))
 199                 return -ENOENT;
 200         if ((current->euid != inode->i_uid) && !suser()) {
 201                 iput(inode);
 202                 return -EPERM;
 203         }
 204         inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
 205         inode->i_dirt = 1;
 206         iput(inode);
 207         return 0;
 208 }
 209 
 210 int sys_fchown(unsigned int fd, uid_t user, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help] */
 211 {
 212         struct inode * inode;
 213         struct file * file;
 214 
 215         if (fd >= NR_OPEN || !(file = current->filp[fd]))
 216                 return -EBADF;
 217         if (!(inode = file->f_inode))
 218                 return -ENOENT;
 219         if ((current->euid == inode->i_uid && user == inode->i_uid &&
 220              (in_group_p(group) || group == inode->i_gid)) ||
 221             suser()) {
 222                 inode->i_uid = user;
 223                 inode->i_gid = group;
 224                 inode->i_dirt=1;
 225                 return 0;
 226         }
 227         return -EPERM;
 228 }
 229 
 230 int sys_chown(const char * filename, uid_t user, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help] */
 231 {
 232         struct inode * inode;
 233 
 234         if (!(inode = lnamei(filename)))
 235                 return -ENOENT;
 236         if ((current->euid == inode->i_uid && user == inode->i_uid &&
 237              (in_group_p(group) || group == inode->i_gid)) ||
 238             suser()) {
 239                 inode->i_uid = user;
 240                 inode->i_gid = group;
 241                 inode->i_dirt=1;
 242                 iput(inode);
 243                 return 0;
 244         }
 245         iput(inode);
 246         return -EPERM;
 247 }
 248 
 249 int sys_open(const char * filename,int flag,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 250 {
 251         struct inode * inode;
 252         struct file * f;
 253         int i,fd;
 254 
 255         for(fd=0 ; fd<NR_OPEN ; fd++)
 256                 if (!current->filp[fd])
 257                         break;
 258         if (fd>=NR_OPEN)
 259                 return -EINVAL;
 260         current->close_on_exec &= ~(1<<fd);
 261         f=0+file_table;
 262         for (i=0 ; i<NR_FILE ; i++,f++)
 263                 if (!f->f_count) break;
 264         if (i>=NR_FILE)
 265                 return -EINVAL;
 266         (current->filp[fd] = f)->f_count++;
 267         if ((i = open_namei(filename,flag,mode,&inode))<0) {
 268                 current->filp[fd]=NULL;
 269                 f->f_count=0;
 270                 return i;
 271         }
 272         f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
 273         f->f_flags = flag;
 274         f->f_count = 1;
 275         f->f_inode = inode;
 276         f->f_pos = 0;
 277         f->f_reada = 0;
 278         f->f_op = NULL;
 279         if (inode->i_op)
 280                 f->f_op = inode->i_op->default_file_ops;
 281         if (f->f_op && f->f_op->open)
 282                 if (i = f->f_op->open(inode,f)) {
 283                         iput(inode);
 284                         f->f_count=0;
 285                         current->filp[fd]=NULL;
 286                         return i;
 287                 }
 288         return (fd);
 289 }
 290 
 291 int sys_creat(const char * pathname, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293         return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 294 }
 295 
 296 int sys_close(unsigned int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 297 {       
 298         struct file * filp;
 299 
 300         if (fd >= NR_OPEN)
 301                 return -EINVAL;
 302         current->close_on_exec &= ~(1<<fd);
 303         if (!(filp = current->filp[fd]))
 304                 return -EINVAL;
 305         current->filp[fd] = NULL;
 306         if (filp->f_count == 0) {
 307                 printk("Close: file count is 0\n");
 308                 return 0;
 309         }
 310         if (filp->f_count > 1) {
 311                 filp->f_count--;
 312                 return 0;
 313         }
 314         if (filp->f_op && filp->f_op->release)
 315                 filp->f_op->release(filp->f_inode,filp);
 316         iput(filp->f_inode);
 317         filp->f_count--;
 318         return 0;
 319 }

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