Exemplo n.º 1
0
char *
Unicode_ReplaceRange(const char *dest,         // IN:
                     UnicodeIndex destStart,   // IN:
                     UnicodeIndex destLength,  // IN:
                     const char *src,          // IN:
                     UnicodeIndex srcStart,    // IN:
                     UnicodeIndex srcLength)   // IN:
{
   char *result;
   char *stringOne;
   char *stringTwo;
   char *stringThree;

   ASSERT(dest);
   ASSERT((destStart >= 0) || (destStart == -1));
   ASSERT((destLength >= 0) || (destLength == -1));

   ASSERT(src);
   ASSERT((srcStart >= 0) || (srcStart == -1));
   ASSERT((srcLength >= 0) || (srcLength == -1));

   stringOne = Unicode_Substr(dest, 0, destStart);
   stringTwo = Unicode_Substr(src, srcStart, srcLength);
   stringThree = Unicode_Substr(dest, destStart + destLength, -1);

   result = Unicode_Join(stringOne, stringTwo, stringThree, NULL);

   free(stringOne);
   free(stringTwo);
   free(stringThree);

   return result;
}
static int
RemoveLockingFile(ConstUnicode lockDir,   // IN:
                  ConstUnicode fileName)  // IN:
{
   int err;
   Unicode path;

   ASSERT(lockDir);
   ASSERT(fileName);

   path = Unicode_Join(lockDir, DIRSEPS, fileName, NULL);

   err = FileDeletionRobust(path, FALSE);

   if (err != 0) {
      if (err == ENOENT) {
         /* Not there anymore; locker unlocked or timed out */
         err = 0;
      } else {
         Warning(LGPFX" %s of '%s' failed: %s\n", __FUNCTION__,
                 UTF8(path), strerror(err));
      }
   }

   Unicode_Free(path);

   return err;
}
Exemplo n.º 3
0
Unicode
File_PathJoin(ConstUnicode dirName,   // IN:
              ConstUnicode baseName)  // IN: See above.
{
   Unicode result;
   Unicode newDir = NULL;

   ASSERT(dirName);
   ASSERT(baseName);

   /*
    * Remove ALL directory separators from baseName begin.
    */
#if defined(_WIN32)
   {
      ConstUnicode oldBaseName = baseName;

      /*
       * Reject drive letters in baseName.
       */
      ASSERT(Unicode_LengthInCodePoints(baseName) < 2 ||
             Unicode_FindSubstrInRange(baseName, 1, 1, ":", 0, 1) ==
             UNICODE_INDEX_NOT_FOUND);

      while (*baseName == '/' || *baseName == '\\') {
         baseName++;
      }

      /*
       * Reject UNC paths for baseName.
       */
      ASSERT(baseName - oldBaseName < 2);
   }
#else
   while (*baseName == '/') {
      baseName++;
   }
#endif

   /*
    * Remove ALL directory separators from dirName end.
    */
   newDir = File_StripSlashes(dirName);

   result = Unicode_Join(newDir, DIRSEPS, baseName, NULL);
   Unicode_Free(newDir);

   return result;
}
Exemplo n.º 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;
}
Exemplo n.º 5
0
Unicode
FileIO_AtomicTempPath(ConstUnicode path)  // IN:
{
    Unicode srcPath;
    Unicode retPath;

    srcPath = File_FullPath(path);
    if (!srcPath) {
        Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, path);
        return NULL;
    }
    retPath = Unicode_Join(srcPath, "~", NULL);
    Unicode_Free(srcPath);

    return retPath;
}
Exemplo n.º 6
0
char *
FileIO_AtomicTempPath(const char *path)  // IN:
{
   char *srcPath;
   char *retPath;

   srcPath = File_FullPath(path);
   if (!srcPath) {
      Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__, path);
      return NULL;
   }
   retPath = Unicode_Join(srcPath, "~", NULL);
   free(srcPath);

   return retPath;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
