When building with newer GLib with GLIB_VERSION_MAX_ALLOWED set
to < 2.76 in downstream, g_clear_fd is marked deprecated in
libglnx and triggers deprecation warnings at each call site.
This forwards to g_clear_fd while silencing deprecation warnings for
Glib >= 2.76
Fixes: https://gitlab.gnome.org/GNOME/libglnx/-/issues/7
We document glnx_close_fd as preserving errno, so let's assert that it
really does. There are three code paths we need to exercise:
1. fd < 0: glnx_close_fd does nothing, successfully
2. fd >= 0 and close() succeeds
3. fd >= 0 and close() fails
The first two are easy, but it's difficult to make close() fail on-demand
with only valid code. close(2) documents EIO, but it's difficult to
cause an I/O error on-demand. Similarly, close(2) documents ENOSPC
and EDQUOT on NFS, but we are unlikely to have a full NFS filesystem
available during testing.
Instead, we can trigger a failure via the programming error of passing a
fd to glnx_close_fd that was already closed, which makes close(2) fail
with EBADF. In older libglnx, we wouldn't have been able to test this
because it caused an assertion failure, but in GLib and new libglnx it
only causes a critical warning, which we can catch and ignore.
See also GLib commit GNOME/glib@f1f711dc "tests: Test EBADF and errno
handling when closing fds". GLib doesn't have a 1:1 equivalent of
glnx_close_fd as public API, but an internal version is used to
implement g_autofd.
Signed-off-by: Simon McVittie <smcv@collabora.com>
We can't easily assert this without triggering warnings from tools like
valgrind by doing an invalid operation on a closed fd, so we only check
this when under `-m undefined`.
Originally contributed to GLib 2.76 in GNOME/glib@b3934133
"gstdio: Add g_clear_fd() and g_autofd". The implementation in GLib used
g_fsync() as a portable thing that we can do with a fd, but that
function is newer than our minimum GLib version, and libglnx isn't
portable to non-Unix anyway, so use fnctl() instead.
Signed-off-by: Simon McVittie <smcv@collabora.com>
The functionality that was prototyped in libglnx as glnx_fd_close
and then glnx_autofd was later added to GLib as g_autofd.
glnx_close_fd() doesn't have a direct equivalent in GLib, so keep
it intact, but using the backported _glnx_clear_fd_ignore_error as
its implementation. g_clear_fd() is the closest thing in GLib, but
g_clear_fd() guarantees to set errno on failure (making it useful for
error-checking), whereas glnx_close_fd() guarantees to leave errno
untouched, making it more useful for cleanup code paths that recover
from a syscall or similar function that sets errno:
int fd = ...;
success = (fsync (fd) == 0);
glnx_close_fd (&fd);
return success; /* if false, errno indicates why fsync failed */
(Of course in many cases, including this simple example, it would have
been easier to use g_autofd.)
glnx_autofd and glnx_fd_close are now equivalent to the backport of
g_autofd, so document them as deprecated. There's essentially no cost to
retaining them, so don't apply deprecation attributes.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This overflows, which is undefined behaviour (in practice it will usually
wrap around into unsigned space, but this can't be guaranteed).
Signed-off-by: Simon McVittie <smcv@collabora.com>
The selling features are:
* Support for RESOLVE_BENEATH, RESOLVE_IN_ROOT and RESOLVE_NO_SYMLINKS
* Fallback from openat2 to open_tree to openat for compatibility
* Triggering of automounts
test_data is an array of (usually) signed char, but
glnx_file_replace_contents_at() takes an array of unsigned bytes.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Formally, `strlen("x")` is not a constant expression, although gcc can
and does optimize it to a constant expression in simple cases.
clang 19.1.6 warns about this usage.
Replace it with the size of a static array (1 more than the strlen of
its contents), which is unambiguously a constant expression.
Resolves: https://gitlab.gnome.org/GNOME/libglnx/-/issues/5
Signed-off-by: Simon McVittie <smcv@collabora.com>
This is a slight generalization of the reproducer contributed by Will
Thompson: as well as exercising the case where the parent is a dangling
symlink (reproducing GNOME/libglnx#1), this also exercises the case where
the parent is a non-directory non-symlink (in this case a regular file).
Reproduces: GNOME/libglnx#1
Co-authored-by: Will Thompson <wjt@endlessos.org>
Signed-off-by: Simon McVittie <smcv@collabora.com>
If we try to create `link/content` where `link` is a dangling symlink,
recursing to create `link` will succeed (mkdirat fails with EEXIST,
which is explicitly ignored), but then mkdirat for `link/content` will
still fail. Fail gracefully instead of crashing out with an assertion
failure.
Resolves: GNOME/libglnx#1
Signed-off-by: Simon McVittie <smcv@collabora.com>
Otherwise it could potentially race with tests in other executables that
also want to create `./test`, or interfere with other test-cases in the
same executable that expect `./test` to be nonexistent or empty.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Meson 1.1.0 officially deprecates string defaults for boolean options,
but boolean defaults worked in many older Meson versions, going back to
at least 0.49.x.
Signed-off-by: Simon McVittie <smcv@collabora.com>
When compiling with GLib older than 2.80.x, we provide a compatibility
backport of g_closefrom() and g_fdwalk_set_cloexec(), but when compiling
with newer GLib, we rely on GLib to provide those.
The intended scope of libglnx (Linux only) is narrower than the scope
of `<glib-unix.h>` (any Unix platform), so we can safely include
`<glib-unix.h>` unconditionally. This provides least-astonishment by
having `#include <libglnx.h>` with newer GLib always provide a superset
of the functionality it provides with older GLib.
This would have avoided needing
https://github.com/flatpak/flatpak/pull/5737.
Fixes: 6ada39c3 "backports: Add a backport of g_closefrom(), g_fdwalk_set_cloexec()"
Signed-off-by: Simon McVittie <smcv@collabora.com>
Recent versions of openSUSE default to using -Werror=return-type for
package builds, which results in all of these function checks
incorrectly detecting the function as not being available.
Co-authored-by: Peng Yi
Resolves: https://gitlab.gnome.org/GNOME/libglnx/-/issues/4
Signed-off-by: Simon McVittie <smcv@debian.org>