aboutsummaryrefslogtreecommitdiffstats
path: root/fs/hostfs/hostfs_user.c
diff options
context:
space:
mode:
authorAlberto Bertogli <albertito@gmail.com>2007-05-08 03:23:16 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-08 14:14:57 -0400
commit5822b7faca709c03a59c2929005bfe9caffe6592 (patch)
tree4de7b322cfd25794a79cb46b0feab1113785f7a8 /fs/hostfs/hostfs_user.c
parent0e6b9c98be1b517bf99a21d8a7036a8a21e47dd1 (diff)
uml: make hostfs_setattr() support operations on unlinked open files
This patch allows hostfs_setattr() to work on unlinked open files by calling set_attr() (the userspace part) with the inode's fd. Without this, applications that depend on doing attribute changes to unlinked open files will fail. It works by using the fd versions instead of the path ones (for example fchmod() instead of chmod(), fchown() instead of chown()) when an fd is available. Signed-off-by: Alberto Bertogli <albertito@gmail.com> Signed-off-by: Jeff Dike <jdike@linux.intel.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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);