7#include "qplatformdefs.h"
9#include "private/qtemporaryfile_p.h"
10#include "private/qfile_p.h"
11#include "private/qsystemerror_p.h"
14#include "private/qcore_unix_p.h"
18#if defined(QT_BUILD_CORE_LIB)
21#define tr(X) QString::fromLatin1(X)
54 if (qfilename[phPos] == u
'X') {
60 || qfilename[phPos] == u
'/') {
70 qfilename.append(
".XXXXXX"_L1);
77 phPos = filename.
size();
115 Char *
const placeholderEnd = placeholderStart +
length;
129 enum { BitsPerCharacter = 10 };
131 Char *rIter = placeholderEnd;
132 while (rIter != placeholderStart) {
134 auto applyOne = [&]() {
135 quint32 v = rnd & ((1 << BitsPerCharacter) - 1);
136 rnd >>= BitsPerCharacter;
137 char ch = char((26 + 26) *
v / (1 << BitsPerCharacter));
145 if (rIter == placeholderStart)
149 if (rIter == placeholderStart)
159#if QT_CONFIG(temporaryfile)
177 const int maxAttempts = 16;
178 for (
int attempt = 0; attempt < maxAttempts; ++attempt) {
184 const DWORD shareMode = (
flags & QTemporaryFileEngine::Win32NonShared)
185 ? 0u : (FILE_SHARE_READ | FILE_SHARE_WRITE);
187 const DWORD extraAccessFlags = (
flags & QTemporaryFileEngine::Win32NonShared) ? DELETE : 0;
188 file = CreateFile((
const wchar_t *)
path.constData(),
189 GENERIC_READ | GENERIC_WRITE | extraAccessFlags,
190 shareMode, NULL, CREATE_NEW,
191 FILE_ATTRIBUTE_NORMAL, NULL);
193 if (
file != INVALID_HANDLE_VALUE)
196 DWORD err = GetLastError();
197 if (err == ERROR_ACCESS_DENIED) {
198 WIN32_FILE_ATTRIBUTE_DATA attributes;
199 if (!GetFileAttributesEx((
const wchar_t *)
path.constData(),
200 GetFileExInfoStandard, &attributes)
206 }
else if (err != ERROR_FILE_EXISTS) {
213 QT_OPEN_CREAT | QT_OPEN_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
214 static_cast<mode_t
>(
mode));
230enum class CreateUnnamedFileStatus {
236static CreateUnnamedFileStatus
239#ifdef LINUX_UNNAMED_TMPFILE
243 return CreateUnnamedFileStatus::NotSupported;
247 if (lastSlash >= 0) {
250 tfn.path[lastSlash] =
'\0';
254 file =
QT_OPEN(
p, O_TMPFILE | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
255 static_cast<mode_t
>(
mode));
257 return CreateUnnamedFileStatus::Success;
259 if (errno == EOPNOTSUPP || errno == EISDIR) {
263 tfn.path[lastSlash] =
'/';
264 return CreateUnnamedFileStatus::NotSupported;
269 return CreateUnnamedFileStatus::OtherError;
275 return CreateUnnamedFileStatus::NotSupported;
280QTemporaryFileEngine::~QTemporaryFileEngine()
287bool QTemporaryFileEngine::isReallyOpen()
const
291 if (!((
nullptr ==
d->fh) && (-1 ==
d->fd)
293 && (INVALID_HANDLE_VALUE ==
d->fileHandle)
302void QTemporaryFileEngine::setFileName(
const QString &
file)
309bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode,
310 std::optional<QFile::Permissions> permissions)
317 if (!filePathIsTemplate)
329 CreateUnnamedFileStatus st = createUnnamedFile(
file, tfn, fileMode, &
error);
330 if (st == CreateUnnamedFileStatus::Success) {
332 d->fileEntry.clear();
333 }
else if (st == CreateUnnamedFileStatus::NotSupported &&
335 filePathIsTemplate =
false;
343#if !defined(Q_OS_WIN)
344 d->closeFileHandle =
true;
347 d->openMode = openMode;
348 d->lastFlushFailed =
false;
354bool QTemporaryFileEngine::remove()
364 d->fileEntry.clear();
370 filePathIsTemplate = filePathWasTemplate;
376bool QTemporaryFileEngine::rename(
const QString &newName)
378 if (isUnnamedFile()) {
379 bool ok = materializeUnnamedFile(newName, DontOverwrite);
387bool QTemporaryFileEngine::renameOverwrite(
const QString &newName)
389 if (isUnnamedFile()) {
390 bool ok = materializeUnnamedFile(newName, Overwrite);
395 if (
flags & Win32NonShared) {
397 bool ok = d_func()->nativeRenameOverwrite(newEntry);
401 setFileEntry(std::move(newEntry));
410bool QTemporaryFileEngine::close()
420 if (isUnnamedFile()) {
421 if (
file == AbsoluteLinkTarget ||
file == RawLinkPath) {
427 const_cast<QTemporaryFileEngine *
>(
this)->materializeUnnamedFile(templateName, NameIsTemplate);
432bool QTemporaryFileEngine::materializeUnnamedFile(
const QString &newName, QTemporaryFileEngine::MaterializationMode
mode)
436#ifdef LINUX_UNNAMED_TMPFILE
440 return ::linkat(AT_FDCWD,
src, AT_FDCWD,
dst.nativeFilePath(), AT_SYMLINK_FOLLOW) == 0;
447 filePathIsTemplate =
false;
449 d_func()->fileEntry =
entry;
453 auto materializeAsTemplate = [=](
const QString &newName) {
455 static const int maxAttempts = 16;
456 for (
int attempt = 0; attempt < maxAttempts; ++attempt) {
459 if (materializeAt(
entry))
460 return success(
entry);
465 if (
mode == NameIsTemplate) {
466 if (materializeAsTemplate(newName))
471 if (materializeAt(
dst))
474 if (errno == EEXIST &&
mode == Overwrite) {
476 if (!materializeAsTemplate(templateName))
490bool QTemporaryFileEngine::isUnnamedFile()
const
492#ifdef LINUX_UNNAMED_TMPFILE
494 Q_ASSERT(d_func()->fileEntry.isEmpty());
505QTemporaryFilePrivate::QTemporaryFilePrivate()
509QTemporaryFilePrivate::QTemporaryFilePrivate(
const QString &templateNameIn)
510 : templateName(templateNameIn)
514QTemporaryFilePrivate::~QTemporaryFilePrivate()
521 fileEngine.reset(
new QTemporaryFileEngine(&templateName));
524 return fileEngine.get();
527void QTemporaryFilePrivate::resetFileEngine()
const
532 QTemporaryFileEngine *tef =
static_cast<QTemporaryFileEngine *
>(fileEngine.get());
534 tef->initialize(templateName, 0600);
536 tef->initialize(
fileName, 0600,
false);
539void QTemporaryFilePrivate::materializeUnnamedFile()
541#ifdef LINUX_UNNAMED_TMPFILE
542 if (!
fileName.isEmpty() || !fileEngine)
545 auto *tef =
static_cast<QTemporaryFileEngine *
>(fileEngine.get());
550QString QTemporaryFilePrivate::defaultTemplateName()
553#if defined(QT_BUILD_CORE_LIB)
557 baseName =
"qt_temp"_L1;
621QTemporaryFile::QTemporaryFile()
622 :
QFile(*new QTemporaryFilePrivate)
626QTemporaryFile::QTemporaryFile(
const QString &templateName)
627 :
QFile(*new QTemporaryFilePrivate(templateName))
640QTemporaryFile::QTemporaryFile()
669QTemporaryFile::QTemporaryFile(
const QString &templateName)
670 : QTemporaryFile(templateName,
nullptr)
682QTemporaryFile::QTemporaryFile(
QObject *parent)
683 :
QFile(*new QTemporaryFilePrivate, parent)
705QTemporaryFile::QTemporaryFile(
const QString &templateName,
QObject *parent)
706 :
QFile(*new QTemporaryFilePrivate(templateName), parent)
718QTemporaryFile::~QTemporaryFile()
722 if (!
d->fileName.isEmpty() &&
d->autoRemove)
749bool QTemporaryFile::autoRemove()
const
751 Q_D(
const QTemporaryFile);
752 return d->autoRemove;
773void QTemporaryFile::setAutoRemove(
bool b)
788QString QTemporaryFile::fileName()
const
790 Q_D(
const QTemporaryFile);
791 auto tef =
static_cast<QTemporaryFileEngine *
>(
d->fileEngine.get());
792 if (tef && tef->isReallyOpen())
793 const_cast<QTemporaryFilePrivate *
>(
d)->materializeUnnamedFile();
795 if (
d->fileName.isEmpty())
806QString QTemporaryFile::fileTemplate()
const
808 Q_D(
const QTemporaryFile);
809 return d->templateName;
833void QTemporaryFile::setFileTemplate(
const QString &
name)
836 d->templateName =
name;
863bool QTemporaryFile::rename(
const QString &newName)
866 auto tef =
static_cast<QTemporaryFileEngine *
>(
d->fileEngine.get());
867 if (!tef || !tef->isReallyOpen() || !tef->filePathWasTemplate)
873 if (tef->rename(newName)) {
876 d->fileName = newName;
911QTemporaryFile *QTemporaryFile::createNativeFile(
QFile &
file)
924 QTemporaryFile *
ret =
new QTemporaryFile;
957bool QTemporaryFile::open(OpenMode
flags)
960 auto tef =
static_cast<QTemporaryFileEngine *
>(
d->fileEngine.get());
961 if (tef && tef->isReallyOpen()) {
971 d->resetFileEngine();
974 tef =
static_cast<QTemporaryFileEngine *
>(
d->fileEngine.get());
975 if (tef->isUnnamedFile())
989#include "moc_qtemporaryfile.cpp"
\inmodule QtCore \reentrant
FileName
These values are used to request a file name in a particular format.
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
QString applicationName
the name of this application
static QString fromNativeSeparators(const QString &pathName)
static QString tempPath()
Returns the absolute canonical path of the system's temporary directory.
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
QString fileName(FileName file) const override
\reimp
bool rename(const QString &newName) override
Requests that the file be renamed to newName in the file system.
bool renameOverwrite(const QString &newName) override
bool close() override
\reimp
bool open(QIODevice::OpenMode openMode, std::optional< QFile::Permissions > permissions) override
\reimp
void setFileName(const QString &file) override
\reimp
bool remove() override
\reimp
qint64 pos() const override
\reimp
bool seek(qint64 offset) override
For random-access devices, this function sets the current position to pos, returning true on success,...
void close() override
Calls QFileDevice::flush() and closes the file.
Q_AUTOTEST_EXPORT NativePath nativeFilePath() const
QFILE_MAYBE_NODISCARD bool open(OpenMode flags) override
Opens the file using OpenMode mode, returning true if successful; otherwise false.
bool rename(const QString &newName)
Renames the file currently specified by fileName() to newName.
bool isOpen() const
Returns true if the device is open; otherwise returns false.
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read.
static Q_DECL_CONST_FUNCTION QRandomGenerator * global()
\threadsafe
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Combined button and popup list for selecting options.
bool qt_haveLinuxProcfs()
DBusConnection const char DBusError * error
#define INVALID_FILE_ATTRIBUTES
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLenum GLuint GLenum GLsizei length
GLsizei const GLchar *const * path
static void setError(QJsonObject *response, const QString &msg)
settings remove("monkey")
char * toString(const MyType &t)
[31]
QTemporaryFileName(const QString &templateName)
QFileSystemEntry::NativePath generateNext()
QFileSystemEntry::NativePath path