summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dir.c47
-rw-r--r--dir.h2
2 files changed, 29 insertions, 20 deletions
diff --git a/dir.c b/dir.c
index 3068ca809a..fcb68729b1 100644
--- a/dir.c
+++ b/dir.c
@@ -799,12 +799,12 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
*/
while ((stk = dir->exclude_stack) != NULL) {
if (stk->baselen <= baselen &&
- !strncmp(dir->basebuf, base, stk->baselen))
+ !strncmp(dir->basebuf.buf, base, stk->baselen))
break;
el = &group->el[dir->exclude_stack->exclude_ix];
dir->exclude_stack = stk->prev;
dir->exclude = NULL;
- free((char *)el->src); /* see strdup() below */
+ free((char *)el->src); /* see strbuf_detach() below */
clear_exclude_list(el);
free(stk);
group->nr--;
@@ -814,8 +814,17 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
if (dir->exclude)
return;
+ /*
+ * Lazy initialization. All call sites currently just
+ * memset(dir, 0, sizeof(*dir)) before use. Changing all of
+ * them seems lots of work for little benefit.
+ */
+ if (!dir->basebuf.buf)
+ strbuf_init(&dir->basebuf, PATH_MAX);
+
/* Read from the parent directories and push them down. */
current = stk ? stk->baselen : -1;
+ strbuf_setlen(&dir->basebuf, current < 0 ? 0 : current);
while (current < baselen) {
struct exclude_stack *stk = xcalloc(1, sizeof(*stk));
const char *cp;
@@ -833,48 +842,47 @@ static void prep_exclude(struct dir_struct *dir, const char *base, int baselen)
stk->baselen = cp - base;
stk->exclude_ix = group->nr;
el = add_exclude_list(dir, EXC_DIRS, NULL);
- memcpy(dir->basebuf + current, base + current,
- stk->baselen - current);
+ strbuf_add(&dir->basebuf, base + current, stk->baselen - current);
+ assert(stk->baselen == dir->basebuf.len);
/* Abort if the directory is excluded */
if (stk->baselen) {
int dt = DT_DIR;
- dir->basebuf[stk->baselen - 1] = 0;
+ dir->basebuf.buf[stk->baselen - 1] = 0;
dir->exclude = last_exclude_matching_from_lists(dir,
- dir->basebuf, stk->baselen - 1,
- dir->basebuf + current, &dt);
- dir->basebuf[stk->baselen - 1] = '/';
+ dir->basebuf.buf, stk->baselen - 1,
+ dir->basebuf.buf + current, &dt);
+ dir->basebuf.buf[stk->baselen - 1] = '/';
if (dir->exclude &&
dir->exclude->flags & EXC_FLAG_NEGATIVE)
dir->exclude = NULL;
if (dir->exclude) {
- dir->basebuf[stk->baselen] = 0;
dir->exclude_stack = stk;
return;
}
}
- /* Try to read per-directory file unless path is too long */
- if (dir->exclude_per_dir &&
- stk->baselen + strlen(dir->exclude_per_dir) < PATH_MAX) {
- strcpy(dir->basebuf + stk->baselen,
- dir->exclude_per_dir);
+ /* Try to read per-directory file */
+ if (dir->exclude_per_dir) {
/*
* dir->basebuf gets reused by the traversal, but we
* need fname to remain unchanged to ensure the src
* member of each struct exclude correctly
* back-references its source file. Other invocations
* of add_exclude_list provide stable strings, so we
- * strdup() and free() here in the caller.
+ * strbuf_detach() and free() here in the caller.
*/
- el->src = strdup(dir->basebuf);
- add_excludes_from_file_to_list(dir->basebuf,
- dir->basebuf, stk->baselen, el, 1);
+ struct strbuf sb = STRBUF_INIT;
+ strbuf_addbuf(&sb, &dir->basebuf);
+ strbuf_addstr(&sb, dir->exclude_per_dir);
+ el->src = strbuf_detach(&sb, NULL);
+ add_excludes_from_file_to_list(el->src, el->src,
+ stk->baselen, el, 1);
}
dir->exclude_stack = stk;
current = stk->baselen;
}
- dir->basebuf[baselen] = '\0';
+ strbuf_setlen(&dir->basebuf, baselen);
}
/*
@@ -1671,4 +1679,5 @@ void clear_directory(struct dir_struct *dir)
free(stk);
stk = prev;
}
+ strbuf_release(&dir->basebuf);
}
diff --git a/dir.h b/dir.h
index 02e371090b..6c45e9d4b9 100644
--- a/dir.h
+++ b/dir.h
@@ -119,7 +119,7 @@ struct dir_struct {
*/
struct exclude_stack *exclude_stack;
struct exclude *exclude;
- char basebuf[PATH_MAX];
+ struct strbuf basebuf;
};
/*