about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fclose_keep_errno.c9
-rw-r--r--src/getfs_a.c29
-rw-r--r--src/getfsent.c35
-rw-r--r--src/getfsent_a.c78
-rw-r--r--src/include/fsent.h11
5 files changed, 162 insertions, 0 deletions
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 *);