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
  17. sys_vhangup

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

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