Fix mkdir-p if directory exists (RHBZ#503133).
authorRichard W.M. Jones <rjones@redhat.com>
Fri, 29 May 2009 10:20:29 +0000 (11:20 +0100)
committerRichard W.M. Jones <rjones@redhat.com>
Fri, 29 May 2009 10:20:29 +0000 (11:20 +0100)
capitests/tests.c
daemon/dir.c
src/generator.ml

index 3b29642..959d09b 100644 (file)
@@ -12805,6 +12805,198 @@ static int test_mkdir_p_2 (void)
   return 0;
 }
 
+static int test_mkdir_p_3_skip (void)
+{
+  const char *str;
+
+  str = getenv ("SKIP_TEST_MKDIR_P_3");
+  if (str && strcmp (str, "1") == 0) return 1;
+  str = getenv ("SKIP_TEST_MKDIR_P");
+  if (str && strcmp (str, "1") == 0) return 1;
+  return 0;
+}
+
+static int test_mkdir_p_3 (void)
+{
+  if (test_mkdir_p_3_skip ()) {
+    printf ("%s skipped (reason: SKIP_TEST_* variable set)\n", "test_mkdir_p_3");
+    return 0;
+  }
+
+  /* InitBasicFS for test_mkdir_p_3: create ext2 on /dev/sda1 */
+  {
+    char device[] = "/dev/sda";
+    device[5] = devchar;
+    int r;
+    suppress_error = 0;
+    r = guestfs_blockdev_setrw (g, device);
+    if (r == -1)
+      return -1;
+  }
+  {
+    int r;
+    suppress_error = 0;
+    r = guestfs_umount_all (g);
+    if (r == -1)
+      return -1;
+  }
+  {
+    int r;
+    suppress_error = 0;
+    r = guestfs_lvm_remove_all (g);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char device[] = "/dev/sda";
+    device[5] = devchar;
+    char lines_0[] = ",";
+    char *lines[] = {
+      lines_0,
+      NULL
+    };
+    int r;
+    suppress_error = 0;
+    r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char fstype[] = "ext2";
+    char device[] = "/dev/sda1";
+    device[5] = devchar;
+    int r;
+    suppress_error = 0;
+    r = guestfs_mkfs (g, fstype, device);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char device[] = "/dev/sda1";
+    device[5] = devchar;
+    char mountpoint[] = "/";
+    int r;
+    suppress_error = 0;
+    r = guestfs_mount (g, device, mountpoint);
+    if (r == -1)
+      return -1;
+  }
+  /* TestRun for mkdir_p (3) */
+  {
+    char path[] = "/new";
+    int r;
+    suppress_error = 0;
+    r = guestfs_mkdir (g, path);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char path[] = "/new";
+    int r;
+    suppress_error = 0;
+    r = guestfs_mkdir_p (g, path);
+    if (r == -1)
+      return -1;
+  }
+  return 0;
+}
+
+static int test_mkdir_p_4_skip (void)
+{
+  const char *str;
+
+  str = getenv ("SKIP_TEST_MKDIR_P_4");
+  if (str && strcmp (str, "1") == 0) return 1;
+  str = getenv ("SKIP_TEST_MKDIR_P");
+  if (str && strcmp (str, "1") == 0) return 1;
+  return 0;
+}
+
+static int test_mkdir_p_4 (void)
+{
+  if (test_mkdir_p_4_skip ()) {
+    printf ("%s skipped (reason: SKIP_TEST_* variable set)\n", "test_mkdir_p_4");
+    return 0;
+  }
+
+  /* InitBasicFS for test_mkdir_p_4: create ext2 on /dev/sda1 */
+  {
+    char device[] = "/dev/sda";
+    device[5] = devchar;
+    int r;
+    suppress_error = 0;
+    r = guestfs_blockdev_setrw (g, device);
+    if (r == -1)
+      return -1;
+  }
+  {
+    int r;
+    suppress_error = 0;
+    r = guestfs_umount_all (g);
+    if (r == -1)
+      return -1;
+  }
+  {
+    int r;
+    suppress_error = 0;
+    r = guestfs_lvm_remove_all (g);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char device[] = "/dev/sda";
+    device[5] = devchar;
+    char lines_0[] = ",";
+    char *lines[] = {
+      lines_0,
+      NULL
+    };
+    int r;
+    suppress_error = 0;
+    r = guestfs_sfdisk (g, device, 0, 0, 0, lines);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char fstype[] = "ext2";
+    char device[] = "/dev/sda1";
+    device[5] = devchar;
+    int r;
+    suppress_error = 0;
+    r = guestfs_mkfs (g, fstype, device);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char device[] = "/dev/sda1";
+    device[5] = devchar;
+    char mountpoint[] = "/";
+    int r;
+    suppress_error = 0;
+    r = guestfs_mount (g, device, mountpoint);
+    if (r == -1)
+      return -1;
+  }
+  /* TestLastFail for mkdir_p (4) */
+  {
+    char path[] = "/new";
+    int r;
+    suppress_error = 0;
+    r = guestfs_touch (g, path);
+    if (r == -1)
+      return -1;
+  }
+  {
+    char path[] = "/new";
+    int r;
+    suppress_error = 1;
+    r = guestfs_mkdir_p (g, path);
+    if (r != -1)
+      return -1;
+  }
+  return 0;
+}
+
 static int test_mkdir_0_skip (void)
 {
   const char *str;
@@ -15843,7 +16035,7 @@ int main (int argc, char *argv[])
     free (devs[i]);
   free (devs);
 
-  nr_tests = 140;
+  nr_tests = 142;
 
   test_num++;
   printf ("%3d/%3d test_find_0\n", test_num, nr_tests);
@@ -16536,6 +16728,18 @@ int main (int argc, char *argv[])
     failed++;
   }
   test_num++;
