logo

utils-std

Collection of commonly available Unix tools
commit: ff61a3d2270fe08be2798dca3ad0bd966803eff2
parent 34425ed4c12736d8357835e1ee12d3b08ef2d9e8
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Sat,  4 May 2024 23:01:58 +0200

cmd/mkdir: move mkdir_parents function to lib/mkdir.c

Diffstat:

MMakefile4++--
Mcmd/mkdir.c70+++++++++++++---------------------------------------------------------
Alib/mkdir.c61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Alib/mkdir.h13+++++++++++++
Mmakeless.sh2+-
5 files changed, 90 insertions(+), 60 deletions(-)

diff --git a/Makefile b/Makefile @@ -107,9 +107,9 @@ cmd/chmod: cmd/chmod.c lib/mode.c lib/symbolize_mode.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} $(CC) -std=c99 $(CFLAGS) -o $@ cmd/chmod.c lib/mode.c lib/symbolize_mode.c $(LDFLAGS) $(LDSTATIC) -cmd/mkdir: cmd/mkdir.c lib/mode.c Makefile +cmd/mkdir: cmd/mkdir.c lib/mode.c lib/mode.h lib/mkdir.c lib/mkdir.h Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} - $(CC) -std=c99 $(CFLAGS) -o $@ cmd/mkdir.c lib/mode.c $(LDFLAGS) $(LDSTATIC) + $(CC) -std=c99 $(CFLAGS) -o $@ cmd/mkdir.c lib/mode.c lib/mkdir.c $(LDFLAGS) $(LDSTATIC) cmd/mknod: cmd/mknod.c lib/mode.c Makefile rm -f ${<:=.gcov} ${@:=.gcda} ${@:=.gcno} diff --git a/cmd/mkdir.c b/cmd/mkdir.c @@ -4,20 +4,23 @@ #define _POSIX_C_SOURCE 200809L +#include "../lib/mkdir.h" + #include "../lib/mode.h" #include <assert.h> #include <errno.h> -#include <limits.h> // PATH_MAX #include <stdbool.h> #include <stdio.h> // fprintf #include <stdlib.h> // abort -#include <string.h> // strerror, strrchr +#include <string.h> // strerror #include <sys/stat.h> // mkdir #include <unistd.h> // getopt -bool verbose = false; -mode_t filemask; +char *argv0 = "mkdir"; + +bool mkdir_parents_verbose = false; +mode_t mkdir_parents_filemask; static int mkdir_simple(char *path, mode_t mode) @@ -30,54 +33,7 @@ mkdir_simple(char *path, mode_t mode) return -1; } - if(verbose) fprintf(stderr, "mkdir: Made directory: %s\n", path); - - return 0; -} - -static int -mkdir_parents(char *path, mode_t mode) -{ - assert(errno == 0); - - for(int i = strlen(path) - 1; i >= 0; i--) - { - if(path[i] != '/') break; - - path[i] = 0; - } - - char parent[PATH_MAX] = ""; - strncpy(parent, path, PATH_MAX); - - for(int i = strlen(parent) - 1; i >= 0; i--) - { - if(parent[i] == '/') break; - - parent[i] = 0; - } - - if(path[0] == 0) return 0; - - mode_t parent_mode = (S_IWUSR | S_IXUSR | ~filemask) & 0777; - - if(mkdir_parents(parent, parent_mode) < 0) return -1; - - assert(errno == 0); - if(mkdir(path, mode) < 0) - { - if(errno == EEXIST) - { - errno = 0; - return 0; - } - - fprintf(stderr, "mkdir: Failed making directory '%s': %s\n", path, strerror(errno)); - errno = 0; - return -1; - } - - if(verbose) fprintf(stderr, "mkdir: Made directory: %s\n", path); + if(mkdir_parents_verbose) fprintf(stderr, "mkdir: Made directory: %s\n", path); return 0; } @@ -91,15 +47,15 @@ usage() int main(int argc, char *argv[]) { + mkdir_parents_filemask = umask(0); + umask(mkdir_parents_filemask); + // clang-format off - mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO | ~filemask) & 0777; + mode_t mode = (S_IRWXU | S_IRWXG | S_IRWXO | ~mkdir_parents_filemask) & 0777; bool opt_p = false; const char *errstr = NULL; // clang-format on - filemask = umask(0); - umask(filemask); - int c = -1; while((c = getopt(argc, argv, ":pvm:")) != -1) { @@ -109,7 +65,7 @@ main(int argc, char *argv[]) opt_p = true; break; case 'v': - verbose = true; + mkdir_parents_verbose = true; break; case 'm': mode = new_mode(optarg, 0777, &errstr); diff --git a/lib/mkdir.c b/lib/mkdir.c @@ -0,0 +1,61 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#define _POSIX_C_SOURCE 200809L + +#include "./mkdir.h" + +#include <assert.h> +#include <errno.h> +#include <limits.h> // PATH_MAX +#include <stdio.h> // fprintf +#include <string.h> // strlen, strerror +#include <sys/stat.h> // mkdir + +int +mkdir_parents(char *path, mode_t mode) +{ + assert(errno == 0); + + for(int i = strlen(path) - 1; i >= 0; i--) + { + if(path[i] != '/') break; + + path[i] = 0; + } + + char parent[PATH_MAX] = ""; + strncpy(parent, path, PATH_MAX); + + for(int i = strlen(parent) - 1; i >= 0; i--) + { + if(parent[i] == '/') break; + + parent[i] = 0; + } + + if(path[0] == 0) return 0; + + mode_t parent_mode = (S_IWUSR | S_IXUSR | ~mkdir_parents_filemask) & 0777; + + if(mkdir_parents(parent, parent_mode) < 0) return -1; + + assert(errno == 0); + if(mkdir(path, mode) < 0) + { + if(errno == EEXIST) + { + errno = 0; + return 0; + } + + fprintf(stderr, "%s: Failed making directory '%s': %s\n", argv0, path, strerror(errno)); + errno = 0; + return -1; + } + + if(mkdir_parents_verbose) fprintf(stderr, "%s: Made directory: %s\n", argv0, path); + + return 0; +} diff --git a/lib/mkdir.h b/lib/mkdir.h @@ -0,0 +1,13 @@ +// utils-std: Collection of commonly available Unix tools +// SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me> +// SPDX-License-Identifier: MPL-2.0 + +#include <stdbool.h> +#include <sys/types.h> // mode_t + +// to be declared in each utility +extern char *argv0; +extern bool mkdir_parents_verbose; +extern mode_t mkdir_parents_filemask; + +int mkdir_parents(char *path, mode_t mode); diff --git a/makeless.sh b/makeless.sh @@ -29,7 +29,7 @@ $CC -std=c99 $CFLAGS -o cmd/install cmd/install.c lib/mode.c lib/user_group_pars $CC -std=c99 $CFLAGS -o cmd/link cmd/link.c $LDFLAGS $LDSTATIC $CC -std=c99 $CFLAGS -o cmd/ln cmd/ln.c $LDFLAGS $LDSTATIC $CC -std=c99 $CFLAGS -o cmd/logname cmd/logname.c $LDFLAGS $LDSTATIC -$CC -std=c99 $CFLAGS -o cmd/mkdir cmd/mkdir.c lib/mode.c $LDFLAGS $LDSTATIC +$CC -std=c99 $CFLAGS -o cmd/mkdir cmd/mkdir.c lib/mode.c lib/mkdir.c $LDFLAGS $LDSTATIC $CC -std=c99 $CFLAGS -o cmd/mkfifo cmd/mkfifo.c lib/mode.c $LDFLAGS $LDSTATIC $CC -std=c99 $CFLAGS -o cmd/mknod cmd/mknod.c lib/mode.c $LDFLAGS $LDSTATIC $CC -std=c99 $CFLAGS -o cmd/nice cmd/nice.c $LDFLAGS $LDSTATIC