static char * FindSuitableExistingDirectory( const char *realRoot, // IN: e.g. $HOME/.cache/vmware/drag_and_drop/ const char *apparentRoot) // IN: e.g. /tmp/VMwareDnD/ { char *result = NULL; char **stagingDirList; int numStagingDirs = File_ListDirectory(realRoot, &stagingDirList); int i; for (i = 0; i < numStagingDirs && result == NULL; i++) { char *stagingDir = Unicode_Append(realRoot, stagingDirList[i]); char *apparentStagingDir = Unicode_Append(apparentRoot, stagingDirList[i]); char *temp = NULL; struct stat sb; if ( File_IsEmptyDirectory(stagingDir) && ( Posix_Symlink(stagingDir, apparentStagingDir) == 0 || ( Posix_Lstat(apparentStagingDir, &sb) == 0 && sb.st_uid == getuid() && (temp = Posix_ReadLink(apparentStagingDir)) != NULL && strcmp(stagingDir, temp) == 0))) { result = apparentStagingDir; apparentStagingDir = NULL; } free(stagingDir); free(apparentStagingDir); free(temp); } Util_FreeStringList(stagingDirList, numStagingDirs); return result; }
char * DnD_CreateStagingDirectory(void) { const char *root; char **stagingDirList; int numStagingDirs; int i; char *ret = NULL; Bool found = FALSE; /* * Make sure the root staging directory is created with the correct * permissions. */ root = DnDCreateRootStagingDirectory(); if (!root) { return NULL; } /* Look for an existing, empty staging directory */ numStagingDirs = File_ListDirectory(root, &stagingDirList); if (numStagingDirs < 0) { goto exit; } for (i = 0; i < numStagingDirs; i++) { if (!found) { char *stagingDir; stagingDir = Unicode_Append(root, stagingDirList[i]); if (File_IsEmptyDirectory(stagingDir) && DnDStagingDirectoryUsable(stagingDir)) { ret = Unicode_Append(stagingDir, DIRSEPS); /* * We can use this directory. Make sure to continue to loop * so we don't leak the remaining stagindDirList[i]s. */ found = TRUE; } free(stagingDir); } } Util_FreeStringList(stagingDirList, numStagingDirs); /* Only create a directory if we didn't find one above. */ if (!found) { rqContext *context; context = Random_QuickSeed((unsigned)time(NULL)); for (i = 0; i < 10; i++) { char *temp; /* Each staging directory is given a random name. */ free(ret); temp = Unicode_Format("%08x%c", Random_Quick(context), DIRSEPC); VERIFY(temp); ret = Unicode_Append(root, temp); free(temp); if (File_CreateDirectory(ret) && DnDSetPermissionsOnStagingDir(ret)) { found = TRUE; break; } } free(context); } exit: if (!found && ret != NULL) { free(ret); ret = NULL; } return ret; }