209 Commits

Author SHA1 Message Date
Thiago Macieira
db34e27f7f Replace qgetenv() calls converted to QString with qEnvironmentVariable()
It's slightly more efficient.

Pick-to: 6.9
Change-Id: Id5ac04fc27eee108c8e5fffd786c3d5f793a0a9d
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2025-01-01 14:23:05 -03:00
Ahmad Samir
b6ab002b3b QFileSystemEngine: remove QFSMetaData* parameter from setPermissions()
Nothing passes a QFileSystemMetaData* to any of those methods.

Add QFileSystemMetaData::setPermissions(), which contains the code that
used to be in QFileSystemEngine::setPermissions(); callers can use it
directly to set the permissions on a QFileSystemMetaData object, after
the QFileSystemEngine::setPermissions() call succeeds.

Change-Id: I9f3415e969680f3b7039a7a8982032349e0133e1
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
2024-11-13 08:12:00 +03:00
Jarno Lämsä
039b0c6b9b Don't support moving files to trash on VxWorks
On VxWorks 24.03, the `AT_FDCWD` wasn't defined, which happened to
branch to the correct branch. VxWorsk 24.09 TP does define the
`AT_FDCWD`, which causes the preprocessor directives to branch to a
branch where moving files to trash would be supported.

In a sidenote, VxWorks doesn't define `renameat`, `O_DIRECTORY` nor
`O_NOFOLLOW`.

Task-number: QTBUG-130629
Pick-to: 6.8
Change-Id: I2b850813aeff6f925ab91932efd7aeb13f753f69
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-11-08 15:45:05 +02:00
Michał Łoś
2cf12a6bae Fix directory permissions not set correctly on VxWorks
In commit e275db9d885ccccc3def4d52c2dae2f8c062df1a, changes were made to
handling directory creation in qfilesystem_unix.cpp. These changes
missed VxWorks-specific case where its system `mkdir` function treats
permissions of `000` as `default permissions`. This is causing failure
of `tst_QDir::mkdirWithPermissions(0000)` test.

To fix this, use `forceRequestedPermissionsOnVxWorks` function for
VxWorks in `QFileSystemEngine::mkdir`.

Fixes: QTBUG-130737
Task-number: QTBUG-115777
Change-Id: I16fc36448693050c7c92096d804a1caeb7e65115
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-11-05 19:53:02 +01:00
Jari Helaakoski
3ee98d6adf Fix -no-feature-datestring and -no-feature-xmlstreamreader
Task-number: QTBUG-112830
Change-Id: I25dad19dee98d64eb5c226cbcc2b628f2a371ea4
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-28 11:48:28 +03:00
Ahmad Samir
e275db9d88 QFileSystemEngine: split dir creation into mkdir/mkpath
Split the logic of createDirectory() into mkdir and mkpath.
This matches QDir::mkdir()/mkpath().

"mkdir()" won't confuse the compiler about which method to call,
because libc's mkdir() is either used via QT_MKDIR which expands to
"::mkdir" or directly as ::mdkir(), whereas the static
QFileSystemEngine::mkdir() is always called with full scope.

Change-Id: I31b67727cce23f1bc560432d40231a24dc560d5b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-25 22:52:38 +03:00
Ahmad Samir
42bde675de QFileSystemEngine/Unix: refactor rmpath()
Convert the path to QByteArray once up top, instead of using
QFile::encodeName() multiple times in the for-loop, and then use the
same QByteArray and truncate() it in each iteration.

Extend tst_qdir unittests.

Change-Id: I0d879e7f429db25879859acab074c2c197f41f6c
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-10 19:03:43 +03:00
Ahmad Samir
ead72a1155 QFileSystemEngine: add rmpath()
removeDirectory() acts in two mode, rmdir (one entry) and rmpath (the
entry and all empty parent directories). This is irregular behavior, and
API with a very specific use-case (in unittests, where you create a dir
tree and want to cleanup after the test finishes).

So, split the code into rmdir() and rmpath(), which matches
QDir::rmdir() and QDir::rmpath().

On Unix, a further optimization pointed out by Thiago in review, remove
the stat() call, ::rmdir() will fail with ENOTDIR if we try to remove
anything that isn't a dir.

