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
75
76
77
78QSaveFile::QSaveFile(QObject *parent)
79 : QFileDevice(*
new QSaveFilePrivate, parent)
84
85
86
87QSaveFile::QSaveFile(
const QString &name, QObject *parent)
88 : QFileDevice(*
new QSaveFilePrivate, parent)
95
96
97
98
99
100
103
104
105QSaveFile::~QSaveFile()
109 QFileDevice::close();
110 Q_ASSERT(d->fileEngine);
111 d->fileEngine->remove();
116
117
118
119
120
121QString QSaveFile::fileName()
const
123 return d_func()->fileName;
127
128
129
130
133
134
135
136
137
138void QSaveFile::setFileName(
const QString &name)
140 d_func()->fileName = name;
144
145
146
147
150
151
152
153
154
155
156
157
158
159
160bool QSaveFile::open(OpenMode mode)
164 qWarning(
"QSaveFile::open: File (%ls) already open", qUtf16Printable(fileName()));
168 d->writeError = QFileDevice::NoError;
169 if ((mode & (ReadOnly | WriteOnly)) == 0) {
170 qWarning(
"QSaveFile::open: Open mode not specified");
175 if (mode & (ReadOnly | Append | NewOnly | ExistingOnly)) {
176 qWarning(
"QSaveFile::open: Unsupported open mode 0x%x", uint(mode.toInt()));
181 QFileInfo existingFile(d->fileName);
182 if (existingFile.exists() && !existingFile.isWritable()) {
183 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Existing file %1 is not writable").arg(d->fileName));
184 d->writeError = QFileDevice::WriteError;
188 if (existingFile.isDir()) {
189 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Filename refers to a directory"));
190 d->writeError = QFileDevice::WriteError;
196 d->finalFileName = d->fileName;
197 if (existingFile.isSymLink()) {
199 while (--maxDepth && existingFile.isSymLink())
200 existingFile.setFile(existingFile.symLinkTarget());
202 d->finalFileName = existingFile.filePath();
205 auto openDirectly = [&]() {
206 d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
207 if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
208 d->useTemporaryFile =
false;
209 QFileDevice::open(mode);
215 bool requiresDirectWrite =
false;
218 requiresDirectWrite = d->finalFileName == d->fileName && d->fileName.indexOf(u':', 2) > 1;
219#elif defined(Q_OS_ANDROID)
221 requiresDirectWrite = d->fileName.startsWith(
"content://"_L1);
223 if (requiresDirectWrite) {
225 if (d->directWriteFallback) {
228 d->setError(d->fileEngine->error(), d->fileEngine->errorString());
229 d->fileEngine.reset();
232 QSaveFile::tr(
"QSaveFile cannot open '%1' without direct write fallback enabled.")
233 .arg(QDir::toNativeSeparators(d->fileName));
234 d->setError(QFileDevice::OpenError, msg);
239 d->fileEngine.reset(
new QTemporaryFileEngine(&d->finalFileName, QTemporaryFileEngine::Win32NonShared));
243 int perm = (existingFile.exists() ? 0600 : 0666);
244 static_cast<QTemporaryFileEngine *>(d->fileEngine.get())->initialize(d->finalFileName, perm);
246 if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
247 QFileDevice::FileError err = d->fileEngine->error();
249 if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) {
252 err = d->fileEngine->error();
255 if (err == QFileDevice::UnspecifiedError)
256 err = QFileDevice::OpenError;
257 d->setError(err, d->fileEngine->errorString());
258 d->fileEngine.reset();
262 d->useTemporaryFile =
true;
263 QFileDevice::open(mode);
264 if (existingFile.exists())
265 setPermissions(existingFile.permissions());
270
271
272
273
274
275void QSaveFile::close()
277 qFatal(
"QSaveFile::close called");
281
282
283
284
285
286
287
288
289
290
291
292bool QSaveFile::commit()
299 qWarning(
"QSaveFile::commit: File (%ls) is not open", qUtf16Printable(fileName()));
302 QFileDevice::close();
304 const auto &fe = d->fileEngine;
311 if (d->error == QFileDevice::NoError)
312 d->error = d->writeError;
313 d->writeError = QFileDevice::NoError;
315 if (d->useTemporaryFile) {
316 if (d->error != QFileDevice::NoError) {
323 if (!fe->renameOverwrite(d->finalFileName)) {
324 d->setError(fe->error(), fe->errorString());
332 return d->error == QFileDevice::NoError;
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353void QSaveFile::cancelWriting()
358 d->setError(QFileDevice::WriteError, QSaveFile::tr(
"Writing canceled by application"));
359 d->writeError = QFileDevice::WriteError;
363
364
365qint64 QSaveFile::writeData(
const char *data, qint64 len)
368 if (d->writeError != QFileDevice::NoError)
371 const qint64 ret = QFileDevice::writeData(data, len);
373 if (d->error != QFileDevice::NoError)
374 d->writeError = d->error;
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402void QSaveFile::setDirectWriteFallback(
bool enabled)
405 d->directWriteFallback = enabled;
409
410
411
412
413
414bool QSaveFile::directWriteFallback()
const
416 Q_D(
const QSaveFile);
417 return d->directWriteFallback;
422#include "moc_qsavefile.cpp"