`util-linux` seems to fail to handle a use case that users like me seem to be hitting with some frequency. The issue is around https://github.com/util-linux/util-linux/blob/86b6684e7a215a0608bd130371bd7b3faae67aca/libmount/src/context.c#L2115-L2121 and seems rooted in the fact that `util-linux` operates on `type` where type is always of the form <a>.<b> but where <b> is apparently assumed to not contain Unicode U+002E (ASCII 2E): '.' ("dotless"). I say it "appears to assume" this since the logic which appears to remove the subtype does so by using `strrchr`, which addresses only the last period in the `helper` string. If the `subtype`, itself, has a U+002E character then this won't remove the subtype.
As an example, if `helper` looks like `path/name.type./subtype/path/with/a.period` then the modified `helper` after `strrchr` will look like `path/name.type./subtype/path/with/a` instead of the apparently-intended `path/name.type`.
This crops up for users like me because I use NixOS which is a store-based Linux operating system using paths like:
```
$ readlink -f $(which s3fs)
/nix/store/xwbx0fbg65ml2qjl86p9p2w58kghqn8r-s3fs-fuse-1.94/bin/s3fs
```
(So, paths like `/nix/store/<hash>-<name>-<version>/bin/<cmd>`). `version` is usually a dot-delimited string like `1.23`.
I've generated a patch which seems to ameliorate this behavior. It's attached (sorry if attachments are not the way to go with this mailing list, specifically, or mailing lists, generally - this is my first time submitting a patch to a mailing list). The logic is simple, but it basically iterates through all possible substrings according to the number of U+002E characters in the `type` string. It's a more generic form of the logic already present, but it's a little heavy-handed. Happy with any and all changes which preserve the apparently-corrected behavior.
Please let me know if I should make any changes or if a change like this won't be accepted for some reason or if I'm misunderstanding the problem/solution.
Thank you!
Cf.
1. https://discourse.nixos.org/t/how-to-setup-s3fs-mount/6283/5
2. https://github.com/NixOS/nixpkgs/issues/46529#issuecomment-655536831
As an example, if `helper` looks like `path/name.type./subtype/path/with/a.period` then the modified `helper` after `strrchr` will look like `path/name.type./subtype/path/with/a` instead of the apparently-intended `path/name.type`.
This crops up for users like me because I use NixOS which is a store-based Linux operating system using paths like:
```
$ readlink -f $(which s3fs)
/nix/store/xwbx0fbg65ml2qjl86p9p2w58kghqn8r-s3fs-fuse-1.94/bin/s3fs
```
(So, paths like `/nix/store/<hash>-<name>-<version>/bin/<cmd>`). `version` is usually a dot-delimited string like `1.23`.
I've generated a patch which seems to ameliorate this behavior. It's attached (sorry if attachments are not the way to go with this mailing list, specifically, or mailing lists, generally - this is my first time submitting a patch to a mailing list). The logic is simple, but it basically iterates through all possible substrings according to the number of U+002E characters in the `type` string. It's a more generic form of the logic already present, but it's a little heavy-handed. Happy with any and all changes which preserve the apparently-corrected behavior.
Please let me know if I should make any changes or if a change like this won't be accepted for some reason or if I'm misunderstanding the problem/solution.
Thank you!
Cf.
1. https://discourse.nixos.org/t/how-to-setup-s3fs-mount/6283/5
2. https://github.com/NixOS/nixpkgs/issues/46529#issuecomment-655536831
-- John Rinehart
diff --git a/libmount/src/context.c b/libmount/src/context.c index d38e3671f..411f98f3f 100644 --- a/libmount/src/context.c +++ b/libmount/src/context.c @@ -2097,6 +2097,11 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, if (!ns_old) return -MNT_ERR_NAMESPACE; + /* Record number of '.' in `type` so we can try a few things later. */ + int dot_count = 0; + for (int i=0; type[i]; i++) + dot_count += (type[i] == '.'); + /* Ignore errors when search in $PATH and do not modify @rc */ path = strtok_r(search_path, ":", &p); @@ -2112,8 +2117,8 @@ int mnt_context_prepare_helper(struct libmnt_context *cxt, const char *name, continue; found = mnt_is_path(helper); - if (!found && strchr(type, '.')) { - /* If type ends with ".subtype" try without it */ + /* If type contains '.' then try without them. */ + for (int cnt = dot_count; !found && cnt; --cnt) { char *hs = strrchr(helper, '.'); if (hs) *hs = '\0';