dir: restructure in a way to avoid passing around a struct dirent
Restructure the code slightly to avoid passing around a struct dirent anywhere, which also enables us to avoid trying to manufacture one. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Elijah Newren <newren@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Jeff King committed
Jan 16, 2020 at 20:21 UTC
ad6f2157f951dc2ffeb7a01f090686f0bbb06f7a
1 file changed
+31
-42
dir.c
+31
-42
@@ -41,7 +41,8 @@ struct cached_dir {
41
int nr_files;
42
int nr_dirs;
43
44
- struct dirent *de;
44
+ const char *d_name;
45
+ int d_type;
46
const char *file;
47
struct untracked_cache_dir *ucd;
48
};
@@ -50,8 +51,8 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
51
struct index_state *istate, const char *path, int len,
52
struct untracked_cache_dir *untracked,
53
int check_only, int stop_at_first_file, const struct pathspec *pathspec);
53
-static int get_dtype(struct dirent *de, struct index_state *istate,
54
- const char *path, int len);
54
+static int resolve_dtype(int dtype, struct index_state *istate,
55
+ const char *path, int len);
56
57
int count_slashes(const char *s)
58
{
@@ -1215,8 +1216,7 @@ static struct path_pattern *last_matching_pattern_from_list(const char *pathname
1216
int prefix = pattern->nowildcardlen;
1217
1218
if (pattern->flags & PATTERN_FLAG_MUSTBEDIR) {
1218
- if (*dtype == DT_UNKNOWN)
1219
- *dtype = get_dtype(NULL, istate, pathname, pathlen);
1219
+ *dtype = resolve_dtype(*dtype, istate, pathname, pathlen);
1220
if (*dtype != DT_DIR)
1221
continue;
1222
}
@@ -1842,10 +1842,9 @@ static int get_index_dtype(struct index_state *istate,
1842
return DT_UNKNOWN;
1843
}
1844
1845
-static int get_dtype(struct dirent *de, struct index_state *istate,
1846
- const char *path, int len)
1845
+static int resolve_dtype(int dtype, struct index_state *istate,
1846
+ const char *path, int len)
1847
{
1848
- int dtype = de ? DTYPE(de) : DT_UNKNOWN;
1848
struct stat st;
1849
1850
if (dtype != DT_UNKNOWN)
@@ -1870,14 +1869,13 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
1869
struct strbuf *path,
1870
int baselen,
1871
const struct pathspec *pathspec,
1873
- int dtype, struct dirent *de)
1872
+ int dtype)
1873
{
1874
int exclude;
1875
int has_path_in_index = !!index_file_exists(istate, path->buf, path->len, ignore_case);
1876
enum path_treatment path_treatment;
1877
1879
- if (dtype == DT_UNKNOWN)
1880
- dtype = get_dtype(de, istate, path->buf, path->len);
1878
+ dtype = resolve_dtype(dtype, istate, path->buf, path->len);
1879
1880
/* Always exclude indexed files */
1881
if (dtype != DT_DIR && has_path_in_index)
@@ -1985,21 +1983,18 @@ static enum path_treatment treat_path(struct dir_struct *dir,
1983
int baselen,
1984
const struct pathspec *pathspec)
1985
{
1988
- int dtype;
1989
- struct dirent *de = cdir->de;
1990
-
1991
- if (!de)
1986
+ if (!cdir->d_name)
1987
return treat_path_fast(dir, untracked, cdir, istate, path,
1988
baselen, pathspec);
1994
- if (is_dot_or_dotdot(de->d_name) || !fspathcmp(de->d_name, ".git"))
1989
+ if (is_dot_or_dotdot(cdir->d_name) || !fspathcmp(cdir->d_name, ".git"))
1990
return path_none;
1991
strbuf_setlen(path, baselen);
1997
- strbuf_addstr(path, de->d_name);
1992
+ strbuf_addstr(path, cdir->d_name);
1993
if (simplify_away(path->buf, path->len, pathspec))
1994
return path_none;
1995
2001
- dtype = DTYPE(de);
2002
- return treat_one_path(dir, untracked, istate, path, baselen, pathspec, dtype, de);
1996
+ return treat_one_path(dir, untracked, istate, path, baselen, pathspec,
1997
+ cdir->d_type);
1998
}
1999
2000
static void add_untracked(struct untracked_cache_dir *dir, const char *name)
@@ -2087,10 +2082,17 @@ static int open_cached_dir(struct cached_dir *cdir,
2082
2083
static int read_cached_dir(struct cached_dir *cdir)
2084
{
2085
+ struct dirent *de;
2086
+
2087
if (cdir->fdir) {
2091
- cdir->de = readdir(cdir->fdir);
2092
- if (!cdir->de)
2088
+ de = readdir(cdir->fdir);
2089
+ if (!de) {
2090
+ cdir->d_name = NULL;
2091
+ cdir->d_type = DT_UNKNOWN;
2092
return -1;
2093
+ }
2094
+ cdir->d_name = de->d_name;
2095
+ cdir->d_type = DTYPE(de);
2096
return 0;
2097
}
2098
while (cdir->nr_dirs < cdir->untracked->dirs_nr) {
@@ -2216,7 +2218,7 @@ static enum path_treatment read_directory_recursive(struct dir_struct *dir,
2218
/* recurse into subdir if instructed by treat_path */
2219
if ((state == path_recurse) ||
2220
((state == path_untracked) &&
2219
- (get_dtype(cdir.de, istate, path.buf, path.len) == DT_DIR) &&
2221
+ (resolve_dtype(cdir.d_type, istate, path.buf, path.len) == DT_DIR) &&
2222
((dir->flags & DIR_SHOW_IGNORED_TOO) ||
2223
(pathspec &&
2224
do_match_pathspec(istate, pathspec, path.buf, path.len,
@@ -2314,10 +2316,10 @@ static int treat_leading_path(struct dir_struct *dir,
2316
*/
2317
2318
struct strbuf sb = STRBUF_INIT;
2319
+ struct strbuf subdir = STRBUF_INIT;
2320
int prevlen, baselen;
2321
const char *cp;
2322
struct cached_dir cdir;
2320
- struct dirent *de;
2323
enum path_treatment state = path_none;
2324
2325
/*
@@ -2342,22 +2344,8 @@ static int treat_leading_path(struct dir_struct *dir,
2344
if (!len)
2345
return 1;
2346
2345
- /*
2346
- * We need a manufactured dirent with sufficient space to store a
2347
- * leading directory component of path in its d_name. Here, we
2348
- * assume that the dirent's d_name is either declared as
2349
- * char d_name[BIG_ENOUGH]
2350
- * or that it is declared at the end of the struct as
2351
- * char d_name[]
2352
- * For either case, padding with len+1 bytes at the end will ensure
2353
- * sufficient storage space.
2354
- */
2355
- de = xcalloc(1, st_add3(sizeof(struct dirent), len, 1));
2347
memset(&cdir, 0, sizeof(cdir));
2357
- cdir.de = de;
2358
-#if defined(DT_UNKNOWN) && !defined(NO_D_TYPE_IN_DIRENT)
2359
- de->d_type = DT_DIR;
2360
-#endif
2348
+ cdir.d_type = DT_DIR;
2349
baselen = 0;
2350
prevlen = 0;
2351
while (1) {
@@ -2374,12 +2362,13 @@ static int treat_leading_path(struct dir_struct *dir,
2362
break;
2363
strbuf_reset(&sb);
2364
strbuf_add(&sb, path, prevlen);
2377
- memcpy(de->d_name, path+prevlen, baselen-prevlen);
2378
- de->d_name[baselen-prevlen] = '\0';
2365
+ strbuf_reset(&subdir);
2366
+ strbuf_add(&subdir, path+prevlen, baselen-prevlen);
2367
+ cdir.d_name = subdir.buf;
2368
state = treat_path(dir, NULL, &cdir, istate, &sb, prevlen,
2369
pathspec);
2370
if (state == path_untracked &&
2382
- get_dtype(cdir.de, istate, sb.buf, sb.len) == DT_DIR &&
2371
+ resolve_dtype(cdir.d_type, istate, sb.buf, sb.len) == DT_DIR &&
2372
(dir->flags & DIR_SHOW_IGNORED_TOO ||
2373
do_match_pathspec(istate, pathspec, sb.buf, sb.len,
2374
baselen, NULL, DO_MATCH_LEADING_PATHSPEC) == MATCHED_RECURSIVELY_LEADING_PATHSPEC)) {
@@ -2403,7 +2392,7 @@ static int treat_leading_path(struct dir_struct *dir,
2392
&sb, baselen, pathspec,
2393
state);
2394
2406
- free(de);
2395
+ strbuf_release(&subdir);
2396
strbuf_release(&sb);
2397
return state == path_recurse;
2398
}