示例#1
0
MXUserExclLock *
MXUser_CreateExclLock(const char *userName,  // IN:
                      MX_Rank rank)          // IN:
{
   Bool doStats;
   char *properName;
   MXUserExclLock *lock;

   lock = Util_SafeCalloc(1, sizeof(*lock));

   if (userName == NULL) {
      properName = Str_SafeAsprintf(NULL, "X-%p", GetReturnAddress());
   } else {
      properName = Util_SafeStrdup(userName);
   }

   if (!MXRecLockInit(&lock->recursiveLock)) {
      free(properName);
      free(lock);

      return NULL;
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_EXCL);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpExclLock;

   if (vmx86_stats) {
      doStats = MXUserStatsEnabled();
   } else {
      doStats = FALSE;
   }

   if (doStats) {
      MXUser_ControlExclLock(lock, MXUSER_CONTROL_ENABLE_STATS);
   } else {
      lock->header.statsFunc = NULL;
      Atomic_WritePtr(&lock->statsMem, NULL);
   }

   MXUserAddToList(&lock->header);

   return lock;
}
示例#2
0
MXUserSemaphore *
MXUser_CreateSemaphore(const char *userName,  // IN:
                       MX_Rank rank)          // IN:
{
   char *properName;
   MXUserSemaphore *sema;

   sema = Util_SafeCalloc(1, sizeof(*sema));

   if (userName == NULL) {
      properName = Str_SafeAsprintf(NULL, "Sema-%p", GetReturnAddress());
   } else {
      properName = Util_SafeStrdup(userName);
   }

   if (LIKELY(MXUserInit(&sema->nativeSemaphore) == 0)) {
      sema->header.signature = MXUserGetSignature(MXUSER_TYPE_SEMA);
      sema->header.name = properName;
      sema->header.rank = rank;
      sema->header.serialNumber = MXUserAllocSerialNumber();
      sema->header.dumpFunc = MXUserDumpSemaphore;

      if (MXUserStatsMode() == 0) {
         sema->header.statsFunc = NULL;
         Atomic_WritePtr(&sema->acquireStatsMem, NULL);
      } else {
         MXUserAcquireStats *acquireStats;

         acquireStats = Util_SafeCalloc(1, sizeof(*acquireStats));

         MXUserAcquisitionStatsSetUp(&acquireStats->data);

         sema->header.statsFunc = MXUserStatsActionSema;
         Atomic_WritePtr(&sema->acquireStatsMem, acquireStats);
      }

      MXUserAddToList(&sema->header);
   } else {
      free(properName);
      free(sema);
      sema = NULL;
   }

   return sema;
}
static char *
ToolsDaemonTcloGetQuotedString(const char *args,      // IN
                               const char **endOfArg) // OUT
{
   char *resultStr = NULL;
   char *endStr;
   Debug(">ToolsDaemonTcloGetQuotedString\n");

   while ((*args) && ('\"' != *args)) {
      args++;
   }
   if ('\"' == *args) {
      args++;
   }

   resultStr = Util_SafeStrdup(args);

   endStr = resultStr;
   while (*endStr) {
      if (('\\' == *endStr) && (*(endStr + 1))) {
         endStr += 2;
      } else if ('\"' == *endStr) {
         *endStr = 0;
         endStr++;
         break;
      } else {
         endStr++;
      }
   }

   if (NULL != endOfArg) {
      args += (endStr - resultStr);
      while (' ' == *args) {
         args++;
      }
      *endOfArg = args;
   }

   Debug("<ToolsDaemonTcloGetQuotedString\n");
   return resultStr;
} // ToolsDaemonTcloGetQuotedString
Bool
SyncDriver_Freeze(const char *userPaths,     // IN
                  SyncDriverHandle *handle)  // OUT
{
   char *paths = NULL;
   SyncDriverErr err = SD_UNAVAILABLE;
   size_t i = 0;

   /*
    * First, convert the given path list to something the backends will
    * understand: a colon-separated list of paths.
    */
   if (userPaths == NULL || Str_Strncmp(userPaths, "all", sizeof "all") == 0) {
      paths = SyncDriverListMounts();
      if (paths == NULL) {
         Debug(LGPFX "Failed to list mount points.\n");
         return SD_ERROR;
      }
   } else {
      /*
       * The sync driver API specifies spaces as separators, but the driver
       * uses colons as the path separator on Unix.
       */
      char *c;
      paths = Util_SafeStrdup(userPaths);
      for (c = paths; *c != '\0'; c++) {
         if (*c == ' ') {
            *c = ':';
         }
      }
   }

   while (err == SD_UNAVAILABLE && i < ARRAYSIZE(gBackends)) {
      err = gBackends[i++](paths, handle);
   }

   free(paths);
   return err == SD_SUCCESS;
}
Unicode
Unicode_Duplicate(ConstUnicode str) // IN
{
   return (Unicode)Util_SafeStrdup((const char *)str);
}
示例#6
0
static int
DnD_TryInitVmblock(const char *vmbFsName,          // IN
                   const char *vmbMntPoint,        // IN
                   const char *vmbDevice,          // IN
                   mode_t vmbDeviceMode,           // IN
                   Bool (*verifyBlock)(int fd))    // IN
{
#if defined NO_SETMNTENT || defined NO_ENDMNTENT
   NOT_IMPLEMENTED();
   errno = ENOSYS;
   return -1;
#else
   Bool found = FALSE;
   int blockFd = -1;
   char *realMntPoint;
   MNTHANDLE fp;
   DECLARE_MNTINFO(mnt);

   ASSERT(vmbFsName);
   ASSERT(vmbMntPoint);
   ASSERT(vmbDevice);

   /* Resolve desired mount point in case it is symlinked somewhere */
   realMntPoint = Posix_RealPath(vmbMntPoint);
   if (!realMntPoint) {
      /*
       * If resolve failed for some reason try to fall back to
       * original mount point specification.
       */
      realMntPoint = Util_SafeStrdup(vmbMntPoint);
   }

   /* Make sure the vmblock file system is mounted. */
   fp = OPEN_MNTFILE("r");
   if (fp == NULL) {
      LOG(1, ("%s: could not open mount file\n", __func__));
      goto out;
   }

   while (GETNEXT_MNTINFO(fp, mnt)) {
      /*
       * In the future we can publish the mount point in VMDB so that the UI
       * can use it rather than enforcing the VMBLOCK_MOUNT_POINT check here.
       */

      if (strcmp(MNTINFO_FSTYPE(mnt), vmbFsName) == 0 &&
          strcmp(MNTINFO_MNTPT(mnt), realMntPoint) == 0) {
         found = TRUE;
         break;
      }
   }

   (void) CLOSE_MNTFILE(fp);

   if (found) {
      /* Open device node for communication with vmblock. */
      blockFd = Posix_Open(vmbDevice, vmbDeviceMode);
      if (blockFd < 0) {
         LOG(1, ("%s: Can not open blocker device (%s)\n",
                 __func__, strerror(errno)));
      } else {
         LOG(4, ("%s: Opened blocker device at %s\n",
                 __func__, VMBLOCK_DEVICE));
         if (verifyBlock && !verifyBlock(blockFd)) {
            LOG(4, ("%s: Blocker device at %s did not pass checks, closing.\n",
                    __func__, VMBLOCK_DEVICE));
            close(blockFd);
            blockFd = -1;
         }
      }
   }

out:
   free(realMntPoint);
   return blockFd;
#endif
}
static Bool
RecordResolverInfo(NicInfoV3 *nicInfo)  // OUT
{
   DnsConfigInfo *dnsConfigInfo = NULL;
   char namebuf[DNSINFO_MAX_ADDRLEN + 1];
   char **s;

   if (res_init() == -1) {
      return FALSE;
   }

   dnsConfigInfo = Util_SafeCalloc(1, sizeof *dnsConfigInfo);

   /*
    * Copy in the host name. not this
    */
   if (!GuestInfoGetFqdn(sizeof namebuf, namebuf)) {
      goto fail;
   }
   dnsConfigInfo->hostName =
      Util_SafeCalloc(1, sizeof *dnsConfigInfo->hostName);
   *dnsConfigInfo->hostName = Util_SafeStrdup(namebuf);

   /*
    * Repeat with the domain name. not this
    */
   dnsConfigInfo->domainName =
      Util_SafeCalloc(1, sizeof *dnsConfigInfo->domainName);
   *dnsConfigInfo->domainName = Util_SafeStrdup(_res.defdname);

   /*
    * Name servers.
    */
   RecordResolverNS(dnsConfigInfo);

   /*
    * Search suffixes.
    */
   for (s = _res.dnsrch; *s; s++) {
      DnsHostname *suffix;

      /* Check to see if we're going above our limit. See bug 605821. */
      if (dnsConfigInfo->searchSuffixes.searchSuffixes_len == DNSINFO_MAX_SUFFIXES) {
         g_message("%s: dns search suffix limit (%d) reached, skipping overflow.",
                   __FUNCTION__, DNSINFO_MAX_SUFFIXES);
         break;
      }

      suffix = XDRUTIL_ARRAYAPPEND(dnsConfigInfo, searchSuffixes, 1);
      ASSERT_MEM_ALLOC(suffix);
      *suffix = Util_SafeStrdup("test suffix");
   }

   /*
    * "Commit" dnsConfigInfo to nicInfo.
    */
   nicInfo->dnsConfigInfo = dnsConfigInfo;

   return TRUE;

fail:
   VMX_XDR_FREE(xdr_DnsConfigInfo, dnsConfigInfo);
   free(dnsConfigInfo);
   return FALSE;
}
示例#8
0
MXUserRWLock *
MXUser_CreateRWLock(const char *userName,  // IN:
                    MX_Rank rank)          // IN:
{
   Bool lockInited;
   char *properName;
   MXUserRWLock *lock;
   Bool useNative = MXUserNativeRWSupported();

   lock = Util_SafeCalloc(1, sizeof(*lock));

   if (userName == NULL) {
      if (LIKELY(useNative)) {
         properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress());
      } else {
         /* emulated */
         properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress());
      }
   } else {
      properName = Util_SafeStrdup(userName);
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpRWLock;

   /*
    * Always attempt to use native locks when they are available. If, for some
    * reason, a native lock should be available but isn't, fall back to using
    * an internal recursive lock - something is better than nothing.
    */

   lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock);

   lockInited = MXRecLockInit(&lock->recursiveLock);

   if (LIKELY(lockInited)) {
      Bool doStats;

      lock->holderTable = HashTable_Alloc(256,
                                          HASH_INT_KEY | HASH_FLAG_ATOMIC,
                                          MXUserFreeHashEntry);

      if (vmx86_stats) {
         doStats = MXUserStatsEnabled();
      } else {
         doStats = FALSE;
      }

      if (doStats) {
         MXUser_ControlRWLock(lock, MXUSER_CONTROL_ENABLE_STATS);
      } else {
         lock->header.statsFunc = NULL;
         Atomic_WritePtr(&lock->statsMem, NULL);
      }

      MXUserAddToList(&lock->header);
   } else {
      if (lock->useNative) {
         MXUserNativeRWDestroy(&lock->nativeLock);
      }

      free(properName);
      free(lock);
      lock = NULL;
   }

   return lock;
}
char *
File_GetSafeTmpDir(Bool useConf)  // IN:
{
   char *tmpDir;

#if defined(__FreeBSD__) || defined(sun)
   tmpDir = FileGetTmpDir(useConf);
#else
   static Atomic_Ptr lckStorage;
   static char *safeDir;
   char *baseTmpDir = NULL;
   char *userName = NULL;
   uid_t userId;
   MXUserExclLock *lck;

   userId = geteuid();

   /* Get and take lock for our safe dir. */
   lck = MXUser_CreateSingletonExclLock(&lckStorage, "getSafeTmpDirLock",
                                        RANK_getSafeTmpDirLock);
   VERIFY(lck != NULL);

   MXUser_AcquireExclLock(lck);

   /*
    * Check if we've created a temporary dir already and if it is still usable.
    */

   tmpDir = NULL;

   if (safeDir && FileAcceptableSafeTmpDir(safeDir, userId)) {
      tmpDir = Util_SafeStrdup(safeDir);
      goto exit;
   }

   /* We don't have a useable temporary dir, create one. */
   baseTmpDir = FileGetTmpDir(useConf);

   if (!baseTmpDir) {
      Warning("%s: FileGetTmpDir failed.\n", __FUNCTION__);
      goto exit;
   }

   userName = FileGetUserName(userId);

   if (!userName) {
      Warning("%s: FileGetUserName failed, using numeric ID "
              "as username instead.\n", __FUNCTION__);

      /* Fallback on just using the userId as the username. */
      userName = Str_Asprintf(NULL, "uid-%d", userId);

      if (!userName) {
         Warning("%s: Str_Asprintf error.\n", __FUNCTION__);
         goto exit;
      }
   }

   tmpDir = Str_Asprintf(NULL, "%s%s%s-%s", baseTmpDir, DIRSEPS,
                         PRODUCT_GENERIC_NAME_LOWER, userName);

   if (!tmpDir) {
      Warning("%s: Out of memory error.\n", __FUNCTION__);
      goto exit;
   }

   if (!FileAcceptableSafeTmpDir(tmpDir, userId)) {
      /*
       * We didn't get our first choice for the safe temp directory.
       * Search through the unsafe tmp directory to see if there is
       * an acceptable one to use.
       */

      free(tmpDir);

      tmpDir = FileFindExistingSafeTmpDir(userId, userName, baseTmpDir);

      if (!tmpDir) {
         /*
          * We didn't find any usable directories, so try to create one now.
          */

         tmpDir = FileCreateSafeTmpDir(userId, userName, baseTmpDir);
      }
   }

   if (tmpDir) {
      /*
       * We have successfully created a temporary directory, remember it for
       * future calls.
       */

      free(safeDir);
      safeDir = Util_SafeStrdup(tmpDir);
   }

  exit:
   MXUser_ReleaseExclLock(lck);
   free(baseTmpDir);
   free(userName);
#endif

   return tmpDir;
}
示例#10
0
const char *
Err_Errno2String(Err_Number errorNumber) // IN
{
   HashTable *numTable;
   HashTable *ptrTable;
   ErrInfo *info;
   ErrInfo *oldInfo;
   Err_Number oldErrno = Err_Errno();

   ASSERT(errorNumber != ERR_INVALID);

   /*
    * Look up the error in numTable.
    * Or insert it if it's not there.
    */

   numTable = NUMTABLE();
   if (!HashTable_Lookup(numTable, (void *) (uintptr_t) errorNumber,
			 (void **) &info)) {
      char buf[2048];
      const char *p;
      size_t n;

      /*
       * Convert number to string and build the info structure.
       */

      p = ErrErrno2String(errorNumber, buf, sizeof buf);

      info = Util_SafeMalloc(sizeof *info);
      info->number = errorNumber;
      info->string = Util_SafeStrdup(p);

      /*
       * To be safe, make sure the end of the string is at
       * a UTF-8 boundary, but we can only do this when the
       * string is in our buffer (it may not be).
       */

      n = strlen(info->string);
      n = CodeSet_Utf8FindCodePointBoundary(info->string, n);
      info->string[n] = '\0';

      /*
       * Try to insert new info into numTable.
       * If that fails, then we must have lost out to someone else.
       * Use theirs in that case.
       */

      oldInfo = HashTable_LookupOrInsert(numTable,
				         (void *) (uintptr_t) errorNumber,
				         info);
      if (oldInfo != info) {
	 ASSERT(oldInfo->number == info->number);
	 ASSERT(Str_Strcmp(oldInfo->string, info->string) == 0);
	 free(info->string);
	 free(info);
	 info = oldInfo;
      }
   }

   /*
    * Try to insert info into ptrTable.
    * We need to do it even if we didn't create this entry,
    * because we may get here before the other guy (who created
    * the entry and inserted it into numTable).
    */

   ptrTable = PTRTABLE();
   oldInfo = HashTable_LookupOrInsert(ptrTable, info->string, info);
   ASSERT(oldInfo == info);

#if defined VMX86_DEBUG && defined __linux__
   {
      HashTable *strTable = STRTABLE();
      ErrInfo *i = HashTable_LookupOrInsert(strTable, info->string, info);
      ASSERT(i == info);
   }
#endif

   Err_SetErrno(oldErrno);
   return info->string;
}
示例#11
0
MXUserRWLock *
MXUser_CreateRWLock(const char *userName,  // IN:
                    MX_Rank rank)          // IN:
{
   Bool lockInited;
   char *properName;
   Bool useNative = MXUserNativeRWSupported();
   MXUserRWLock *lock = Util_SafeCalloc(1, sizeof *lock);

   if (userName == NULL) {
      if (LIKELY(useNative)) {
         properName = Str_SafeAsprintf(NULL, "RW-%p", GetReturnAddress());
      } else {
         /* emulated */
         properName = Str_SafeAsprintf(NULL, "RWemul-%p", GetReturnAddress());
      }
   } else {
      properName = Util_SafeStrdup(userName);
   }

   lock->header.signature = MXUserGetSignature(MXUSER_TYPE_RW);
   lock->header.name = properName;
   lock->header.rank = rank;
   lock->header.bits.serialNumber = MXUserAllocSerialNumber();
   lock->header.dumpFunc = MXUserDumpRWLock;

   /*
    * Always attempt to use native locks when they are available. If, for some
    * reason, a native lock should be available but isn't, fall back to using
    * an internal recursive lock - something is better than nothing.
    */

   lock->useNative = useNative && MXUserNativeRWInit(&lock->nativeLock);

   lockInited = MXRecLockInit(&lock->recursiveLock);

   if (LIKELY(lockInited)) {
      uint32 statsMode;

      lock->holderTable = HashTable_Alloc(256,
                                          HASH_INT_KEY | HASH_FLAG_ATOMIC,
                                          MXUserFreeHashEntry);

      statsMode = MXUserStatsMode();

      switch (MXUserStatsMode()) {
      case 0:
         MXUserDisableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
         lock->header.statsFunc = NULL;
         break;

      case 1:
         MXUserEnableStats(&lock->acquireStatsMem, NULL);
         lock->header.statsFunc = MXUserStatsActionRW;
         break;

      case 2:
         MXUserEnableStats(&lock->acquireStatsMem, &lock->heldStatsMem);
         lock->header.statsFunc = MXUserStatsActionRW;
         break;

      default:
         Panic("%s: unknown stats mode: %d!\n", __FUNCTION__, statsMode);
      }

      MXUserAddToList(&lock->header);
   } else {
      Panic("%s: native lock initialization routine failed\n", __FUNCTION__);
   }

   return lock;
}
示例#12
0
static HashTable *
SNEBuildHash(const char **compatEnviron)
                // IN: original "compatibility" environment
{
   HashTable *environTable;
   const char **p;

   /*
    * Number of buckets picked arbitrarily.  We're more interested in having an
    * associative array than raw table performance.
    */
   environTable = HashTable_Alloc(64, HASH_STRING_KEY | HASH_FLAG_COPYKEY, free);

   for (p = compatEnviron; p && *p; p++) {
      const size_t prefixLength = sizeof "VMWARE_" - 1;
      char *key;
      char *value;
      unsigned int index;

      index = 0;
      key = StrUtil_GetNextToken(&index, *p, "=");
      if (!key) {
         /* XXX Must empty environment variables still contain a '=' delimiter? */
         Debug("%s: Encountered environment entry without '='.\n", __func__);
         continue;
      }

      /*
       * Copy the value beginning after the '=' delimiter (even if it's empty).
       */
      ++index;
      value = Util_SafeStrdup(&(*p)[index]);

      if (StrUtil_StartsWith(key, "VMWARE_") &&
          key[prefixLength] != '\0' &&
          (value[0] == '0' || value[0] == '1')) {
         /*
          * Okay, this appears to be one of the wrapper's variables, so let's
          * figure out the original environment variable name (by just indexing
          * past the prefix) and value (by indexing past the "was this variable
          * in the native environment?" marker).
          *
          * XXX Should we move this marker to a separate header?
          */
         char *realKey = &key[prefixLength];
         char *realValue = (value[0] == '0')
                           ? NULL
                           : Util_SafeStrdup(&value[1]);
         HashTable_ReplaceOrInsert(environTable, realKey, realValue);
      } else {
         HashTable_LookupOrInsert(environTable, key, value);
      }

      /*
       * The hash table makes a copy of our key, and it takes ownership of inserted
       * values (via our passed freeing function).  So that means we're responsible
       * for freeing 'key', but -not- 'value'.
       */
      free(key);
   }

   return environTable;
}
示例#13
0
Bool
FileIO_AtomicUpdate(FileIODescriptor *newFD,   // IN/OUT: file IO descriptor
                    FileIODescriptor *currFD)  // IN/OUT: file IO descriptor
{
   char *currPath = NULL;
   char *newPath = NULL;
#if defined(_WIN32)
   uint32 currAccess;
   uint32 newAccess;
   FileIOResult status;
   FileIODescriptor tmpFD;
#else
   int fd;
#endif
   int savedErrno = 0;
   Bool ret = FALSE;

   ASSERT(FileIO_IsValid(newFD));
   ASSERT(FileIO_IsValid(currFD));

   if (HostType_OSIsVMK()) {
#if defined(VMX86_SERVER)
      FS_SwapFilesArgs *args = NULL;
      char *dirName = NULL;
      char *fileName = NULL;
      char *dstDirName = NULL;
      char *dstFileName = NULL;

      currPath = File_FullPath(FileIO_Filename(currFD));
      if (!currPath) {
         savedErrno = errno;
         Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__,
             FileIO_Filename(currFD));
         goto swapdone;
      }

      newPath = File_FullPath(FileIO_Filename(newFD));
      if (!newPath) {
         savedErrno = errno;
         Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__,
             FileIO_Filename(newFD));
         goto swapdone;
      }

      File_GetPathName(newPath, &dirName, &fileName);
      File_GetPathName(currPath, &dstDirName, &dstFileName);

      ASSERT(dirName);
      ASSERT(fileName && *fileName);
      ASSERT(dstDirName);
      ASSERT(dstFileName && *dstFileName);
      ASSERT(File_IsSameFile(dirName, dstDirName));

      args = Util_SafeCalloc(1, sizeof *args);
      if (Str_Snprintf(args->srcFile, sizeof args->srcFile, "%s",
                       fileName) < 0) {
         Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName);
         savedErrno = ENAMETOOLONG;
         goto swapdone;
      }
      if (Str_Snprintf(args->dstFilePath, sizeof args->dstFilePath, "%s/%s",
                       dstDirName, dstFileName) < 0) {
         Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName);
         savedErrno = ENAMETOOLONG;
         goto swapdone;
      }

      /*
       * Issue the ioctl on the directory rather than on the file,
       * because the file could be open.
       */

      if (!*dirName) {
         /* need a proper root directory string for Posix_Open() */
         free(dirName);
         dirName = Util_SafeStrdup("/");
      }

      fd = Posix_Open(dirName, O_RDONLY);
      if (fd < 0) {
         Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName, errno);
         ASSERT(errno != EBUSY);   /* #615124. */
         savedErrno = errno;
         goto swapdone;
      }

      if (ioctl(fd, IOCTLCMD_VMFS_SWAP_FILES, args) != 0) {
         savedErrno = errno;
         if (errno != ENOSYS && errno != ENOTTY) {
            Log("%s: ioctl failed %d.\n", __FUNCTION__, errno);
            ASSERT(errno != EBUSY);   /* #615124. */
         }
      } else {
         ret = TRUE;
      }

      close(fd);

      /*
       * Did we fail because we are on a file system that does not
       * support the IOCTLCMD_VMFS_SWAP_FILES ioctl? If so fallback to
       * using rename.
       *
       * Check for both ENOSYS and ENOTTY. PR 957695
       */
      if (savedErrno == ENOSYS || savedErrno == ENOTTY) {
         /*
          * NFS allows renames of locked files, even if both files
          * are locked.  The file lock follows the file handle, not
          * the name, so after the rename we can swap the underlying
          * file descriptors instead of closing and reopening the
          * target file.
          *
          * This is different than the hosted path below because
          * ESX uses native file locks and hosted does not.
          *
          * We assume that all ESX file systems that support rename
          * have the same file lock semantics as NFS.
          */

         if (File_Rename(newPath, currPath)) {
            Log("%s: rename of '%s' to '%s' failed %d.\n",
                __FUNCTION__, newPath, currPath, errno);
            savedErrno = errno;
            goto swapdone;
         }
         ret = TRUE;
         fd = newFD->posix;
         newFD->posix = currFD->posix;
         currFD->posix = fd;
         FileIO_Close(newFD);
      }

