summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2022-12-30 14:49:46 -0500
committerTavian Barnes <tavianator@tavianator.com>2023-01-19 14:41:55 -0500
commit683552c4c9a3dfee4ce603157bb2cf18d64fbcfc (patch)
tree475130eeb136007eea7c59cb7190dc05287e2c56
parent944cd72f40a84d318453c320a84d443273956859 (diff)
downloadbfs-683552c4c9a3dfee4ce603157bb2cf18d64fbcfc.tar.xz
bfstd: New wrappers for dirname()/basename()
-rw-r--r--Makefile13
-rw-r--r--src/bfstd.c45
-rw-r--r--src/bfstd.h28
-rw-r--r--src/bftw.c2
-rw-r--r--src/color.c2
-rw-r--r--src/diag.c11
-rw-r--r--src/eval.c10
-rw-r--r--src/exec.c2
-rw-r--r--src/mtab.c5
-rw-r--r--src/parse.c6
-rw-r--r--tests/bfstd.c57
-rw-r--r--tests/mksock.c22
-rw-r--r--tests/xtouch.c1
13 files changed, 158 insertions, 46 deletions
diff --git a/Makefile b/Makefile
index 49a3a87..b39a88a 100644
--- a/Makefile
+++ b/Makefile
@@ -197,6 +197,7 @@ $(FLAG_GOALS): $(FLAG_PREREQS)
all: \
$(BIN)/bfs \
+ $(BIN)/tests/bfstd \
$(BIN)/tests/mksock \
$(BIN)/tests/trie \
$(BIN)/tests/xtimegm \
@@ -250,22 +251,26 @@ LIBBFS := \
# The main executable
$(BIN)/bfs: $(OBJ)/src/main.o $(LIBBFS)
+# Standalone binary tests
+STANDALONE_CHECKS := check-bfstd check-trie check-xtimegm
+
# The different search strategies that we test
STRATEGIES := bfs dfs ids eds
STRATEGY_CHECKS := $(STRATEGIES:%=check-%)
# All the different checks we run
-CHECKS := $(STRATEGY_CHECKS) check-trie check-xtimegm
+CHECKS := $(STANDALONE_CHECKS) $(STRATEGY_CHECKS)
check: $(CHECKS)
.PHONY: check $(CHECKS)
+$(STANDALONE_CHECKS): check-%: $(BIN)/tests/%
+ $<
+
$(STRATEGY_CHECKS): check-%: $(BIN)/bfs $(BIN)/tests/mksock $(BIN)/tests/xtouch
./tests/tests.sh --bfs="$(BIN)/bfs -S $*" $(TEST_FLAGS)
-check-trie check-xtimegm: check-%: $(BIN)/tests/%
- $<
-
+$(BIN)/tests/bfstd: $(OBJ)/tests/bfstd.o $(LIBBFS)
$(BIN)/tests/mksock: $(OBJ)/tests/mksock.o $(LIBBFS)
$(BIN)/tests/trie: $(OBJ)/tests/trie.o $(LIBBFS)
$(BIN)/tests/xtimegm: $(OBJ)/tests/xtimegm.o $(LIBBFS)
diff --git a/src/bfstd.c b/src/bfstd.c
index 1561796..3a37250 100644
--- a/src/bfstd.c
+++ b/src/bfstd.c
@@ -45,17 +45,52 @@ bool is_nonexistence_error(int error) {
return error == ENOENT || errno == ENOTDIR;
}
-const char *xbasename(const char *path) {
- const char *i;
+char *xdirname(const char *path) {
+ size_t i = xbaseoff(path);
// Skip trailing slashes
- for (i = path + strlen(path); i > path && i[-1] == '/'; --i);
+ while (i > 0 && path[i - 1] == '/') {
+ --i;
+ }
+
+ if (i > 0) {
+ return strndup(path, i);
+ } else if (path[i] == '/') {
+ return strdup("/");
+ } else {
+ return strdup(".");
+ }
+}
+
+char *xbasename(const char *path) {
+ size_t i = xbaseoff(path);
+ size_t len = strcspn(path + i, "/");
+ if (len > 0) {
+ return strndup(path + i, len);
+ } else if (path[i] == '/') {
+ return strdup("/");
+ } else {
+ return strdup(".");
+ }
+}
+
+size_t xbaseoff(const char *path) {
+ size_t i = strlen(path);
+
+ // Skip trailing slashes
+ while (i > 0 && path[i - 1] == '/') {
+ --i;
+ }
// Find the beginning of the name
- for (; i > path && i[-1] != '/'; --i);
+ while (i > 0 && path[i - 1] != '/') {
+ --i;
+ }
// Skip leading slashes
- for (; i[0] == '/' && i[1]; ++i);
+ while (path[i] == '/' && path[i + 1]) {
+ ++i;
+ }
return i;
}
diff --git a/src/bfstd.h b/src/bfstd.h
index 6bf6ec8..d46fa02 100644
--- a/src/bfstd.h
+++ b/src/bfstd.h
@@ -22,6 +22,7 @@
#define BFS_BFSTD_H
#include <stdbool.h>
+#include <stddef.h>
// #include <errno.h>
@@ -45,13 +46,34 @@ bool is_nonexistence_error(int error);
// #include <libgen.h>
/**
- * basename() variant that doesn't modify the input.
+ * Re-entrant dirname() variant that always allocates a copy.
*
* @param path
* The path in question.
- * @return A pointer into path at the base name offset.
+ * @return
+ * The parent directory of the path.
+ */
+char *xdirname(const char *path);
+
+/**
+ * Re-entrant basename() variant that always allocates a copy.
+ *
+ * @param path
+ * The path in question.
+ * @return
+ * The final component of the path.
+ */
+char *xbasename(const char *path);
+
+/**
+ * Find the offset of the final component of a path.
+ *
+ * @param path
+ * The path in question.
+ * @return
+ * The offset of the basename.
*/
-const char *xbasename(const char *path);
+size_t xbaseoff(const char *path);
#include <stdio.h>
diff --git a/src/bftw.c b/src/bftw.c
index 8c88101..5f3ebde 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -793,7 +793,7 @@ static void bftw_init_ftwbuf(struct bftw_state *state, enum bftw_visit visit) {
if (ftwbuf->depth == 0) {
// Compute the name offset for root paths like "foo/bar"
- ftwbuf->nameoff = xbasename(ftwbuf->path) - ftwbuf->path;
+ ftwbuf->nameoff = xbaseoff(ftwbuf->path);
}
if (ftwbuf->error != 0) {
diff --git a/src/color.c b/src/color.c
index cc37e96..7c16ec5 100644
--- a/src/color.c
+++ b/src/color.c
@@ -809,7 +809,7 @@ static int print_path_colored(CFILE *cfile, const char *path, const struct BFTW
if (path == ftwbuf->path) {
nameoff = ftwbuf->nameoff;
} else {
- nameoff = xbasename(path) - path;
+ nameoff = xbaseoff(path);
}
if (print_dirs_colored(cfile, path, ftwbuf, flags, nameoff) != 0) {
diff --git a/src/diag.c b/src/diag.c
index a0c11f2..b02473a 100644
--- a/src/diag.c
+++ b/src/diag.c
@@ -84,13 +84,18 @@ bool bfs_vdebug(const struct bfs_ctx *ctx, enum debug_flags flag, const char *fo
}
}
+/** Get the command name without any leading directories. */
+static const char *bfs_cmd(const struct bfs_ctx *ctx) {
+ return ctx->argv[0] + xbaseoff(ctx->argv[0]);
+}
+
void bfs_error_prefix(const struct bfs_ctx *ctx) {
- cfprintf(ctx->cerr, "${bld}%s:${rs} ${err}error:${rs} ", xbasename(ctx->argv[0]));
+ cfprintf(ctx->cerr, "${bld}%s:${rs} ${err}error:${rs} ", bfs_cmd(ctx));
}
bool bfs_warning_prefix(const struct bfs_ctx *ctx) {
if (ctx->warn) {
- cfprintf(ctx->cerr, "${bld}%s:${rs} ${wrn}warning:${rs} ", xbasename(ctx->argv[0]));
+ cfprintf(ctx->cerr, "${bld}%s:${rs} ${wrn}warning:${rs} ", bfs_cmd(ctx));
return true;
} else {
return false;
@@ -99,7 +104,7 @@ bool bfs_warning_prefix(const struct bfs_ctx *ctx) {
bool bfs_debug_prefix(const struct bfs_ctx *ctx, enum debug_flags flag) {
if (ctx->debug & flag) {
- cfprintf(ctx->cerr, "${bld}%s:${rs} ${cyn}-D %s${rs}: ", xbasename(ctx->argv[0]), debug_flag_name(flag));
+ cfprintf(ctx->cerr, "${bld}%s:${rs} ${cyn}-D %s${rs}: ", bfs_cmd(ctx), debug_flag_name(flag));
return true;
} else {
return false;
diff --git a/src/eval.c b/src/eval.c
index 89591b2..32b2e0e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -590,15 +590,7 @@ bool eval_name(const struct bfs_expr *expr, struct bfs_eval *state) {
if (ftwbuf->depth == 0) {
// Any trailing slashes are not part of the name. This can only
// happen for the root path.
- const char *slash = strchr(name, '/');
- if (slash && slash > name) {
- copy = strndup(name, slash - name);
- if (!copy) {
- eval_report_error(state);
- return false;
- }
- name = copy;
- }
+ name = copy = xbasename(name);
}
bool ret = fnmatch(expr->argv[1], name, expr->num) == 0;
diff --git a/src/exec.c b/src/exec.c
index a1cbde1..8630469 100644
--- a/src/exec.c
+++ b/src/exec.c
@@ -295,7 +295,7 @@ static int bfs_exec_openwd(struct bfs_exec *execbuf, const struct BFTW *ftwbuf)
if (ftwbuf->at_fd != AT_FDCWD) {
// Rely on at_fd being the immediate parent
- assert(ftwbuf->at_path == xbasename(ftwbuf->at_path));
+ assert(xbaseoff(ftwbuf->at_path) == 0);
execbuf->wd_fd = ftwbuf->at_fd;
if (!(execbuf->flags & BFS_EXEC_MULTI)) {
diff --git a/src/mtab.c b/src/mtab.c
index 316ec6e..39676e5 100644
--- a/src/mtab.c
+++ b/src/mtab.c
@@ -86,7 +86,8 @@ static int bfs_mtab_add(struct bfs_mtab *mtab, const char *path, const char *typ
goto fail_entry;
}
- if (!trie_insert_str(&mtab->names, xbasename(path))) {
+ const char *name = path + xbaseoff(path);
+ if (!trie_insert_str(&mtab->names, name)) {
goto fail;
}
@@ -223,7 +224,7 @@ const char *bfs_fstype(const struct bfs_mtab *mtab, const struct bfs_stat *statb
}
bool bfs_might_be_mount(const struct bfs_mtab *mtab, const char *path) {
- const char *name = xbasename(path);
+ const char *name = path + xbaseoff(path);
return trie_find_str(&mtab->names, name);
}
diff --git a/src/parse.c b/src/parse.c
index ad32714..51a9d0a 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -2888,7 +2888,8 @@ static CFILE *launch_pager(pid_t *pid, CFILE *cout) {
NULL,
};
- if (strcmp(xbasename(exe), "less") == 0) {
+ const char *cmd = exe + xbaseoff(exe);
+ if (strcmp(cmd, "less") == 0) {
// We know less supports colors, other pagers may not
ret->colors = cout->colors;
argv[1] = "-FKRX";
@@ -3931,7 +3932,8 @@ struct bfs_ctx *bfs_parse_cmdline(int argc, char *argv[]) {
.now = ctx->now,
};
- if (strcmp(xbasename(state.command), "find") == 0) {
+ const char *cmd = state.command + xbaseoff(state.command);
+ if (strcmp(cmd, "find") == 0) {
// Operate depth-first when invoked as "find"
ctx->strategy = BFTW_DFS;
}
diff --git a/tests/bfstd.c b/tests/bfstd.c
new file mode 100644
index 0000000..4a8181b
--- /dev/null
+++ b/tests/bfstd.c
@@ -0,0 +1,57 @@
+/****************************************************************************
+ * bfs *
+ * Copyright (C) 2022 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * Permission to use, copy, modify, and/or distribute this software for any *
+ * purpose with or without fee is hereby granted. *
+ * *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES *
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF *
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR *
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES *
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN *
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF *
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
+ ****************************************************************************/
+
+#include "../src/bfstd.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/** Check the result of xdirname()/xbasename(). */
+static void check_base_dir(const char *path, const char *dir, const char *base) {
+ char *xdir = xdirname(path);
+ if (!xdir) {
+ perror("xdirname()");
+ abort();
+ } else if (strcmp(xdir, dir) != 0) {
+ fprintf(stderr, "xdirname(\"%s\") == \"%s\" (!= \"%s\")\n", path, xdir, dir);
+ abort();
+ }
+ free(xdir);
+
+ char *xbase = xbasename(path);
+ if (!xbase) {
+ perror("xbasename()");
+ abort();
+ } else if (strcmp(xbase, base) != 0) {
+ fprintf(stderr, "xbasename(\"%s\") == \"%s\" (!= \"%s\")\n", path, xbase, base);
+ abort();
+ }
+ free(xbase);
+}
+
+int main(void) {
+ // From man 3p basename
+ check_base_dir("usr", ".", "usr");
+ check_base_dir("usr/", ".", "usr");
+ check_base_dir("", ".", ".");
+ check_base_dir("/", "/", "/");
+ // check_base_dir("//", "/" or "//", "/" or "//");
+ check_base_dir("///", "/", "/");
+ check_base_dir("/usr/", "/", "usr");
+ check_base_dir("/usr/lib", "/usr", "lib");
+ check_base_dir("//usr//lib//", "//usr", "lib");
+ check_base_dir("/home//dwc//test", "/home//dwc", "test");
+}
diff --git a/tests/mksock.c b/tests/mksock.c
index d1776b3..5068bc8 100644
--- a/tests/mksock.c
+++ b/tests/mksock.c
@@ -19,8 +19,8 @@
* program does the job.
*/
+#include "../src/bfstd.h"
#include <errno.h>
-#include <libgen.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -41,18 +41,13 @@ static void errmsg(const char *cmd, const char *path) {
* file name is not.
*/
static int chdir_parent(const char *path) {
- char *copy = strdup(path);
- if (!copy) {
+ char *dir = xdirname(path);
+ if (!dir) {
return -1;
}
- const char *dir = dirname(copy);
int ret = chdir(dir);
-
- int error = errno;
- free(copy);
- errno = error;
-
+ free(dir);
return ret;
}
@@ -66,22 +61,21 @@ static int init_sun(struct sockaddr_un *sock, const char *path) {
return -1;
}
- char *copy = strdup(path);
- if (!copy) {
+ char *base = xbasename(path);
+ if (!base) {
return -1;
}
- const char *base = basename(copy);
len = strlen(base);
if (len >= sizeof(sock->sun_path)) {
- free(copy);
+ free(base);
errno = ENAMETOOLONG;
return -1;
}
sock->sun_family = AF_UNIX;
memcpy(sock->sun_path, base, len + 1);
- free(copy);
+ free(base);
return 0;
}
diff --git a/tests/xtouch.c b/tests/xtouch.c
index 9a91ec7..262fc33 100644
--- a/tests/xtouch.c
+++ b/tests/xtouch.c
@@ -14,7 +14,6 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
****************************************************************************/
-#include "../src/bfstd.h"
#include "../src/xtime.h"
#include <errno.h>
#include <fcntl.h>