aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/hostfs/hostfs.h4
-rw-r--r--fs/hostfs/hostfs_kern.c6
-rw-r--r--fs/hostfs/hostfs_user.c108
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);
59extern int access_file(char *path, int r, int w, int x); 59extern int access_file(char *path, int r, int w, int x);
60extern int open_file(char *path, int r, int w, int append); 60extern int open_file(char *path, int r, int w, int append);
61extern int file_type(const char *path, int *maj, int *min); 61extern 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);
71extern int fsync_file(int fd, int datasync); 71extern int fsync_file(int fd, int datasync);
72extern int file_create(char *name, int ur, int uw, int ux, int gr, 72extern 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);
74extern int set_attr(const char *file, struct hostfs_iattr *attrs); 74extern int set_attr(const char *file, struct hostfs_iattr *attrs, int fd);
75extern int make_symlink(const char *from, const char *to); 75extern int make_symlink(const char *from, const char *to);
76extern int unlink_file(const char *file); 76extern int unlink_file(const char *file);
77extern int do_mkdir(const char *file, int mode); 77extern 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
205int set_attr(const char *file, struct hostfs_iattr *attrs) 209int 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);