swapdone:
      free(args);
      free(dirName);
      free(fileName);
      free(dstDirName);
      free(dstFileName);
      free(currPath);
      free(newPath);

      errno = savedErrno;
      return ret;
#else
      NOT_REACHED();
#endif
   }
#if defined(_WIN32)
   currPath = Unicode_Duplicate(FileIO_Filename(currFD));
   newPath = Unicode_Duplicate(FileIO_Filename(newFD));

   newAccess = newFD->flags;
   currAccess = currFD->flags;

   FileIO_Close(newFD);

   /*
    * The current file needs to be closed and reopened,
    * but we don't want to drop the file lock by calling
    * FileIO_Close() on it.  Instead, use native close primitives.
    * We'll reopen it later with FileIO_Open.  Set the
    * descriptor/handle to an invalid value while we're in the
    * middle of transferring ownership.
    */

   CloseHandle(currFD->win32);
   currFD->win32 = INVALID_HANDLE_VALUE;
   if (File_RenameRetry(newPath, currPath, 10) == 0) {
      ret = TRUE;
   } else {
      savedErrno = errno;
      ASSERT(!ret);
   }

   FileIO_Invalidate(&tmpFD);

   /*
    * Clear the locking bits from the requested access so that reopening
    * the file ignores the advisory lock.
    */

   ASSERT((currAccess & FILEIO_OPEN_LOCK_MANDATORY) == 0);
   currAccess &= ~(FILEIO_OPEN_LOCK_MANDATORY | FILEIO_OPEN_LOCK_ADVISORY |
                   FILEIO_OPEN_LOCK_BEST | FILEIO_OPEN_LOCKED);
   status = FileIO_Open(&tmpFD, currPath, currAccess, FILEIO_OPEN);
   if (!FileIO_IsSuccess(status)) {
      Panic("Failed to reopen dictionary after renaming "
            "\"%s\" to \"%s\": %s (%d)\n", newPath, currPath,
            FileIO_ErrorEnglish(status), status);
   }
   ASSERT(tmpFD.lockToken == NULL);

   currFD->win32 = tmpFD.win32;

   FileIO_Cleanup(&tmpFD);
   free(currPath);
   free(newPath);
   errno = savedErrno;

   return ret;
