linux-old/fs/open.c
<<
>>
Prefs
   1/*
   2 *  linux/fs/open.c
   3 *
   4 *  Copyright (C) 1991, 1992  Linus Torvalds
   5 */
   6
   7#include <linux/mm.h>
   8#include <linux/utime.h>
   9#include <linux/file.h>
  10#include <linux/smp_lock.h>
  11#include <linux/quotaops.h>
  12
  13#include <asm/uaccess.h>
  14
  15asmlinkage int sys_statfs(const char * path, struct statfs * buf)
  16{
  17        struct dentry * dentry;
  18        int error;
  19
  20        lock_kernel();
  21        dentry = namei(path);
  22        error = PTR_ERR(dentry);
  23        if (!IS_ERR(dentry)) {
  24                struct inode * inode = dentry->d_inode;
  25                struct super_block * sb = inode->i_sb;
  26
  27                error = -ENODEV;
  28                if (sb && sb->s_op && sb->s_op->statfs)
  29                        error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
  30
  31                dput(dentry);
  32        }
  33        unlock_kernel();
  34        return error;
  35}
  36
  37asmlinkage int sys_fstatfs(unsigned int fd, struct statfs * buf)
  38{
  39        struct file * file;
  40        struct inode * inode;
  41        struct dentry * dentry;
  42        struct super_block * sb;
  43        int error;
  44
  45        lock_kernel();
  46        error = -EBADF;
  47        file = fget(fd);
  48        if (!file)
  49                goto out;
  50        error = -ENOENT;
  51        if (!(dentry = file->f_dentry))
  52                goto out_putf;
  53        if (!(inode = dentry->d_inode))
  54                goto out_putf;
  55        error = -ENODEV;
  56        sb = inode->i_sb;
  57        if (sb && sb->s_op && sb->s_op->statfs)
  58                error = sb->s_op->statfs(sb, buf, sizeof(struct statfs));
  59out_putf:
  60        fput(file);
  61out:
  62        unlock_kernel();
  63        return error;
  64}
  65
  66int do_truncate(struct dentry *dentry, unsigned long length)
  67{
  68        struct inode *inode = dentry->d_inode;
  69        int error;
  70        struct iattr newattrs;
  71
  72        /* Not pretty: "inode->i_size" shouldn't really be "off_t". But it is. */
  73        if ((off_t) length < 0)
  74                return -EINVAL;
  75
  76        fs_down(&inode->i_sem);
  77        newattrs.ia_size = length;
  78        newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME;
  79        error = notify_change(dentry, &newattrs);
  80        if (!error) {
  81                /* truncate virtual mappings of this file */
  82                vmtruncate(inode, length);
  83                if (inode->i_op && inode->i_op->truncate)
  84                        inode->i_op->truncate(inode);
  85        }
  86        fs_up(&inode->i_sem);
  87        return error;
  88}
  89
  90asmlinkage int sys_truncate(const char * path, unsigned long length)
  91{
  92        struct dentry * dentry;
  93        struct inode * inode;
  94        int error;
  95
  96        lock_kernel();
  97        dentry = namei(path);
  98
  99        error = PTR_ERR(dentry);
 100        if (IS_ERR(dentry))
 101                goto out;
 102        inode = dentry->d_inode;
 103
 104        error = -EACCES;
 105        if (S_ISDIR(inode->i_mode))
 106                goto dput_and_out;
 107
 108        error = permission(inode,MAY_WRITE);
 109        if (error)
 110                goto dput_and_out;
 111
 112        error = -EROFS;
 113        if (IS_RDONLY(inode))
 114                goto dput_and_out;
 115
 116        error = -EPERM;
 117        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 118                goto dput_and_out;
 119
 120        error = get_write_access(inode);
 121        if (error)
 122                goto dput_and_out;
 123
 124        error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, NULL,
 125                                  length < inode->i_size ? length : inode->i_size,
 126                                  abs(inode->i_size - length));
 127        if (!error) {
 128                DQUOT_INIT(inode);
 129                error = do_truncate(dentry, length);
 130        }
 131        put_write_access(inode);
 132dput_and_out:
 133        dput(dentry);
 134out:
 135        unlock_kernel();
 136        return error;
 137}
 138
 139asmlinkage int sys_ftruncate(unsigned int fd, unsigned long length)
 140{
 141        struct inode * inode;
 142        struct dentry *dentry;
 143        struct file * file;
 144        int error;
 145
 146        lock_kernel();
 147        error = -EBADF;
 148        file = fget(fd);
 149        if (!file)
 150                goto out;
 151        error = -ENOENT;
 152        if (!(dentry = file->f_dentry))
 153                goto out_putf;
 154        if (!(inode = dentry->d_inode))
 155                goto out_putf;
 156        error = -EACCES;
 157        if (S_ISDIR(inode->i_mode) || !(file->f_mode & FMODE_WRITE))
 158                goto out_putf;
 159        error = -EPERM;
 160        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 161                goto out_putf;
 162        error = locks_verify_area(FLOCK_VERIFY_WRITE, inode, file,
 163                                  length<inode->i_size ? length : inode->i_size,
 164                                  abs(inode->i_size - length));
 165        if (!error)
 166                error = do_truncate(dentry, length);
 167out_putf:
 168        fput(file);
 169out:
 170        unlock_kernel();
 171        return error;
 172}
 173
 174#ifndef __alpha__
 175
 176/*
 177 * sys_utime() can be implemented in user-level using sys_utimes().
 178 * Is this for backwards compatibility?  If so, why not move it
 179 * into the appropriate arch directory (for those architectures that
 180 * need it).
 181 */
 182
 183/* If times==NULL, set access and modification to current time,
 184 * must be owner or have write permission.
 185 * Else, update from *times, must be owner or super user.
 186 */
 187asmlinkage int sys_utime(char * filename, struct utimbuf * times)
 188{
 189        int error;
 190        struct dentry * dentry;
 191        struct inode * inode;
 192        struct iattr newattrs;
 193
 194        lock_kernel();
 195        dentry = namei(filename);
 196
 197        error = PTR_ERR(dentry);
 198        if (IS_ERR(dentry))
 199                goto out;
 200        inode = dentry->d_inode;
 201
 202        error = -EROFS;
 203        if (IS_RDONLY(inode))
 204                goto dput_and_out;
 205
 206        /* Don't worry, the checks are done in inode_change_ok() */
 207        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 208        if (times) {
 209                error = get_user(newattrs.ia_atime, &times->actime);
 210                if (!error) 
 211                        error = get_user(newattrs.ia_mtime, &times->modtime);
 212                if (error)
 213                        goto dput_and_out;
 214
 215                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 216        } else {
 217                if (current->fsuid != inode->i_uid &&
 218                    (error = permission(inode,MAY_WRITE)) != 0)
 219                        goto dput_and_out;
 220        }
 221        error = notify_change(dentry, &newattrs);
 222dput_and_out:
 223        dput(dentry);
 224out:
 225        unlock_kernel();
 226        return error;
 227}
 228
 229#endif
 230
 231/* If times==NULL, set access and modification to current time,
 232 * must be owner or have write permission.
 233 * Else, update from *times, must be owner or super user.
 234 */
 235asmlinkage int sys_utimes(char * filename, struct timeval * utimes)
 236{
 237        int error;
 238        struct dentry * dentry;
 239        struct inode * inode;
 240        struct iattr newattrs;
 241
 242        lock_kernel();
 243        dentry = namei(filename);
 244
 245        error = PTR_ERR(dentry);
 246        if (IS_ERR(dentry))
 247                goto out;
 248        inode = dentry->d_inode;
 249
 250        error = -EROFS;
 251        if (IS_RDONLY(inode))
 252                goto dput_and_out;
 253
 254        /* Don't worry, the checks are done in inode_change_ok() */
 255        newattrs.ia_valid = ATTR_CTIME | ATTR_MTIME | ATTR_ATIME;
 256        if (utimes) {
 257                struct timeval times[2];
 258                error = -EFAULT;
 259                if (copy_from_user(&times, utimes, sizeof(times)))
 260                        goto dput_and_out;
 261                newattrs.ia_atime = times[0].tv_sec;
 262                newattrs.ia_mtime = times[1].tv_sec;
 263                newattrs.ia_valid |= ATTR_ATIME_SET | ATTR_MTIME_SET;
 264        } else {
 265                if ((error = permission(inode,MAY_WRITE)) != 0)
 266                        goto dput_and_out;
 267        }
 268        error = notify_change(dentry, &newattrs);
 269dput_and_out:
 270        dput(dentry);
 271out:
 272        unlock_kernel();
 273        return error;
 274}
 275
 276/*
 277 * access() needs to use the real uid/gid, not the effective uid/gid.
 278 * We do this by temporarily clearing all FS-related capabilities and
 279 * switching the fsuid/fsgid around to the real ones.
 280 */
 281asmlinkage int sys_access(const char * filename, int mode)
 282{
 283        struct dentry * dentry;
 284        int old_fsuid, old_fsgid;
 285        kernel_cap_t old_cap;
 286        int res = -EINVAL;
 287
 288        lock_kernel();
 289        if (mode != (mode & S_IRWXO))   /* where's F_OK, X_OK, W_OK, R_OK? */
 290                goto out;
 291        old_fsuid = current->fsuid;
 292        old_fsgid = current->fsgid;
 293        old_cap = current->cap_effective;
 294
 295        current->fsuid = current->uid;
 296        current->fsgid = current->gid;
 297
 298        /* Clear the capabilities if we switch to a non-root user */
 299        if (current->uid)
 300                cap_clear(current->cap_effective);
 301        else
 302                current->cap_effective = current->cap_permitted;
 303                
 304        dentry = namei(filename);
 305        res = PTR_ERR(dentry);
 306        if (!IS_ERR(dentry)) {
 307                res = permission(dentry->d_inode, mode);
 308
 309                /* SUSv2 says to return EROFS for open() and access()
 310                   for files on a read-only filesystem, when writing
 311                   is requested.  Clearly, we want to be able to run
 312                   a system from read-only media, so should not
 313                   interpret this to mean that open("/dev/tty") should
 314                   fail when the device node lives on a CDROM.
 315                   In other words, no additional check is needed here. */
 316
 317                dput(dentry);
 318        }
 319
 320        current->fsuid = old_fsuid;
 321        current->fsgid = old_fsgid;
 322        current->cap_effective = old_cap;
 323out:
 324        unlock_kernel();
 325        return res;
 326}
 327
 328asmlinkage int sys_chdir(const char * filename)
 329{
 330        int error;
 331        struct inode *inode;
 332        struct dentry *dentry, *tmp;
 333
 334        lock_kernel();
 335        
 336        dentry = namei(filename);
 337        error = PTR_ERR(dentry);
 338        if (IS_ERR(dentry))
 339                goto out;
 340
 341        inode = dentry->d_inode;
 342
 343        error = -ENOTDIR;
 344        if (!S_ISDIR(inode->i_mode))
 345                goto dput_and_out;
 346
 347        error = permission(inode,MAY_EXEC);
 348        if (error)
 349                goto dput_and_out;
 350
 351        /* exchange dentries */
 352        tmp = current->fs->pwd;
 353        current->fs->pwd = dentry;
 354        dentry = tmp;
 355
 356dput_and_out:
 357        dput(dentry);
 358out:
 359        unlock_kernel();
 360        return error;
 361}
 362
 363asmlinkage int sys_fchdir(unsigned int fd)
 364{
 365        struct file *file;
 366        struct dentry *dentry;
 367        struct inode *inode;
 368        int error;
 369
 370        lock_kernel();
 371
 372        error = -EBADF;
 373        file = fget(fd);
 374        if (!file)
 375                goto out;
 376
 377        error = -ENOENT;
 378        if (!(dentry = file->f_dentry))
 379                goto out_putf;
 380        if (!(inode = dentry->d_inode))
 381                goto out_putf;
 382
 383        error = -ENOTDIR;
 384        if (!S_ISDIR(inode->i_mode))
 385                goto out_putf;
 386
 387        error = permission(inode, MAY_EXEC);
 388        if (!error) {
 389                struct dentry *tmp = current->fs->pwd;
 390                current->fs->pwd = dget(dentry);
 391                dput(tmp);
 392        }
 393out_putf:
 394        fput(file);
 395out:
 396        unlock_kernel();
 397        return error;
 398}
 399
 400asmlinkage int sys_chroot(const char * filename)
 401{
 402        int error;
 403        struct inode *inode;
 404        struct dentry *dentry, *tmp;
 405
 406        lock_kernel();
 407        
 408        dentry = namei(filename);
 409        error = PTR_ERR(dentry);
 410        if (IS_ERR(dentry))
 411                goto out;
 412
 413        inode = dentry->d_inode;
 414
 415        error = -ENOTDIR;
 416        if (!S_ISDIR(inode->i_mode))
 417                goto dput_and_out;
 418
 419        error = permission(inode,MAY_EXEC);
 420        if (error)
 421                goto dput_and_out;
 422
 423        error = -EPERM;
 424        if (!capable(CAP_SYS_CHROOT))
 425                goto dput_and_out;
 426
 427        /* exchange dentries */
 428        tmp = current->fs->root;
 429        current->fs->root = dentry;
 430        dentry = tmp;
 431        error = 0;
 432
 433dput_and_out:
 434        dput(dentry);
 435out:
 436        unlock_kernel();
 437        return error;
 438}
 439
 440asmlinkage int sys_fchmod(unsigned int fd, mode_t mode)
 441{
 442        struct inode * inode;
 443        struct dentry * dentry;
 444        struct file * file;
 445        int err = -EBADF;
 446        struct iattr newattrs;
 447
 448        lock_kernel();
 449        file = fget(fd);
 450        if (!file)
 451                goto out;
 452
 453        err = -ENOENT;
 454        if (!(dentry = file->f_dentry))
 455                goto out_putf;
 456        if (!(inode = dentry->d_inode))
 457                goto out_putf;
 458
 459        err = -EROFS;
 460        if (IS_RDONLY(inode))
 461                goto out_putf;
 462        err = -EPERM;
 463        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 464                goto out_putf;
 465        if (mode == (mode_t) -1)
 466                mode = inode->i_mode;
 467        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 468        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 469        err = notify_change(dentry, &newattrs);
 470
 471out_putf:
 472        fput(file);
 473out:
 474        unlock_kernel();
 475        return err;
 476}
 477
 478asmlinkage int sys_chmod(const char * filename, mode_t mode)
 479{
 480        struct dentry * dentry;
 481        struct inode * inode;
 482        int error;
 483        struct iattr newattrs;
 484
 485        lock_kernel();
 486        dentry = namei(filename);
 487
 488        error = PTR_ERR(dentry);
 489        if (IS_ERR(dentry))
 490                goto out;
 491        inode = dentry->d_inode;
 492
 493        error = -EROFS;
 494        if (IS_RDONLY(inode))
 495                goto dput_and_out;
 496
 497        error = -EPERM;
 498        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 499                goto dput_and_out;
 500
 501        if (mode == (mode_t) -1)
 502                mode = inode->i_mode;
 503        newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
 504        newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
 505        error = notify_change(dentry, &newattrs);
 506
 507dput_and_out:
 508        dput(dentry);
 509out:
 510        unlock_kernel();
 511        return error;
 512}
 513
 514static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
 515{
 516        struct inode * inode;
 517        int error;
 518        struct iattr newattrs;
 519
 520        error = -ENOENT;
 521        if (!(inode = dentry->d_inode)) {
 522                printk("chown_common: NULL inode\n");
 523                goto out;
 524        }
 525        error = -EROFS;
 526        if (IS_RDONLY(inode))
 527                goto out;
 528        error = -EPERM;
 529        if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
 530                goto out;
 531        if (user == (uid_t) -1)
 532                user = inode->i_uid;
 533        if (group == (gid_t) -1)
 534                group = inode->i_gid;
 535        newattrs.ia_mode = inode->i_mode;
 536        newattrs.ia_uid = user;
 537        newattrs.ia_gid = group;
 538        newattrs.ia_valid =  ATTR_UID | ATTR_GID | ATTR_CTIME;
 539        /*
 540         * If the user or group of a non-directory has been changed by a
 541         * non-root user, remove the setuid bit.
 542         * 19981026     David C Niemi <niemi@tux.org>
 543         *
 544         * Changed this to apply to all users, including root, to avoid
 545         * some races. This is the behavior we had in 2.0. The check for
 546         * non-root was definitely wrong for 2.2 anyway, as it should
 547         * have been using CAP_FSETID rather than fsuid -- 19990830 SD.
 548         */
 549        if ((inode->i_mode & S_ISUID) == S_ISUID &&
 550                !S_ISDIR(inode->i_mode))
 551        {
 552                newattrs.ia_mode &= ~S_ISUID;
 553                newattrs.ia_valid |= ATTR_MODE;
 554        }
 555        /*
 556         * Likewise, if the user or group of a non-directory has been changed
 557         * by a non-root user, remove the setgid bit UNLESS there is no group
 558         * execute bit (this would be a file marked for mandatory locking).
 559         * 19981026     David C Niemi <niemi@tux.org>
 560         *
 561         * Removed the fsuid check (see the comment above) -- 19990830 SD.
 562         */
 563        if (((inode->i_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) 
 564                && !S_ISDIR(inode->i_mode))
 565        {
 566                newattrs.ia_mode &= ~S_ISGID;
 567                newattrs.ia_valid |= ATTR_MODE;
 568        }
 569        error = DQUOT_TRANSFER(dentry, &newattrs);
 570out:
 571        return error;
 572}
 573
 574asmlinkage int sys_chown(const char * filename, uid_t user, gid_t group)
 575{
 576        struct dentry * dentry;
 577        int error;
 578
 579        lock_kernel();
 580        dentry = namei(filename);
 581
 582        error = PTR_ERR(dentry);
 583        if (!IS_ERR(dentry)) {
 584                error = chown_common(dentry, user, group);
 585                dput(dentry);
 586        }
 587        unlock_kernel();
 588        return error;
 589}
 590
 591asmlinkage int sys_lchown(const char * filename, uid_t user, gid_t group)
 592{
 593        struct dentry * dentry;
 594        int error;
 595
 596        lock_kernel();
 597        dentry = lnamei(filename);
 598
 599        error = PTR_ERR(dentry);
 600        if (!IS_ERR(dentry)) {
 601                error = chown_common(dentry, user, group);
 602                dput(dentry);
 603        }
 604        unlock_kernel();
 605        return error;
 606}
 607
 608
 609asmlinkage int sys_fchown(unsigned int fd, uid_t user, gid_t group)
 610{
 611        struct dentry * dentry;
 612        struct file * file;
 613        int error = -EBADF;
 614
 615        lock_kernel();
 616        file = fget(fd);
 617        if (!file)
 618                goto out;
 619        error = -ENOENT;
 620        if ((dentry = file->f_dentry) != NULL)
 621                error = chown_common(dentry, user, group);
 622        fput(file);
 623
 624out:
 625        unlock_kernel();
 626        return error;
 627}
 628
 629/*
 630 * Note that while the flag value (low two bits) for sys_open means:
 631 *      00 - read-only
 632 *      01 - write-only
 633 *      10 - read-write
 634 *      11 - special
 635 * it is changed into
 636 *      00 - no permissions needed
 637 *      01 - read-permission
 638 *      10 - write-permission
 639 *      11 - read-write
 640 * for the internal routines (ie open_namei()/follow_link() etc). 00 is
 641 * used by symlinks.
 642 */
 643struct file *filp_open(const char * filename, int flags, int mode)
 644{
 645        struct inode * inode;
 646        struct dentry * dentry;
 647        struct file * f;
 648        int flag,error;
 649
 650        error = -ENFILE;
 651        f = get_empty_filp();
 652        if (!f)
 653                goto out;
 654        f->f_flags = flag = flags;
 655        f->f_mode = (flag+1) & O_ACCMODE;
 656        if (f->f_mode)
 657                flag++;
 658        if (flag & O_TRUNC)
 659                flag |= 2;
 660        dentry = open_namei(filename,flag,mode);
 661        error = PTR_ERR(dentry);
 662        if (IS_ERR(dentry))
 663                goto cleanup_file;
 664        inode = dentry->d_inode;
 665        if (f->f_mode & FMODE_WRITE) {
 666                error = get_write_access(inode);
 667                if (error)
 668                        goto cleanup_dentry;
 669        }
 670
 671        f->f_dentry = dentry;
 672        f->f_pos = 0;
 673        f->f_reada = 0;
 674        f->f_op = NULL;
 675        if (inode->i_op)
 676                f->f_op = inode->i_op->default_file_ops;
 677        if (f->f_op && f->f_op->open) {
 678                error = f->f_op->open(inode,f);
 679                if (error)
 680                        goto cleanup_all;
 681        }
 682        f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
 683
 684        return f;
 685
 686cleanup_all:
 687        if (f->f_mode & FMODE_WRITE)
 688                put_write_access(inode);
 689cleanup_dentry:
 690        f->f_dentry = NULL;
 691        dput(dentry);
 692cleanup_file:
 693        put_filp(f);
 694out:
 695        return ERR_PTR(error);
 696}
 697
 698/*
 699 * Find an empty file descriptor entry, and mark it busy.
 700 */
 701int get_unused_fd(void)
 702{
 703        struct files_struct * files = current->files;
 704        int fd, error;
 705        
 706repeat:
 707        error = -EMFILE;
 708
 709        fd = find_next_zero_bit(files->open_fds, 
 710                                current->files->max_fdset, 
 711                                files->next_fd);
 712        /*
 713         * N.B. For clone tasks sharing a files structure, this test
 714         * will limit the total number of files that can be opened.
 715         */
 716        if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur)
 717                goto out;
 718
 719        /* Do we need to expand the fdset array? */
 720        if (fd >= current->files->max_fdset) {
 721                error = expand_fdset(files, fd + 1);
 722                if (!error)
 723                        goto repeat;
 724                goto out;
 725        }
 726        
 727        /* 
 728         * Check whether we need to expand the fd array.
 729         */
 730        if (fd >= files->max_fds) {
 731                error = expand_fd_array(files, fd + 1);
 732                if (!error)
 733                        goto repeat;
 734                goto out;
 735        }
 736
 737        FD_SET(fd, files->open_fds);
 738        FD_CLR(fd, files->close_on_exec);
 739        files->next_fd = fd + 1;
 740#if 1
 741        /* Sanity check */
 742        if (files->fd[fd] != NULL) {
 743                printk("get_unused_fd: slot %d not NULL!\n", fd);
 744                files->fd[fd] = NULL;
 745        }
 746#endif
 747        error = fd;
 748
 749out:
 750#ifdef FDSET_DEBUG      
 751        if (error < 0)
 752                printk (KERN_ERR __FUNCTION__ ": return %d\n", error);
 753#endif
 754        return error;
 755}
 756
 757asmlinkage int sys_open(const char * filename, int flags, int mode)
 758{
 759        char * tmp;
 760        int fd, error;
 761
 762        tmp = getname(filename);
 763        fd = PTR_ERR(tmp);
 764        if (!IS_ERR(tmp)) {
 765                lock_kernel();
 766                fd = get_unused_fd();
 767                if (fd >= 0) {
 768                        struct file * f = filp_open(tmp, flags, mode);
 769                        error = PTR_ERR(f);
 770                        if (IS_ERR(f))
 771                                goto out_error;
 772                        fd_install(fd, f);
 773                }
 774out:
 775                unlock_kernel();
 776                putname(tmp);
 777        }
 778        return fd;
 779
 780out_error:
 781        put_unused_fd(fd);
 782        fd = error;
 783        goto out;
 784}
 785
 786#ifndef __alpha__
 787
 788/*
 789 * For backward compatibility?  Maybe this should be moved
 790 * into arch/i386 instead?
 791 */
 792asmlinkage int sys_creat(const char * pathname, int mode)
 793{
 794        return sys_open(pathname, O_CREAT | O_WRONLY | O_TRUNC, mode);
 795}
 796
 797#endif
 798
 799/*
 800 * Called when retiring the last use of a file pointer.
 801 */
 802void __fput(struct file *filp)
 803{
 804        struct dentry * dentry = filp->f_dentry;
 805        struct inode * inode = dentry->d_inode;
 806
 807        if (filp->f_op && filp->f_op->release)
 808                filp->f_op->release(inode, filp);
 809        filp->f_dentry = NULL;
 810        if (filp->f_mode & FMODE_WRITE)
 811                put_write_access(inode);
 812        dput(dentry);
 813}
 814
 815/*
 816 * "id" is the POSIX thread ID. We use the
 817 * files pointer for this..
 818 */
 819int filp_close(struct file *filp, fl_owner_t id)
 820{
 821        int retval;
 822        struct dentry *dentry = filp->f_dentry;
 823
 824        if (filp->f_count == 0) {
 825                printk("VFS: Close: file count is 0\n");
 826                return 0;
 827        }
 828        retval = 0;
 829        if (filp->f_op && filp->f_op->flush)
 830                retval = filp->f_op->flush(filp);
 831        if (dentry->d_inode)
 832                locks_remove_posix(filp, id);
 833        fput(filp);
 834        return retval;
 835}
 836
 837/*
 838 * Careful here! We test whether the file pointer is NULL before
 839 * releasing the fd. This ensures that one clone task can't release
 840 * an fd while another clone is opening it.
 841 */
 842asmlinkage int sys_close(unsigned int fd)
 843{
 844        int error;
 845        struct file * filp;
 846
 847        lock_kernel();
 848        error = -EBADF;
 849        filp = fcheck(fd);
 850        if (filp) {
 851                struct files_struct * files = current->files;
 852                files->fd[fd] = NULL;
 853                put_unused_fd(fd);
 854                FD_CLR(fd, files->close_on_exec);
 855                error = filp_close(filp, files);
 856        }
 857        unlock_kernel();
 858        return error;
 859}
 860
 861/*
 862 * This routine simulates a hangup on the tty, to arrange that users
 863 * are given clean terminals at login time.
 864 */
 865asmlinkage int sys_vhangup(void)
 866{
 867        int ret = -EPERM;
 868
 869        lock_kernel();
 870        if (!capable(CAP_SYS_TTY_CONFIG))
 871                goto out;
 872        /* If there is a controlling tty, hang it up */
 873        if (current->tty)
 874                tty_vhangup(current->tty);
 875        ret = 0;
 876out:
 877        unlock_kernel();
 878        return ret;
 879}
 880
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.