From 42e0a931f1424c2d13794e3a064d328669ed7767 Mon Sep 17 00:00:00 2001 From: Sebastian Harl Date: Sun, 29 Jun 2014 20:43:00 +0200 Subject: [PATCH] utils os: Added sdb_mkdir_all() helper function. This function recursively creates a directory (similar to 'mkdir -p' on the command line). --- src/Makefile.am | 1 + src/include/utils/os.h | 60 +++++++++++++++++++++++ src/utils/os.c | 108 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 src/include/utils/os.h create mode 100644 src/utils/os.c diff --git a/src/Makefile.am b/src/Makefile.am index 686827b..672b90b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -79,6 +79,7 @@ libsysdb_la_SOURCES = \ utils/channel.c include/utils/channel.h \ utils/error.c include/utils/error.h \ utils/llist.c include/utils/llist.h \ + utils/os.c include/utils/os.h \ utils/proto.c include/utils/proto.h \ utils/strbuf.c include/utils/strbuf.h \ core/time.c include/core/time.h \ diff --git a/src/include/utils/os.h b/src/include/utils/os.h new file mode 100644 index 0000000..26f7e59 --- /dev/null +++ b/src/include/utils/os.h @@ -0,0 +1,60 @@ +/* + * SysDB - src/include/utils/os.h + * Copyright (C) 2014 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SDB_UTILS_OS_H +#define SDB_UTILS_OS_H 1 + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * sysdb_mkdir_all: + * Recursively create the directory 'pathname' (similar to 'mkdir -p' on the + * command line) and ensure that its mode is 'mode'. Any newly created + * directories will have permissions according the the specified mode + * (modified by the process's umask in the usual way). The function will + * always ensure the specified permissions for the specified directory, even + * if it exists already. + * + * Returns: + * - 0 on success + * - a negative value else + */ +int +sdb_mkdir_all(const char *pathname, mode_t mode); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* ! SDB_UTILS_OS_H */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + diff --git a/src/utils/os.c b/src/utils/os.c new file mode 100644 index 0000000..b1e143a --- /dev/null +++ b/src/utils/os.c @@ -0,0 +1,108 @@ +/* + * SysDB - src/utils/os.c + * Copyright (C) 2014 Sebastian 'tokkee' Harl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif /* HAVE_CONFIG_H */ + +#include "utils/os.h" + +#include + +#include +#include + +#include +#include +#include + +#include + +/* + * private helper functions + */ + +/* + * Recursively create the directory 'pathname' using the specified 'mode'. If + * 'enforce_mode' is true, the mode will be enforced even if the directory + * exists already. + */ +static int +mkdir_rec(const char *pathname, mode_t mode, _Bool enforce_mode) +{ + struct stat st; + char *base_dir; + + int status = 0; + + if ((! pathname) || (! *pathname)) { + errno = EINVAL; + return -1; + } + + memset(&st, 0, sizeof(st)); + if (! stat(pathname, &st)) { + if (! S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return -1; + } + + if ((st.st_mode != mode) && enforce_mode) + return chmod(pathname, mode); + return 0; + } + + if (errno != ENOENT) + /* pathname exists but we cannot access it */ + return -1; + + base_dir = strdup(pathname); + if (! base_dir) + return -1; + base_dir = dirname(base_dir); + + /* don't enforce the mode on parent directories */ + status = mkdir_rec(base_dir, mode, 0); + if (! status) + status = mkdir(pathname, mode); + + free(base_dir); + return status; +} /* mkdir_rec */ + +/* + * public API + */ + +int +sdb_mkdir_all(const char *pathname, mode_t mode) +{ + return mkdir_rec(pathname, mode, 1); +} /* sdb_mkdir_all */ + +/* vim: set tw=78 sw=4 ts=4 noexpandtab : */ + -- 2.30.2