mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
csync_vio_local: merge readdir and stat in the same call
For the remote this was already done long time ago For windows, this was already partially done The goal is to avoid needless conversion of the path to local encoding.
This commit is contained in:
parent
dc0a0841fa
commit
b19677ea97
@ -565,16 +565,10 @@ int csync_ftw(CSYNC *ctx, const char *uri, csync_walker_fn fn,
|
||||
continue;
|
||||
}
|
||||
|
||||
fullpath = uri;
|
||||
if (!fullpath.isEmpty())
|
||||
fullpath += '/';
|
||||
fullpath += filename;
|
||||
/* Only for the local replica we have to stat(), for the remote one we have all data already */
|
||||
if (ctx->current == LOCAL_REPLICA) {
|
||||
if (csync_vio_stat(ctx, fullpath, dirent.get()) != 0) {
|
||||
// Will get excluded by _csync_detect_update.
|
||||
dirent->type = CSYNC_FTW_TYPE_SKIP;
|
||||
}
|
||||
if (uri[0] == '\0') {
|
||||
fullpath = filename;
|
||||
} else {
|
||||
fullpath = QByteArray() % uri % '/' % filename;
|
||||
}
|
||||
|
||||
/* if the filename starts with a . we consider it a hidden file
|
||||
|
||||
@ -24,7 +24,6 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <QLoggingCategory>
|
||||
#include "common/asserts.h"
|
||||
|
||||
#include "csync_private.h"
|
||||
@ -34,8 +33,6 @@
|
||||
#include "csync_statedb.h"
|
||||
#include "common/c_jhash.h"
|
||||
|
||||
Q_LOGGING_CATEGORY(lcVio, "sync.csync.vio", QtInfoMsg)
|
||||
|
||||
csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name) {
|
||||
switch(ctx->current) {
|
||||
case REMOTE_REPLICA:
|
||||
@ -94,17 +91,6 @@ std::unique_ptr<csync_file_stat_t> csync_vio_readdir(CSYNC *ctx, csync_vio_handl
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int csync_vio_stat(CSYNC *ctx, const char *uri, csync_file_stat_t *buf) {
|
||||
int rc = -1;
|
||||
|
||||
ASSERT(ctx->current == LOCAL_REPLICA);
|
||||
rc = csync_vio_local_stat(uri, buf);
|
||||
if (rc < 0)
|
||||
qCWarning(lcVio, "Local stat failed, errno %d for %s", errno, uri);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx) {
|
||||
if(ctx->error_string) {
|
||||
return ctx->error_string;
|
||||
|
||||
@ -36,8 +36,6 @@ csync_vio_handle_t *csync_vio_opendir(CSYNC *ctx, const char *name);
|
||||
int csync_vio_closedir(CSYNC *ctx, csync_vio_handle_t *dhandle);
|
||||
std::unique_ptr<csync_file_stat_t> csync_vio_readdir(CSYNC *ctx, csync_vio_handle_t *dhandle);
|
||||
|
||||
int csync_vio_stat(CSYNC *ctx, const char *uri, csync_file_stat_t *buf);
|
||||
|
||||
char *csync_vio_get_status_string(CSYNC *ctx);
|
||||
|
||||
|
||||
|
||||
@ -45,6 +45,8 @@ typedef struct dhandle_s {
|
||||
char *path;
|
||||
} dhandle_t;
|
||||
|
||||
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 = NULL;
|
||||
mbchar_t *dirname = NULL;
|
||||
@ -84,7 +86,6 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *dhandle) {
|
||||
|
||||
dhandle_t *handle = NULL;
|
||||
@ -93,17 +94,17 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
struct _tdirent *dirent = NULL;
|
||||
std::unique_ptr<csync_file_stat_t> file_stat;
|
||||
|
||||
dirent = _treaddir(handle->dh);
|
||||
if (dirent == NULL) {
|
||||
return {};
|
||||
}
|
||||
do {
|
||||
dirent = _treaddir(handle->dh);
|
||||
if (dirent == NULL)
|
||||
return {};
|
||||
} while (qstrcmp(dirent->d_name, ".") == 0 || qstrcmp(dirent->d_name, "..") == 0);
|
||||
|
||||
file_stat.reset(new 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);
|
||||
if (file_stat->path.isNull()) {
|
||||
file_stat->original_path = handle->path;
|
||||
file_stat->original_path += '/';
|
||||
file_stat->original_path += dirent->d_name;
|
||||
file_stat->original_path = fullPath;
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_WARN, "Invalid characters in file/directory name, please rename: \"%s\" (%s)",
|
||||
dirent->d_name, handle->path);
|
||||
}
|
||||
@ -129,23 +130,35 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
}
|
||||
#endif
|
||||
|
||||
if (file_stat->path.isNull())
|
||||
return file_stat;
|
||||
|
||||
if (_csync_vio_local_stat_mb(fullPath.constData(), file_stat.get()) < 0) {
|
||||
// Will get excluded by _csync_detect_update.
|
||||
file_stat->type = CSYNC_FTW_TYPE_SKIP;
|
||||
}
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) {
|
||||
csync_stat_t sb;
|
||||
|
||||
mbchar_t *wuri = c_utf8_path_to_locale( uri );
|
||||
|
||||
if( _tstat(wuri, &sb) < 0) {
|
||||
int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf)
|
||||
{
|
||||
mbchar_t *wuri = c_utf8_path_to_locale(uri);
|
||||
*buf = csync_file_stat_t();
|
||||
int rc = _csync_vio_local_stat_mb(wuri, buf);
|
||||
c_free_locale_string(wuri);
|
||||
return -1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
*buf = csync_file_stat_t();
|
||||
static int _csync_vio_local_stat_mb(const mbchar_t *wuri, csync_file_stat_t *buf)
|
||||
{
|
||||
csync_stat_t sb;
|
||||
|
||||
switch(sb.st_mode & S_IFMT) {
|
||||
if (_tstat(wuri, &sb) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (sb.st_mode & S_IFMT) {
|
||||
case S_IFDIR:
|
||||
buf->type = CSYNC_FTW_TYPE_DIR;
|
||||
break;
|
||||
@ -170,7 +183,5 @@ int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) {
|
||||
buf->inode = sb.st_ino;
|
||||
buf->modtime = sb.st_mtime;
|
||||
buf->size = sb.st_size;
|
||||
|
||||
c_free_locale_string(wuri);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -45,9 +45,11 @@ typedef struct dhandle_s {
|
||||
WIN32_FIND_DATA ffd;
|
||||
HANDLE hFind;
|
||||
int firstFind;
|
||||
char *path;
|
||||
mbchar_t *path; // Always ends with '\'
|
||||
} dhandle_t;
|
||||
|
||||
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 = NULL;
|
||||
mbchar_t *dirname = NULL;
|
||||
@ -73,6 +75,7 @@ csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
|
||||
}
|
||||
|
||||
if (!dirname || handle->hFind == INVALID_HANDLE_VALUE) {
|
||||
c_free_locale_string(dirname);
|
||||
int retcode = GetLastError();
|
||||
if( retcode == ERROR_FILE_NOT_FOUND ) {
|
||||
errno = ENOENT;
|
||||
@ -85,8 +88,8 @@ csync_vio_handle_t *csync_vio_local_opendir(const char *name) {
|
||||
|
||||
handle->firstFind = 1; // Set a flag that there first fileinfo is available.
|
||||
|
||||
handle->path = c_strdup(name);
|
||||
c_free_locale_string(dirname);
|
||||
dirname[std::wcslen(dirname) - 1] = L'\0'; // remove the *
|
||||
handle->path = dirname;
|
||||
|
||||
return (csync_vio_handle_t *) handle;
|
||||
}
|
||||
@ -109,7 +112,7 @@ int csync_vio_local_closedir(csync_vio_handle_t *dhandle) {
|
||||
errno = EBADF;
|
||||
}
|
||||
|
||||
SAFE_FREE(handle->path);
|
||||
c_free_locale_string(handle->path);
|
||||
SAFE_FREE(handle);
|
||||
|
||||
return rc;
|
||||
@ -158,20 +161,24 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
file_stat.reset(new csync_file_stat_t);
|
||||
file_stat->path = c_utf8_from_locale(handle->ffd.cFileName);
|
||||
auto path = c_utf8_from_locale(handle->ffd.cFileName);
|
||||
if (path == "." || path == "..")
|
||||
return csync_vio_local_readdir(dhandle);
|
||||
|
||||
if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
// Detect symlinks, and treat junctions as symlinks too.
|
||||
if (handle->ffd.dwReserved0 == IO_REPARSE_TAG_SYMLINK
|
||||
|| handle->ffd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
file_stat->type = CSYNC_FTW_TYPE_SLINK;
|
||||
} else {
|
||||
// The SIS and DEDUP reparse points should be treated as
|
||||
// regular files. We don't know about the other ones yet,
|
||||
// but will also treat them normally for now.
|
||||
file_stat->type = CSYNC_FTW_TYPE_FILE;
|
||||
}
|
||||
file_stat.reset(new csync_file_stat_t);
|
||||
file_stat->path = path;
|
||||
|
||||
if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
// Detect symlinks, and treat junctions as symlinks too.
|
||||
if (handle->ffd.dwReserved0 == IO_REPARSE_TAG_SYMLINK
|
||||
|| handle->ffd.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
file_stat->type = CSYNC_FTW_TYPE_SLINK;
|
||||
} else {
|
||||
// The SIS and DEDUP reparse points should be treated as
|
||||
// regular files. We don't know about the other ones yet,
|
||||
// but will also treat them normally for now.
|
||||
file_stat->type = CSYNC_FTW_TYPE_FILE;
|
||||
}
|
||||
} else if (handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_DEVICE
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE
|
||||
|| handle->ffd.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) {
|
||||
@ -189,12 +196,31 @@ std::unique_ptr<csync_file_stat_t> csync_vio_local_readdir(csync_vio_handle_t *d
|
||||
|
||||
file_stat->size = (handle->ffd.nFileSizeHigh * ((int64_t)(MAXDWORD)+1)) + handle->ffd.nFileSizeLow;
|
||||
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 += handle->ffd.cFileName;
|
||||
|
||||
if (_csync_vio_local_stat_mb(fullPath.data(), file_stat.get()) < 0) {
|
||||
// Will get excluded by _csync_detect_update.
|
||||
file_stat->type = CSYNC_FTW_TYPE_SKIP;
|
||||
}
|
||||
|
||||
return file_stat;
|
||||
}
|
||||
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf)
|
||||
{
|
||||
mbchar_t *wuri = c_utf8_path_to_locale(uri);
|
||||
int rc = _csync_vio_local_stat_mb(wuri, buf);
|
||||
c_free_locale_string(wuri);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) {
|
||||
static int _csync_vio_local_stat_mb(const mbchar_t *wuri, 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.
|
||||
Possible optimisation: only fetch the file id when we need it (for new files)
|
||||
@ -203,23 +229,20 @@ int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) {
|
||||
HANDLE h;
|
||||
BY_HANDLE_FILE_INFORMATION fileInfo;
|
||||
ULARGE_INTEGER FileIndex;
|
||||
mbchar_t *wuri = c_utf8_path_to_locale( uri );
|
||||
|
||||
h = CreateFileW( wuri, 0, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
NULL );
|
||||
if( h == INVALID_HANDLE_VALUE ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "CreateFileW failed on %s", uri );
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "CreateFileW failed on %ls", wuri);
|
||||
errno = GetLastError();
|
||||
c_free_locale_string(wuri);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!GetFileInformationByHandle( h, &fileInfo ) ) {
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "GetFileInformationByHandle failed on %s", uri );
|
||||
CSYNC_LOG(CSYNC_LOG_PRIORITY_CRIT, "GetFileInformationByHandle failed on %ls", wuri);
|
||||
errno = GetLastError();
|
||||
c_free_locale_string(wuri);
|
||||
CloseHandle(h);
|
||||
return -1;
|
||||
}
|
||||
@ -235,7 +258,6 @@ int csync_vio_local_stat(const char *uri, csync_file_stat_t *buf) {
|
||||
DWORD rem;
|
||||
buf->modtime = FileTimeToUnixTime(&fileInfo.ftLastWriteTime, &rem);
|
||||
|
||||
c_free_locale_string(wuri);
|
||||
CloseHandle(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user