Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Build failure on musl-1.2.5 due to removed basename prototype from string.h #778

Closed
hhoffstaette opened this issue Apr 15, 2024 · 9 comments
Labels
bug build Changes in build system
Milestone

Comments

@hhoffstaette
Copy link
Contributor

Originally found in Gentoo: https://bugs.gentoo.org/926288

musl 1.2.5 removed basename from string.h.

This is messy because of the different semantics between the POSIX and GNU implementations and might require not just a conditional import of libgen.h. 😞

Current calls to basename are in:

name = basename(path);

newname = basename(dupname);

char *tmp_path, *slash, *dirname, *basename;
(multiple)

@kdave kdave added bug build Changes in build system labels Apr 15, 2024
@kdave
Copy link
Owner

kdave commented Apr 18, 2024

What is the suggested fix?

@kdave
Copy link
Owner

kdave commented Apr 18, 2024

The CI images are using alpine:edge that has musl version 1.2.5r0, so this should fail the build but it does not. We're using the GNU basename, _GNU_SOURCE is defined for the entire build.

From the example only one seems to miss the libgen.h include, common/device-utils.c, for subvolume.c it's already there and in libbtrfsutil it's only a local variable.

I'm assuming the fix is to add libgen.h, right?

@hhoffstaette
Copy link
Contributor Author

Note that I'm just the messenger, I don't use musl myself.

How to fix this really depends on the code of every individual project. Search all of github for "musl basename" and you will find countless slightly different approaches.

If you want the GNU semantics where the input argument is never modified and therefore does not crash when it's a static constant string (IMHO the sanest real-world approach, despite the fact that this is not POSIX compliant) then maybe just steal a gnu_basename replacement function from some other project and only compile it as basename() when it is undefined.

In Gentoo we have added variations of kmod-project/kmod#32 in several projects, and that means - as documented in that PR - the solution is to never include libgen.h. :)

@kdave
Copy link
Owner

kdave commented Apr 18, 2024

That's helpful, thanks. I'll add a helper working as the GNU basename and drop libgen.h.

@kdave kdave added this to the v6.8.1 milestone Apr 18, 2024
kdave added a commit that referenced this issue Apr 18, 2024
What basename(3) does with the argument depends on _GNU_SOURCE and
inclusion of libgen.h. This is problematic on Musl (1.2.5) as reported.

We want the GNU semantics that does not modify the argument. Common way
to make it portable is to add own helper. This is now implemented in
path_basename() that does not use the libc provided basename but preserves
the semantics. The path_dirname() is just for parity, otherwise same as
dirname().

Sources:
- https://bugs.gentoo.org/926288
- https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7

Issue: #778
Signed-off-by: David Sterba <dsterba@suse.com>
@kdave
Copy link
Owner

kdave commented Apr 18, 2024

Fixed in devel. The manual page says that path / should be returned as / from basename, this should be added to the kmod project wrapper I think.

@kdave kdave closed this as completed Apr 18, 2024
kdave added a commit that referenced this issue Apr 18, 2024
What basename(3) does with the argument depends on _GNU_SOURCE and
inclusion of libgen.h. This is problematic on Musl (1.2.5) as reported.

We want the GNU semantics that does not modify the argument. Common way
to make it portable is to add own helper. This is now implemented in
path_basename() that does not use the libc provided basename but preserves
the semantics. The path_dirname() is just for parity, otherwise same as
dirname().

Sources:
- https://bugs.gentoo.org/926288
- https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7

Issue: #778
Signed-off-by: David Sterba <dsterba@suse.com>
@hhoffstaette
Copy link
Contributor Author

I have a musl chroot but it's still on 1.2.4; will update and give this a try tomorrow.

@hhoffstaette
Copy link
Contributor Author

I have a musl chroot but it's still on 1.2.4; will update and give this a try tomorrow.

Seems to compile - thanks! 👍

kdave added a commit that referenced this issue Apr 19, 2024
What basename(3) does with the argument depends on _GNU_SOURCE and
inclusion of libgen.h. This is problematic on Musl (1.2.5) as reported.

We want the GNU semantics that does not modify the argument. Common way
to make it portable is to add own helper. This is now implemented in
path_basename() that does not use the libc provided basename but preserves
the semantics. The path_dirname() is just for parity, otherwise same as
dirname().

Sources:
- https://bugs.gentoo.org/926288
- https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7

Issue: #778
Signed-off-by: David Sterba <dsterba@suse.com>
@kdave
Copy link
Owner

kdave commented Apr 30, 2024

The simple implementation using strrchr() does not work in cases like /path/dir///// as it returns empty path due to number of trailing slashes. This also breaks one test that uses such paths. I think this can happen by accident or even one trailing slash will break it. This is where the argument modifying basename works and I'll probably change the internal implementation to behave like that. There should be no change regarding Musl support.

@kdave
Copy link
Owner

kdave commented Apr 30, 2024

I'll keep current version for 6.8.1 as it works in most cases and fixes the musl support but this looks like reimplementation of posix basename behaviour. It is also possible that path handling can be simplified in some cases, changing just before a release won't be good.

kdave added a commit that referenced this issue Apr 30, 2024
What basename(3) does with the argument depends on _GNU_SOURCE and
inclusion of libgen.h. This is problematic on Musl (1.2.5) as reported.

We want the GNU semantics that does not modify the argument. Common way
to make it portable is to add own helper. This is now implemented in
path_basename() that does not use the libc provided basename but preserves
the semantics. The path_dirname() is just for parity, otherwise same as
dirname().

Sources:
- https://bugs.gentoo.org/926288
- https://git.musl-libc.org/cgit/musl/commit/?id=725e17ed6dff4d0cd22487bb64470881e86a92e7

Issue: #778
Signed-off-by: David Sterba <dsterba@suse.com>
kdave added a commit that referenced this issue Apr 30, 2024
This is a followup to 884a609 ("btrfs-progs: add basename
wrappers for unified semantics"). Test cli/019-subvolume-create-parents
fails as there are paths with trailing slashes.

The GNU semantics does not change the argument of basename(3) but this
is problematic with trailing slashes. This is not uncommon and could
potentially break things.

To minimize impact of the basename behaviour depending on the include of
libgen.h use the single wrapper in path utils that has to include libgen
anyway for dirname. Our code passes writable buffers to basename.

Issue: #778
Signed-off-by: David Sterba <dsterba@suse.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug build Changes in build system
Projects
None yet
Development

No branches or pull requests

2 participants