mirror of
https://github.com/chylex/Nextcloud-Desktop.git
synced 2025-08-21 15:54:01 +02:00
.github
.tx
admin
cmake
doc
man
shell_integration
src
3rdparty
cmd
common
crashreporter
csync
gui
libsync
creds
vfs
CMakeLists.txt
abstractnetworkjob.cpp
abstractnetworkjob.h
abstractpropagateremotedeleteencrypted.cpp
abstractpropagateremotedeleteencrypted.h
accessmanager.cpp
accessmanager.h
account.cpp
account.h
accountfwd.h
bandwidthmanager.cpp
bandwidthmanager.h
bulkpropagatorjob.cpp
bulkpropagatorjob.h
capabilities.cpp
capabilities.h
clientproxy.cpp
clientproxy.h
clientsideencryption.cpp
clientsideencryption.h
clientsideencryptionjobs.cpp
clientsideencryptionjobs.h
configfile.cpp
configfile.h
cookiejar.cpp
cookiejar.h
datetimeprovider.cpp
datetimeprovider.h
deletejob.cpp
deletejob.h
discovery.cpp
discovery.h
discoveryphase.cpp
discoveryphase.h
encryptfolderjob.cpp
encryptfolderjob.h
filesystem.cpp
filesystem.h
httplogger.cpp
httplogger.h
iconjob.cpp
iconjob.h
libsync.md
localdiscoverytracker.cpp
localdiscoverytracker.h
logger.cpp
logger.h
networkjobs.cpp
networkjobs.h
nextcloudtheme.cpp
nextcloudtheme.h
ocsprofileconnector.cpp
ocsprofileconnector.h
ocsuserstatusconnector.cpp
ocsuserstatusconnector.h
owncloudpropagator.cpp
owncloudpropagator.h
owncloudpropagator_p.h
progressdispatcher.cpp
progressdispatcher.h
propagatedownload.cpp
propagatedownload.h
propagatedownloadencrypted.cpp
propagatedownloadencrypted.h
propagateremotedelete.cpp
propagateremotedelete.h
propagateremotedeleteencrypted.cpp
propagateremotedeleteencrypted.h
propagateremotedeleteencryptedrootfolder.cpp
propagateremotedeleteencryptedrootfolder.h
propagateremotemkdir.cpp
propagateremotemkdir.h
propagateremotemove.cpp
propagateremotemove.h
propagateupload.cpp
propagateupload.h
propagateuploadencrypted.cpp
propagateuploadencrypted.h
propagateuploadng.cpp
propagateuploadv1.cpp
propagatorjobs.cpp
propagatorjobs.h
pushnotifications.cpp
pushnotifications.h
putmultifilejob.cpp
putmultifilejob.h
syncengine.cpp
syncengine.h
syncfileitem.cpp
syncfileitem.h
syncfilestatustracker.cpp
syncfilestatustracker.h
syncoptions.cpp
syncoptions.h
syncresult.cpp
syncresult.h
theme.cpp
theme.h
userstatusconnector.cpp
userstatusconnector.h
wordlist.cpp
wordlist.h
CMakeLists.txt
test
theme
translations
.clang-format
.clang-tidy
.drone.yml
.git-blame-ignore-revs
.gitattributes
.gitignore
.gitmodules
.tag
CMakeLists.txt
CONTRIBUTING.md
COPYING
COPYING.documentation
CPackOptions.cmake.in
ChangeLog
NEXTCLOUD.cmake
NextcloudCPack.cmake
README.md
VERSION.cmake
appveyor.ini
appveyor.yml
config.h.in
mirall.desktop.in
resources.qrc
sonar-project.properties
sync-exclude.lst
theme.qrc.in
version.h.in
195 lines
6.2 KiB
C++
195 lines
6.2 KiB
C++
/*
|
|
* Copyright (C) by Daniel Molkentin <danimo@owncloud.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License
|
|
* for more details.
|
|
*/
|
|
|
|
#include "filesystem.h"
|
|
|
|
#include "common/utility.h"
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QDir>
|
|
#include <QDirIterator>
|
|
#include <QCoreApplication>
|
|
|
|
#include "csync.h"
|
|
#include "vio/csync_vio_local.h"
|
|
#include "std/c_time.h"
|
|
|
|
namespace OCC {
|
|
|
|
bool FileSystem::fileEquals(const QString &fn1, const QString &fn2)
|
|
{
|
|
// compare two files with given filename and return true if they have the same content
|
|
QFile f1(fn1);
|
|
QFile f2(fn2);
|
|
if (!f1.open(QIODevice::ReadOnly) || !f2.open(QIODevice::ReadOnly)) {
|
|
qCWarning(lcFileSystem) << "fileEquals: Failed to open " << fn1 << "or" << fn2;
|
|
return false;
|
|
}
|
|
|
|
if (getSize(fn1) != getSize(fn2)) {
|
|
return false;
|
|
}
|
|
|
|
const int BufferSize = 16 * 1024;
|
|
QByteArray buffer1(BufferSize, 0);
|
|
QByteArray buffer2(BufferSize, 0);
|
|
// the files have the same size, compare all of it
|
|
while(!f1.atEnd()){
|
|
f1.read(buffer1.data(), BufferSize);
|
|
f2.read(buffer2.data(), BufferSize);
|
|
if (buffer1 != buffer2) {
|
|
return false;
|
|
}
|
|
};
|
|
return true;
|
|
}
|
|
|
|
time_t FileSystem::getModTime(const QString &filename)
|
|
{
|
|
csync_file_stat_t stat;
|
|
qint64 result = -1;
|
|
if (csync_vio_local_stat(filename, &stat) != -1
|
|
&& (stat.modtime != 0)) {
|
|
result = stat.modtime;
|
|
} else {
|
|
result = Utility::qDateTimeToTime_t(QFileInfo(filename).lastModified());
|
|
qCWarning(lcFileSystem) << "Could not get modification time for" << filename
|
|
<< "with csync, using QFileInfo:" << result;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool FileSystem::setModTime(const QString &filename, time_t modTime)
|
|
{
|
|
struct timeval times[2];
|
|
times[0].tv_sec = times[1].tv_sec = modTime;
|
|
times[0].tv_usec = times[1].tv_usec = 0;
|
|
int rc = c_utimes(filename, times);
|
|
if (rc != 0) {
|
|
qCWarning(lcFileSystem) << "Error setting mtime for" << filename
|
|
<< "failed: rc" << rc << ", errno:" << errno;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool FileSystem::fileChanged(const QString &fileName,
|
|
qint64 previousSize,
|
|
time_t previousMtime)
|
|
{
|
|
return getSize(fileName) != previousSize
|
|
|| getModTime(fileName) != previousMtime;
|
|
}
|
|
|
|
bool FileSystem::verifyFileUnchanged(const QString &fileName,
|
|
qint64 previousSize,
|
|
time_t previousMtime)
|
|
{
|
|
const qint64 actualSize = getSize(fileName);
|
|
const time_t actualMtime = getModTime(fileName);
|
|
if (actualSize != previousSize || actualMtime != previousMtime) {
|
|
qCInfo(lcFileSystem) << "File" << fileName << "has changed:"
|
|
<< "size: " << previousSize << "<->" << actualSize
|
|
<< ", mtime: " << previousMtime << "<->" << actualMtime;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#ifdef Q_OS_WIN
|
|
static qint64 getSizeWithCsync(const QString &filename)
|
|
{
|
|
qint64 result = 0;
|
|
csync_file_stat_t stat;
|
|
if (csync_vio_local_stat(filename, &stat) != -1) {
|
|
result = stat.size;
|
|
} else {
|
|
qCWarning(lcFileSystem) << "Could not get size for" << filename << "with csync" << Utility::formatWinError(errno);
|
|
}
|
|
return result;
|
|
}
|
|
#endif
|
|
|
|
qint64 FileSystem::getSize(const QString &filename)
|
|
{
|
|
#ifdef Q_OS_WIN
|
|
if (isLnkFile(filename)) {
|
|
// Qt handles .lnk as symlink... https://doc.qt.io/qt-5/qfileinfo.html#details
|
|
return getSizeWithCsync(filename);
|
|
}
|
|
#endif
|
|
return QFileInfo(filename).size();
|
|
}
|
|
|
|
// Code inspired from Qt5's QDir::removeRecursively
|
|
bool FileSystem::removeRecursively(const QString &path, const std::function<void(const QString &path, bool isDir)> &onDeleted, QStringList *errors)
|
|
{
|
|
bool allRemoved = true;
|
|
QDirIterator di(path, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
|
|
|
|
while (di.hasNext()) {
|
|
di.next();
|
|
const QFileInfo &fi = di.fileInfo();
|
|
bool removeOk = false;
|
|
// The use of isSymLink here is okay:
|
|
// we never want to go into this branch for .lnk files
|
|
bool isDir = fi.isDir() && !fi.isSymLink() && !FileSystem::isJunction(fi.absoluteFilePath());
|
|
if (isDir) {
|
|
removeOk = removeRecursively(path + QLatin1Char('/') + di.fileName(), onDeleted, errors); // recursive
|
|
} else {
|
|
QString removeError;
|
|
removeOk = FileSystem::remove(di.filePath(), &removeError);
|
|
if (removeOk) {
|
|
if (onDeleted)
|
|
onDeleted(di.filePath(), false);
|
|
} else {
|
|
if (errors) {
|
|
errors->append(QCoreApplication::translate("FileSystem", "Error removing \"%1\": %2")
|
|
.arg(QDir::toNativeSeparators(di.filePath()), removeError));
|
|
}
|
|
qCWarning(lcFileSystem) << "Error removing " << di.filePath() << ':' << removeError;
|
|
}
|
|
}
|
|
if (!removeOk)
|
|
allRemoved = false;
|
|
}
|
|
if (allRemoved) {
|
|
allRemoved = QDir().rmdir(path);
|
|
if (allRemoved) {
|
|
if (onDeleted)
|
|
onDeleted(path, true);
|
|
} else {
|
|
if (errors) {
|
|
errors->append(QCoreApplication::translate("FileSystem", "Could not remove folder \"%1\"")
|
|
.arg(QDir::toNativeSeparators(path)));
|
|
}
|
|
qCWarning(lcFileSystem) << "Error removing folder" << path;
|
|
}
|
|
}
|
|
return allRemoved;
|
|
}
|
|
|
|
bool FileSystem::getInode(const QString &filename, quint64 *inode)
|
|
{
|
|
csync_file_stat_t fs;
|
|
if (csync_vio_local_stat(filename, &fs) == 0) {
|
|
*inode = fs.inode;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
} // namespace OCC
|