diff options
Diffstat (limited to 'src/rc/mountinfo.c')
-rw-r--r-- | src/rc/mountinfo.c | 488 |
1 files changed, 0 insertions, 488 deletions
diff --git a/src/rc/mountinfo.c b/src/rc/mountinfo.c deleted file mode 100644 index 6652760d..00000000 --- a/src/rc/mountinfo.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * mountinfo.c - * Obtains information about mounted filesystems. - */ - -/* - * Copyright 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/types.h> -#include <sys/param.h> - -#if defined(__DragonFly__) || defined(__FreeBSD__) -# include <sys/ucred.h> -# include <sys/mount.h> -# define F_FLAGS f_flags -#elif defined(BSD) && !defined(__GNU__) -# include <sys/statvfs.h> -# define statfs statvfs -# define F_FLAGS f_flag -#elif defined(__linux__) || (defined(__FreeBSD_kernel__) && \ - defined(__GLIBC__)) || defined(__GNU__) -# include <mntent.h> -#endif - -#include <errno.h> -#include <getopt.h> -#include <limits.h> -#include <regex.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "einfo.h" -#include "queue.h" -#include "rc.h" -#include "rc-misc.h" -#include "_usage.h" - -const char *applet = NULL; -const char *procmounts = "/proc/mounts"; -const char *extraopts = "[mount1] [mount2] ..."; -const char getoptstring[] = "f:F:n:N:o:O:p:P:iste:E:" getoptstring_COMMON; -const struct option longopts[] = { - { "fstype-regex", 1, NULL, 'f'}, - { "skip-fstype-regex", 1, NULL, 'F'}, - { "node-regex", 1, NULL, 'n'}, - { "skip-node-regex", 1, NULL, 'N'}, - { "options-regex", 1, NULL, 'o'}, - { "skip-options-regex", 1, NULL, 'O'}, - { "point-regex", 1, NULL, 'p'}, - { "skip-point-regex", 1, NULL, 'P'}, - { "options", 0, NULL, 'i'}, - { "fstype", 0, NULL, 's'}, - { "node", 0, NULL, 't'}, - { "netdev", 0, NULL, 'e'}, - { "nonetdev", 0, NULL, 'E'}, - longopts_COMMON -}; -const char * const longopts_help[] = { - "fstype regex to find", - "fstype regex to skip", - "node regex to find", - "node regex to skip", - "options regex to find", - "options regex to skip", - "point regex to find", - "point regex to skip", - "print options", - "print fstype", - "print node", - "is it a network device", - "is it not a network device", - longopts_help_COMMON -}; -const char *usagestring = NULL; - -typedef enum { - mount_from, - mount_to, - mount_fstype, - mount_options -} mount_type; - -typedef enum { - net_ignore, - net_yes, - net_no -} net_opts; - -struct args { - regex_t *node_regex; - regex_t *skip_node_regex; - regex_t *fstype_regex; - regex_t *skip_fstype_regex; - regex_t *options_regex; - regex_t *skip_options_regex; - RC_STRINGLIST *mounts; - mount_type mount_type; - net_opts netdev; -}; - -static int -process_mount(RC_STRINGLIST *list, struct args *args, - char *from, char *to, char *fstype, char *options, - int netdev) -{ - char *p; - RC_STRING *s; - - errno = ENOENT; - -#ifdef __linux__ - /* Skip the really silly rootfs */ - if (strcmp(fstype, "rootfs") == 0) - return -1; -#endif - - if (args->netdev == net_yes && - (netdev != -1 || TAILQ_FIRST(args->mounts))) - { - if (netdev != 0) - return 1; - } else if (args->netdev == net_no && - (netdev != -1 || TAILQ_FIRST(args->mounts))) - { - if (netdev != 1) - return 1; - } else { - if (args->node_regex && - regexec(args->node_regex, from, 0, NULL, 0) != 0) - return 1; - if (args->skip_node_regex && - regexec(args->skip_node_regex, from, 0, NULL, 0) == 0) - return 1; - - if (args->fstype_regex && - regexec(args->fstype_regex, fstype, 0, NULL, 0) != 0) - return -1; - if (args->skip_fstype_regex && - regexec(args->skip_fstype_regex, fstype, 0, NULL, 0) == 0) - return -1; - - if (args->options_regex && - regexec(args->options_regex, options, 0, NULL, 0) != 0) - return -1; - if (args->skip_options_regex && - regexec(args->skip_options_regex, options, 0, NULL, 0) == 0) - return -1; - } - - if (TAILQ_FIRST(args->mounts)) { - TAILQ_FOREACH(s, args->mounts, entries) - if (strcmp(s->value, to) == 0) - break; - if (!s) - return -1; - } - - switch (args->mount_type) { - case mount_from: - p = from; - break; - case mount_to: - p = to; - break; - case mount_fstype: - p = fstype; - break; - case mount_options: - p = options; - break; - default: - p = NULL; - errno = EINVAL; - break; - } - - if (p) { - errno = 0; - rc_stringlist_add(list, p); - return 0; - } - - return -1; -} - -#if defined(BSD) && !defined(__GNU__) - -/* Translate the mounted options to english - * This is taken directly from FreeBSD mount.c */ -static struct opt { - int o_opt; - const char *o_name; -} optnames[] = { - { MNT_ASYNC, "asynchronous" }, - { MNT_EXPORTED, "NFS exported" }, - { MNT_LOCAL, "local" }, - { MNT_NOATIME, "noatime" }, - { MNT_NOEXEC, "noexec" }, - { MNT_NOSUID, "nosuid" }, -#ifdef MNT_NOSYMFOLLOW - { MNT_NOSYMFOLLOW, "nosymfollow" }, -#endif - { MNT_QUOTA, "with quotas" }, - { MNT_RDONLY, "read-only" }, - { MNT_SYNCHRONOUS, "synchronous" }, - { MNT_UNION, "union" }, -#ifdef MNT_NOCLUSTERR - { MNT_NOCLUSTERR, "noclusterr" }, -#endif -#ifdef MNT_NOCLUSTERW - { MNT_NOCLUSTERW, "noclusterw" }, -#endif -#ifdef MNT_SUIDDIR - { MNT_SUIDDIR, "suiddir" }, -#endif - { MNT_SOFTDEP, "soft-updates" }, -#ifdef MNT_MULTILABEL - { MNT_MULTILABEL, "multilabel" }, -#endif -#ifdef MNT_ACLS - { MNT_ACLS, "acls" }, -#endif -#ifdef MNT_GJOURNAL - { MNT_GJOURNAL, "gjournal" }, -#endif - { 0, NULL } -}; - -static RC_STRINGLIST * -find_mounts(struct args *args) -{ - struct statfs *mnts; - int nmnts; - int i; - RC_STRINGLIST *list; - char *options = NULL; - uint64_t flags; - struct opt *o; - int netdev; - char *tmp; - - if ((nmnts = getmntinfo(&mnts, MNT_NOWAIT)) == 0) - eerrorx("getmntinfo: %s", strerror (errno)); - - list = rc_stringlist_new(); - for (i = 0; i < nmnts; i++) { - netdev = 0; - flags = mnts[i].F_FLAGS & MNT_VISFLAGMASK; - for (o = optnames; flags && o->o_opt; o++) { - if (flags & o->o_opt) { - if (o->o_opt == MNT_LOCAL) - netdev = 1; - if (!options) - options = xstrdup(o->o_name); - else { - xasprintf(&tmp, "%s,%s", options, o->o_name); - free(options); - options = tmp; - } - } - flags &= ~o->o_opt; - } - - process_mount(list, args, - mnts[i].f_mntfromname, - mnts[i].f_mntonname, - mnts[i].f_fstypename, - options, - netdev); - - free(options); - options = NULL; - } - - return list; -} - -#elif defined(__linux__) || (defined(__FreeBSD_kernel__) && \ - defined(__GLIBC__)) || defined(__GNU__) -static struct mntent * -getmntfile(const char *file) -{ - struct mntent *ent = NULL; - FILE *fp; - - if (!exists("/etc/fstab")) - return NULL; - - fp = setmntent("/etc/fstab", "r"); - while ((ent = getmntent(fp))) - if (strcmp(file, ent->mnt_dir) == 0) - break; - endmntent(fp); - - return ent; -} - -static RC_STRINGLIST * -find_mounts(struct args *args) -{ - FILE *fp; - char *buffer; - size_t size; - char *p; - char *from; - char *to; - char *fst; - char *opts; - struct mntent *ent; - int netdev; - RC_STRINGLIST *list; - - if ((fp = fopen(procmounts, "r")) == NULL) - eerrorx("getmntinfo: %s", strerror(errno)); - - list = rc_stringlist_new(); - - buffer = NULL; - while (getline(&buffer, &size, fp) != -1) { - netdev = -1; - p = buffer; - from = strsep(&p, " "); - to = strsep(&p, " "); - fst = strsep(&p, " "); - opts = strsep(&p, " "); - - if ((ent = getmntfile(to))) { - if (strstr(ent->mnt_opts, "_netdev")) - netdev = 0; - else - netdev = 1; - } - - process_mount(list, args, from, to, fst, opts, netdev); - free(buffer); - buffer = NULL; - } - free(buffer); - fclose(fp); - - return list; -} - -#else -# error "Operating system not supported!" -#endif - -static regex_t * -get_regex(const char *string) -{ - regex_t *reg = xmalloc(sizeof (*reg)); - int result; - char buffer[256]; - - if ((result = regcomp(reg, string, REG_EXTENDED | REG_NOSUB)) != 0) - { - regerror(result, reg, buffer, sizeof(buffer)); - eerrorx("%s: invalid regex `%s'", applet, buffer); - } - - return reg; -} - -int main(int argc, char **argv) -{ - struct args args; - regex_t *point_regex = NULL; - regex_t *skip_point_regex = NULL; - RC_STRINGLIST *nodes; - RC_STRING *s; - char *real_path = NULL; - int opt; - int result; - char *this_path; - -#define DO_REG(_var) \ - if (_var) free(_var); \ - _var = get_regex(optarg); -#define REG_FREE(_var) \ - if (_var) { regfree(_var); free(_var); } - - applet = basename_c(argv[0]); - memset (&args, 0, sizeof(args)); - args.mount_type = mount_to; - args.netdev = net_ignore; - args.mounts = rc_stringlist_new(); - - while ((opt = getopt_long(argc, argv, getoptstring, - longopts, (int *) 0)) != -1) - { - switch (opt) { - case 'e': - args.netdev = net_yes; - break; - case 'E': - args.netdev = net_no; - break; - case 'f': - DO_REG(args.fstype_regex); - break; - case 'F': - DO_REG(args.skip_fstype_regex); - break; - case 'n': - DO_REG(args.node_regex); - break; - case 'N': - DO_REG(args.skip_node_regex); - break; - case 'o': - DO_REG(args.options_regex); - break; - case 'O': - DO_REG(args.skip_options_regex); - break; - case 'p': - DO_REG(point_regex); - break; - case 'P': - DO_REG(skip_point_regex); - break; - case 'i': - args.mount_type = mount_options; - break; - case 's': - args.mount_type = mount_fstype; - break; - case 't': - args.mount_type = mount_from; - break; - - case_RC_COMMON_GETOPT - } - } - - while (optind < argc) { - if (argv[optind][0] != '/') - eerrorx("%s: `%s' is not a mount point", - argv[0], argv[optind]); - this_path = argv[optind++]; - real_path = realpath(this_path, NULL); - if (real_path) - this_path = real_path; - rc_stringlist_add(args.mounts, this_path); - free(real_path); - real_path = NULL; - } - nodes = find_mounts(&args); - rc_stringlist_free(args.mounts); - - REG_FREE(args.fstype_regex); - REG_FREE(args.skip_fstype_regex); - REG_FREE(args.node_regex); - REG_FREE(args.skip_node_regex); - REG_FREE(args.options_regex); - REG_FREE(args.skip_options_regex); - - result = EXIT_FAILURE; - - /* We should report the mounts in reverse order to ease unmounting */ - TAILQ_FOREACH_REVERSE(s, nodes, rc_stringlist, entries) { - if (point_regex && - regexec(point_regex, s->value, 0, NULL, 0) != 0) - continue; - if (skip_point_regex && - regexec(skip_point_regex, s->value, 0, NULL, 0) == 0) - continue; - if (!rc_yesno(getenv("EINFO_QUIET"))) - printf("%s\n", s->value); - result = EXIT_SUCCESS; - } - rc_stringlist_free(nodes); - - REG_FREE(point_regex); - REG_FREE(skip_point_regex); - - return result; -} |