From c43a9ae78220daadd71e00fc0596ceb839621e28 Mon Sep 17 00:00:00 2001 From: Laurent Bercot Date: Tue, 25 Aug 2020 20:04:42 +0000 Subject: Initial commit. --- src/fclose_keep_errno.c | 9 ++++++ src/getfs_a.c | 29 ++++++++++++++++++ src/getfsent.c | 35 ++++++++++++++++++++++ src/getfsent_a.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++ src/include/fsent.h | 11 +++++++ 5 files changed, 162 insertions(+) create mode 100644 src/fclose_keep_errno.c create mode 100644 src/getfs_a.c create mode 100644 src/getfsent.c create mode 100644 src/getfsent_a.c create mode 100644 src/include/fsent.h (limited to 'src') diff --git a/src/fclose_keep_errno.c b/src/fclose_keep_errno.c new file mode 100644 index 0000000..68d6113 --- /dev/null +++ b/src/fclose_keep_errno.c @@ -0,0 +1,9 @@ +#include +#include "fsent.h" + +void __fclose_keep_errno(FILE *f) +{ + int e = errno; + fclose(f); + errno = e; +} diff --git a/src/getfs_a.c b/src/getfs_a.c new file mode 100644 index 0000000..22a18d2 --- /dev/null +++ b/src/getfs_a.c @@ -0,0 +1,29 @@ +#include +#include "fsent.h" + +int __getfs_a(char const *spec, char const *file, struct fstab *fstab, char **line, size_t *size) +{ + int r; + int cs; + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); + + FILE *f = fopen(_PATH_FSTAB, "rbe"); + if (!f) + { + pthread_setcancelstate(cs, 0); + return 0; + } + + for (;;) + { + r = __getfsent_a(f, fstab, line, size); + if (!r) break; + if (spec && !strcmp(spec, fstab->fs_spec) + || file && !strcmp(file, fstab->fs_file)) + break; + } + + __fclose_keep_errno(f); + pthread_setcancelstate(cs, 0); + return r; +} diff --git a/src/getfsent.c b/src/getfsent.c new file mode 100644 index 0000000..ccfc0d3 --- /dev/null +++ b/src/getfsent.c @@ -0,0 +1,35 @@ +#include "fsent.h" + +static FILE *f; +static char *line; +static struct fstab fstab; +static size_t size; + +void endfsent() +{ + if (f) __fclose_keep_errno(f); + f = 0; +} + +int setfsent() +{ + endfsent(); + return 1; +} + +struct fstab *getfsent() +{ + if (!f) f = fopen(_PATH_FSTAB, "rbe"); + if (!f) return 0; + return __getfsent_a(f, &fstab, &line, &size) ? &fstab : 0; +} + +struct fstab *getfsspec(char const *spec) +{ + return __getfs_a(spec, 0, &fstab, &line, &size) ? &fstab : 0; +} + +struct fstab *getfsfile(char const *file) +{ + return __getfs_a(0, file, &fstab, &line, &size) ? &fstab : 0; +} diff --git a/src/getfsent_a.c b/src/getfsent_a.c new file mode 100644 index 0000000..3d302b7 --- /dev/null +++ b/src/getfsent_a.c @@ -0,0 +1,78 @@ +#include +#include +#include "fsent.h" + +static int nextword(char **s) +{ + for (; **s; (*s)++) + if (!isspace(**s)) return 1; + return 0; +} + +static void endword(char **s) +{ + for (; **s; (*s)++) + if (isspace(**s)) { *(*s)++ = 0; break; } +} + +static int scan_int(char *s) +{ + unsigned int x = 0; + for (; *s-'0'<10U; ++s) x = 10*x + (*s-'0'); + return (int)x; +} + +static inline int hasmntopt(char const *blob, char const *opt) +{ + size_t optlen = strlen(opt); + char const *s = blob; + for (;;) + { + char const *p = strstr(s, opt); + if (!p) break; + if ((p == s || p[-1] == ',') && (!p[optlen] || p[optlen] == '=' || p[optlen] == ',')) + return 1; + s = strchr(p, ','); + if (!s) break; + s++; + } + return 0; +} + +static inline void compute_legacy_fs_type(struct fstab *fstab) +{ + if (!strcmp(fstab->fs_vfstype, "ignore")) fstab->fs_type = FSTAB_XX; + else if (!strcmp(fstab->fs_vfstype, "swap")) fstab->fs_type = FSTAB_SW; + else if (hasmntopt(fstab->fs_mntops, "ro")) fstab->fs_type = FSTAB_RO; + else fstab->fs_type = FSTAB_RW; +} + +int __getfsent_a(FILE *f, struct fstab *fstab, char **line, size_t *size) +{ + for (;;) + { + char *s; + char *tmp; + size_t l = getline(line, size, f); + if (l < 0) + { + free(*line); + *line = 0; + return 0; + } + s = *line; + + if (*s == '#') continue; + if (!nextword(&s)) continue; fstab->fs_spec = s; endword(&s); + if (!nextword(&s)) continue; fstab->fs_file = s; endword(&s); + if (!nextword(&s)) continue; fstab->fs_vfstype = s; endword(&s); + if (!nextword(&s)) continue; fstab->fs_mntops = s; endword(&s); + fstab->fs_freq = fstab->fs_passno = 0; + compute_legacy_fs_type(fstab); + if (!nextword(&s)) return 1; tmp = s; endword(&s); + fstab->fs_freq = scan_int(tmp); + if (!nextword(&s)) return 1; tmp = s; endword(&s); + fstab->fs_passno = scan_int(tmp); + return 1; + } +} diff --git a/src/include/fsent.h b/src/include/fsent.h new file mode 100644 index 0000000..676130c --- /dev/null +++ b/src/include/fsent.h @@ -0,0 +1,11 @@ +#include +#include +#ifdef IN_MUSL +#include +#else +#include "fstab.h" +#endif + +void __fclose_keep_errno(FILE *); +int __getfs_a(char const *, char const *, struct fstab *, char **, size_t *); +int __getfsent_a(FILE *, struct fstab *, char **, size_t *); -- cgit 1.4.1