linux-bk/fs/open.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/open.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/string.h>
   8#include <linux/mm.h>
   9#include <linux/utime.h>
  10#include <linux/file.h>
  11#include <linux/smp_lock.h>
  12#include <linux/quotaops.h>
  13#include <linux/dnotify.h>
  14#include <linux/module.h>
  15#include <linux/slab.h>
  16#include <linux/tty.h>
  17#include <linux/namei.h>
  18#include <linux/backing-dev.h>
  19#include <linux/security.h>
  20#include <linux/mount.h>
  21#include <linux/vfs.h>
  22#include <asm/uaccess.h>
  23#include <linux/fs.h>
  24#include <linux/pagemap.h>
  25
  26int vfs_statfs(struct super_block *sb, struct kstatfs *buf)
  27{
  28        int retval = -ENODEV;
  29
  30        if (sb) {
  31                retval = -ENOSYS;
  32                if (sb->s_op->statfs) {
  33                        memset(buf, 0, sizeof(*buf));
  34                        retval = security_sb_statfs(sb);
  35                        if (retval)
  36                                return retval;
  37                        retval = sb->s_op->statfs(sb, buf);
  38                        if (retval == 0 && buf->f_frsize == 0)
  39                                buf->f_frsize = buf->f_bsize;
  40                }
  41        }
  42        return retval;
  43}
  44
  45EXPORT_SYMBOL(vfs_statfs);
  46
  47static int vfs_statfs_native(struct super_block *sb, struct statfs *buf)
  48{
  49        struct kstatfs st;
  50        int retval;
  51
  52        retval = vfs_statfs(sb, &st);
  53        if (retval)
  54                return retval;
  55
  56        if (sizeof(*buf) == sizeof(st))
  57                memcpy(buf, &st, sizeof(st));
  58        else {
  59                if (sizeof buf->f_blocks == 4) {
  60                        if ((st.f_blocks | st.f_bfree |
  61                             st.f_bavail | st.f_files | st.f_ffree) &
  62                            0xffffffff00000000ULL)
  63                                return -EOVERFLOW;
  64                }
  65
  66                buf->f_type = st.f_type;
  67                buf->f_bsize = st.f_bsize;
  68                buf->f_blocks = st.f_blocks;
  69                buf->f_bfree = st.f_bfree;
  70                buf->f_bavail = st.f_bavail;
  71                buf->f_files = st.f_files;
  72                buf->f_ffree = st.f_ffree;
  73                buf->f_fsid = st.f_fsid;
  74                buf->f_namelen = st.f_namelen;
  75                buf->f_frsize = st.f_frsize;
  76                memset(buf->f_spare, 0, sizeof(buf->f_spare));
  77        }
  78        return 0;
  79}
  80
  81static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf)
  82{
  83        struct kstatfs st;
  84        int retval;
  85
  86        retval = vfs_statfs(sb, &st);
  87        if (retval)
  88                return retval;
  89
  90        if (sizeof(*buf) == sizeof(st))
  91                memcpy(buf, &st, sizeof(st));
  92        else {
  93                buf->f_type = st.f_type;
  94                buf->f_bsize = st.f_bsize;
  95                buf->f_blocks = st.f_blocks;
  96                buf->f_bfree = st.f_bfree;
  97                buf->f_bavail = st.f_bavail;
  98                buf->f_files = st.f_files;
  99                buf->f_ffree = st.f_ffree;
 100                buf->f_fsid = st.f_fsid;
 101                buf->f_namelen = st.f_namelen;
 102                buf->f_frsize = st.f_frsize;
 103                memset(buf->f_spare, 0, sizeof(buf->f_spare));
 104        }
 105        return 0;
 106}
 107
 108asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf)
 109{
 110        struct nameidata nd;
 111        int error;
 112
 113        error = user_path_walk(path, &nd);
 114        if (!error) {
 115                struct statfs tmp;
 116                error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp);
 117                if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 118                        error = -EFAULT;
 119                path_release(&nd);
 120        }
 121        return error;
 122}
 123
 124
 125asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 __user *buf)
 126{
 127        struct nameidata nd;
 128        long error;
 129
 130        if (sz != sizeof(*buf))
 131                return -EINVAL;
 132        error = user_path_walk(path, &nd);
 133        if (!error) {
 134                struct statfs64 tmp;
 135                error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp);
 136                if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 137                        error = -EFAULT;
 138                path_release(&nd);
 139        }
 140        return error;
 141}
 142
 143
 144asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf)
 145{
 146        struct file * file;
 147        struct statfs tmp;
 148        int error;
 149
 150        error = -EBADF;
 151        file = fget(fd);
 152        if (!file)
 153                goto out;
 154        error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp);
 155        if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 156                error = -EFAULT;
 157        fput(file);
 158out:
 159        return error;
 160}
 161
 162asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user *buf)
 163{
 164        struct file * file;
 165        struct statfs64 tmp;
 166        int error;
 167
 168        if (sz != sizeof(*buf))
 169                return -EINVAL;
 170
 171        error = -EBADF;
 172        file = fget(fd);
 173        if (!file)
 174                goto out;
 175        error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp);
 176        if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
 177                error = -EFAULT;
 178        fput(file);
 179out:
 180        return error;
 181}
 182
 183int do_truncate(struct dentry *dentry, loff_t length)
 184{
 185        int err;
 186        struct iattr newattrs;
 187
 188        /* Not pretty: "inode->i_size" shouldn't really be signed. But it is. */
 189        if (length < 0)
 190                return -EINVAL;
 191
 192        newattrs.ia_size = length;
 193        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
 194        down(&dentry->d_inode->i_sem);
 195        err = notify_change(dentry, &newattrs);
 196        up(&dentry->d_inode->i_sem);
 197        return err;
 198}
 199
 200static inline long do_sys_truncate(const char __user * path, loff_t length)
 201{
 202        struct nameidata nd;
 203        struct inode * inode;
 204        int error;
 205
 206        error = -EINVAL;
 207        if (length < 0) /* sorry, but loff_t says... */
 208                goto out;
 209
 210        error = user_path_walk(path, &nd);
 211        if (error)
 212                goto out;
 213        inode = nd.dentry->d_inode;
 214
 215        /* For directories it's -EISDIR, for other non-regulars - -EINVAL */
 216        error = -EISDIR;
 217        if (S_ISDIR(inode->i_mode))
 218                goto dput_and_out;
 219
 220        error = -EINVAL;
 221        if (!S_ISREG(inode->i_mode))
 222                goto dput_and_out;
 223
 224        error = permission(inode,MAY_WRITE,&nd);
 225        if (error)
 226                goto dput_and_out;
 227
 228        error = -EROFS;
 229        if (IS_RDONLY(inode))
 230                goto dput_and_out;
 231
 232        error = -EPERM;
 233        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 234                goto dput_and_out;
 235
 236        /*
 237         * Make sure that there are no leases.
 238         */
 239        error = break_lease(inode, FMODE_WRITE);
 240        if (error)
 241                goto dput_and_out;
 242
 243        error = get_write_access(inode);
 244        if (error)
 245                goto dput_and_out;
 246
 247        error = locks_verify_truncate(inode, NULL, length);
 248        if (!error) {
 249                DQUOT_INIT(inode);
 250                error = do_truncate(nd.dentry, length);
 251        }
 252        put_write_access(inode);
 253
 254dput_and_out:
 255        path_release(&nd);
 256out:
 257        return error;
 258}
 259
 260asmlinkage long sys_truncate(const char __user * path, unsigned long length)
 261{
 262        /* on 32-bit boxen it will cut the range 2^31--2^32-1 off */
 263        return do_sys_truncate(path, (long)length);
 264}
 265
 266static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
 267{
 268        struct inode * inode;
 269        struct dentry *dentry;
 270        struct file * file;
 271        int error;
 272
 273        error = -EINVAL;
 274        if (length < 0)
 275                goto out;
 276        error = -EBADF;
 277        file = fget(fd);
 278        if (!file)
 279                goto out;
 280
 281        /* explicitly opened as large or we are on 64-bit box */
 282        if (file->f_flags & O_LARGEFILE)
 283                small = 0;
 284
 285        dentry = file->f_dentry;
 286        inode = dentry->d_inode;
 287        error = -EINVAL;
 288        if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
 289                goto out_putf;
 290
 291        error = -EINVAL;
 292        /* Cannot ftruncate over 2^31 bytes without large file support */
 293        if (small && length > MAX_NON_LFS)
 294                goto out_putf;
 295
 296        error = -EPERM;
 297        if (IS_APPEND(inode))
 298                goto out_putf;
 299
 300        error = locks_verify_truncate(inode, file, length);
 301        if (!error)
 302                error = do_truncate(dentry, length);
 303out_putf:
 304        fput(file);
 305out:
 306        return error;
 307}
 308
 309asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length)
 310{
 311        return do_sys_ftruncate(fd, length, 1);
 312}
 313
 314/* LFS versions of truncate are only needed on 32 bit machines */
 315#if BITS_PER_LONG == 32
 316asmlinkage long sys_truncate64(const char __user * path, loff_t length)
 317{
 318        return do_sys_truncate(path, length);
 319}
 320
 321asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length)
 322{
 323        return do_sys_ftruncate(fd, length, 0);
 324}
 325#endif
 326
 327#if !(defined(__alpha__) || defined(__ia64__))
 328
 329/*
 330 * sys_utime() can be implemented in user-level using sys_utimes().
 331 * Is this for backwards compatibility?  If so, why not move it
 332 * into the appropriate arch directory (for those architectures that
 333 * need it).
 334 */
 335
 336/* If times==NULL, set access and modification to current time,
 337 * must be owner or have write permission.
 338 * Else, update from *times, must be owner or super user.
 339 */
 340asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times)
 341{
 342        int error;
 343        struct nameidata nd;
 344        struct inode * inode;
 345        struct iattr newattrs;
 346
 347        error = user_path_walk(filename, &nd);
 348        if (error)
 349                goto out;
 350        inode = nd.dentry->d_inode;
 351
 352        error = -EROFS;
 353        if (IS_RDONLY(inode))
 354                goto dput_and_out;
 355
 356        /* Don't worry, the checks are done in inode_change_ok() */
 357        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 358        if (times) {
 359                error = -EPERM;
 360                if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 361                        goto dput_and_out;
 362
 363                error = get_user(newattrs.ia_atime.tv_sec, &times->actime);
 364                newattrs.ia_atime.tv_nsec = 0;
 365                if (!error) 
 366                        error = get_user(newattrs.ia_mtime.tv_sec, &times->modtime);
 367                newattrs.ia_mtime.tv_nsec = 0;
 368                if (error)
 369                        goto dput_and_out;
 370
 371                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 372        } else {
 373                error = -EACCES;
 374                if (IS_IMMUTABLE(inode))
 375                        goto dput_and_out;
 376
 377                if (current->fsuid != inode->i_uid &&
 378                    (error = permission(inode,MAY_WRITE,&nd)) != 0)
 379                        goto dput_and_out;
 380        }
 381        down(&inode->i_sem);
 382        error = notify_change(nd.dentry, &newattrs);
 383        up(&inode->i_sem);
 384dput_and_out:
 385        path_release(&nd);
 386out:
 387        return error;
 388}
 389
 390#endif
 391
 392/* If times==NULL, set access and modification to current time,
 393 * must be owner or have write permission.
 394 * Else, update from *times, must be owner or super user.
 395 */
 396long do_utimes(char __user * filename, struct timeval * times)
 397{
 398        int error;
 399        struct nameidata nd;
 400        struct inode * inode;
 401        struct iattr newattrs;
 402
 403        error = user_path_walk(filename, &nd);
 404
 405        if (error)
 406                goto out;
 407        inode = nd.dentry->d_inode;
 408
 409        error = -EROFS;
 410        if (IS_RDONLY(inode))
 411                goto dput_and_out;
 412
 413        /* Don't worry, the checks are done in inode_change_ok() */
 414        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 415        if (times) {
 416                error = -EPERM;
 417                if (IS_APPEND(inode) || IS_IMMUTABLE(inode))
 418                        goto dput_and_out;
 419
 420                newattrs.ia_atime.tv_sec = times[0].tv_sec;
 421                newattrs.ia_atime.tv_nsec = times[0].tv_usec * 1000;
 422                newattrs.ia_mtime.tv_sec = times[1].tv_sec;
 423                newattrs.ia_mtime.tv_nsec = times[1].tv_usec * 1000;
 424                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 425        } else {
 426                error = -EACCES;
 427                if (IS_IMMUTABLE(inode))
 428                        goto dput_and_out;
 429
 430                if (current->fsuid != inode->i_uid &&
 431                    (error = permission(inode,MAY_WRITE,&nd)) != 0)
 432                        goto dput_and_out;
 433        }
 434        down(&inode->i_sem);
 435        error = notify_change(nd.dentry, &newattrs);
 436        up(&inode->i_sem);
 437dput_and_out:
 438        path_release(&nd);
 439out:
 440        return error;
 441}
 442
 443asmlinkage long sys_utimes(char __user * filename, struct timeval __user * utimes)
 444{
 445        struct timeval times[2];
 446
 447        if (utimes && copy_from_user(&times, utimes, sizeof(times)))
 448                return -EFAULT;
 449        return do_utimes(filename, utimes ? times : NULL);
 450}
 451
 452
 453/*
 454 * access() needs to use the real uid/gid, not the effective uid/gid.
 455 * We do this by temporarily clearing all FS-related capabilities and
 456 * switching the fsuid/fsgid around to the real ones.
 457 */
 458asmlinkage long sys_access(const char __user * filename, int mode)
 459{
 460        struct nameidata nd;
 461        int old_fsuid, old_fsgid;
 462        kernel_cap_t old_cap;
 463        int res;
 464
 465        if (mode & ~S_IRWXO)    /* where's F_OK, X_OK, W_OK, R_OK? */
 466                return -EINVAL;
 467
 468        old_fsuid = current->fsuid;
 469        old_fsgid = current->fsgid;
 470        old_cap = current->cap_effective;
 471
 472        current->fsuid = current->uid;
 473        current->fsgid = current->gid;
 474
 475        /*
 476         * Clear the capabilities if we switch to a non-root user
 477         *
 478         * FIXME: There is a race here against sys_capset.  The
 479         * capabilities can change yet we will restore the old
 480         * value below.  We should hold task_capabilities_lock,
 481         * but we cannot because user_path_walk can sleep.
 482         */
 483        if (current->uid)
 484                cap_clear(current->cap_effective);
 485        else
 486                current->cap_effective = current->cap_permitted;
 487
 488        res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd);
 489        if (!res) {
 490                res = permission(nd.dentry->d_inode, mode, &nd);
 491                /* SuS v2 requires we report a read only fs too */
 492                if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
 493                   && !special_file(nd.dentry->d_inode->i_mode))
 494                        res = -EROFS;
 495                path_release(&nd);
 496        }
 497
 498        current->fsuid = old_fsuid;
 499        current->fsgid = old_fsgid;
 500        current->cap_effective = old_cap;
 501
 502        return res;
 503}
 504
 505asmlinkage long sys_chdir(const char __user * filename)
 506{
 507        struct nameidata nd;
 508        int error;
 509
 510        error = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &nd);
 511        if (error)
 512                goto out;
 513
 514        error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
 515        if (error)
 516                goto dput_and_out;
 517
 518        set_fs_pwd(current->fs, nd.mnt, nd.dentry);
 519
 520dput_and_out:
 521        path_release(&nd);
 522out:
 523        return error;
 524}
 525
 526asmlinkage long sys_fchdir(unsigned int fd)
 527{
 528        struct file *file;
 529        struct dentry *dentry;
 530        struct inode *inode;
 531        struct vfsmount *mnt;
 532        int error;
 533
 534        error = -EBADF;
 535        file = fget(fd);
 536        if (!file)
 537                goto out;
 538
 539        dentry = file->f_dentry;
 540        mnt = file->f_vfsmnt;
 541        inode = dentry->d_inode;
 542
 543        error = -ENOTDIR;
 544        if (!S_ISDIR(inode->i_mode))
 545                goto out_putf;
 546
 547        error = permission(inode, MAY_EXEC, NULL);
 548        if (!error)
 549                set_fs_pwd(current->fs, mnt, dentry);
 550out_putf:
 551        fput(file);
 552out:
 553        return error;
 554}
 555
 556asmlinkage long sys_chroot(const char __user * filename)
 557{
 558        struct nameidata nd;
 559        int error;
 560
 561        error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
 562        if (error)
 563                goto out;
 564
 565        error = permission(nd.dentry->d_inode,MAY_EXEC,&nd);
 566        if (error)
 567                goto dput_and_out;
 568
 569        error = -EPERM;
 570        if (!capable(CAP_SYS_CHROOT))
 571                goto dput_and_out;
 572
 573        set_fs_root(current->fs, nd.mnt, nd.dentry);
 574        set_fs_altroot();
 575        error = 0;
 576dput_and_out:
 577        path_release(&nd);
 578out:
 579        return error;
 580}
 581
 582asmlinkage long sys_fchmod(unsigned int fd, mode_t mode)
 583{
 584        struct inode * inode;
 585        struct dentry * dentry;
 586        struct file * file;
 587        int err = -EBADF;
 588        struct iattr newattrs;
 589
 590        file = fget(fd);
 591        if (!file)
 592                goto out;
 593
 594        dentry = file->f_dentry;
 595        inode = dentry->d_inode;
 596
 597        err = -EROFS;
 598        if (IS_RDONLY(inode))
 599                goto out_putf;
 600        err = -EPERM;
 601        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 602                goto out_putf;
 603        down(&inode->i_sem);
 604        if (mode == (mode_t) -1)
 605                mode = inode->i_mode;
 606        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 607        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 608        err = notify_change(dentry, &newattrs);
 609        up(&inode->i_sem);
 610
 611out_putf:
 612        fput(file);
 613out:
 614        return err;
 615}
 616
 617asmlinkage long sys_chmod(const char __user * filename, mode_t mode)
 618{
 619        struct nameidata nd;
 620        struct inode * inode;
 621        int error;
 622        struct iattr newattrs;
 623
 624        error = user_path_walk(filename, &nd);
 625        if (error)
 626                goto out;
 627        inode = nd.dentry->d_inode;
 628
 629        error = -EROFS;
 630        if (IS_RDONLY(inode))
 631                goto dput_and_out;
 632
 633        error = -EPERM;
 634        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 635                goto dput_and_out;
 636
 637        down(&inode->i_sem);
 638        if (mode == (mode_t) -1)
 639                mode = inode->i_mode;
 640        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 641        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 642        error = notify_change(nd.dentry, &newattrs);
 643        up(&inode->i_sem);
 644
 645dput_and_out:
 646        path_release(&nd);
 647out:
 648        return error;
 649}
 650
 651static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 652{
 653        struct inode * inode;
 654        int error;
 655        struct iattr newattrs;
 656
 657        error = -ENOENT;
 658        if (!(inode = dentry->d_inode)) {
 659                printk(KERN_ERR "chown_common: NULL inode\n");
 660                goto out;
 661        }
 662        error = -EROFS;
 663        if (IS_RDONLY(inode))
 664                goto out;
 665        error = -EPERM;
 666        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 667                goto out;
 668        newattrs.ia_valid =  ATTR_CTIME;
 669        if (user != (uid_t) -1) {
 670                newattrs.ia_valid |= ATTR_UID;
 671                newattrs.ia_uid = user;
 672        }
 673        if (group != (gid_t) -1) {
 674                newattrs.ia_valid |= ATTR_GID;
 675                newattrs.ia_gid = group;
 676        }
 677        if (!S_ISDIR(inode->i_mode))
 678                newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID;
 679        down(&inode->i_sem);
 680        error = notify_change(dentry, &newattrs);
 681        up(&inode->i_sem);
 682out:
 683        return error;
 684}
 685
 686asmlinkage long sys_chown(const char __user * filename, uid_t user, gid_t group)
 687{
 688        struct nameidata nd;
 689        int error;
 690
 691        error = user_path_walk(filename, &nd);
 692        if (!error) {
 693                error = chown_common(nd.dentry, user, group);
 694                path_release(&nd);
 695        }
 696        return error;
 697}
 698
 699asmlinkage long sys_lchown(const char __user * filename, uid_t user, gid_t group)
 700{
 701        struct nameidata nd;
 702        int error;
 703
 704        error = user_path_walk_link(filename, &nd);
 705        if (!error) {
 706                error = chown_common(nd.dentry, user, group);
 707                path_release(&nd);
 708        }
 709        return error;
 710}
 711
 712
 713asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group)
 714{
 715        struct file * file;
 716        int error = -EBADF;
 717
 718        file = fget(fd);
 719        if (file) {
 720                error = chown_common(file->f_dentry, user, group);
 721                fput(file);
 722        }
 723        return error;
 724}
 725
 726/*
 727 * Note that while the flag value (low two bits) for sys_open means:
 728 *      00 - read-only
 729 *      01 - write-only
 730 *      10 - read-write
 731 *      11 - special
 732 * it is changed into
 733 *      00 - no permissions needed
 734 *      01 - read-permission
 735 *      10 - write-permission
 736 *      11 - read-write
 737 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
 738 * used by symlinks.
 739 */
 740struct file *filp_open(const char * filename, int flags, int mode)
 741{
 742        int namei_flags, error;
 743        struct nameidata nd;
 744
 745        namei_flags = flags;
 746        if ((namei_flags+1) & O_ACCMODE)
 747                namei_flags++;
 748        if (namei_flags & O_TRUNC)
 749                namei_flags |= 2;
 750
 751        error = open_namei(filename, namei_flags, mode, &nd);
 752        if (!error)
 753                return dentry_open(nd.dentry, nd.mnt, flags);
 754
 755        return ERR_PTR(error);
 756}
 757
 758EXPORT_SYMBOL(filp_open);
 759
 760struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
 761{
 762        struct file * f;
 763        struct inode *inode;
 764        int error;
 765
 766        error = -ENFILE;
 767        f = get_empty_filp();
 768        if (!f)
 769                goto cleanup_dentry;
 770        f->f_flags = flags;
 771        f->f_mode = (flags+1) & O_ACCMODE;
 772        inode = dentry->d_inode;
 773        if (f->f_mode & FMODE_WRITE) {
 774                error = get_write_access(inode);
 775                if (error)
 776                        goto cleanup_file;
 777        }
 778
 779        file_ra_state_init(&f->f_ra, inode->i_mapping);
 780        f->f_dentry = dentry;
 781        f->f_vfsmnt = mnt;
 782        f->f_pos = 0;
 783        f->f_op = fops_get(inode->i_fop);
 784        file_move(f, &inode->i_sb->s_files);
 785
 786        if (f->f_op && f->f_op->open) {
 787                error = f->f_op->open(inode,f);
 788                if (error)
 789                        goto cleanup_all;
 790        }
 791        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 792
 793        /* NB: we're sure to have correct a_ops only after f_op->open */
 794        if (f->f_flags & O_DIRECT) {
 795                if (!inode->i_mapping || !inode->i_mapping->a_ops ||
 796                        !inode->i_mapping->a_ops->direct_IO) {
 797                                fput(f);
 798                                f = ERR_PTR(-EINVAL);
 799                }
 800        }
 801
 802        return f;
 803
 804cleanup_all:
 805        fops_put(f->f_op);
 806        if (f->f_mode & FMODE_WRITE)
 807                put_write_access(inode);
 808        file_kill(f);
 809        f->f_dentry = NULL;
 810        f->f_vfsmnt = NULL;
 811cleanup_file:
 812        put_filp(f);
 813cleanup_dentry:
 814        dput(dentry);
 815        mntput(mnt);
 816        return ERR_PTR(error);
 817}
 818
 819EXPORT_SYMBOL(dentry_open);
 820
 821/*
 822 * Find an empty file descriptor entry, and mark it busy.
 823 */
 824int get_unused_fd(void)
 825{
 826        struct files_struct * files = current->files;
 827        int fd, error;
 828
 829        error = -EMFILE;
 830        spin_lock(&files->file_lock);
 831
 832repeat:
 833        fd = find_next_zero_bit(files->open_fds->fds_bits, 
 834                                files->max_fdset, 
 835                                files->next_fd);
 836
 837        /*
 838         * N.B. For clone tasks sharing a files structure, this test
 839         * will limit the total number of files that can be opened.
 840         */
 841        if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
 842                goto out;
 843
 844        /* Do we need to expand the fdset array? */
 845        if (fd >= files->max_fdset) {
 846                error = expand_fdset(files, fd);
 847                if (!error) {
 848                        error = -EMFILE;
 849                        goto repeat;
 850                }
 851                goto out;
 852        }
 853        
 854        /* 
 855         * Check whether we need to expand the fd array.
 856         */
 857        if (fd >= files->max_fds) {
 858                error = expand_fd_array(files, fd);
 859                if (!error) {
 860                        error = -EMFILE;
 861                        goto repeat;
 862                }
 863                goto out;
 864        }
 865
 866        FD_SET(fd, files->open_fds);
 867        FD_CLR(fd, files->close_on_exec);
 868        files->next_fd = fd + 1;
 869#if 1
 870        /* Sanity check */
 871        if (files->fd[fd] != NULL) {
 872                printk(KERN_WARNING "get_unused_fd: slot %d not NULL!\n", fd);
 873                files->fd[fd] = NULL;
 874        }
 875#endif
 876        error = fd;
 877
 878out:
 879        spin_unlock(&files->file_lock);
 880        return error;
 881}
 882
 883EXPORT_SYMBOL(get_unused_fd);
 884
 885static inline void __put_unused_fd(struct files_struct *files, unsigned int fd)
 886{
 887        __FD_CLR(fd, files->open_fds);
 888        if (fd < files->next_fd)
 889                files->next_fd = fd;
 890}
 891
 892void put_unused_fd(unsigned int fd)
 893{
 894        struct files_struct *files = current->files;
 895        spin_lock(&files->file_lock);
 896        __put_unused_fd(files, fd);
 897        spin_unlock(&files->file_lock);
 898}
 899
 900EXPORT_SYMBOL(put_unused_fd);
 901
 902/*
 903 * Install a file pointer in the fd array.  
 904 *
 905 * The VFS is full of places where we drop the files lock between
 906 * setting the open_fds bitmap and installing the file in the file
 907 * array.  At any such point, we are vulnerable to a dup2() race
 908 * installing a file in the array before us.  We need to detect this and
 909 * fput() the struct file we are about to overwrite in this case.
 910 *
 911 * It should never happen - if we allow dup2() do it, _really_ bad things
 912 * will follow.
 913 */
 914
 915void fd_install(unsigned int fd, struct file * file)
 916{
 917        struct files_struct *files = current->files;
 918        spin_lock(&files->file_lock);
 919        if (unlikely(files->fd[fd] != NULL))
 920                BUG();
 921        files->fd[fd] = file;
 922        spin_unlock(&files->file_lock);
 923}
 924
 925EXPORT_SYMBOL(fd_install);
 926
 927asmlinkage long sys_open(const char __user * filename, int flags, int mode)
 928{
 929        char * tmp;
 930        int fd, error;
 931
 932#if BITS_PER_LONG != 32
 933        flags |= O_LARGEFILE;
 934#endif
 935        tmp = getname(filename);
 936        fd = PTR_ERR(tmp);
 937        if (!IS_ERR(tmp)) {
 938                fd = get_unused_fd();
 939                if (fd >= 0) {
 940                        struct file *f = filp_open(tmp, flags, mode);
 941                        error = PTR_ERR(f);
 942                        if (IS_ERR(f))
 943                                goto out_error;
 944                        fd_install(fd, f);
 945                }
 946out:
 947                putname(tmp);
 948        }
 949        return fd;
 950
 951out_error:
 952        put_unused_fd(fd);
 953        fd = error;
 954        goto out;
 955}
 956
 957#ifndef __alpha__
 958
 959/*
 960 * For backward compatibility?  Maybe this should be moved
 961 * into arch/i386 instead?
 962 */
 963asmlinkage long sys_creat(const char __user * pathname, int mode)
 964{
 965        return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 966}
 967
 968#endif
 969
 970/*
 971 * "id" is the POSIX thread ID. We use the
 972 * files pointer for this..
 973 */
 974int filp_close(struct file *filp, fl_owner_t id)
 975{
 976        int retval;
 977
 978        /* Report and clear outstanding errors */
 979        retval = filp->f_error;
 980        if (retval)
 981                filp->f_error = 0;
 982
 983        if (!file_count(filp)) {
 984                printk(KERN_ERR "VFS: Close: file count is 0\n");
 985                return retval;
 986        }
 987
 988        if (filp->f_op && filp->f_op->flush) {
 989                int err = filp->f_op->flush(filp);
 990                if (!retval)
 991                        retval = err;
 992        }
 993
 994        dnotify_flush(filp, id);
 995        locks_remove_posix(filp, id);
 996        fput(filp);
 997        return retval;
 998}
 999
