author | Olivier Brunel
<jjk@jjacky.com> 2023-05-11 17:22:38 UTC |
committer | Olivier Brunel
<jjk@jjacky.com> 2023-07-05 07:37:02 UTC |
parent | d6e0a08918a2e757f34f1127dd562cd473146f7d |
src/doc/djbunix.h.0.md | +14 | -0 |
src/doc/djbunix.h/fd_mkdirpat.3.md | +55 | -0 |
src/liblimb/djbunix.h/fd_mkdirp.c | +10 | -0 |
src/liblimb/djbunix.h/fd_mkdirpat.c | +42 | -0 |
src/liblimb/djbunix.h/mkdirp.c | +10 | -0 |
src/liblimb/djbunix.h/mkdirpat.c | +12 | -0 |
src/liblimb/include/limb/djbunix.h | +5 | -0 |
diff --git a/src/doc/djbunix.h.0.md b/src/doc/djbunix.h.0.md index a33da9b..d6eab10 100644 --- a/src/doc/djbunix.h.0.md +++ b/src/doc/djbunix.h.0.md @@ -22,6 +22,20 @@ operations, file descriptors, environment, child processes, and so on. The following functions/macros are defined : +: [fd_mkdirpat](3) +:: Create a path of directories and returns the file descriptor. + +: [fd_mkdirp](3) +:: Same as [fd_mkdirpat](3) but relative path are based on current working +:: directory. + +: [mkdirpat](3) +:: Create a path of directories. + +: [mkdirp](3) +:: Same as [mkdirpat](3) but relative path are based on current working +:: directory. + : [open_parsed_name](3) :: Return the specified file descriptor, or that of the given file name. diff --git a/src/doc/djbunix.h/fd_mkdirpat.3.md b/src/doc/djbunix.h/fd_mkdirpat.3.md new file mode 100644 index 0000000..b476523 --- /dev/null +++ b/src/doc/djbunix.h/fd_mkdirpat.3.md @@ -0,0 +1,55 @@ +% limb manual +% fd_mkdirpat(3) + +# NAME + +fd\_mkdirpat, fd\_mkdirp, mkdirpat, mkdirp - create a path of directories + +# SYNOPSIS + + #include <limb/djbunix.h> + +```pre hl +int fd_mkdirpat(int <em>fd</em>, const char *<em>name</em>, mode_t <em>mode</em>) +int fd_mkdirp(const char *<em>name</em>, mode_t <em>mode</em>) +int mkdirpat(int <em>fd</em>, const char *<em>name</em>, mode_t <em>mode</em>) +int mkdirp(const char *<em>name</em>, mode_t <em>mode</em>) +``` + +# DESCRIPTION + +The `fd_mkdirpat`() function creates the path of directories `name`, i.e. it +attempts not only to create the last element of `name` but every single one. +This can be thinking thought of as equivalent to `mkdir --parent`. +The file permission bits of the new directory will be initialized from `mode` +for newly created directories (already existing ones aren't changed). + +If `name` specifies a relative path, it is relative to the directory associated +with the file descriptor `fd` which may be *AT_FDCWD* to use the current working +directory. + +A file descriptior to the last directory of the path in `name` is returned. + +The `fd_mkdirp`() function is similar to `fd_mkdirpat`() except when `name` +specifies a relative path, in which case it is relative to the current working +directory. + +The `mkdirpat`() function is similar to `fd_mkdirpat`() except that, on success, +it returns zero. + +The `mkdirp`() function is similar to `fd_mkdirp`() except that, on success, it +returns zero. + +# RETURN VALUE + +The `fd_mkdirpat`() and `fd_mkdirp`() functions return a file descriptor to the +full directory specified in `name` on success. Otherwise, they return -1 and set +`errno` to indicate the error. + +The `mkdirpat`() and `mkdirp`() functions return 0 on success. Otherwise, they +return -1 and set `errno` to indicate the error. + +# ERRORS + +These functions may fail and set errno for any of the errors specified for +[mkdirat](3) and [openat](3), save for *EEXIST*. diff --git a/src/liblimb/djbunix.h/fd_mkdirp.c b/src/liblimb/djbunix.h/fd_mkdirp.c new file mode 100644 index 0000000..c9a8167 --- /dev/null +++ b/src/liblimb/djbunix.h/fd_mkdirp.c @@ -0,0 +1,10 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <limb/djbunix.h> + +int +fd_mkdirp(const char *name, mode_t mode) +{ + return fd_mkdirpat(AT_FDCWD, name, mode); +} diff --git a/src/liblimb/djbunix.h/fd_mkdirpat.c b/src/liblimb/djbunix.h/fd_mkdirpat.c new file mode 100644 index 0000000..c14701a --- /dev/null +++ b/src/liblimb/djbunix.h/fd_mkdirpat.c @@ -0,0 +1,42 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <limb/bytestr.h> +#include <limb/djbunix.h> +#include <limb/unix-transactional.h> + +int +fd_mkdirpat(int bfd, const char *name, mode_t mode) +{ + size_t nlen = strlen(name); + int fd = bfd; + + for (;;) { + char buf[512]; + const char *n; + size_t o = byte_chr(name, nlen, '/'); + if (o == nlen) { + n = name; + } else { + n = buf; + memcpy(buf, name, o); + buf[o] = 0; + } + if (mkdirat(fd, n, mode) < 0 && errno != EEXIST) + goto err; + int dfd = open2_at(fd, n, O_RDONLY | O_DIRECTORY); + if (dfd < 0) goto err; + if (fd != bfd) fd_close(fd); + fd = dfd; + if (o == nlen) return fd; + name += o + 1; + nlen -= o + 1; + } + +err: + if (fd != bfd) fd_close(fd); + return -1; +} diff --git a/src/liblimb/djbunix.h/mkdirp.c b/src/liblimb/djbunix.h/mkdirp.c new file mode 100644 index 0000000..836510a --- /dev/null +++ b/src/liblimb/djbunix.h/mkdirp.c @@ -0,0 +1,10 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <limb/djbunix.h> + +int +mkdirp(const char *name, mode_t mode) +{ + return mkdirpat(AT_FDCWD, name, mode); +} diff --git a/src/liblimb/djbunix.h/mkdirpat.c b/src/liblimb/djbunix.h/mkdirpat.c new file mode 100644 index 0000000..87f919c --- /dev/null +++ b/src/liblimb/djbunix.h/mkdirpat.c @@ -0,0 +1,12 @@ +/* This file is part of limb https://lila.oss/limb + * Copyright (C) 2023 Olivier Brunel jjk@jjacky.com */ +/* SPDX-License-Identifier: GPL-2.0-only */ +#include <limb/djbunix.h> + +int mkdirpat(int bfd, const char *name, mode_t mode) +{ + int fd = fd_mkdirpat(bfd, name, mode); + if (fd < 0) return -1; + fd_close(fd); + return 0; +} diff --git a/src/liblimb/include/limb/djbunix.h b/src/liblimb/include/limb/djbunix.h index 6a276cd..a97af3c 100644 --- a/src/liblimb/include/limb/djbunix.h +++ b/src/liblimb/include/limb/djbunix.h @@ -19,6 +19,11 @@ extern int open_parsed_name(const char *name, open_fn open); #define open_write_close(file,data,dlen) open_write_closeat(AT_FDCWD, file, data, dlen) #define open_writev_close(file,v,n) open_writev_closeat(AT_FDCWD, file, v, n) +extern int fd_mkdirpat(int fd, const char *name, mode_t mode); +extern int fd_mkdirp(const char *name, mode_t mode); +extern int mkdirpat(int fd, const char *name, mode_t mode); +extern int mkdirp(const char *name, mode_t mode); + extern int rm_rfat(int fd, const char *name); extern int rm_rf_tmpat(int fd, const char *name, stralloc *sa); extern int rm_rf_in_tmpat(int fd, stralloc *sa, size_t offset);