/*
 * nfsumount.c -- Linux NFS umount
 * Copyright (C) 2006 Amit Gud <agud@redhat.com>
 *
 * - Basic code and wrapper around NFS umount code originally
 *   in util-linux/mount/nfsmount.c
 *
 * This program 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.
 *
 * This program 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.
 *
 */

#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"
#include "nls.h"

#include "mount_constants.h"
#include "nfs_mount.h"
#include "mount.h"
#include "error.h"
#include "network.h"
#include "parse_opt.h"
#include "parse_dev.h"
#include "utils.h"

#define MOUNTSFILE	"/proc/mounts"
#define LINELEN		(4096)

#if !defined(MNT_FORCE)
/* dare not try to include <linux/mount.h> -- lots of errors */
#define MNT_FORCE 1
#endif

#if !defined(MNT_DETACH)
#define MNT_DETACH 2
#endif

extern char *progname;
extern int nomtab;
extern int verbose;
int force;
int lazy;
int remount;


static int try_remount(const char *spec, const char *node)
{
	int res;

	res = mount(spec, node, NULL,
		    MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
	if (res == 0) {
		struct mntent remnt;
		nfs_error(_("%s: %s busy - remounted read-only"),
				progname, spec);
		remnt.mnt_type = remnt.mnt_fsname = NULL;
		remnt.mnt_dir = xstrdup(node);
		remnt.mnt_opts = xstrdup("ro");
		if (!nomtab)
			update_mtab(node, &remnt);
	} else if (errno != EBUSY) {    /* hmm ... */
		perror(_("remount"));
		nfs_error(_("%s: could not remount %s read-only"),
				progname, spec);
	}
	return res;
}

static int del_mtab(const char *spec, const char *node)
{
	int umnt_err, res;

	umnt_err = 0;
	if (lazy) {
		res = umount2 (node, MNT_DETACH);
		if (res < 0)
			umnt_err = errno;
		goto writemtab;
	}

	if (force) {
		res = umount2 (node, MNT_FORCE);
		if (res == -1) {
			int errsv = errno;
			perror(_("umount2"));
			errno = errsv;
			if (errno == ENOSYS) {
				if (verbose)
					printf(_("no umount2, trying umount...\n"));
				res = umount (node);
			}
		}
	} else
		res = umount (node);

	if (res < 0) {
		if (remount && errno == EBUSY && spec) {
			res = try_remount(spec, node);
			if (res)
				goto writemtab;
			return EX_SUCCESS;
		} else
			umnt_err = errno;
	}

	if (res >= 0) {
		/* Umount succeeded */
		if (verbose)
			printf(_("%s umounted\n"), spec ? spec : node);
	}

 writemtab:
	if (!nomtab &&
	    (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) {
		update_mtab(node, NULL);
	}

	if (res >= 0)
		return EX_SUCCESS;

	if (umnt_err)
		umount_error(umnt_err, node);
	return EX_FILEIO;
}

/*
 * Detect NFSv4 mounts.
 *
 * Consult /proc/mounts to determine if the mount point
 * is an NFSv4 mount.  The kernel is authoritative about
 * what type of mount this is.
 *
 * Returns 1 if "mc" is an NFSv4 mount, zero if not, and
 * -1 if some error occurred.
 */
static int nfs_umount_is_vers4(const struct mntentchn *mc)
{
	struct mntentchn *pmc;
	struct mount_options *options;
	int retval;

	retval = -1;
	pmc = getprocmntdirbackward(mc->m.mnt_dir, NULL);
	if (!pmc)
		goto not_found;

	do {
		size_t nlen = strlen(pmc->m.mnt_fsname);

		/*
		 * It's possible the mount location string in /proc/mounts
		 * ends with a '/'. In this case, if the entry came from
		 * /etc/mtab, it won't have the trailing '/' so deal with
		 * it.
		 */
		while (pmc->m.mnt_fsname[nlen - 1] == '/')
			nlen--;
		if (strncmp(pmc->m.mnt_fsname, mc->m.mnt_fsname, nlen) != 0)
			continue;

		if (strcmp(pmc->m.mnt_type, "nfs4") == 0)
			goto out_nfs4;

		options = po_split(pmc->m.mnt_opts);
		if (options != NULL) {
			unsigned long version;
			int rc = nfs_nfs_version(options, &version);
			po_destroy(options);
			if (rc && version == 4)
				goto out_nfs4;
		}

		if (strcmp(pmc->m.mnt_type, "nfs") == 0)
			goto out_nfs;
	} while ((pmc = getprocmntdirbackward(mc->m.mnt_dir, pmc)) != NULL);

	if (retval == -1) {
not_found:
		fprintf(stderr, "%s was not found in %s\n",
			mc->m.mnt_dir, MOUNTSFILE);
		goto out;
	}

out_nfs4:
	if (verbose)
		fprintf(stderr, "NFSv4 mount point detected\n");
	retval = 1;
	goto out;

out_nfs:
	if (verbose)
		fprintf(stderr, "Legacy NFS mount point detected\n");
	retval = 0;

out:
	return retval;
}

static struct option umount_longopts[] =
{
  { "force", 0, 0, 'f' },
  { "help", 0, 0, 'h' },
  { "no-mtab", 0, 0, 'n' },
  { "verbose", 0, 0, 'v' },
  { "read-only", 0, 0, 'r' },
  { NULL, 0, 0, 0 }
};

int nfsumount(int argc, char *argv[])
{
	int c, ret;
	char *spec;
	struct mntentchn *mc;

	if (argc < 2) {
		umount_usage();
		return EX_USAGE;
	}

	spec = argv[1];

	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) {

		switch (c) {
		case 'f':
			++force;
			break;
		case 'v':
			++verbose;
			break;
		case 'n':
			++nomtab;
			break;
		case 'r':
			++remount;
			break;
		case 'l':
			++lazy;
			break;
		case 'h':
		default:
			umount_usage();
			return EX_USAGE;
		}
	}
	if (optind != argc) {
		umount_usage();
		return EX_USAGE;
	}
	
	if (spec == NULL || (*spec != '/' && strchr(spec,':') == NULL)) {
		nfs_error(_("%s: %s: not found\n"), progname, spec);
		return EX_USAGE;
	}

	if (*spec == '/')
		mc = getmntdirbackward(spec, NULL);
	else
		mc = getmntdevbackward(spec, NULL);
	if (!mc && verbose)
		printf(_("Could not find %s in mtab\n"), spec);

	if (mc && strcmp(mc->m.mnt_type, "nfs") != 0 &&
	    strcmp(mc->m.mnt_type, "nfs4") != 0) {
		nfs_error(_("%s: %s on %s is not an NFS filesystem"),
				progname, mc->m.mnt_fsname, mc->m.mnt_dir);
		return EX_USAGE;
	}

	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 EX_SUCCESS;

		only_root:
			nfs_error(_("%s: You are not permitted to unmount %s"),
					progname, spec);
			return EX_USAGE;
		}
		if (hasmntopt(&mc->m, "users") == NULL) {
			char *opt = hasmntopt(&mc->m, "user");
			struct passwd *pw;
			char *comma;
			size_t 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 = EX_SUCCESS;
	if (mc) {
		if (!lazy) {
			switch (nfs_umount_is_vers4(mc)) {
			case 0:
				/* We ignore the error from nfs_umount23.
				 * If the actual umount succeeds (in del_mtab),
				 * we don't want to signal an error, as that
				 * could cause /sbin/mount to retry!
				 */
				nfs_umount23(mc->m.mnt_fsname, mc->m.mnt_opts);
				break;
			case 1:
				break;
			default:
				return EX_FAIL;
			}
		}
		ret = del_mtab(mc->m.mnt_fsname, mc->m.mnt_dir);
	} else if (*spec != '/') {
		if (!lazy)
			ret = nfs_umount23(spec, "tcp,v3");
	} else
		ret = del_mtab(NULL, spec);

	return ret;
}
