6#include "qplatformdefs.h"
12#include <QtCore/qoperatingsystemversion.h>
13#include <QtCore/private/qcore_unix_p.h>
14#include <QtCore/private/qfiledevice_p.h>
15#include <QtCore/private/qfunctions_p.h>
16#include <QtCore/qvarlengtharray.h>
17#ifndef QT_BOOTSTRAPPED
18# include <QtCore/qstandardpaths.h>
19# include <QtCore/private/qtemporaryfile_p.h>
32#if __has_include(<paths.h>)
36# define _PATH_TMP "/tmp"
39#if defined(Q_OS_DARWIN)
40# include <QtCore/private/qcore_mac_p.h>
41# include <CoreFoundation/CFBundle.h>
42# include <UniformTypeIdentifiers/UTType.h>
43# include <UniformTypeIdentifiers/UTCoreTypes.h>
44# include <Foundation/Foundation.h>
45# include <sys/clonefile.h>
50#include <CoreServices/CoreServices.h>
53#if defined(QT_PLATFORM_UIKIT)
54#include <MobileCoreServices/MobileCoreServices.h>
57#if defined(Q_OS_LINUX)
58# include <sys/ioctl.h>
59# include <sys/sendfile.h>
64# define FICLONE _IOW(0x94, 9, int)
68#if defined(Q_OS_ANDROID)
72# undef STATX_BASIC_STATS
93#if defined(Q_OS_DARWIN)
98 QCFString path = CFStringCreateWithFileSystemRepresentation(0,
99 entry.nativeFilePath().constData());
103 QCFType<CFURLRef>
url = CFURLCreateWithFileSystemPath(0,
path, kCFURLPOSIXPathStyle,
109 if (CFURLCopyResourcePropertyForKey(
url,
key, &
value, NULL)) {
110 if (
value == kCFBooleanTrue)
119 if (!
data.isDirectory())
125 if (suffix.
length() > 0) {
127 const auto *utType = [UTType typeWithFilenameExtension:suffix.toNSString()];
128 if ([utType conformsToType:UTTypeBundle])
132 QCFType<CFStringRef>
path =
entry.filePath().toCFString();
133 QCFType<CFURLRef>
url = CFURLCreateWithFileSystemPath(0,
path, kCFURLPOSIXPathStyle,
true);
142 QCFType<CFURLRef> application = LSCopyDefaultApplicationURLForURL(
url,
143 kLSRolesEditor | kLSRolesViewer,
nullptr);
146 QCFType<CFBundleRef> bundle = CFBundleCreate(kCFAllocatorDefault, application);
147 CFStringRef identifier = CFBundleGetIdentifier(bundle);
148 QString applicationId = QString::fromCFString(identifier);
149 if (applicationId !=
"com.apple.finder"_L1)
156 return hasResourcePropertyFlag(
data,
entry, kCFURLIsPackageKey);
164 using namespace std::chrono;
165 return milliseconds{seconds{
t}}.count();
169[[maybe_unused]]
qint64 atime(
const QT_STATBUF &statBuffer,
ulong)
171 return time_t_toMsecs(statBuffer.st_atime);
173[[maybe_unused]]
qint64 birthtime(
const QT_STATBUF &,
ulong)
177[[maybe_unused]]
qint64 ctime(
const QT_STATBUF &statBuffer,
ulong)
179 return time_t_toMsecs(statBuffer.st_ctime);
181[[maybe_unused]]
qint64 mtime(
const QT_STATBUF &statBuffer,
ulong)
183 return time_t_toMsecs(statBuffer.st_mtime);
189qint64 timespecToMSecs(
const T &spec)
191 using namespace std::chrono;
192 const nanoseconds nsecs = seconds{spec.tv_sec} + nanoseconds{spec.tv_nsec};
193 return duration_cast<milliseconds>(nsecs).count();
198[[maybe_unused]]
static typename std::enable_if<(&T::st_atim,
true),
qint64>
::type
199atime(
const T &statBuffer,
int)
200{
return timespecToMSecs(statBuffer.st_atim); }
203[[maybe_unused]]
static typename std::enable_if<(&T::st_birthtim,
true),
qint64>
::type
204birthtime(
const T &statBuffer,
int)
205{
return timespecToMSecs(statBuffer.st_birthtim); }
208[[maybe_unused]]
static typename std::enable_if<(&T::st_ctim,
true),
qint64>
::type
209ctime(
const T &statBuffer,
int)
210{
return timespecToMSecs(statBuffer.st_ctim); }
213[[maybe_unused]]
static typename std::enable_if<(&T::st_mtim,
true),
qint64>
::type
214mtime(
const T &statBuffer,
int)
215{
return timespecToMSecs(statBuffer.st_mtim); }
220[[maybe_unused]]
static typename std::enable_if<(&T::st_atimespec,
true),
qint64>
::type
221atime(
const T &statBuffer,
int)
222{
return timespecToMSecs(statBuffer.st_atimespec); }
225[[maybe_unused]]
static typename std::enable_if<(&T::st_birthtimespec,
true),
qint64>
::type
226birthtime(
const T &statBuffer,
int)
227{
return timespecToMSecs(statBuffer.st_birthtimespec); }
230[[maybe_unused]]
static typename std::enable_if<(&T::st_ctimespec,
true),
qint64>
::type
231ctime(
const T &statBuffer,
int)
232{
return timespecToMSecs(statBuffer.st_ctimespec); }
235[[maybe_unused]]
static typename std::enable_if<(&T::st_mtimespec,
true),
qint64>
::type
236mtime(
const T &statBuffer,
int)
237{
return timespecToMSecs(statBuffer.st_mtimespec); }
240#if !defined(st_mtimensec) && !defined(__alpha__)
243[[maybe_unused]]
static typename std::enable_if<(&T::st_atimensec,
true),
qint64>
::type
244atime(
const T &statBuffer,
int)
245{
return statBuffer.st_atime *
Q_INT64_C(1000) + statBuffer.st_atimensec / 1000000; }
248[[maybe_unused]]
static typename std::enable_if<(&T::st_birthtimensec,
true),
qint64>
::type
249birthtime(
const T &statBuffer,
int)
250{
return statBuffer.st_birthtime *
Q_INT64_C(1000) + statBuffer.st_birthtimensec / 1000000; }
253[[maybe_unused]]
static typename std::enable_if<(&T::st_ctimensec,
true),
qint64>
::type
254ctime(
const T &statBuffer,
int)
255{
return statBuffer.st_ctime *
Q_INT64_C(1000) + statBuffer.st_ctimensec / 1000000; }
258[[maybe_unused]]
static typename std::enable_if<(&T::st_mtimensec,
true),
qint64>
::type
259mtime(
const T &statBuffer,
int)
260{
return statBuffer.st_mtime *
Q_INT64_C(1000) + statBuffer.st_mtimensec / 1000000; }
265#ifdef STATX_BASIC_STATS
266static int qt_real_statx(
int fd,
const char *pathname,
int flags,
struct statx *statxBuffer)
268 unsigned mask = STATX_BASIC_STATS | STATX_BTIME;
270 return ret == -1 ? -errno : 0;
273static int qt_statx(
const char *pathname,
struct statx *statxBuffer)
275 return qt_real_statx(AT_FDCWD, pathname, 0, statxBuffer);
278static int qt_lstatx(
const char *pathname,
struct statx *statxBuffer)
280 return qt_real_statx(AT_FDCWD, pathname, AT_SYMLINK_NOFOLLOW, statxBuffer);
285 return qt_real_statx(
fd,
"", AT_EMPTY_PATH, statxBuffer);
288inline void QFileSystemMetaData::fillFromStatxBuf(
const struct statx &statxBuffer)
291 if (statxBuffer.stx_mode & S_IRUSR)
293 if (statxBuffer.stx_mode & S_IWUSR)
295 if (statxBuffer.stx_mode & S_IXUSR)
298 if (statxBuffer.stx_mode & S_IRGRP)
300 if (statxBuffer.stx_mode & S_IWGRP)
302 if (statxBuffer.stx_mode & S_IXGRP)
305 if (statxBuffer.stx_mode & S_IROTH)
307 if (statxBuffer.stx_mode & S_IWOTH)
309 if (statxBuffer.stx_mode & S_IXOTH)
313 if (S_ISLNK(statxBuffer.stx_mode))
315 if ((statxBuffer.stx_mode & S_IFMT) == S_IFREG)
317 else if ((statxBuffer.stx_mode & S_IFMT) == S_IFDIR)
319 else if ((statxBuffer.stx_mode & S_IFMT) != S_IFBLK)
324 if (statxBuffer.stx_nlink == 0)
326 size_ =
qint64(statxBuffer.stx_size);
330 accessTime_ = timespecToMSecs(statxBuffer.stx_atime);
331 metadataChangeTime_ = timespecToMSecs(statxBuffer.stx_ctime);
332 modificationTime_ = timespecToMSecs(statxBuffer.stx_mtime);
333 const bool birthMask = statxBuffer.stx_mask & STATX_BTIME;
334 birthTime_ = birthMask ? timespecToMSecs(statxBuffer.stx_btime) : 0;
336 userId_ = statxBuffer.stx_uid;
337 groupId_ = statxBuffer.stx_gid;
349inline void QFileSystemMetaData::fillFromStatxBuf(
const struct statx &)
359 struct statx statxBuffer;
362 if (
ret != -ENOSYS) {
364 data.fillFromStatxBuf(statxBuffer);
370 QT_STATBUF statBuffer;
372 if (QT_FSTAT(
fd, &statBuffer) == 0) {
373 data.fillFromStatBuf(statBuffer);
380#if defined(_DEXTRA_FIRST)
381static void fillStat64fromStat32(
struct stat64 *statBuf64,
const struct stat &statBuf32)
383 statBuf64->st_mode = statBuf32.st_mode;
384 statBuf64->st_size = statBuf32.st_size;
385#if _POSIX_VERSION >= 200809L
386 statBuf64->st_ctim = statBuf32.st_ctim;
387 statBuf64->st_mtim = statBuf32.st_mtim;
388 statBuf64->st_atim = statBuf32.st_atim;
390 statBuf64->st_ctime = statBuf32.st_ctime;
391 statBuf64->st_mtime = statBuf32.st_mtime;
392 statBuf64->st_atime = statBuf32.st_atime;
394 statBuf64->st_uid = statBuf32.st_uid;
395 statBuf64->st_gid = statBuf32.st_gid;
399void QFileSystemMetaData::fillFromStatBuf(
const QT_STATBUF &statBuffer)
402 if (statBuffer.st_mode & S_IRUSR)
404 if (statBuffer.st_mode & S_IWUSR)
406 if (statBuffer.st_mode & S_IXUSR)
409 if (statBuffer.st_mode & S_IRGRP)
411 if (statBuffer.st_mode & S_IWGRP)
413 if (statBuffer.st_mode & S_IXGRP)
416 if (statBuffer.st_mode & S_IROTH)
418 if (statBuffer.st_mode & S_IWOTH)
420 if (statBuffer.st_mode & S_IXOTH)
424 if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
426 else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
428 else if ((statBuffer.st_mode & S_IFMT) != S_IFBLK)
433 if (statBuffer.st_nlink == 0)
435 size_ = statBuffer.st_size;
437 if (statBuffer.st_flags & UF_HIDDEN) {
444 accessTime_ = GetFileTimes::atime(statBuffer, 0);
445 birthTime_ = GetFileTimes::birthtime(statBuffer, 0);
446 metadataChangeTime_ = GetFileTimes::ctime(statBuffer, 0);
447 modificationTime_ = GetFileTimes::mtime(statBuffer, 0);
449 userId_ = statBuffer.st_uid;
450 groupId_ = statBuffer.st_gid;
453void QFileSystemMetaData::fillFromDirEnt(
const QT_DIRENT &
entry)
455#if defined(_DEXTRA_FIRST)
458 for (dirent_extra *extra = _DEXTRA_FIRST(&
entry); _DEXTRA_VALID(extra, &
entry);
459 extra = _DEXTRA_NEXT(extra)) {
460 if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
462 const struct dirent_extra_stat *
const extra_stat =
463 reinterpret_cast<struct dirent_extra_stat *
>(extra);
466 if (extra->d_type == _DTYPE_LSTAT) {
468 if (S_ISLNK(extra_stat->d_stat.st_mode))
477 if (S_ISLNK(extra_stat->d_stat.st_mode) && extra->d_type == _DTYPE_LSTAT)
480#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
483 struct stat64 statBuf;
484 fillStat64fromStat32(&statBuf, extra_stat->d_stat);
485 fillFromStatBuf(statBuf);
487 fillFromStatBuf(extra_stat->d_stat);
490 if (!S_ISLNK(extra_stat->d_stat.st_mode)) {
496#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
500 switch (
entry.d_type)
581 if (
data.isDirectory() &&
s[0] !=
'/') {
585 if (!
ret.isEmpty() && !
ret.endsWith(u
'/'))
590 if (!
ret.startsWith(u
'/'))
593 if (
ret.size() > 1 &&
ret.endsWith(u
'/'))
597#if defined(Q_OS_DARWIN)
599 QCFString path = CFStringCreateWithFileSystemRepresentation(0,
604 QCFType<CFURLRef>
url = CFURLCreateWithFileSystemPath(0,
path, kCFURLPOSIXPathStyle,
609 QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0,
url, NULL);
613 QCFType<CFURLRef>
resolvedUrl = CFURLCreateByResolvingBookmarkData(0,
615 (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask
616 | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL);
645#if !defined(Q_OS_DARWIN) && !defined(Q_OS_QNX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_HAIKU) && _POSIX_VERSION < 200809L && !defined(Q_OS_VXWORKS)
650# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
655 std::nullptr_t stack_result =
nullptr;
657 auto resolved_path_deleter = [&](
char *
ptr) {
659# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || _POSIX_VERSION < 200801L
667 std::unique_ptr<char,
decltype (resolved_path_deleter)> resolved_name {
nullptr, resolved_path_deleter};
668# if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID)
677 resolved_name.reset(realpath(
entry.nativeFilePath().constData(), stack_result));
679 resolved_name.reset(realpath(
entry.nativeFilePath().constData(), stack_result));
686 }
else if (errno == ENOENT || errno == ENOTDIR) {
707 result = cur.nativeFilePath();
709 if (!orig.
isEmpty() && !(orig.
size() == 1 && orig[0] ==
'.')) {
717 const bool isDir =
result.endsWith(
'/');
726 stringVersion.append(u
'/');
735 QT_STATBUF statResult;
736 if (QT_STAT(
entry.nativeFilePath().constData(), &statResult)) {
750 QT_STATBUF statResult;
751 if (QT_FSTAT(
fd, &statResult)) {
764#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
765 long size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
768 QVarLengthArray<char, 1024>
buf(size_max);
771#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
772 struct passwd *pw =
nullptr;
773#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS)
775 getpwuid_r(userId, &
entry,
buf.data(),
buf.size(), &pw);
777 pw = getpwuid(userId);
790#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
791 long size_max = sysconf(_SC_GETPW_R_SIZE_MAX);
794 QVarLengthArray<char, 1024>
buf(size_max);
797#if !defined(Q_OS_INTEGRITY) && !defined(Q_OS_WASM)
798 struct group *gr =
nullptr;
799#if QT_CONFIG(thread) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD) && !defined(Q_OS_VXWORKS) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID) && (__ANDROID_API__ >= 24))
800 size_max = sysconf(_SC_GETGR_R_SIZE_MAX);
803 buf.resize(size_max);
811 if (!getgrgid_r(groupId, &
entry,
buf.data(),
buf.size(), &gr)
816 gr = getgrgid(groupId);
826#if defined(Q_OS_DARWIN)
830 QCFType<CFURLRef>
url = CFURLCreateWithFileSystemPath(0,
QCFString(
entry.filePath()),
831 kCFURLPOSIXPathStyle,
true);
832 if (QCFType<CFDictionaryRef> dict = CFBundleCopyInfoDictionaryForURL(
url)) {
833 if (CFTypeRef
name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
834 if (CFGetTypeID(
name) == CFStringGetTypeID())
835 return QString::fromCFString((CFStringRef)
name);
844 QFileSystemMetaData::MetaDataFlags what)
848#if defined(Q_OS_DARWIN)
867 data.entryFlags &= ~what;
886 QT_STATBUF statBuffer;
887 struct statx statxBuffer;
892 statResult =
qt_lstatx(nativeFilePath, &statxBuffer);
893 if (statResult == -ENOSYS) {
895 statResult = QT_LSTAT(nativeFilePath, &statBuffer);
897 mode = statBuffer.st_mode;
898 }
else if (statResult == 0) {
900 mode = statxBuffer.stx_mode;
903 if (statResult >= 0) {
911 data.fillFromStatxBuf(statxBuffer);
913 data.fillFromStatBuf(statBuffer);
929 if (entryErrno == 0 && statResult == -1) {
931 statResult =
qt_statx(nativeFilePath, &statxBuffer);
932 if (statResult == -ENOSYS) {
934 statResult = QT_STAT(nativeFilePath, &statBuffer);
936 data.fillFromStatBuf(statBuffer);
937 }
else if (statResult == 0) {
938 data.fillFromStatxBuf(statxBuffer);
942 if (statResult != 0) {
945 data.metadataChangeTime_ = 0;
946 data.modificationTime_ = 0;
947 data.accessTime_ = 0;
962 if (entryErrno != 0 || (what & flag) == 0)
964 if (QT_ACCESS(nativeFilePath,
mode) == 0) {
967 }
else if (errno != EACCES && errno != EROFS) {
978 if (QT_ACCESS(nativeFilePath, F_OK) == -1)
988#if defined(Q_OS_DARWIN)
990 if (entryErrno == 0 && hasResourcePropertyFlag(
data,
entry, kCFURLIsAliasFileKey)) {
999 if (entryErrno == 0 && isPackage(
data,
entry))
1007 && !
data.isHidden()) {
1010#
if defined(Q_OS_DARWIN)
1011 || (entryErrno == 0 && hasResourcePropertyFlag(
data,
entry, kCFURLIsHiddenKey))
1018 if (entryErrno != 0) {
1027bool QFileSystemEngine::cloneFile(
int srcfd,
int dstfd,
const QFileSystemMetaData &knownData)
1029 QT_STATBUF statBuffer;
1031 knownData.isFile()) {
1032 statBuffer.st_mode = S_IFREG;
1034 knownData.isDirectory()) {
1036 }
else if (QT_FSTAT(srcfd, &statBuffer) == -1) {
1038 }
else if (!S_ISREG((statBuffer.st_mode))) {
1043#if defined(Q_OS_LINUX)
1045 if (::ioctl(dstfd, FICLONE, srcfd) == 0)
1050 const size_t SendfileSize = 0x7ffff000;
1052 ssize_t
n = ::sendfile(dstfd, srcfd,
nullptr, SendfileSize);
1059 n = ::sendfile(dstfd, srcfd,
nullptr, SendfileSize);
1065 n = ftruncate(dstfd, 0);
1066 n = lseek(srcfd, 0, SEEK_SET);
1067 n = lseek(dstfd, 0, SEEK_SET);
1073#elif defined(Q_OS_DARWIN)
1075 return fcopyfile(srcfd, dstfd,
nullptr, COPYFILE_DATA | COPYFILE_STAT) == 0;
1085 bool shouldMkdirFirst =
true)
1090 const auto isDir = [](
const QByteArray &nativeName) {
1092 return QT_STAT(nativeName.constData(), &st) == 0 && (st.st_mode & S_IFMT) == S_IFDIR;
1095 if (shouldMkdirFirst && QT_MKDIR(nativeName,
mode) == 0)
1097 if (errno == EISDIR)
1099 if (errno == EEXIST)
1100 return isDir(nativeName);
1101 if (errno != ENOENT)
1105 qsizetype slash = nativeName.lastIndexOf(
'/');
1114 if (QT_MKDIR(nativeName,
mode) == 0)
1116 return errno == EEXIST && isDir(nativeName);
1121 std::optional<QFile::Permissions> permissions)
1131 mode_t
mode = permissions ? QtPrivate::toMode_t(*permissions) : 0777;
1132 if (QT_MKDIR(dirName,
mode) == 0)
1145 if (removeEmptyParents) {
1147 for (
qsizetype oldslash = 0, slash=dirName.
size(); slash > 0; oldslash = slash) {
1150 if (QT_STAT(chunk.
constData(), &st) != -1) {
1151 if ((st.st_mode & S_IFMT) != S_IFDIR)
1154 return oldslash != 0;
1171 if (::symlink(
source.nativeFilePath().constData(),
target.nativeFilePath().constData()) == 0)
1179#elif defined(QT_BOOTSTRAPPED) || !defined(AT_FDCWD)
1194struct FreeDesktopTrashOperation
1200 int filesDirFd = -1;
1208 int infoFileFd = -1;
1209 ~FreeDesktopTrashOperation()
1214 constexpr bool isTrashDirOpen()
const {
return filesDirFd != -1 && infoDirFd != -1; }
1218 int savedErrno = errno;
1219 if (infoFileFd != -1) {
1225 unlinkat(infoDirFd, infoFilePath, 0);
1228 if (!tempTrashFileName.isEmpty()) {
1230 unlinkat(filesDirFd, tempTrashFileName, 0);
1232 if (filesDirFd >= 0)
1236 filesDirFd = infoDirFd = -1;
1243 infoFileFd = qt_safe_openat(infoDirFd,
p, QT_OPEN_RDWR | QT_OPEN_CREAT | QT_OPEN_EXCL, 0666);
1244 if (infoFileFd < 0) {
1248 infoFilePath = std::move(
p);
1256 tempTrashFileName = {};
1260 static int openDirFd(
int dfd,
const char *
path,
int mode = 0)
1262 mode |= QT_OPEN_RDONLY | O_NOFOLLOW | O_DIRECTORY;
1263 return qt_safe_openat(dfd,
path,
mode);
1267 static int openOrCreateDir(
int dfd,
const char *
path)
1270 int fd = openDirFd(dfd,
path);
1271 if (
fd >= 0 || errno != ENOENT)
1275 if (mkdirat(dfd,
path, 0700) < 0)
1279 return openDirFd(dfd,
path);
1286 if (parentfd == AT_FDCWD)
1287 trashPath = targetDir;
1291 int trashfd = openOrCreateDir(parentfd, nativePath);
1292 if (trashfd < 0 && errno != ENOENT) {
1298 if (QT_STATBUF st; QT_FSTAT(trashfd, &st) < 0) {
1301 }
else if (st.st_uid != getuid()) {
1306 filesDirFd = openOrCreateDir(trashfd,
"files");
1307 if (filesDirFd >= 0) {
1310 for (
int i = 0;
i < 16; ++
i) {
1312 if (linkat(AT_FDCWD,
source.nativeFilePath(), filesDirFd, attempt, 0) == 0) {
1313 tempTrashFileName = std::move(attempt);
1316 if (errno != EEXIST)
1327 if (!tempTrashFileName.isEmpty() || errno == EPERM || errno == EMLINK)
1328 infoDirFd = openOrCreateDir(trashfd,
"info");
1334 return infoDirFd >= 0;
1351 const auto dotTrash =
"/.Trash"_L1;
1356 int genericTrashFd = openDirFd(AT_FDCWD, dotTrashDir.nativeFilePath());
1358 if (genericTrashFd < 0 && errno != ENOENT && errno != EACCES) {
1360 if (QT_LSTAT(dotTrashDir.nativeFilePath(), &st) == 0 && S_ISLNK(st.st_mode)) {
1362 qCritical(
"Warning: '%s' is a symlink to '%s'",
1363 dotTrashDir.nativeFilePath().constData(),
1367 }
else if (genericTrashFd >= 0) {
1368 QT_FSTAT(genericTrashFd, &st);
1369 if ((st.st_mode & S_ISVTX) == 0) {
1371 qCritical(
"Warning: '%s' doesn't have sticky bit set!",
1372 dotTrashDir.nativeFilePath().constData());
1384 if (getTrashDir(genericTrashFd, userID,
source,
error)) {
1386 trashPath = dotTrashDir.filePath() + u
'/' + userID;
1399 if (!isTrashDirOpen())
1400 getTrashDir(AT_FDCWD, sourceStorage.rootPath() + dotTrash + u
'-' + userID,
source,
error);
1402 if (isTrashDirOpen()) {
1403 volumePrefixLength = sourceStorage.rootPath().size();
1404 if (volumePrefixLength == 1)
1405 volumePrefixLength = 0;
1407 ++volumePrefixLength;
1409 return isTrashDirOpen();
1415 return getTrashDir(AT_FDCWD, topDir +
"/Trash"_L1,
source,
error);
1428 if (
error.errorCode != EXDEV)
1433 if (!sourceStorage.isValid())
1435 return openMountPointTrashLocation(
source, sourceStorage,
error);
1451 FreeDesktopTrashOperation op;
1452 if (!op.findTrashFor(sourcePath,
error))
1476 if (!op.tryCreateInfoFile(uniqueTrashedName,
error) &&
error.errorCode == EEXIST) {
1480 if (QT_STATBUF st;
Q_LIKELY(QT_STAT(
source.nativeFilePath(), &st) == 0)) {
1487 QString uniqueTrashBase = std::move(uniqueTrashedName);
1491 if (op.tryCreateInfoFile(uniqueTrashedName,
error))
1493 if (
error.errorCode != EEXIST)
1514 if (op.tempTrashFileName.isEmpty()) {
1521 renamed = renameat(AT_FDCWD,
source.nativeFilePath(), op.filesDirFd,
1524 renamed = renameat(op.filesDirFd, op.tempTrashFileName, op.filesDirFd,
1535 newLocation =
QFileSystemEntry(op.trashPath +
"/files/"_L1 + uniqueTrashedName);
1543#if defined(Q_OS_DARWIN)
1544 if (::clonefile(
source.nativeFilePath().constData(),
1545 target.nativeFilePath().constData(), 0) == 0)
1566#if defined(RENAME_NOREPLACE) && QT_CONFIG(renameat2)
1567 if (renameat2(AT_FDCWD,
srcPath, AT_FDCWD, tgtPath, RENAME_NOREPLACE) == 0)
1571 if (errno != EINVAL) {
1576#if defined(Q_OS_DARWIN) && defined(RENAME_EXCL)
1577 if (renameatx_np(AT_FDCWD,
srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
1579 if (errno != ENOTSUP) {
1592 int savedErrno = errno;
1621 if (::rename(
srcPath, tgtPath) == 0)
1635 if (::rename(
source.nativeFilePath().constData(),
target.nativeFilePath().constData()) == 0)
1645 if (unlink(
entry.nativeFilePath().constData()) == 0)
1657 mode_t
mode = QtPrivate::toMode_t(permissions);
1658 bool success = ::chmod(
entry.nativeFilePath().constData(),
mode) == 0;
1659 if (success &&
data) {
1672 mode_t
mode = QtPrivate::toMode_t(permissions);
1674 bool success = ::fchmod(
fd,
mode) == 0;
1675 if (success &&
data) {
1688 if (!newDate.isValid()
1694#if QT_CONFIG(futimens)
1696 struct timespec ts[2] = {{0, UTIME_OMIT}, {0, UTIME_OMIT}};
1700 const std::chrono::milliseconds msecs{newDate.toMSecsSinceEpoch()};
1704 if (futimens(
fd, ts) == -1) {
1732#ifdef QT_UNIX_TEMP_PATH_OVERRIDE
1733 return QT_UNIX_TEMP_PATH_OVERRIDE
""_L1;
1738#if defined(Q_OS_DARWIN) && !defined(QT_BOOTSTRAPPED)
1739 }
else if (NSString *nsPath = NSTemporaryDirectory()) {
1740 temp = QString::fromCFString((CFStringRef)nsPath);
1753 r = QT_CHDIR(
path.nativeFilePath().constData());
1760#if defined(__GLIBC__) && !defined(PATH_MAX)
1761 char *currentName = ::get_current_dir_name();
1764 ::free(currentName);
1768 if (::getcwd(currentName,
PATH_MAX)) {
1769#if defined(Q_OS_VXWORKS) && defined(VXWORKS_VXSIM)
1778# if defined(QT_DEBUG)
1780 qWarning(
"QFileSystemEngine::currentPath: getcwd() failed");
bool endsWith(char c) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
QByteArray left(qsizetype n) const &
void chop(qsizetype n)
Removes n bytes from the end of the byte array.
bool startsWith(QByteArrayView bv) const
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
\inmodule QtCore\reentrant
static QDateTime currentDateTime()
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool cdUp()
Changes directory by moving one directory up from the QDir's current directory.
QString path() const
Returns the path.
QString canonicalPath() const
Returns the canonical path, i.e.
static QChar separator()
Returns the native directory separator: "/" under Unix and "\\" under Windows.
static QString cleanPath(const QString &path)
Returns path with directory separators normalized (that is, platform-native separators converted to "...
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
static QByteArray id(const QFileSystemEntry &entry)
static bool setCurrentPath(const QFileSystemEntry &entry)
static bool moveFileToTrash(const QFileSystemEntry &source, QFileSystemEntry &newLocation, QSystemError &error)
static QFileSystemEntry getRawLinkPath(const QFileSystemEntry &link, QFileSystemMetaData &data)
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
static bool renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
static QString rootPath()
static bool createDirectory(const QFileSystemEntry &entry, bool createParents, std::optional< QFile::Permissions > permissions=std::nullopt)
static QString bundleName(const QFileSystemEntry &)
static bool createLink(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data=nullptr)
static QString homePath()
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
static QFileSystemEntry absoluteName(const QFileSystemEntry &entry)
static QString tempPath()
static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate, QFile::FileTime whatTime, QSystemError &error)
static QString resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
static QString resolveGroupName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error)
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
static QFileSystemEntry currentPath()
Q_AUTOTEST_EXPORT NativePath nativeFilePath() const
Q_AUTOTEST_EXPORT QString filePath() const
Q_AUTOTEST_EXPORT QString fileName() const
static QByteArray encodeName(const QString &fileName)
Converts fileName to an 8-bit encoding that you can use in native APIs.
static QString decodeName(const QByteArray &localFileName)
This does the reverse of QFile::encodeName() using localFileName.
static QString writableLocation(StandardLocation type)
\macro QT_RESTRICTED_CAST_FROM_ASCII
QString left(qsizetype n) const &
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
qsizetype lastIndexOf(QChar c, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
const QChar * constData() const
Returns a pointer to the data stored in the QString.
qsizetype size() const noexcept
Returns the number of characters in this string.
static QString number(int, int base=10)
This is an overloaded member function, provided for convenience. It differs from the above function o...
QString & remove(qsizetype i, qsizetype len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
static QString static QString asprintf(const char *format,...) Q_ATTRIBUTE_FORMAT_PRINTF(1
qsizetype length() const noexcept
Returns the number of characters in this string.
static QByteArray toPercentEncoding(const QString &, const QByteArray &exclude=QByteArray(), const QByteArray &include=QByteArray())
Returns an encoded copy of input.
void qErrnoWarning(const char *msg,...)
Combined button and popup list for selecting options.
Q_CORE_EXPORT char * qstrncpy(char *dst, const char *src, size_t len)
QByteArray qt_readlink(const char *path)
timespec durationToTimespec(std::chrono::nanoseconds timeout) noexcept
DBusConnection const char DBusError * error
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_CHECK_FILE_NAME(name, result)
static int qt_lstatx(const char *, struct statx *)
static int qt_fstatx(int, struct statx *)
static bool createDirectoryWithParents(const QByteArray &nativeName, mode_t mode, bool shouldMkdirFirst=true)
static int qt_statx(const char *, struct statx *)
static ControlElement< T > * ptr(QWidget *widget)
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLint GLint GLint GLsizei GLsizei GLsizei GLboolean commit
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLuint GLenum GLsizei const GLchar * buf
GLint GLint GLint GLint GLint GLint GLint GLbitfield mask
GLsizei GLsizei GLchar * source
GLsizei const GLchar *const * path
static QUrl resolvedUrl(const QUrl &url, const QQmlRefPointer< QQmlContextData > &context)
static QString canonicalPath(const QString &rootPath)
#define qUtf16Printable(string)
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
unsigned long long quint64
QUrl url("example.com")
[constructor-url-reference]
QItemEditorCreatorBase * creator