diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2019-04-07 08:12:15 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2019-04-07 08:13:05 -0400 |
commit | 60020d1f52d032c495785802c44226a63a217737 (patch) | |
tree | 3595b22d873dc525543c80d1de0c9467e23de890 | |
parent | f301f9cb4d1300724af98d47594c465599aaa749 (diff) | |
download | bfs-60020d1f52d032c495785802c44226a63a217737.tar.xz |
bftw: Don't store trailing slashes in bftw_file names
-rw-r--r-- | bftw.c | 49 |
1 files changed, 23 insertions, 26 deletions
@@ -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); } } |