diff options
-rw-r--r-- | fs/hostfs/hostfs.h | 4 | ||||
-rw-r--r-- | fs/hostfs/hostfs_kern.c | 6 | ||||
-rw-r--r-- | fs/hostfs/hostfs_user.c | 108 |
3 files changed, 74 insertions, 44 deletions
diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index 70543b17e4c7..d8850c701564 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h | |||
@@ -55,7 +55,7 @@ extern int stat_file(const char *path, unsigned long long *inode_out, | |||
55 | int *mode_out, int *nlink_out, int *uid_out, int *gid_out, | 55 | int *mode_out, int *nlink_out, int *uid_out, int *gid_out, |
56 | unsigned long long *size_out, struct timespec *atime_out, | 56 | unsigned long long *size_out, struct timespec *atime_out, |
57 | struct timespec *mtime_out, struct timespec *ctime_out, | 57 | struct timespec *mtime_out, struct timespec *ctime_out, |
58 | int *blksize_out, unsigned long long *blocks_out); | 58 | int *blksize_out, unsigned long long *blocks_out, int fd); |
59 | extern int access_file(char *path, int r, int w, int x); | 59 | extern int access_file(char *path, int r, int w, int x); |
60 | extern int open_file(char *path, int r, int w, int append); | 60 | extern int open_file(char *path, int r, int w, int append); |
61 | extern int file_type(const char *path, int *maj, int *min); | 61 | extern int file_type(const char *path, int *maj, int *min); |
@@ -71,7 +71,7 @@ extern int lseek_file(int fd, long long offset, int whence); | |||
71 | extern int fsync_file(int fd, int datasync); | 71 | extern int fsync_file(int fd, int datasync); |
72 | extern int file_create(char *name, int ur, int uw, int ux, int gr, | 72 | extern int file_create(char *name, int ur, int uw, int ux, int gr, |
73 | int gw, int gx, int or, int ow, int ox); | 73 | int gw, int gx, int or, int ow, int ox); |
74 | extern int set_attr(const char *file, struct hostfs_iattr *attrs); | 74 | extern int set_attr(const char *file, struct hostfs_iattr *attrs, int fd); |
75 | extern int make_symlink(const char *from, const char *to); | 75 | extern int make_symlink(const char *from, const char *to); |
76 | extern int unlink_file(const char *file); | 76 | extern int unlink_file(const char *file); |
77 | extern int do_mkdir(const char *file, int mode); | 77 | extern int do_mkdir(const char *file, int mode); |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index fd301a910122..4e8bb2fba048 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -147,7 +147,7 @@ static int read_name(struct inode *ino, char *name) | |||
147 | 147 | ||
148 | err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, | 148 | err = stat_file(name, &i_ino, &i_mode, &i_nlink, &ino->i_uid, |
149 | &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, | 149 | &ino->i_gid, &i_size, &ino->i_atime, &ino->i_mtime, |
150 | &ino->i_ctime, &i_blksize, &i_blocks); | 150 | &ino->i_ctime, &i_blksize, &i_blocks, -1); |
151 | if(err) | 151 | if(err) |
152 | return(err); | 152 | return(err); |
153 | 153 | ||
@@ -820,6 +820,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
820 | char *name; | 820 | char *name; |
821 | int err; | 821 | int err; |
822 | 822 | ||
823 | int fd = HOSTFS_I(dentry->d_inode)->fd; | ||
824 | |||
823 | err = inode_change_ok(dentry->d_inode, attr); | 825 | err = inode_change_ok(dentry->d_inode, attr); |
824 | if (err) | 826 | if (err) |
825 | return err; | 827 | return err; |
@@ -864,7 +866,7 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
864 | } | 866 | } |
865 | name = dentry_name(dentry, 0); | 867 | name = dentry_name(dentry, 0); |
866 | if(name == NULL) return(-ENOMEM); | 868 | if(name == NULL) return(-ENOMEM); |
867 | err = set_attr(name, &attrs); | 869 | err = set_attr(name, &attrs, fd); |
868 | kfree(name); | 870 | kfree(name); |
869 | if(err) | 871 | if(err) |
870 | return(err); | 872 | return(err); |
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); |