1000EXPORT_SYMBOL(filp_close);
1001
1002/*
1003 * Careful here! We test whether the file pointer is NULL before
1004 * releasing the fd. This ensures that one clone task can't release
1005 * an fd while another clone is opening it.
1006 */
1007asmlinkage long sys_close(unsigned int fd)
1008{
1009        struct file * filp;
1010        struct files_struct *files = current->files;
1011
1012        spin_lock(&files->file_lock);
1013        if (fd >= files->max_fds)
1014                goto out_unlock;
1015        filp = files->fd[fd];
1016        if (!filp)
1017                goto out_unlock;
1018        files->fd[fd] = NULL;
1019        FD_CLR(fd, files->close_on_exec);
1020        __put_unused_fd(files, fd);
1021        spin_unlock(&files->file_lock);
1022        return filp_close(filp, files);
1023
1024out_unlock:
1025        spin_unlock(&files->file_lock);
1026        return -EBADF;
1027}
1028
1029EXPORT_SYMBOL(sys_close);
1030
1031/*
1032 * This routine simulates a hangup on the tty, to arrange that users
1033 * are given clean terminals at login time.
1034 */
1035asmlinkage long sys_vhangup(void)
1036{
1037        if (capable(CAP_SYS_TTY_CONFIG)) {
1038                tty_vhangup(current->tty);
1039                return 0;
1040        }
1041        return -EPERM;
1042}
1043
1044/*
1045 * Called when an inode is about to be open.
1046 * We use this to disallow opening large files on 32bit systems if
1047 * the caller didn't specify O_LARGEFILE.  On 64bit systems we force
1048 * on this flag in sys_open.
1049 */
1050int generic_file_open(struct inode * inode, struct file * filp)
1051{
1052        if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS)
1053                return -EFBIG;
1054        return 0;
1055}
1056
1057EXPORT_SYMBOL(generic_file_open);
1058
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.