Commit e9b76fedc61235da80b6b7f81dfd67ec224dfb49
Committed by
Al Viro
1 parent
9767d74957
Exists in
master
and in
7 other branches
[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
fs/utimes.c
... | ... | @@ -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 | } |