aboutsummaryrefslogtreecommitdiff
path: root/src/fstabinfo/fstabinfo.c
diff options
context:
space:
mode:
authorWilliam Hubbs <w.d.hubbs@gmail.com>2022-04-06 10:51:55 -0500
committerWilliam Hubbs <w.d.hubbs@gmail.com>2022-04-06 10:51:55 -0500
commit391d12db48754861b5cecac92ee3321597ee02c1 (patch)
treeb42fad5a31ca342de7b7ecf1fb78784194c1400c /src/fstabinfo/fstabinfo.c
parent0efc1b133e4182bd53cde78153bd8b5cc2e99448 (diff)
migrate fully to meson build system
- drop old build system - move shared include and source files to common directory - drop "rc-" prefix from shared include and source files - move executable-specific code to individual directories under src - adjust top-level .gitignore file for new build system This closes #489.
Diffstat (limited to 'src/fstabinfo/fstabinfo.c')
-rw-r--r--src/fstabinfo/fstabinfo.c339
1 files changed, 339 insertions, 0 deletions
diff --git a/src/fstabinfo/fstabinfo.c b/src/fstabinfo/fstabinfo.c
new file mode 100644
index 00000000..ef7d0609
--- /dev/null
+++ b/src/fstabinfo/fstabinfo.c
@@ -0,0 +1,339 @@
+/*
+ * fstabinfo.c
+ * Gets information about /etc/fstab.
+ */
+
+/*
+ * Copyright (c) 2007-2015 The OpenRC Authors.
+ * See the Authors file at the top-level directory of this distribution and
+ * https://github.com/OpenRC/openrc/blob/HEAD/AUTHORS
+ *
+ * This file is part of OpenRC. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution and at https://github.com/OpenRC/openrc/blob/HEAD/LICENSE
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Yay for linux and its non liking of POSIX functions.
+ Okay, we could use getfsent but the man page says use getmntent instead
+ AND we don't have getfsent on uclibc or dietlibc for some odd reason. */
+#ifdef __linux__
+# define HAVE_GETMNTENT
+# include <mntent.h>
+# define ENT mntent
+# define START_ENT fp = setmntent ("/etc/fstab", "r");
+# define GET_ENT getmntent (fp)
+# define GET_ENT_FILE(_name) getmntfile (_name)
+# define END_ENT endmntent (fp)
+# define ENT_BLOCKDEVICE(_ent) (_ent)->mnt_fsname
+# define ENT_FILE(_ent) (_ent)->mnt_dir
+# define ENT_TYPE(_ent) (_ent)->mnt_type
+# define ENT_OPTS(_ent) (_ent)->mnt_opts
+# define ENT_PASS(_ent) (_ent)->mnt_passno
+#else
+# define HAVE_GETFSENT
+# include <fstab.h>
+# define ENT fstab
+# define START_ENT
+# define GET_ENT getfsent ()
+# define GET_ENT_FILE(_name) getfsfile (_name)
+# define END_ENT endfsent ()
+# define ENT_BLOCKDEVICE(_ent) (_ent)->fs_spec
+# define ENT_TYPE(_ent) (_ent)->fs_vfstype
+# define ENT_FILE(_ent) (_ent)->fs_file
+# define ENT_OPTS(_ent) (_ent)->fs_mntops
+# define ENT_PASS(_ent) (_ent)->fs_passno
+#endif
+
+#include "einfo.h"
+#include "queue.h"
+#include "rc.h"
+#include "misc.h"
+#include "_usage.h"
+
+const char *applet = NULL;
+const char *extraopts = NULL;
+const char getoptstring[] = "MRbmop:t:" getoptstring_COMMON;
+const struct option longopts[] = {
+ { "mount", 0, NULL, 'M' },
+ { "remount", 0, NULL, 'R' },
+ { "blockdevice", 0, NULL, 'b' },
+ { "mountargs", 0, NULL, 'm' },
+ { "options", 0, NULL, 'o' },
+ { "passno", 1, NULL, 'p' },
+ { "fstype", 1, NULL, 't' },
+ longopts_COMMON
+};
+const char * const longopts_help[] = {
+ "Mounts the filesytem from the mountpoint",
+ "Remounts the filesystem based on the information in fstab",
+ "Extract the block device",
+ "Show arguments needed to mount the entry",
+ "Extract the options field",
+ "Extract or query the pass number field",
+ "List entries with matching file system type",
+ longopts_help_COMMON
+};
+const char *usagestring = NULL;
+
+#ifdef HAVE_GETMNTENT
+static struct mntent *
+getmntfile(const char *file)
+{
+ struct mntent *ent;
+ FILE *fp;
+
+ START_ENT;
+ while ((ent = getmntent(fp)))
+ if (strcmp(file, ent->mnt_dir) == 0)
+ break;
+ END_ENT;
+
+ return ent;
+}
+#endif
+
+extern const char *applet;
+
+static int
+do_mount(struct ENT *ent, bool remount)
+{
+ char *argv[10];
+ pid_t pid;
+ int status;
+
+ argv[0] = UNCONST("mount");
+ argv[1] = UNCONST("-o");
+ argv[2] = ENT_OPTS(ent);
+ argv[3] = UNCONST("-t");
+ argv[4] = ENT_TYPE(ent);
+ if (!remount) {
+ argv[5] = ENT_BLOCKDEVICE(ent);
+ argv[6] = ENT_FILE(ent);
+ argv[7] = NULL;
+ } else {
+#ifdef __linux__
+ argv[5] = UNCONST("-o");
+ argv[6] = UNCONST("remount");
+ argv[7] = ENT_BLOCKDEVICE(ent);
+ argv[8] = ENT_FILE(ent);
+ argv[9] = NULL;
+#else
+ argv[5] = UNCONST("-u");
+ argv[6] = ENT_BLOCKDEVICE(ent);
+ argv[7] = ENT_FILE(ent);
+ argv[8] = NULL;
+#endif
+ }
+ switch (pid = vfork()) {
+ case -1:
+ eerrorx("%s: vfork: %s", applet, strerror(errno));
+ /* NOTREACHED */
+ case 0:
+ execvp(argv[0], argv);
+ eerror("%s: execvp: %s", applet, strerror(errno));
+ _exit(EXIT_FAILURE);
+ /* NOTREACHED */
+ default:
+ waitpid(pid, &status, 0);
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ else
+ return -1;
+ /* NOTREACHED */
+ }
+}
+
+#define OUTPUT_FILE (1 << 1)
+#define OUTPUT_MOUNTARGS (1 << 2)
+#define OUTPUT_OPTIONS (1 << 3)
+#define OUTPUT_PASSNO (1 << 4)
+#define OUTPUT_BLOCKDEV (1 << 5)
+#define OUTPUT_MOUNT (1 << 6)
+#define OUTPUT_REMOUNT (1 << 7)
+
+int main(int argc, char **argv)
+{
+ struct ENT *ent;
+ int result = EXIT_SUCCESS;
+ char *token;
+ int i, p;
+ int opt;
+ int output = OUTPUT_FILE;
+ RC_STRINGLIST *files = rc_stringlist_new();
+ RC_STRING *file, *file_np;
+ bool filtered = false;
+
+#ifdef HAVE_GETMNTENT
+ FILE *fp;
+#endif
+
+ /* fail if there is no /etc/fstab */
+ if (!exists("/etc/fstab"))
+ eerrorx("/etc/fstab does not exist");
+ /* Ensure that we are only quiet when explicitly told to be */
+ unsetenv("EINFO_QUIET");
+
+ applet = basename_c(argv[0]);
+ while ((opt = getopt_long(argc, argv, getoptstring,
+ longopts, (int *) 0)) != -1)
+ {
+ switch (opt) {
+ case 'M':
+ output = OUTPUT_MOUNT;
+ break;
+ case 'R':
+ output = OUTPUT_REMOUNT;
+ break;
+ case 'b':
+ output = OUTPUT_BLOCKDEV;
+ break;
+ case 'o':
+ output = OUTPUT_OPTIONS;
+ break;
+ case 'm':
+ output = OUTPUT_MOUNTARGS;
+ break;
+
+ case 'p':
+ switch (optarg[0]) {
+ case '=':
+ case '<':
+ case '>':
+ if (sscanf(optarg + 1, "%d", &i) != 1)
+ eerrorx("%s: invalid passno %s",
+ argv[0], optarg + 1);
+
+ filtered = true;
+ opt = optarg[0];
+ START_ENT;
+ while ((ent = GET_ENT)) {
+ if (strcmp(ENT_FILE(ent), "none") == 0)
+ continue;
+ p = ENT_PASS(ent);
+ if ((opt == '=' && i == p) ||
+ (opt == '<' && i > p && p != 0) ||
+ (opt == '>' && i < p && p != 0))
+ rc_stringlist_add(files,
+ ENT_FILE(ent));
+ }
+ END_ENT;
+ break;
+
+ default:
+ rc_stringlist_add(files, optarg);
+ output = OUTPUT_PASSNO;
+ break;
+ }
+ break;
+
+ case 't':
+ filtered = true;
+ while ((token = strsep(&optarg, ","))) {
+ START_ENT;
+ while ((ent = GET_ENT))
+ if (strcmp(token, ENT_TYPE(ent)) == 0)
+ rc_stringlist_add(files,
+ ENT_FILE(ent));
+ END_ENT;
+ }
+ break;
+
+ case_RC_COMMON_GETOPT
+ }
+ }
+
+ if (optind < argc) {
+ if (TAILQ_FIRST(files)) {
+ TAILQ_FOREACH_SAFE(file, files, entries, file_np) {
+ for (i = optind; i < argc; i++)
+ if (strcmp(argv[i], file->value) == 0)
+ break;
+ if (i >= argc)
+ rc_stringlist_delete(files,
+ file->value);
+ }
+ } else {
+ while (optind < argc)
+ rc_stringlist_add(files, argv[optind++]);
+ }
+ } else if (!filtered) {
+ START_ENT;
+ while ((ent = GET_ENT))
+ rc_stringlist_add(files, ENT_FILE(ent));
+ END_ENT;
+
+ if (!TAILQ_FIRST(files))
+ eerrorx("%s: empty fstab", argv[0]);
+ }
+
+ if (!TAILQ_FIRST(files)) {
+ rc_stringlist_free(files);
+ return (EXIT_FAILURE);
+ }
+
+ /* Ensure we always display something */
+ START_ENT;
+ TAILQ_FOREACH(file, files, entries) {
+ if (!(ent = GET_ENT_FILE(file->value))) {
+ result = EXIT_FAILURE;
+ continue;
+ }
+
+ /* mount or remount? */
+ switch (output) {
+ case OUTPUT_MOUNT:
+ result += do_mount(ent, false);
+ break;
+
+ case OUTPUT_REMOUNT:
+ result += do_mount(ent, true);
+ break;
+ }
+
+ /* No point in outputting if quiet */
+ if (rc_yesno(getenv("EINFO_QUIET")))
+ continue;
+
+ switch (output) {
+ case OUTPUT_BLOCKDEV:
+ printf("%s\n", ENT_BLOCKDEVICE(ent));
+ break;
+
+ case OUTPUT_MOUNTARGS:
+ printf("-o %s -t %s %s %s\n",
+ ENT_OPTS(ent),
+ ENT_TYPE(ent),
+ ENT_BLOCKDEVICE(ent),
+ file->value);
+ break;
+
+ case OUTPUT_OPTIONS:
+ printf("%s\n", ENT_OPTS(ent));
+ break;
+
+ case OUTPUT_FILE:
+ printf("%s\n", file->value);
+ break;
+
+ case OUTPUT_PASSNO:
+ printf("%d\n", ENT_PASS(ent));
+ break;
+ }
+ }
+ END_ENT;
+
+ rc_stringlist_free(files);
+ exit(result);
+ /* NOTREACHED */
+}