aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hostfs/hostfs_user.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/hostfs/hostfs_user.c')
-rw-r--r--fs/hostfs/hostfs_user.c108
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
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);