Bug 951028 - Fix NTFS permissions when a file is moved to a different directory. r=yoric, r=bbondy, a=sledru
authorMasatoshi Kimura <VYV03354@nifty.ne.jp>
Thu, 23 Jan 2014 02:33:48 +0900
changeset 176247 c6ab73e8a021593eef228d524ef8bea962b11928
parent 176246 c61c6b9d0cb99e527a1372c333f1f231054a738a
child 176248 959db82272fedee45a4375e9077b7bd5d48236aa
push id445
push userffxbld
push dateMon, 10 Mar 2014 22:05:19 +0000
treeherdermozilla-release@dc38b741b04e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersyoric, bbondy, sledru
bugs951028
milestone28.0
Bug 951028 - Fix NTFS permissions when a file is moved to a different directory. r=yoric, r=bbondy, a=sledru
dom/system/OSFileConstants.cpp
toolkit/components/osfile/modules/osfile_win_back.jsm
toolkit/components/osfile/modules/osfile_win_front.jsm
--- a/dom/system/OSFileConstants.cpp
+++ b/dom/system/OSFileConstants.cpp
@@ -23,16 +23,17 @@
 #endif // defined(XP_LINUX)
 
 #if defined(XP_MACOSX)
 #include "copyfile.h"
 #endif // defined(XP_MACOSX)
 
 #if defined(XP_WIN)
 #include <windows.h>
+#include <accctrl.h>
 #endif // defined(XP_WIN)
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "BindingUtils.h"
 
 // Used to provide information on the OS
 
@@ -657,16 +658,21 @@ static const dom::ConstantSpec gWinPrope
 
   // MoveFile flags
   INT_CONSTANT(MOVEFILE_COPY_ALLOWED),
   INT_CONSTANT(MOVEFILE_REPLACE_EXISTING),
 
   // GetFileAttributes error constant
   INT_CONSTANT(INVALID_FILE_ATTRIBUTES),
 
+  // GetNamedSecurityInfo and SetNamedSecurityInfo constants
+  INT_CONSTANT(UNPROTECTED_DACL_SECURITY_INFORMATION),
+  INT_CONSTANT(SE_FILE_OBJECT),
+  INT_CONSTANT(DACL_SECURITY_INFORMATION),
+
   // Errors
   INT_CONSTANT(ERROR_ACCESS_DENIED),
   INT_CONSTANT(ERROR_DIR_NOT_EMPTY),
   INT_CONSTANT(ERROR_FILE_EXISTS),
   INT_CONSTANT(ERROR_ALREADY_EXISTS),
   INT_CONSTANT(ERROR_FILE_NOT_FOUND),
   INT_CONSTANT(ERROR_NO_MORE_FILES),
   INT_CONSTANT(ERROR_PATH_NOT_FOUND),
--- a/toolkit/components/osfile/modules/osfile_win_back.jsm
+++ b/toolkit/components/osfile/modules/osfile_win_back.jsm
@@ -34,16 +34,17 @@
      if (exports.OS && exports.OS.Win && exports.OS.Win.File) {
        return; // Avoid double initialization
      }
 
      let SharedAll = require("resource://gre/modules/osfile/osfile_shared_allthreads.jsm");
      let SysAll = require("resource://gre/modules/osfile/osfile_win_allthreads.jsm");
      let LOG = SharedAll.LOG.bind(SharedAll, "Unix", "back");
      let libc = SysAll.libc;
+     let advapi32 = ctypes.open("advapi32.dll");
      let Const = SharedAll.Constants.Win;
 
      /**
       * Initialize the Windows module.
       *
       * @param {function=} declareFFI
       */
      // FIXME: Both |init| and |aDeclareFFI| are deprecated, we should remove them
@@ -116,19 +117,40 @@
 
        /**
         * A C integer holding 0 in case of error, any other value in
         * case of success.
         */
        Type.zero_or_nothing =
          Type.int.withName("zero_or_nothing");
 
+       /**
+        * A C integer holding flags related to NTFS security.
+        */
        Type.SECURITY_ATTRIBUTES =
          Type.void_t.withName("SECURITY_ATTRIBUTES");
 
