Skip to content

Commit

Permalink
Pass OpenMode::Truncate on write on Android
Browse files Browse the repository at this point in the history
Because unlike every other platform, this is not implied there. Instead
you start overwriting the file from the beginning, but potentially leave
garbage at the end of it if the new file is shorter than the old one.

Fixes #1252.
  • Loading branch information
askmeaboutlo0m committed Jul 15, 2024
1 parent 79a5b82 commit de08192
Show file tree
Hide file tree
Showing 20 changed files with 53 additions and 28 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ Unreleased Version 2.2.2-pre
* Feature: New dialog Selection > Expand/Shrink/Feather Selection that alters selections accordingly. Thanks MorrowShore for suggesting.
* Feature: Zooming with keyboard shortcuts now zooms in on the cursor when it's pointing at the canvas. If you don't like this, there's new shortcuts that always zoom on the center, which you can bind in the preferences. Thanks Chryssabliss for suggesting.
* Feature: Make header and footer buttons on docks stretch further if there's empty space, making them easier to hit. Thanks MorrowShore for suggesting.
* Fix: Properly truncate files when writing them on Android to avoid corruption from leftover junk at the end.

2024-02-25 Version 2.2.2-beta.1
* Server Feature: Allow adding a message when kicking someone through the admin API.
Expand Down
3 changes: 2 additions & 1 deletion src/desktop/dialogs/sessionsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <QStringListModel>
#include <QTemporaryFile>
#include <QTimer>
#include <dpcommon/platform_qt.h>

