summaryrefslogtreecommitdiffstats
path: root/src
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 /src
parent944cd72f40a84d318453c320a84d443273956859 (diff)
downloadbfs-683552c4c9a3dfee4ce603157bb2cf18d64fbcfc.tar.xz
bfstd: New wrappers for dirname()/basename()
Diffstat (limited to 'src')
-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
9 files changed, 84 insertions, 27 deletions
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;
}