Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions 3rdparty/cli7zplugin/cli7zplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ bool Cli7zPlugin::isCorruptArchiveMsg(const QString &line)

bool Cli7zPlugin::isDiskFullMsg(const QString &line)
{
return line.contains(QLatin1String("No space left on device"));
// 7-Zip prints strerror() in the user's language ("errno=28 : 设备上没有空间"); 28 is ENOSPC
return line.contains(QLatin1String("No space left on device")) || line.contains(QLatin1String("errno=28 "));
}

bool Cli7zPlugin::isFileExistsMsg(const QString &line)
Expand Down Expand Up @@ -365,7 +366,8 @@ bool Cli7zPlugin::handleLine(const QString &line, WorkType workStatus)
}

if (isDiskFullMsg(line)) {
// m_eErrorType = ;
m_eErrorType = ET_InsufficientDiskSpace;
m_finishType = PFT_Error;
return false;
}

Expand Down
13 changes: 13 additions & 0 deletions 3rdparty/clirarplugin/clirarplugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,19 @@ bool CliRarPlugin::isOpenFileFailed(const QString &line)
return line.startsWith("Cannot create ");
}

ErrorType CliRarPlugin::errorTypeForExitCode(int exitCode) const
{
switch (exitCode) {
case 5: // write error
case 9: // cannot create a file
return ET_FileWriteError;
case 11: // wrong password
return ET_WrongPassword;
default: // 3 checksum error, 2 fatal error, ...
return ET_ArchiveDamaged;
}
}

void CliRarPlugin::killProcess(bool emitFinished)
{
Q_UNUSED(emitFinished);
Expand Down
5 changes: 5 additions & 0 deletions 3rdparty/clirarplugin/clirarplugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ class CliRarPlugin : public CliInterface

void killProcess(bool emitFinished) override;

/**
* @brief errorTypeForExitCode unrar: 5 write error, 9 cannot create a file, 11 wrong password
*/
ErrorType errorTypeForExitCode(int exitCode) const override;

private:
ParseState m_parseState = ParseStateTitle;
FileEntry m_fileEntry;
Expand Down
5 changes: 5 additions & 0 deletions 3rdparty/interface/archiveinterface/archiveinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ ErrorType ReadOnlyArchiveInterface::errorType()
return m_eErrorType;
}

void ReadOnlyArchiveInterface::resetResult()
{
m_eErrorType = ET_NoError;
}

bool ReadOnlyArchiveInterface::doKill()
{
return false; // 修改默认为未取消
Expand Down
6 changes: 6 additions & 0 deletions 3rdparty/interface/archiveinterface/archiveinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@ class ReadOnlyArchiveInterface : public QObject
*/
ErrorType errorType();

/**
* @brief resetResult forget the result of the previous operation; the interface is reused for
* later operations on the same archive, so a job starts with this
*/
virtual void resetResult();

/**
* @brief pauseOperation 暂停操作
*/
Expand Down
22 changes: 22 additions & 0 deletions 3rdparty/interface/archiveinterface/cliinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ CliInterface::~CliInterface()
deleteProcess();
}

void CliInterface::resetResult()
{
ReadOnlyArchiveInterface::resetResult();
m_finishType = PFT_Nomral;
}

PluginFinishType CliInterface::list()
{
setPassword(QString());
Expand Down Expand Up @@ -1488,6 +1494,12 @@ void CliInterface::processFinished(int exitCode, QProcess::ExitStatus exitStatus
emit signalFinished(m_finishType);
}

ErrorType CliInterface::errorTypeForExitCode(int exitCode) const
{
Q_UNUSED(exitCode);
return ET_ArchiveDamaged;
}

void CliInterface::extractProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
qCInfo(ifaceLog) << "Extraction process finished, exitcode:" << exitCode << " exitstatus:" << exitStatus;
Expand All @@ -1499,6 +1511,16 @@ void CliInterface::extractProcessFinished(int exitCode, QProcess::ExitStatus exi
m_finishType = PFT_Nomral;
}

// A failure the output parsing did not recognise is still a failure: unrar exits 3 after a
// checksum error and 5 when it cannot write, 7z exits 2 after any fatal error. Exit code 1 is
// "warnings" for both (the files were extracted), so it stays a success.
if (QProcess::NormalExit == exitStatus && exitCode >= 2 && PFT_Nomral == m_finishType) {
m_finishType = PFT_Error;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reset the finish type before reusing the interface

After this fallback marks an unrecognized extraction failure as PFT_Error, a subsequent successful extraction on the same open archive is also reported as failed. ArchiveManager::extractFiles() retains the interface, runProcess() clears only m_eErrorType, and the exit-code-0 branch in extractProcessFinished() refuses to overwrite PFT_Error. Consequently, even after resolving the original problem, extraction emits an error with ET_NoError until the archive is reopened. Reset m_finishType before starting each new operation while preserving errors detected within that operation.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, fixed by the same change: the finish type and the error type are both reset when a job starts (resetResult(), called from SingleJob::start() and UpdateJob::start()), not in runProcess().

if (ET_NoError == m_eErrorType) {
m_eErrorType = errorTypeForExitCode(exitCode);
}
}

m_indexOfListRootEntry = 0;
m_isEmptyArchive = false;

Expand Down
12 changes: 12 additions & 0 deletions 3rdparty/interface/archiveinterface/cliinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ class CliInterface : public ReadWriteArchiveInterface
explicit CliInterface(QObject *parent, const QVariantList &args);
~CliInterface() override;

/**
* @brief resetResult also forget the previous finish type: an operation that succeeds after a
* failed one on the same archive must not end as an error
*/
void resetResult() override;

// ReadOnlyArchiveInterface interface
public:
PluginFinishType list() override;
Expand Down Expand Up @@ -143,6 +149,12 @@ class CliInterface : public ReadWriteArchiveInterface
*/
virtual void killProcess(bool emitFinished = true) = 0;

/**
* @brief errorTypeForExitCode the error of an extraction that exited with this code (2 or more)
* although its output showed no error the plugin recognises
*/
virtual ErrorType errorTypeForExitCode(int exitCode) const;

/**
* @brief handleProgress 解析进度并发送进度信号
* @param line
Expand Down
8 changes: 8 additions & 0 deletions src/source/archivemanager/singlejob.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ void SingleJob::start()
return;
}

// The interface is reused for later operations on the same archive: start without the result of
// the previous one (errors found during this job, e.g. while listing first, are kept)
m_pInterface->resetResult();

// 判断是否通过线程的方式调用
if (m_pInterface->waitForFinished()) {
qCDebug(appLog) << "Executing work directly";
Expand Down Expand Up @@ -532,6 +536,10 @@ void UpdateJob::start()
return;
}

// The interface is reused for later operations on the same archive: start without the result of
// the previous one (errors found during this job, e.g. while listing first, are kept)
m_pInterface->resetResult();

d->start(); // 开启线程,执行操作
}

Expand Down
Loading