summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2019-04-07 08:12:15 -0400
committerTavian Barnes <tavianator@tavianator.com>2019-04-07 08:13:05 -0400
commit60020d1f52d032c495785802c44226a63a217737 (patch)
tree3595b22d873dc525543c80d1de0c9467e23de890
parentf301f9cb4d1300724af98d47594c465599aaa749 (diff)
downloadbfs-60020d1f52d032c495785802c44226a63a217737.tar.xz
bftw: Don't store trailing slashes in bftw_file names
-rw-r--r--bftw.c49
1 files changed, 23 insertions, 26 deletions
diff --git a/bftw.c b/bftw.c
index 717ffab..aee3689 100644
--- a/bftw.c
+++ b/bftw.c
@@ -281,17 +281,19 @@ static int bftw_cache_shrink(struct bftw_cache *cache, const struct bftw_file *s
return ret;
}
+/** Compute the name offset of a child path. */
+static size_t bftw_child_nameoff(const struct bftw_file *parent) {
+ size_t ret = parent->nameoff + parent->namelen;
+ if (parent->name[parent->namelen - 1] != '/') {
+ ++ret;
+ }
+ return ret;
+}
+
/** Create a new bftw_file. */
static struct bftw_file *bftw_file_new(struct bftw_cache *cache, struct bftw_file *parent, const char *name) {
size_t namelen = strlen(name);
size_t size = sizeof(struct bftw_file) + namelen + 1;
-
- bool needs_slash = false;
- if (namelen == 0 || name[namelen - 1] != '/') {
- needs_slash = true;
- ++size;
- }
-
struct bftw_file *file = malloc(size);
if (!file) {
return NULL;
@@ -301,7 +303,7 @@ static struct bftw_file *bftw_file_new(struct bftw_cache *cache, struct bftw_fil
if (parent) {
file->depth = parent->depth + 1;
- file->nameoff = parent->nameoff + parent->namelen;
+ file->nameoff = bftw_child_nameoff(parent);
bftw_file_incref(cache, parent);
} else {
file->depth = 0;
@@ -316,12 +318,8 @@ static struct bftw_file *bftw_file_new(struct bftw_cache *cache, struct bftw_fil
file->dev = -1;
file->ino = -1;
- memcpy(file->name, name, namelen);
- if (needs_slash) {
- file->name[namelen++] = '/';
- }
- file->name[namelen] = '\0';
file->namelen = namelen;
+ memcpy(file->name, name, namelen + 1);
return file;
}
@@ -338,6 +336,9 @@ static int bftw_file_path(const struct bftw_file *file, char **path) {
// Build the path backwards
while (file) {
+ if (file->nameoff > 0) {
+ dest[file->nameoff - 1] = '/';
+ }
memcpy(dest + file->nameoff, file->name, file->namelen);
file = file->parent;
}
@@ -365,7 +366,7 @@ static struct bftw_file *bftw_file_base(struct bftw_file *file, int *at_fd, cons
if (base) {
*at_fd = base->fd;
- *at_path += base->nameoff + base->namelen;
+ *at_path += bftw_child_nameoff(base);
}
return base;
@@ -839,16 +840,7 @@ static int bftw_update_path(struct bftw_state *state) {
struct bftw_file *file = reader->file;
struct dirent *de = reader->de;
- size_t length;
- if (de) {
- length = file->nameoff + file->namelen;
- } else if (file->depth == 0) {
- // Use exactly the string passed to bftw(), including any trailing slashes
- length = strlen(state->root);
- } else {
- // -1 to trim the trailing slash
- length = file->nameoff + file->namelen - 1;
- }
+ size_t length = file->nameoff + file->namelen;
if (dstrlen(reader->path) < length) {
errno = reader->error;
@@ -857,6 +849,11 @@ static int bftw_update_path(struct bftw_state *state) {
dstresize(&reader->path, length);
if (de) {
+ if (reader->path[length - 1] != '/') {
+ if (dstrapp(&reader->path, '/') != 0) {
+ return -1;
+ }
+ }
if (dstrcat(&reader->path, reader->de->d_name) != 0) {
return -1;
}
@@ -920,16 +917,16 @@ static void bftw_prepare_visit(struct bftw_state *state) {
ftwbuf->at_flags = AT_SYMLINK_NOFOLLOW;
if (file) {
- ftwbuf->nameoff = file->nameoff;
ftwbuf->depth = file->depth;
if (de) {
- ftwbuf->nameoff += file->namelen;
+ ftwbuf->nameoff = bftw_child_nameoff(file);
++ftwbuf->depth;
ftwbuf->at_fd = file->fd;
ftwbuf->at_path += ftwbuf->nameoff;
} else {
+ ftwbuf->nameoff = file->nameoff;
bftw_file_base(file, &ftwbuf->at_fd, &ftwbuf->at_path);
}
}