diff options
Diffstat (limited to 'dir.c')
| -rw-r--r-- | dir.c | 65 |
1 files changed, 51 insertions, 14 deletions
@@ -30,6 +30,7 @@ #include "read-cache-ll.h" #include "setup.h" #include "sparse-index.h" +#include "strbuf.h" #include "submodule-config.h" #include "symlinks.h" #include "trace2.h" @@ -87,6 +88,33 @@ struct dirent *readdir_skip_dot_and_dotdot(DIR *dirp) return e; } +int for_each_file_in_dir(struct strbuf *path, file_iterator fn, const void *data) +{ + struct dirent *e; + int res = 0; + size_t baselen = path->len; + DIR *dir = opendir(path->buf); + + if (!dir) + return 0; + + while (!res && (e = readdir_skip_dot_and_dotdot(dir)) != NULL) { + unsigned char dtype = get_dtype(e, path, 0); + strbuf_setlen(path, baselen); + strbuf_addstr(path, e->d_name); + + if (dtype == DT_REG) { + res = fn(path->buf, data); + } else if (dtype == DT_DIR) { + strbuf_addch(path, '/'); + res = for_each_file_in_dir(path, fn, data); + } + } + + closedir(dir); + return res; +} + int count_slashes(const char *s) { int cnt = 0; @@ -277,7 +305,7 @@ int within_depth(const char *name, int namelen, if (depth > max_depth) return 0; } - return 1; + return depth <= max_depth; } /* @@ -1360,18 +1388,25 @@ int match_pathname(const char *pathname, int pathlen, if (fspathncmp(pattern, name, prefix)) return 0; - pattern += prefix; - patternlen -= prefix; - name += prefix; - namelen -= prefix; /* * If the whole pattern did not have a wildcard, * then our prefix match is all we need; we * do not need to call fnmatch at all. */ - if (!patternlen && !namelen) + if (patternlen == prefix && namelen == prefix) return 1; + + /* + * Retain one character of the prefix to + * pass to fnmatch, which lets it distinguish + * the start of a directory component correctly. + */ + prefix--; + pattern += prefix; + patternlen -= prefix; + name += prefix; + namelen -= prefix; } return fnmatch_icase_mem(pattern, patternlen, @@ -3579,7 +3614,8 @@ static void write_one_dir(struct untracked_cache_dir *untracked, struct stat_data stat_data; struct strbuf *out = &wd->out; unsigned char intbuf[16]; - unsigned int intlen, value; + unsigned int value; + uint8_t intlen; int i = wd->index++; /* @@ -3632,7 +3668,7 @@ void write_untracked_extension(struct strbuf *out, struct untracked_cache *untra struct ondisk_untracked_cache *ouc; struct write_data wd; unsigned char varbuf[16]; - int varint_len; + uint8_t varint_len; const unsigned hashsz = the_hash_algo->rawsz; CALLOC_ARRAY(ouc, 1); @@ -3738,7 +3774,7 @@ static int read_one_dir(struct untracked_cache_dir **untracked_, struct untracked_cache_dir ud, *untracked; const unsigned char *data = rd->data, *end = rd->end; const unsigned char *eos; - unsigned int value; + uint64_t value; int i; memset(&ud, 0, sizeof(ud)); @@ -3830,7 +3866,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long struct read_data rd; const unsigned char *next = data, *end = (const unsigned char *)data + sz; const char *ident; - int ident_len; + uint64_t ident_len; + uint64_t varint_len; ssize_t len; const char *exclude_per_dir; const unsigned hashsz = the_hash_algo->rawsz; @@ -3867,8 +3904,8 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long if (next >= end) goto done2; - len = decode_varint(&next); - if (next > end || len == 0) + varint_len = decode_varint(&next); + if (next > end || varint_len == 0) goto done2; rd.valid = ewah_new(); @@ -3877,9 +3914,9 @@ struct untracked_cache *read_untracked_extension(const void *data, unsigned long rd.data = next; rd.end = end; rd.index = 0; - ALLOC_ARRAY(rd.ucd, len); + ALLOC_ARRAY(rd.ucd, varint_len); - if (read_one_dir(&uc->root, &rd) || rd.index != len) + if (read_one_dir(&uc->root, &rd) || rd.index != varint_len) goto done; next = rd.data; |
