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 (!permission(inode,MAY_WRITE)) {
  53                 iput(inode);
  54                 return -EPERM;
  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 (!(file->f_flags & 2))
  75                 return -EPERM;
  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 -EPERM;
  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         iput(current->pwd);
 151         current->pwd = inode;
 152         return (0);
 153 }
 154 
 155 int sys_chroot(const char * filename)
     /* [previous][next][first][last][top][bottom][index][help] */
 156 {
 157         struct inode * inode;
 158 
 159         if (!(inode=namei(filename)))
 160                 return -ENOENT;
 161         if (!S_ISDIR(inode->i_mode)) {
 162                 iput(inode);
 163                 return -ENOTDIR;
 164         }
 165         iput(current->root);
 166         current->root = inode;
 167         return (0);
 168 }
 169 
 170 int sys_fchmod(unsigned int fd, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 171 {
 172         struct inode * inode;
 173         struct file * file;
 174 
 175         if (fd >= NR_OPEN || !(file = current->filp[fd]))
 176                 return -EBADF;
 177         if (!(inode = file->f_inode))
 178                 return -ENOENT;
 179         if ((current->euid != inode->i_uid) && !suser())
 180                 return -EACCES;
 181         inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
 182         inode->i_dirt = 1;
 183         return 0;
 184 }
 185 
 186 int sys_chmod(const char * filename, mode_t mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 187 {
 188         struct inode * inode;
 189 
 190         if (!(inode = namei(filename)))
 191                 return -ENOENT;
 192         if ((current->euid != inode->i_uid) && !suser()) {
 193                 iput(inode);
 194                 return -EACCES;
 195         }
 196         inode->i_mode = (mode & 07777) | (inode->i_mode & ~07777);
 197         inode->i_dirt = 1;
 198         iput(inode);
 199         return 0;
 200 }
 201 
 202 int sys_fchown(unsigned int fd, uid_t user, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help] */
 203 {
 204         struct inode * inode;
 205         struct file * file;
 206 
 207         if (fd >= NR_OPEN || !(file = current->filp[fd]))
 208                 return -EBADF;
 209         if (!(inode = file->f_inode))
 210                 return -ENOENT;
 211         if (!suser())
 212                 return -EACCES;
 213         inode->i_uid = user;
 214         inode->i_gid = group;
 215         inode->i_dirt=1;
 216         return 0;
 217 }
 218 
 219 int sys_chown(const char * filename, uid_t user, gid_t group)
     /* [previous][next][first][last][top][bottom][index][help] */
 220 {
 221         struct inode * inode;
 222 
 223         if (!(inode = namei(filename)))
 224                 return -ENOENT;
 225         if (!suser()) {
 226                 iput(inode);
 227                 return -EACCES;
 228         }
 229         inode->i_uid = user;
 230         inode->i_gid = group;
 231         inode->i_dirt = 1;
 232         iput(inode);
 233         return 0;
 234 }
 235 
 236 int sys_open(const char * filename,int flag,int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238         struct inode * inode;
 239         struct file * f;
 240         int i,fd;
 241 
 242         for(fd=0 ; fd<NR_OPEN ; fd++)
 243                 if (!current->filp[fd])
 244                         break;
 245         if (fd>=NR_OPEN)
 246                 return -EINVAL;
 247         current->close_on_exec &= ~(1<<fd);
 248         f=0+file_table;
 249         for (i=0 ; i<NR_FILE ; i++,f++)
 250                 if (!f->f_count) break;
 251         if (i>=NR_FILE)
 252                 return -EINVAL;
 253         (current->filp[fd] = f)->f_count++;
 254         if ((i = open_namei(filename,flag,mode,&inode))<0) {
 255                 current->filp[fd]=NULL;
 256                 f->f_count=0;
 257                 return i;
 258         }
 259         f->f_op = NULL;
 260         if (inode)
 261                 if (S_ISCHR(inode->i_mode)) {
 262                         i = MAJOR(inode->i_rdev);
 263                         if (i < MAX_CHRDEV)
 264                                 f->f_op = chrdev_fops[i];
 265                 } else if (S_ISBLK(inode->i_mode)) {
 266                         i = MAJOR(inode->i_rdev);
 267                         if (i < MAX_CHRDEV)
 268                                 f->f_op = blkdev_fops[i];
 269                 }
 270         f->f_mode = "\001\002\003\000"[flag & O_ACCMODE];
 271         f->f_flags = flag;
 272         f->f_count = 1;
 273         f->f_inode = inode;
 274         f->f_pos = 0;
 275         if (inode->i_op && inode->i_op->open)
 276                 if (i = inode->i_op->open(inode,f)) {
 277                         iput(inode);
 278                         f->f_count=0;
 279                         current->filp[fd]=NULL;
 280                         return i;
 281                 }
 282         return (fd);
 283 }
 284 
 285 int sys_creat(const char * pathname, int mode)
     /* [previous][next][first][last][top][bottom][index][help] */
 286 {
 287         return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 288 }
 289 
 290 int sys_close(unsigned int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 291 {       
 292         struct file * filp;
 293 
 294         if (fd >= NR_OPEN)
 295                 return -EINVAL;
 296         current->close_on_exec &= ~(1<<fd);
 297         if (!(filp = current->filp[fd]))
 298                 return -EINVAL;
 299         current->filp[fd] = NULL;
 300         if (filp->f_count == 0)
 301                 panic("Close: file count is 0");
 302         if (--filp->f_count)
 303                 return (0);
 304         if (filp->f_op && filp->f_op->close)
 305                 return filp->f_op->close(filp->f_inode,filp);
 306         iput(filp->f_inode);
 307         return 0;
 308 }

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