diff options
author | Matthias Görgens <matthias.goergens@gmail.com> | 2023-04-02 17:45:27 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-02 10:45:27 +0100 |
commit | 7be56c57f93e3436b1fbd9ecc320de5c03a3e4b8 (patch) | |
tree | 91ba1e928cca176f23776715dc076a99ea36bd82 /util | |
parent | 2113871279d3c270c01c54c81782e982ec6e8246 (diff) | |
download | fuse-7be56c57f93e3436b1fbd9ecc320de5c03a3e4b8.tar.gz |
Workaround musl bug when mountdir has whitespace (#761)
Fixes https://github.com/libfuse/libfuse/issues/634 and https://github.com/mpartel/bindfs/issues/106
Diffstat (limited to 'util')
-rw-r--r-- | util/fusermount.c | 63 |
1 files changed, 58 insertions, 5 deletions
diff --git a/util/fusermount.c b/util/fusermount.c index f8124cb..7a6bc24 100644 --- a/util/fusermount.c +++ b/util/fusermount.c @@ -7,7 +7,7 @@ */ /* This program does the mounting and unmounting of FUSE filesystems */ -#define _GNU_SOURCE /* for clone */ +#define _GNU_SOURCE /* for clone and strchrnul */ #include "fuse_config.h" #include "mount_util.h" @@ -63,6 +63,59 @@ static int mount_max = 1000; static int auto_unmount = 0; +#ifdef GETMNTENT_NEEDS_UNESCAPING +// Older versions of musl libc don't unescape entries in /etc/mtab + +// unescapes octal sequences like \040 in-place +// That's ok, because unescaping can not extend the length of the string. +static void unescape(char *buf) { + char *src = buf; + char *dest = buf; + while (1) { + char *next_src = strchrnul(src, '\\'); + int offset = next_src - src; + memmove(dest, src, offset); + src = next_src; + dest += offset; + + if(*src == '\0') { + *dest = *src; + return; + } + src++; + + if('0' <= src[0] && src[0] < '2' && + '0' <= src[1] && src[1] < '8' && + '0' <= src[2] && src[2] < '8') { + *dest++ = (src[0] - '0') << 6 + | (src[1] - '0') << 3 + | (src[2] - '0') << 0; + src += 3; + } else if (src[0] == '\\') { + *dest++ = '\\'; + src += 1; + } else { + *dest++ = '\\'; + } + } +} + +static struct mntent *GETMNTENT(FILE *stream) +{ + struct mntent *entp = getmntent(stream); + if(entp != NULL) { + unescape(entp->mnt_fsname); + unescape(entp->mnt_dir); + unescape(entp->mnt_type); + unescape(entp->mnt_opts); + } + return entp; +} +#else +#define GETMNTENT getmntent +#endif // GETMNTENT_NEEDS_UNESCAPING + + static const char *get_user_name(void) { struct passwd *pw = getpwuid(getuid()); @@ -169,7 +222,7 @@ static int may_unmount(const char *mnt, int quiet) uidlen = sprintf(uidstr, "%u", getuid()); found = 0; - while ((entp = getmntent(fp)) != NULL) { + while ((entp = GETMNTENT(fp)) != NULL) { if (!found && strcmp(entp->mnt_dir, mnt) == 0 && (strcmp(entp->mnt_type, "fuse") == 0 || strcmp(entp->mnt_type, "fuseblk") == 0 || @@ -261,7 +314,7 @@ static int check_is_mount_child(void *p) } count = 0; - while (getmntent(fp) != NULL) + while (GETMNTENT(fp) != NULL) count++; endmntent(fp); @@ -280,7 +333,7 @@ static int check_is_mount_child(void *p) } found = 0; - while ((entp = getmntent(fp)) != NULL) { + while ((entp = GETMNTENT(fp)) != NULL) { if (count > 0) { count--; continue; @@ -464,7 +517,7 @@ static int count_fuse_fs(void) strerror(errno)); return -1; } - while ((entp = getmntent(fp)) != NULL) { + while ((entp = GETMNTENT(fp)) != NULL) { if (strcmp(entp->mnt_type, "fuse") == 0 || strncmp(entp->mnt_type, "fuse.", 5) == 0) count ++; |