From a4b2d0218a399e5e4809671d20a8bea5edb2f7d4 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Mon, 16 Mar 2026 17:11:08 +0000 Subject: util/nvmutil: proper /dev/fd search in fchmod some systems may not even have it works with /dev/fd (bsd/mac etc) works with linux (/proc/self/fd) and falls back on super old systems that have neither Signed-off-by: Leah Rowe --- util/nvmutil/nvmutil.c | 77 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 50 insertions(+), 27 deletions(-) (limited to 'util/nvmutil/nvmutil.c') diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index 7731d31f..851eb0fb 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -492,6 +492,10 @@ static void *x_v_memcpy(void *dst, static int x_i_memcmp(const void *a, const void *b, unsigned long n); static int x_i_fchmod(int fd, mode_t mode); +static int x_try_fdpath(const char *prefix, + int fd, mode_t mode); +static unsigned long x_conv_fd(char *buf, + unsigned long n); /* * Sizes in bytes: @@ -3180,38 +3184,57 @@ x_i_memcmp(const void *a, const void *b, unsigned long n) static int x_i_fchmod(int fd, mode_t mode) { - char path[32]; - char tmp[16]; - int i = 0; - int j = 0; - int n; - - /* build "/dev/fd/" */ - path[i++] = '/'; - path[i++] = 'd'; - path[i++] = 'e'; - path[i++] = 'v'; - path[i++] = '/'; - path[i++] = 'f'; - path[i++] = 'd'; - path[i++] = '/'; - - /* convert fd to decimal */ - n = fd; + if (x_try_fdpath("/dev/fd/", fd, mode) == 0) + return 0; - if (n == 0) { - path[i++] = '0'; - } else { - while (n > 0) { - tmp[j++] = (char)('0' + (n % 10)); - n /= 10; - } + if (x_try_fdpath("/proc/self/fd/", fd, mode) == 0) + return 0; - while (j > 0) - path[i++] = tmp[--j]; + errno = ENOSYS; + return -1; +} + +static int +x_try_fdpath(const char *prefix, int fd, mode_t mode) +{ + char path[PATH_LEN]; + + unsigned long i = 0; + unsigned long j; + + while (prefix[i]) { + path[i] = prefix[i]; + i++; } + j = x_conv_fd(path + i, (unsigned long)fd); + i += j; + path[i] = '\0'; return chmod(path, mode); } + +static unsigned long +x_conv_fd(char *buf, unsigned long n) +{ + char tmp[256]; + + unsigned long i = 0; + unsigned long j = 0; + + if (n == 0) { + buf[0] = '0'; + return 1; + } + + while (n > 0) { + tmp[i++] = (char)('0' + (n % 10)); + n /= 10; + } + + while (i > 0) + buf[j++] = tmp[--i]; + + return j; +} -- cgit v1.2.1