From: Urban Wallasch Date: Sun, 10 Nov 2019 22:23:20 +0000 (+0100) Subject: * mkdirp: initial commit X-Git-Url: https://git.packet-gain.de/?a=commitdiff_plain;h=f5482b7520a7c41e473def07743ae6765b65b330;p=oddbits.git * mkdirp: initial commit * updated README.html --- diff --git a/README.html b/README.html index edf3666..661cf0e 100644 --- a/README.html +++ b/README.html @@ -9,6 +9,13 @@ dict standard C dictionary to store data associated with unique string keys + +mkdirp +- +create a directory and missing parents + + net diff --git a/mkdirp/mkdirp.c b/mkdirp/mkdirp.c new file mode 100644 index 0000000..502b7f6 --- /dev/null +++ b/mkdirp/mkdirp.c @@ -0,0 +1,42 @@ +#include +#include + +#include +#include +#include + +#include "mkdirp.h" + + +/* mkdirp - create a directory and missing parents */ + +int mkdirp(const char *pathname, mode_t mode) { + if (!pathname || !*pathname) { + errno = ENOENT; + return -1; + } + + int err = 0; + char *p; + char path[strlen(pathname) + 1]; + struct stat sb; + + if (stat(pathname, &sb) == 0 && S_ISDIR(sb.st_mode)) + return 0; + + mode |= S_IRWXU; + strcpy(path, pathname); + p = path + 1; + do { + p = strchr(p, '/'); + if (p) + *p = '\0'; + if (stat(path, &sb) != 0 || !S_ISDIR(sb.st_mode)) + err = mkdir(path, mode); + if (p) + *p++ = '/'; + } while (!err && p && *p); + + return err; +} + diff --git a/mkdirp/mkdirp.h b/mkdirp/mkdirp.h new file mode 100644 index 0000000..9ea4184 --- /dev/null +++ b/mkdirp/mkdirp.h @@ -0,0 +1,42 @@ +/* + * mkdirp.h + * + * Copyright (c) 2019, Urban Wallasch + * BSD 3-Clause License, see LICENSE file for more details. + * + * Create a directory and its parents, if they do not already exist. + * + */ + + +#ifndef MKDIRP_H_INCLUDED +#define MKDIRP_H_INCLUDED + +#ifdef cplusplus +extern "C" { +#endif + +#include + + +/* + * mkdirp - create a directory and missing parents + * + * The mkdirp() function creates the directory pathname with the specified + * mode, if it does not already exist. If necessary, any missing parent + * directories are created as part of the process. The file mode of each + * created directory is ((mode | 0700) & ~umask & 0777). The modes of + * already existing directories are left unchanged. + * + * The mkdirp() function returns 0, if the specified directory already + * exists or was successfully created, or -1 if an error occurred, in + * which case errno is set appropriately. + */ +extern int mkdirp(const char *pathname, mode_t mode); + + +#ifdef cplusplus +} +#endif + +#endif /* ndef MKDIRP_H_INCLUDED */ diff --git a/mkdirp/mkdirp_test.c b/mkdirp/mkdirp_test.c new file mode 100644 index 0000000..df77419 --- /dev/null +++ b/mkdirp/mkdirp_test.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include + +#include "mkdirp.h" + + +int main(void) { + struct { + const char *d; + int m; + int expect; + } t[] = { + { "", 0, -1 }, + { "/", 0, 0 }, + { "A_test", 0755, 0 }, + { "A_test/a", 0644, 0 }, + { "B_test/", 0, 0 }, + { "B_test/b/", 0, 0 }, + { "/C", 0, -1 }, + { "/D/", 0, -1 }, + { "C_test/E", 0, 0 }, + { "C_test/F/", 0, 0 }, + { "./C_test//////..///C_test//././././././//X///// ", 0777, 0 }, + { "/tmp/G_test", 0, 0 }, + { "/tmp/H_test/", 0, 0 }, + { "/tmp/I_test/bar/baz/zonk/", 0, 0 }, + { "/tmp/I_test/bar/baz/borg", 0, 0 }, + { NULL, 0, -1 } + }; + int i = 0, err; + + do { + err = mkdirp(t[i].d, t[i].m); + assert( err == t[i].expect ); + if (err) + fprintf(stderr, "mkdir_p(\"%s\", 0%03o) : %s\n", t[i].d, t[i].m, strerror(errno)); + else + fprintf(stderr, "mkdir_p(\"%s\", 0%03o) : Ok\n", t[i].d, t[i].m); + } while (t[i++].d); + + return 0; +} + diff --git a/mkdirp/run_test.sh b/mkdirp/run_test.sh new file mode 100755 index 0000000..6d380c6 --- /dev/null +++ b/mkdirp/run_test.sh @@ -0,0 +1,9 @@ +#!/bin/bash +EXEC=mkdirp_test +SRC="mkdirp.c mkdirp_test.c" +OPTS="-Wall -Wextra -Werror" + +CMD="gcc $OPTS -o $EXEC $SRC" +echo $CMD +$CMD && "./$EXEC" +rm -rf [ABC]_test /tmp/[GHI]_test