+  printf ("%3d/%3d test_mkdir_p_3\n", test_num, nr_tests);
+  if (test_mkdir_p_3 () == -1) {
+    printf ("test_mkdir_p_3 FAILED\n");
+    failed++;
+  }
+  test_num++;
+  printf ("%3d/%3d test_mkdir_p_4\n", test_num, nr_tests);
+  if (test_mkdir_p_4 () == -1) {
+    printf ("test_mkdir_p_4 FAILED\n");
+    failed++;
+  }
+  test_num++;
   printf ("%3d/%3d test_mkdir_0\n", test_num, nr_tests);
   if (test_mkdir_0 () == -1) {
     printf ("test_mkdir_0 FAILED\n");
index f706466..3df6233 100644 (file)
@@ -117,10 +117,21 @@ recursive_mkdir (const char *path)
   int loop = 0;
   int r;
   char *ppath, *p;
+  struct stat buf;
 
  again:
   r = mkdir (path, 0777);
   if (r == -1) {
+    if (errno == EEXIST) {     /* Something exists here, might not be a dir. */
+      r = lstat (path, &buf);
+      if (r == -1) return -1;
+      if (!S_ISDIR (buf.st_mode)) {
+       errno = ENOTDIR;
+       return -1;
+      }
+      return 0;                        /* OK - directory exists here already. */
+    }
+
     if (!loop && errno == ENOENT) {
       loop = 1;                        /* Stops it looping forever. */
 
index f30d779..9f01904 100755 (executable)
@@ -1002,7 +1002,14 @@ Create a directory named C<path>.");
        ["is_dir"; "/new/foo"]];
     InitBasicFS, Always, TestOutputTrue
       [["mkdir_p"; "/new/foo/bar"];
-       ["is_dir"; "/new"]]],
+       ["is_dir"; "/new"]];
+    (* Regression tests for RHBZ#503133: *)
+    InitBasicFS, Always, TestRun
+      [["mkdir"; "/new"];
+       ["mkdir_p"; "/new"]];
+    InitBasicFS, Always, TestLastFail
+      [["touch"; "/new"];
+       ["mkdir_p"; "/new"]]],
    "create a directory and parents",
    "\
 Create a directory named C<path>, creating any parent directories