+       /**
+        * A C integer holding pointers related to NTFS security.
+        */
+       Type.PSID =
+         Type.voidptr_t.withName("PSID");
+
+       Type.PACL =
+         Type.voidptr_t.withName("PACL");
+
+       Type.PSECURITY_DESCRIPTOR =
+         Type.voidptr_t.withName("PSECURITY_DESCRIPTOR");
+
+       /**
+        * A C integer holding Win32 local memory handle.
+        */
+       Type.HLOCAL =
+         Type.voidptr_t.withName("HLOCAL");
+
        Type.FILETIME =
          new SharedAll.Type("FILETIME",
                   ctypes.StructType("FILETIME", [
                   { lo: Type.DWORD.implementation },
                   { hi: Type.DWORD.implementation }]));
 
        Type.FindData =
          new SharedAll.Type("FIND_DATA",
@@ -351,16 +373,44 @@
                      /*return*/   Type.DWORD,
                      /*fileName*/ Type.path);
 
         declareLazyFFI(SysFile, "SetFileAttributes", libc,
           "SetFileAttributesW", ctypes.winapi_abi,
                      /*return*/         Type.zero_or_nothing,
                      /*fileName*/       Type.path,
                      /*fileAttributes*/ Type.DWORD);
+
+        declareLazyFFI(SysFile, "GetNamedSecurityInfo", advapi32,
+          "GetNamedSecurityInfoW", ctypes.winapi_abi,
+                     /*return*/       Type.DWORD,
+                     /*objectName*/   Type.path,
+                     /*objectType*/   Type.DWORD,
+                     /*securityInfo*/ Type.DWORD,
+                     /*sidOwner*/     Type.PSID.out_ptr,
+                     /*sidGroup*/     Type.PSID.out_ptr,
+                     /*dacl*/         Type.PACL.out_ptr,
+                     /*sacl*/         Type.PACL.out_ptr,
+                     /*securityDesc*/ Type.PSECURITY_DESCRIPTOR.out_ptr);
+
+        declareLazyFFI(SysFile, "SetNamedSecurityInfo", advapi32,
+          "SetNamedSecurityInfoW", ctypes.winapi_abi,
+                     /*return*/       Type.DWORD,
+                     /*objectName*/   Type.path,
+                     /*objectType*/   Type.DWORD,
+                     /*securityInfo*/ Type.DWORD,
+                     /*sidOwner*/     Type.PSID,
+                     /*sidGroup*/     Type.PSID,
+                     /*dacl*/         Type.PACL,
+                     /*sacl*/         Type.PACL);
+
+        declareLazyFFI(SysFile, "LocalFree", libc,
+          "LocalFree", ctypes.winapi_abi,
+                     /*return*/       Type.HLOCAL,
+                     /*mem*/          Type.HLOCAL);
      };
 
      exports.OS.Win = {
        File: {
            _init:  init
        }
      };
    })(this);
--- a/toolkit/components/osfile/modules/osfile_win_front.jsm
+++ b/toolkit/components/osfile/modules/osfile_win_front.jsm
@@ -511,16 +511,47 @@
          flags = Const.MOVEFILE_COPY_ALLOWED;
        }
        if (!options.noOverwrite) {
          flags = flags | Const.MOVEFILE_REPLACE_EXISTING;
        }
        throw_on_zero("move",
          WinFile.MoveFileEx(sourcePath, destPath, flags)
        );
+
+       // Inherit NTFS permissions from the destination directory
+       // if possible.
+       if (Path.dirname(sourcePath) === Path.dirname(destPath)) {
+         // Skip if the move operation was the simple rename,
+         return;
+       }
+       // The function may fail for various reasons (e.g. not all
+       // filesystems support NTFS permissions or the user may not
+       // have the enough rights to read/write permissions).
+       // However we can safely ignore errors. The file was already
+       // moved. Setting permissions is not mandatory.
+       let dacl = new ctypes.voidptr_t();
+       let sd = new ctypes.voidptr_t();
+       WinFile.GetNamedSecurityInfo(destPath, Const.SE_FILE_OBJECT,
+                                    Const.DACL_SECURITY_INFORMATION,
+                                    null /*sidOwner*/, null /*sidGroup*/,
+                                    dacl.address(), null /*sacl*/,
+                                    sd.address());
+       // dacl will be set only if the function succeeds.
+       if (!dacl.isNull()) {
+         WinFile.SetNamedSecurityInfo(destPath, Const.SE_FILE_OBJECT,
+                                      Const.DACL_SECURITY_INFORMATION |
+                                      Const.UNPROTECTED_DACL_SECURITY_INFORMATION,
+                                      null /*sidOwner*/, null /*sidGroup*/,
+                                      dacl, null /*sacl*/);
+       }
+       // sd will be set only if the function succeeds.
+       if (!sd.isNull()) {
+           WinFile.LocalFree(Type.HLOCAL.cast(sd));
+       }
      };
 
      /**
       * A global value used to receive data during time conversions.
       */
      let gSystemTime = new Type.SystemTime.implementation();
      let gSystemTimePtr = gSystemTime.address();