daemon: Fix utimens so it doesn't hang on named pipes (RHBZ#761460).
authorRichard W.M. Jones <rjones@redhat.com>
Thu, 8 Dec 2011 11:39:58 +0000 (11:39 +0000)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 9 Dec 2011 15:35:40 +0000 (15:35 +0000)
This also adds comprehensive tests for utimens on regular files,
directories (RHBZ#761451), named pipes (RHBZ#761460), symbolic links,
block and char devices.

Note that there is a small change in the (previously undefined)
semantics of this call: It now sets the time on a symbolic link
itself, not on what the symbolic link points to.
(cherry picked from commit 19e2f5aa4fd4ed70b505661d918b5575616ad441)

daemon/utimens.c
generator/generator_actions.ml

index a9857db..2df6fc7 100644 (file)
@@ -33,18 +33,8 @@ do_utimens (const char *path,
             int64_t atsecs, int64_t atnsecs,
             int64_t mtsecs, int64_t mtnsecs)
 {
-  int fd;
   int r;
 
-  CHROOT_IN;
-  fd = open (path, O_RDONLY | O_NOCTTY);
-  CHROOT_OUT;
-
-  if (fd == -1) {
-    reply_with_perror ("open: %s", path);
-    return -1;
-  }
-
   if (atnsecs == -1)
     atnsecs = UTIME_NOW;
   if (atnsecs == -2)
@@ -60,15 +50,12 @@ do_utimens (const char *path,
   times[1].tv_sec = mtsecs;
   times[1].tv_nsec = mtnsecs;
 
-  r = futimens (fd, times);
-  if (r == -1) {
-    reply_with_perror ("futimens: %s", path);
-    close (fd);
-    return -1;
-  }
+  CHROOT_IN;
+  r = utimensat (-1, path, times, AT_SYMLINK_NOFOLLOW);
+  CHROOT_OUT;
 
-  if (close (fd) == -1) {
-    reply_with_perror ("close: %s", path);
+  if (r == -1) {
+    reply_with_perror ("utimensat: %s", path);
     return -1;
   }
 
index d3fa3e0..ece471f 100644 (file)
@@ -4812,10 +4812,31 @@ for the file until you write to it).  To create a non-sparse
 file of zeroes, use C<guestfs_fallocate64> instead.");
 
   ("utimens", (RErr, [Pathname "path"; Int64 "atsecs"; Int64 "atnsecs"; Int64 "mtsecs"; Int64 "mtnsecs"], []), 201, [],
+   (* Test directories, named pipes etc (RHBZ#761451, RHBZ#761460) *)
    [InitScratchFS, Always, TestOutputStruct (
-      [["touch"; "/utimens"];
-       ["utimens"; "/utimens"; "12345"; "67890"; "9876"; "5432"];
-       ["stat"; "/utimens"]], [CompareWithInt ("mtime", 9876)])],
+      [["touch"; "/utimens-file"];
+       ["utimens"; "/utimens-file"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-file"]], [CompareWithInt ("mtime", 9876)]);
+    InitScratchFS, Always, TestOutputStruct (
+      [["mkdir"; "/utimens-dir"];
+       ["utimens"; "/utimens-dir"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-dir"]], [CompareWithInt ("mtime", 9876)]);
+    InitScratchFS, Always, TestOutputStruct (
+      [["mkfifo"; "0o644"; "/utimens-fifo"];
+       ["utimens"; "/utimens-fifo"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-fifo"]], [CompareWithInt ("mtime", 9876)]);
+    InitScratchFS, Always, TestOutputStruct (
+      [["ln_sf"; "/utimens-file"; "/utimens-link"];
+       ["utimens"; "/utimens-link"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-link"]], [CompareWithInt ("mtime", 9876)]);
+    InitScratchFS, Always, TestOutputStruct (
+      [["mknod_b"; "0o644"; "8"; "0"; "/utimens-block"];
+       ["utimens"; "/utimens-block"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-block"]], [CompareWithInt ("mtime", 9876)]);
+    InitScratchFS, Always, TestOutputStruct (
+      [["mknod_c"; "0o644"; "1"; "3"; "/utimens-char"];
+       ["utimens"; "/utimens-char"; "12345"; "67890"; "9876"; "5432"];
+       ["stat"; "/utimens-char"]], [CompareWithInt ("mtime", 9876)])],
    "set timestamp of a file with nanosecond precision",
    "\
 This command sets the timestamps of a file with nanosecond