mirror of
https://github.com/nextcloud/desktop.git
synced 2024-11-26 06:55:59 +03:00
Merge pull request #3016 from nextcloud/fix_for_win_createfile_long_path
Fix for Windows CreateFile long path
This commit is contained in:
commit
6abb0b2184
3 changed files with 34 additions and 21 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -403,7 +411,7 @@ OCC::CfApiWrapper::PlaceHolderInfo OCC::CfApiWrapper::findPlaceholderInfo(const
|
|||
}
|
||||
}
|
||||
|
||||
OCC::Result<void, QString> OCC::CfApiWrapper::setPinState(const FileHandle &handle, PinState state, SetPinRecurseMode mode)
|
||||
OCC::Result<void, QString> OCC::CfApiWrapper::setPinState(const FileHandle &handle, OCC::PinStateEnums::PinState state, SetPinRecurseMode mode)
|
||||
{
|
||||
const auto cfState = pinStateToCfPinState(state);
|
||||
const auto flags = pinRecurseModeToCfSetPinFlags(mode);
|
||||
|
@ -413,7 +421,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::setPinState(const FileHandle &hand
|
|||
return {};
|
||||
} else {
|
||||
qCWarning(lcCfApiWrapper) << "Couldn't set pin state" << state << "for" << pathForHandle(handle) << "with recurse mode" << mode << ":" << _com_error(result).ErrorMessage();
|
||||
return "Couldn't set pin state";
|
||||
return { "Couldn't set pin state" };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,7 +456,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::createPlaceholderInfo(const QStrin
|
|||
const qint64 result = CfCreatePlaceholders(localBasePath.data(), &cloudEntry, 1, CF_CREATE_FLAG_NONE, nullptr);
|
||||
if (result != S_OK) {
|
||||
qCWarning(lcCfApiWrapper) << "Couldn't create placeholder info for" << path << ":" << _com_error(result).ErrorMessage();
|
||||
return "Couldn't create placeholder info";
|
||||
return { "Couldn't create placeholder info" };
|
||||
}
|
||||
|
||||
const auto parentHandle = handleForPath(QDir::toNativeSeparators(QFileInfo(path).absolutePath()));
|
||||
|
@ -457,7 +465,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::createPlaceholderInfo(const QStrin
|
|||
|
||||
const auto handle = handleForPath(path);
|
||||
if (!setPinState(handle, cfPinStateToPinState(state), NoRecurse)) {
|
||||
return "Couldn't set the default inherit pin state";
|
||||
return { "Couldn't set the default inherit pin state" };
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -470,7 +478,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::updatePlaceholderInfo(const FileHa
|
|||
const auto info = replacesPath.isEmpty() ? findPlaceholderInfo(handle)
|
||||
: findPlaceholderInfo(handleForPath(replacesPath));
|
||||
if (!info) {
|
||||
return "Can't update non existing placeholder info";
|
||||
return { "Can't update non existing placeholder info" };
|
||||
}
|
||||
|
||||
const auto previousPinState = cfPinStateToPinState(info->PinState);
|
||||
|
@ -490,12 +498,12 @@ OCC::Result<void, QString> OCC::CfApiWrapper::updatePlaceholderInfo(const FileHa
|
|||
|
||||
if (result != S_OK) {
|
||||
qCWarning(lcCfApiWrapper) << "Couldn't update placeholder info for" << pathForHandle(handle) << ":" << _com_error(result).ErrorMessage();
|
||||
return "Couldn't update placeholder info";
|
||||
return { "Couldn't update placeholder info" };
|
||||
}
|
||||
|
||||
// Pin state tends to be lost on updates, so restore it every time
|
||||
if (!setPinState(handle, previousPinState, NoRecurse)) {
|
||||
return "Couldn't restore pin state";
|
||||
return { "Couldn't restore pin state" };
|
||||
}
|
||||
|
||||
return {};
|
||||
|
@ -503,6 +511,9 @@ OCC::Result<void, QString> OCC::CfApiWrapper::updatePlaceholderInfo(const FileHa
|
|||
|
||||
OCC::Result<void, QString> OCC::CfApiWrapper::convertToPlaceholder(const FileHandle &handle, time_t modtime, qint64 size, const QByteArray &fileId, const QString &replacesPath)
|
||||
{
|
||||
Q_UNUSED(modtime);
|
||||
Q_UNUSED(size);
|
||||
|
||||
Q_ASSERT(handle);
|
||||
|
||||
const auto fileIdentity = QString::fromUtf8(fileId).toStdWString();
|
||||
|
@ -511,7 +522,7 @@ OCC::Result<void, QString> OCC::CfApiWrapper::convertToPlaceholder(const FileHan
|
|||
Q_ASSERT(result == S_OK);
|
||||
if (result != S_OK) {
|
||||
qCCritical(lcCfApiWrapper) << "Couldn't convert to placeholder" << pathForHandle(handle) << ":" << _com_error(result).ErrorMessage();
|
||||
return "Couldn't convert to placeholder";
|
||||
return { "Couldn't convert to placeholder" };
|
||||
}
|
||||
|
||||
const auto originalHandle = handleForPath(replacesPath);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue