]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
HGFS: Cleanup the directory entry code to be really platform specific - part I
authorVMware, Inc <>
Wed, 26 Dec 2012 21:21:22 +0000 (13:21 -0800)
committerDmitry Torokhov <dtor@vmware.com>
Thu, 27 Dec 2012 19:21:18 +0000 (11:21 -0800)
The directory entry work is very inefficient and will cause oplock issues.
For Windows platforms the directory reads will change and thus the assumptions
about the platform specific DirectoryEntry structure will not hold true.
Therefore, the DirectoryEntry code is moving to the platform specific files
and will allow the code to have complete control over the structure and contents.
Initially, there will be some duplication of code but that will change in later
work.
There is already bugs with this code and places where ifdefs are added for
platform specific cases not handled by some platforms. These should not be
in platform independent code.
The volume query is also broken and misses some of the Windows platform specific
cases completely which should be handled and will be in the Windows only code.
(Again, later change sets.)

For now, this just simply moves a routine out of the common code into the platform
specific code. More changes to follow.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/hgfsServer/hgfsServer.c
open-vm-tools/lib/hgfsServer/hgfsServerInt.h
open-vm-tools/lib/hgfsServer/hgfsServerLinux.c

index 9f1da8112b84d9f9831fa76338a4a9e2c80b964e..ef5a16e387ed0eaeca5f408525b62287bfb94c4d 100644 (file)
@@ -5004,175 +5004,6 @@ HgfsServerDumpDents(HgfsHandle searchHandle,  // IN: Handle to dump dents from
 }
 
 
