diff options
| author | Mr. Goblin <mrgoblin@mrgoblin.net> | 2026-09-17 20:55:34 +0300 |
|---|---|---|
| committer | Mr. Goblin <mrgoblin@mrgoblin.net> | 2026-09-17 20:55:34 +0300 |
| commit | e8cac0c4441d3c77b7e0181da441d416f481edd7 (patch) | |
| tree | 9ef0c02ae7a6ad20b7a66e80a63a3987bb5aee85 /src | |
| parent | 51a1bad32dec2f0ebff5f16345759934c233ef71 (diff) | |
Implemented mkdir -p in db module (not used)
Diffstat (limited to 'src')
| -rw-r--r-- | src/cliflags.h | 10 | ||||
| -rw-r--r-- | src/db.c | 166 | ||||
| -rw-r--r-- | src/db.h | 59 |
3 files changed, 230 insertions, 5 deletions
diff --git a/src/cliflags.h b/src/cliflags.h index 21ffebc..5bf251b 100644 --- a/src/cliflags.h +++ b/src/cliflags.h @@ -28,16 +28,16 @@ * OF SUCH DAMAGE. */ -#ifndef BTASKT_CLIFLAGS_H_SENTRY -#define BTASKT_CLIFLAGS_H_SENTRY +#ifndef BTASKTD_CLIFLAGS_H_SENTRY +#define BTASKTD_CLIFLAGS_H_SENTRY #ifdef __cplusplus extern "C" { #endif enum flag_val_res { - fvr_not_found = -1, - fvr_min = fvr_not_found, fvr_ok = 0, + fvr_min = fvr_ok, + fvr_not_found, fvr_invalid, fvr_max = fvr_invalid }; @@ -72,4 +72,4 @@ extract_int_flag(char flagletter, int argc, char **argv); #ifdef __cplusplus } #endif -#endif /* BTASKT_CLIFLAGS_H_SENTRY */ +#endif /* BTASKTD_CLIFLAGS_H_SENTRY */ diff --git a/src/db.c b/src/db.c new file mode 100644 index 0000000..a46f806 --- /dev/null +++ b/src/db.c @@ -0,0 +1,166 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <dirent.h> +#include <fcntl.h> +#include <unistd.h> +#include <wait.h> +#include <string.h> +#include <limits.h> +#include <errno.h> +#include "db.h" + +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif + +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif + +#define DIR_NAME_BUF_SIZE (NAME_MAX+1) + + +static const char * +find_chr_or_zero(const char *s, char ch) +{ + while (*s && *s != ch) + s++; + return s; +} + +static const char * +find_chr_or_zero_n(const char *s, char ch, int n) +{ + int i = 0; + while (i < n && *s && *s != ch) { + s++; + i++; + } + return s; +} + +static struct db_value_int +does_dir_exist(const char *path) +{ + struct db_value_int res = {0}; + struct stat st = {0}; + int code; + res.code = dbe_ok; + res.data = 1; + code = stat(path, &st); + if (code != 0) { + if (errno == ENOENT) + res.data = 0; + else if (errno == EACCES) + res.code = dbe_access; + else + res.code = dbe_unknown; + } else { + res.data = ((st.st_mode & S_IFMT) == S_IFDIR) ? 1 : 0; + } + return res; +} + +static enum db_error +make_dir_ifne(const char *path, int rights) +{ + struct db_value_int val = {0}; + int code; + val = does_dir_exist(path); + if (val.code != dbe_ok) + return val.code; + else if (val.data) + return dbe_ok; + code = mkdir(path, rights); + if (code != 0) { + if (errno == EACCES) + return dbe_access; + else if (errno == EEXIST) + return dbe_notdir; + } + return dbe_ok; +} + +static enum db_error +do_make_dir_path(const char *path, int rights) +{ + char buf[DIR_NAME_BUF_SIZE] = {0}; + const char *p = find_chr_or_zero(path, '/'); + unsigned sz = p - path + 1, code; + if (sz > sizeof(buf)) + return dbe_inval; + strncpy(buf, path, sz); + buf[sz-1] = '\0'; + code = make_dir_ifne(buf, rights); + if (code != dbe_ok) + return code; + if (*p) { + code = chdir(buf); + if (0 != code) + return dbe_access; + do_make_dir_path(p+1, rights); + code = chdir(".."); + if (0 != code) + return dbe_access; + } + return dbe_ok; +} + +/* mkdir -p */ +enum db_error +make_dir_path(const char *path, int rights) +{ + return do_make_dir_path(path, rights); +} + +/* ==================================================================== */ + +#ifdef BTASKTD_DB_TEST + +#include <stdio.h> + +#define TEST_CODE(code) \ + do { \ + const char *s = NULL; \ + switch (code) { \ + case dbe_ok: s = "NO_ERROR"; break; \ + case dbe_notdir: s = "NOT_DIR"; break; \ + case dbe_inval: s = "INV_INPUT"; break; \ + case dbe_access: s = "ACCESS"; break; \ + default: s = "UNKNOWN"; \ + } \ + fprintf(stderr, "%s\n", s); \ + } while (0) + + +int +main(void) +{ + int i, pid; + const char *path = "test_db/super_test/mtest"; + for (i = 0; i < 10; i++) + TEST_CODE(make_dir_path(path, 0777)); + pid = fork(); + if (pid == -1) { + fprintf(stderr, "can't fork\n"); + return 1; + } else if (pid == 0) { + execlp("ls", "ls", "-laR", NULL); + _exit(128); + } else { + wait(NULL); + } + pid = fork(); + if (pid == -1) { + fprintf(stderr, "can't fork\n"); + return 1; + } else if (pid == 0) { + execlp("rm", "rm", "-rf", "test_db", NULL); + _exit(128); + } else { + wait(NULL); + } + return 0; +} + +#endif diff --git a/src/db.h b/src/db.h new file mode 100644 index 0000000..ebb42c5 --- /dev/null +++ b/src/db.h @@ -0,0 +1,59 @@ +/*- + * Copyright (c) 2026, Mr. Goblin + * + * SPDX-License-Identifier: BSD-2-Clause + * + * 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 OWNER 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 BTASKT_DB_H_SENTRY +#define BTASKT_DB_H_SENTRY +#ifdef __cplusplus +extern "C" { +#endif + +enum db_error { + dbe_ok = 0, + dbe_min = dbe_ok, + dbe_notdir, + dbe_inval, + dbe_access, + dbe_unknown, + dbe_max = dbe_unknown +}; + +struct db_value_int { + enum db_error code; + int data; +}; + +/* mkdir -p */ +enum db_error +make_dir_path(const char *path, int rights); + +#ifdef __cplusplus +} +#endif +#endif /* BTASKT_DB_H_SENTRY */ |
