csync_vio_locale: use QString for the path in opendir
authorOlivier Goffart <ogoffart@woboq.com>
Tue, 6 Nov 2018 14:44:22 +0000 (15:44 +0100)
committerKevin Ottens <kevin.ottens@nextcloud.com>
Tue, 15 Dec 2020 09:58:20 +0000 (10:58 +0100)
So we don't have to convert to utf8 and back again

src/csync/vio/csync_vio_local.h
src/csync/vio/csync_vio_local_unix.cpp
src/csync/vio/csync_vio_local_win.cpp
src/libsync/discovery.cpp

index 734f6021102c212aec1f1349fd098f6b56c6165c..97ac34d63ec2b1711023698de6c2e32925ab7c42 100644 (file)
@@ -23,7 +23,7 @@
 
 struct csync_vio_handle_t;
 
-csync_vio_handle_t OCSYNC_EXPORT *csync_vio_local_opendir(const char *name);
+csync_vio_handle_t OCSYNC_EXPORT *csync_vio_local_opendir(const QString &name);
 int OCSYNC_EXPORT csync_vio_local_closedir(csync_vio_handle_t *dhandle);
 std::unique_ptr<csync_file_stat_t> OCSYNC_EXPORT csync_vio_local_readdir(csync_vio_handle_t *dhandle);
 
index c13b0fab7b8e34f1632df007dd8569327f4ec8b5..ea6f925dfd4299d71c3bf1d220ea7fad47608407 100644 (file)
@@ -37,6 +37,7 @@
 #include "vio/csync_vio_local.h"
 
 #include <QtCore/QLoggingCategory>
+#include <QtCore/QFile>
 
 Q_LOGGING_CATEGORY(lcCSyncVIOLocal, "nextcloud.sync.csync.vio_local", QtInfoMsg)
 
@@ -44,58 +45,37 @@ Q_LOGGING_CATEGORY(lcCSyncVIOLocal, "nextcloud.sync.csync.vio_local", QtInfoMsg)
  * directory functions
  */
 
-struct dhandle_t {
+struct csync_vio_handle_t {
   DIR *dh;
-  char *path;
+  QByteArray path;
 };
 
 static int _csync_vio_local_stat_mb(const mbchar_t *wuri, csync_file_stat_t *buf);
 
-csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
-  dhandle_t *handle = nullptr;
-  mbchar_t *dirname = nullptr;
+csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
+    QScopedPointer<csync_vio_handle_t> handle(new csync_vio_handle_t{});
 
-  handle = (dhandle_t*)c_malloc(sizeof(dhandle_t));
+    auto dirname = QFile::encodeName(name);
 
-  dirname = c_utf8_path_to_locale(name);
-
-  handle->dh = _topendir( dirname );
-  if (!handle->dh) {
-    c_free_locale_string(dirname);
-    SAFE_FREE(handle);
-    return nullptr;
-  }
-
-  handle->path = c_strdup(name);
-  c_free_locale_string(dirname);
+    handle->dh = _topendir( dirname );
+    if (!handle->dh) {
+        return nullptr;
+    }
 
-  return (csync_vio_handle_t *) handle;
+    handle->path = dirname;
+    return handle.take();
 }
 
 int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
-  dhandle_t *handle = nullptr;
-  int rc = -1;
-
-  if (!dhandle) {
-    errno = EBADF;
-    return -1;
-  }
-
-  handle = (dhandle_t *) dhandle;
-  rc = _tclosedir(handle->dh);
-
-  SAFE_FREE(handle->path);
-  SAFE_FREE(handle);
-
-  return rc;
+    Q_ASSERT(dhandle);
+    auto rc = _tclosedir(dhandle->dh);
+    delete dhandle;
+    return rc;
 }
 