Change-Id: I1bbb6e6c1ce49ba6d73d3c510b449223498612fb
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-10 03:10:24 +03:00
Tor Arne Vestbø
3d08816f4c Darwin: Teach QFileSystemEngine how to resolve case-sensitivity
Both APFS and HFS+ can be both case-sensitive and case-insensitive
(the default), and the mounted file system may be any other file
system than these two as well, so hard-coding to case-sensitive
is not sufficient.

Pick-to: 6.8
Task-number: QTBUG-28246
Task-number: QTBUG-31103
Change-Id: Ibdb902df3f169b016a519f67ad5a79e6afb6aae3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-10-02 11:41:14 +00:00
Thiago Macieira
3b9f5c82f5 QFileSystemEngine/Unix: implement getting the size of block devices
Implemented for Linux, macOS, and FreeBSD. This works only on open files
because of the need to ioctl().

Before:
"/dev/system/stuff2" : 0

After:
"/dev/system/stuff2" : 68719476736              [Linux]
"/dev/ada1" : 42949672960                       [FreeBSD]
"/dev/disk0" : 500277792768                     [macOS]
"/dev/disk2" : 39306240                         [macOS]

With:
    if (f.open(QIODevice::ReadOnly | QIODevice::Unbuffered))
        qDebug() << f.fileName() << ':' << f.size();

[ChangeLog][QtCore][QFile] For open block devices on Unix systems,
size() now returns the size of the underlying device. Previously, it
would always return 0.

Change-Id: I8a96935cf6c742259c9dfffd17e9402bdbd6b963
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
2024-09-25 11:15:32 -07:00
Even Oscar Andersen
0568511e84 wasm: Make sure QDir::mkpath("/") works on webassembly
As described in bug QTBUG-127767 mkdir("/") returns ENOSPC
on webassembly, and the code is not prepared to handle that.
We solve it by explicitly checking for "/" which shall
always be present.

Fixes: QTBUG-127767
Change-Id: Icf86f0b681ac3bd8ddc97c1a4168c2faf02aa4a1
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-09-25 20:15:31 +02:00
Thiago Macieira
c41b6b7986 QFile::moveFileToTrash: explicitly disable Android support
This code has been enabled but didn't work: we kept getting permission
errors on use. So let's save some library size.

Pick-to: 6.8
Change-Id: Ifb754f0e28774c20aa7cfffd17e7549e7624e42a
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2024-08-07 18:35:48 -07:00
Thiago Macieira
17d1d577c9 QFile: add supportsMoveToTrash()
[ChangeLog][QtCore][QFile] Added supportsMoveToTrash() to check if Qt
supports moving files to trash in the current OS.

Fixes: QTBUG-127580
Change-Id: Ifb754f0e28774c20aa7cfffd17e6c951ffd9d9ff
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2024-08-08 01:35:47 +00:00
Thiago Macieira
31cf699e69 QFileSystemEngine::canonicalName: skip QDir::cleanPath()
realpath() is supposed to return the canonicalized absolute path, so
there should be nothing left to clean.

Pick-to: 6.8
Change-Id: Ie30a3caf09ef4176bb36fffd17cde30c7538dba9
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2024-07-10 05:55:19 -07:00
Thiago Macieira
3302b0cdc1 QFile::moveToTrash/Unix: ensure we try to remove the proper source
We already had code to strip ending slashes, which makes sense if trying
to trash directories. In the case of symlinks to directories, that also
changes from trashing the directory to trashing the symlink. But had to
removeFile() on the same modified path.

Fixes: QTBUG-126621
Pick-to: 6.7 6.8
Change-Id: I46feca3a447244a8ba19fffd17dc0b56f2b1c68c
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2024-06-25 08:12:39 -07:00
Łukasz Matysiak
90e79aea8e Force requested permissions when calling mkdir on VxWorks
Calling mkdir with mode == 0 works just fine on Linux - it creates a
directory and the permissions are set to 0.
On VxWorks, calling mkdir with mode == 0 uses the default mode set in
the system.
This leads to a failing test (tst_QDir::mkdirWithPermissions(0000)) and
potential confusion when the same code does not behave in the same way
when called on Linux and VxWorks.

To keep the same interface between unix-like systems, explicitly set the
permissions to 0 when on VxWorks.

