diff options
Diffstat (limited to 'fs/hostfs/hostfs_user.c')
-rw-r--r-- | fs/hostfs/hostfs_user.c | 108 |
1 files changed, 68 insertions, 40 deletions
diff --git a/fs/hostfs/hostfs_user.c b/fs/hostfs/hostfs_user.c index 1ed5ea389f15..0acf562a5f06 100644 --- a/fs/hostfs/hostfs_user.c +++ b/fs/hostfs/hostfs_user.c | |||
@@ -21,12 +21,16 @@ int stat_file(const char *path, unsigned long long *inode_out, int *mode_out, | |||
21 | int *nlink_out, int *uid_out, int *gid_out, | 21 | int *nlink_out, int *uid_out, int *gid_out, |
22 | unsigned long long *size_out, struct timespec *atime_out, | 22 | unsigned long long *size_out, struct timespec *atime_out, |
23 | struct timespec *mtime_out, struct timespec *ctime_out, | 23 | struct timespec *mtime_out, struct timespec *ctime_out, |
24 | int *blksize_out, unsigned long long *blocks_out) | 24 | int *blksize_out, unsigned long long *blocks_out, int fd) |
25 | { | 25 | { |
26 | struct stat64 buf; | 26 | struct stat64 buf; |
27 | 27 | ||
28 | if(lstat64(path, &buf) < 0) | 28 | if(fd >= 0) { |
29 | if (fstat64(fd, &buf) < 0) | ||
30 | return(-errno); | ||
31 | } else if(lstat64(path, &buf) < 0) { | ||
29 | return(-errno); | 32 | return(-errno); |
33 | } | ||
30 | 34 | ||
31 | if(inode_out != NULL) *inode_out = buf.st_ino; | 35 | if(inode_out != NULL) *inode_out = buf.st_ino; |
32 | if(mode_out != NULL) *mode_out = buf.st_mode; | 36 | if(mode_out != NULL) *mode_out = buf.st_mode; |
@@ -202,58 +206,82 @@ int file_create(char *name, int ur, int uw, int ux, int gr, | |||
202 | return(fd); | 206 | return(fd); |
203 | } | 207 | } |
204 | 208 | ||
205 | int set_attr(const char *file, struct hostfs_iattr *attrs) | 209 | int set_attr(const char *file, struct hostfs_iattr *attrs, int fd) |
206 | { | 210 | { |
207 | struct utimbuf buf; | 211 | struct timeval times[2]; |
212 | struct timespec atime_ts, mtime_ts; | ||
208 | int err, ma; | 213 | int err, ma; |
209 | 214 | ||
210 | if(attrs->ia_valid & HOSTFS_ATTR_MODE){ | 215 | if (attrs->ia_valid & HOSTFS_ATTR_MODE) { |
211 | if(chmod(file, attrs->ia_mode) != 0) return(-errno); | 216 | if (fd >= 0) { |
212 | } | 217 | if (fchmod(fd, attrs->ia_mode) != 0) |
213 | if(attrs->ia_valid & HOSTFS_ATTR_UID){ | 218 | return (-errno); |
214 | if(chown(file, attrs->ia_uid, -1)) return(-errno); | 219 | } else if (chmod(file, attrs->ia_mode) != 0) { |
220 | return (-errno); | ||
221 | } | ||
215 | } | 222 | } |
216 | if(attrs->ia_valid & HOSTFS_ATTR_GID){ | 223 | if (attrs->ia_valid & HOSTFS_ATTR_UID) { |
217 | if(chown(file, -1, attrs->ia_gid)) return(-errno); | 224 | if (fd >= 0) { |
225 | if (fchown(fd, attrs->ia_uid, -1)) | ||
226 | return (-errno); | ||
227 | } else if(chown(file, attrs->ia_uid, -1)) { | ||
228 | return (-errno); | ||
229 | } | ||
218 | } | 230 | } |
219 | if(attrs->ia_valid & HOSTFS_ATTR_SIZE){ | 231 | if (attrs->ia_valid & HOSTFS_ATTR_GID) { |
220 | if(truncate(file, attrs->ia_size)) return(-errno); | 232 | if (fd >= 0) { |
233 | if (fchown(fd, -1, attrs->ia_gid)) | ||
234 | return (-errno); | ||
235 | } else if (chown(file, -1, attrs->ia_gid)) { | ||
236 | return (-errno); | ||
237 | } | ||
221 | } | 238 | } |
222 | ma = HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET; | 239 | if (attrs->ia_valid & HOSTFS_ATTR_SIZE) { |
223 | if((attrs->ia_valid & ma) == ma){ | 240 | if (fd >= 0) { |
224 | buf.actime = attrs->ia_atime.tv_sec; | 241 | if (ftruncate(fd, attrs->ia_size)) |
225 | buf.modtime = attrs->ia_mtime.tv_sec; | 242 | return (-errno); |
226 | if(utime(file, &buf) != 0) return(-errno); | 243 | } else if (truncate(file, attrs->ia_size)) { |
244 | return (-errno); | ||
245 | } | ||
227 | } | 246 | } |
228 | else { | 247 | |
229 | struct timespec ts; | 248 | /* Update accessed and/or modified time, in two parts: first set |
230 | 249 | * times according to the changes to perform, and then call futimes() | |
231 | if(attrs->ia_valid & HOSTFS_ATTR_ATIME_SET){ | 250 | * or utimes() to apply them. */ |
232 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, | 251 | ma = (HOSTFS_ATTR_ATIME_SET | HOSTFS_ATTR_MTIME_SET); |
233 | NULL, NULL, &ts, NULL, NULL, NULL); | 252 | if (attrs->ia_valid & ma) { |
234 | if(err != 0) | 253 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, |
235 | return(err); | 254 | &atime_ts, &mtime_ts, NULL, NULL, NULL, fd); |
236 | buf.actime = attrs->ia_atime.tv_sec; | 255 | if (err != 0) |
237 | buf.modtime = ts.tv_sec; | 256 | return err; |
238 | if(utime(file, &buf) != 0) | 257 | |
239 | return(-errno); | 258 | times[0].tv_sec = atime_ts.tv_sec; |
259 | times[0].tv_usec = atime_ts.tv_nsec * 1000; | ||
260 | times[1].tv_sec = mtime_ts.tv_sec; | ||
261 | times[1].tv_usec = mtime_ts.tv_nsec * 1000; | ||
262 | |||
263 | if (attrs->ia_valid & HOSTFS_ATTR_ATIME_SET) { | ||
264 | times[0].tv_sec = attrs->ia_atime.tv_sec; | ||
265 | times[0].tv_usec = attrs->ia_atime.tv_nsec * 1000; | ||
240 | } | 266 | } |
241 | if(attrs->ia_valid & HOSTFS_ATTR_MTIME_SET){ | 267 | if (attrs->ia_valid & HOSTFS_ATTR_MTIME_SET) { |
242 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, | 268 | times[1].tv_sec = attrs->ia_mtime.tv_sec; |
243 | NULL, &ts, NULL, NULL, NULL, NULL); | 269 | times[1].tv_usec = attrs->ia_mtime.tv_nsec * 1000; |
244 | if(err != 0) | 270 | } |
245 | return(err); | 271 | |
246 | buf.actime = ts.tv_sec; | 272 | if (fd >= 0) { |
247 | buf.modtime = attrs->ia_mtime.tv_sec; | 273 | if (futimes(fd, times) != 0) |
248 | if(utime(file, &buf) != 0) | 274 | return (-errno); |
249 | return(-errno); | 275 | } else if (utimes(file, times) != 0) { |
276 | return (-errno); | ||
250 | } | 277 | } |
251 | } | 278 | } |
279 | |||
252 | if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; | 280 | if(attrs->ia_valid & HOSTFS_ATTR_CTIME) ; |
253 | if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ | 281 | if(attrs->ia_valid & (HOSTFS_ATTR_ATIME | HOSTFS_ATTR_MTIME)){ |
254 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, | 282 | err = stat_file(file, NULL, NULL, NULL, NULL, NULL, NULL, |
255 | &attrs->ia_atime, &attrs->ia_mtime, NULL, | 283 | &attrs->ia_atime, &attrs->ia_mtime, NULL, |
256 | NULL, NULL); | 284 | NULL, NULL, fd); |
257 | if(err != 0) return(err); | 285 | if(err != 0) return(err); |
258 | } | 286 | } |
259 | return(0); | 287 | return(0); |