static int
ActivateLockList(ConstUnicode dirName,  // IN:
                 LockValues *myValues)  // IN:
{
   ActiveLock   *ptr;

   ASSERT(dirName);

   ASSERT(Unicode_StartsWith(dirName, "D"));

   /* Search the list for a matching entry */
   for (ptr = myValues->lockList; ptr != NULL; ptr = ptr->next) {
      if (Unicode_Compare(ptr->dirName, dirName) == 0) {
         break;
      }
   }

   /* No entry? Attempt to add one. */
   if (ptr == NULL) {
      ptr = Util_SafeMalloc(sizeof *ptr);

      ptr->next = myValues->lockList;
      myValues->lockList = ptr;

      ptr->age = 0;
      ptr->dirName = Unicode_Duplicate(dirName);
   }

   /* Mark the entry (exists) */
   ptr->marked = TRUE;

   return 0;
}
Пример #2
0
static char *
FileFindExistingSafeTmpDir(uid_t userId,            // IN:
                           const char *userName,    // IN:
                           const char *baseTmpDir)  // IN:
{
   int i;
   int numFiles;
   char *pattern;
   char *tmpDir = NULL;
   char **fileList = NULL;

   /*
    * We always use the pattern PRODUCT-USER-xxxx when creating
    * alternative safe temp directories, so check for ones with
    * those names and the appropriate permissions.
    */

   pattern = Unicode_Format("%s-%s-", PRODUCT_GENERIC_NAME_LOWER, userName);
   if (pattern == NULL) {
      return NULL;
   }

   numFiles = File_ListDirectory(baseTmpDir, &fileList);

   if (numFiles == -1) {
      free(pattern);

      return NULL;
   }

   for (i = 0; i < numFiles; i++) {
       if (Unicode_StartsWith(fileList[i], pattern)) {
          char *path = Unicode_Join(baseTmpDir, DIRSEPS, fileList[i], NULL);

          if (File_IsDirectory(path) &&
              FileAcceptableSafeTmpDir(path, userId)) {
             tmpDir = path;
             break;
          }

          free(path);
       }
   }

   Util_FreeStringList(fileList, numFiles);
   free(pattern);

   return tmpDir;
}
Пример #3
0
char *
HgfsUri_ConvertFromPathToHgfsUri(const char *pathName,  // IN: path to convert
                                 Bool hgfsOnly)         // IN
{
   char *shareUri = NULL;
   Bool isHgfsName = FALSE;
   char *sharesDefaultRootPath = NULL;

   /* We can only operate on full paths. */
   if (pathName[0] != DIRSEPC) {
      return shareUri;
   }

   /* Retrieve the servername & share name in use. */
   if (!HgfsHlpr_QuerySharesDefaultRootPath(&sharesDefaultRootPath)) {
      Debug("%s: Unable to query shares default root path\n", __FUNCTION__);
      goto exit;
   }

   if (Unicode_StartsWith(pathName, sharesDefaultRootPath)) {
      char *relativeSharePath = NULL;
      char *escapedSharePath = NULL;
      UnicodeIndex relativePathStart = strlen(sharesDefaultRootPath);
      if (   strlen(pathName) > relativePathStart
          && pathName[relativePathStart] == DIRSEPC) {
         relativePathStart++;
      }
      relativeSharePath = Unicode_RemoveRange(pathName, 0, relativePathStart);
      HgfsEscape_Undo(relativeSharePath, strlen(relativeSharePath) + 1);
      escapedSharePath = g_uri_escape_string(relativeSharePath, "/", FALSE);
      shareUri = Unicode_Append(GHI_HGFS_SHARE_URL_UTF8, escapedSharePath);
      g_free(escapedSharePath);
      free(relativeSharePath);
      isHgfsName = TRUE;
   }

exit:
   if (!isHgfsName && !hgfsOnly) {
      /* Only convert non-hgfs file name if hgfsOnly is not set. */
      char *escapedPath = g_uri_escape_string(pathName, "/", FALSE);
      shareUri = Str_Asprintf(NULL,
                              "file://%s",
                               escapedPath);
      g_free(escapedPath);
   }
   HgfsHlpr_FreeSharesRootPath(sharesDefaultRootPath);
   return shareUri;
}
Bool
FileLockIsLocked(ConstUnicode pathName,  // IN:
                 int *err)               // OUT:
{
   uint32 i;
   int errValue;
   int numEntries;
   Unicode lockDir;

   Bool isLocked = FALSE;
   Unicode *fileList = NULL;

   lockDir = Unicode_Append(pathName, FILELOCK_SUFFIX);

   numEntries = FileListDirectoryRobust(lockDir, &fileList);

   if (numEntries == -1) {
      errValue = errno;

      goto bail;
   }

   for (i = 0; i < numEntries; i++) {
      if (Unicode_StartsWith(fileList[i], "M")) {
         isLocked = TRUE;
         break;
      }
   }

   for (i = 0; i < numEntries; i++) {
      Unicode_Free(fileList[i]);
   }

   free(fileList);

   errValue = 0;

bail:
   Unicode_Free(lockDir);

   if (err != NULL) {
      *err = errValue;
   }

   return isLocked;
}
Пример #5
0
Unicode
File_ReplaceExtension(ConstUnicode pathName,      // IN:
                      ConstUnicode newExtension,  // IN:
                      uint32 numExtensions,       // IN:
                      ...)                        // IN:
{
   Unicode path;
   Unicode base;
   Unicode result;
   va_list arguments;
   UnicodeIndex index;
   
   ASSERT(pathName);
   ASSERT(newExtension);
   ASSERT(Unicode_StartsWith(newExtension, "."));

   File_GetPathName(pathName, &path, &base);

   index = Unicode_FindLast(base, ".");

   if (index != UNICODE_INDEX_NOT_FOUND) {
      Unicode oldBase = base;

      if (numExtensions) {
         uint32 i;

         /*
          * Only truncate the old extension from the base if it exists in
          * in the valid extensions list.
          */

         va_start(arguments, numExtensions);

         for (i = 0; i < numExtensions ; i++) {
            Unicode oldExtension = va_arg(arguments, Unicode);

            ASSERT(Unicode_StartsWith(oldExtension, "."));

            if (Unicode_CompareRange(base, index, -1,
                                     oldExtension, 0, -1, FALSE) == 0) {
               base = Unicode_Truncate(oldBase, index); // remove '.'
               break;
            }
         }

         va_end(arguments);
      } else {
         /* Always truncate the old extension if extension list is empty . */
         base = Unicode_Truncate(oldBase, index); // remove '.'
      }

      if (oldBase != base) {
         Unicode_Free(oldBase);
      }
   }

   if (Unicode_IsEmpty(path)) {
      result = Unicode_Append(base, newExtension);
   } else {
      result = Unicode_Join(path, DIRSEPS, base, newExtension, NULL);
   }

   Unicode_Free(path);
   Unicode_Free(base);

   return result;
}
Пример #6
0
void
File_SplitName(ConstUnicode pathName,  // IN:
               Unicode *volume,        // OUT (OPT):
               Unicode *directory,     // OUT (OPT):
               Unicode *base)          // OUT (OPT):
{
   Unicode vol;
   Unicode dir;
   Unicode bas;
   UnicodeIndex volEnd;
   UnicodeIndex length;
   UnicodeIndex baseBegin;
   WIN32_ONLY(UnicodeIndex pathLen);

   ASSERT(pathName);

   /*
    * Get volume.
    */

   volEnd = 0;

#if defined(_WIN32)
   pathLen = Unicode_LengthInCodePoints(pathName);
   if ((pathLen > 2) &&
       (Unicode_StartsWith(pathName, "\\\\") ||
        Unicode_StartsWith(pathName, "//"))) {
      /* UNC path */
      volEnd = FileFirstSlashIndex(pathName, 2);

      if (volEnd == UNICODE_INDEX_NOT_FOUND) {
         /* we have \\foo, which is just bogus */
         volEnd = 0;
      } else {
         volEnd = FileFirstSlashIndex(pathName, volEnd + 1);

         if (volEnd == UNICODE_INDEX_NOT_FOUND) {
            /* we have \\foo\bar, which is legal */
            volEnd = pathLen;
         }
      }
   } else if ((pathLen >= 2) &&
              (Unicode_FindSubstrInRange(pathName, 1, 1, ":", 0,
                                         1) != UNICODE_INDEX_NOT_FOUND)) {
      /* drive-letter path */
      volEnd = 2;
   }

   if (volEnd > 0) {
      vol = Unicode_Substr(pathName, 0, volEnd);
   } else {
      vol = Unicode_Duplicate("");
   }
#else
   vol = Unicode_Duplicate("");
#endif /* _WIN32 */

   /*
    * Get base.
    */

   baseBegin = FileLastSlashIndex(pathName, 0);
   baseBegin = (baseBegin == UNICODE_INDEX_NOT_FOUND) ? 0 : baseBegin + 1;

   if (baseBegin >= volEnd) {
      bas = Unicode_Substr(pathName, baseBegin, -1);
   } else {
      bas = Unicode_Duplicate("");
   }

   /*
    * Get dir.
    */

   length = baseBegin - volEnd;

   if (length > 0) {
      dir = Unicode_Substr(pathName, volEnd, length);
   } else {
      dir = Unicode_Duplicate("");
   }

   /*
    * Return what needs to be returned.
    */

   if (volume) {
      *volume = vol;
   } else {
      Unicode_Free(vol);
   }

   if (directory) {
      *directory = dir;
   } else {
      Unicode_Free(dir);
   }

   if (base) {
      *base = bas;
   } else {
      Unicode_Free(bas);
   }
}
static int
Scanner(ConstUnicode lockDir,    // IN:
        int (*func)(             // IN:
               ConstUnicode lockDir,
               ConstUnicode fileName,
               LockValues *memberValues,
               LockValues *myValues
            ),
        LockValues *myValues,    // IN:
        Bool cleanUp)            // IN:
{
   int        err;
   ActiveLock *ptr;

   ASSERT(lockDir);

   myValues->lockList = NULL;

   while (TRUE) {
      ActiveLock *prev;

      err = ScanDirectory(lockDir, func, myValues, cleanUp);
      if ((err > 0) || ((err == 0) && (myValues->lockList == NULL))) {
         break;
      }

      prev = NULL;
      ptr = myValues->lockList;

      /*
       * Some 'D' entries have persisted. Age them and remove those that
       * have not progressed. Remove those that have disappeared.
       */

      while (ptr != NULL) {
         Bool remove;

         if (ptr->marked) {
            if (ptr->age > FILELOCK_PROGRESS_DEARTH) {
               Unicode temp;
               Unicode path;
               UnicodeIndex index;

               ASSERT(Unicode_StartsWith(ptr->dirName, "D"));

               Log(LGPFX" %s discarding %s data from '%s'.\n",
                   __FUNCTION__, UTF8(ptr->dirName), UTF8(lockDir));

               path = Unicode_Join(lockDir, DIRSEPS, ptr->dirName, NULL);

               index = Unicode_FindLast(path, "D");
               ASSERT(index != UNICODE_INDEX_NOT_FOUND);

               temp = Unicode_Replace(path, index, 1, "M");
               FileDeletionRobust(temp, FALSE);
               Unicode_Free(temp);

               temp = Unicode_Replace(path, index, 1, "E");
               FileDeletionRobust(temp, FALSE);
               Unicode_Free(temp);

               FileRemoveDirectoryRobust(path);

               Unicode_Free(path);

               remove = TRUE;
            } else {
               ptr->marked = FALSE;
               ptr->age += FILELOCK_PROGRESS_SAMPLE;

               remove = FALSE;
            }
         } else {
            remove = TRUE;
         }

         if (remove) {
            if (prev == NULL) {
               myValues->lockList = ptr->next;
            } else {
               prev->next = ptr->next;
            }
         }

         prev = ptr;
         ptr = ptr->next;
      }

      FileSleeper(FILELOCK_PROGRESS_SAMPLE); // relax
   }

   /* Clean up anything still on the list; they are no longer important */
   while (myValues->lockList != NULL) {
      ptr = myValues->lockList;
      myValues->lockList = ptr->next;

      Unicode_Free(ptr->dirName);

      free(ptr);
   }

   return err;
}
static int
ScanDirectory(ConstUnicode lockDir,     // IN:
              int (*func)(              // IN:
                     ConstUnicode lockDir,
                     ConstUnicode fileName,
                     LockValues *memberValues,
                     LockValues *myValues
                   ),
              LockValues *myValues,    // IN:
              Bool cleanUp)            // IN:
{
   uint32 i;
   int err;
   int numEntries;

   Unicode *fileList = NULL;
   char *myExecutionID = NULL;
   char *locationChecksum = NULL;

   ASSERT(lockDir);

   numEntries = FileListDirectoryRobust(lockDir, &fileList);

   if (numEntries == -1) {
      Log(LGPFX" %s: Could not read the directory '%s': %d\n",
          __FUNCTION__, UTF8(lockDir), Err_Errno());

      return EDOM;  // out of my domain
   }

   /* Pass 1: Validate entries and handle any 'D' entries */
   for (i = 0, err = 0; i < numEntries; i++) {
      /* Remove any non-locking files */
      if (!FileLockValidName(fileList[i])) {
         Log(LGPFX" %s discarding %s from %s'; invalid file name.\n",
             __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir));

         err = RemoveLockingFile(lockDir, fileList[i]);
         if (err != 0) {
            goto bail;
         }

        Unicode_Free(fileList[i]);
        fileList[i] = NULL;

        continue;
      }

      /*
       * Any lockers appear to be entering?
       *
       * This should be rather rare. If a locker dies while entering
       * this will cleaned-up.
       */

      if (Unicode_StartsWith(fileList[i], "D")) {
         if (cleanUp) {
            err = ActivateLockList(fileList[i], myValues);
            if (err != 0) {
               goto bail;
            }
        }

        Unicode_Free(fileList[i]);
        fileList[i] = NULL;
      }
   }

   if (myValues->lockList != NULL) {
      goto bail;
   }

   myExecutionID = FileLockGetExecutionID();
   locationChecksum = FileLockLocationChecksum(lockDir);

   /* Pass 2: Handle the 'M' entries */
   for (i = 0, err = 0; i < numEntries; i++) {
      LockValues *ptr;
      Bool       myLockFile;
      LockValues memberValues;
      char       buffer[FILELOCK_DATA_SIZE];

      if ((fileList[i] == NULL) ||
          (Unicode_StartsWith(fileList[i], "E"))) {
         continue;
      }

      myLockFile = (Unicode_Compare(fileList[i],
                          myValues->memberName) == 0) ? TRUE : FALSE;

      if (myLockFile) {
         /* It's me! No need to read or validate anything. */
         ptr = myValues;
      } else {
         /* It's not me! Attempt to extract the member values. */
         err = FileLockMemberValues(lockDir, fileList[i], buffer,
                                    FILELOCK_DATA_SIZE, &memberValues);

         if (err != 0) {
            if (err == ENOENT) {
               err = 0;
               /* Not there anymore; locker unlocked or timed out */
               continue;
            }

            break;
         }

         /* Remove any stale locking files */
         if (FileLockMachineIDMatch(myValues->machineID,
                                    memberValues.machineID)) {
            char *dispose = NULL;

            if (FileLockValidOwner(memberValues.executionID,
                                   memberValues.payload)) {
               /* If it's mine it better still be where I put it! */
               if ((strcmp(myExecutionID, memberValues.executionID) == 0) &&
                   ((memberValues.locationChecksum != NULL) &&
                    (strcmp(memberValues.locationChecksum,
                            locationChecksum) != 0))) {
                  dispose = "lock file has been moved.";
               }
            } else {
               dispose = "invalid executionID.";
            }

            if (dispose) {
               Log(LGPFX" %s discarding %s from %s': %s\n",
                   __FUNCTION__, UTF8(fileList[i]), UTF8(lockDir), dispose);

               Unicode_Free(memberValues.memberName);

               err = RemoveLockingFile(lockDir, fileList[i]);
               if (err != 0) {
                  break;
               }

               continue;
            }
         }

         ptr = &memberValues;
      }

      /* Locking file looks good; see what happens */
      err = (*func)(lockDir, fileList[i], ptr, myValues);

      if (ptr == &memberValues) {
         Unicode_Free(memberValues.memberName);
      }

      if (err != 0) {
         break;
      }
   }

bail:

   for (i = 0; i < numEntries; i++) {
      Unicode_Free(fileList[i]);
   }

   free(fileList);
   free(locationChecksum);
   free(myExecutionID);

   return err;
}