-/*
- *-----------------------------------------------------------------------------
- *
- * HgfsServerScanvdir --
- *
- *    Perform a scandir on our virtual directory.
- *
- *    Get directory entry names from the given callback function, and
- *    build an array of DirectoryEntrys of all the names. Somewhat similar to
- *    scandir(3) on linux, but more general.
- *
- * Results:
- *    On success, the number of directory entries found.
- *    On failure, negative error.
- *
- * Side effects:
- *    Memory allocation.
- *
- *-----------------------------------------------------------------------------
- */
-
-static HgfsInternalStatus
-HgfsServerScanvdir(HgfsGetNameFunc enumNamesGet,     // IN: Function to get name
-                   HgfsInitFunc enumNamesInit,       // IN: Setup function
-                   HgfsCleanupFunc enumNamesExit,    // IN: Cleanup function
-                   DirectoryEntry ***dents,          // OUT: Array of DirectoryEntrys
-                   uint32 *numDents)                 // OUT: total number of directory entrys
-{
-   HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
-   uint32 totalDents = 0;   // Number of allocated dents
-   uint32 myNumDents = 0;     // Current actual number of dents
-   DirectoryEntry **myDents = NULL; // So realloc is happy w/ zero myNumDents
-   void *enumNamesHandle;
-
-   ASSERT(NULL != enumNamesInit);
-   ASSERT(NULL != enumNamesGet);
-   ASSERT(NULL != enumNamesExit);
-
-   enumNamesHandle = enumNamesInit();
-   if (NULL == enumNamesHandle) {
-      status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
-      LOG(4, ("%s: Error: init state ret %u\n", __FUNCTION__, status));
-      goto exit;
-   }
-
-   for (;;) {
-      DirectoryEntry *currentEntry;
-      char const *currentEntryName;
-      size_t currentEntryNameLen;
-      size_t currentEntryLen;
-      size_t maxNameLen;
-      Bool done = FALSE;
-
-      /* Add '.' and ".." as the first dents. */
-      if (myNumDents == 0) {
-         currentEntryName = ".";
-         currentEntryNameLen = 1;
-      } else if (myNumDents == 1) {
-         currentEntryName = "..";
-         currentEntryNameLen = 2;
-      } else {
-         if (!enumNamesGet(enumNamesHandle, &currentEntryName, &currentEntryNameLen, &done)) {
-            status = HGFS_ERROR_INVALID_PARAMETER;
-            LOG(4, ("%s: Error: get next entry name ret %u\n", __FUNCTION__, status));
-            goto exit;
-         }
-      }
-
-      if (done) {
-         LOG(4, ("%s: No more names\n", __FUNCTION__));
-         break;
-      }
-
-#if defined(sun)
-      /*
-       * Solaris lacks a single definition of NAME_MAX and using pathconf(), to
-       * determine NAME_MAX for the current directory, is too cumbersome for
-       * our purposes, so we use PATH_MAX as a reasonable upper bound on the
-       * length of the name.
-       */
-      maxNameLen = PATH_MAX;
-#else
-      maxNameLen = sizeof currentEntry->d_name;
-#endif
-      if (currentEntryNameLen >= maxNameLen) {
-         Log("%s: Error: Name \"%s\" is too long.\n", __FUNCTION__, currentEntryName);
-         continue;
-      }
-
-      /* See if we need to allocate more memory */
-      if (myNumDents == totalDents) {
-         void *p;
-
-         if (totalDents != 0) {
-            totalDents *= 2;
-         } else {
-            totalDents = 100;
-         }
-         p = realloc(myDents, totalDents * sizeof *myDents);
-         if (NULL == p) {
-            status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
-            LOG(4, ("%s:  Error: realloc growing array memory ret %u\n", __FUNCTION__, status));
-            goto exit;
-         }
-         myDents = p;
-      }
-
-      /* This file/directory can be added to the list. */
-      LOG(4, ("%s: Nextfilename = \"%s\"\n", __FUNCTION__, currentEntryName));
-
-      /*
-       * Start with the size of the DirectoryEntry struct, subtract the static
-       * length of the d_name buffer (256 in Linux, 1 in Solaris, etc) and add
-       * back just enough space for the UTF-8 name and nul terminator.
-       */
-
-      currentEntryLen = offsetof(DirectoryEntry, d_name) + currentEntryNameLen + 1;
-      currentEntry = malloc(currentEntryLen);
-      if (NULL == currentEntry) {
-         status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
-         LOG(4, ("%s:  Error: allocate dentry memory ret %u\n", __FUNCTION__, status));
-         goto exit;
-      }
-      currentEntry->d_reclen = (unsigned short)currentEntryLen;
-      memcpy(currentEntry->d_name, currentEntryName, currentEntryNameLen);
-      currentEntry->d_name[currentEntryNameLen] = 0;
-
-      myDents[myNumDents] = currentEntry;
-      myNumDents++;
-   }
-
-   /* Trim extra memory off of dents */
-   {
-      void *p;
-
-      p = realloc(myDents, myNumDents * sizeof *myDents);
-      if (NULL != p) {
-         myDents = p;
-      } else {
-         LOG(4, ("%s: Error: realloc trimming array memory\n", __FUNCTION__));
-      }
-   }
-
-   *dents = myDents;
-   *numDents = myNumDents;
-
-exit:
-   if (NULL != enumNamesHandle) {
-      /* Call the exit callback to teardown any state. */
-      if (!enumNamesExit(enumNamesHandle)) {
-         LOG(4, ("%s: Error cleanup failed\n", __FUNCTION__));
-      }
-   }
-
-   if (HGFS_ERROR_SUCCESS != status) {
-      unsigned int i;
-
-      /* Free whatever has been allocated so far */
-      for (i = 0; i < myNumDents; i++) {
-         free(myDents[i]);
-      }
-
-      free(myDents);
-   }
-
-   return status;
-}
-
-
 /*
  *-----------------------------------------------------------------------------
  *
@@ -5300,11 +5131,11 @@ HgfsServerSearchVirtualDir(HgfsGetNameFunc *getName,     // IN: Name enumerator
       goto out;
    }
 
-   status = HgfsServerScanvdir(getName,
-                               initName,
-                               cleanupName,
-                               &search->dents,
-                               &search->numDents);
+   status = HgfsPlatformScanvdir(getName,
+                                 initName,
+                                 cleanupName,
+                                 &search->dents,
+                                 &search->numDents);
    if (HGFS_ERROR_SUCCESS != status) {
       LOG(4, ("%s: couldn't get dents\n", __FUNCTION__));
       HgfsRemoveSearchInternal(search, session);
@@ -5367,11 +5198,11 @@ HgfsServerRestartSearchVirtualDir(HgfsGetNameFunc *getName,     // IN: Name enum
    HgfsFreeSearchDirents(vdirSearch);
 
    /* Restart by rescanning the virtual directory. */