#else
   currPath = (char *)FileIO_Filename(currFD);
   newPath = (char *)FileIO_Filename(newFD);

   if (File_Rename(newPath, currPath)) {
      Log("%s: rename of '%s' to '%s' failed %d.\n",
          __FUNCTION__, newPath, currPath, errno);
          savedErrno = errno;
   } else {
      ret = TRUE;
      fd = newFD->posix;
      newFD->posix = currFD->posix;
      currFD->posix = fd;
      FileIO_Close(newFD);
   }

   errno = savedErrno;

   return ret;
#endif
}
char *
Unicode_Duplicate(const char *str) // IN
{
   return Util_SafeStrdup(str);
}
示例#15
0
void
VMTools_BindTextDomain(const char *domain,
                       const char *lang,
                       const char *catdir)
{
   char *dfltdir = NULL;
   gchar *file;
   gchar *usrlang = NULL;
   MsgState *state = MsgGetState();
   MsgCatalog *catalog;

   ASSERT(domain);

   /*
    * If the caller has asked for the default user language, detect it and
    * translate to our internal language string representation.
    */

   if (lang == NULL || *lang == '\0') {
      usrlang = MsgGetUserLanguage();
      lang = usrlang;
   }

   g_debug("%s: user locale=%s\n", __FUNCTION__, lang);

   /*
    * Use the default install directory if none is provided.
    */

   if (catdir == NULL) {
#if defined(OPEN_VM_TOOLS)
      dfltdir = Util_SafeStrdup(VMTOOLS_DATA_DIR);
#else
      dfltdir = GuestApp_GetInstallPath();
#endif
      catdir = (dfltdir) ? dfltdir : ".";
   }

   file = g_strdup_printf("%s%smessages%s%s%s%s.vmsg",
                          catdir, DIRSEPS, DIRSEPS, lang, DIRSEPS, domain);

   if (!File_IsFile(file)) {
      /*
       * If we couldn't find the catalog file for the user's language, see if
       * we can find a more generic language (e.g., for "en_US", also try "en").
       */
      char *sep = Str_Strrchr(lang, '_');
      if (sep != NULL) {
         if (usrlang == NULL) {
            usrlang = Util_SafeStrdup(lang);
         }
         usrlang[sep - lang] = '\0';
         g_free(file);
         file = g_strdup_printf("%s%smessages%s%s%s%s.vmsg",
                                catdir, DIRSEPS, DIRSEPS, usrlang, DIRSEPS, domain);
      }
   }

   catalog = MsgLoadCatalog(file);

   if (catalog == NULL) {
      if (Str_Strncmp(lang, "en", 2)) {
         /*
          * Don't warn about english dictionary, which may not exist (it is the
          * default translation).
          */
         g_message("Cannot load message catalog for domain '%s', language '%s', "
                   "catalog dir '%s'.\n", domain, lang, catdir);
      }
   } else {
      g_static_mutex_lock(&state->lock);
      MsgSetCatalog(domain, catalog);
      g_static_mutex_unlock(&state->lock);
   }
   g_free(file);
   free(dfltdir);
   g_free(usrlang);
}
示例#16
0
VmBackupOp *
VmBackup_NewScriptOp(VmBackupScriptType type, // IN
                     VmBackupState *state)    // IN
{
   Bool fail = FALSE;
   char **fileList = NULL;
   char *scriptDir = NULL;
   int numFiles = 0;
   size_t i;
   VmBackupScriptOp *op = NULL;

   scriptDir = VmBackupGetScriptPath();
   if (scriptDir == NULL) {
      goto exit;
   }

   op = calloc(1, sizeof *op);
   if (op == NULL) {
      goto exit;
   }

   op->state = state;
   op->type = type;
   op->callbacks.queryFn = VmBackupScriptOpQuery;
   op->callbacks.cancelFn = VmBackupScriptOpCancel;
   op->callbacks.releaseFn = VmBackupScriptOpRelease;

   g_debug("Trying to run scripts from %s\n", scriptDir);

   /*
    * Load the list of scripts to run when freezing. The same list will be
    * used later in case of failure, or when thawing, in reverse order.
    *
    * This logic won't recurse into directories, so only files directly under
    * the script dir will be considered.
    *
    * Legacy scripts will be the first ones to run (or last ones in the
    * case of thawing). If either the legacy freeze or thaw script
    * exist, the first entry in the script list will be reserved for
    * them, and their path might not exist (in case, for example, the
    * freeze script exists but the thaw script doesn't).
    */
   if (type == VMBACKUP_SCRIPT_FREEZE) {
      VmBackupScript *scripts = NULL;
      int legacy = 0;
      size_t idx = 0;

      state->scripts = NULL;
      state->currentScript = 0;

      if (File_IsFile(LEGACY_FREEZE_SCRIPT) ||
          File_IsFile(LEGACY_THAW_SCRIPT)) {
         legacy = 1;
      }

      if (File_IsDirectory(scriptDir)) {
         numFiles = File_ListDirectory(scriptDir, &fileList);
      }

      if (numFiles + legacy > 0) {
         scripts = calloc(numFiles + legacy + 1, sizeof *scripts);
         if (scripts == NULL) {
            fail = TRUE;
            goto exit;
         }

         /*
          * VmBackupRunNextScript increments the index, so need to make it point
          * to "before the first script".
          */
         state->currentScript = -1;
         state->scripts = scripts;
      }

      if (legacy > 0) {
         scripts[idx++].path = Util_SafeStrdup(LEGACY_FREEZE_SCRIPT);
      }

      if (numFiles > 0) {
         size_t i;

         if (numFiles > 1) {
            qsort(fileList, (size_t) numFiles, sizeof *fileList, VmBackupStringCompare);
         }

         for (i = 0; i < numFiles; i++) {
            char *script;

            script = Str_Asprintf(NULL, "%s%c%s", scriptDir, DIRSEPC, fileList[i]);
            if (script == NULL) {
               fail = TRUE;
               goto exit;
            } else if (File_IsFile(script)) {
               scripts[idx++].path = script;
            } else {
               free(script);
            }
         }
      }
   } else if (state->scripts != NULL) {
      VmBackupScript *scripts = state->scripts;
      if (strcmp(scripts[0].path, LEGACY_FREEZE_SCRIPT) == 0) {
         vm_free(scripts[0].path);
         scripts[0].path = Util_SafeStrdup(LEGACY_THAW_SCRIPT);
      }
   }

   /*
    * If there are any scripts to be executed, start the first one. If we get to
    * this point, we won't free the scripts array until VmBackupScriptOpRelease
    * is called after thawing (or after the sync provider failed and the "fail"
    * scripts are run).
    */
   fail = (state->scripts != NULL && VmBackupRunNextScript(op) == -1);

exit:
   /* Free the file list. */
   for (i = 0; i < numFiles; i++) {
      free(fileList[i]);
   }
   free(fileList);

   if (fail && op != NULL) {
      VmBackup_Release((VmBackupOp *) op);
      op = NULL;
   }
   free(scriptDir);
   return (VmBackupOp *) op;
}