mntent: Library methods for managing mtab and fstab
authorAlan Cox <alan@linux.intel.com>
Thu, 21 Dec 2017 14:11:38 +0000 (14:11 +0000)
committerAlan Cox <alan@linux.intel.com>
Thu, 21 Dec 2017 14:11:38 +0000 (14:11 +0000)
We don't use these or hook them in yet but add them ready

Library/include/mntent.h [new file with mode: 0644]
Library/libs/mntent.c [new file with mode: 0644]

diff --git a/Library/include/mntent.h b/Library/include/mntent.h
new file mode 100644 (file)
index 0000000..62d2760
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef _MNTENT_H
+#define _MNTENT_H
+
+struct mntent {
+    char *mnt_fsname;
+    char *mnt_dir;
+    char *mnt_type;
+    char *mnt_opts;
+    int mnt_freq;
+    int mnt_passno;
+};
+
+#define _MAX_MNTLEN    512
+
+/* Standard functions */
+extern FILE *setmntent(char *filep, char *type);
+extern struct mntent *getmntent(FILE *fp);
+extern int addmntent(FILE *fp, struct mntent *mnt);
+extern int endmntent(FILE *fp);
+extern char *hasmntopt(struct mntent *mnt, char *opt);
+
+/* Extended function found in some Unixen */
+extern int delmntent(FILE *fp, struct mntent *mnt);
+
+#endif
diff --git a/Library/libs/mntent.c b/Library/libs/mntent.c
new file mode 100644 (file)
index 0000000..e1af5d7
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ *     An implementation of the mountpoint handling library. This one
+ *     handles all the modern quoting rules for spaces in mount entries
+ *     but does not currently implement the delmntent() extension as we
+ *     can't do that easily without ftruncate().
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/file.h>
+#include <mntent.h>
+
+static char mntbuf[_MAX_MNTLEN];
+
+FILE *setmntent(char *filep, char *type)
+{
+       int lock;
+       FILE *fp = fopen(filep, type);
+       
+       if (fp == NULL)
+               return NULL;
+       if (strchr(type,'w') || strchr(type,'a'))
+               lock = LOCK_SH;
+       else
+               lock = LOCK_EX;
+       if (flock(fileno(fp), lock) == -1) {
+               fclose(fp);
+               return NULL;
+       }
+       return fp;
+}
+
+static int isoct(char c)
+{
+       if (c >= '0' && c <= '7')
+               return 1;
+       return 0;
+}
+
+static int mntparse(char *p, char **t, char *def)
+{
+       char *d = strtok(p, " \t\n");
+       if (d == NULL)
+               d = def;
+       else {
+               /* Dequote */
+               char *s = d;
+               while (*s) {
+                       if (*s == '\\' && isoct(s[1]) && isoct(s[2]) && isoct(s[3])) {
+                               *d++ = ((s[1] - '0') << 6) | ((s[2] - '0') << 3) | (s[3] - '0');
+                               s += 4;
+                       } else
+                               *d++ = *s++;
+               }
+       }
+       if (t)
+               *t = d;
+       return atoi(d);
+}
+
+struct mntent *getmntent(FILE * fp)
+{
+       static struct mntent me;
+       char *p = mntbuf;
+       /* Skip blank lines and comments */
+       do {
+               if (fgets(mntbuf, _MAX_MNTLEN, fp) == NULL)
+                       return NULL;
+       } while(*p == '\n' || *p == '#');
+       mntparse(mntbuf, &me.mnt_fsname, NULL);
+       mntparse(NULL, &me.mnt_dir, NULL);
+       mntparse(NULL, &me.mnt_type, "fuzix");
+       mntparse(NULL, &me.mnt_opts, "");
+       me.mnt_freq = mntparse(NULL, NULL, "0");
+       me.mnt_passno = mntparse(NULL, NULL, "0");
+       if (me.mnt_fsname == NULL || me.mnt_dir == NULL)
+               return NULL;
+       return &me;
+}
+
+void quote_out(char **p, char *s)
+{
+       char *t = *p;
+       if (t == NULL)
+               return;
+       while (t < mntbuf + _MAX_MNTLEN - 1) {
+               if (*s == 0) {
+                       *p = t;
+                       return;
+               }
+               if (*s == ' ' || *s == '\n' || *s == '\t' || *s == '\\') {
+                       if (t < mntbuf + _MAX_MNTLEN - 5) {
+                               sprintf(t, "\\%3o", *s);
+                               t += 4;
+                               s++;
+                       } else
+                               break;
+               } else {
+                       *t++ = *s++;
+               }
+       }
+       /* Overrun */
+       *p = NULL;
+}
+
+void quote_out_int(char **p, int s)
+{
+       quote_out(p, _itoa(s));
+}
+
+int addmntent(FILE * fp, struct mntent *mnt)
+{
+       char *p = mntbuf;
+       quote_out(&p, mnt->mnt_fsname);
+       quote_out(&p, mnt->mnt_dir);
+       quote_out(&p, mnt->mnt_type);
+       quote_out(&p, mnt->mnt_opts);
+       quote_out_int(&p, mnt->mnt_freq);
+       quote_out_int(&p, mnt->mnt_passno);
+       if (p) {
+               *p = '\n';
+               if (fwrite(mntbuf, p - mntbuf, 1, fp) == 1)
+                       return 0;
+       }
+       return 1;
+}
+
+int endmntent(FILE *fp)
+{
+       /* Will automatically drop the flock */
+       return fclose(fp);
+}
+
+char *hasmntopt(struct mntent *mnt, char *opt)
+{
+       char *p = mnt->mnt_opts;
+       ssize_t o = strlen(opt);
+
+       while (p) {
+               if (memcmp(p, opt, o) == 0 && (p[o] == ',' || isspace(p[o]) || p[o] == 0 || p[o] == '='))
+                       return p;
+               p = strchr(p, ',');
+               if (p)
+                       p++;
+       }
+}