summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c40
-rw-r--r--options.c16
-rw-r--r--options.h1
-rw-r--r--string.h2
4 files changed, 55 insertions, 4 deletions
diff --git a/main.c b/main.c
index a326c2b..997dfe9 100644
--- a/main.c
+++ b/main.c
@@ -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);
diff --git a/options.c b/options.c
index 2619602..6d43ccb 100644
--- a/options.c
+++ b/options.c
@@ -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,
};
diff --git a/options.h b/options.h
index f015c33..402e492 100644
--- a/options.h
+++ b/options.h
@@ -13,6 +13,7 @@ struct options {
char **cachetags;
char *rootpath;
+ char *treeroot; // relative within rootpath (or NULL)
int print_depth;
diff --git a/string.h b/string.h
index ecb49b6..c2036a8 100644
--- a/string.h
+++ b/string.h
@@ -1,5 +1,7 @@
#pragma once
+#include <stddef.h>
+
struct string {
size_t len, cap;