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>
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>
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>
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>
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>
These will be new API in GLib 2.79.2.
The only code change in the implementation, other than the _glnx
wrappers, was to use `close()` instead of `g_close (fd, NULL)` in a
context where it must be async-signal safe.
The test-case needed some more adjustments to be backwards-compatible
with GLib from the distant past.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This allows doing:
meson setup _build
meson test -C _build
without an intervening `meson compile` step. Previously, this would have
failed in `tests/testing` because `testing-helper` was never compiled.
For a project this small, there's no real need to distinguish precisely
which tests need the helper: we can have a simpler build by just
assuming that they all do, like Autotools would.
Signed-off-by: Simon McVittie <smcv@collabora.com>
When testing something that is expected to fail or crash, it's useful
to disable core dump reporting.
This is a slightly simplified version of GNOME/glib!3510: because
libglnx isn't portable to non-Linux, we can assume that <sys/prctl.h>,
prctl() and <sys/resource.h> are always available, so we don't need
to check for them in the build system.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This is a very useful utility function that allows you to compare two
strings arrays.
Signed-off-by: Ludovico de Nittis <ludovico.denittis@collabora.com>
This is essentially the same as glnx_steal_fd, so make glnx_steal_fd an
alias for it.
The unit test is taken from GLib, slightly modified to avoid g_close()
and also test the old name glnx_steal_fd().
Signed-off-by: Simon McVittie <smcv@collabora.com>
The standards-conformant behaviour is that the contents of saveptr
are ignored when the first argument is non-NULL, but the man page notes
that some older implementations required saveptr to be NULL in that
situation, and the gcc 4.8 provided by the Steam Runtime warns about this.
Signed-off-by: Simon McVittie <smcv@collabora.com>
These were only added in 2.38, and some projects with particularly
ancient dependencies (like the Steam Runtime, based on a 2012 version
of Ubuntu) still avoid depending on that version.
Signed-off-by: Simon McVittie <smcv@collabora.com>
libglnx is intentionally not portable to non-Unix platforms or to
compilers that do not implement gcc/clang extensions, so it's
counterproductive to warn about these extensions, even if libglnx is used
by a parent project that generally (for the parts that don't use
libglnx) wants to be portable to any ISO C compiler.
Suggested by Will Thompson on !36.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This includes a test (who tests the tests themselves?). Run
as `${build}/tests/testing --tap` with semi-modern GLib, or
`${build}/tests/testing --verbose` with GLib < 2.38, to check that the
output is as reasonable as possible given the limitations of the GLib
version in use.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This is an enabler for testing a backport of GTest helpers
(g_test_skip(), etc.) in the oldest environment that I have conveniently
available (Steam Runtime 1 'scout' with GLib 2.32).
Signed-off-by: Simon McVittie <smcv@collabora.com>
The rest of the g_log() wrappers have been there since time immemorial,
but g_info() was initially omitted. It's useful for projects like Flatpak
that want to have two levels of off-by-default logging, which map nicely
to info and debug.
Signed-off-by: Simon McVittie <smcv@collabora.com>
g_variant_n_children() returns a size_t (or gsize, which is equivalent)
so in principle it could overflow an int, although in practice we are
not going to have that many extended attributes. This silences a
warning from gcc -Wsign-compare.
Signed-off-by: Simon McVittie <smcv@collabora.com>
fallocate() is only visible in fcntl.h if _GNU_SOURCE is defined.
Most users of libglnx will want to do that anyway, but it seems nicer
to avoid "implicit declaration of function ‘fallocate’" warnings from
simply including <libglnx.h> into naive code.
Signed-off-by: Simon McVittie <smcv@collabora.com>
What isn't tested usually doesn't work, and the only way to use libglnx
is as a subproject, so test it like that.
Signed-off-by: Simon McVittie <smcv@collabora.com>
If we're building libglnx as a subproject in a larger project, we won't
necessarily want to run these.
Signed-off-by: Simon McVittie <smcv@collabora.com>
One of Flatpak's unit tests uses this, for _GLNX_TEST_SCOPED_TEMP_DIR.
Its API is not really stable, but libglnx is a "copylib" anyway, so
none of it has (or needs) a strictly stable API.
Signed-off-by: Simon McVittie <smcv@collabora.com>
It seems that on SELinux systems, files in /proc have extended
attributes that cannot be copied by an unprivileged user.
Signed-off-by: Simon McVittie <smcv@debian.org>
To fill in some gaps, I've had to make some assumptions:
* trivial changes (such as checking for an additional function or
header file in libglnx.m4) are assumed to not be copyrightable
* Will Thompson and Matthew Leeds are assumed to be contributing on
behalf of Endless Mobile Inc.
* files with no explicit licensing information are assumed to be
under the license found in COPYING
Reference: https://reuse.software/
Signed-off-by: Simon McVittie <smcv@debian.org>
Some pseudo-files in /proc and /sys list a size of 0 bytes in stat()
results, but do in fact have content. For these pseudo-files, the only
way to find out the true file size is to try read() until EOF, so leave
the max_bytes set to -1.
copy_file_range() and sendfile() don't work for such files in some
kernel versions (see <https://lwn.net/Articles/846403/>), so skip the
fast-paths and use a read() and write() loop. For pseudo-files, we
expect to be able to copy the whole content in one read() in any case.
Signed-off-by: Simon McVittie <smcv@debian.org>
This avoids colliding with a config.h generated by a parent Meson
project.
In the Meson build system, we generate libglnx-config.h by doing our
own checks, so we want to avoid it colliding.
In the Autotools build system, we assume that the parent project will
generate its own config.h that contains the results of LIBGLNX_CONFIGURE,
and create a forwarding header libglnx-config.h in the $(top_builddir)
(so that it is next to config.h).
Note that after updating libglnx in an Autotools non-recursive-Make
project (libostree, flatpak, flatpak-builder) it will be necessary to
re-run autogen.sh.
Signed-off-by: Simon McVittie <smcv@collabora.com>
This doesn't really matter, since it only happens when our process is
about to exit anyway, but it makes it easier to use AddressSanitizer
and similar tools.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Otherwise, clang diagnoses it as unused. It is - deliberately - only
allocated and cleaned up, with no other use.
Signed-off-by: Simon McVittie <smcv@collabora.com>
Often, the caller doesn't actually care about the details of the stat
struct itself, but just whether the entry exists or not. It does work
to just pass `NULL` directly to glibc in a quick test, but given that
the argument is tagged as `__nonnull` and that the documentation does
not explicitly specify this is supported, let's do this safely.
Particularly if `AT_FDCWD` is used, we need to open
in the target dir, otherwise we can get `EXDEV` when trying
to do the final link.
(Theoretically we can cross a mountpoint even with fd-relative
though this is a lot less likely)
Having our tests forced into a `goto out` style is seriously annoying
since we can't write tests like we write production code. Add
a macro that checks for the error being NULL.
This doesn't fully solve the problem since the test functions are
still forced into `void` returns; at some point I may extend
GLib to have `g_test_add_err_func()`.