-std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
-
-  dhandle_t *handle = nullptr;
+std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *handle) {
 
-  handle = (dhandle_t *) dhandle;
-  struct _tdirent *dirent = nullptr;
+  struct _tdirent *dirent = NULL;
   std::unique_ptr<csync_file_stat_t> file_stat;
 
   do {
@@ -106,7 +86,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
 
   file_stat = std::make_unique<csync_file_stat_t>();
   file_stat->path = c_utf8_from_locale(dirent->d_name);
-  QByteArray fullPath = QByteArray() % const_cast<const char *>(handle->path) % '/' % QByteArray() % const_cast<const char *>(dirent->d_name);
+  QByteArray fullPath = handle->path % '/' % QByteArray() % const_cast<const char *>(dirent->d_name);
   if (file_stat->path.isNull()) {
       file_stat->original_path = fullPath;
       qCWarning(lcCSyncVIOLocal) << "Invalid characters in file/directory name, please rename:" << dirent->d_name << handle->path;
index 3a58be31c11e1e644b5d91b6e61651f7209c8d6c..7eeab68277b64eaa4002c3cba02161352dfedab2 100644 (file)
@@ -34,6 +34,7 @@
 #include "c_utf8.h"
 #include "csync_util.h"
 #include "vio/csync_vio_local.h"
+#include "common/filesystembase.h"
 
 #include <QtCore/QLoggingCategory>
 
@@ -43,81 +44,54 @@ Q_LOGGING_CATEGORY(lcCSyncVIOLocal, "nextcloud.sync.csync.vio_local", QtInfoMsg)
  * directory functions
  */
 
-struct dhandle_t {
+struct csync_vio_handle_t {
   WIN32_FIND_DATA ffd;
   HANDLE hFind;
   int firstFind;
-  mbchar_t *path; // Always ends with '\'
+  QString path; // Always ends with '\'
 };
 
 static int _csync_vio_local_stat_mb(const mbchar_t *uri, csync_file_stat_t *buf);
 
-csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
-  dhandle_t *handle = nullptr;
-  mbchar_t *dirname = nullptr;
+csync_vio_handle_t *csync_vio_local_opendir(const QString &name) {
 
-  handle = (dhandle_t*)c_malloc(sizeof(dhandle_t));
+    QScopedPointer<csync_vio_handle_t> handle(new csync_vio_handle_t{});
 
-  // the file wildcard has to be attached
-  size_t len_name = strlen(name);
-  if( len_name ) {
-      char *h = nullptr;
+    // the file wildcard has to be attached
+    QString dirname = OCC::FileSystem::longWinPath(name + QLatin1String("/*"));
 
-      // alloc an enough large buffer to take the name + '/*' + the closing zero.
-      h = (char*)c_malloc(len_name+3);
-      strncpy( h, name, 1+len_name);
-      strncat(h, "/*", 2);
+    handle->hFind = FindFirstFile(reinterpret_cast<const wchar_t *>(dirname.utf16()), &(handle->ffd));
 
-      dirname = c_utf8_path_to_locale(h);
-      SAFE_FREE(h);
-  }
-
-  if( dirname ) {
-      handle->hFind = FindFirstFile(dirname, &(handle->ffd));
-  }
-
-  if (!dirname || handle->hFind == INVALID_HANDLE_VALUE) {
-      c_free_locale_string(dirname);
-      int retcode = GetLastError();
-      if( retcode == ERROR_FILE_NOT_FOUND ) {
-          errno = ENOENT;
-      } else {
-          errno = EACCES;
-      }
-      SAFE_FREE(handle);
-      return nullptr;
-  }
-
-  handle->firstFind = 1; // Set a flag that there first fileinfo is available.
+    if (handle->hFind == INVALID_HANDLE_VALUE) {
+        int retcode = GetLastError();
+        if( retcode == ERROR_FILE_NOT_FOUND ) {
+            errno = ENOENT;
+        } else {
+            errno = EACCES;
+        }
+        return nullptr;
+    }
 
-  dirname[std::wcslen(dirname) - 1] = L'\0'; // remove the *
-  handle->path = dirname;
+    handle->firstFind = 1; // Set a flag that there first fileinfo is available.
 
-  return (csync_vio_handle_t *) handle;
+    dirname.chop(1); // remove the *
+    handle->path = std::move(dirname);
+    return handle.take();
 }
 
 int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
-  dhandle_t *handle = nullptr;
-  int rc = -1;
+    Q_ASSERT(dhandle);
+    int rc = -1;
 
-  if (!dhandle) {
-    errno = EBADF;
-    return -1;
-  }
-
-  handle = (dhandle_t *) dhandle;
-  // FindClose returns non-zero on success
-  if( FindClose(handle->hFind) != 0 ) {
-      rc = 0;
-  } else {
-      // error case, set errno
-      errno = EBADF;
-  }
-
-  c_free_locale_string(handle->path);
-  SAFE_FREE(handle);
-
-  return rc;
+    // FindClose returns non-zero on success
+    if( FindClose(dhandle->hFind) != 0 ) {
+        rc = 0;
+    } else {
+        // error case, set errno
+        errno = EBADF;
+    }
+    delete dhandle;
+    return rc;
 }
 
 
@@ -139,14 +113,11 @@ static time_t FileTimeToUnixTime(FILETIME *filetime, DWORD *remainder)
     }
 }
 
-std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
+std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *handle) {
 
-  dhandle_t *handle = nullptr;
   std::unique_ptr<csync_file_stat_t> file_stat;
   DWORD rem;
 
-  handle = (dhandle_t *) dhandle;
-
   errno = 0;
 
   // the win32 functions get the first valid entry with the opendir
@@ -166,7 +137,7 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
   }
   auto path = c_utf8_from_locale(handle->ffd.cFileName);
   if (path == "." || path == "..")