Pick-to: 6.7 6.8
Task-number: QTBUG-115777
Change-Id: I75e429c086500cb7c19f9bb14693bb4266e18046
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Michał Łoś <michal.los@siili.com>
2024-06-18 17:55:33 +02:00
Łukasz Matysiak
8915ae3a75 Make createDirectoryWithParents return true for existing dirs on read only fs
When the filesystem is mounted in a read only mode, Linux returns true
on an attempt to create a dir that already exists on that fs.
However not every platform behaves that way.

VxWorks is not a fully unix-like system.
It is possible to enable a component that provides a virtual root file
system (VRFS) so that devices and paths can be managed using "/" as a root.
The root itself is not an actual path that can be used like on other systems.
It is not possible to store files directly in "/".

On Linux, mkdir on "/" returns EEXIST.
On VxWorks, it returns EROFS (read only file system).

That leads to a failing test (tst_QDir::makedirReturnCode).
It also leads to a broken contract, since the doc for QDir::mkpath states that:
`If the path already exists when this function is called, it will return
true.`
The doc for createDirectoryWithParents has no such comment and it is
used by other functions that also do not promise such things, but the
implementation behaves that way anyway: when errno == EEXIST -> return
true if the target path is an existing directory.

Since the existing unix implementation already returns true for existing dirs
(without checking if it was called in the context of `mkpath` or any other
function), fix the problem by checking if errno == EROFS after a call
to mkdir and then checking if the target path already exists and is a directory

Pick-to: 6.7 6.8
Task-number: QTBUG-115777
Change-Id: I849bca56618bf675933cccc5a9d5313e0014628b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Karim Pinter <karim.pinter@qt.io>
Reviewed-by: Jarno Lämsä <jarno.lamsa@qt.io>
2024-06-16 23:56:59 +02:00
Thiago Macieira
e32009fc0d QFileSystemEngine::canonicalName: don't use malloc()'ing realpath()
It is available in POSIX.1-2008 but is not worth it. The Linux man page
says it only works up to PATH_MAX anyway and the POSIX documentation
says it's UB if PATH_MAX isn't defined.

This cleans up the source code out of these messy #if and should be
faster, because we avoid a heap allocation (stack is always faster).

Instead, we only relegate the heap version to the case where PATH_MAX
isn't defined (i.e., GNU HURD), because in that case the realpath()
function can't be used with a stack allocation.

Pick-to: 6.7
Change-Id: Ie30a3caf09ef4176bb36fffd17cde1ed5c5dad59
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2024-05-24 21:34:27 +00:00
Łukasz Matysiak
f097cbd9bf Make QFileSystemEngine::canonicalName use the realpath function on VxWorks
Despite realpath being available on VxWorks (when the INCLUDE_IO_REALPATH
component is used in the VIP), canonicalName doesn't use it, because
the system reports _POSIX_VERSION as 200112.

Fix the problem by adding an additional condition so that VxWorks
correctly uses realpath.

Pick-to: 6.7
Task-number: QTBUG-115777
Change-Id: I734f525e870f93a7ec955d379dcc2137b591e171
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-05-10 10:15:42 +02:00
Ahmad Samir
fd295f4bf6 QAbstractFileEngine: remove member FileTime and use QFile::FileTime
This is probably a remnant from when QAbstractFileEngine was public API
since it's been changed to private API, just use QFile::FileTime.

Pick-to: 6.7
Change-Id: I60d3d4ff811f95434b81d5ca115f5d43cfff8b15
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-03-21 19:05:02 +02:00
Tor Arne Vestbø
2a2a301557 Apple: Fix a few deprecation warnings after bumping deployment targets
- kIOMasterPortDefault -> kIOMainPortDefault
 - Use UTType instead of Carbon Core functions/constants
 - NSWorkspace iconForFileType -> iconForContentType
 - Removed obsoleted kUTTypeInkText pasteboard type

There are still a few more, but these will be fixed in follow ups.

Change-Id: Ibbca226d578b4ba64bd9c8c5d0addc1870114a20
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
2024-02-19 18:03:11 +01:00
Krzysztof Sommerfeld
21196d26d8 Make use of methods defined in utils unix layer
Some unix-like concepts are supported by VxWorks VSB layer - UTILS_UNIX.
One of such methods is getgrgid(). Include it in
`qfilesystemengine_unix.cpp`, so that we don't need to exclude VxWorks from code that uses it anymore.

