~n-muench/ubuntu/precise/open-vm-tools/open-vm-tools.raring-precise.backport

« back to all changes in this revision

Viewing changes to lib/file/fileIO.c

  • Committer: Package Import Robot
  • Author(s): Nate Muench
  • Date: 2012-01-23 16:09:45 UTC
  • mfrom: (1.4.6) (2.4.26 sid)
  • Revision ID: package-import@ubuntu.com-20120123160945-b6s0r1vkcovucpf3
Tags: 2011.12.20-562307-0ubuntu1
* Merge latest upstream git tag. Fixes building on Precise
  (LP: #898289, LP: #905612)

* Items merged from Debian unstable:
  - debian/control:
    + open-vm-tools recommends open-vm-dkms. (LP: #598933)
    + open-vm-tools now suggests open-vm-toolbox. (LP: #604998)
  (From 2011.08.21-471295-1 release)
  - Updating maintainer and uploaders fields.
  - Removing vcs fields.
  - Removing references to Daniel's old email address.
  - Updating years in copyright file.
  - Updating to standards version 3.9.2.
  - Updating to debhelper version 8.
  - Switching to source format 3.0 (quilt).
  - Removing manual chrpath setting.
  - Removing exclusion from plugins from debhelper shlibs.
  - Rediffing kvers.patch.
  (From 2011.09.23-491607-1 release)
  - Marking binary architecture-dependend packages as linux and kfreebsd
  only.
  - Removing liburiparser-dev from build-depends as upstream dropped
  unity support.
  - Building with libproc-dev on amd64 again.
  - Dropping disabling of dnet support.
  (From 2011.09.23-491607-2 release)
  - Adding doxygen to build-depends for api documentation.
  - Adding libcunit1-dev to build-depends for test suites.
  - Minimizing rules file.
  - Adding open-vm-tools-dev package, containing only the api
    documentation for now.
  (From 2011.09.23-491607-3 release)
  - Sorting overrides in rules alphabetically.
  - Compacting copyright file.
  - Adding udev rule to set timeout for vmware scsi devices
  (From 2011.12.20-562307-1 release)
  - Adding patch to correct typo in upstreams dkms configuration

* Remaining Changes:
  - Remove Stable part of version numbering.
  - debian folder:
    + Re-added open-vm-dkms.postinst & open-vm-dkms.prerm.
      * Allows dkms modules to compile upon installation.
  - debian/control:
    + Re-add open-vm-source and make into a transitional package
      for open-vm-toolbox.
    + Return dependancies that were moved to open-vm-tools back to
      open-vm-toolbox.
  - debian/rules and debian/open-vm-toolbox.lintian-overrides:
    + Make vmware-user-suid-wrapper suid-root
  - debian/rules:
    + Added CFLAGS field with -Wno-deprecated-declarations
      * Will suppress issues with glib 2.31 or later.
    + Add line to copy vmware-xdg-detect-de into place.
    + Install vmware-user.desktop through toolbox package.
  - debian/open-vm-tools.init:
    + Re-add 'modprobe [-r] vmblock'.
    + Add 'modprobe [-r] vmxnet'.
      * Incase it's not loaded during boot.
    + Remove and re-add pcnet32 module
      * Will be done before (remove) and after (readd) vmxnet module
        is added.
      * If vmxnet doesn't exist (aka modules fail to build), pcnet32 can be
        still used for network connectivity.
      * Workaround until a better fix can be done.
  - Re-add gnome-session to debian/local/xautostart.conf
  - Manpages removed (from debian/manpages):
    + vmmemctl.9
    + vmxnet3.9
    + Remove references to manpages that have been removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
37
37
#include "fileInt.h"
38
38
#include "msg.h"
39
39
#include "unicodeOperations.h"
 
40
#include "hostType.h"
 
41
#if defined(_WIN32)
 
42
#include <io.h>
 
43
#else
 
44
#include <fcntl.h>
 
45
#include <sys/ioctl.h>
 
46
#include <sys/types.h>
 
47
#include <sys/stat.h>
 
48
#include <unistd.h>
 
49
#endif
 
50
#if defined(VMX86_SERVER)
 
51
#include "fs_public.h"
 
52
#endif
40
53
 
41
54
 
42
55
/*
227
240
/*
228
241
 *----------------------------------------------------------------------
229
242
 *
 
243
 * FileIOResolveLockBits --
 
244
 *
 
245
 *      Resolve the multitude of lock bits from historical public names
 
246
 *      to newer internal names.
 
247
 *
 
248
 *      Input flags: FILEIO_OPEN_LOCKED a.k.a. FILEIO_OPEN_LOCK_BEST,
 
249
 *                   FILEIO_OPEN_EXCLUSIVE_LOCK
 
250
 *      Output flags: FILEIO_OPEN_LOCK_MANDATORY, FILEIO_OPEN_LOCK_ADVISORY
 
251
 *
 
252
 * Results:
 
253
 *      None
 
254
 *
 
255
 * Side effects:
 
256
 *      Only output flags are set in *access.
 
257
 *
 
258
 *----------------------------------------------------------------------
 
259
 */
 
260
 
 
261
void
 
262
FileIOResolveLockBits(int *access)  // IN/OUT: FILEIO_OPEN_* bits
 
263
{
 
264
   /*
 
265
    * Lock types:
 
266
    *    none: no locking at all
 
267
    *    advisory: open() ignores lock, FileIO_ respects lock.
 
268
    *    mandatory: open() and FileIO_ respect lock.
 
269
    *    "best": downgrades to advisory or mandatory based on OS support
 
270
    */
 
271
   if ((*access & FILEIO_OPEN_EXCLUSIVE_LOCK) != 0) {
 
272
      *access &= ~FILEIO_OPEN_EXCLUSIVE_LOCK;
 
273
      *access |= FILEIO_OPEN_LOCK_MANDATORY;
 
274
   }
 
275
   if ((*access & FILEIO_OPEN_LOCK_BEST) != 0) {
 
276
      /* "Best effort" bit: mandatory if OS supports, advisory otherwise */
 
277
      *access &= ~FILEIO_OPEN_LOCK_BEST;
 
278
      if (HostType_OSIsVMK()) {
 
279
         *access |= FILEIO_OPEN_LOCK_MANDATORY;
 
280
      } else {
 
281
         *access |= FILEIO_OPEN_LOCK_ADVISORY;
 
282
      }
 
283
   }
 
284
 
 
285
   /* Only one lock type (or none at all) allowed */
 
286
   ASSERT(((*access & FILEIO_OPEN_LOCK_ADVISORY) == 0) ||
 
287
          ((*access & FILEIO_OPEN_LOCK_MANDATORY) == 0));
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
 *----------------------------------------------------------------------
 
293
 *
230
294
 * FileIO_Lock --
231
295
 *
232
296
 *      Call the FileLock module to lock the given file.
233
297
 *
234
298
 * Results:
235
 
 *      FILEIO_SUCCESS      All is well
236
 
 *      FILEIO_LOCK_FAILED  Requested lock on file was not acquired
237
 
 *      FILEIO_ERROR        A serious error occured.
 
299
 *      FILEIO_ERROR               A serious error occured.
 
300
 *      FILEIO_SUCCESS             All is well
 
301
 *      FILEIO_LOCK_FAILED         Requested lock on file was not acquired
 
302
 *      FILEIO_FILE_NOT_FOUND      Unable to find the specified file
 
303
 *      FILEIO_NO_PERMISSION       Permissions issues
 
304
 *      FILEIO_FILE_NAME_TOO_LONG  The path name is too long
238
305
 *
239
306
 * Side effects:
240
307
 *      None
253
320
    */
254
321
 
255
322
   ASSERT(file);
 
323
   ASSERT(file->lockToken == NULL);
 
324
 
 
325
   FileIOResolveLockBits(&access);
 
326
   ASSERT((access & FILEIO_OPEN_LOCKED) == 0);
256
327
 
257
328
#if !defined(__FreeBSD__) && !defined(sun)
258
 
   if (access & FILEIO_OPEN_LOCKED) {
259
 
      int err;
260
 
 
261
 
      ASSERT(file->lockToken == NULL);
 
329
   if ((access & FILEIO_OPEN_LOCK_MANDATORY) != 0) {
 
330
      /* Mandatory file locks are available only when opening a file */
 
331
      ret = FILEIO_LOCK_FAILED;
 
332
   } else if ((access & FILEIO_OPEN_LOCK_ADVISORY) != 0) {
 
333
      int err = 0;
262
334
 
263
335
      file->lockToken = FileLock_Lock(file->fileName,
264
336
                                      (access & FILEIO_OPEN_ACCESS_WRITE) == 0,
265
337
                                      FILELOCK_DEFAULT_WAIT,
266
 
                                      &err);
 
338
                                      &err,
 
339
                                      NULL);
267
340
 
268
341
      if (file->lockToken == NULL) {
269
342
         /* Describe the lock not acquired situation in detail */
291
364
         }
292
365
      }
293
366
   }
294
 
#else
295
 
   ASSERT(file->lockToken == NULL);
296
367
#endif // !__FreeBSD__ && !sun
297
368
 
298
369
   return ret;
325
396
 
326
397
#if !defined(__FreeBSD__) && !defined(sun)
327
398
   if (file->lockToken != NULL) {
328
 
      int err;
329
 
 
330
 
      err = FileLock_Unlock(file->lockToken);
331
 
 
332
 
      if (err != 0) {
 
399
      int err = 0;
 
400
 
 
401
      if (!FileLock_Unlock(file->lockToken, &err, NULL)) {
333
402
         Warning(LGPFX" %s on '%s' failed: %s\n",
334
403
                 __FUNCTION__, UTF8(file->fileName), strerror(err));
335
404
 
349
418
/*
350
419
 *----------------------------------------------------------------------
351
420
 *
 
421
 * FileIO_GetSize --
 
422
 *
 
423
 *      Get size of file.
 
424
 *
 
425
 * Results:
 
426
 *      Size of file or -1.
 
427
 *
 
428
 * Side effects:
 
429
 *      errno is set on error.
 
430
 *
 
431
 *----------------------------------------------------------------------
 
432
 */
 
433
 
 
434
int64
 
435
FileIO_GetSize(const FileIODescriptor *fd)  // IN:
 
436
{
 
437
   int64 logicalBytes;
 
438
 
 
439
   return (FileIO_GetAllocSize(fd, &logicalBytes, NULL) != FILEIO_SUCCESS) ?
 
440
      -1 : logicalBytes;
 
441
}
 
442
 
 
443
 
 
444
/*
 
445
 *----------------------------------------------------------------------
 
446
 *
 
447
 * FileIO_GetSizeByPath --
 
448
 *
 
449
 *      Get size of a file specified by path. 
 
450
 *
 
451
 * Results:
 
452
 *      Size of file or -1.
 
453
 *
 
454
 * Side effects:
 
455
 *      errno is set on error
 
456
 *
 
457
 *----------------------------------------------------------------------
 
458
 */
 
459
 
 
460
int64
 
461
FileIO_GetSizeByPath(ConstUnicode pathName)  // IN:
 
462
{
 
463
   int64 logicalBytes;
 
464
 
 
465
   return (FileIO_GetAllocSizeByPath(pathName, &logicalBytes, NULL) !=
 
466
      FILEIO_SUCCESS) ? -1 : logicalBytes;
 
467
}
 
468
 
 
469
 
 
470
/*
 
471
 *----------------------------------------------------------------------
 
472
 *
352
473
 * FileIO_Filename --
353
474
 *
354
475
 *      Returns the filename that was used to open a FileIODescriptor
373
494
}
374
495
 
375
496
 
 
497
/*
 
498
 *----------------------------------------------------------------------
 
499
 *
 
500
 * FileIO_CloseAndUnlink
 
501
 *
 
502
 *      Closes and unlinks the file associated with a FileIODescriptor.
 
503
 *
 
504
 * Results:
 
505
 *      TRUE: An error occurred.
 
506
 *      FALSE: The file was closed and unlinked.
 
507
 *
 
508
 * Side effects:
 
509
 *      File is probably closed and unlinked.
 
510
 *
 
511
 *----------------------------------------------------------------------
 
512
 */
 
513
 
 
514
Bool
 
515
FileIO_CloseAndUnlink(FileIODescriptor *fd)  // IN:
 
516
{
 
517
   Unicode path;
 
518
   Bool ret;
 
519
 
 
520
   ASSERT(fd);
 
521
   ASSERT(FileIO_IsValid(fd));
 
522
 
 
523
   path = Unicode_Duplicate(fd->fileName);
 
524
   ret = FileIO_Close(fd) || File_Unlink(path);
 
525
   Unicode_Free(path);
 
526
 
 
527
   return ret;
 
528
}
 
529
 
 
530
 
376
531
#if defined(_WIN32) || defined(__linux__) || defined(__APPLE__) || \
377
532
    defined(__FreeBSD__) || defined(sun)
378
533
/*
474
629
   return res == FILEIO_SUCCESS;
475
630
}
476
631
#endif
 
632
 
 
633
 
 
634
/*
 
635
 *-----------------------------------------------------------------------------
 
636
 *
 
637
 * FileIOAtomicTempPath
 
638
 *
 
639
 *      Return a temp path name in the same directory as the argument file.
 
640
 *      The path is the full path of the source file with a '~' appended.
 
641
 *      The caller must free the path when done.
 
642
 *
 
643
 * Results:
 
644
 *      Unicode path if successful, NULL on failure.
 
645
 *
 
646
 * Side effects:
 
647
 *      None.
 
648
 *
 
649
 *-----------------------------------------------------------------------------
 
650
 */
 
651
 
 
652
static Unicode 
 
653
FileIOAtomicTempPath(FileIODescriptor *fileFD)  // IN:
 
654
{
 
655
   Unicode path;
 
656
   Unicode srcPath;
 
657
 
 
658
   ASSERT(FileIO_IsValid(fileFD));
 
659
 
 
660
   srcPath = File_FullPath(FileIO_Filename(fileFD));
 
661
   if (!srcPath) {
 
662
      Log("%s: File_FullPath of '%s' failed.\n", __FUNCTION__,
 
663
          FileIO_Filename(fileFD));
 
664
      return NULL;
 
665
   }
 
666
   path = Unicode_Join(srcPath, "~", NULL);
 
667
   Unicode_Free(srcPath);
 
668
 
 
669
   return path;
 
670
}
 
671
 
 
672
 
 
673
/*
 
674
 *-----------------------------------------------------------------------------
 
675
 *
 
676
 * FileIO_AtomicTempFile
 
677
 *
 
678
 *      Create a temp file in the same directory as the argument file. 
 
679
 *      On non-Windows attempts to create the temp file with the same
 
680
 *      permissions and owner/group as the argument file.
 
681
 *
 
682
 * Results:
 
683
 *      FileIOResult of call that failed or FILEIO_SUCCESS
 
684
 *
 
685
 * Side effects:
 
686
 *      Creates a new file.
 
687
 *
 
688
 *-----------------------------------------------------------------------------
 
689
 */
 
690
 
 
691
FileIOResult
 
692
FileIO_AtomicTempFile(FileIODescriptor *fileFD,  // IN:
 
693
                      FileIODescriptor *tempFD)  // OUT:
 
694
{
 
695
   Unicode tempPath = NULL;
 
696
   int permissions;
 
697
   FileIOResult status;
 
698
#if !defined(_WIN32)
 
699
   int ret;
 
700
   struct stat stbuf;
 
701
#endif
 
702
 
 
703
   ASSERT(FileIO_IsValid(fileFD));
 
704
   ASSERT(tempFD && !FileIO_IsValid(tempFD));
 
705
 
 
706
   tempPath = FileIOAtomicTempPath(fileFD);
 
707
   if (!tempPath) {
 
708
      status = FILEIO_ERROR;
 
709
      goto bail;
 
710
   }
 
711
 
 
712
#if defined(_WIN32)
 
713
   permissions = 0;
 
714
   File_UnlinkIfExists(tempPath);
 
715
#else
 
716
   if (fstat(fileFD->posix, &stbuf)) {
 
717
      Log("%s: Failed to fstat '%s', errno: %d.\n", __FUNCTION__,
 
718
          FileIO_Filename(fileFD), errno);
 
719
      ASSERT(!vmx86_server); // For APD, hosted can fall-back and write directly
 
720
      status = FILEIO_ERROR;
 
721
      goto bail;
 
722
   }
 
723
   permissions = stbuf.st_mode;
 
724
 
 
725
   /* Do a "cleanup" unlink in case some previous process left a temp file around */
 
726
   ret = Posix_Unlink(tempPath);
 
727
   if (ret != 0 && errno != ENOENT) { /* ENOENT is expected, file should not exist */
 
728
      Log("%s: Failed to unlink temporary file, errno: %d\n",
 
729
          __FUNCTION__, errno);
 
730
      /* Fall through; FileIO_Create will report the actual error */
 
731
   }
 
732
#endif
 
733
 
 
734
   status = FileIO_Create(tempFD, tempPath,
 
735
                          FILEIO_ACCESS_READ | FILEIO_ACCESS_WRITE,
 
736
                          FILEIO_OPEN_CREATE_SAFE, permissions);
 
737
   if (!FileIO_IsSuccess(status)) {
 
738
      Log("%s: Failed to create temporary file, err: %d\n", __FUNCTION__,
 
739
          Err_Errno());
 
740
      goto bail;
 
741
   }
 
742
 
 
743
#if !defined(_WIN32)
 
744
   /*
 
745
    * On ESX we always use the vmkernel atomic file swap primitive, so
 
746
    * there's no need to set the permissions and owner of the temp file.
 
747
    */
 
748
 
 
749
   if (!HostType_OSIsVMK()) {
 
750
      if (fchmod(tempFD->posix, stbuf.st_mode)) {
 
751
         Log("%s: Failed to chmod temporary file, errno: %d\n",
 
752
             __FUNCTION__, errno);
 
753
         status = FILEIO_ERROR;
 
754
         goto bail;
 
755
      }
 
756
      if (fchown(tempFD->posix, stbuf.st_uid, stbuf.st_gid)) {
 
757
         Log("%s: Failed to chown temporary file, errno: %d\n",
 
758
             __FUNCTION__, errno);
 
759
         status = FILEIO_ERROR;
 
760
         goto bail;
 
761
      }
 
762
   }
 
763
#endif
 
764
 
 
765
   Unicode_Free(tempPath);
 
766
   return FILEIO_SUCCESS;
 
767
 
 
768
bail:
 
769
   ASSERT(!FileIO_IsSuccess(status));
 
770
   if (FileIO_IsValid(tempFD)) {
 
771
      FileIO_Close(tempFD);
 
772
#if defined(_WIN32)
 
773
      File_UnlinkIfExists(tempPath);
 
774
#else
 
775
      ret = Posix_Unlink(tempPath);
 
776
      if (ret != 0) {
 
777
         Log("%s: Failed to clean up temporary file, errno: %d\n",
 
778
             __FUNCTION__, errno);
 
779
      }
 
780
      ASSERT(ret == 0);
 
781
#endif
 
782
   }
 
783
   Unicode_Free(tempPath);
 
784
   return status;
 
785
}
 
786
 
 
787
 
 
788
/*
 
789
 *-----------------------------------------------------------------------------
 
790
 *
 
791
 * FileIO_AtomicUpdate --
 
792
 *
 
793
 *      On ESX when the target files reside on vmfs, exchanges the contents
 
794
 *      of two files using code modeled from VmkfsLib_SwapFiles.  Both "curr"
 
795
 *      and "new" are left open.
 
796
 *
 
797
 *      On ESX when the target files reside on NFS, and on hosted products,
 
798
 *      uses rename to swap files, so "new" becomes "curr", and path to "new"
 
799
 *      no longer exists on success.
 
800
 *
 
801
 *      On success the caller must call FileIO_IsValid on newFD to verify it
 
802
 *      is still open before using it again.
 
803
 *
 
804
 * Results:
 
805
 *      TRUE if successful, FALSE on failure.
 
806
 *
 
807
 * Side effects:
 
808
 *      Disk I/O.
 
809
 *
 
810
 *-----------------------------------------------------------------------------
 
811
 */
 
812
 
 
813
 
 
814
Bool
 
815
FileIO_AtomicUpdate(FileIODescriptor *newFD,   // IN/OUT: file IO descriptor
 
816
                    FileIODescriptor *currFD)  // IN/OUT: file IO descriptor
 
817
{
 
818
   char *currPath;
 
819
   char *newPath;
 
820
   uint32 currAccess;
 
821
   uint32 newAccess;
 
822
   Bool ret = FALSE;
 
823
   FileIOResult status;
 
824
 
 
825
   ASSERT(FileIO_IsValid(newFD));
 
826
   ASSERT(FileIO_IsValid(currFD));
 
827
 
 
828
   if (HostType_OSIsVMK()) {
 
829
#if defined(VMX86_SERVER)
 
830
      FS_SwapFilesArgs *args = NULL;
 
831
      char *dirName = NULL;
 
832
      char *fileName = NULL;
 
833
      char *dstDirName = NULL;
 
834
      char *dstFileName = NULL;
 
835
      int savedErrno;
 
836
      int fd;
 
837
 
 
838
      currPath = File_FullPath(FileIO_Filename(currFD));
 
839
      newPath = File_FullPath(FileIO_Filename(newFD));
 
840
 
 
841
      ASSERT(currPath);
 
842
      ASSERT(newPath);
 
843
 
 
844
      File_GetPathName(newPath, &dirName, &fileName);
 
845
      File_GetPathName(currPath, &dstDirName, &dstFileName);
 
846
 
 
847
      ASSERT(dirName && *dirName);
 
848
      ASSERT(fileName && *fileName);
 
849
      ASSERT(dstDirName && *dstDirName);
 
850
      ASSERT(dstFileName && *dstFileName);
 
851
      ASSERT(!strcmp(dirName, dstDirName));
 
852
 
 
853
      args = (FS_SwapFilesArgs *) Util_SafeCalloc(1, sizeof(*args));
 
854
      if (Str_Snprintf(args->srcFile, sizeof(args->srcFile), "%s",
 
855
                       fileName) < 0) {
 
856
         Log("%s: Path too long \"%s\".\n", __FUNCTION__, fileName);
 
857
         goto swapdone;
 
858
      }
 
859
      if (Str_Snprintf(args->dstFilePath, sizeof(args->dstFilePath), "%s/%s",
 
860
                       dstDirName, dstFileName) < 0) {
 
861
         Log("%s: Path too long \"%s\".\n", __FUNCTION__, dstFileName);
 
862
         goto swapdone;
 
863
      }
 
864
 
 
865
      /*
 
866
       * Issue the ioctl on the directory rather than on the file,
 
867
       * because the file could be open.
 
868
       */
 
869
 
 
870
      fd = Posix_Open(dirName, O_RDONLY);
 
871
      if (fd < 0) {
 
872
         Log("%s: Open failed \"%s\" %d.\n", __FUNCTION__, dirName,
 
873
             errno);
 
874
         ASSERT_BUG_DEBUGONLY(615124, errno != EBUSY);
 
875
         goto swapdone;
 
876
      }
 
877
 
 
878
      savedErrno = 0;
 
879
      if (ioctl(fd, IOCTLCMD_VMFS_SWAP_FILES, args) != 0) {
 
880
         savedErrno = errno;
 
881
         if (errno != ENOSYS) {
 
882
            Log("%s: ioctl failed %d.\n", __FUNCTION__, errno);
 
883
            ASSERT_BUG_DEBUGONLY(615124, errno != EBUSY);
 
884
         }
 
885
      } else {
 
886
         ret = TRUE;
 
887
      }
 
888
 
 
889
      close(fd);
 
890
 
 
891
      /*
 
892
       * Did we fail because we are on NFS?
 
893
       */
 
894
      if (savedErrno == ENOSYS) {
 
895
         /*
 
896
          * NFS allows renames of locked files, even if both files
 
897
          * are locked.  The file lock follows the file handle, not
 
898
          * the name, so after the rename we can swap the underlying
 
899
          * file descriptors instead of closing and reopening the
 
900
          * target file.
 
901
          *
 
902
          * This is different than the hosted path below because
 
903
          * ESX uses native file locks and hosted does not.
 
904
          */
 
905
 
 
906
         if (File_Rename(newPath, currPath)) {
 
907
            Log("%s: rename of '%s' to '%s' failed %d.\n",
 
908
                newPath, currPath, __FUNCTION__, errno);
 
909
            goto swapdone;
 
910
         }
 
911
         ret = TRUE;
 
912
         fd = newFD->posix;
 
913
         newFD->posix = currFD->posix;
 
914
         currFD->posix = fd;
 
915
         FileIO_Close(newFD);
 
916
      }
 
917
 
 
918
swapdone:
 
919
      free(args);
 
920
      free(dirName);
 
921
      free(fileName);
 
922
      free(dstDirName);
 
923
      free(dstFileName);
 
924
      free(currPath);
 
925
      free(newPath);
 
926
 
 
927
      return ret;
 
928
#else
 
929
      NOT_REACHED();
 
930
#endif
 
931
   }
 
932
 
 
933
   currPath = Unicode_Duplicate(FileIO_Filename(currFD));
 
934
   newPath = Unicode_Duplicate(FileIO_Filename(newFD));
 
935
 
 
936
   newAccess = newFD->flags;
 
937
   currAccess = currFD->flags;
 
938
 
 
939
   FileIO_Close(newFD);
 
940
 
 
941
   /*
 
942
    * The current file needs to be closed and reopened,
 
943
    * but we don't want to drop the file lock by calling 
 
944
    * FileIO_Close() on it.  Instead, use native close primitives.
 
945
    * We'll reopen it later with a temp FileIODescriptor, and
 
946
    * swap the file descriptor/handle.  Set the descriptor/handle
 
947
    * to an invalid value while we're in the middle of transferring
 
948
    * ownership.
 
949
    */
 
950
 
 
951
#if defined(_WIN32)
 
952
   CloseHandle(currFD->win32);
 
953
   currFD->win32 = INVALID_HANDLE_VALUE;
 
954
#else
 
955
   close(currFD->posix);
 
956
   currFD->posix = -1;
 
957
#endif
 
958
   if (File_RenameRetry(newPath, currPath, 10)) {
 
959
      goto bail;
 
960
   }
 
961
 
 
962
   ret = TRUE;
 
963
   
 
964
bail:
 
965
 
 
966
   /*
 
967
    * XXX - We shouldn't drop the file lock here.
 
968
    *       Need to implement FileIO_Reopen to close
 
969
    *       and reopen without dropping the lock.
 
970
    */
 
971
 
 
972
   FileIO_Close(currFD);  // XXX - PR 769296
 
973
 
 
974
   status = FileIO_Open(currFD, currPath, currAccess, 0);
 
975
   if (!FileIO_IsSuccess(status)) {
 
976
      Panic("Failed to reopen dictionary file.\n");
 
977
   }
 
978
 
 
979
   Unicode_Free(currPath);
 
980
   Unicode_Free(newPath);
 
981
   return ret;
 
982
}