From 485a8bfa98f8d89855b7ae0305e6698048c6f050 Mon Sep 17 00:00:00 2001 From: Masatake YAMATO Date: Thu, 19 Jan 2012 13:16:20 +0900 Subject: libmount: scandirat based mnt_table_parse_dir implementation In comment of `mnt_table_parse_dir' of libmount/src/tab_parse.c: /* TODO: it would be nice to have a scandir() implementation that * is able to use already opened directory */ Nowadays glibc provides `scandirat'. This patch implements `scandirat' based `mnt_table_parse_dir'. Signed-off-by: Masatake YAMATO --- libmount/src/tab_parse.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 63 insertions(+), 2 deletions(-) (limited to 'libmount/src') diff --git a/libmount/src/tab_parse.c b/libmount/src/tab_parse.c index 6cd66afeb..1b0324ef4 100644 --- a/libmount/src/tab_parse.c +++ b/libmount/src/tab_parse.c @@ -5,6 +5,12 @@ * GNU Lesser General Public License. */ +#ifdef HAVE_SCANDIRAT +#ifndef __USE_GNU +#define __USE_GNU +#endif /* !__USE_GNU */ +#endif /* HAVE_SCANDIRAT */ + #include #include #include @@ -429,14 +435,68 @@ int mnt_table_parse_file(struct libmnt_table *tb, const char *filename) return rc; } +#ifdef HAVE_SCANDIRAT +static int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) +{ + int n = 0, i; + int dd; + struct dirent **namelist = NULL; + + dd = open(dirname, O_RDONLY|O_CLOEXEC|O_DIRECTORY); + if (dd < 0) + return -errno; + n = scandirat(dd, ".", &namelist, NULL, versionsort); + if (n <= 0) { + close(dd); + return 0; + } + + for (i = 0; i < n; i++) { + struct dirent *d = namelist[i]; + struct stat st; + size_t namesz; + FILE *f; + +#ifdef _DIRENT_HAVE_D_TYPE + if (d->d_type != DT_UNKNOWN && d->d_type != DT_REG && + d->d_type != DT_LNK) + continue; +#endif + if (*d->d_name == '.') + continue; + +#define MNT_MNTTABDIR_EXTSIZ (sizeof(MNT_MNTTABDIR_EXT) - 1) + + namesz = strlen(d->d_name); + if (!namesz || namesz < MNT_MNTTABDIR_EXTSIZ + 1 || + strcmp(d->d_name + (namesz - MNT_MNTTABDIR_EXTSIZ), + MNT_MNTTABDIR_EXT)) + continue; + + if (fstat_at(dd, ".", d->d_name, &st, 0) || + !S_ISREG(st.st_mode)) + continue; + + f = fopen_at(dd, ".", d->d_name, O_RDONLY, "r"); + if (f) { + mnt_table_parse_stream(tb, f, d->d_name); + fclose(f); + } + } + + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + close(dd); + return 0; +} +#else static int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) { int n = 0, i; DIR *dir = NULL; struct dirent **namelist = NULL; - /* TODO: it would be nice to have a scandir() implementation that - * is able to use already opened directory */ n = scandir(dirname, &namelist, NULL, versionsort); if (n <= 0) return 0; @@ -487,6 +547,7 @@ static int mnt_table_parse_dir(struct libmnt_table *tb, const char *dirname) closedir(dir); return 0; } +#endif struct libmnt_table *__mnt_new_table_from_file(const char *filename, int fmt) { -- cgit v1.2.3-55-g7522