namespace dialogs {

Expand Down Expand Up @@ -538,7 +539,7 @@ void SessionSettingsDialog::permissionPresetSaving(const QString &presetFile)

// Save
QFile f(presetFile);
if(!f.open(QFile::WriteOnly)) {
if(!f.open(DP_QT_WRITE_FLAGS)) {
qWarning("%s: could not open file", qPrintable(presetFile));
return;
}
Expand Down
3 changes: 2 additions & 1 deletion src/desktop/filewrangler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include <QTemporaryDir>
#include <QTemporaryFile>
#include <QThreadPool>
#include <dpcommon/platform_qt.h>
#if defined(Q_OS_ANDROID) || defined(__EMSCRIPTEN__)
# include "desktop/dialogs/filetypedialog.h"
#endif
Expand Down Expand Up @@ -890,7 +891,7 @@ bool FileWrangler::saveBytesContent(
return true;
} else {
QFile file(path);
bool ok = file.open(QFile::WriteOnly) &&
bool ok = file.open(DP_QT_WRITE_FLAGS) &&
file.write(bytes) == bytes.size() && file.flush();
if(!ok && outError) {
*outError = file.errorString();
Expand Down
1 change: 1 addition & 0 deletions src/drawdance/libcommon/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ if(FILE_IO_IMPL STREQUAL "QT")
dpcommon/input_qt.h
dpcommon/output_qt.cpp
dpcommon/output_qt.h
dpcommon/platform_qt.h
)
target_link_libraries(dpcommon PUBLIC "Qt${QT_VERSION_MAJOR}::Core")

Expand Down
8 changes: 4 additions & 4 deletions src/drawdance/libcommon/dpcommon/output_qt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern "C" {
#include "output_qt.h"
#include "output.h"
}

#include "platform_qt.h"
#include <QFile>
#include <QSaveFile>
#ifdef DP_QT_IO_KARCHIVE
Expand Down Expand Up @@ -138,7 +138,7 @@ extern "C" DP_Output *DP_qfile_output_new_from_path(const char *path,
DP_OutputQtNewFn new_fn)
{
QFile *file = new QFile{QString::fromUtf8(path)};
if (file->open(QIODevice::WriteOnly)) {
if (file->open(DP_QT_WRITE_FLAGS)) {
return DP_qfile_output_new(file, true, new_fn);
}
else {
Expand Down Expand Up @@ -214,7 +214,7 @@ extern "C" DP_Output *DP_qsavefile_output_new_from_path(const char *path,
{
QSaveFile *sf = new QSaveFile{QString::fromUtf8(path)};
sf->setDirectWriteFallback(true);
if (sf->open(QIODevice::WriteOnly)) {
if (sf->open(DP_QT_WRITE_FLAGS)) {
return new_fn(qsavefile_output_init, sf, sizeof(DP_QFileOutputState));
}
else {
Expand Down Expand Up @@ -301,7 +301,7 @@ DP_karchive_gzip_output_new_from_path(const char *path, DP_OutputQtNewFn new_fn)
{
KCompressionDevice *dev = new KCompressionDevice{QString::fromUtf8(path),
KCompressionDevice::GZip};
if (dev->open(QIODevice::WriteOnly)) {
if (dev->open(DP_QT_WRITE_FLAGS)) {
return new_fn(kcompressiondevice_output_init, dev,
sizeof(DP_KCompressionDeviceOutputState));
}
Expand Down
14 changes: 14 additions & 0 deletions src/drawdance/libcommon/dpcommon/platform_qt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#ifndef DPCOMMON_PLATFORM_H
#define DPCOMMON_PLATFORM_H
#include <QIODevice>

// On Android, files don't get truncated when writing without the truncate flag.
static constexpr QIODevice::OpenMode DP_QT_WRITE_FLAGS =
#ifdef Q_OS_ANDROID
QIODevice::WriteOnly | QIODevice::Truncate;
#else
QIODevice::WriteOnly;
#endif

#endif
3 changes: 2 additions & 1 deletion src/drawdance/libengine/dpengine/image_qt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern "C" {
#include <dpcommon/input.h>
#include <dpcommon/output.h>
}
#include <dpcommon/platform_qt.h>
#include <QIODevice>
#include <QImage>

Expand Down Expand Up @@ -75,7 +76,7 @@ class DP_OutputDevice : public QIODevice {
public:
explicit DP_OutputDevice(DP_Output *output) : QIODevice{}, m_output{output}
{
open(QIODevice::WriteOnly);
open(DP_QT_WRITE_FLAGS);
}

protected:
Expand Down
3 changes: 2 additions & 1 deletion src/drawdance/libengine/dpengine/zip_archive_karchive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern "C" {
#include <dpcommon/common.h>
#include <dpcommon/conversions.h>
}
#include <dpcommon/platform_qt.h>
#include <KZip>


Expand Down Expand Up @@ -83,7 +84,7 @@ extern "C" void DP_zip_reader_file_free(DP_ZipReaderFile *zrf)
extern "C" DP_ZipWriter *DP_zip_writer_new(const char *path)
{
KZip *kz = new KZip{path};
if (kz->open(QIODevice::WriteOnly)) {
if (kz->open(DP_QT_WRITE_FLAGS)) {
return reinterpret_cast<DP_ZipWriter *>(kz);
}
else {
Expand Down
4 changes: 2 additions & 2 deletions src/libclient/brushes/brushpresetmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
#include "libshared/util/paths.h"
#include "libshared/util/qtcompat.h"
#include "libclient/drawdance/ziparchive.h"

#include <dpcommon/platform_qt.h>
#include <QBuffer>
#include <QDebug>
#include <QDirIterator>
Expand Down Expand Up @@ -1263,7 +1263,7 @@ QByteArray BrushPresetModel::toPng(const QPixmap &pixmap)
{
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
buffer.open(DP_QT_WRITE_FLAGS);
pixmap.save(&buffer, "PNG");
buffer.close();
return bytes;
Expand Down
3 changes: 2 additions & 1 deletion src/libclient/document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <QThreadPool>
#include <QTimer>
#include <QtEndian>
#include <dpcommon/platform_qt.h>
#include <parson.h>
#ifndef HAVE_CLIPBOARD_EMULATION
# include <QClipboard>
Expand Down Expand Up @@ -1197,7 +1198,7 @@ void Document::downloadSelection(const QString &fileName)
QFileInfo fileInfo(fileName);
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
buffer.open(DP_QT_WRITE_FLAGS);
bool ok = selectionToImage().save(
&buffer, qUtf8Printable(fileInfo.completeSuffix()));
buffer.close();
Expand Down
3 changes: 2 additions & 1 deletion src/libclient/net/login.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <QStringList>
#include <QUrlQuery>
#include <QUuid>
#include <dpcommon/platform_qt.h>
#include <utility>
#ifdef __EMSCRIPTEN__
# include "libclient/wasmsupport.h"
Expand Down Expand Up @@ -1033,7 +1034,7 @@ void saveCert(const QFileInfo &file, const QSslCertificate &cert)

QFile certOut(filename);

if(certOut.open(QFile::WriteOnly))
if(certOut.open(DP_QT_WRITE_FLAGS))
certOut.write(cert.toPem());
else
qCWarning(lcDpLogin) << "Couldn't open" << filename << "for writing!";
Expand Down
4 changes: 2 additions & 2 deletions src/libclient/utils/avatarlistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "libclient/utils/identicon.h"
#include "libclient/utils/wasmpersistence.h"
#include "libshared/util/paths.h"

#include <dpcommon/platform_qt.h>
#include <QDir>
#include <QBuffer>
#include <QCryptographicHash>
Expand Down Expand Up @@ -169,7 +169,7 @@ void AvatarListModel::commit()

const QString filename = QString::fromUtf8(hash.result().toHex() + ".png");
QFile f { dir.filePath(filename) };
if(!f.open(QFile::WriteOnly)) {
if(!f.open(DP_QT_WRITE_FLAGS)) {
qWarning("Couldn't open %s", qUtf8Printable(filename));
continue;
}
Expand Down
4 changes: 2 additions & 2 deletions src/libclient/utils/certificatestoremodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#include "libclient/utils/certificatestoremodel.h"
#include "libclient/utils/wasmpersistence.h"
#include "libshared/util/paths.h"

#include <dpcommon/platform_qt.h>
#include <QDir>
#include <QFile>
#include <QIcon>
Expand Down Expand Up @@ -198,7 +198,7 @@ bool CertificateStoreModel::submit()

if (cert.pending == Pending::Copy) {
auto file = QFile(to);
if (!file.open(QFile::WriteOnly)) {
if (!file.open(DP_QT_WRITE_FLAGS)) {
m_lastError = tr("Could not open '%1' for writing: %2.")
.arg(file.fileName())
.arg(file.errorString());
Expand Down
6 changes: 3 additions & 3 deletions src/libclient/utils/listservermodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#include "libclient/utils/listservermodel.h"
#include "libclient/utils/wasmpersistence.h"
#include "libshared/util/paths.h"

#include <dpcommon/platform_qt.h>
#include <QImage>
#include <QBuffer>
#include <QCryptographicHash>
Expand Down Expand Up @@ -152,7 +152,7 @@ QIcon ListServerModel::setFavicon(const QString &url, const QImage &icon)
// Serialize icon in PNG format
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
buffer.open(DP_QT_WRITE_FLAGS);
scaledIcon.save(&buffer, "PNG");

// Generate file name
Expand All @@ -174,7 +174,7 @@ QIcon ListServerModel::setFavicon(const QString &url, const QImage &icon)
if(!saved) {
saved = true;
QFile f(utils::paths::writablePath("favicons/", s.iconName));
if(!f.open(QIODevice::WriteOnly)) {
if(!f.open(DP_QT_WRITE_FLAGS)) {
qWarning() << "Unable to open" << f.fileName() << f.errorString();
} else {
f.write(data);
Expand Down
3 changes: 2 additions & 1 deletion src/libserver/filedhistory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern "C" {
#include <QSet>
#include <QTimerEvent>
#include <QVarLengthArray>
#include <dpcommon/platform_qt.h>

namespace server {

Expand Down Expand Up @@ -127,7 +128,7 @@ bool FiledHistory::create()
return false;
}

if(!m_journal->open(QFile::WriteOnly)) {
if(!m_journal->open(DP_QT_WRITE_FLAGS)) {
qWarning() << m_journal->fileName() << m_journal->errorString();
return false;
}
Expand Down
4 changes: 2 additions & 2 deletions src/libserver/tests/filename.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#include "libserver/util/filename.h"

#include <dpcommon/platform_qt.h>
#include <QtTest/QtTest>
#include <QTemporaryDir>
#include <QDir>
Expand Down Expand Up @@ -38,7 +38,7 @@ private slots:
bool touch(const QString &path)
{
QFile f { path };
if(!f.open(QIODevice::WriteOnly))
if(!f.open(DP_QT_WRITE_FLAGS))
return false;
f.close();
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/libshared/tests/filename.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later

#include "libshared/util/filename.h"

#include <dpcommon/platform_qt.h>
#include <QtTest/QtTest>
#include <QTemporaryDir>
#include <QDir>
Expand Down Expand Up @@ -38,7 +38,7 @@ private slots:
bool touch(const QString &path)
{
QFile f { path };
if(!f.open(QIODevice::WriteOnly))
if(!f.open(DP_QT_WRITE_FLAGS))
return false;
f.close();
return true;
Expand Down
4 changes: 2 additions & 2 deletions src/libshared/util/networkaccess.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "libshared/util/networkaccess.h"
#include "libshared/util/qtcompat.h"

#include <dpcommon/platform_qt.h>
#include <QNetworkReply>
#include <QMutexLocker>
#include <QHash>
Expand Down Expand Up @@ -127,7 +127,7 @@ void FileDownload::onReadyRead()
Q_ASSERT(m_file);

if(!m_file->isOpen()) {
if(!m_file->open(m_file->inherits("QSaveFile") ? QIODevice::WriteOnly : QIODevice::ReadWrite)) {
if(!m_file->open(m_file->inherits("QSaveFile") ? DP_QT_WRITE_FLAGS : QIODevice::ReadWrite)) {
m_errorMessage = m_file->errorString();
m_reply->abort();
return;
Expand Down
3 changes: 2 additions & 1 deletion src/thinsrv/tests/templates.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <QFile>
#include <QTemporaryDir>
#include <QtTest/QtTest>
#include <dpcommon/platform_qt.h>

using namespace server;

Expand Down Expand Up @@ -75,7 +76,7 @@ private slots:
bool touch(const QString &path)
{
QFile f{path};
if(!f.open(QIODevice::WriteOnly))
if(!f.open(DP_QT_WRITE_FLAGS))
return false;
f.close();
return true;
Expand Down
3 changes: 2 additions & 1 deletion src/tools/drawpile-timelapse/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <QSaveFile>
#include <QStandardPaths>
#include <QString>
#include <dpcommon/platform_qt.h>

extern "C" int drawpile_timelapse_main(const char *default_logo_path);

Expand All @@ -29,7 +30,7 @@ static QString writeDefaultLogo()
QByteArray bytes = in.readAll();
in.close();

if(!out.open(QIODevice::WriteOnly)) {
if(!out.open(DP_QT_WRITE_FLAGS)) {
qWarning(
"Error opening '%s': %s", qUtf8Printable(out.fileName()),
qUtf8Printable(out.errorString()));
Expand Down

0 comments on commit de08192

Please sign in to comment.