Task-number: QTBUG-115777
Change-Id: I72b301647bfdb208cb6859bb0f9994e3537fc345
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-02-06 15:23:42 +00:00
Ahmad Samir
6d9185c0e6 QFileSystemEngine: use nativeFilePath()
Instead of filePath() then converting to QByteArray.

Change-Id: I6f656774979bedde5c657613303518750ab06855
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-02-01 23:42:56 +02:00
Marcin Zdunek
1d4ab5c135 Remove qfunctions_vxworks files and usage as it is no longer needed
Task-number: QTBUG-115777
Change-Id: I0d803ac7ce067737b79a39a267a2b0eb509ae0b8
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2024-01-25 12:21:41 +01:00
Thiago Macieira
d5393a936d moveToTrash/Unix: use linkat() to check early for cross-device renames
This ensures that we will succeed in renaming files, because we already
have created a link to it in the right directory. With this, we can
remove the home filesystem check that was using QStorageInfo. The
majority of file deletions we expect applications to perform will use
this code path.

An additional benefit is that we ensure we can't get an ENOSPC when
renaming any more, because we already have the entry in the directory.

This needs a fallback to the existing mechanism for two cases:
* trashing full directories, because you can't hardlink them
* when operating on a volume that isn't a Unix filesystem (e.g., a FAT
  filesystem on a removable device)

QTemporaryFileName required a small change to allow non-absolute paths.

openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
newfstatat(5, "", {st_mode=S_IFDIR|0700, st_size=18, ...}, AT_EMPTY_PATH) = 0
getuid()                                = 1000
openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
linkat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.MuahmK", 6, ".eRPdPI", 0) = 0
openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 7
close(5)                                = 0
openat(7, "tst_qfile.moveToTrashOpenFile.MuahmK.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 5
[../etc/localtime..]
write(5, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103
renameat(6, ".eRPdPI", 6, "tst_qfile.moveToTrashOpenFile.MuahmK") = 0
unlink("/home/tjmaciei/tst_qfile.moveToTrashOpenFile.MuahmK") = 0
close(5)                                = 0
close(6)                                = 0
close(7)                                = 0

Change-Id: I9d43e5b91eb142d6945cfffd1786d714fc24f161
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-10-26 11:36:46 -07:00
Thiago Macieira
c94bed69b7 moveToTrash/Unix: refactor to use openat()/mkdirat()/renameat()
This ensures much better security against race conditions and attacks,
at the expense of a few more system calls.

On first run (when no trash dir is yet present):

  openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)
  mkdirat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", 0700) = 0
  openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
  newfstatat(5, "", {st_mode=S_IFDIR|0700, st_size=0, ...}, AT_EMPTY_PATH) = 0
  getuid()                                = 1000
  openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)
  mkdirat(5, "files", 0700)               = 0
  openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
  openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = -1 ENOENT (No such file or directory)
  mkdirat(5, "info", 0700)                = 0
  openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 7
  close(5)                                = 0
  openat(7, "tst_qfile.moveToTrashOpenFile.fjYRxv.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 5
  openat(AT_FDCWD, "/usr/share/zoneinfo/UTC", O_RDONLY|O_CLOEXEC) = 8
  newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
  newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
  read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114
  lseek(8, -60, SEEK_CUR)                 = 54
  read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60
  close(8)                                = 0
  write(5, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103
  renameat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.fjYRxv", 6, "tst_qfile.moveToTrashOpenFile.fjYRxv") = 0
  close(5)                                = 0
  close(6)                                = 0
  close(7)                                = 0

On subsequent runs:

  openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 5
  newfstatat(5, "", {st_mode=S_IFDIR|0700, st_size=18, ...}, AT_EMPTY_PATH) = 0
  getuid()                                = 1000
  openat(5, "files", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 6
  openat(5, "info", O_RDONLY|O_NOFOLLOW|O_CLOEXEC|O_DIRECTORY) = 7
  close(5)                                = 0
  openat(7, "tst_qfile.moveToTrashOpenFile.sPjrcA.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 5
  openat(AT_FDCWD, "/usr/share/zoneinfo/UTC", O_RDONLY|O_CLOEXEC) = 8
  newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
  newfstatat(8, "", {st_mode=S_IFREG|0644, st_size=114, ...}, AT_EMPTY_PATH) = 0
  read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 114
  lseek(8, -60, SEEK_CUR)                 = 54
  read(8, "TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 60
  close(8)                                = 0
  write(5, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103
  renameat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.sPjrcA", 6, "tst_qfile.moveToTrashOpenFile.sPjrcA") = 0
  close(5)                                = 0
  close(6)                                = 0
  close(7)                                = 0

Change-Id: I9d43e5b91eb142d6945cfffd1787117927650dab
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2023-10-17 19:08:25 -07:00
Thiago Macieira
25b1990784 moveToTrash/Unix: use the file's inode number as collision avoidance
Instead of a sequential and thus predictable counter. This improves the
performance of when you keep creating and trashing the same file base
name. The previous algorithm would try all occurrences from 0 to however
many trashings have happened.

This could have been any random number, but the source file's inode is
"random" enough for us.

strace of the second file's trashing:

openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/info/tst_qfile.moveToTrashOpenFile.vLwfNe.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = -1 EEXIST (File exists)
newfstatat(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.vLwfNe", {st_mode=S_IFREG|0644, st_size=16, ...}, 0) = 0
openat(AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/info/tst_qfile.moveToTrashOpenFile.vLwfNe-23527891.trashinfo", O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, 0666) = 4
newfstatat(AT_FDCWD, "/etc/localtime", {st_mode=S_IFREG|0644, st_size=2852, ...}, 0) = 0
write(4, "[Trash Info]\nPath=/home/tjmaciei"..., 103) = 103
renameat2(AT_FDCWD, "/home/tjmaciei/tst_qfile.moveToTrashOpenFile.vLwfNe", AT_FDCWD, "/home/tjmaciei/.qttest/share/Trash/files/tst_qfile.moveToTrashOpenFile.vLwfNe-23527891", RENAME_NOREPLACE) = 0
close(4)                                = 0

Change-Id: I9d43e5b91eb142d6945cfffd1786d73459c2eb3d
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-10-17 19:08:25 -07:00
Thiago Macieira
77c661b275 moveToTrash/Unix: use lower-level API to write the info file
So we can more easily get any errors from attempting to write the file.
It is possible to get them with QFile, by either doing .flush() or using
QIODevice::Unbuffered, but using the C API is a definite sure way. Plus,
since this is QFileSystemEngine, this avoids the possibility that QFile
may choose to use a different file engine than the native one, for some
reason. And it reduces overhead.

This allows us to more easily detect why the file creation failed and
therefore stop looping if the error wasn't EEXIST. That will avoid an
infinite loop in case the necessary directories exist but aren't
writable.

It's also moved above the renaming, such that the failure to populate
the info file prevents the renaming too. Both operations can have the
same likely errors, ENOSPC and EIO. The likelihood of EIO is very low,
for both; but for ENOSPC it's far more likely for writing the
file. Avoiding the ENOSPC error for the renaming is handled in a later
commit.

Change-Id: I9d43e5b91eb142d6945cfffd1786d417142ac728
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2023-10-17 19:08:25 -07:00
Thiago Macieira
6359e8b8bd moveToTrash/Unix: avoid creating too many QStorageInfo
QStorageInfo is great, but rather expensive, so this introduces a faster
check by stat()ing the source file and $HOME, to see if they are the
same device, saving us two or three QStorageInfo constructions. That is
a necessary condition: if they aren't the same device, we know rename()
into $HOME/.local/share/Trash will fail.

But it's not a sufficient condition: they need to be the same mount
point and that's something only QStorageInfo will give us. Strictly
speaking, the only way to be sure that you can rename() into the trash
path is to, well, attempt it (as usual, something for a later commit).

Change-Id: I9d43e5b91eb142d6945cfffd1786c474cac25083
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2023-10-17 19:08:25 -07:00
Thiago Macieira
de24134aa7 moveToTrash/Unix: avoid TOCTOU in creating the unique file name
This is not a security issue because we still use QIODevice::NewOnly
(O_EXCL) and loop again. But because we do so, we don't need to check
for existence with QFile::exists() in the first place.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786c98a39781517
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
2023-10-17 19:08:25 -07:00
Thiago Macieira
1c5575f194 moveToTrash/Unix: trust freeDesktopTrashLocation() to find the directory
Make it receive the QSystemError so it can set the error condition
properly in case the suitable location for this input file can't be
found. This also includes the case when the input file does not exist in
the first place, which I moved into the function because upcoming
commits will imply this check anyway.

Change-Id: I9d43e5b91eb142d6945cfffd1786c6e59d3b0204
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-10-17 19:08:24 -07:00
Thiago Macieira
61d99530c8 moveToTrash/Unix: avoid QFileInfo to get an absolute file name
We know what engine we're using, so don't go the long way around via
QFileInfo and QFSFileEngine to get back to QFileSystemEngine in order to
calculate an absolute and clean path.

Since we're doing that, we may as well use QFileSystemEntry's ability to
give us the file name portion of this absolute path without having to go
via QFileInfo and QDir again. We just need to make sure that a dir name
isn't ending in a slash: absoluteName() would remove that for us, but
only if the entry isn't already absolute and clean.

Change-Id: I9d43e5b91eb142d6945cfffd17871389d359e750
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-10-06 18:43:30 -07:00
Thiago Macieira
fa97531952 moveToTrash/Unix: reorganize the #ifdef
Change-Id: I9d43e5b91eb142d6945cfffd178708f58b71e7ef
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-10-06 18:43:29 -07:00
Thiago Macieira
36a169e31e moveToTrash/Unix: use lstat() to confirm $root/.Trash is suitable
We can't use QFileSystemEngine::fillMetaData() because there's no bit in
QFileSystemMetaData to indicate the sticky flag, so we must make a at
least one stat() or lstat() call ourselves. Given that we need to know
if $root/.Trash is a symlink, that system call must be lstat(). And it
turns out that system call provides everything we need to confirm its
suitability.

This avoids QDir overhead just to manipulate strings.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786c5e54199ecb2
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-23 16:16:09 -07:00
Thiago Macieira
3d027f8d95 moveToTrash/Unix: remove unnecessary targetPath variable
It was used twice, in both cases to create a QFileSystemEntry, so the
two results were equal. Therefore, just use the first result to create
the second.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786d45d20485f40
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-23 08:18:31 -07:00
Thiago Macieira
6434b6ea48 moveToTrash/Unix: rename 'infoPath' variable to 'pathForInfo'
We have other variables whose name start with 'info' in this function,
so infoPath is misleading: it's not the path to infoFile and it isn't
related to the infoFileName. Instead, it's the path to the file being
trashed which will be saved in the info file.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786d358a0e02dfd
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-23 08:18:30 -07:00
Thiago Macieira
6e4d9ff74d moveToTrash/Unix: use Qt::ISODate to format the current date
Instead of forcing QDateTime to parse our pattern.

Pick-to: 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786d094a123826a
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-23 08:18:23 -07:00
Thiago Macieira
a71f556830 moveToTrash/Unix: avoid mkdir/chmod race condition for the trash dir
QDir::mkdir() followed by QFile::setPermissions() is a race condition
because an attacker could enter the directory before we set the
permissions. QDir::mkdir() got an overload with the permissions in 6.3,
but I decided to go a level lower and use QFileSystemEngine directly
here.

Pick-to: 6.5 6.6
Change-Id: I9d43e5b91eb142d6945cfffd1786c338e21c129e
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2023-09-23 08:18:22 -07:00
Jacek Poplawski
43480998ef Fix compilation of qfilesystemengine on VxWorks
Change-Id: I533f262bf6624008d216d96aa29ae2dfc4ba9195
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-07-27 20:13:55 +02:00
Edward Welbourne
db5279825c Corelib: s/Q_OS_MAC/Q_OS_DARWIN/wg except for doc and definition
I got tired of being told off by the inanity 'bot for faithfully
reflecting existing #if-ery in new #if-ery. Retain only the
documentation and definition of the deprecated define.

Change-Id: I47f47b76bd239a360f27ae5afe593dfad8746538
Reviewed-by: Ahmad Samir <a.samirh78@gmail.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
2023-03-20 19:18:52 +01:00
Ahmad Samir
8a1eb24de8 Misc: Fix qsizetype-related narrowing coversions
Task-number: QTBUG-102461
Change-Id: I96757abc50fc45756bc1271a970f819a48021663
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-03-11 12:39:47 +02:00
Ahmad Samir
dda60cf0d1 sysconf() system function returns long
Change-Id: Ia7218c1cc0e8ec55822aee55d7643d6df48efa8b
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-03-11 12:39:41 +02:00
Ahmad Samir
683ddddc6a q_core_unix: move timspec<->chrono helpers from qtools_p.h
Where it has a home with its other timespec/chrono siblings.

Luckily I only needed to change one place in the code, and that source
file already has #include's q_core_unix_p.h.

Change-Id: I783383f958ceccfd6f9210f0b76d35b0f82b7cb5
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-02-25 23:11:54 +02:00
Ahmad Samir
dd82f39910 QtMiscUtils: add std::chrono::duration <-> timespec helpers
Change-Id: I91f36a3d651fd57443072fde4c3e8f811682328e
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-02-20 21:28:38 +02:00
Jonas Kvinge
314a4d121f QFileSystemEngine: URL encode path in trash info, use relative path
According to the specifications, the path in .trashinfo should be URL
encoded.

The path can be relative when possible, otherwise changing the
mountpoint will break restoring files from trash.
But don't do that for root (/) and home.

For more info, see.:
https://specifications.freedesktop.org/trash-spec/trashspec-1.0.html

Pick-to: 6.5 5.15
Change-Id: Id8271a893a007f4cb5c10611f2b1bc71c1ff4860
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-01-02 17:39:37 +01:00
Wang Fei
936cae6b53 Add QFileInfo::readSymLink() to read the raw link path
The existing symLinkTarget() always resolves the symlink target to an
absolute path; readSymLink() provides access to the relative path when
that is how the symlink references its target.

[ChangeLog][QtCore][QFileInfo] Added readSymLink() to read the symlink's
raw target, without resolving to an absolute path.

Fixes: QTBUG-96761
Change-Id: I360e55f1a3bdb00e2966229ea8de78cf29a29417
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2022-12-23 06:26:44 +01:00
Ahmad Samir
7566c7381d QFileSystemEngine/Unix: use chrono for time related arithmetic
Change-Id: I1647c6ab44ec5c3569411cca88738746e44cc4b2
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2022-12-15 12:44:26 +02:00
Ahmad Samir
cb9d76169a QFileSystemEngine/Unix: remove futimes related code
- futimes isn't a standard system call[1]:
«
This system call is nonstandard.  It was implemented from a specification
that was proposed for POSIX.1, but that specification was replaced by the
one for utimensat(2).

A similar system call exists on Solaris.
»
[1] https://man7.org/linux/man-pages/man2/futimesat.2.html
[2] https://pubs.opengroup.org/onlinepubs/9699919799/functions/futimens.html

- futimens is a standard system call[2], it's available on:
 - Linux: https://man7.org/linux/man-pages/man2/futimesat.2.html
 - FreeBSD: https://www.freebsd.org/cgi/man.cgi?query=futimens&sektion=2&n=1
 - OpenBSD: https://man.openbsd.org/futimens.2
 - QNX: https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/futimens.html

So, remove futimes related code.

Change-Id: I58ac466f08161a88219e3a32eab98d168f065140
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2022-11-09 14:22:29 +02:00
Marc Mutz
df9d882d41 Port from container.count()/length() to size()
This is semantic patch using ClangTidyTransformator:

  auto QtContainerClass = expr(hasType(namedDecl(hasAnyName(<classes>)))).bind(o)
  makeRule(cxxMemberCallExpr(on(QtContainerClass),
                             callee(cxxMethodDecl(hasAnyName({"count", "length"),
                                                  parameterCountIs(0))))),
           changeTo(cat(access(o, cat("size"), "()"))),
           cat("use 'size()' instead of 'count()/length()'"))

a.k.a qt-port-to-std-compatible-api with config Scope: 'Container'.

<classes> are:

    // sequential:
    "QByteArray",
    "QList",
    "QQueue",
    "QStack",
    "QString",
    "QVarLengthArray",
    "QVector",
    // associative:
    "QHash",
    "QMultiHash",
    "QMap",
    "QMultiMap",
    "QSet",
    // Qt has no QMultiSet

Change-Id: Ibe8837be96e8d30d1846881ecd65180c1bc459af
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2022-10-04 07:40:08 +02:00
Lucie Gérard
05fc3aef53 Use SPDX license identifiers
Replace the current license disclaimer in files by
a SPDX-License-Identifier.
Files that have to be modified by hand are modified.
License files are organized under LICENSES directory.

Task-number: QTBUG-67283
Change-Id: Id880c92784c40f3bbde861c0d93f58151c18b9f1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Reviewed-by: Jörg Bornemann <joerg.bornemann@qt.io>
2022-05-16 16:37:38 +02:00