7#if QT_CONFIG(temporaryfile)
9#include "qplatformdefs.h"
10#include "private/qsavefile_p.h"
12#include "qabstractfileengine_p.h"
14#include "qtemporaryfile.h"
15#include "private/qiodevice_p.h"
16#include "private/qtemporaryfile_p.h"
23using namespace Qt::StringLiterals;
25QSaveFilePrivate::QSaveFilePrivate()
26 : writeError(QFileDevice::NoError),
27 useTemporaryFile(
true),
28 directWriteFallback(
false)
32QSaveFilePrivate::~QSaveFilePrivate()
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
75QSaveFile::QSaveFile(
const QString &name)
76 : QFileDevice(*
new QSaveFilePrivate)
83
84
85QSaveFile::QSaveFile(
const QString &name)
86 : QFileDevice(*
new QSaveFilePrivate,
nullptr)
93
94
95
96QSaveFile::QSaveFile(QObject *parent)
97 : QFileDevice(*
new QSaveFilePrivate, parent)
101
102
103
104QSaveFile::QSaveFile(
const QString &name, QObject *parent)
105 : QFileDevice(*
new QSaveFilePrivate, parent)
113
114
115QSaveFile::~QSaveFile()
119 QFileDevice::close();
120 Q_ASSERT(d->fileEngine);
121 d->fileEngine->remove();
126
127
128
129
130
131QString QSaveFile::fileName()
const
133 return d_func()->fileName;
137
138
139
140
141
142void QSaveFile::setFileName(
const QString &name)
144 d_func()->fileName = name;
148
149
150
151
152
153
154
155
156
157
158bool QSaveFile::open(OpenMode mode)
162 qWarning(
"QSaveFile::open: File (%ls) already open", qUtf16Printable(fileName()));
166 d->writeError = QFileDevice::NoError;
167 if ((mode & (ReadOnly | WriteOnly)) == 0) {
168 qWarning(
"QSaveFile::open: Open mode not specified");
173 if (mode & (ReadOnly | Append | NewOnly | ExistingOnly)) {
174 qWarning(
"QSaveFile::open: Unsupported open mode 0x%x", uint(mode.toInt()));
179 QFileInfo existingFile(d->fileName);
180 if (existingFile.exists() && !existingFile.isWritable()) {
181 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Existing file %1 is not writable").arg(d->fileName));
182 d->writeError = QFileDevice::WriteError;
186 if (existingFile.isDir()) {
187 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Filename refers to a directory"));
188 d->writeError = QFileDevice::WriteError;
194 d->finalFileName = d->fileName;
195 if (existingFile.isSymLink()) {
197 while (--maxDepth && existingFile.isSymLink())
198 existingFile.setFile(existingFile.symLinkTarget());
200 d->finalFileName = existingFile.filePath();
203 auto openDirectly = [&]() {
204 d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
205 if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
206 d->useTemporaryFile =
false;
207 QFileDevice::open(mode);
213 bool requiresDirectWrite =
false;
216 requiresDirectWrite = d->finalFileName == d->fileName && d->fileName.indexOf(u':', 2) > 1;
217#elif defined(Q_OS_ANDROID)
219 requiresDirectWrite = d->fileName.startsWith(
"content://"_L1);
221 if (requiresDirectWrite) {
223 if (d->directWriteFallback) {
226 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
227 d->fileEngine.reset();
230 QSaveFile::tr(
"QSaveFile cannot open '%1' without direct write fallback enabled.")
231 .arg(QDir::toNativeSeparators(d->fileName));
232 d->setError(QFileDevice::OpenError, msg);
237 d->fileEngine.reset(
new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared));
241 int perm = (existingFile.exists() ? 0600 : 0666);
242 static_cast<QTemporaryFileEngine *>(d->fileEngine.get())->initialize(d->finalFileName, perm);
244 if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
245 QFileDevice::FileError err = d->fileEngine->error();
247 if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) {
250 err = d->fileEngine->error();
253 if (err == QFileDevice::UnspecifiedError)
254 err = QFileDevice::OpenError;
255 d->setError(err, d->fileEngine->errorString());
256 d->fileEngine.reset();
260 d->useTemporaryFile =
true;
261 QFileDevice::open(mode);
262 if (existingFile.exists())
263 setPermissions(existingFile.permissions());
268
269
270
271
272
273void QSaveFile::close()
275 qFatal(
"QSaveFile::close called");
279
280
281
282
283
284
285
286
287
288
289
290bool QSaveFile::commit()
297 qWarning(
"QSaveFile::commit: File (%ls) is not open", qUtf16Printable(fileName()));
300 QFileDevice::close();
302 const auto &fe = d->fileEngine;
309 if (d->error == QFileDevice::NoError)
310 d->error = d->writeError;
311 d->writeError = QFileDevice::NoError;
313 if (d->useTemporaryFile) {
314 if (d->error != QFileDevice::NoError) {
321 if (!fe->renameOverwrite(d->finalFileName)) {
322 d->setError(fe->error(), fe->errorString());
330 return d->error == QFileDevice::NoError;
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351void QSaveFile::cancelWriting()
356 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Writing canceled by application"));
357 d->writeError = QFileDevice::WriteError;
361
362
363qint64 QSaveFile::writeData(
const char *data, qint64 len)
366 if (d->writeError != QFileDevice::NoError)
369 const qint64 ret = QFileDevice::writeData(data, len);
371 if (d->error != QFileDevice::NoError)
372 d->writeError = d->error;
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400void QSaveFile::setDirectWriteFallback(
bool enabled)
403 d->directWriteFallback = enabled;
407
408
409
410
411
412bool QSaveFile::directWriteFallback()
const
414 Q_D(
const QSaveFile);
415 return d->directWriteFallback;
421#include "moc_qsavefile.cpp"