1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-12-24 21:34:08 +03:00

Merge pull request #20962 from poettering/dttoif

Some tweaks to dirent-util.c
This commit is contained in:
Lennart Poettering 2021-10-08 11:14:03 +02:00 committed by GitHub
commit c17e8ce9ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 44 additions and 33 deletions

View File

@ -5,22 +5,12 @@
#include "dirent-util.h" #include "dirent-util.h"
#include "path-util.h" #include "path-util.h"
#include "stat-util.h"
#include "string-util.h" #include "string-util.h"
int stat_mode_to_dirent_type(mode_t mode) {
return
S_ISREG(mode) ? DT_REG :
S_ISDIR(mode) ? DT_DIR :
S_ISLNK(mode) ? DT_LNK :
S_ISFIFO(mode) ? DT_FIFO :
S_ISSOCK(mode) ? DT_SOCK :
S_ISCHR(mode) ? DT_CHR :
S_ISBLK(mode) ? DT_BLK :
DT_UNKNOWN;
}
static int dirent_ensure_type(DIR *d, struct dirent *de) { static int dirent_ensure_type(DIR *d, struct dirent *de) {
struct stat st; STRUCT_STATX_DEFINE(sx);
int r;
assert(d); assert(d);
assert(de); assert(de);
@ -33,10 +23,17 @@ static int dirent_ensure_type(DIR *d, struct dirent *de) {
return 0; return 0;
} }
if (fstatat(dirfd(d), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) /* Let's ask only for the type, nothing else. */
return -errno; r = statx_fallback(dirfd(d), de->d_name, AT_SYMLINK_NOFOLLOW|AT_NO_AUTOMOUNT, STATX_TYPE, &sx);
if (r < 0)
return r;
de->d_type = stat_mode_to_dirent_type(st.st_mode); assert(FLAGS_SET(sx.stx_mask, STATX_TYPE));
de->d_type = IFTODT(sx.stx_mode);
/* If the inode is passed too, update the field, i.e. report most recent data */
if (FLAGS_SET(sx.stx_mask, STATX_INO))
de->d_ino = sx.stx_ino;
return 0; return 0;
} }
@ -69,24 +66,40 @@ bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) {
} }
struct dirent *readdir_ensure_type(DIR *d) { struct dirent *readdir_ensure_type(DIR *d) {
struct dirent *de; int r;
assert(d); assert(d);
errno = 0; /* Like readdir(), but fills in .d_type if it is DT_UNKNOWN */
de = readdir(d);
if (de)
(void) dirent_ensure_type(d, de);
return de;
}
struct dirent *readdir_no_dot(DIR *dirp) {
struct dirent *d;
for (;;) { for (;;) {
d = readdir_ensure_type(dirp); struct dirent *de;
if (d && dot_or_dot_dot(d->d_name))
continue; errno = 0;
return d; de = readdir(d);
if (!de)
return NULL;
r = dirent_ensure_type(d, de);
if (r >= 0)
return de;
if (r != -ENOENT) {
errno = -r; /* We want to be compatible with readdir(), hence propagate error via errno here */
return NULL;
}
/* Vanished by now? Then skip immedately to next */
}
}
struct dirent *readdir_no_dot(DIR *d) {
assert(d);
for (;;) {
struct dirent *de;
de = readdir_ensure_type(d);
if (!de || !dot_or_dot_dot(de->d_name))
return de;
} }
} }

View File

@ -8,8 +8,6 @@
#include "macro.h" #include "macro.h"
#include "path-util.h" #include "path-util.h"
int stat_mode_to_dirent_type(mode_t mode);
bool dirent_is_file(const struct dirent *de) _pure_; bool dirent_is_file(const struct dirent *de) _pure_;
bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_; bool dirent_is_file_with_suffix(const struct dirent *de, const char *suffix) _pure_;

View File

@ -290,7 +290,7 @@ int recurse_dir(
/* Copy over the data we acquired through statx() if we acquired any */ /* Copy over the data we acquired through statx() if we acquired any */
if (sx.stx_mask & STATX_TYPE) { if (sx.stx_mask & STATX_TYPE) {
assert(!!subdir == !!S_ISDIR(sx.stx_mode)); assert(!!subdir == !!S_ISDIR(sx.stx_mode));
de[i]->d_type = stat_mode_to_dirent_type(sx.stx_mode); de[i]->d_type = IFTODT(sx.stx_mode);
} }
if (sx.stx_mask & STATX_INO) if (sx.stx_mask & STATX_INO)