Unicode
File_StripSlashes(ConstUnicode path)  // IN:
{
   Unicode result, volume, dir, base;

   /*
    * SplitName handles all drive letter/UNC/whatever cases, all we
    * have to do is make sure the dir part is stripped of slashes if
    * there isn't a base part.
    */

   File_SplitName(path, &volume, &dir, &base);

   if (!Unicode_IsEmpty(dir) && Unicode_IsEmpty(base)) {
      char *dir2 = Unicode_GetAllocBytes(dir, STRING_ENCODING_UTF8);
      size_t i = strlen(dir2);

      /*
       * Don't strip first slash on Windows, since we want at least
       * one slash to trail a drive letter/colon or UNC specifier.
       */

#if defined(_WIN32)
      while ((i > 1) && (('/' == dir2[i - 1]) ||
                         ('\\' == dir2[i - 1]))) {
#else
      while ((i > 0) && ('/' == dir2[i - 1])) {
#endif
         i--;
      }

      Unicode_Free(dir);
      dir = Unicode_AllocWithLength(dir2, i, STRING_ENCODING_UTF8);
      free(dir2);
   }

   result = Unicode_Join(volume, dir, base, NULL);

   Unicode_Free(volume);
   Unicode_Free(dir);
   Unicode_Free(base);

   return result;
}


/*
 *-----------------------------------------------------------------------------
 *
 * File_MapPathPrefix --
 *
 *      Given a path and a newPrefix -> oldPrefix mapping, transform
 *      oldPath according to the mapping.
 *
 * Results:
 *      The new path, or NULL if there is no mapping.
 *
 * Side effects:
 *      The returned string is allocated, free it.
 *
 *-----------------------------------------------------------------------------
 */

char *
File_MapPathPrefix(const char *oldPath,       // IN:
                   const char **oldPrefixes,  // IN:
                   const char **newPrefixes,  // IN:
                   size_t numPrefixes)        // IN:
{
   int i;
   size_t oldPathLen = strlen(oldPath);

   for (i = 0; i < numPrefixes; i++) {
      char *newPath;
      char *oldPrefix;
      char *newPrefix;
      size_t oldPrefixLen;

      oldPrefix = File_StripSlashes(oldPrefixes[i]);
      newPrefix = File_StripSlashes(newPrefixes[i]);
      oldPrefixLen = strlen(oldPrefix);

      /*
       * If the prefix matches on a DIRSEPS boundary, or the prefix is the
       * whole string, replace it.
       *
       * If we don't insist on matching a whole directory name, we could
       * mess things of if one directory is a substring of another.
       *
       * Perform a case-insensitive compare on Windows. (There are
       * case-insensitive filesystems on MacOS also, but the problem
       * is more acute with Windows because of frequent drive-letter
       * case mismatches. So in lieu of actually asking the
       * filesystem, let's just go with a simple ifdef for now.)
       */

      if ((oldPathLen >= oldPrefixLen) &&
#ifdef _WIN32
          (Str_Strncasecmp(oldPath, oldPrefix, oldPrefixLen) == 0) &&
#else
          (Str_Strncmp(oldPath, oldPrefix, oldPrefixLen) == 0) &&
#endif
          (strchr(VALID_DIRSEPS, oldPath[oldPrefixLen]) ||
              (oldPath[oldPrefixLen] == '\0'))) {
         size_t newPrefixLen = strlen(newPrefix);
         size_t newPathLen = (oldPathLen - oldPrefixLen) + newPrefixLen;

         ASSERT(newPathLen > 0);
         ASSERT(oldPathLen >= oldPrefixLen);

         newPath = Util_SafeMalloc((newPathLen + 1) * sizeof(char));
         memcpy(newPath, newPrefix, newPrefixLen);
         memcpy(newPath + newPrefixLen, oldPath + oldPrefixLen,
                oldPathLen - oldPrefixLen + 1);
         /*
          * It should only match once.  Weird self-referencing mappings
          * aren't allowed.
          */

         free(oldPrefix);
         free(newPrefix);

         return newPath;
      }
      free(oldPrefix);
      free(newPrefix);
   }

   return NULL;
}
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;
}
int
FileLockMemberValues(ConstUnicode lockDir,      // IN:
                     ConstUnicode fileName,     // IN:
                     char *buffer,              // OUT:
                     uint32 requiredSize,       // IN:
                     LockValues *memberValues)  // OUT:
{
#ifndef __MINGW32__
   uint32 argc = 0;
   FILELOCK_FILE_HANDLE handle;
   uint32 len;
   char *argv[FL_MAX_ARGS];
   char *saveptr = NULL;
   int err;
   Unicode path;
   FileData fileData;

   ParseTable table = { PARSE_TABLE_STRING,
                        "lc",
                        (void *) &memberValues->locationChecksum
                      };
 
   ASSERT(lockDir);
   ASSERT(fileName);

   path = Unicode_Join(lockDir, DIRSEPS, fileName, NULL);

   err = FileLockOpenFile(path, O_RDONLY, &handle);

   if (err != 0) {
      /*
       * A member file may "disappear" if is deleted due to an unlock
       * immediately after a directory scan but before the scan is processed.
       * Since this is a "normal" thing ENOENT will be suppressed.
       */

      if (err != ENOENT) {
         Warning(LGPFX" %s open failure on '%s': %s\n", __FUNCTION__,
                 UTF8(path), strerror(err));
      }

      goto bail;
   }

   /* Attempt to obtain the lock file attributes now that it is opened */
   err = FileAttributesRobust(path, &fileData);

   if (err != 0) {
      Warning(LGPFX" %s file size failure on '%s': %s\n", __FUNCTION__,
              UTF8(path), strerror(err));

      FileLockCloseFile(handle);

      goto bail;
   }

   /* Complain if the lock file is not the proper size */
   if (fileData.fileSize != requiredSize) {
      Warning(LGPFX" %s file '%s': size %"FMT64"u, required size %u\n",
              __FUNCTION__, UTF8(path), fileData.fileSize, requiredSize);

      FileLockCloseFile(handle);

      goto corrupt;
   }

   /* Attempt to read the lock file data and validate how much was read. */
   err = FileLockReadFile(handle, buffer, requiredSize, &len);

   FileLockCloseFile(handle);

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

      goto bail;
   }

   if (len != requiredSize) {
      Warning(LGPFX" %s read length issue on '%s': %u and %u\n",
              __FUNCTION__, UTF8(path), len, requiredSize);

      err = EIO;
      goto bail;
   }

   /* Extract and validate the lock file data. */
   for (argc = 0; argc < FL_MAX_ARGS; argc++) {
      argv[argc] = strtok_r((argc == 0) ? buffer : NULL, " ", &saveptr);

      if (argv[argc] == NULL) {
         break;
      }
   }

   if ((argc < 4) || ((argc == FL_MAX_ARGS) &&
                       (strtok_r(NULL, " ", &saveptr) != NULL))) {
      goto corrupt;
   }

   /*
    * Lock file arguments are space separated. There is a minimum of 4
    * arguments - machineID, executionID, Lamport number and lock type.
    * The maximum number of arguments is FL_MAX_ARGS.
    *
    * The fifth argument, if present, is the payload or "[" if there is no
    * payload and additional arguments are present. The additional arguments
    * form  a properly list - one or more "name=value" pairs.
    *
    * Here is picture of valid forms:
    *
    * 0 1 2 3 4 5 6   Comment
    *-------------------------
    * A B C D         contents, no payload, no list entries
    * A B C D [       contents, no payload, no list entries
    * A B C D P       contents, a payload,  no list entries
    * A B C D [ x     contents, no payload, one list entry
    * A B C D P x     contents, a payload,  one list entry
    * A B C D [ x y   contents, no payload, two list entries
    * A B C D P x y   contents, a payload,  two list entries
    */

   memberValues->locationChecksum = NULL;

   if (argc == 4) {
      memberValues->payload = NULL;
   } else {
      if (strcmp(argv[4], "[") == 0) {
         memberValues->payload = NULL;
      } else {
         memberValues->payload = argv[4];
      }

      if (FileLockParseArgs(argv, argc - 5, &table, 1)) {
         goto corrupt;
      }
   }

   if (sscanf(argv[2], "%u", &memberValues->lamportNumber) != 1) {
      goto corrupt;
   }

   if ((strcmp(argv[3], LOCK_SHARED) != 0) &&
       (strcmp(argv[3], LOCK_EXCLUSIVE) != 0)) {
      goto corrupt;
   }

   memberValues->machineID = argv[0];
   memberValues->executionID = argv[1];
   memberValues->lockType = argv[3];
   memberValues->memberName = Unicode_Duplicate(fileName);

   Unicode_Free(path);

   return 0;

