diff options
author | Victoria Dye <vdye@github.com> | 2023-10-09 23:58:55 +0200 |
---|---|---|
committer | Junio C Hamano <gitster@pobox.com> | 2023-10-10 00:53:13 +0200 |
commit | aa79636fe70247a19648d73e52a7774536100567 (patch) | |
tree | 8c98aea4e38c513512d92fea9e38fbf1f926ed3b /dir.c | |
parent | dir.[ch]: expose 'get_dtype' (diff) | |
download | git-aa79636fe70247a19648d73e52a7774536100567.tar.xz git-aa79636fe70247a19648d73e52a7774536100567.zip |
dir.[ch]: add 'follow_symlink' arg to 'get_dtype'
Add a 'follow_symlink' boolean option to 'get_type()'. If 'follow_symlink'
is enabled, DT_LNK (in addition to DT_UNKNOWN) d_types triggers the
stat-based d_type resolution, using 'stat' instead of 'lstat' to get the
type of the followed symlink. Note that symlinks are not followed
recursively, so a symlink pointing to another symlink will still resolve to
DT_LNK.
Update callers in 'diagnose.c' to specify 'follow_symlink = 0' to preserve
current behavior.
Signed-off-by: Victoria Dye <vdye@github.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Diffstat (limited to 'dir.c')
-rw-r--r-- | dir.c | 13 |
1 files changed, 9 insertions, 4 deletions
@@ -2235,19 +2235,24 @@ static int get_index_dtype(struct index_state *istate, return DT_UNKNOWN; } -unsigned char get_dtype(struct dirent *e, struct strbuf *path) +unsigned char get_dtype(struct dirent *e, struct strbuf *path, + int follow_symlink) { struct stat st; unsigned char dtype = DTYPE(e); size_t base_path_len; - if (dtype != DT_UNKNOWN) + if (dtype != DT_UNKNOWN && !(follow_symlink && dtype == DT_LNK)) return dtype; - /* d_type unknown in dirent, try to fall back on lstat results */ + /* + * d_type unknown or unfollowed symlink, try to fall back on [l]stat + * results. If [l]stat fails, explicitly set DT_UNKNOWN. + */ base_path_len = path->len; strbuf_addstr(path, e->d_name); - if (lstat(path->buf, &st)) + if ((follow_symlink && stat(path->buf, &st)) || + (!follow_symlink && lstat(path->buf, &st))) goto cleanup; /* determine d_type from st_mode */ |