From 5257ba51b9524b101533308024862e4344c8b6f6 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Wed, 11 Jul 2007 17:27:46 +0000 Subject: [PATCH] Don't unmount network filesystems in localmount or halt.sh, #175602. --- ChangeLog | 1 + init.d/halt.sh | 7 ++- init.d/localmount | 10 +++- sh/rc-mount.sh | 6 +- src/mountinfo.c | 150 +++++++++++++++++++++++++++------------------- 5 files changed, 105 insertions(+), 69 deletions(-) diff --git a/ChangeLog b/ChangeLog index c124179c..76ae4c2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,6 +3,7 @@ 11 Jul 2007; Roy Marples : + Don't unmount network filesystems in localmount or halt.sh, #175602. Don't do interactive when changing init, #174141. 10 Jul 2007; Roy Marples : diff --git a/init.d/halt.sh b/init.d/halt.sh index 1b4acca0..dfcacedd 100755 --- a/init.d/halt.sh +++ b/init.d/halt.sh @@ -65,7 +65,12 @@ if [ "${RC_UNAME}" = "Linux" ] ; then # We need the do_unmount function . "${RC_LIBDIR}"/sh/rc-mount.sh eindent - do_unmount "mount -n -o remount,ro" "^(/dev|/dev/pts|/dev/shm|/proc|/proc/.*|/sys)$" + fs= + for x in ${RC_NET_FS_LIST} ; do + fs="${fs}${fs:+|}${x}" + done + [ -n "${fs}" ] && fs="^(${fs})$" + do_unmount "mount -n -o remount,ro" "^(/dev|/dev/pts|/dev/shm|/proc|/proc/.*|/sys)$" "" "" "${fs}" eoutdent eend $? unmounted=$? diff --git a/init.d/localmount b/init.d/localmount index bf12638b..18d84a91 100755 --- a/init.d/localmount +++ b/init.d/localmount @@ -202,10 +202,16 @@ stop() { do_unmount "umount -d" "${no_umounts}" "^/dev/loop" eoutdent - # Now everything else + # Now everything else, except network filesystems as the + # network should be down by this point. einfo "Unmounting filesystems" eindent - do_unmount "umount" "${no_umounts}" + local fs= + for x in ${RC_NET_FS_LIST} ; do + fs="${fs}${fs:+|}${x}" + done + [ -n "${fs}" ] && fs="^(${fs})$" + do_unmount "umount" "${no_umounts}" "" "" "${fs}" eoutdent return 0 diff --git a/sh/rc-mount.sh b/sh/rc-mount.sh index be9dffba..17ef9b5f 100644 --- a/sh/rc-mount.sh +++ b/sh/rc-mount.sh @@ -1,9 +1,9 @@ # Copyright 2007 Gentoo Foundation # Distributed under the terms of the GNU General Public License v2 -# bool do_unmount(char *cmd, char *no_unmounts, char *nodes, char *fslist) +# bool do_unmount(char *cmd, char *no_unmounts, char *nodes, char *fslist, char *no_fslist) # Handy function to handle all our unmounting needs -# find-mount is a C program to actually find our mounts on our supported OS's +# mountinfo is a C program to actually find our mounts on our supported OS's do_unmount() { local cmd="$1" retval=0 retry= local f_opts="-m -c" f_kill="-s " mnt= @@ -12,7 +12,7 @@ do_unmount() { f_kill="-" fi - local mnts="$(mountinfo ${2:+--skip-regex} $2 ${3:+--node-regex} $3 ${4:+--fstype-regex} $4 --reverse \ + local mnts="$(mountinfo ${2:+--skip-point-regex} $2 ${3:+--node-regex} $3 ${4:+--fstype-regex} $4 ${5:+--skip-fstype-regex} $5 \ | sed -e "s/'/'\\\\''/g" -e "s/^/'/g" -e "s/$/'/g")" eval set -- ${mnts} for mnt in "$@" ; do diff --git a/src/mountinfo.c b/src/mountinfo.c index 18243fb3..9a44466a 100644 --- a/src/mountinfo.c +++ b/src/mountinfo.c @@ -31,7 +31,8 @@ #if defined(__FreeBSD__) || defined(__NetBSD__) || defined (__OpenBSD__) -static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, +static char **find_mounts (regex_t *node_regex, regex_t *skip_node_regex, + regex_t *fstype_regex, regex_t *skip_fstype_regex, char **mounts, bool list_nodes, bool list_fstype) { struct statfs *mnts; @@ -46,9 +47,15 @@ static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, if (node_regex && regexec (node_regex, mnts[i].f_mntfromname, 0, NULL, 0) != 0) continue; + if (skip_node_regex && + regexec (skip_node_regex, mnts[i].f_mntfromname, 0, NULL, 0) == 0) + continue; if (fstype_regex && regexec (fstype_regex, mnts[i].f_fstypename, 0, NULL, 0) != 0) continue; + if (skip_fstype_regex && + regexec (skip_fstype_regex, mnts[i].f_fstypename, 0, NULL, 0) == 0) + continue; if (mounts) { bool found = false; @@ -73,7 +80,8 @@ static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, } #elif defined (__linux__) -static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, +static char **find_mounts (regex_t *node_regex, regex_t *skip_node_regex, + regex_t *fstype_regex, regex_t *skip_fstype_regex, char **mounts, bool list_nodes, bool list_fstype) { FILE *fp; @@ -93,6 +101,9 @@ static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, if (node_regex && regexec (node_regex, from, 0, NULL, 0) != 0) continue; + if (skip_node_regex && + regexec (skip_node_regex, from, 0, NULL, 0) == 0) + continue; to = strsep (&p, " "); fstype = strsep (&p, " "); @@ -102,6 +113,9 @@ static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, if (fstype_regex && regexec (fstype_regex, fstype, 0, NULL, 0) != 0) continue; + if (skip_fstype_regex && + regexec (skip_fstype_regex, fstype, 0, NULL, 0) == 0) + continue; if (mounts) { bool found = false; @@ -130,15 +144,32 @@ static char **find_mounts (regex_t *node_regex, regex_t *fstype_regex, # error "Operating system not supported!" #endif +static regex_t *get_regex (char *string) +{ + regex_t *reg = rc_xmalloc (sizeof (regex_t)); + 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); +} + #include "_usage.h" -#define getoptstring "F:N:S:fnrV" getoptstring_COMMON +#define getoptstring "f:F:n:N:p:P:os" getoptstring_COMMON static struct option longopts[] = { - { "fstype-regex", 1, NULL, 'F'}, - { "node-regex", 1, NULL, 'N'}, - { "skip-regex", 1, NULL, 'S'}, - { "fstype", 0, NULL, 'f'}, - { "node", 0, NULL, 'n'}, - { "reverse", 0, NULL, 'r'}, + { "fstype-regex", 1, NULL, 'f'}, + { "skip-fstype-regex", 1, NULL, 'F'}, + { "node-regex", 1, NULL, 'n'}, + { "skip-node-regex", 1, NULL, 'N'}, + { "point-regex", 1, NULL, 'p'}, + { "skip-point-regex", 1, NULL, 'P'}, + { "list-nodes", 0, NULL, 'o'}, + { "list-fstype", 0, NULL, 's'}, longopts_COMMON { NULL, 0, NULL, 0} }; @@ -149,100 +180,93 @@ int main (int argc, char **argv) int i; regex_t *fstype_regex = NULL; regex_t *node_regex = NULL; - regex_t *skip_regex = NULL; + regex_t *point_regex = NULL; + regex_t *skip_fstype_regex = NULL; + regex_t *skip_node_regex = NULL; + regex_t *skip_point_regex = NULL; char **nodes = NULL; char *node; - int result; - char buffer[256]; bool list_nodes = false; bool list_fstype = false; - bool reverse = false; char **mounts = NULL; int opt; + int result; + +#define DO_REG(_var) \ + if (_var) free (_var); \ + _var = get_regex (optarg); while ((opt = getopt_long (argc, argv, getoptstring, longopts, (int *) 0)) != -1) + { switch (opt) { - case 'F': - if (fstype_regex) - free (fstype_regex); - fstype_regex = rc_xmalloc (sizeof (regex_t)); - if ((result = regcomp (fstype_regex, optarg, - REG_EXTENDED | REG_NOSUB)) != 0) - { - regerror (result, fstype_regex, buffer, sizeof (buffer)); - eerrorx ("%s: invalid regex `%s'", argv[0], buffer); - } - break; - - case 'N': - if (node_regex) - free (node_regex); - node_regex = rc_xmalloc (sizeof (regex_t)); - if ((result = regcomp (node_regex, optarg, - REG_EXTENDED | REG_NOSUB)) != 0) - { - regerror (result, node_regex, buffer, sizeof (buffer)); - eerrorx ("%s: invalid regex `%s'", argv[0], buffer); - } - break; - - case 'S': - if (skip_regex) - free (skip_regex); - skip_regex = rc_xmalloc (sizeof (regex_t)); - if ((result = regcomp (skip_regex, optarg, - REG_EXTENDED | REG_NOSUB)) != 0) - { - regerror (result, skip_regex, buffer, sizeof (buffer)); - eerrorx ("%s: invalid regex `%s'", argv[0], buffer); - } - break; - case 'f': - list_fstype = true; - list_nodes = false; + DO_REG (fstype_regex); + break; + case 'F': + DO_REG (skip_fstype_regex); break; - case 'n': + DO_REG (node_regex); + break; + case 'N': + DO_REG (skip_node_regex); + break; + case 'p': + DO_REG (point_regex); + break; + case 'P': + DO_REG (skip_point_regex); + break; + case 'o': list_nodes = true; list_fstype = false; break; - - case 'r': - reverse = true; + case 's': + list_nodes = false; + list_fstype = true; break; - case_RC_COMMON_GETOPT + case_RC_COMMON_GETOPT } + } while (optind < argc) { if (argv[optind][0] != '/') eerrorx ("%s: `%s' is not a mount point", argv[0], argv[optind]); mounts = rc_strlist_add (mounts, argv[optind++]); } - nodes = find_mounts (node_regex, fstype_regex, mounts, - list_nodes, list_fstype); + + nodes = find_mounts (node_regex, skip_node_regex, + fstype_regex, skip_fstype_regex, + mounts, list_nodes, list_fstype); if (node_regex) regfree (node_regex); + if (skip_node_regex) + regfree (skip_node_regex); if (fstype_regex) regfree (fstype_regex); + if (skip_fstype_regex) + regfree (skip_fstype_regex); - if (reverse) - rc_strlist_reverse (nodes); + rc_strlist_reverse (nodes); result = EXIT_FAILURE; STRLIST_FOREACH (nodes, node, i) { - if (skip_regex && regexec (skip_regex, node, 0, NULL, 0) == 0) + if (point_regex && regexec (point_regex, node, 0, NULL, 0) != 0) + continue; + if (skip_point_regex && regexec (skip_point_regex, node, 0, NULL, 0) == 0) continue; printf ("%s\n", node); result = EXIT_SUCCESS; } rc_strlist_free (nodes); - if (skip_regex) - free (skip_regex); + if (point_regex) + regfree (point_regex); + if (skip_point_regex) + regfree (skip_point_regex); exit (result); }