summaryrefslogtreecommitdiff
path: root/dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'dir.c')
-rw-r--r--dir.c65
1 files changed, 51 insertions, 14 deletions
diff --git a/dir.c b/dir.c
index dfb4d40103..b00821f294 100644
--- a/dir.c
+++ b/dir.c
@@ -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;