-      return csync_vio_local_readdir(dhandle);
+      return csync_vio_local_readdir(handle);
 
   file_stat = std::make_unique<csync_file_stat_t>();
   file_stat->path = path;
@@ -201,8 +172,8 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
     file_stat->modtime = FileTimeToUnixTime(&handle->ffd.ftLastWriteTime, &rem);
 
     std::wstring fullPath;
-    fullPath.reserve(std::wcslen(handle->path) + std::wcslen(handle->ffd.cFileName));
-    fullPath += handle->path; // path always ends with '\', by construction
+    fullPath.reserve(handle->path.size() + std::wcslen(handle->ffd.cFileName));
+    fullPath += reinterpret_cast<const wchar_t *>(handle->path.utf16()); // path always ends with '\', by construction
     fullPath += handle->ffd.cFileName;
 
     if (_csync_vio_local_stat_mb(fullPath.data(), file_stat.get()) < 0) {
index 79560e7856d247f2a686ad6236f2a5bd52764a38..a0949c330d81a67ead6b5ffc71f0221872b5a5b0 100644 (file)
@@ -1220,13 +1220,13 @@ DiscoverySingleDirectoryJob *ProcessDirectoryJob::startAsyncServerQuery()
 
 bool ProcessDirectoryJob::runLocalQuery()
 {
-    QByteArray localPath = (_discoveryData->_localDir + _currentFolder._local).toUtf8();
+    QString localPath = _discoveryData->_localDir + _currentFolder._local;
     if (localPath.endsWith('/')) // Happens if _currentFolder._local.isEmpty()
         localPath.chop(1);
     auto dh = csync_vio_local_opendir(localPath);
     if (!dh) {
-        qCInfo(lcDisco) << "Error while opening directory" << (_discoveryData->_localDir + _currentFolder._local) << errno;
-        QString errorString = tr("Error while opening directory %1").arg(_discoveryData->_localDir + _currentFolder._local);
+        qCInfo(lcDisco) << "Error while opening directory" << (localPath) << errno;
+        QString errorString = tr("Error while opening directory %1").arg(localPath);
         if (errno == EACCES) {
             errorString = tr("Directory not accessible on client, permission denied");
             if (_dirItem) {
@@ -1236,7 +1236,7 @@ bool ProcessDirectoryJob::runLocalQuery()
                 return false;
             }
         } else if (errno == ENOENT) {
-            errorString = tr("Directory not found: %1").arg(_discoveryData->_localDir + _currentFolder._local);
+            errorString = tr("Directory not found: %1").arg(localPath);
         } else if (errno == ENOTDIR) {
             // Not a directory..
             // Just consider it is empty
@@ -1276,7 +1276,7 @@ bool ProcessDirectoryJob::runLocalQuery()
     if (errno != 0) {
         // Note: Windows vio converts any error into EACCES
         qCWarning(lcDisco) << "readdir failed for file in " << _currentFolder._local << " - errno: " << errno;
-        emit _discoveryData->fatalError(tr("Error while reading directory %1").arg(_discoveryData->_localDir + _currentFolder._local));
+        emit _discoveryData->fatalError(tr("Error while reading directory %1").arg(localPath));
         return false;
     }
     return true;