diff options
author | Tom Smeding <tom@tomsmeding.com> | 2025-03-10 18:59:40 +0100 |
---|---|---|
committer | Tom Smeding <tom@tomsmeding.com> | 2025-03-10 18:59:40 +0100 |
commit | d1c85b546ae8f8ceaf9ba5962a36f6b6bae5a0a7 (patch) | |
tree | b54168119975df694aacabbacd079a92c7383084 | |
parent | 39148b1b6dc6c7a10f7e713ece084b6d5cf27537 (diff) |
-rw-r--r-- | main.c | 40 | ||||
-rw-r--r-- | options.c | 16 | ||||
-rw-r--r-- | options.h | 1 | ||||
-rw-r--r-- | string.h | 2 |
4 files changed, 55 insertions, 4 deletions
@@ -242,14 +242,46 @@ static struct tree_node* make_dir_tree(const struct options *opts, struct string return result; } -static struct tree_node* make_dir_tree_root(const struct options *opts, const char *rootpath) { - int fd = open(rootpath, O_DIRECTORY); +static struct tree_node* make_dir_tree_root(const struct options *opts, const char *rootpath, const char *treeroot) { + // If the first character is a /, keep it + size_t rootpath_len = strlen(rootpath); + while (rootpath_len > 1 && rootpath[rootpath_len - 1] == '/') rootpath_len--; + + // But not in the tree root + size_t treeroot_len = treeroot != NULL ? strlen(treeroot) : 0; + while (treeroot_len > 0 && treeroot[treeroot_len - 1] == '/') treeroot_len--; + + if (treeroot_len > 0 && treeroot[0] == '/') { + fprintf(stderr, "Tree root is not a relative path\n"); + exit(1); + } + + char *pathbuf = malloc(rootpath_len + 1 + treeroot_len + 1); + size_t pathbuf_len = rootpath_len; + strcpy(pathbuf, rootpath); + if (treeroot) { + pathbuf[pathbuf_len++] = '/'; + strcpy(pathbuf + pathbuf_len, treeroot); + pathbuf_len += treeroot_len; + } + + if (opts->debug) { + fprintf(stderr, "Expanding from path <%s>\n", pathbuf); + } + + int fd = open(pathbuf, O_DIRECTORY); if (fd < 0) { perror("open"); exit(1); } - struct string s = string_make(""); + struct string s = string_make(treeroot_len > 0 ? pathbuf + rootpath_len+1 : ""); + + if (opts->debug) { + fprintf(stderr, "Virtual start path <%s>\n", string_read(s)); + } + + free(pathbuf); bool was_cache_dir = false; struct tree_node *tree = make_dir_tree(opts, &s, fd, &was_cache_dir); @@ -300,7 +332,7 @@ int main(int argc, char **argv) { } } - struct tree_node *root = make_dir_tree_root(&opts, opts.rootpath); + struct tree_node *root = make_dir_tree_root(&opts, opts.rootpath, opts.treeroot); printf("files=%zu dirs=%zu size=%zu\n", root->total_files, root->total_dirs, root->total_size); @@ -12,6 +12,7 @@ struct options parse_options(int argc, char **argv) { char **cachetags = malloc(cachetags_cap * sizeof(char*)); char *rootpath = NULL; + char *treeroot = NULL; int print_depth = 1; @@ -25,6 +26,20 @@ struct options parse_options(int argc, char **argv) { } rootpath = strdup(argv[i]); + } else if (strcmp(argv[i], "--treeroot") == 0) { + if (i + 1 >= argc) { + fprintf(stderr, "'--treeroot' takes an argument\n"); + exit(1); + } + + if (treeroot) { + fprintf(stderr, "Multiple tree roots given\n"); + exit(1); + } + treeroot = strdup(argv[i+1]); + + i++; + } else if (strcmp(argv[i], "--exclude") == 0) { if (i + 1 >= argc) { fprintf(stderr, "'--exclude' takes an argument\n"); @@ -89,6 +104,7 @@ struct options parse_options(int argc, char **argv) { .ncachetags = cachetags_len, .cachetags = cachetags, .rootpath = rootpath, + .treeroot = treeroot, .print_depth = print_depth, .debug = debug, }; @@ -13,6 +13,7 @@ struct options { char **cachetags; char *rootpath; + char *treeroot; // relative within rootpath (or NULL) int print_depth; @@ -1,5 +1,7 @@ #pragma once +#include <stddef.h> + struct string { size_t len, cap; |