logo

utils-std

Collection of commonly available Unix tools
commit: 722a1008ed5cf8ecb3396d59e57e3c437e4f6a77
parent 229f34110452281f787f1d3ca31c90247bcea57c
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Fri,  1 Mar 2024 06:32:33 +0100

cmd/df: escape getmntent output, note on musl prior to 1.2.5

Diffstat:

Mcmd/df.c61+++++++++++++++++++++----------------------------------------
1 file changed, 21 insertions(+), 40 deletions(-)

diff --git a/cmd/df.c b/cmd/df.c @@ -7,6 +7,7 @@ #include "../lib/humanize.h" +#include <ctype.h> // iscntrl, isspace #include <errno.h> // errno #include <mntent.h> #include <stdbool.h> @@ -18,28 +19,12 @@ size_t forced_bsize = 0; +// Replaces control characters and whitespaces with '?' in-place (no allocation) static void -unescape_path(char *path) +static_escape(char *str) { - char *needle = "\\040"; - size_t esc_len = 3; // 4 chars but leading-slash is kept for space - - char *str = strstr(path, needle); - - if(str != NULL) - { - size_t pos = 0; - - str[pos++] = ' '; - - while(str[pos] != '\0') - { - str[pos] = str[pos + esc_len]; - pos++; - } - - unescape_path(str + pos); - } + for(int i = 0; i < strlen(str); i++) + if(iscntrl(str[i]) || isspace(str[i])) str[i] = '?'; } int @@ -84,8 +69,8 @@ main(int argc, char *argv[]) printf("Filesystem Total Used Available Use%% Mountpoint\n"); } - FILE *mnt = setmntent(MOUNTED, "r"); - if(mnt == NULL) + FILE *mounted = setmntent(MOUNTED, "r"); + if(mounted == NULL) { fprintf(stderr, "df: Error opening setmntent(\"" MOUNTED "\", \"r\"): %s", strerror(errno)); return 1; @@ -93,31 +78,27 @@ main(int argc, char *argv[]) while(1) { - struct mntent *mntent = getmntent(mnt); + struct mntent *mntent = getmntent(mounted); if(mntent == NULL) break; - // Linux escapes spaces in filesystems and mountpoints with \040 - // which statvfs(3) doesn't interprets - // Also shouldn't be printed out to not break parsing of df(1) output - char *mountpoint = strdup(mntent->mnt_dir); - if(mountpoint == NULL) - { - fprintf(stderr, "df: Failed duplicating mnt_dir string: %s\n", strerror(errno)); - return 1; - exit(1); - } - unescape_path(mountpoint); - + // Note: musl prior to 1.2.5 has broken getmntent when octal sequences and carriage return is used + // https://git.musl-libc.org/cgit/musl/commit/src/misc/mntent.c?id=f314e133929b6379eccc632bef32eaebb66a7335 + // https://git.musl-libc.org/cgit/musl/commit/src/misc/mntent.c?id=ee1d39bc1573c1ae49ee6b658938b56bbef95a6c struct statvfs stats; - if(statvfs(mountpoint, &stats) != 0) + if(statvfs(mntent->mnt_dir, &stats) != 0) { - fprintf(stderr, "df: Error statvfs(\"%s\", _): %s\n", mountpoint, strerror(errno)); + fprintf(stderr, "df: Error statvfs(\"%s\", _): %s\n", mntent->mnt_dir, strerror(errno)); + + static_escape(mntent->mnt_fsname); + static_escape(mntent->mnt_dir); printf("%s - - - - %s\n", mntent->mnt_fsname, mntent->mnt_dir); - free(mountpoint); continue; } - free(mountpoint); + + // Needs to be done after calling statvfs(3) + static_escape(mntent->mnt_fsname); + static_escape(mntent->mnt_dir); size_t percent = 0; size_t total = stats.f_frsize * stats.f_blocks; @@ -166,7 +147,7 @@ main(int argc, char *argv[]) } } - endmntent(mnt); + endmntent(mounted); return 0; }