Commit e9b76fedc61235da80b6b7f81dfd67ec224dfb49

Authored by Miklos Szeredi
Committed by Al Viro
1 parent 9767d74957

[patch 2/4] vfs: utimes cleanup

Untange the mess that is do_utimes().  Add kerneldoc comment to
do_utimes().

CC: Ulrich Drepper <drepper@redhat.com>
CC: Michael Kerrisk <mtk.manpages@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 1 changed file with 65 additions and 49 deletions Side-by-side Diff

... ... @@ -48,55 +48,16 @@
48 48 return nsec >= 0 && nsec <= 999999999;
49 49 }
50 50  
51   -/* If times==NULL, set access and modification to current time,
52   - * must be owner or have write permission.
53   - * Else, update from *times, must be owner or super user.
54   - */
55   -long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags)
  51 +static int utimes_common(struct path *path, struct timespec *times)
56 52 {
57 53 int error;
58   - struct nameidata nd;
59   - struct dentry *dentry;
60   - struct inode *inode;
61 54 struct iattr newattrs;
62   - struct file *f = NULL;
63   - struct vfsmount *mnt;
  55 + struct inode *inode = path->dentry->d_inode;
64 56  
65   - error = -EINVAL;
66   - if (times && (!nsec_valid(times[0].tv_nsec) ||
67   - !nsec_valid(times[1].tv_nsec))) {
  57 + error = mnt_want_write(path->mnt);
  58 + if (error)
68 59 goto out;
69   - }
70 60  
71   - if (flags & ~AT_SYMLINK_NOFOLLOW)
72   - goto out;
73   -
74   - if (filename == NULL && dfd != AT_FDCWD) {
75   - error = -EINVAL;
76   - if (flags & AT_SYMLINK_NOFOLLOW)
77   - goto out;
78   -
79   - error = -EBADF;
80   - f = fget(dfd);
81   - if (!f)
82   - goto out;
83   - dentry = f->f_path.dentry;
84   - mnt = f->f_path.mnt;
85   - } else {
86   - error = __user_walk_fd(dfd, filename, (flags & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW, &nd);
87   - if (error)
88   - goto out;
89   -
90   - dentry = nd.path.dentry;
91   - mnt = nd.path.mnt;
92   - }
93   -
94   - inode = dentry->d_inode;
95   -
96   - error = mnt_want_write(mnt);
97   - if (error)
98   - goto dput_and_out;
99   -
100 61 if (times && times[0].tv_nsec == UTIME_NOW &&
101 62 times[1].tv_nsec == UTIME_NOW)
102 63 times = NULL;
103 64  
104 65  
105 66  
... ... @@ -145,15 +106,70 @@
145 106 }
146 107 }
147 108 mutex_lock(&inode->i_mutex);
148   - error = notify_change(dentry, &newattrs);
  109 + error = notify_change(path->dentry, &newattrs);
149 110 mutex_unlock(&inode->i_mutex);
  111 +
150 112 mnt_drop_write_and_out:
151   - mnt_drop_write(mnt);
152   -dput_and_out:
153   - if (f)
154   - fput(f);
155   - else
  113 + mnt_drop_write(path->mnt);
  114 +out:
  115 + return error;
  116 +}
  117 +
  118 +/*
  119 + * do_utimes - change times on filename or file descriptor
  120 + * @dfd: open file descriptor, -1 or AT_FDCWD
  121 + * @filename: path name or NULL
  122 + * @times: new times or NULL
  123 + * @flags: zero or more flags (only AT_SYMLINK_NOFOLLOW for the moment)
  124 + *
  125 + * If filename is NULL and dfd refers to an open file, then operate on
  126 + * the file. Otherwise look up filename, possibly using dfd as a
  127 + * starting point.
  128 + *
  129 + * If times==NULL, set access and modification to current time,
  130 + * must be owner or have write permission.
  131 + * Else, update from *times, must be owner or super user.
  132 + */
  133 +long do_utimes(int dfd, char __user *filename, struct timespec *times, int flags)
  134 +{
  135 + int error = -EINVAL;
  136 +
  137 + if (times && (!nsec_valid(times[0].tv_nsec) ||
  138 + !nsec_valid(times[1].tv_nsec))) {
  139 + goto out;
  140 + }
  141 +
  142 + if (flags & ~AT_SYMLINK_NOFOLLOW)
  143 + goto out;
  144 +
  145 + if (filename == NULL && dfd != AT_FDCWD) {
  146 + struct file *file;
  147 +
  148 + if (flags & AT_SYMLINK_NOFOLLOW)
  149 + goto out;
  150 +
  151 + file = fget(dfd);
  152 + error = -EBADF;
  153 + if (!file)
  154 + goto out;
  155 +
  156 + error = utimes_common(&file->f_path, times);
  157 + fput(file);
  158 + } else {
  159 + struct nameidata nd;
  160 + int lookup_flags = 0;
  161 +
  162 + if (!(flags & AT_SYMLINK_NOFOLLOW))
  163 + lookup_flags |= LOOKUP_FOLLOW;
  164 +
  165 + error = __user_walk_fd(dfd, filename, lookup_flags, &nd);
  166 + if (error)
  167 + goto out;
  168 +
  169 + error = utimes_common(&nd.path, times);
156 170 path_put(&nd.path);
  171 + }
  172 +
157 173 out:
158 174 return error;
159 175 }