diff options
-rw-r--r-- | debian/changelog | 6 | ||||
-rw-r--r-- | debian/patches/mount-ignore-mounted-all.patch | 32 | ||||
-rw-r--r-- | debian/patches/mount-t-auto.patch | 86 | ||||
-rw-r--r-- | debian/patches/mount-test-opts.patch | 214 | ||||
-rw-r--r-- | debian/patches/series | 8 | ||||
-rw-r--r-- | debian/patches/sutils-multiple-none.patch | 40 | ||||
-rw-r--r-- | debian/patches/sutils-types.patch | 150 | ||||
-rw-r--r-- | debian/patches/umount.patch | 382 |
8 files changed, 916 insertions, 2 deletions
diff --git a/debian/changelog b/debian/changelog index 92161bc2..dadaa49c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,8 +1,10 @@ hurd (20130620-1.1) UNRELEASED; urgency=low - * patches/mount-{f,n,remount}.patch: New patches from Justus Winter to make - mount more compatible with Linux'. + * patches/{mount-{f,n,remount,test-opts,ignore-mounted-all,t-auto}, + sutils-{types,multiple-none}}.patch: New + patches from Justus Winter to make mount more compatible with Linux'. * patches/mount-loop.patch: New patch to ignore loop option. + * patches/umount.patch: New patch to add umount tool. * patches/procfs-{update,default,get-options}.patch: New patches from Justus Winter to make procfs behave as sysvinit desires. diff --git a/debian/patches/mount-ignore-mounted-all.patch b/debian/patches/mount-ignore-mounted-all.patch new file mode 100644 index 00000000..b3890d4a --- /dev/null +++ b/debian/patches/mount-ignore-mounted-all.patch @@ -0,0 +1,32 @@ +Linux' mount utility ignores mounted filesystems if mount --all is +invoked. This patch makes our mount do the same. + +utils/mount.c (main): Ignore mounted filesystems if --all is given. +--- + utils/mount.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/utils/mount.c b/utils/mount.c +index 73a7539..77b2138 100644 +--- a/utils/mount.c ++++ b/utils/mount.c +@@ -631,6 +631,15 @@ main (int argc, char **argv) + + if (! match_options (&fs->mntent)) + continue; ++ ++ fsys_t mounted; ++ err = fs_fsys (fs, &mounted); ++ if (err) ++ error (0, err, "cannot determine if %s is already mounted", ++ fs->mntent.mnt_fsname); ++ ++ if (mounted != MACH_PORT_NULL) ++ continue; + } + err |= do_mount (fs, remount); + } +-- +1.7.10.4 + + diff --git a/debian/patches/mount-t-auto.patch b/debian/patches/mount-t-auto.patch new file mode 100644 index 00000000..5f800f41 --- /dev/null +++ b/debian/patches/mount-t-auto.patch @@ -0,0 +1,86 @@ +Use libblkid to detect the filesystem type if "auto" is given as +type. Remove the translator localization from main, this is also done +in do_mount and any errors are propagated properly. This way "auto" is +handled correctly if given on the command line or used as filesystem +type in the fstab. + +* utils/mount.c (DEFAULT_FSTYPE): Use "auto" as default type. +(do_mount): Detect type using libblkid. +(main): Drop translator localization. +--- + utils/Makefile | 1 + + utils/mount.c | 27 +++++++++++++++++++-------- + 2 files changed, 20 insertions(+), 8 deletions(-) + +diff --git a/utils/Makefile b/utils/Makefile +index 6975fb5..207c904 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -37,6 +37,7 @@ LDLIBS += -lpthread + login-LDLIBS = -lutil $(LIBCRYPT) + addauth-LDLIBS = $(LIBCRYPT) + setauth-LDLIBS = $(LIBCRYPT) ++mount-LDLIBS = -lblkid + + INSTALL-login-ops = -o root -m 4755 + INSTALL-ids-ops = -o root -m 4755 +diff --git a/utils/mount.c b/utils/mount.c +index 77b2138..5863f96 100644 +--- a/utils/mount.c ++++ b/utils/mount.c +@@ -28,11 +28,12 @@ + #include <hurd/fsys.h> + #include <hurd/fshelp.h> + #include <hurd/paths.h> ++#include <blkid/blkid.h> + + #include "match-options.h" + + #define SEARCH_FMTS _HURD "%sfs\0" _HURD "%s" +-#define DEFAULT_FSTYPE "ext2" ++#define DEFAULT_FSTYPE "auto" + + static char *fstype = DEFAULT_FSTYPE; + static char *device, *mountpoint; +@@ -338,6 +339,23 @@ do_mount (struct fs *fs, int remount) + return EBUSY; + } + ++ if (strcmp (fs->mntent.mnt_type, "auto") == 0) ++ { ++ char *type = ++ blkid_get_tag_value (NULL, "TYPE", fs->mntent.mnt_fsname); ++ if (! type) ++ { ++ error (0, 0, "failed to detect file system type"); ++ return EFTYPE; ++ } ++ else ++ { ++ fs->mntent.mnt_type = strdup (type); ++ if (! fs->mntent.mnt_type) ++ error (3, ENOMEM, "failed to allocate memory"); ++ } ++ } ++ + err = fs_type (fs, &type); + if (err) + { +@@ -579,13 +597,6 @@ main (int argc, char **argv) + mnt_opts: 0, + mnt_freq: 0, mnt_passno: 0 + }; +- struct fstype *fst; +- +- err = fstypes_get (fstab->types, fstype, &fst); +- if (err) +- error (106, err, "cannot initialize type %s", fstype); +- if (fst->program == 0) +- error (2, 0, "filesystem type %s not recognized", fstype); + + err = fstab_add_mntent (fstab, &m, &fs); + if (err) +-- +1.7.10.4 + + diff --git a/debian/patches/mount-test-opts.patch b/debian/patches/mount-test-opts.patch new file mode 100644 index 00000000..e694b69f --- /dev/null +++ b/debian/patches/mount-test-opts.patch @@ -0,0 +1,214 @@ +--test-opts in combination with --all mounts only those filesystems +with options matching the given set of options. + +Note that the semantic of the inverting "no" prefix differs from +--types: While --types=nonfs,ufs means neither nfs nor ufs, +--test-opts=nofoo,bar means not foo, but bar. + +* utils/match-options.h: New file. +* utils/match-options.c: Likewise. +(test_opts): New variable. +(test_opts_len): Likewise. +(match_options): New function. +* utils/mount.c (parse_opt): Handle -O, --test-opts. +(main): Use match_options as filter. +--- + utils/Makefile | 5 ++-- + utils/match-options.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++ + utils/match-options.h | 33 ++++++++++++++++++++++++ + utils/mount.c | 19 ++++++++++++-- + 4 files changed, 121 insertions(+), 4 deletions(-) + create mode 100644 utils/match-options.c + create mode 100644 utils/match-options.h + +diff --git a/utils/Makefile b/utils/Makefile +index e3bed0b..6975fb5 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -28,7 +28,8 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ + uptime.sh psout.c ids.c vmstat.c portinfo.c devprobe.c vminfo.c \ + parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ + unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ +- rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh ++ rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ ++ match-options.c + + OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) + HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc +@@ -72,7 +73,7 @@ fakeauth-CPPFLAGS = -I$(srcdir)/../auth + authServer-CPPFLAGS = -I$(srcdir)/../auth + auth_requestUser-CPPFLAGS = -I$(srcdir)/../auth + +-mount: ../sutils/fstab.o ../sutils/clookup.o \ ++mount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ + $(foreach L,fshelp ports,../lib$L/lib$L.a) + ../sutils/fstab.o ../sutils/clookup.o: FORCE + $(MAKE) -C $(@D) $(@F) +diff --git a/utils/match-options.c b/utils/match-options.c +new file mode 100644 +index 0000000..11fc9dc +--- /dev/null ++++ b/utils/match-options.c +@@ -0,0 +1,68 @@ ++/* Common functionality for the --test-opts flag of mount and umount. ++ ++ Copyright (C) 2013 Free Software Foundation, Inc. ++ Written by Justus Winter <4winter@informatik.uni-hamburg.de> ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ ++#include <argz.h> ++#include <error.h> ++#include <stdlib.h> ++#include <string.h> ++ ++#include "match-options.h" ++ ++char *test_opts; ++size_t test_opts_len; ++ ++int ++match_options (struct mntent *mntent) ++{ ++ char *opts; ++ size_t opts_len; ++ ++ error_t err = argz_create_sep (mntent->mnt_opts, ',', &opts, &opts_len); ++ if (err) ++ error (3, err, "parsing mount options failed"); ++ ++ for (char *test = test_opts; ++ test; test = argz_next (test_opts, test_opts_len, test)) ++ { ++ char *needle = test; ++ int inverse = strncmp("no", needle, 2) == 0; ++ if (inverse) ++ needle += 2; ++ ++ int match = 0; ++ for (char *opt = opts; opt; opt = argz_next (opts, opts_len, opt)) ++ { ++ if (strcmp (opt, needle) == 0) { ++ if (inverse) ++ return 0; /* foo in opts, nofoo in test_opts. */ ++ ++ /* foo in opts, foo in test_opts, record match. */ ++ match = 1; ++ } ++ } ++ ++ if (! inverse && ! match) ++ return 0; /* No foo in opts, but foo in test_opts. */ ++ } ++ ++ /* If no conflicting test_opt was encountered, return success. */ ++ return 1; ++} +diff --git a/utils/match-options.h b/utils/match-options.h +new file mode 100644 +index 0000000..ea7ae70 +--- /dev/null ++++ b/utils/match-options.h +@@ -0,0 +1,33 @@ ++/* Common functionality for the --test-opts flag of mount and umount. ++ ++ Copyright (C) 2013 Free Software Foundation, Inc. ++ Written by Justus Winter <4winter@informatik.uni-hamburg.de> ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ ++#include <mntent.h> ++ ++extern char *test_opts; ++extern size_t test_opts_len; ++ ++/* Check whether the given mount entry matches the given set of ++ options. ++ ++ Returns 0 if foo is in the options vector but nofoo is in test_opts. ++ Returns 0 if foo is in test_opts but foo is not in the options vector. */ ++int ++match_options (struct mntent *mntent); +diff --git a/utils/mount.c b/utils/mount.c +index f8928f1..73a7539 100644 +--- a/utils/mount.c ++++ b/utils/mount.c +@@ -29,6 +29,8 @@ + #include <hurd/fshelp.h> + #include <hurd/paths.h> + ++#include "match-options.h" ++ + #define SEARCH_FMTS _HURD "%sfs\0" _HURD "%s" + #define DEFAULT_FSTYPE "ext2" + +@@ -57,6 +59,8 @@ static const struct argp_option argp_opts[] = + {"remount", 0, 0, OPTION_ALIAS}, + {"verbose", 'v', 0, 0, "Give more detailed information"}, + {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, ++ {"test-opts", 'O', "OPTIONS", 0, ++ "Only mount fstab entries matching the given set of options"}, + {"fake", 'f', 0, 0, "Do not actually mount, just pretend"}, + {0, 0} + }; +@@ -122,6 +126,12 @@ parse_opt (int key, char *arg, struct argp_state *state) + fake = 1; + break; + ++ case 'O': ++ err = argz_create_sep (arg, ',', &test_opts, &test_opts_len); ++ if (err) ++ argp_failure (state, 100, ENOMEM, "%s", arg); ++ break; ++ + case ARGP_KEY_ARG: + if (mountpoint == 0) /* One arg: mountpoint */ + mountpoint = arg; +@@ -615,8 +625,13 @@ main (int argc, char **argv) + case mount: + for (fs = fstab->entries; fs; fs = fs->next) + { +- if (fstab_params.do_all && hasmntopt (&fs->mntent, MNTOPT_NOAUTO)) +- continue; ++ if (fstab_params.do_all) { ++ if (hasmntopt (&fs->mntent, MNTOPT_NOAUTO)) ++ continue; ++ ++ if (! match_options (&fs->mntent)) ++ continue; ++ } + err |= do_mount (fs, remount); + } + break; +-- +1.7.10.4 + + diff --git a/debian/patches/series b/debian/patches/series index 52ff2b98..2e80be7b 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -41,6 +41,8 @@ libmachdev.patch exec_filename_exec.patch exec_filename_fs.patch exec_filename_use.patch + +# Justus Winter's work, to be pushed mount-n.patch mount-f.patch mount-remount.patch @@ -48,3 +50,9 @@ mount-loop.patch procfs-update.patch procfs-default.patch procfs-get-options.patch +sutils-types.patch +mount-test-opts.patch +mount-ignore-mounted-all.patch +mount-t-auto.patch +sutils-multiple-none.patch +umount.patch diff --git a/debian/patches/sutils-multiple-none.patch b/debian/patches/sutils-multiple-none.patch new file mode 100644 index 00000000..c787b5a7 --- /dev/null +++ b/debian/patches/sutils-multiple-none.patch @@ -0,0 +1,40 @@ +Previously it was not possible to add two mount entries with the same +device information to an fstab structure. This is easily fixed by +breaking the assumption, that there is only one possible mount entry +for the "none" device as used by many purely virtual file systems. + +* utils/fstab.c (fstab_find_device): Return NULL if name is "none". +--- + sutils/fstab.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/sutils/fstab.c b/sutils/fstab.c +index e241de6..d3b8b6f 100644 +--- a/sutils/fstab.c ++++ b/sutils/fstab.c +@@ -457,11 +457,19 @@ fs_remount (struct fs *fs) + return err; + } + +-/* Returns the FS entry in FSTAB with the device field NAME (there can only +- be one such entry). */ ++/* Returns the FS entry in FSTAB with the device field NAME. ++ ++ In general there can only be one such entry. This holds not true ++ for virtual file systems that use "none" as device name. ++ ++ If name is "none", NULL is returned. This also makes it possible to ++ add more than one entry for the device "none". */ + inline struct fs * + fstab_find_device (const struct fstab *fstab, const char *name) + { ++ if (strcmp (name, "none") == 0) ++ return NULL; ++ + struct fs *fs; + for (fs = fstab->entries; fs; fs = fs->next) + if (strcmp (fs->mntent.mnt_fsname, name) == 0) +-- +1.7.10.4 + + diff --git a/debian/patches/sutils-types.patch b/debian/patches/sutils-types.patch new file mode 100644 index 00000000..d2a21e94 --- /dev/null +++ b/debian/patches/sutils-types.patch @@ -0,0 +1,150 @@ +The mount utility on both Linux and FreeBSD allows one to either +specify a whitelist or a blacklist of filesystem types to consider for +--all. Prefixing the list with "no" indicates that the list is a +blacklist. Furthermore, Linux' mount utility ignores a "no" prefix on +any entry in the given list. + +Previously the Hurd variant first applied whitelist containing all +positive values given and then filtered the resulting list using all +negative values. But this makes little sense because each entry only +has one value for the filesystem type (mnt_type) and all values are +mutually exclusive. + +This patch adjusts the fstab handling code so that our mount utility +behaves like the Linux mount utility. This code is used by both mount +and fsck. The same argumentation applies to fsck as well. + +Like implemented in Linux mount, any "no" prefix is ignored to retain +compatibility with the old behavior. + +* sutils/fstab.c (fstab_argp_create): Fix semantic of --types. +--- + sutils/fstab.c | 103 +++++++++++++++----------------------------------------- + 1 file changed, 27 insertions(+), 76 deletions(-) + +diff --git a/sutils/fstab.c b/sutils/fstab.c +index b66e519..e241de6 100644 +--- a/sutils/fstab.c ++++ b/sutils/fstab.c +@@ -880,90 +880,41 @@ fstab_argp_create (struct fstab_argp_params *params, + check = fstab; + else + { +- struct fs *fs; +- const char *tn; +- unsigned int nonexclude_types; +- + err = fstab_create (types, &check); + if (err) + error (105, err, "fstab_create"); + +- /* For each excluded type (i.e. `-t notype'), clobber the +- fstype entry's program with an empty string to mark it. */ +- nonexclude_types = 0; +- for (tn = params->types; tn; +- tn = argz_next (params->types, params->types_len, tn)) +- { +- if (!strncasecmp (tn, "no", 2)) +- { +- struct fstype *type; +- err = fstypes_get (types, &tn[2], &type); +- if (err) +- error (106, err, "fstypes_get"); +- free (type->program); +- type->program = strdup (""); +- } +- else +- ++nonexclude_types; +- } +- +- if (nonexclude_types != 0) +- { +- const char *tn; +- struct fstypes *wanttypes; +- +- /* We will copy the types we want to include into a fresh +- list in WANTTYPES. Since we specify no search formats, +- `fstypes_get' applied to WANTTYPES can only create +- elements with a null `program' field. */ +- err = fstypes_create (0, 0, &wanttypes); +- if (err) +- error (102, err, "fstypes_create"); +- +- for (tn = params->types; tn; +- tn = argz_next (params->types, params->types_len, tn)) +- if (strncasecmp (tn, "no", 2)) +- { +- struct fstype *type; +- err = fstypes_get (types, tn, &type); +- if (err) +- error (106, err, "fstypes_get"); +- if (type->program == 0) +- error (0, 0, +- "requested filesystem type `%s' unknown", tn); +- else +- { +- struct fstype *newtype = malloc (sizeof *newtype); +- newtype->name = strdup (type->name); +- newtype->program = strdup (type->program); +- newtype->next = wanttypes->entries; +- wanttypes->entries = newtype; +- } +- } +- +- /* fstypes_free (types); */ +- types = wanttypes; +- } ++ int blacklist = strncasecmp (params->types, "no", 2) == 0; ++ if (blacklist) ++ params->types += 2; /* Skip no. */ + ++ struct fs *fs; + for (fs = fstab->entries; fs; fs = fs->next) + { +- const char *ptn; +- struct fstype *type; +- +- err = fs_type (fs, &type); +- if (err || nonexclude_types) +- { +- err = fstypes_get (types, fs->mntent.mnt_type, &type); +- if (err) +- error (106, err, "fstypes_get"); +- if (params->types != 0) +- continue; +- } +- if (nonexclude_types && type->program == 0) +- continue; /* Freshly created, was not in WANTTYPES. */ +- if (type->program != 0 && type->program[0] == '\0') +- continue; /* This type is marked as excluded. */ ++ if (strcmp (fs->mntent.mnt_type, MNTTYPE_SWAP) == 0) ++ continue; /* Ignore swap entries. */ ++ ++ const char *tn; ++ int matched = 0; ++ for (tn = params->types; tn; ++ tn = argz_next (params->types, params->types_len, tn)) ++ { ++ const char *type = fs->mntent.mnt_type; ++ if (strcmp (type, tn) == 0 ++ /* Skip no for compatibility. */ ++ || ((strncasecmp (type, "no", 2) == 0) ++ && strcmp (type, tn) == 0)) ++ { ++ matched = 1; ++ break; ++ } ++ } ++ ++ if (matched == blacklist) ++ continue; /* Either matched and types is a blacklist ++ or not matched and types is a whitelist */ + ++ const char *ptn; + for (ptn = params->exclude; ptn; + ptn = argz_next (params->exclude, params->exclude_len, ptn)) + if (fnmatch (ptn, fs->mntent.mnt_dir, 0) == 0) +-- +1.7.10.4 + + diff --git a/debian/patches/umount.patch b/debian/patches/umount.patch new file mode 100644 index 00000000..b2f1cafa --- /dev/null +++ b/debian/patches/umount.patch @@ -0,0 +1,382 @@ +This adds a umount utility that implements most of the functions that +the Linux umount utility provides, especially that subset that is used +by the Debian package initscripts. + +* utils/umount.c: New file. +--- + utils/Makefile | 10 +- + utils/umount.c | 319 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 325 insertions(+), 4 deletions(-) + create mode 100644 utils/umount.c + +diff --git a/utils/Makefile b/utils/Makefile +index 207c904..4fe2dc2 100644 +--- a/utils/Makefile ++++ b/utils/Makefile +@@ -21,7 +21,9 @@ makemode := utilities + targets = shd ps settrans showtrans syncfs fsysopts \ + storeinfo login w uptime ids loginpr sush vmstat portinfo \ + devprobe vminfo addauth rmauth unsu setauth ftpcp ftpdir storecat \ +- storeread msgport rpctrace mount gcore fakeauth fakeroot remap ++ storeread msgport rpctrace mount gcore fakeauth fakeroot remap \ ++ umount ++ + special-targets = loginpr sush uptime fakeroot remap + SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ + fsysopts.c storeinfo.c login.c loginpr.sh sush.sh w.c \ +@@ -29,7 +31,7 @@ SRCS = shd.c ps.c settrans.c syncfs.c showtrans.c addauth.c rmauth.c \ + parse.c frobauth.c frobauth-mod.c setauth.c pids.c nonsugid.c \ + unsu.c ftpcp.c ftpdir.c storeread.c storecat.c msgport.c \ + rpctrace.c mount.c gcore.c fakeauth.c fakeroot.sh remap.sh \ +- match-options.c ++ match-options.c umount.c + + OBJS = $(filter-out %.sh,$(SRCS:.c=.o)) + HURDLIBS = ps ihash store fshelp ports ftpconn shouldbeinlibc +@@ -58,7 +60,7 @@ ftpcp ftpdir: ../libftpconn/libftpconn.a + settrans: ../libfshelp/libfshelp.a ../libports/libports.a + ps w ids settrans syncfs showtrans fsysopts storeinfo login vmstat portinfo \ + devprobe vminfo addauth rmauth setauth unsu ftpcp ftpdir storeread \ +- storecat msgport mount: \ ++ storecat msgport mount umount: \ + ../libshouldbeinlibc/libshouldbeinlibc.a + + $(filter-out $(special-targets), $(targets)): %: %.o +@@ -74,7 +76,7 @@ fakeauth-CPPFLAGS = -I$(srcdir)/../auth + authServer-CPPFLAGS = -I$(srcdir)/../auth + auth_requestUser-CPPFLAGS = -I$(srcdir)/../auth + +-mount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ ++mount umount: ../sutils/fstab.o ../sutils/clookup.o match-options.o \ + $(foreach L,fshelp ports,../lib$L/lib$L.a) + ../sutils/fstab.o ../sutils/clookup.o: FORCE + $(MAKE) -C $(@D) $(@F) +diff --git a/utils/umount.c b/utils/umount.c +new file mode 100644 +index 0000000..64e6ee2 +--- /dev/null ++++ b/utils/umount.c +@@ -0,0 +1,319 @@ ++/* Roughly Unix/Linux-compatible `umount' frontend for Hurd translators. ++ ++ Copyright (C) 2013 Free Software Foundation, Inc. ++ Written by Justus Winter <4winter@informatik.uni-hamburg.de> ++ ++ This file is part of the GNU Hurd. ++ ++ The GNU Hurd is free software; you can redistribute it and/or ++ modify it under the terms of the GNU General Public License as ++ published by the Free Software Foundation; either version 2, or (at ++ your option) any later version. ++ ++ The GNU Hurd is distributed in the hope that it will be useful, but ++ WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ ++ ++#include "../sutils/fstab.h" ++#include <argp.h> ++#include <argz.h> ++#include <blkid/blkid.h> ++#include <error.h> ++#include <fcntl.h> ++#include <hurd/fshelp.h> ++#include <hurd/fsys.h> ++#include <hurd/paths.h> ++#include <hurd/process.h> ++#include <stdlib.h> ++#include <unistd.h> ++ ++#include "match-options.h" ++ ++/* XXX fix libc */ ++#undef _PATH_MOUNTED ++#define _PATH_MOUNTED "/etc/mtab" ++ ++static char *targets; ++static size_t targets_len; ++static int readonly; ++static int verbose; ++static int passive_flags = FS_TRANS_SET; ++static int active_flags = FS_TRANS_SET; ++static int goaway_flags; ++static int fake; ++ ++static struct fstab_argp_params fstab_params; ++ ++#define FAKE_KEY 0x80 /* !isascii (FAKE_KEY), so no short option. */ ++ ++static const struct argp_option argp_opts[] = ++{ ++ {"fake", FAKE_KEY, 0, 0, "Do not actually umount, just pretend"}, ++ {"force", 'f', 0, 0, "Force umount by killing the translator"}, ++ {"no-mtab", 'n', 0, 0, "Do not update /etc/mtab"}, ++ {"read-only", 'r', 0, 0, "If unmounting fails, try to remount read-only"}, ++ {"nosync", 'S', 0, 0, "Don't sync a translator before killing it"}, ++ {"test-opts", 'O', "OPTIONS", 0, ++ "Only mount fstab entries matching the given set of options"}, ++ {"verbose", 'v', 0, 0, "Give more detailed information"}, ++ {}, ++}; ++ ++static error_t ++parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ struct fstab_argp_params *params = state->input; ++ error_t err; ++ switch (key) ++ { ++ case ARGP_KEY_INIT: ++ state->child_inputs[0] = params; /* pass down to fstab_argp parser */ ++ break; ++ ++ case FAKE_KEY: ++ fake = 1; ++ break; ++ ++ case 'f': ++ goaway_flags |= FSYS_GOAWAY_FORCE; ++ break; ++ ++ case 'n': ++ /* do nothing */ ++ break; ++ ++ case 'r': ++ readonly = 1; ++ break; ++ ++ case 'S': ++ goaway_flags |= FSYS_GOAWAY_NOSYNC; ++ break; ++ ++ case 'O': ++ err = argz_create_sep (arg, ',', &test_opts, &test_opts_len); ++ if (err) ++ argp_failure (state, 100, ENOMEM, "%s", arg); ++ break; ++ ++ case 'v': ++ verbose += 1; ++ break; ++ ++ case ARGP_KEY_ARG: ++ err = argz_add (&targets, &targets_len, arg); ++ if (err) ++ argp_failure (state, 100, ENOMEM, "%s", arg); ++ break; ++ ++ case ARGP_KEY_NO_ARGS: ++ if (! params->do_all) ++ { ++ argp_error (state, ++ "filesystem argument required if --all is not given"); ++ return EINVAL; ++ } ++ break; ++ ++ case ARGP_KEY_END: ++ if (params->do_all && targets) ++ { ++ argp_error (state, "filesystem argument not allowed with --all"); ++ return EINVAL; ++ } ++ break; ++ ++ default: ++ return ARGP_ERR_UNKNOWN; ++ } ++ ++ return 0; ++} ++ ++static const char doc[] = "Stop active and remove passive translators"; ++static const char args_doc[] = "DEVICE|DIRECTORY [DEVICE|DIRECTORY ...]"; ++ ++static struct argp fstab_argp_mtab; /* Slightly modified version. */ ++ ++static const struct argp_child argp_kids[] = ++{ ++ {&fstab_argp_mtab, 0, ++ "Filesystem selection (if no explicit filesystem arguments given):", 2}, ++ {}, ++}; ++static struct argp argp = ++{ ++ options: argp_opts, ++ parser: parse_opt, ++ args_doc: args_doc, ++ doc: doc, ++ children: argp_kids, ++}; ++ ++/* This is a trimmed and slightly modified version of ++ fstab_argp.options which uses _PATH_MOUNTED instead of _PATH_MNTTAB ++ in the doc strings. */ ++static const struct argp_option fstab_argp_mtab_opts[] = ++{ ++ {"all", 'a', 0, 0, "Do all filesystems in " _PATH_MOUNTED}, ++ {0, 'A', 0, OPTION_ALIAS }, ++ {"fstab", 'F', "FILE", 0, "File to use instead of " _PATH_MOUNTED}, ++ {"fstype", 't', "TYPE", 0, "Do only filesystems of given type(s)"}, ++ {"exclude-root",'R',0, 0, ++ "Exclude root (/) filesystem from " _PATH_MOUNTED " list"}, ++ {"exclude", 'X', "PATTERN", 0, "Exclude directories matching PATTERN"}, ++ {} ++}; ++ ++static error_t ++fstab_argp_mtab_parse_opt (int key, char *arg, struct argp_state *state) ++{ ++ return fstab_argp.parser (key, arg, state); ++} ++ ++static struct argp fstab_argp_mtab = ++{ ++ options: fstab_argp_mtab_opts, ++ parser: fstab_argp_mtab_parse_opt, ++}; ++ ++/* Unmount one filesystem. */ ++static error_t ++do_umount (struct fs *fs) ++{ ++ error_t err = 0; ++ ++ file_t node = file_name_lookup(fs->mntent.mnt_dir, O_NOTRANS, 0666); ++ if (node == MACH_PORT_NULL) ++ { ++ error(0, errno, "%s", fs->mntent.mnt_dir); ++ return errno; ++ } ++ ++ if (verbose) ++ printf ("settrans -pg%s%s %s\n", ++ goaway_flags & FSYS_GOAWAY_NOSYNC? "S": "", ++ goaway_flags & FSYS_GOAWAY_FORCE? "f": "", ++ fs->mntent.mnt_dir); ++ ++ if (! fake) ++ { ++ err = file_set_translator (node, ++ passive_flags, active_flags, goaway_flags, ++ NULL, 0, ++ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND); ++ if (err) ++ { ++ error (0, err, "%s", fs->mntent.mnt_dir); ++ ++ /* Try remounting readonly instead if requested. */ ++ if (readonly) ++ { ++ if (verbose) ++ printf ("fsysopts %s --readonly\n", fs->mntent.mnt_dir); ++ ++ error_t e = fs_set_readonly (fs, TRUE); ++ if (e) ++ error (0, e, "%s", fs->mntent.mnt_dir); ++ } ++ } ++ } ++ ++ /* Deallocate the reference so that unmounting nested translators ++ works properly. */ ++ mach_port_deallocate (mach_task_self (), node); ++ return err; ++} ++ ++int ++main (int argc, char **argv) ++{ ++ error_t err; ++ ++ err = argp_parse (&argp, argc, argv, 0, 0, &fstab_params); ++ if (err) ++ error (3, err, "parsing arguments"); ++ ++ /* Read the mtab file by default. */ ++ if (! fstab_params.fstab_path) ++ fstab_params.fstab_path = _PATH_MOUNTED; ++ ++ struct fstab *fstab = fstab_argp_create (&fstab_params, NULL, 0); ++ if (! fstab) ++ error (3, ENOMEM, "fstab creation"); ++ ++ if (targets) ++ for (char *t = targets; t; t = argz_next (targets, targets_len, t)) ++ { ++ /* Figure out if t is the device or the mountpoint. */ ++ struct fs *fs = fstab_find_mount (fstab, t); ++ if (! fs) ++ { ++ fs = fstab_find_device (fstab, t); ++ if (! fs) ++ { ++ error (0, 0, "could not find entry for: %s", t); ++ ++ /* As last resort, just assume it is the mountpoint. */ ++ struct mntent m = ++ { ++ mnt_fsname: "", ++ mnt_dir: t, ++ mnt_type: "", ++ mnt_opts: 0, ++ mnt_freq: 0, ++ mnt_passno: 0, ++ }; ++ ++ err = fstab_add_mntent (fstab, &m, &fs); ++ if (err) ++ error (2, err, "%s", t); ++ } ++ } ++ ++ if (fs) ++ err |= do_umount (fs); ++ } ++ else ++ { ++ /* Sort entries. */ ++ size_t count = 0; ++ for (struct fs *fs = fstab->entries; fs; fs = fs->next) ++ count += 1; ++ ++ char **entries = malloc (count * sizeof (char *)); ++ if (! entries) ++ error (3, ENOMEM, "allocating entries array"); ++ ++ char **p = entries; ++ for (struct fs *fs = fstab->entries; fs; fs = fs->next) ++ *p++ = fs->mntent.mnt_dir; ++ ++ /* Reverse lexicographical order. */ ++ int compare_entries (const void *a, const void *b) ++ { ++ return -strcmp ((char *) a, (char *) b); ++ } ++ ++ qsort (entries, count, sizeof (char *), compare_entries); ++ ++ for (int i = 0; i < count; i++) ++ { ++ struct fs *fs = fstab_find_mount (fstab, entries[i]); ++ if (! fs) ++ error (4, 0, "could not find entry for: %s", entries[i]); ++ ++ if (! match_options (&fs->mntent)) ++ continue; ++ ++ err |= do_umount (fs); ++ } ++ } ++ ++ return err? EXIT_FAILURE: EXIT_SUCCESS; ++} +-- +1.7.10.4 + + |