[Libreoffice-commits] core.git: include/osl sal/osl sal/util sfx2/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Thu Sep 27 14:44:12 UTC 2018


 include/osl/file.h          |   31 +++++++++++++++++++++++++++++++
 include/osl/file.hxx        |   33 +++++++++++++++++++++++++++++++++
 sal/osl/unx/file_misc.cxx   |    5 +++++
 sal/osl/w32/file.cxx        |   34 ++++++++++++++++++++++++++++++++++
 sal/util/sal.map            |    5 +++++
 sfx2/source/doc/docfile.cxx |    3 ++-
 6 files changed, 110 insertions(+), 1 deletion(-)

New commits:
commit c9343988204ee3e9889f3cc833adbbaca83e53e6
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Fri Sep 7 17:11:48 2018 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Thu Sep 27 16:43:48 2018 +0200

    tdf#119238: keep replaced file's identity when renaming docfile
    
    Regression from 2157a3536f97ff5ae7c82611a801fef7e3708983
    
      sfx2 store: try rename before copying
    
      Rename is cheaper then copying the content over manually, so try that
      first.
    
    On Windows, we need to keep the file's dentity, including metadata (e.g.,
    creation time, which is kept in FS). WinAPI has ReplaceFileW specifically
    for this, and it keeps ACLs of the original file, and otherwise makes the
    changed file not a separate entry, but updated old file from system's PoV.
    
    Eventually, we could try to restructure creating backup copies (e.g., for
    documents when configured so) to take advantage of this function being able
    to do that.
    
    Change-Id: I6001a2a3af5e10bc010f5ef129f4bb6f83ee1581
    Reviewed-on: https://gerrit.libreoffice.org/60163
    Reviewed-by: Stephan Bergmann <sbergman at redhat.com>
    Tested-by: Jenkins

diff --git a/include/osl/file.h b/include/osl/file.h
index 133b93de0c93..cf0bbfb9495d 100644
--- a/include/osl/file.h
+++ b/include/osl/file.h
@@ -1634,6 +1634,37 @@ SAL_DLLPUBLIC oslFileError SAL_CALL osl_createTempFile(
     oslFileHandle* pHandle,
     rtl_uString**  ppustrTempFileURL);
 
+/** Move a file to a new destination or rename it, taking old file's identity (if exists).
+
+    Moves or renames a file, replacing an existing file if exist. If the old file existed,
+    moved file's metadata, e.g. creation time (on FSes which keep files' creation time) or
+    ACLs, are set to old one's (to keep the old file's identity) - currently this is only
+    implemented on Windows; on other platforms, this is equivalent to osl_moveFile.
+
+    @param[in] pustrSourceFileURL
+    Full qualified URL of the source file.
+
+    @param[in] pustrDestFileURL
+    Full qualified URL of the destination file.
+
+    @retval osl_File_E_None on success
+    @retval osl_File_E_INVAL the format of the parameters was not valid
+    @retval osl_File_E_NOMEM not enough memory for allocating structures
+    @retval osl_File_E_ACCES permission denied
+    @retval osl_File_E_PERM operation not permitted
+    @retval osl_File_E_NAMETOOLONG file name too long
+    @retval osl_File_E_NOENT no such file
+    @retval osl_File_E_ROFS read-only file system
+    @retval osl_File_E_BUSY if the implementation internally requires resources that are
+        (temporarily) unavailable
+
+    @see osl_moveFile()
+
+    @since LibreOffice 6.2
+*/
+SAL_DLLPUBLIC oslFileError SAL_CALL osl_replaceFile(rtl_uString* pustrSourceFileURL,
+                                                    rtl_uString* pustrDestFileURL);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/osl/file.hxx b/include/osl/file.hxx
index a154aa4f27bc..855398db4038 100644
--- a/include/osl/file.hxx
+++ b/include/osl/file.hxx
@@ -1298,6 +1298,39 @@ public:
         return static_cast< RC >( osl_moveFile( ustrSourceFileURL.pData, ustrDestFileURL.pData ) );
     }
 
