Fix for Windows long path issue.
authorallexzander <blackslayer4@gmail.com>
Wed, 17 Mar 2021 08:05:35 +0000 (10:05 +0200)
committerallexzander <blackslayer4@gmail.com>
Thu, 18 Mar 2021 10:07:07 +0000 (12:07 +0200)
Signed-off-by: allexzander <blackslayer4@gmail.com>
src/csync/vio/csync_vio_local_win.cpp
src/libsync/vfs/cfapi/cfapiwrapper.cpp
src/libsync/vfs/cfapi/vfs_cfapi.cpp

index a2cbdaf56e9dfaf601a7ed46bfa5dfb01b28c14d..cc31927d566d1a4faf748dc10d09095d867747fc 100644 (file)
@@ -52,7 +52,7 @@ struct csync_vio_handle_t {
   QString path; // Always ends with '\'
 };
 
-static int _csync_vio_local_stat_mb(const mbchar_t *uri, csync_file_stat_t *buf);
+static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf);
 
 csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
 
@@ -174,12 +174,12 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
     file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
     file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
 
-    std::wstring fullPath;
+    QString fullPath;
     fullPath.reserve(handle->path.size() + std::wcslen(handle->ffd.cFileName));
-    fullPath += handle->path.toStdWString(); // path always ends with '\', by construction
-    fullPath += handle->ffd.cFileName;
+    fullPath += handle->path; // path always ends with '\', by construction
+    fullPath += QString::fromWCharArray(handle->ffd.cFileName);
 
-    if (_csync_vio_local_stat_mb(fullPath.data(), file_stat.get()) < 0) {
+    if (_csync_vio_local_stat_mb(fullPath, file_stat.get()) < 0) {
         // Will get excluded by _csync_detect_update.
         file_stat->type = ItemTypeSkip;
     }
@@ -190,12 +190,11 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *h
 
 int csync_vio_local_stat(const QString &uri, csync_file_stat_t *buf)
 {
-    const std::wstring wuri = uri.toStdWString();
-    int rc = _csync_vio_local_stat_mb(wuri.data(), buf);
+    int rc = _csync_vio_local_stat_mb(uri, buf);
     return rc;
 }
 
-static int _csync_vio_local_stat_mb(const mbchar_t *wuri, csync_file_stat_t *buf)
+static int _csync_vio_local_stat_mb(const QString &path, csync_file_stat_t *buf)
 {
     /* Almost nothing to do since csync_vio_local_readdir already filled up most of the information
        But we still need to fetch the file ID.
@@ -206,18 +205,20 @@ static int _csync_vio_local_stat_mb(const mbchar_t *wuri, csync_file_stat_t *buf
     BY_HANDLE_FILE_INFORMATION fileInfo;
     ULARGE_INTEGER FileIndex;
 
-    h = CreateFileW( wuri, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
+    const auto longPath = OCC::FileSystem::longWinPath(path);
+
+    h = CreateFileW(longPath.toStdWString().data(), 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
                      nullptr, OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
                      nullptr );
     if( h == INVALID_HANDLE_VALUE ) {
-        qCCritical(lcCSyncVIOLocal, "CreateFileW failed on %ls", wuri);
+        qCCritical(lcCSyncVIOLocal) << "CreateFileW failed on" << longPath;
         errno = GetLastError();
         return -1;
     }
 
     if(!GetFileInformationByHandle( h, &fileInfo ) ) {
-        qCCritical(lcCSyncVIOLocal, "GetFileInformationByHandle failed on %ls", wuri);
+        qCCritical(lcCSyncVIOLocal) << "GetFileInformationByHandle failed on" << longPath;
         errno = GetLastError();
         CloseHandle(h);
         return -1;
index fe0c36deab15b60e4c6f307ad33dbbc177023338..7a46040a7fafab7f34f85dc0eace56e9b5f78299 100644 (file)
@@ -15,6 +15,7 @@
 #include "cfapiwrapper.h"
 
 #include "common/utility.h"
+#include "common/filesystembase.h"
 #include "hydrationjob.h"
 #include "vfs_cfapi.h"
 
@@ -370,6 +371,10 @@ bool OCC::CfApiWrapper::isSparseFile(const QString &path)
 
 OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &path)
 {
+    if (path.isEmpty()) {
+        return {};
+    }
+
     if (QFileInfo(path).isDir()) {
         HANDLE handle = nullptr;
         const qint64 openResult = CfOpenFileWithOplock(path.toStdWString().data(), CF_OPEN_FILE_FLAG_NONE, &handle);
@@ -377,10 +382,13 @@ OCC::CfApiWrapper::FileHandle OCC::CfApiWrapper::handleForPath(const QString &pa
             return {handle, [](HANDLE h) { CfCloseHandle(h); }};
         }
     } else {
-        const auto handle = CreateFile(path.toStdWString().data(), 0, 0, nullptr,
+        const auto longpath = OCC::FileSystem::longWinPath(path);
+        const auto handle = CreateFile(longpath.toStdWString().data(), 0, 0, nullptr,
                                        OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
         if (handle != INVALID_HANDLE_VALUE) {
             return {handle, [](HANDLE h) { CloseHandle(h); }};
+        } else {
+            qCCritical(lcCfApiWrapper) << "Could not CreateFile for longpath:" << longpath << "with error:" << GetLastError();
         }
     }
 
index baeea51c12bb44f7963b946a625ccc20e72323e9..6c6d9e49de3b2a6f4b0ca8c35831b159b7e1f092 100644 (file)
@@ -375,7 +375,8 @@ VfsCfApi::HydratationAndPinStates VfsCfApi::computeRecursiveHydrationAndPinState
                 return currentState;
             }
 
-            const auto path = folderPath + '/' + name;
+            // if the folderPath.isEmpty() we don't want to end up having path "/example.file" because this will lead to double slash later, when appending to "SyncFolder/"
+            const auto path = folderPath.isEmpty() ? name : folderPath + '/' + name;
             const auto states = computeRecursiveHydrationAndPinStates(path, currentState.pinState);
             return HydratationAndPinStates {
                 states.pinState,