corrupt:
   Warning(LGPFX" %s removing problematic lock file '%s'\n", __FUNCTION__,
           UTF8(path));

   if (argc) {
      Log(LGPFX" %s '%s' contents are:\n", __FUNCTION__, UTF8(fileName));

      for (len = 0; len < argc; len++) {
         Log(LGPFX" %s %s argv[%d]: '%s'\n", __FUNCTION__, UTF8(fileName),
             len, argv[len]);
      }
   }

   /* Remove the lock file and behave like it has disappeared */
   err = FileDeletionRobust(path, FALSE);

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

bail:
   Unicode_Free(path);

   return err;
#else
   // XXX - incomplete: needs a win/mingw32 implementation, if required.
   NOT_IMPLEMENTED();
   return 0;
#endif
}
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;
}
static int
WaitForPossession(ConstUnicode lockDir,      // IN:
                  ConstUnicode fileName,     // IN:
                  LockValues *memberValues,  // IN:
                  LockValues *myValues)      // IN:
{
   int err = 0;

   ASSERT(lockDir);
   ASSERT(fileName);

   /* "Win" or wait? */
   if (((memberValues->lamportNumber < myValues->lamportNumber) ||
       ((memberValues->lamportNumber == myValues->lamportNumber) &&
          (Unicode_Compare(memberValues->memberName,
                           myValues->memberName) < 0))) &&
        ((strcmp(memberValues->lockType, LOCK_EXCLUSIVE) == 0) ||
         (strcmp(myValues->lockType, LOCK_EXCLUSIVE) == 0))) {
      Unicode path;
      uint32 loopCount;
      Bool   thisMachine; 

      thisMachine = FileLockMachineIDMatch(myValues->machineID,
                                           memberValues->machineID);

      loopCount = 0;

      path = Unicode_Join(lockDir, DIRSEPS, fileName, NULL);

      while ((err = Sleeper(myValues, &loopCount)) == 0) {
         /* still there? */
         err = FileAttributesRobust(path, NULL);
         if (err != 0) {
            if (err == ENOENT) {
               /* Not there anymore; locker unlocked or timed out */
               err = 0;
            }

            break;
         }

         /* still valid? */
         if (thisMachine && !FileLockValidOwner(memberValues->executionID,
                                                memberValues->payload)) {
            /* Invalid Execution ID; remove the member file */
            Warning(LGPFX" %s discarding file '%s'; invalid executionID.\n",
                    __FUNCTION__, UTF8(path));

            err = RemoveLockingFile(lockDir, fileName);
            break;
         }
      }

      /*
       * Log the disposition of each timeout for all non "try lock" locking
       * attempts. This can assist in debugging locking problems.
       */

      if ((myValues->msecMaxWaitTime != FILELOCK_TRYLOCK_WAIT) &&
          (err == EAGAIN)) {
         if (thisMachine) {
            Log(LGPFX" %s timeout on '%s' due to a local process (%s)\n",
                    __FUNCTION__, UTF8(path), memberValues->executionID);
         } else {
            Log(LGPFX" %s timeout on '%s' due to another machine (%s)\n",
                    __FUNCTION__, UTF8(path), memberValues->machineID);
         }
      }

      Unicode_Free(path);
   }

   return err;
}
Exemplo n.º 13
0
int
File_MakeTempEx2(ConstUnicode dir,                             // IN:
                 Bool createTempFile,                          // IN:
                 File_MakeTempCreateNameFunc *createNameFunc,  // IN:
                 void *createNameFuncData,                     // IN:
                 Unicode *presult)                             // OUT:
{
   uint32 i;

   int fd = -1;
   uint32 var = 0;
   Unicode path = NULL;

   if ((dir == NULL) || (createNameFunc == NULL)) {
      errno = EFAULT;

      return -1;
   }

   ASSERT(presult);

   *presult = NULL;

   for (i = 0; i < (MAX_INT32 / 2); i++) {
      Unicode fileName;

      /* construct suffixed pathname to use */
      Unicode_Free(path);
      path = NULL;

      /*
       * Files and directories are kept separate (odd and even respectfully).
       * This way the available exclusion mechanisms work properly - O_EXCL
       * on files, mkdir on directories - and races are avoided.
       *
       * Not attempting an open on a directory is a good thing...
       */

      FileTempNum(createTempFile, &var);

      fileName = (*createNameFunc)(var, createNameFuncData);
      ASSERT(fileName);

      /* construct base full pathname to use */
      path = Unicode_Join(dir, DIRSEPS, fileName, NULL);

      Unicode_Free(fileName);

      if (createTempFile) {
         fd = Posix_Open(path, O_CREAT | O_EXCL | O_BINARY | O_RDWR, 0600);
      } else {
         fd = Posix_Mkdir(path, 0700);
      }

      if (fd != -1) {
         *presult = path;
         path = NULL;
         break;
      }

      if (errno != EEXIST) {
         Log(LGPFX" Failed to create temporary %s \"%s\": %s.\n",
             createTempFile ? "file" : "directory",
             UTF8(path), strerror(errno));
         goto exit;
      }
   }

   if (fd == -1) {
      Warning(LGPFX" Failed to create temporary %s \"%s\": "
              "The name space is full.\n",
              createTempFile ? "file" : "directory", UTF8(path));

      errno = EAGAIN;
   }

  exit:
   Unicode_Free(path);

   return fd;
}