]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
lib/file: Improve File_CreateDirectoryHierarchy error detection
authorOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:57 +0000 (11:23 -0700)
committerOliver Kurth <okurth@vmware.com>
Fri, 15 Sep 2017 18:23:57 +0000 (11:23 -0700)
open-vm-tools/lib/file/file.c

index a8ac28ba63ce243502b02ae858602fafbf373e5a..af39081d21972cf96b16ac129723b7591ee0934e 100644 (file)
@@ -333,7 +333,7 @@ File_UnlinkRetry(const char *pathName,       // IN:
 /*
  *----------------------------------------------------------------------
  *
- * File_CreateDirectoryEx --
+ * FileCreateDirectoryEx --
  *
  *      Creates the specified directory with the specified permissions.
  *
@@ -346,9 +346,9 @@ File_UnlinkRetry(const char *pathName,       // IN:
  *----------------------------------------------------------------------
  */
 
-Bool
-File_CreateDirectoryEx(const char *pathName,  // IN:
-                       int mask)              // IN:
+static int
+FileCreateDirectoryEx(const char *pathName,  // IN:
+                      int mask)              // IN:
 {
    int err = FileCreateDirectory(pathName, mask);
 
@@ -357,6 +357,32 @@ File_CreateDirectoryEx(const char *pathName,  // IN:
           __FUNCTION__, pathName, err);
    }
 
+   return err;
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * File_CreateDirectoryEx --
+ *
+ *      Creates the specified directory with the specified permissions.
+ *
+ * Results:
+ *      True if the directory is successfully created, false otherwise.
+ *
+ * Side effects:
+ *      Creates the directory on disk.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Bool
+File_CreateDirectoryEx(const char *pathName,  // IN:
+                       int mask)              // IN:
+{
+   int err = FileCreateDirectoryEx(pathName, mask);
+
    return err == 0;
 }
 
@@ -1702,12 +1728,8 @@ File_CreateDirectoryHierarchyEx(const char *pathName,   // IN:
     */
 
    while (TRUE) {
-      Bool failed;
+      int err;
       char *temp;
-#if defined(_WIN32)
-      DWORD status;
-      DWORD statusNew;
-#endif
 
       index = FileFirstSlashIndex(pathName, index + 1);
 
@@ -1721,51 +1743,41 @@ File_CreateDirectoryHierarchyEx(const char *pathName,   // IN:
        * operation to fail with no reason.
        * This is why we reverse the attempt and the check.
        */
+      err = FileCreateDirectoryEx(temp, mask);
 
-      /*
-       * Bugfix 1592498, set last error "Access denied" instead of
-       * "File not found". File_XXX have different implementations on
-       * Windows and Linux, this problem only happens on Windows.
-       *
-       * Bugfix 1878912, working around a problem when we have evidence that
-       * directory exists but we get intermittent errors when we check its
-       * existence.
-       */
-      failed = !File_EnsureDirectoryEx(temp, mask);
-#if defined(_WIN32)
-      status = GetLastError();
-      statusNew = ERROR_SUCCESS;
-#endif
+      if (err == 0) {
+         if (topmostCreated != NULL && *topmostCreated == NULL) {
+            *topmostCreated = temp;
+            temp = NULL;
+         }
+      } else {
+         FileData fileData;
+
+         if (err == EEXIST) {
+            err = FileAttributes(temp, &fileData);
+
+            if (err == 0) {
+               if (fileData.fileType != FILE_TYPE_DIRECTORY) {
+                  err = ENOTDIR;
+                  errno = err;
 
-      if (failed) {
-         if (File_IsDirectory(temp)) {
-            failed = FALSE;
-         } else {
 #if defined(_WIN32)
-            statusNew = GetLastError();
+                  SetLastError(ERROR_DIRECTORY);
 #endif
+               }
+            }
          }
-      } else if (topmostCreated != NULL && *topmostCreated == NULL) {
-         *topmostCreated = temp;
-         temp = NULL;
-      }
-
-#if defined(_WIN32)
-      if (status == ERROR_ACCESS_DENIED && statusNew == ERROR_FILE_NOT_FOUND) {
-         SetLastError(status);
       }
-#endif
 
       Posix_Free(temp);
 
-      if (failed) {
+      if (err != 0) {
          return FALSE;
       }
 
       if (index == UNICODE_INDEX_NOT_FOUND) {
          break;
       }
-
    }
 
    return TRUE;