+    /** Move a file to a new destination or rename it, taking old file's identity (if exists).
+
+        Moves or renames a file, replacing an existing file if exist. If the old file existed,
+        moved file's metadata, e.g. creation time (on FSes which keep files' creation time) or
+        ACLs, are set to old one's (to keep the old file's identity) - currently this is only
+        implemented on Windows; on other platforms, this is equivalent to osl_moveFile.
+
+        @param[in] ustrSourceFileURL
+        Full qualified URL of the source file.
+
+        @param[in] ustrDestFileURL
+        Full qualified URL of the destination file.
+
+        @retval E_None on success
+        @retval E_INVAL the format of the parameters was not valid
+        @retval E_NOMEM not enough memory for allocating structures
+        @retval E_ACCES permission denied
+        @retval E_PERM operation not permitted
+        @retval E_NAMETOOLONG file name too long
+        @retval E_NOENT no such file
+        @retval E_ROFS read-only file system
+        @retval E_BUSY device or resource busy
+
+        @see move()
+
+        @since LibreOffice 6.2
+    */
+    static RC replace(const ::rtl::OUString& ustrSourceFileURL,
+                      const ::rtl::OUString& ustrDestFileURL)
+    {
+        return static_cast<RC>(osl_replaceFile(ustrSourceFileURL.pData, ustrDestFileURL.pData));
+    }
+
     /** Remove a regular file.
 
         @param[in] ustrFileURL
diff --git a/sal/osl/unx/file_misc.cxx b/sal/osl/unx/file_misc.cxx
index 873bec3cb988..8ae8c74062ee 100644
--- a/sal/osl/unx/file_misc.cxx
+++ b/sal/osl/unx/file_misc.cxx
@@ -604,6 +604,11 @@ oslFileError SAL_CALL osl_moveFile( rtl_uString* ustrFileURL, rtl_uString* ustrD
     return oslDoMoveFile( srcPath, destPath );
 }
 
+oslFileError SAL_CALL osl_replaceFile(rtl_uString* ustrFileURL, rtl_uString* ustrDestURL)
+{
+    return osl_moveFile(ustrFileURL, ustrDestURL);
+}
+
 oslFileError SAL_CALL osl_copyFile( rtl_uString* ustrFileURL, rtl_uString* ustrDestURL )
 {
     char srcPath[PATH_MAX];
diff --git a/sal/osl/w32/file.cxx b/sal/osl/w32/file.cxx
index c8b001e9847d..a5e6c640b8ed 100644
--- a/sal/osl/w32/file.cxx
+++ b/sal/osl/w32/file.cxx
@@ -1099,4 +1099,38 @@ oslFileError SAL_CALL osl_moveFile(rtl_uString* strPath, rtl_uString *strDestPat
     return error;
 }
 
+oslFileError SAL_CALL osl_replaceFile(rtl_uString* strPath, rtl_uString* strDestPath)
+{
+    rtl_uString *strSysPath = nullptr, *strSysDestPath = nullptr;
+    oslFileError    error = osl_getSystemPathFromFileURL_(strPath, &strSysPath, false);
+
+    if (error == osl_File_E_None)
+        error = osl_getSystemPathFromFileURL_(strDestPath, &strSysDestPath, false);
+
+    if (error == osl_File_E_None)
+    {
+        LPCWSTR src = o3tl::toW(rtl_uString_getStr(strSysPath));
+        LPCWSTR dst = o3tl::toW(rtl_uString_getStr(strSysDestPath));
+
+        if (!ReplaceFileW(dst, src, nullptr,
+                          REPLACEFILE_WRITE_THROUGH | REPLACEFILE_IGNORE_MERGE_ERRORS
+                              | REPLACEFILE_IGNORE_ACL_ERRORS,
+                          nullptr, nullptr))
+        {
+            DWORD dwError = GetLastError();
+            if (dwError == ERROR_FILE_NOT_FOUND) // no strDestPath file?
+                error = osl_moveFile(strPath, strDestPath);
+            else
+                error = oslTranslateFileError(dwError);
+        }
+    }
+
+    if (strSysPath)
+        rtl_uString_release(strSysPath);
+    if (strSysDestPath)
+        rtl_uString_release(strSysDestPath);
+
+    return error;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sal/util/sal.map b/sal/util/sal.map
index 07150ab0340d..9292d50ca423 100644
--- a/sal/util/sal.map
+++ b/sal/util/sal.map
@@ -700,6 +700,11 @@ LIBO_UDK_5.3 { # symbols available in >= LibO 5.3
         rtl_uString_newReplaceFirstUtf16LUtf16L;
 } LIBO_UDK_5.2;
 
+LIBO_UDK_6.2 { # symbols available in >= LibO 6.2
+    global:
+        osl_replaceFile;
+} LIBO_UDK_5.3;
+
 PRIVATE_1.0 {
     global:
         osl_detail_ObjectRegistry_storeAddresses;
diff --git a/sfx2/source/doc/docfile.cxx b/sfx2/source/doc/docfile.cxx
index 8da6f3a6e7b8..4cebc868e2bd 100644
--- a/sfx2/source/doc/docfile.cxx
+++ b/sfx2/source/doc/docfile.cxx
@@ -1845,7 +1845,8 @@ void SfxMedium::TransactedTransferForFS_Impl( const INetURLObject& aSource,
                 OUString aDestMainURL = aDest.GetMainURL(INetURLObject::DecodeMechanism::NONE);
 
                 sal_uInt64 nAttributes = GetDefaultFileAttributes(aDestMainURL);
-                if (IsFileMovable(aDestMainURL) && osl::File::move(aSourceMainURL, aDestMainURL) == osl::FileBase::E_None)
+                if (IsFileMovable(aDestMainURL)
+                    && osl::File::replace(aSourceMainURL, aDestMainURL) == osl::FileBase::E_None)
                 {
                     if (nAttributes)
                         // Adjust attributes, source might be created with


More information about the Libreoffice-commits mailing list