diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | COPYING | 24 | ||||
-rw-r--r-- | Makefile | 34 | ||||
-rw-r--r-- | README | 4 | ||||
-rw-r--r-- | include/fstab.h | 37 | ||||
-rw-r--r-- | src/fclose_keep_errno.c | 9 | ||||
-rw-r--r-- | src/getfs_a.c | 29 | ||||
-rw-r--r-- | src/getfsent.c | 35 | ||||
-rw-r--r-- | src/getfsent_a.c | 78 | ||||
-rw-r--r-- | src/include/fsent.h | 11 |
10 files changed, 263 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d19bb5e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +libfstab.a diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..d239786 --- /dev/null +++ b/COPYING @@ -0,0 +1,24 @@ +(Original MIT license.) +(For inclusion into musl, assign the copyright to Rich Felker.) +---------------------------------------------------------------------- +Copyright (C)2020 Laurent Bercot. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +---------------------------------------------------------------------- diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5a29d42 --- /dev/null +++ b/Makefile @@ -0,0 +1,34 @@ + +LIBDIR := /usr/lib +INCLUDEDIR := /usr/include + +CC := gcc +CFLAGS := -fPIC +AR := ar +RANLIB := ranlib +INSTALL := install + +OBJS := fclose_keep_errno.o getfs_a.o getfsent.o getfsent_a.o + +it: include/fstab.h libfstab.a + +clean: + @exec rm -f *.o libfstab.a + +install: $(DESTDIR)$(INCLUDEDIR)/fstab.h $(DESTDIR)$(LIBDIR)/libfstab.a + + +$(DESTDIR)$(INCLUDEDIR)/fstab.h: include/fstab.h + exec $(INSTALL) -D -m 644 $< $@ + +$(DESTDIR)$(LIBDIR)/libfstab.a: libfstab.a + exec $(INSTALL) -D -m 644 $< $@ + +%.o: src/%.c + exec $(CC) $(CFLAGS) -c -o $@ -I include -I src/include $< + +libfstab.a: $(OBJS) + exec $(AR) rc $@ $^ + exec $(RANLIB) $@ + +.PHONY: it clean install diff --git a/README b/README new file mode 100644 index 0000000..c5c1031 --- /dev/null +++ b/README @@ -0,0 +1,4 @@ +libfstab - an implementation of fstab.h for musl +------------------------------------------------ + + See https://www.gnu.org/software/libc/manual/html_node/fstab.html diff --git a/include/fstab.h b/include/fstab.h new file mode 100644 index 0000000..526329e --- /dev/null +++ b/include/fstab.h @@ -0,0 +1,37 @@ +#ifndef _FSTAB_H +#define _FSTAB_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +#define _PATH_FSTAB "/etc/fstab" + +#define FSTAB_RW "rw" +#define FSTAB_RQ "rq" +#define FSTAB_RO "ro" +#define FSTAB_SW "sw" +#define FSTAB_XX "xx" + +struct fstab { + char *fs_spec; + char *fs_file; + char *fs_vfstype; + char *fs_mntops; + char const *fs_type; + int fs_freq; + int fs_passno; +}; + +struct fstab *getfsent (void); +struct fstab *getfsspec (char const *); +struct fstab *getfsfile (char const *); +int setfsent (void); +void endfsent (void); + +#ifdef __cplusplus +} +#endif + +#endif + 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 <errno.h> +#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 <pthread.h> +#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 <ctype.h> +#include <stdlib.h> +#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 <string.h> +#include <stdio.h> +#ifdef IN_MUSL +#include <fstab.h> +#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 *); |