/*
 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
 *
 * 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.
 *
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 0211-1301 USA
 *
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#include "sockaddr.h"
#include "nfs_mount.h"
#include "nls.h"
#include "xcommon.h"
#include "version.h"
#include "error.h"
#include "utils.h"
#include "mount.h"
#include "network.h"
#include "parse_dev.h"

extern int verbose;
extern char *progname;

/*
 * Choose the version of the nfs_mount_data structure that is appropriate
 * for the kernel that is doing the mount.
 *
 * NFS_MOUNT_VERSION:		maximum version supported by these sources
 * nfs_mount_data_version:	maximum version supported by the running kernel
 */
int discover_nfs_mount_data_version(int *string_ver)
{
	unsigned int kernel_version = linux_version_code();
	int ver = 0;

	*string_ver = 0;

	if (kernel_version) {
		if (kernel_version < MAKE_VERSION(2, 1, 32))
			ver = 1;
		else if (kernel_version < MAKE_VERSION(2, 2, 18))
			ver = 3;
		else if (kernel_version < MAKE_VERSION(2, 3, 0))
			ver = 4;
		else if (kernel_version < MAKE_VERSION(2, 3, 99))
			ver = 3;
		else if (kernel_version < MAKE_VERSION(2, 6, 3))
			ver = 4;
		else
			ver = 6;
	}
	if (ver > NFS_MOUNT_VERSION)
		ver = NFS_MOUNT_VERSION;
	else
		if (kernel_version > MAKE_VERSION(2, 6, 22))
			(*string_ver)++;

	return ver;
}

void print_one(char *spec, char *node, char *type, char *opts)
{
	if (!verbose)
		return;

	if (opts)
		printf(_("%s on %s type %s (%s)\n"), spec, node, type, opts);
	else
		printf(_("%s on %s type %s\n"), spec, node, type);
}

void mount_usage(void)
{
	printf(_("usage: %s remotetarget dir [-rvVwfnsh] [-o nfsoptions]\n"),
		progname);
	printf(_("options:\n"));
	printf(_("\t-r\t\tMount file system readonly\n"));
	printf(_("\t-v\t\tVerbose\n"));
	printf(_("\t-V\t\tPrint version\n"));
	printf(_("\t-w\t\tMount file system read-write\n"));
	printf(_("\t-f\t\tFake mount, do not actually mount\n"));
	printf(_("\t-n\t\tDo not update /etc/mtab\n"));
	printf(_("\t-s\t\tTolerate sloppy mount options rather than fail\n"));
	printf(_("\t-h\t\tPrint this help\n"));
	printf(_("\tnfsoptions\tRefer to mount.nfs(8) or nfs(5)\n\n"));
}

void umount_usage(void)
{
	printf(_("usage: %s dir [-fvnrlh]\n"), progname);
	printf(_("options:\n\t-f\t\tforce unmount\n"));
	printf(_("\t-v\tverbose\n"));
	printf(_("\t-n\tDo not update /etc/mtab\n"));
	printf(_("\t-r\tremount\n"));
	printf(_("\t-l\tlazy unmount\n"));
	printf(_("\t-h\tprint this help\n\n"));
}

int chk_mountpoint(const char *mount_point)
{
	struct stat sb;

	if (stat(mount_point, &sb) < 0){
		mount_error(NULL, mount_point, errno);
		return 1;
	}
	if (S_ISDIR(sb.st_mode) == 0){
		mount_error(NULL, mount_point, ENOTDIR);
		return 1;
	}
	if (getuid() != 0 && geteuid() != 0 && access(mount_point, X_OK) < 0) {
		mount_error(NULL, mount_point, errno);
		return 1;
	}

	return 0;
}

/*
 * Pick up certain mount options used during the original mount
 * from /etc/mtab.  The basics include the server's IP address and
 * the server pathname of the share to unregister.
 *
 * These options might also describe the mount port, mount protocol
 * version, and transport protocol used to punch through a firewall.
 * We will need this information to get through the firewall again
 * to do the umount.
 *
 * Note that option parsing failures won't necessarily cause the
 * umount request to fail.  Those values will be left zero in the
 * pmap tuple.  If the GETPORT call later fails to disambiguate them,
 * then we fail.
 */
int nfs_umount23(const char *devname, char *string)
{
	char *hostname = NULL, *dirname = NULL;
	struct mount_options *options;
	int result = EX_FAIL;

	if (!nfs_parse_devname(devname, &hostname, &dirname))
		return EX_USAGE;

	options = po_split(string);
	if (options) {
		result = nfs_umount_do_umnt(options, &hostname, &dirname);
		po_destroy(options);
	} else
		nfs_error(_("%s: option parsing error"), progname);

	free(hostname);
	free(dirname);
	return result;
}
