diff options
Diffstat (limited to 'fs/open.c')
| -rw-r--r-- | fs/open.c | 63 |
1 files changed, 37 insertions, 26 deletions
| @@ -840,11 +840,15 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 840 | if (flags & __O_SYNC) | 840 | if (flags & __O_SYNC) |
| 841 | flags |= O_DSYNC; | 841 | flags |= O_DSYNC; |
| 842 | 842 | ||
| 843 | /* | 843 | if (flags & O_TMPFILE) { |
| 844 | * If we have O_PATH in the open flag. Then we | 844 | if (!(flags & O_CREAT)) |
| 845 | * cannot have anything other than the below set of flags | 845 | return -EINVAL; |
| 846 | */ | 846 | acc_mode = MAY_OPEN | ACC_MODE(flags); |
| 847 | if (flags & O_PATH) { | 847 | } else if (flags & O_PATH) { |
| 848 | /* | ||
| 849 | * If we have O_PATH in the open flag. Then we | ||
| 850 | * cannot have anything other than the below set of flags | ||
| 851 | */ | ||
| 848 | flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; | 852 | flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH; |
| 849 | acc_mode = 0; | 853 | acc_mode = 0; |
| 850 | } else { | 854 | } else { |
| @@ -876,7 +880,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 876 | lookup_flags |= LOOKUP_DIRECTORY; | 880 | lookup_flags |= LOOKUP_DIRECTORY; |
| 877 | if (!(flags & O_NOFOLLOW)) | 881 | if (!(flags & O_NOFOLLOW)) |
| 878 | lookup_flags |= LOOKUP_FOLLOW; | 882 | lookup_flags |= LOOKUP_FOLLOW; |
| 879 | return lookup_flags; | 883 | op->lookup_flags = lookup_flags; |
| 884 | return 0; | ||
| 880 | } | 885 | } |
| 881 | 886 | ||
| 882 | /** | 887 | /** |
| @@ -893,8 +898,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o | |||
| 893 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) | 898 | struct file *file_open_name(struct filename *name, int flags, umode_t mode) |
| 894 | { | 899 | { |
| 895 | struct open_flags op; | 900 | struct open_flags op; |
| 896 | int lookup = build_open_flags(flags, mode, &op); | 901 | int err = build_open_flags(flags, mode, &op); |
| 897 | return do_filp_open(AT_FDCWD, name, &op, lookup); | 902 | return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op); |
| 898 | } | 903 | } |
| 899 | 904 | ||
| 900 | /** | 905 | /** |
| @@ -919,37 +924,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
| 919 | const char *filename, int flags) | 924 | const char *filename, int flags) |
| 920 | { | 925 | { |
| 921 | struct open_flags op; | 926 | struct open_flags op; |
| 922 | int lookup = build_open_flags(flags, 0, &op); | 927 | int err = build_open_flags(flags, 0, &op); |
| 928 | if (err) | ||
| 929 | return ERR_PTR(err); | ||
| 923 | if (flags & O_CREAT) | 930 | if (flags & O_CREAT) |
| 924 | return ERR_PTR(-EINVAL); | 931 | return ERR_PTR(-EINVAL); |
| 925 | if (!filename && (flags & O_DIRECTORY)) | 932 | if (!filename && (flags & O_DIRECTORY)) |
| 926 | if (!dentry->d_inode->i_op->lookup) | 933 | if (!dentry->d_inode->i_op->lookup) |
| 927 | return ERR_PTR(-ENOTDIR); | 934 | return ERR_PTR(-ENOTDIR); |
| 928 | return do_file_open_root(dentry, mnt, filename, &op, lookup); | 935 | return do_file_open_root(dentry, mnt, filename, &op); |
| 929 | } | 936 | } |
| 930 | EXPORT_SYMBOL(file_open_root); | 937 | EXPORT_SYMBOL(file_open_root); |
| 931 | 938 | ||
| 932 | long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) | 939 | long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode) |
| 933 | { | 940 | { |
| 934 | struct open_flags op; | 941 | struct open_flags op; |
| 935 | int lookup = build_open_flags(flags, mode, &op); | 942 | int fd = build_open_flags(flags, mode, &op); |
| 936 | struct filename *tmp = getname(filename); | 943 | struct filename *tmp; |
| 937 | int fd = PTR_ERR(tmp); | 944 | |
| 938 | 945 | if (fd) | |
| 939 | if (!IS_ERR(tmp)) { | 946 | return fd; |
| 940 | fd = get_unused_fd_flags(flags); | 947 | |
| 941 | if (fd >= 0) { | 948 | tmp = getname(filename); |
| 942 | struct file *f = do_filp_open(dfd, tmp, &op, lookup); | 949 | if (IS_ERR(tmp)) |
| 943 | if (IS_ERR(f)) { | 950 | return PTR_ERR(tmp); |
| 944 | put_unused_fd(fd); | 951 | |
| 945 | fd = PTR_ERR(f); | 952 | fd = get_unused_fd_flags(flags); |
| 946 | } else { | 953 | if (fd >= 0) { |
| 947 | fsnotify_open(f); | 954 | struct file *f = do_filp_open(dfd, tmp, &op); |
| 948 | fd_install(fd, f); | 955 | if (IS_ERR(f)) { |
| 949 | } | 956 | put_unused_fd(fd); |
| 957 | fd = PTR_ERR(f); | ||
| 958 | } else { | ||
| 959 | fsnotify_open(f); | ||
| 960 | fd_install(fd, f); | ||
| 950 | } | 961 | } |
| 951 | putname(tmp); | ||
| 952 | } | 962 | } |
| 963 | putname(tmp); | ||
| 953 | return fd; | 964 | return fd; |
| 954 | } | 965 | } |
| 955 | 966 | ||
