*
*/
+#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <getopt.h>
#include <mntent.h>
#include <sys/mount.h>
#include <ctype.h>
+#include <pwd.h>
#include "xcommon.h"
#include "fstab.h"
res = mount(spec, node, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (res == 0) {
- nfs_mntent_t remnt;
+ struct mntent remnt;
fprintf(stderr,
_("umount: %s busy - remounted read-only\n"),
spec);
/*
* Returns 1 if everything went well, else 0.
*/
-int _nfsumount(const char *spec, const char *opts)
+int _nfsumount(const char *spec, char *opts)
{
char *hostname;
char *dirname;
goto out_bad;
return nfs_call_umount(&mnt_server, &dirname);
out_bad:
- printf("%s: %s: not found or not mounted\n", progname, spec);
+ fprintf(stderr, "%s: %s: not found or not mounted\n", progname, spec);
return 0;
}
argv += 1;
argc -= 1;
+ argv[0] = argv[-1]; /* So that getopt error messages are correct */
while ((c = getopt_long (argc, argv, "fvnrlh",
umount_longopts, NULL)) != -1) {
return 0;
}
}
+ if (optind != argc) {
+ umount_usage();
+ return 0;
+ }
if (spec == NULL || (*spec != '/' && strchr(spec,':') == NULL)) {
printf(_("umount: %s: not found\n"), spec);
if (!mc && verbose)
printf(_("Could not find %s in mtab\n"), spec);
- if (mc) {
- ret = _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
- if(ret)
- ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
- } else {
- if (*spec != '/')
- ret = _nfsumount(spec, "tcp,v3");
- else
- ret = del_mtab(NULL, spec);
+ if (mc && strcmp(mc->m.mnt_type, "nfs") != 0 &&
+ strcmp(mc->m.mnt_type, "nfs4") != 0) {
+ fprintf(stderr, "umount.nfs: %s on %s it not an nfs filesystem\n",
+ mc->m.mnt_fsname, mc->m.mnt_dir);
+ exit(1);
+ }
+
+ if (getuid() != 0) {
+ /* only permitted if "user=" or "users" is in mount options */
+ if (!mc) {
+ /* umount might call us twice. The second time there will
+ * be no entry in mtab and we should just exit quietly
+ */
+ return 0;
+
+ only_root:
+ fprintf(stderr,"%s: You are not permitted to unmount %s\n",
+ progname, spec);
+ return 0;
+ }
+ if (hasmntopt(&mc->m, "users") == NULL) {
+ char *opt = hasmntopt(&mc->m, "user");
+ struct passwd *pw;
+ char *comma;
+ int len;
+ if (!opt)
+ goto only_root;
+ if (opt[4] != '=')
+ goto only_root;
+ comma = strchr(opt, ',');
+ if (comma)
+ len = comma - (opt + 5);
+ else
+ len = strlen(opt+5);
+ pw = getpwuid(getuid());
+ if (pw == NULL || strlen(pw->pw_name) != len
+ || strncmp(pw->pw_name, opt+5, len) != 0)
+ goto only_root;
+ }
}
+ ret = 0;
+ if (mc) {
+ if (!lazy)
+ _nfsumount(mc->m.mnt_fsname, mc->m.mnt_opts);
+ ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
+ } else if (*spec != '/') {
+ if (!lazy)
+ _nfsumount(spec, "tcp,v3");
+ } else
+ ret = del_mtab(NULL, spec);
+
return(ret);
}