[O_TMPFILE] it's still short a few helpers, but infrastructure should be OK now...
[pandora-kernel.git] / fs / open.c
index 8c74100..fca72c4 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -840,11 +840,15 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        if (flags & __O_SYNC)
                flags |= O_DSYNC;
 
-       /*
-        * If we have O_PATH in the open flag. Then we
-        * cannot have anything other than the below set of flags
-        */
-       if (flags & O_PATH) {
+       if (flags & O_TMPFILE) {
+               if (!(flags & O_CREAT))
+                       return -EINVAL;
+               acc_mode = MAY_OPEN | ACC_MODE(flags);
+       } else if (flags & O_PATH) {
+               /*
+                * If we have O_PATH in the open flag. Then we
+                * cannot have anything other than the below set of flags
+                */
                flags &= O_DIRECTORY | O_NOFOLLOW | O_PATH;
                acc_mode = 0;
        } else {
@@ -876,7 +880,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
                lookup_flags |= LOOKUP_DIRECTORY;
        if (!(flags & O_NOFOLLOW))
                lookup_flags |= LOOKUP_FOLLOW;
-       return lookup_flags;
+       op->lookup_flags = lookup_flags;
+       return 0;
 }
 
 /**
@@ -893,8 +898,8 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
 struct file *file_open_name(struct filename *name, int flags, umode_t mode)
 {
        struct open_flags op;
-       int lookup = build_open_flags(flags, mode, &op);
-       return do_filp_open(AT_FDCWD, name, &op, lookup);
+       int err = build_open_flags(flags, mode, &op);
+       return err ? ERR_PTR(err) : do_filp_open(AT_FDCWD, name, &op);
 }
 
 /**
@@ -919,37 +924,43 @@ struct file *file_open_root(struct dentry *dentry, struct vfsmount *mnt,
                            const char *filename, int flags)
 {
        struct open_flags op;
-       int lookup = build_open_flags(flags, 0, &op);
+       int err = build_open_flags(flags, 0, &op);
+       if (err)
+               return ERR_PTR(err);
        if (flags & O_CREAT)
                return ERR_PTR(-EINVAL);
        if (!filename && (flags & O_DIRECTORY))
                if (!dentry->d_inode->i_op->lookup)
                        return ERR_PTR(-ENOTDIR);
-       return do_file_open_root(dentry, mnt, filename, &op, lookup);
+       return do_file_open_root(dentry, mnt, filename, &op);
 }
 EXPORT_SYMBOL(file_open_root);
 
 long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
 {
        struct open_flags op;
-       int lookup = build_open_flags(flags, mode, &op);
-       struct filename *tmp = getname(filename);
-       int fd = PTR_ERR(tmp);
-
-       if (!IS_ERR(tmp)) {
-               fd = get_unused_fd_flags(flags);
-               if (fd >= 0) {
-                       struct file *f = do_filp_open(dfd, tmp, &op, lookup);
-                       if (IS_ERR(f)) {
-                               put_unused_fd(fd);
-                               fd = PTR_ERR(f);
-                       } else {
-                               fsnotify_open(f);
-                               fd_install(fd, f);
-                       }
+       int fd = build_open_flags(flags, mode, &op);
+       struct filename *tmp;
+
+       if (fd)
+               return fd;
+
+       tmp = getname(filename);
+       if (IS_ERR(tmp))
+               return PTR_ERR(tmp);
+
+       fd = get_unused_fd_flags(flags);
+       if (fd >= 0) {
+               struct file *f = do_filp_open(dfd, tmp, &op);
+               if (IS_ERR(f)) {
+                       put_unused_fd(fd);
+                       fd = PTR_ERR(f);
+               } else {
+                       fsnotify_open(f);
+                       fd_install(fd, f);
                }
-               putname(tmp);
        }
+       putname(tmp);
        return fd;
 }