# Essentially they could be in the same directory but are separate to
# help keep track of the different code licenses.
set(common_SOURCES
+ ${CMAKE_CURRENT_LIST_DIR}/filesystembase.cpp
${CMAKE_CURRENT_LIST_DIR}/utility.cpp
)
--- /dev/null
+/*
+ * Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "filesystembase.h"
+
+#include <QDateTime>
+#include <QFile>
+#include <QCryptographicHash>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#ifdef ZLIB_FOUND
+#include <zlib.h>
+#endif
+
+#ifdef Q_OS_WIN
+#include <windows.h>
+#include <windef.h>
+#include <winbase.h>
+#include <fcntl.h>
+#include <io.h>
+#endif
+
+namespace OCC {
+
+Q_LOGGING_CATEGORY(lcFileSystem, "sync.filesystem", QtInfoMsg)
+
+QString FileSystem::longWinPath(const QString &inpath)
+{
+#ifdef Q_OS_WIN
+ return pathtoUNC(inpath);
+#else
+ return inpath;
+#endif
+}
+
+void FileSystem::setFileHidden(const QString &filename, bool hidden)
+{
+#ifdef _WIN32
+ QString fName = longWinPath(filename);
+ DWORD dwAttrs;
+
+ dwAttrs = GetFileAttributesW((wchar_t *)fName.utf16());
+
+ if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
+ if (hidden && !(dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
+ SetFileAttributesW((wchar_t *)fName.utf16(), dwAttrs | FILE_ATTRIBUTE_HIDDEN);
+ } else if (!hidden && (dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
+ SetFileAttributesW((wchar_t *)fName.utf16(), dwAttrs & ~FILE_ATTRIBUTE_HIDDEN);
+ }
+ }
+#else
+ Q_UNUSED(filename);
+ Q_UNUSED(hidden);
+#endif
+}
+
+static QFile::Permissions getDefaultWritePermissions()
+{
+ QFile::Permissions result = QFile::WriteUser;
+#ifndef Q_OS_WIN
+ mode_t mask = umask(0);
+ umask(mask);
+ if (!(mask & S_IWGRP)) {
+ result |= QFile::WriteGroup;
+ }
+ if (!(mask & S_IWOTH)) {
+ result |= QFile::WriteOther;
+ }
+#endif
+ return result;
+}
+
+void FileSystem::setFileReadOnly(const QString &filename, bool readonly)
+{
+ QFile file(filename);
+ QFile::Permissions permissions = file.permissions();
+
+ QFile::Permissions allWritePermissions =
+ QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther | QFile::WriteOwner;
+ static QFile::Permissions defaultWritePermissions = getDefaultWritePermissions();
+
+ permissions &= ~allWritePermissions;
+ if (!readonly) {
+ permissions |= defaultWritePermissions;
+ }
+ file.setPermissions(permissions);
+}
+
+void FileSystem::setFolderMinimumPermissions(const QString &filename)
+{
+#ifdef Q_OS_MAC
+ QFile::Permissions perm = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
+ QFile file(filename);
+ file.setPermissions(perm);
+#else
+ Q_UNUSED(filename);
+#endif
+}
+
+
+void FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly)
+{
+ QFile file(filename);
+ QFile::Permissions permissions = file.permissions();
+
+ if (!readonly && (permissions & QFile::WriteOwner)) {
+ return; // already writable enough
+ }
+
+ setFileReadOnly(filename, readonly);
+}
+
+bool FileSystem::rename(const QString &originFileName,
+ const QString &destinationFileName,
+ QString *errorString)
+{
+ bool success = false;
+ QString error;
+#ifdef Q_OS_WIN
+ QString orig = longWinPath(originFileName);
+ QString dest = longWinPath(destinationFileName);
+
+ if (isLnkFile(originFileName) || isLnkFile(destinationFileName)) {
+ success = MoveFileEx((wchar_t *)orig.utf16(),
+ (wchar_t *)dest.utf16(),
+ MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH);
+ if (!success) {
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string, 0, NULL);
+
+ error = QString::fromWCharArray(string);
+ LocalFree((HLOCAL)string);
+ }
+ } else
+#endif
+ {
+ QFile orig(originFileName);
+ success = orig.rename(destinationFileName);
+ if (!success) {
+ error = orig.errorString();
+ }
+ }
+
+ if (!success) {
+ qCWarning(lcFileSystem) << "Error renaming file" << originFileName
+ << "to" << destinationFileName
+ << "failed: " << error;
+ if (errorString) {
+ *errorString = error;
+ }
+ }
+ return success;
+}
+
+bool FileSystem::uncheckedRenameReplace(const QString &originFileName,
+ const QString &destinationFileName,
+ QString *errorString)
+{
+#ifndef Q_OS_WIN
+ bool success;
+ QFile orig(originFileName);
+ // We want a rename that also overwites. QFile::rename does not overwite.
+ // Qt 5.1 has QSaveFile::renameOverwrite we could use.
+ // ### FIXME
+ success = true;
+ bool destExists = fileExists(destinationFileName);
+ if (destExists && !QFile::remove(destinationFileName)) {
+ *errorString = orig.errorString();
+ qCWarning(lcFileSystem) << "Target file could not be removed.";
+ success = false;
+ }
+ if (success) {
+ success = orig.rename(destinationFileName);
+ }
+ if (!success) {
+ *errorString = orig.errorString();
+ qCWarning(lcFileSystem) << "Renaming temp file to final failed: " << *errorString;
+ return false;
+ }
+
+#else //Q_OS_WIN
+ // You can not overwrite a read-only file on windows.
+ if (!QFileInfo(destinationFileName).isWritable()) {
+ setFileReadOnly(destinationFileName, false);
+ }
+
+ BOOL ok;
+ QString orig = longWinPath(originFileName);
+ QString dest = longWinPath(destinationFileName);
+
+ ok = MoveFileEx((wchar_t *)orig.utf16(),
+ (wchar_t *)dest.utf16(),
+ MOVEFILE_REPLACE_EXISTING + MOVEFILE_COPY_ALLOWED + MOVEFILE_WRITE_THROUGH);
+ if (!ok) {
+ wchar_t *string = 0;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPWSTR)&string, 0, NULL);
+
+ *errorString = QString::fromWCharArray(string);
+ qCWarning(lcFileSystem) << "Renaming temp file to final failed: " << *errorString;
+ LocalFree((HLOCAL)string);
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qint64 seek)
+{
+ QString errorDummy;
+ // avoid many if (errorOrNull) later.
+ QString &error = errorOrNull ? *errorOrNull : errorDummy;
+ error.clear();
+
+#ifdef Q_OS_WIN
+ //
+ // The following code is adapted from Qt's QFSFileEnginePrivate::nativeOpen()
+ // by including the FILE_SHARE_DELETE share mode.
+ //
+
+ // Enable full sharing.
+ DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
+
+ int accessRights = GENERIC_READ;
+ DWORD creationDisp = OPEN_EXISTING;
+
+ // Create the file handle.
+ SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
+ QString fName = longWinPath(file->fileName());
+
+ HANDLE fileHandle = CreateFileW(
+ (const wchar_t *)fName.utf16(),
+ accessRights,
+ shareMode,
+ &securityAtts,
+ creationDisp,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ // Bail out on error.
+ if (fileHandle == INVALID_HANDLE_VALUE) {
+ error = qt_error_string();
+ return false;
+ }
+
+ // Convert the HANDLE to an fd and pass it to QFile's foreign-open
+ // function. The fd owns the handle, so when QFile later closes
+ // the fd the handle will be closed too.
+ int fd = _open_osfhandle((intptr_t)fileHandle, _O_RDONLY);
+ if (fd == -1) {
+ error = "could not make fd from handle";
+ return false;
+ }
+ if (!file->open(fd, QIODevice::ReadOnly, QFile::AutoCloseHandle)) {
+ error = file->errorString();
+ return false;
+ }
+
+ // Seek to the right spot
+ LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER *>(&seek);
+ DWORD newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
+ if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
+ error = qt_error_string();
+ return false;
+ }
+
+ return true;
+#else
+ if (!file->open(QFile::ReadOnly)) {
+ error = file->errorString();
+ return false;
+ }
+ if (!file->seek(seek)) {
+ error = file->errorString();
+ return false;
+ }
+ return true;
+#endif
+}
+
+#ifdef Q_OS_WIN
+static bool fileExistsWin(const QString &filename)
+{
+ WIN32_FIND_DATA FindFileData;
+ HANDLE hFind;
+ QString fName = FileSystem::longWinPath(filename);
+
+ hFind = FindFirstFileW((wchar_t *)fName.utf16(), &FindFileData);
+ if (hFind == INVALID_HANDLE_VALUE) {
+ return false;
+ }
+ FindClose(hFind);
+ return true;
+}
+#endif
+
+bool FileSystem::fileExists(const QString &filename, const QFileInfo &fileInfo)
+{
+#ifdef Q_OS_WIN
+ if (isLnkFile(filename)) {
+ // Use a native check.
+ return fileExistsWin(filename);
+ }
+#endif
+ bool re = fileInfo.exists();
+ // if the filename is different from the filename in fileInfo, the fileInfo is
+ // not valid. There needs to be one initialised here. Otherwise the incoming
+ // fileInfo is re-used.
+ if (fileInfo.filePath() != filename) {
+ QFileInfo myFI(filename);
+ re = myFI.exists();
+ }
+ return re;
+}
+
+#ifdef Q_OS_WIN
+QString FileSystem::fileSystemForPath(const QString &path)
+{
+ // See also QStorageInfo (Qt >=5.4) and GetVolumeInformationByHandleW (>= Vista)
+ QString drive = path.left(2);
+ if (!drive.endsWith(":"))
+ return QString();
+ drive.append('\\');
+
+ const size_t fileSystemBufferSize = 4096;
+ TCHAR fileSystemBuffer[fileSystemBufferSize];
+
+ if (!GetVolumeInformationW(
+ reinterpret_cast<LPCWSTR>(drive.utf16()),
+ NULL, 0,
+ NULL, NULL, NULL,
+ fileSystemBuffer, fileSystemBufferSize)) {
+ return QString();
+ }
+ return QString::fromUtf16(reinterpret_cast<const ushort *>(fileSystemBuffer));
+}
+#endif
+
+#define BUFSIZE qint64(500 * 1024) // 500 KiB
+
+static QByteArray readToCrypto(const QString &filename, QCryptographicHash::Algorithm algo)
+{
+ QFile file(filename);
+ const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
+ QByteArray buf(bufSize, Qt::Uninitialized);
+ QByteArray arr;
+ QCryptographicHash crypto(algo);
+
+ if (file.open(QIODevice::ReadOnly)) {
+ qint64 size;
+ while (!file.atEnd()) {
+ size = file.read(buf.data(), bufSize);
+ if (size > 0) {
+ crypto.addData(buf.data(), size);
+ }
+ }
+ arr = crypto.result().toHex();
+ }
+ return arr;
+}
+
+QByteArray FileSystem::calcMd5(const QString &filename)
+{
+ return readToCrypto(filename, QCryptographicHash::Md5);
+}
+
+QByteArray FileSystem::calcSha1(const QString &filename)
+{
+ return readToCrypto(filename, QCryptographicHash::Sha1);
+}
+
+#ifdef ZLIB_FOUND
+QByteArray FileSystem::calcAdler32(const QString &filename)
+{
+ QFile file(filename);
+ const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
+ QByteArray buf(bufSize, Qt::Uninitialized);
+
+ unsigned int adler = adler32(0L, Z_NULL, 0);
+ if (file.open(QIODevice::ReadOnly)) {
+ qint64 size;
+ while (!file.atEnd()) {
+ size = file.read(buf.data(), bufSize);
+ if (size > 0)
+ adler = adler32(adler, (const Bytef *)buf.data(), size);
+ }
+ }
+
+ return QByteArray::number(adler, 16);
+}
+#endif
+
+QString FileSystem::makeConflictFileName(const QString &fn, const QDateTime &dt)
+{
+ QString conflictFileName(fn);
+ // Add _conflict-XXXX before the extension.
+ int dotLocation = conflictFileName.lastIndexOf('.');
+ // If no extension, add it at the end (take care of cases like foo/.hidden or foo.bar/file)
+ if (dotLocation <= conflictFileName.lastIndexOf('/') + 1) {
+ dotLocation = conflictFileName.size();
+ }
+ QString timeString = dt.toString("yyyyMMdd-hhmmss");
+
+ // Additional marker
+ QByteArray conflictFileUserName = qgetenv("CSYNC_CONFLICT_FILE_USERNAME");
+ if (conflictFileUserName.isEmpty())
+ conflictFileName.insert(dotLocation, "_conflict-" + timeString);
+ else
+ conflictFileName.insert(dotLocation, "_conflict_" + QString::fromUtf8(conflictFileUserName) + "-" + timeString);
+
+ return conflictFileName;
+}
+
+bool FileSystem::remove(const QString &fileName, QString *errorString)
+{
+#ifdef Q_OS_WIN
+ // You cannot delete a read-only file on windows, but we want to
+ // allow that.
+ if (!QFileInfo(fileName).isWritable()) {
+ setFileReadOnly(fileName, false);
+ }
+#endif
+ QFile f(fileName);
+ if (!f.remove()) {
+ if (errorString) {
+ *errorString = f.errorString();
+ }
+ return false;
+ }
+ return true;
+}
+
+bool FileSystem::isFileLocked(const QString &fileName)
+{
+#ifdef Q_OS_WIN
+ const wchar_t *wuri = reinterpret_cast<const wchar_t *>(fileName.utf16());
+ // Check if file exists
+ DWORD attr = GetFileAttributesW(wuri);
+ if (attr != INVALID_FILE_ATTRIBUTES) {
+ // Try to open the file with as much access as possible..
+ HANDLE win_h = CreateFileW(
+ wuri,
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL, OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
+ NULL);
+
+ if (win_h == INVALID_HANDLE_VALUE) {
+ /* could not be opened, so locked? */
+ /* 32 == ERROR_SHARING_VIOLATION */
+ return true;
+ } else {
+ CloseHandle(win_h);
+ }
+ }
+#else
+ Q_UNUSED(fileName);
+#endif
+ return false;
+}
+
+bool FileSystem::isLnkFile(const QString &filename)
+{
+ return filename.endsWith(".lnk");
+}
+
+} // namespace OCC
--- /dev/null
+/*
+ * Copyright (C) by Olivier Goffart <ogoffart@owncloud.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "config.h"
+
+#include <QString>
+#include <ctime>
+#include <QFileInfo>
+#include <QLoggingCategory>
+
+#include <ocsynclib.h>
+
+class QFile;
+
+namespace OCC {
+
+OCSYNC_EXPORT Q_DECLARE_LOGGING_CATEGORY(lcFileSystem)
+
+/**
+ * \addtogroup libsync
+ * @{
+ */
+
+/**
+ * @brief This file contains file system helper
+ */
+namespace FileSystem {
+
+ /**
+ * @brief Mark the file as hidden (only has effects on windows)
+ */
+ void OCSYNC_EXPORT setFileHidden(const QString &filename, bool hidden);
+
+ /**
+ * @brief Marks the file as read-only.
+ *
+ * On linux this either revokes all 'w' permissions or restores permissions
+ * according to the umask.
+ */
+ void OCSYNC_EXPORT setFileReadOnly(const QString &filename, bool readonly);
+
+ /**
+ * @brief Marks the file as read-only.
+ *
+ * It's like setFileReadOnly(), but weaker: if readonly is false and the user
+ * already has write permissions, no change to the permissions is made.
+ *
+ * This means that it will preserve explicitly set rw-r--r-- permissions even
+ * when the umask is 0002. (setFileReadOnly() would adjust to rw-rw-r--)
+ */
+ void OCSYNC_EXPORT setFileReadOnlyWeak(const QString &filename, bool readonly);
+
+ /**
+ * @brief Try to set permissions so that other users on the local machine can not
+ * go into the folder.
+ */
+ void OCSYNC_EXPORT setFolderMinimumPermissions(const QString &filename);
+
+ /** convert a "normal" windows path into a path that can be 32k chars long. */
+ QString OCSYNC_EXPORT longWinPath(const QString &inpath);
+
+ /**
+ * @brief Checks whether a file exists.
+ *
+ * Use this over QFileInfo::exists() and QFile::exists() to avoid bugs with lnk
+ * files, see above.
+ */
+ bool OCSYNC_EXPORT fileExists(const QString &filename, const QFileInfo & = QFileInfo());
+
+ /**
+ * @brief Rename the file \a originFileName to \a destinationFileName.
+ *
+ * It behaves as QFile::rename() but handles .lnk files correctly on Windows.
+ */
+ bool OCSYNC_EXPORT rename(const QString &originFileName,
+ const QString &destinationFileName,
+ QString *errorString = NULL);
+
+ /**
+ * Rename the file \a originFileName to \a destinationFileName, and
+ * overwrite the destination if it already exists - without extra checks.
+ */
+ bool OCSYNC_EXPORT uncheckedRenameReplace(const QString &originFileName,
+ const QString &destinationFileName,
+ QString *errorString);
+
+ /**
+ * Removes a file.
+ *
+ * Equivalent to QFile::remove(), except on Windows, where it will also
+ * successfully remove read-only files.
+ */
+ bool OCSYNC_EXPORT remove(const QString &fileName, QString *errorString = 0);
+
+ /**
+ * Replacement for QFile::open(ReadOnly) followed by a seek().
+ * This version sets a more permissive sharing mode on Windows.
+ *
+ * Warning: The resulting file may have an empty fileName and be unsuitable for use
+ * with QFileInfo! Calling seek() on the QFile with >32bit signed values will fail!
+ */
+ bool OCSYNC_EXPORT openAndSeekFileSharedRead(QFile *file, QString *error, qint64 seek);
+
+#ifdef Q_OS_WIN
+ /**
+ * Returns the file system used at the given path.
+ */
+ QString fileSystemForPath(const QString &path);
+#endif
+
+ QByteArray OCSYNC_EXPORT calcMd5(const QString &fileName);
+ QByteArray OCSYNC_EXPORT calcSha1(const QString &fileName);
+#ifdef ZLIB_FOUND
+ QByteArray OCSYNC_EXPORT calcAdler32(const QString &fileName);
+#endif
+
+ /**
+ * Returns a file name based on \a fn that's suitable for a conflict.
+ */
+ QString OCSYNC_EXPORT makeConflictFileName(const QString &fn, const QDateTime &dt);
+
+ /**
+ * Returns true when a file is locked. (Windows only)
+ */
+ bool OCSYNC_EXPORT isFileLocked(const QString &fileName);
+
+ bool OCSYNC_EXPORT isLnkFile(const QString &filename);
+
+ /*
+ * This function takes a path and converts it to a UNC representation of the
+ * string. That means that it prepends a \\?\ (unless already UNC) and converts
+ * all slashes to backslashes.
+ *
+ * Note the following:
+ * - The string must be absolute.
+ * - it needs to contain a drive character to be a valid UNC
+ * - A conversion is only done if the path len is larger than 245. Otherwise
+ * the windows API functions work with the normal "unixoid" representation too.
+ */
+ template<typename S>
+ S pathtoUNC(const S &str)
+ {
+ int len = 0;
+ S longStr;
+
+ len = str.length();
+ longStr.reserve(len+4);
+
+ // prepend \\?\ and convert '/' => '\' to support long names
+ if( str[0] == '/' || str[0] == '\\' ) {
+ // Don't prepend if already UNC
+ if( !(len > 1 && (str[1] == '/' || str[1] == '\\')) ) {
+ longStr.append("\\\\?");
+ }
+ } else {
+ longStr.append("\\\\?\\"); // prepend string by this four magic chars.
+ }
+ longStr += str;
+
+ /* replace all occurences of / with the windows native \ */
+
+ for (auto it = longStr.begin(); it != longStr.end(); ++it) {
+ if(*it == '/') {
+ *it = '\\';
+ }
+ }
+ return longStr;
+ }
+}
+
+/** @} */
+}
target_link_libraries(${CSYNC_LIBRARY} ${CSYNC_LINK_LIBRARIES})
#target_link_libraries(${CSYNC_LIBRARY}_static ${CSYNC_LINK_LIBRARIES})
+if(ZLIB_FOUND)
+ target_link_libraries(${CSYNC_LIBRARY} ${ZLIB_LIBRARIES})
+ include_directories(${ZLIB_INCLUDE_DIRS})
+endif(ZLIB_FOUND)
+
find_package(Qt5Core REQUIRED)
qt5_use_modules(${CSYNC_LIBRARY} Core)
return -1;
}
-
-
-/*
- * This function takes a path and converts it to a UNC representation of the
- * string. That means that it prepends a \\?\ (unless already UNC) and converts
- * all slashes to backslashes.
- *
- * Note the following:
- * - The string must be absolute.
- * - it needs to contain a drive character to be a valid UNC
- * - A conversion is only done if the path len is larger than 245. Otherwise
- * the windows API functions work with the normal "unixoid" representation too.
- *
- * This function allocates memory that must be freed by the caller.
- */
- const char *c_path_to_UNC(const char *str)
- {
- int len = 0;
- char *longStr = NULL;
-
- len = strlen(str);
- longStr = c_malloc(len+5);
- *longStr = '\0';
-
- // prepend \\?\ and convert '/' => '\' to support long names
- if( str[0] == '/' || str[0] == '\\' ) {
- // Don't prepend if already UNC
- if( !(len > 1 && (str[1] == '/' || str[1] == '\\')) ) {
- strcpy( longStr, "\\\\?");
- }
- } else {
- strcpy( longStr, "\\\\?\\"); // prepend string by this four magic chars.
- }
- strncat( longStr, str, len );
-
- /* replace all occurences of / with the windows native \ */
- char *c = longStr;
- for (; *c; ++c) {
- if(*c == '/') {
- *c = '\\';
- }
- }
- return longStr;
- }
-
- mbchar_t* c_utf8_path_to_locale(const char *str)
- {
- if( str == NULL ) {
- return NULL;
- } else {
- #ifdef _WIN32
- const char *unc_str = c_path_to_UNC(str);
- mbchar_t *dst = c_utf8_string_to_locale(unc_str);
- SAFE_FREE(unc_str);
- return dst;
- #else
- return c_utf8_string_to_locale(str);
- #endif
- }
- }
char * extension;
} C_PATHINFO;
-/**
- * @brief c_path_to_UNC converts a unixoid path to UNC format.
- *
- * It converts the '/' to '\' and prepends \\?\ to the path.
- *
- * A proper windows path has to have a drive letter, otherwise it is not
- * valid UNC.
- *
- * @param str The path to convert
- *
- * @return a pointer to the converted string. Caller has to free it.
- */
-const char *c_path_to_UNC(const char *str);
-
-/**
- * @brief c_utf8_path_to_locale converts a unixoid path to the locale aware format
- *
- * On windows, it converts to UNC and multibyte.
- * On Mac, it converts to the correct utf8 using iconv.
- * On Linux, it returns utf8
- *
- * @param str The path to convert
- *
- * @return a pointer to the converted string. Caller has to free it using the
- * function c_free_locale_string.
- */
-mbchar_t* c_utf8_path_to_locale(const char *str);
-
/**
* }@
*/
#include "c_alloc.h"
#include "c_string.h"
+#include "common/filesystembase.h"
/* Convert a locale String to UTF8 */
QByteArray c_utf8_from_locale(const mbchar_t *wstr)
#endif
}
+ mbchar_t* c_utf8_path_to_locale(const char *str)
+ {
+ if( str == NULL ) {
+ return NULL;
+ } else {
+ #ifdef _WIN32
+ QByteArray unc_str = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(str, strlen(str)));
+ mbchar_t *dst = c_utf8_string_to_locale(unc_str);
+ return dst;
+ #else
+ return c_utf8_string_to_locale(str);
+ #endif
+ }
+ }
+
}
*/
mbchar_t* c_utf8_string_to_locale(const char *wstr);
+/**
+ * @brief c_utf8_path_to_locale converts a unixoid path to the locale aware format
+ *
+ * On windows, it converts to UNC and multibyte.
+ * On Mac, it converts to the correct utf8 using iconv.
+ * On Linux, it returns utf8
+ *
+ * @param str The path to convert
+ *
+ * @return a pointer to the converted string. Caller has to free it using the
+ * function c_free_locale_string.
+ */
+mbchar_t* c_utf8_path_to_locale(const char *str);
+
/**
* @brief Free buffer malloced by c_utf8_to_locale().
*
link_directories(${INOTIFY_LIBRARY_DIR})
endif()
-if(ZLIB_FOUND)
- list(APPEND libsync_LINK_TARGETS ${ZLIB_LIBRARIES})
- include_directories(${ZLIB_INCLUDE_DIRS})
-endif(ZLIB_FOUND)
-
add_library(${synclib_NAME} SHARED ${libsync_SRCS} ${syncMoc})
GENERATE_EXPORT_HEADER( ${synclib_NAME}
BASE_NAME ${synclib_NAME}
#include "common/utility.h"
#include <QFile>
#include <QFileInfo>
-#include <QLoggingCategory>
-#include <QCoreApplication>
-#include <QCryptographicHash>
-
-#ifdef ZLIB_FOUND
-#include <zlib.h>
-#endif
-
-#ifdef Q_OS_WIN
-#include <windows.h>
-#include <windef.h>
-#include <winbase.h>
-#include <fcntl.h>
-#include <io.h>
-#endif
// We use some internals of csync:
extern "C" int c_utimes(const char *, const struct timeval *);
namespace OCC {
-Q_LOGGING_CATEGORY(lcFileSystem, "sync.filesystem", QtInfoMsg)
-
-QString FileSystem::longWinPath(const QString &inpath)
-{
-#ifdef Q_OS_WIN
- const char *unc_str = c_path_to_UNC(inpath.toUtf8());
- QString path = QString::fromUtf8(unc_str);
- free((void*)unc_str);
- return path;
-#else
- return inpath;
-#endif
-}
-
bool FileSystem::fileEquals(const QString &fn1, const QString &fn2)
{
// compare two files with given filename and return true if they have the same content
return false;
}
-void FileSystem::setFileHidden(const QString &filename, bool hidden)
-{
-#ifdef _WIN32
- QString fName = longWinPath(filename);
- DWORD dwAttrs;
-
- dwAttrs = GetFileAttributesW((wchar_t *)fName.utf16());
-
- if (dwAttrs != INVALID_FILE_ATTRIBUTES) {
- if (hidden && !(dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
- SetFileAttributesW((wchar_t *)fName.utf16(), dwAttrs | FILE_ATTRIBUTE_HIDDEN);
- } else if (!hidden && (dwAttrs & FILE_ATTRIBUTE_HIDDEN)) {
- SetFileAttributesW((wchar_t *)fName.utf16(), dwAttrs & ~FILE_ATTRIBUTE_HIDDEN);
- }
- }
-#else
- Q_UNUSED(filename);
- Q_UNUSED(hidden);
-#endif
-}
-
-static QFile::Permissions getDefaultWritePermissions()
-{
- QFile::Permissions result = QFile::WriteUser;
-#ifndef Q_OS_WIN
- mode_t mask = umask(0);
- umask(mask);
- if (!(mask & S_IWGRP)) {
- result |= QFile::WriteGroup;
- }
- if (!(mask & S_IWOTH)) {
- result |= QFile::WriteOther;
- }
-#endif
- return result;
-}
-
-void FileSystem::setFileReadOnly(const QString &filename, bool readonly)
-{
- QFile file(filename);
- QFile::Permissions permissions = file.permissions();
-
- QFile::Permissions allWritePermissions =
- QFile::WriteUser | QFile::WriteGroup | QFile::WriteOther | QFile::WriteOwner;
- static QFile::Permissions defaultWritePermissions = getDefaultWritePermissions();
-
- permissions &= ~allWritePermissions;
- if (!readonly) {
- permissions |= defaultWritePermissions;
- }
- file.setPermissions(permissions);
-}
-
-void FileSystem::setFolderMinimumPermissions(const QString &filename)
-{
-#ifdef Q_OS_MAC
- QFile::Permissions perm = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
- QFile file(filename);
- file.setPermissions(perm);
-#else
- Q_UNUSED(filename);
-#endif
-}
-
-
-void FileSystem::setFileReadOnlyWeak(const QString &filename, bool readonly)
-{
- QFile file(filename);
- QFile::Permissions permissions = file.permissions();
-
- if (!readonly && (permissions & QFile::WriteOwner)) {
- return; // already writable enough
- }
-
- setFileReadOnly(filename, readonly);
-}
-
time_t FileSystem::getModTime(const QString &filename)
{
csync_file_stat_t stat;
return true;
}
-#ifdef Q_OS_WIN
-static bool isLnkFile(const QString &filename)
-{
- return filename.endsWith(".lnk");
-}
-#endif
-
-bool FileSystem::rename(const QString &originFileName,
- const QString &destinationFileName,
- QString *errorString)
-{
- bool success = false;
- QString error;
-#ifdef Q_OS_WIN
- QString orig = longWinPath(originFileName);
- QString dest = longWinPath(destinationFileName);
-
- if (isLnkFile(originFileName) || isLnkFile(destinationFileName)) {
- success = MoveFileEx((wchar_t *)orig.utf16(),
- (wchar_t *)dest.utf16(),
- MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH);
- if (!success) {
- wchar_t *string = 0;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPWSTR)&string, 0, NULL);
-
- error = QString::fromWCharArray(string);
- LocalFree((HLOCAL)string);
- }
- } else
-#endif
- {
- QFile orig(originFileName);
- success = orig.rename(destinationFileName);
- if (!success) {
- error = orig.errorString();
- }
- }
-
- if (!success) {
- qCWarning(lcFileSystem) << "Error renaming file" << originFileName
- << "to" << destinationFileName
- << "failed: " << error;
- if (errorString) {
- *errorString = error;
- }
- }
- return success;
-}
-
bool FileSystem::fileChanged(const QString &fileName,
qint64 previousSize,
time_t previousMtime)
return true;
}
-bool FileSystem::renameReplace(const QString &originFileName,
- const QString &destinationFileName,
- qint64 destinationSize,
- time_t destinationMtime,
- QString *errorString)
-{
- if (fileExists(destinationFileName)
- && fileChanged(destinationFileName, destinationSize, destinationMtime)) {
- if (errorString) {
- *errorString = qApp->translate("FileSystem",
- "The destination file has an unexpected size or modification time");
- }
- return false;
- }
-
- return uncheckedRenameReplace(originFileName, destinationFileName, errorString);
-}
-
-bool FileSystem::uncheckedRenameReplace(const QString &originFileName,
- const QString &destinationFileName,
- QString *errorString)
-{
-#ifndef Q_OS_WIN
- bool success;
- QFile orig(originFileName);
- // We want a rename that also overwites. QFile::rename does not overwite.
- // Qt 5.1 has QSaveFile::renameOverwrite we could use.
- // ### FIXME
- success = true;
- bool destExists = fileExists(destinationFileName);
- if (destExists && !QFile::remove(destinationFileName)) {
- *errorString = orig.errorString();
- qCWarning(lcFileSystem) << "Target file could not be removed.";
- success = false;
- }
- if (success) {
- success = orig.rename(destinationFileName);
- }
- if (!success) {
- *errorString = orig.errorString();
- qCWarning(lcFileSystem) << "Renaming temp file to final failed: " << *errorString;
- return false;
- }
-
-#else //Q_OS_WIN
- // You can not overwrite a read-only file on windows.
- if (!QFileInfo(destinationFileName).isWritable()) {
- setFileReadOnly(destinationFileName, false);
- }
-
- BOOL ok;
- QString orig = longWinPath(originFileName);
- QString dest = longWinPath(destinationFileName);
-
- ok = MoveFileEx((wchar_t *)orig.utf16(),
- (wchar_t *)dest.utf16(),
- MOVEFILE_REPLACE_EXISTING + MOVEFILE_COPY_ALLOWED + MOVEFILE_WRITE_THROUGH);
- if (!ok) {
- wchar_t *string = 0;
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- NULL, ::GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- (LPWSTR)&string, 0, NULL);
-
- *errorString = QString::fromWCharArray(string);
- qCWarning(lcFileSystem) << "Renaming temp file to final failed: " << *errorString;
- LocalFree((HLOCAL)string);
- return false;
- }
-#endif
- return true;
-}
-
-bool FileSystem::openAndSeekFileSharedRead(QFile *file, QString *errorOrNull, qint64 seek)
-{
- QString errorDummy;
- // avoid many if (errorOrNull) later.
- QString &error = errorOrNull ? *errorOrNull : errorDummy;
- error.clear();
-
-#ifdef Q_OS_WIN
- //
- // The following code is adapted from Qt's QFSFileEnginePrivate::nativeOpen()
- // by including the FILE_SHARE_DELETE share mode.
- //
-
- // Enable full sharing.
- DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
-
- int accessRights = GENERIC_READ;
- DWORD creationDisp = OPEN_EXISTING;
-
- // Create the file handle.
- SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
- QString fName = longWinPath(file->fileName());
-
- HANDLE fileHandle = CreateFileW(
- (const wchar_t *)fName.utf16(),
- accessRights,
- shareMode,
- &securityAtts,
- creationDisp,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- // Bail out on error.
- if (fileHandle == INVALID_HANDLE_VALUE) {
- error = qt_error_string();
- return false;
- }
-
- // Convert the HANDLE to an fd and pass it to QFile's foreign-open
- // function. The fd owns the handle, so when QFile later closes
- // the fd the handle will be closed too.
- int fd = _open_osfhandle((intptr_t)fileHandle, _O_RDONLY);
- if (fd == -1) {
- error = "could not make fd from handle";
- return false;
- }
- if (!file->open(fd, QIODevice::ReadOnly, QFile::AutoCloseHandle)) {
- error = file->errorString();
- return false;
- }
-
- // Seek to the right spot
- LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER *>(&seek);
- DWORD newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
- if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
- error = qt_error_string();
- return false;
- }
-
- return true;
-#else
- if (!file->open(QFile::ReadOnly)) {
- error = file->errorString();
- return false;
- }
- if (!file->seek(seek)) {
- error = file->errorString();
- return false;
- }
- return true;
-#endif
-}
-
#ifdef Q_OS_WIN
static qint64 getSizeWithCsync(const QString &filename)
{
return QFileInfo(filename).size();
}
-#ifdef Q_OS_WIN
-static bool fileExistsWin(const QString &filename)
-{
- WIN32_FIND_DATA FindFileData;
- HANDLE hFind;
- QString fName = FileSystem::longWinPath(filename);
-
- hFind = FindFirstFileW((wchar_t *)fName.utf16(), &FindFileData);
- if (hFind == INVALID_HANDLE_VALUE) {
- return false;
- }
- FindClose(hFind);
- return true;
-}
-#endif
-
-bool FileSystem::fileExists(const QString &filename, const QFileInfo &fileInfo)
-{
-#ifdef Q_OS_WIN
- if (isLnkFile(filename)) {
- // Use a native check.
- return fileExistsWin(filename);
- }
-#endif
- bool re = fileInfo.exists();
- // if the filename is different from the filename in fileInfo, the fileInfo is
- // not valid. There needs to be one initialised here. Otherwise the incoming
- // fileInfo is re-used.
- if (fileInfo.filePath() != filename) {
- QFileInfo myFI(filename);
- re = myFI.exists();
- }
- return re;
-}
-
-#ifdef Q_OS_WIN
-QString FileSystem::fileSystemForPath(const QString &path)
-{
- // See also QStorageInfo (Qt >=5.4) and GetVolumeInformationByHandleW (>= Vista)
- QString drive = path.left(2);
- if (!drive.endsWith(":"))
- return QString();
- drive.append('\\');
-
- const size_t fileSystemBufferSize = 4096;
- TCHAR fileSystemBuffer[fileSystemBufferSize];
-
- if (!GetVolumeInformationW(
- reinterpret_cast<LPCWSTR>(drive.utf16()),
- NULL, 0,
- NULL, NULL, NULL,
- fileSystemBuffer, fileSystemBufferSize)) {
- return QString();
- }
- return QString::fromUtf16(reinterpret_cast<const ushort *>(fileSystemBuffer));
-}
-#endif
-
-#define BUFSIZE qint64(500 * 1024) // 500 KiB
-
-static QByteArray readToCrypto(const QString &filename, QCryptographicHash::Algorithm algo)
-{
- QFile file(filename);
- const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
- QByteArray buf(bufSize, Qt::Uninitialized);
- QByteArray arr;
- QCryptographicHash crypto(algo);
-
- if (file.open(QIODevice::ReadOnly)) {
- qint64 size;
- while (!file.atEnd()) {
- size = file.read(buf.data(), bufSize);
- if (size > 0) {
- crypto.addData(buf.data(), size);
- }
- }
- arr = crypto.result().toHex();
- }
- return arr;
-}
-
-QByteArray FileSystem::calcMd5(const QString &filename)
-{
- return readToCrypto(filename, QCryptographicHash::Md5);
-}
-
-QByteArray FileSystem::calcSha1(const QString &filename)
-{
- return readToCrypto(filename, QCryptographicHash::Sha1);
-}
-
-#ifdef ZLIB_FOUND
-QByteArray FileSystem::calcAdler32(const QString &filename)
-{
- QFile file(filename);
- const qint64 bufSize = qMin(BUFSIZE, file.size() + 1);
- QByteArray buf(bufSize, Qt::Uninitialized);
-
- unsigned int adler = adler32(0L, Z_NULL, 0);
- if (file.open(QIODevice::ReadOnly)) {
- qint64 size;
- while (!file.atEnd()) {
- size = file.read(buf.data(), bufSize);
- if (size > 0)
- adler = adler32(adler, (const Bytef *)buf.data(), size);
- }
- }
-
- return QByteArray::number(adler, 16);
-}
-#endif
-
-QString FileSystem::makeConflictFileName(const QString &fn, const QDateTime &dt)
-{
- QString conflictFileName(fn);
- // Add _conflict-XXXX before the extension.
- int dotLocation = conflictFileName.lastIndexOf('.');
- // If no extension, add it at the end (take care of cases like foo/.hidden or foo.bar/file)
- if (dotLocation <= conflictFileName.lastIndexOf('/') + 1) {
- dotLocation = conflictFileName.size();
- }
- QString timeString = dt.toString("yyyyMMdd-hhmmss");
-
- // Additional marker
- QByteArray conflictFileUserName = qgetenv("CSYNC_CONFLICT_FILE_USERNAME");
- if (conflictFileUserName.isEmpty())
- conflictFileName.insert(dotLocation, "_conflict-" + timeString);
- else
- conflictFileName.insert(dotLocation, "_conflict_" + QString::fromUtf8(conflictFileUserName) + "-" + timeString);
-
- return conflictFileName;
-}
-
-bool FileSystem::remove(const QString &fileName, QString *errorString)
-{
-#ifdef Q_OS_WIN
- // You cannot delete a read-only file on windows, but we want to
- // allow that.
- if (!QFileInfo(fileName).isWritable()) {
- setFileReadOnly(fileName, false);
- }
-#endif
- QFile f(fileName);
- if (!f.remove()) {
- if (errorString) {
- *errorString = f.errorString();
- }
- return false;
- }
- return true;
-}
-
-bool FileSystem::isFileLocked(const QString &fileName)
-{
-#ifdef Q_OS_WIN
- mbchar_t *wuri = c_utf8_path_to_locale(fileName.toUtf8());
-
- // Check if file exists
- DWORD attr = GetFileAttributesW(wuri);
- if (attr != INVALID_FILE_ATTRIBUTES) {
- // Try to open the file with as much access as possible..
- HANDLE win_h = CreateFileW(
- wuri,
- GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
- NULL, OPEN_EXISTING,
- FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
- NULL);
-
- c_free_locale_string(wuri);
- if (win_h == INVALID_HANDLE_VALUE) {
- /* could not be opened, so locked? */
- /* 32 == ERROR_SHARING_VIOLATION */
- return true;
- } else {
- CloseHandle(win_h);
- }
- } else {
- c_free_locale_string(wuri);
- }
-#else
- Q_UNUSED(fileName);
-#endif
- return false;
-}
} // namespace OCC
#include <QString>
#include <ctime>
-#include <QCryptographicHash>
-#include <QFileInfo>
#include <owncloudlib.h>
+// Chain in the base include and extend the namespace
+#include "common/filesystembase.h"
class QFile;
-class QFileInfo;
namespace OCC {
*/
bool fileEquals(const QString &fn1, const QString &fn2);
- /**
- * @brief Mark the file as hidden (only has effects on windows)
- */
- void OWNCLOUDSYNC_EXPORT setFileHidden(const QString &filename, bool hidden);
-
- /**
- * @brief Marks the file as read-only.
- *
- * On linux this either revokes all 'w' permissions or restores permissions
- * according to the umask.
- */
- void OWNCLOUDSYNC_EXPORT setFileReadOnly(const QString &filename, bool readonly);
-
- /**
- * @brief Marks the file as read-only.
- *
- * It's like setFileReadOnly(), but weaker: if readonly is false and the user
- * already has write permissions, no change to the permissions is made.
- *
- * This means that it will preserve explicitly set rw-r--r-- permissions even
- * when the umask is 0002. (setFileReadOnly() would adjust to rw-rw-r--)
- */
- void OWNCLOUDSYNC_EXPORT setFileReadOnlyWeak(const QString &filename, bool readonly);
-
- /**
- * @brief Try to set permissions so that other users on the local machine can not
- * go into the folder.
- */
- void OWNCLOUDSYNC_EXPORT setFolderMinimumPermissions(const QString &filename);
-
- /** convert a "normal" windows path into a path that can be 32k chars long. */
- QString OWNCLOUDSYNC_EXPORT longWinPath(const QString &inpath);
-
/**
* @brief Get the mtime for a filepath
*
*/
qint64 OWNCLOUDSYNC_EXPORT getSize(const QString &filename);
- /**
- * @brief Checks whether a file exists.
- *
- * Use this over QFileInfo::exists() and QFile::exists() to avoid bugs with lnk
- * files, see above.
- */
- bool OWNCLOUDSYNC_EXPORT fileExists(const QString &filename, const QFileInfo & = QFileInfo());
-
- /**
- * @brief Rename the file \a originFileName to \a destinationFileName.
- *
- * It behaves as QFile::rename() but handles .lnk files correctly on Windows.
- */
- bool OWNCLOUDSYNC_EXPORT rename(const QString &originFileName,
- const QString &destinationFileName,
- QString *errorString = NULL);
-
/**
* @brief Check if \a fileName has changed given previous size and mtime
*
bool verifyFileUnchanged(const QString &fileName,
qint64 previousSize,
time_t previousMtime);
-
- /**
- * @brief renames a file, overriding the target if it exists
- *
- * Rename the file \a originFileName to \a destinationFileName, and
- * overwrite the destination if it already exists - as long as the
- * destination file has the expected \a destinationSize and
- * \a destinationMtime.
- *
- * If the destination file does not exist, the given size and mtime are
- * ignored.
- */
- bool renameReplace(const QString &originFileName,
- const QString &destinationFileName,
- qint64 destinationSize,
- time_t destinationMtime,
- QString *errorString);
-
- /**
- * Rename the file \a originFileName to \a destinationFileName, and
- * overwrite the destination if it already exists - without extra checks.
- */
- bool uncheckedRenameReplace(const QString &originFileName,
- const QString &destinationFileName,
- QString *errorString);
-
- /**
- * Removes a file.
- *
- * Equivalent to QFile::remove(), except on Windows, where it will also
- * successfully remove read-only files.
- */
- bool OWNCLOUDSYNC_EXPORT remove(const QString &fileName, QString *errorString = 0);
-
- /**
- * Replacement for QFile::open(ReadOnly) followed by a seek().
- * This version sets a more permissive sharing mode on Windows.
- *
- * Warning: The resulting file may have an empty fileName and be unsuitable for use
- * with QFileInfo! Calling seek() on the QFile with >32bit signed values will fail!
- */
- bool openAndSeekFileSharedRead(QFile *file, QString *error, qint64 seek);
-
-#ifdef Q_OS_WIN
- /**
- * Returns the file system used at the given path.
- */
- QString fileSystemForPath(const QString &path);
-#endif
-
- QByteArray OWNCLOUDSYNC_EXPORT calcMd5(const QString &fileName);
- QByteArray OWNCLOUDSYNC_EXPORT calcSha1(const QString &fileName);
-#ifdef ZLIB_FOUND
- QByteArray OWNCLOUDSYNC_EXPORT calcAdler32(const QString &fileName);
-#endif
-
- /**
- * Returns a file name based on \a fn that's suitable for a conflict.
- */
- QString OWNCLOUDSYNC_EXPORT makeConflictFileName(const QString &fn, const QDateTime &dt);
-
- /**
- * Returns true when a file is locked. (Windows only)
- */
- bool OWNCLOUDSYNC_EXPORT isFileLocked(const QString &fileName);
}
/** @} */
* for more details.
*/
+#include <QCryptographicHash>
#include <QFile>
#include <QLoggingCategory>
#include <QStringList>
#include "c_string.h"
#include "c_path.h"
#include "c_utf8.h"
+#include "common/filesystembase.h"
+#include "torture.h"
#ifdef _WIN32
#include <string.h>
{
const char *path = "C://DATA/FILES/MUSIC/MY_MUSIC.mp3"; // check a short path
const char *exp_path = "\\\\?\\C:\\\\DATA\\FILES\\MUSIC\\MY_MUSIC.mp3";
- const char *new_short = c_path_to_UNC(path);
+ QByteArray new_short = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(path, strlen(path)));
assert_string_equal(new_short, exp_path);
- SAFE_FREE(new_short);
}
{
const char *path = "\\\\foo\\bar/MY_MUSIC.mp3";
const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3";
- const char *new_short = c_path_to_UNC(path);
+ QByteArray new_short = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(path, strlen(path)));
assert_string_equal(new_short, exp_path);
- SAFE_FREE(new_short);
}
{
const char *path = "//foo\\bar/MY_MUSIC.mp3";
const char *exp_path = "\\\\foo\\bar\\MY_MUSIC.mp3";
- const char *new_short = c_path_to_UNC(path);
+ QByteArray new_short = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(path, strlen(path)));
assert_string_equal(new_short, exp_path);
- SAFE_FREE(new_short);
}
{
const char *path = "\\foo\\bar";
const char *exp_path = "\\\\?\\foo\\bar";
- const char *new_short = c_path_to_UNC(path);
+ QByteArray new_short = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(path, strlen(path)));
assert_string_equal(new_short, exp_path);
- SAFE_FREE(new_short);
}
{
const char *path = "/foo/bar";
const char *exp_path = "\\\\?\\foo\\bar";
- const char *new_short = c_path_to_UNC(path);
+ QByteArray new_short = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(path, strlen(path)));
assert_string_equal(new_short, exp_path);
- SAFE_FREE(new_short);
}
const char *longPath = "D://alonglonglonglong/blonglonglonglong/clonglonglonglong/dlonglonglonglong/"
"jlonglonglonglong\\klonglonglonglong\\llonglonglonglong\\mlonglonglonglong\\nlonglonglonglong\\"
"olonglonglonglong\\file.txt";
- const char *new_long = c_path_to_UNC(longPath);
+ QByteArray new_long = OCC::FileSystem::pathtoUNC(QByteArray::fromRawData(longPath, strlen(longPath)));
// printf( "XXXXXXXXXXXX %s %d\n", new_long, mem_reserved);
assert_string_equal(new_long, longPathConv);
// printf( "YYYYYYYYYYYY %ld\n", strlen(new_long));
assert_int_equal( strlen(new_long), 286);
- SAFE_FREE(new_long);
}
int torture_run_tests(void)