Пример #1
0
char *
Unicode_Join(const char *first,  // IN:
             ...)                // IN:
{
   char *result;

   if (first == NULL) {
      result = NULL;
   } else {
      va_list args;
      const char *cur;

      result = Unicode_Duplicate(first);

      va_start(args, first);

      while ((cur = va_arg(args, const char *)) != NULL) {
         char *temp;

         temp = Unicode_Format("%s%s", result, cur);
         free(result);
         result = temp;
      }

      va_end(args);
   }

   return result;
}
Пример #2
0
static Unicode
FileMakeTempExCreateNameFunc(uint32 num,  // IN:
                             void *data)  // IN:
{
   if (data == NULL) {
      return NULL;
   }

   return Unicode_Format("%s%u", (Unicode) data, num);
}
Пример #3
0
Unicode
System_GetTimeAsString(void)
{
   struct timeval tv;
   time_t sec;
   int msec;
   size_t charsWritten;
   size_t bufSize = 8; // Multiplied by 2 for the initial allocation.
   char *buf = NULL;
   Unicode dateTime = NULL;
   Unicode output = NULL;

   if (gettimeofday(&tv, NULL)) {
      goto out;
   }
   sec = tv.tv_sec;
   msec = tv.tv_usec / 1000;

   /*
    * Loop repeatedly trying to format the time into a buffer, doubling the
    * buffer with each failure. This should be safe as the manpage for
    * strftime(3) seems to suggest that it only fails if the buffer isn't large
    * enough.
    *
    * The resultant string is encoded according to the current locale.
    */
   do {
      char *newBuf;
      bufSize *= 2;

      newBuf = realloc(buf, bufSize);
      if (newBuf == NULL) {
         goto out;
      }
      buf = newBuf;
      charsWritten = strftime(buf, bufSize, "%b %d %H:%M:%S", localtime(&sec));
   } while (charsWritten == 0);

   /*
    * Append the milliseconds field, but only after converting the date/time
    * string from encoding specified in the current locale to an opaque type.
    */
   dateTime = Unicode_Alloc(buf, STRING_ENCODING_DEFAULT);
   if (dateTime == NULL) {
      goto out;
   }
   output = Unicode_Format("%s.%03d", dateTime, msec);

  out:
   free(buf);
   Unicode_Free(dateTime);
   return output;
}
Пример #4
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;
}
Пример #5
0
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;
}
static int
CreateEntryDirectory(const char *machineID,    // IN:
                     const char *executionID,  // IN:
                     ConstUnicode lockDir,     // IN:
                     Unicode *entryDirectory,  // OUT:
                     Unicode *entryFilePath,   // OUT:
                     Unicode *memberFilePath,  // OUT:
                     Unicode *memberName)      // OUT:
{
   int err = 0;
   uint32 randomNumber = 0;

   ASSERT(lockDir);

   *entryDirectory = NULL;
   *entryFilePath = NULL;
   *memberFilePath = NULL;
   *memberName = NULL;

   /* Fun at the races */

   while (TRUE) {
      Unicode temp;
      FileData fileData;

      err = FileAttributesRobust(lockDir, &fileData);
      if (err == 0) {
        /* The name exists. Deal with it... */

        if (fileData.fileType == FILE_TYPE_REGULAR) {
           /*
            * It's a file. Assume this is an (active?) old style lock and
            * err on the safe side - don't remove it (and automatically
            * upgrade to a new style lock).
            */

            Log(LGPFX" %s: '%s' exists; an old style lock file?\n",
                      __FUNCTION__, UTF8(lockDir));

            err = EAGAIN;
            break;
        }

        if (fileData.fileType != FILE_TYPE_DIRECTORY) {
           /* Not a directory; attempt to remove the debris */
           if (FileDeletionRobust(lockDir, FALSE) != 0) {
              Warning(LGPFX" %s: '%s' exists and is not a directory.\n",
                      __FUNCTION__, UTF8(lockDir));

              err = ENOTDIR;
              break;
           }

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

            if ((err != 0) && (err != EEXIST)) {
               Warning(LGPFX" %s creation failure on '%s': %s\n",
                       __FUNCTION__, UTF8(lockDir), strerror(err));

               break;
            }
         } else {
            Warning(LGPFX" %s stat failure on '%s': %s\n",
                    __FUNCTION__, UTF8(lockDir), strerror(err));

            break;
         }
      }

      /* There is a small chance of collision/failure; grab stings now */
      randomNumber = SimpleRandomNumber(machineID, executionID);

      *memberName = Unicode_Format("M%05u%s", randomNumber, FILELOCK_SUFFIX);

      temp = Unicode_Format("D%05u%s", randomNumber, FILELOCK_SUFFIX);
      *entryDirectory = Unicode_Join(lockDir, DIRSEPS, temp, NULL);
      Unicode_Free(temp);

      temp = Unicode_Format("E%05u%s", randomNumber, FILELOCK_SUFFIX);
      *entryFilePath = Unicode_Join(lockDir, DIRSEPS, temp, NULL);
      Unicode_Free(temp);

      *memberFilePath = Unicode_Join(lockDir, DIRSEPS, *memberName, NULL);

      err = MakeDirectory(*entryDirectory);

      if (err == 0) {
         /*
          * The entry directory was safely created. See if a member file
          * is in use (the entry directory is removed once the member file
          * is created). If a member file is in use, choose another number,
          * otherwise the use of the this number is OK.
          *
          * Err on the side of caution... don't want to trash perfectly
          * good member files.
          */

         err = FileAttributesRobust(*memberFilePath, NULL);

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

            if (vmx86_debug) {
               Log(LGPFX" %s stat failure on '%s': %s\n",
                   __FUNCTION__, UTF8(*memberFilePath), strerror(err));
             }
         }

         FileRemoveDirectoryRobust(*entryDirectory);
      } else {
          if ((err != EEXIST) &&  // Another process/thread created it...
              (err != ENOENT)) {  // lockDir is gone...
             Warning(LGPFX" %s creation failure on '%s': %s\n",
                     __FUNCTION__, UTF8(*entryDirectory), strerror(err));

             break;
          }
      }

      Unicode_Free(*entryDirectory);
      Unicode_Free(*entryFilePath);
      Unicode_Free(*memberFilePath);
      Unicode_Free(*memberName);

      *entryDirectory = NULL;
      *entryFilePath = NULL;
      *memberFilePath = NULL;
      *memberName = NULL;
   }

   if (err != 0) {
      Unicode_Free(*entryDirectory);
      Unicode_Free(*entryFilePath);
      Unicode_Free(*memberFilePath);
      Unicode_Free(*memberName);

      *entryDirectory = NULL;
      *entryFilePath = NULL;
      *memberFilePath = NULL;
      *memberName = NULL;
   }

   return err;
}