mirror of
https://github.com/nextcloud/desktop.git
synced 2025-10-26 11:17:43 +00:00
Merge pull request #4045 from nextcloud/bugfix/assertInvalidModtime
Bugfix/assert invalid modtime
This commit is contained in:
commit
833e3bbcf6
@ -275,6 +275,9 @@ void BulkPropagatorJob::slotStartUpload(SyncFileItemPtr item,
|
||||
// have been changed again, so better check again here.
|
||||
|
||||
item->_modtime = FileSystem::getModTime(originalFilePath);
|
||||
if (item->_modtime <= 0) {
|
||||
return slotOnErrorStartFolderUnlock(item, SyncFileItem::SoftError, tr("Local file has invalid modified time. Do not upload to the server."));
|
||||
}
|
||||
if (prevModtime != item->_modtime) {
|
||||
propagator()->_anotherSyncNeeded = true;
|
||||
qDebug() << "trigger another sync after checking modified time of item" << item->_file << "prevModtime" << prevModtime << "Curr" << item->_modtime;
|
||||
|
||||
@ -542,6 +542,19 @@ void ProcessDirectoryJob::processFileAnalyzeRemoteInfo(
|
||||
} else {
|
||||
item->_instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
}
|
||||
} else if (dbEntry._modtime <= 0 && serverEntry.modtime > 0) {
|
||||
item->_direction = SyncFileItem::Down;
|
||||
item->_modtime = serverEntry.modtime;
|
||||
item->_size = sizeOnServer;
|
||||
if (serverEntry.isDirectory) {
|
||||
ENFORCE(dbEntry.isDirectory());
|
||||
item->_instruction = CSYNC_INSTRUCTION_UPDATE_METADATA;
|
||||
} else if (!localEntry.isValid() && _queryLocal != ParentNotChanged) {
|
||||
// Deleted locally, changed on server
|
||||
item->_instruction = CSYNC_INSTRUCTION_NEW;
|
||||
} else {
|
||||
item->_instruction = CSYNC_INSTRUCTION_SYNC;
|
||||
}
|
||||
} else if (dbEntry._remotePerm != serverEntry.remotePerm || dbEntry._fileId != serverEntry.fileId || metaDataSizeNeedsUpdateForE2EeFilePlaceholder) {
|
||||
if (metaDataSizeNeedsUpdateForE2EeFilePlaceholder) {
|
||||
// we are updating placeholder sizes after migrating from older versions with VFS + E2EE implicit hydration not supported
|
||||
|
||||
@ -98,7 +98,7 @@ bool FileSystem::verifyFileUnchanged(const QString &fileName,
|
||||
{
|
||||
const qint64 actualSize = getSize(fileName);
|
||||
const time_t actualMtime = getModTime(fileName);
|
||||
if (actualSize != previousSize || actualMtime != previousMtime) {
|
||||
if (actualSize != previousSize || (actualMtime != previousMtime && previousMtime > 0 && actualMtime > 0)) {
|
||||
qCInfo(lcFileSystem) << "File" << fileName << "has changed:"
|
||||
<< "size: " << previousSize << "<->" << actualSize
|
||||
<< ", mtime: " << previousMtime << "<->" << actualMtime;
|
||||
|
||||
@ -1126,6 +1126,13 @@ void PropagateDirectory::slotSubJobsFinished(SyncFileItem::Status status)
|
||||
if (_item->_instruction == CSYNC_INSTRUCTION_NEW && _item->_direction == SyncFileItem::Down) {
|
||||
// special case for local MKDIR, set local directory mtime
|
||||
// (it's not synced later at all, but can be nice to have it set initially)
|
||||
|
||||
if (_item->_modtime <= 0) {
|
||||
status = _item->_status = SyncFileItem::NormalError;
|
||||
_item->_errorString = tr("Error updating metadata due to invalid modified time");
|
||||
qCWarning(lcDirectory) << "Error writing to the database for file" << _item->_file;
|
||||
}
|
||||
|
||||
FileSystem::setModTime(propagator()->fullLocalPath(_item->destination()), _item->_modtime);
|
||||
}
|
||||
|
||||
|
||||
@ -564,6 +564,10 @@ void PropagateDownloadFile::startAfterIsEncryptedIsChecked()
|
||||
return checksum_header.startsWith("SHA")
|
||||
|| checksum_header.startsWith("MD5:");
|
||||
};
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (_item->_instruction == CSYNC_INSTRUCTION_CONFLICT
|
||||
&& _item->_size == _item->_previousSize
|
||||
&& !_item->_checksumHeader.isEmpty()
|
||||
@ -592,11 +596,20 @@ void PropagateDownloadFile::conflictChecksumComputed(const QByteArray &checksumT
|
||||
// Apply the server mtime locally if necessary, ensuring the journal
|
||||
// and local mtimes end up identical
|
||||
auto fn = propagator()->fullLocalPath(_item->_file);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (_item->_modtime != _item->_previousModtime) {
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
FileSystem::setModTime(fn, _item->_modtime);
|
||||
emit propagator()->touchedFile(fn);
|
||||
}
|
||||
_item->_modtime = FileSystem::getModTime(fn);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
updateMetadata(/*isConflict=*/false);
|
||||
return;
|
||||
}
|
||||
@ -820,6 +833,10 @@ void PropagateDownloadFile::slotGetFinished()
|
||||
// It is possible that the file was modified on the server since we did the discovery phase
|
||||
// so make sure we have the up-to-date time
|
||||
_item->_modtime = job->lastModified();
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
}
|
||||
|
||||
_tmpFile.close();
|
||||
@ -1058,10 +1075,26 @@ void PropagateDownloadFile::downloadFinished()
|
||||
return;
|
||||
}
|
||||
|
||||
if (_item->_modtime <= 0) {
|
||||
done(SyncFileItem::NormalError, tr("File %1 has invalid modified time reported by server. Do not save it.").arg(QDir::toNativeSeparators(_item->_file)));
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
FileSystem::setModTime(_tmpFile.fileName(), _item->_modtime);
|
||||
// We need to fetch the time again because some file systems such as FAT have worse than a second
|
||||
// Accuracy, and we really need the time from the file system. (#3103)
|
||||
_item->_modtime = FileSystem::getModTime(_tmpFile.fileName());
|
||||
if (_item->_modtime <= 0) {
|
||||
done(SyncFileItem::NormalError, tr("File %1 has invalid modified time reported by server. Do not save it.").arg(QDir::toNativeSeparators(_item->_file)));
|
||||
return;
|
||||
}
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateDownload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
|
||||
bool previousFileExists = FileSystem::fileExists(fn);
|
||||
if (previousFileExists) {
|
||||
|
||||
@ -210,6 +210,10 @@ void PropagateUploadFileCommon::start()
|
||||
}
|
||||
_item->_file = _item->_renameTarget;
|
||||
_item->_modtime = FileSystem::getModTime(newFilePathAbsolute);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
}
|
||||
|
||||
SyncJournalFileRecord parentRec;
|
||||
@ -312,6 +316,10 @@ void PropagateUploadFileCommon::slotComputeContentChecksum()
|
||||
// and not the _fileToUpload because we are checking the original file, not there
|
||||
// probably temporary one.
|
||||
_item->_modtime = FileSystem::getModTime(filePath);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
|
||||
const QByteArray checksumType = propagator()->account()->capabilities().preferredUploadChecksumType();
|
||||
|
||||
@ -383,11 +391,27 @@ void PropagateUploadFileCommon::slotStartUpload(const QByteArray &transmissionCh
|
||||
if (!FileSystem::fileExists(fullFilePath)) {
|
||||
return slotOnErrorStartFolderUnlock(SyncFileItem::SoftError, tr("File Removed (start upload) %1").arg(fullFilePath));
|
||||
}
|
||||
if (_item->_modtime <= 0) {
|
||||
return slotOnErrorStartFolderUnlock(
|
||||
SyncFileItem::SoftError, tr("Local file has invalid modified time. Do not upload to the server."));
|
||||
}
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
time_t prevModtime = _item->_modtime; // the _item value was set in PropagateUploadFile::start()
|
||||
// but a potential checksum calculation could have taken some time during which the file could
|
||||
// have been changed again, so better check again here.
|
||||
|
||||
_item->_modtime = FileSystem::getModTime(originalFilePath);
|
||||
if (_item->_modtime <= 0) {
|
||||
return slotOnErrorStartFolderUnlock(
|
||||
SyncFileItem::SoftError, tr("Local file has invalid modified time. Do not upload to the server."));
|
||||
}
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (prevModtime != _item->_modtime) {
|
||||
propagator()->_anotherSyncNeeded = true;
|
||||
qDebug() << "prevModtime" << prevModtime << "Curr" << _item->_modtime;
|
||||
@ -585,6 +609,10 @@ void PropagateUploadFileCommon::startPollJob(const QString &path)
|
||||
info._file = _item->_file;
|
||||
info._url = path;
|
||||
info._modtime = _item->_modtime;
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
info._fileSize = _item->_size;
|
||||
propagator()->_journal->setPollInfo(info);
|
||||
propagator()->_journal->commit("add poll info");
|
||||
@ -707,6 +735,10 @@ QMap<QByteArray, QByteArray> PropagateUploadFileCommon::headers()
|
||||
{
|
||||
QMap<QByteArray, QByteArray> headers;
|
||||
headers[QByteArrayLiteral("Content-Type")] = QByteArrayLiteral("application/octet-stream");
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
headers[QByteArrayLiteral("X-OC-Mtime")] = QByteArray::number(qint64(_item->_modtime));
|
||||
if (qEnvironmentVariableIntValue("OWNCLOUD_LAZYOPS"))
|
||||
headers[QByteArrayLiteral("OC-LazyOps")] = QByteArrayLiteral("true");
|
||||
|
||||
@ -83,6 +83,10 @@ void PropagateUploadFileNG::doStartUpload()
|
||||
propagator()->_activeJobList.append(this);
|
||||
|
||||
const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (progressInfo._valid && progressInfo.isChunked() && progressInfo._modtime == _item->_modtime
|
||||
&& progressInfo._size == _item->_size) {
|
||||
_transferId = progressInfo._transferid;
|
||||
@ -229,6 +233,10 @@ void PropagateUploadFileNG::slotDeleteJobFinished()
|
||||
void PropagateUploadFileNG::startNewUpload()
|
||||
{
|
||||
ASSERT(propagator()->_activeJobList.count(this) == 1);
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
_transferId = uint(Utility::rand() ^ uint(_item->_modtime) ^ (uint(_fileToUpload._size) << 16) ^ qHash(_fileToUpload._file));
|
||||
_sent = 0;
|
||||
_currentChunk = 0;
|
||||
@ -238,6 +246,10 @@ void PropagateUploadFileNG::startNewUpload()
|
||||
SyncJournalDb::UploadInfo pi;
|
||||
pi._valid = true;
|
||||
pi._transferid = _transferId;
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
pi._modtime = _item->_modtime;
|
||||
pi._contentChecksum = _item->_checksumHeader;
|
||||
pi._size = _item->_size;
|
||||
@ -423,6 +435,10 @@ void PropagateUploadFileNG::slotPutFinished()
|
||||
}
|
||||
|
||||
// Check whether the file changed since discovery - this acts on the original file.
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (!FileSystem::verifyFileUnchanged(fullFilePath, _item->_size, _item->_modtime)) {
|
||||
propagator()->_anotherSyncNeeded = true;
|
||||
if (!_finished) {
|
||||
|
||||
@ -39,10 +39,18 @@ void PropagateUploadFileV1::doStartUpload()
|
||||
{
|
||||
_chunkCount = int(std::ceil(_fileToUpload._size / double(chunkSize())));
|
||||
_startChunk = 0;
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
_transferId = uint(Utility::rand()) ^ uint(_item->_modtime) ^ (uint(_fileToUpload._size) << 16);
|
||||
|
||||
const SyncJournalDb::UploadInfo progressInfo = propagator()->_journal->getUploadInfo(_item->_file);
|
||||
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (progressInfo._valid && progressInfo.isChunked() && progressInfo._modtime == _item->_modtime && progressInfo._size == _item->_size
|
||||
&& (progressInfo._contentChecksum == _item->_checksumHeader || progressInfo._contentChecksum.isEmpty() || _item->_checksumHeader.isEmpty())) {
|
||||
_startChunk = progressInfo._chunk;
|
||||
@ -56,6 +64,10 @@ void PropagateUploadFileV1::doStartUpload()
|
||||
pi._valid = true;
|
||||
pi._chunk = 0;
|
||||
pi._transferid = 0; // We set a null transfer id because it is not chunked.
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
pi._modtime = _item->_modtime;
|
||||
pi._errorCount = 0;
|
||||
pi._contentChecksum = _item->_checksumHeader;
|
||||
@ -245,6 +257,10 @@ void PropagateUploadFileV1::slotPutFinished()
|
||||
}
|
||||
|
||||
// Check whether the file changed since discovery. the file check here is the original and not the temprary.
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
if (!FileSystem::verifyFileUnchanged(fullFilePath, _item->_size, _item->_modtime)) {
|
||||
propagator()->_anotherSyncNeeded = true;
|
||||
if (!_finished) {
|
||||
@ -283,6 +299,10 @@ void PropagateUploadFileV1::slotPutFinished()
|
||||
}
|
||||
pi._chunk = (currentChunk + _startChunk + 1) % _chunkCount; // next chunk to start with
|
||||
pi._transferid = _transferId;
|
||||
Q_ASSERT(_item->_modtime > 0);
|
||||
if (_item->_modtime <= 0) {
|
||||
qCWarning(lcPropagateUpload()) << "invalid modified time" << _item->_file << _item->_modtime;
|
||||
}
|
||||
pi._modtime = _item->_modtime;
|
||||
pi._errorCount = 0; // successful chunk upload resets
|
||||
pi._contentChecksum = _item->_checksumHeader;
|
||||
|
||||
@ -643,6 +643,10 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::se
|
||||
|
||||
OCC::Result<void, QString> OCC::CfApiWrapper::createPlaceholderInfo(const QString &path, time_t modtime, qint64 size, const QByteArray &fileId)
|
||||
{
|
||||
if (modtime <= 0) {
|
||||
return {QString{"Could not update metadata due to invalid modified time for %1: %2"}.arg(path).arg(modtime)};
|
||||
}
|
||||
|
||||
const auto fileInfo = QFileInfo(path);
|
||||
const auto localBasePath = QDir::toNativeSeparators(fileInfo.path()).toStdWString();
|
||||
const auto relativePath = fileInfo.fileName().toStdWString();
|
||||
@ -691,6 +695,10 @@ OCC::Result<OCC::Vfs::ConvertToPlaceholderResult, QString> OCC::CfApiWrapper::up
|
||||
{
|
||||
Q_ASSERT(handle);
|
||||
|
||||
if (modtime <= 0) {
|
||||
return {QString{"Could not update metadata due to invalid modified time for %1: %2"}.arg(pathForHandle(handle)).arg(modtime)};
|
||||
}
|
||||
|
||||
const auto info = replacesPath.isEmpty() ? findPlaceholderInfo(handle)
|
||||
: findPlaceholderInfo(handleForPath(replacesPath));
|
||||
if (!info) {
|
||||
|
||||
@ -68,12 +68,20 @@ bool VfsSuffix::isHydrating() const
|
||||
|
||||
Result<void, QString> VfsSuffix::updateMetadata(const QString &filePath, time_t modtime, qint64, const QByteArray &)
|
||||
{
|
||||
if (modtime <= 0) {
|
||||
return {tr("Error updating metadata due to invalid modified time")};
|
||||
}
|
||||
|
||||
FileSystem::setModTime(filePath, modtime);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void, QString> VfsSuffix::createPlaceholder(const SyncFileItem &item)
|
||||
{
|
||||
if (item._modtime <= 0) {
|
||||
return {tr("Error updating metadata due to invalid modified time")};
|
||||
}
|
||||
|
||||
// The concrete shape of the placeholder is also used in isDehydratedPlaceholder() below
|
||||
QString fn = _setupParams.filesystemPath + item._file;
|
||||
if (!fn.endsWith(fileSuffix())) {
|
||||
|
||||
@ -69,12 +69,20 @@ bool VfsXAttr::isHydrating() const
|
||||
|
||||
Result<void, QString> VfsXAttr::updateMetadata(const QString &filePath, time_t modtime, qint64, const QByteArray &)
|
||||
{
|
||||
if (modtime <= 0) {
|
||||
return {tr("Error updating metadata due to invalid modified time")};
|
||||
}
|
||||
|
||||
FileSystem::setModTime(filePath, modtime);
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<void, QString> VfsXAttr::createPlaceholder(const SyncFileItem &item)
|
||||
{
|
||||
if (item._modtime <= 0) {
|
||||
return {tr("Error updating metadata due to invalid modified time")};
|
||||
}
|
||||
|
||||
const auto path = QString(_setupParams.filesystemPath + item._file);
|
||||
QFile file(path);
|
||||
if (file.exists() && file.size() > 1
|
||||
|
||||
Loading…
Reference in New Issue
Block a user