-   status = HgfsServerScanvdir(getName,
-                               initName,
-                               cleanupName,
-                               &vdirSearch->dents,
-                               &vdirSearch->numDents);
+   status = HgfsPlatformScanvdir(getName,
+                                 initName,
+                                 cleanupName,
+                                 &vdirSearch->dents,
+                                 &vdirSearch->numDents);
    if (HGFS_ERROR_SUCCESS != status) {
       ASSERT_DEVEL(0);
       LOG(4, ("%s: couldn't get root dents %u\n", __FUNCTION__, status));
index feb1afb2423da34ba73c4fa301ac59227896003a..0b38ad195dd763252e0d8113308000194ebb9bf4 100644 (file)
@@ -1132,6 +1132,12 @@ HgfsPlatformScandir(char const *baseDir,      // IN: Directory to search in
                     DirectoryEntry ***dents,  // OUT: Array of DirectoryEntrys
                     int *numDents);           // OUT: Number of DirectoryEntrys
 HgfsInternalStatus
+HgfsPlatformScanvdir(HgfsGetNameFunc enumNamesGet,     // IN: Function to get name
+                     HgfsInitFunc enumNamesInit,       // IN: Setup function
+                     HgfsCleanupFunc enumNamesExit,    // IN: Cleanup function
+                     DirectoryEntry ***dents,          // OUT: Array of DirectoryEntrys
+                     uint32 *numDents);                // OUT: total number of directory entrys
+HgfsInternalStatus
 HgfsPlatformSearchDir(HgfsNameStatus nameStatus,       // IN: name status
                       char *dirName,                   // IN: relative directory name
                       uint32 dirNameLength,            // IN: length of dirName
index 4e3bfe21252356861b13df0cf2aa554035dad58a..dff01069513d8a6e678f22e6e556b5962a060e2f 100644 (file)
@@ -3253,6 +3253,175 @@ HgfsPlatformScandir(char const *baseDir,      // IN: Directory to search in
 }
 
 
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * HgfsPlatformScanvdir --
+ *
+ *    Perform a scandir on our virtual directory.
+ *
+ *    Get directory entry names from the given callback function, and
+ *    build an array of DirectoryEntrys of all the names. Somewhat similar to
+ *    scandir(3) on linux, but more general.
+ *
+ * Results:
+ *    On success, the number of directory entries found.
+ *    On failure, negative error.
+ *
+ * Side effects:
+ *    Memory allocation.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+HgfsInternalStatus
+HgfsPlatformScanvdir(HgfsGetNameFunc enumNamesGet,     // IN: Function to get name
+                     HgfsInitFunc enumNamesInit,       // IN: Setup function
+                     HgfsCleanupFunc enumNamesExit,    // IN: Cleanup function
+                     DirectoryEntry ***dents,          // OUT: Array of DirectoryEntrys
+                     uint32 *numDents)                 // OUT: total number of directory entrys
+{
+   HgfsInternalStatus status = HGFS_ERROR_SUCCESS;
+   uint32 totalDents = 0;   // Number of allocated dents
+   uint32 myNumDents = 0;     // Current actual number of dents
+   DirectoryEntry **myDents = NULL; // So realloc is happy w/ zero myNumDents
+   void *enumNamesHandle;
+
+   ASSERT(NULL != enumNamesInit);
+   ASSERT(NULL != enumNamesGet);
+   ASSERT(NULL != enumNamesExit);
+
+   enumNamesHandle = enumNamesInit();
+   if (NULL == enumNamesHandle) {
+      status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
+      LOG(4, ("%s: Error: init state ret %u\n", __FUNCTION__, status));
+      goto exit;
+   }
+
+   for (;;) {
+      DirectoryEntry *currentEntry;
+      char const *currentEntryName;
+      size_t currentEntryNameLen;
+      size_t currentEntryLen;
+      size_t maxNameLen;
+      Bool done = FALSE;
+
+      /* Add '.' and ".." as the first dents. */
+      if (myNumDents == 0) {
+         currentEntryName = ".";
+         currentEntryNameLen = 1;
+      } else if (myNumDents == 1) {
+         currentEntryName = "..";
+         currentEntryNameLen = 2;
+      } else {
+         if (!enumNamesGet(enumNamesHandle, &currentEntryName, &currentEntryNameLen, &done)) {
+            status = HGFS_ERROR_INVALID_PARAMETER;
+            LOG(4, ("%s: Error: get next entry name ret %u\n", __FUNCTION__, status));
+            goto exit;
+         }
+      }
+
+      if (done) {
+         LOG(4, ("%s: No more names\n", __FUNCTION__));
+         break;
+      }
+
+#if defined(sun)
+      /*
+       * Solaris lacks a single definition of NAME_MAX and using pathconf(), to
+       * determine NAME_MAX for the current directory, is too cumbersome for
+       * our purposes, so we use PATH_MAX as a reasonable upper bound on the
+       * length of the name.
+       */
+      maxNameLen = PATH_MAX;
+#else
+      maxNameLen = sizeof currentEntry->d_name;
+#endif
+      if (currentEntryNameLen >= maxNameLen) {
+         Log("%s: Error: Name \"%s\" is too long.\n", __FUNCTION__, currentEntryName);
+         continue;
+      }
+
+      /* See if we need to allocate more memory */
+      if (myNumDents == totalDents) {
+         void *p;
+
+         if (totalDents != 0) {
+            totalDents *= 2;
+         } else {
+            totalDents = 100;
+         }
+         p = realloc(myDents, totalDents * sizeof *myDents);
+         if (NULL == p) {
+            status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
+            LOG(4, ("%s:  Error: realloc growing array memory ret %u\n", __FUNCTION__, status));
+            goto exit;
+         }
+         myDents = p;
+      }
+
+      /* This file/directory can be added to the list. */
+      LOG(4, ("%s: Nextfilename = \"%s\"\n", __FUNCTION__, currentEntryName));
+
+      /*
+       * Start with the size of the DirectoryEntry struct, subtract the static
+       * length of the d_name buffer (256 in Linux, 1 in Solaris, etc) and add
+       * back just enough space for the UTF-8 name and nul terminator.
+       */
+
+      currentEntryLen = offsetof(DirectoryEntry, d_name) + currentEntryNameLen + 1;
+      currentEntry = malloc(currentEntryLen);
+      if (NULL == currentEntry) {
+         status = HGFS_ERROR_NOT_ENOUGH_MEMORY;
+         LOG(4, ("%s:  Error: allocate dentry memory ret %u\n", __FUNCTION__, status));
+         goto exit;
+      }
+      currentEntry->d_reclen = (unsigned short)currentEntryLen;
+      memcpy(currentEntry->d_name, currentEntryName, currentEntryNameLen);
+      currentEntry->d_name[currentEntryNameLen] = 0;
+
+      myDents[myNumDents] = currentEntry;
+      myNumDents++;
+   }
+
+   /* Trim extra memory off of dents */
+   {
+      void *p;
+
+      p = realloc(myDents, myNumDents * sizeof *myDents);
+      if (NULL != p) {
+         myDents = p;
+      } else {
+         LOG(4, ("%s: Error: realloc trimming array memory\n", __FUNCTION__));
+      }
+   }
+
+   *dents = myDents;
+   *numDents = myNumDents;
+
+exit:
+   if (NULL != enumNamesHandle) {
+      /* Call the exit callback to teardown any state. */
+      if (!enumNamesExit(enumNamesHandle)) {
+         LOG(4, ("%s: Error cleanup failed\n", __FUNCTION__));
+      }
+   }
+
+   if (HGFS_ERROR_SUCCESS != status) {
+      unsigned int i;
+
+      /* Free whatever has been allocated so far */
+      for (i = 0; i < myNumDents; i++) {
+         free(myDents[i]);
+      }
+
+      free(myDents);
+   }
+
+   return status;
+}
+
+
 /*
  *----------------------------------------------------------------------
  *