fix delayed write

authenticate when delayed write is checked
cancel helper when delayed write is unchecked
uncheck delayed write when dialog is closed
This commit is contained in:
Dmitry Degtyarev 2021-04-22 16:49:58 +04:00
parent 5e9730ed49
commit aa70baed33
9 changed files with 124 additions and 19 deletions

View File

@ -345,7 +345,12 @@ Dialog {
value: 0.0
}
}
// TODO: need to uncheck when drive
// changes because delayedwrite
// starts a helper that is setup for
// one specific drive
AdwaitaCheckBox {
id: delayedWriteCheck
text: qsTr("Write the image after downloading")
enabled: drives.selected && ((releases.selected.variant.status == Variant.DOWNLOADING) || (releases.selected.variant.status == Variant.DOWNLOAD_RESUMING)) && releases.selected.variant.canWrite
visible: enabled
@ -454,6 +459,7 @@ Dialog {
text: qsTr("Cancel")
enabled: true
onClicked: {
delayedWriteCheck.checked = false
dialog.close()
}
}

View File

@ -294,8 +294,10 @@ bool Drive::write(Variant *variant) {
m_variant->setErrorString(QString());
const QFile file(m_variant->filePath());
m_progress->setMax(file.size());
// TODO: this won't work for delayed write. When delayed
// write is turned on, this write() f-n is called and
// file size is not known yet.
if (file.size() > size()) {
m_variant->setErrorString(tr("This drive is not large enough."));
cancel();

View File

@ -278,7 +278,12 @@ void LinuxDrive::onReadyRead() {
while (m_process->bytesAvailable() > 0) {
QString line = m_process->readLine().trimmed();
qDebug() << "helper:" << line;
if (line == "WRITE") {
// Set progress bar max value at start of writing
const QFile file(m_variant->filePath());
m_progress->setMax(file.size());
m_progress->setCurrent(0);
}
else if (line == "DONE") {

View File

@ -103,6 +103,15 @@ Progress *Variant::progress() {
void Variant::setDelayedWrite(const bool value) {
delayedWrite = value;
Drive *drive = DriveManager::instance()->selected();
if (drive != nullptr) {
if (value) {
drive->write(this);
} else {
drive->cancel();
}
}
}
Variant::Status Variant::status() const {
@ -128,14 +137,6 @@ void Variant::onImageDownloadFinished() {
qDebug() << this->metaObject()->className() << "Image is ready";
setStatus(READY_FOR_WRITING);
if (delayedWrite) {
Drive *drive = DriveManager::instance()->selected();
if (drive != nullptr) {
drive->write(this);
}
}
break;
}
case ImageDownload::DiskError: {

View File

@ -378,6 +378,10 @@ void WinDrive::onReadyRead() {
QString line = m_child->readLine().trimmed();
if (line == "WRITE") {
m_progress->setCurrent(0);
// Set progress bar max value at start of writing
const QFile file(m_variant->filePath());
m_progress->setMax(file.size());
}
else if (line == "DONE") {
m_variant->setStatus(Variant::WRITING_FINISHED);

View File

@ -54,6 +54,9 @@ WriteJob::WriteJob(const QString &what, const QString &where)
qDBusRegisterMetaType<Properties>();
qDBusRegisterMetaType<InterfacesAndProperties>();
qDBusRegisterMetaType<DBusIntrospection>();
connect(
&watcher, &QFileSystemWatcher::fileChanged,
this, &WriteJob::onFileChanged);
QTimer::singleShot(0, this, SLOT(work()));
}
@ -251,12 +254,46 @@ void WriteJob::work() {
if (fd.fileDescriptor() < 0)
return;
if (!write(fd.fileDescriptor()))
const bool delayed_write =
[&]() {
const QString part_path = what + ".part";
return (QFile::exists(part_path) && !QFile::exists(what));
}();
if (delayed_write) {
watcher.addPath(what + ".part");
return;
}
// NOTE: let the app know that writing started
out << "WRITE\n";
out.flush();
const bool write_success = write(fd.fileDescriptor());
if (write_success) {
out.flush();
err << "DONE\n";
qApp->exit(0);
} else {
qApp->exit(4);
}
}
void WriteJob::onFileChanged(const QString &path) {
const bool still_downloading = QFile::exists(path);
if (still_downloading)
return;
err << "DONE\n";
out.flush();
qApp->exit(0);
const bool downloaded_file_exists = QFile::exists(what);
if (!downloaded_file_exists) {
qApp->exit(4);
return;
}
work();
}
std::tuple<std::unique_ptr<char[]>, char*, std::size_t> pageAlignedBuffer(std::size_t pages) {

View File

@ -28,6 +28,7 @@
#include <QProcess>
#include <QFile>
#include <QDBusUnixFileDescriptor>
#include <QFileSystemWatcher>
#include <unistd.h>
@ -52,12 +53,15 @@ public:
bool writePlain(int fd);
public slots:
void work();
private slots:
void onFileChanged(const QString &path);
private:
QString what;
QString where;
QTextStream out { stdout };
QTextStream err { stderr };
QDBusUnixFileDescriptor fd { -1 };
QFileSystemWatcher watcher;
};
std::tuple<std::unique_ptr<char[]>, char*, std::size_t> pageAlignedBuffer(std::size_t pages = 1024);

View File

@ -41,6 +41,10 @@ WriteJob::WriteJob(const QString &what, const QString &where)
bool ok = false;
this->where = where.toInt(&ok);
connect(
&watcher, &QFileSystemWatcher::fileChanged,
this, &WriteJob::onFileChanged);
QTimer::singleShot(0, this, &WriteJob::work);
}
@ -194,17 +198,42 @@ void WriteJob::unlockDrive(HANDLE drive) {
}
void WriteJob::work() {
if (!write()) {
const bool delayed_write =
[&]() {
const QString part_path = what + ".part";
return (QFile::exists(part_path) && !QFile::exists(what));
}();
if (delayed_write) {
watcher.addPath(what + ".part");
return;
}
// NOTE: let the app know that writing started
out << "WRITE\n";
out.flush();
bool write_success = write();
// NOTE: try to write 2 times and sleep between
// attempts. Apparently needed on windows.
if (!write_success) {
out << "0\n";
out.flush();
QThread::sleep(5);
if (!write())
return;
write_success = write();
}
err << "DONE\n";
out.flush();
qApp->exit(0);
if (write_success) {
out.flush();
err << "DONE\n";
qApp->exit(0);
} else {
qApp->exit(4);
}
}
bool WriteJob::write() {
@ -361,3 +390,17 @@ bool WriteJob::writePlain(HANDLE drive) {
return true;
}
void WriteJob::onFileChanged(const QString &path) {
const bool still_downloading = QFile::exists(path);
if (still_downloading)
return;
const bool downloaded_file_exists = QFile::exists(what);
if (!downloaded_file_exists) {
qApp->exit(4);
return;
}
work();
}

View File

@ -25,6 +25,7 @@
#include <QObject>
#include <QTextStream>
#include <QFileSystemWatcher>
#include <windows.h>
@ -57,12 +58,14 @@ private slots:
bool write();
bool writeCompressed(HANDLE drive);
bool writePlain(HANDLE drive);
void onFileChanged(const QString &path);
private:
QString what;
uint where;
QTextStream out { stdout };
QTextStream err { stderr };
QFileSystemWatcher watcher;
const int BLOCK_SIZE { 512 * 128 };
};