From b9edfbfb94b3582cf32dfc04e0dd867ecef2ba92 Mon Sep 17 00:00:00 2001 From: Joachim Wiberg <troglobit@gmail.com> Date: Sat, 3 Aug 2024 13:25:39 +0200 Subject: [PATCH] Refactor mkpath() to drop all uses of strdupa() Fixes #488 Signed-off-by: Joachim Wiberg <troglobit@gmail.com> --- include/Makefile.am | 2 +- include/compat.h | 4 ++-- include/strdupa.h | 52 ----------------------------------------- src/makepath.c | 56 ++++++++++++++++++++++++++++++--------------- src/os.c | 2 +- 5 files changed, 42 insertions(+), 74 deletions(-) delete mode 100644 include/strdupa.h --- a/include/compat.h +++ b/include/compat.h @@ -29,14 +29,14 @@ #include <unistd.h> #include <sys/param.h> /* MAX(), isset(), setbit(), TRUE, FALSE, et consortes. :-) */ #include <sys/types.h> -#include "strdupa.h" /* From The Practice of Programming, by Kernighan and Pike */ #ifndef NELEMS #define NELEMS(array) (sizeof(array) / sizeof(array[0])) #endif -int mkpath (char *dir, mode_t mode); +int mkpath (const char *dir, mode_t mode); +int makepath (const char *dir); #ifndef pidfile int pidfile (const char *basename); --- a/src/makepath.c +++ b/src/makepath.c @@ -1,6 +1,6 @@ /* mkpath() -- Create all components leading up to a given directory * - * Copyright (c) 2013-2021 Joachim Wiberg <troglobit@gmail.com> + * Copyright (c) 2013-2024 Joachim Wiberg <troglobit@gmail.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -16,11 +16,35 @@ */ #include <errno.h> -#include <libgen.h> -#include <sys/stat.h> -#include <sys/types.h> +#include <string.h> /* strdup(), strrchr() */ +#include <stdlib.h> /* free() */ +#include <sys/stat.h> /* mkdir() */ + #include "compat.h" +/* Recursively create directories */ +static int _mkpath(char *dir, mode_t mode) +{ + char *slash; + + if (!mkdir(dir, mode) || errno == EEXIST) + return 0; + + if (errno != ENOENT) + return -1; + + slash = strrchr(dir, '/'); + if (!slash) + return -1; + + *slash = 0; + if (_mkpath(dir, mode) == -1) + return -1; + + *slash = '/'; + return mkdir(dir, mode); +} + /** * mkpath - Like makepath() but takes a mode_t argument * @dir: Directory to created, relative or absolute @@ -29,21 +53,24 @@ * Returns: * POSIX OK(0) on success, otherwise -1 with @errno set. */ -int mkpath(char *dir, mode_t mode) +int mkpath(const char *dir, mode_t mode) { - struct stat sb; + char *_dir; + int rc; if (!dir) { errno = EINVAL; return 1; } - if (!stat(dir, &sb)) - return 0; + _dir = strdup(dir); + if (!_dir) + return -1; - mkpath(dirname(strdupa(dir)), mode); + rc = _mkpath(_dir, mode); + free(_dir); - return mkdir(dir, mode); + return rc; } /** @@ -56,14 +83,7 @@ int mkpath(char *dir, mode_t mode) * fails allocating temporary memory. For other error codes see the * mkdir() syscall description. */ -int makepath(char *dir) +int makepath(const char *dir) { return mkpath(dir, 0777); } - -/** - * Local Variables: - * indent-tabs-mode: t - * c-file-style: "linux" - * End: - */ --- a/src/os.c +++ b/src/os.c @@ -266,7 +266,7 @@ int os_check_perms(void) } } - pidfile_dir = dirname(strdupa(pidfn)); + pidfile_dir = dirname(pidfn); if (access(pidfile_dir, F_OK)) { if (mkpath(pidfile_dir, 0755) && errno != EEXIST) logit(LOG_ERR, "No write permission to %s, aborting.", pidfile_dir);