Blame fedfs/mount.fedfs.c

Packit Service 4c70d1
/*
Packit Service 4c70d1
 * Copyright 2011 Oracle.  All rights reserved.
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * This file is part of fedfs-utils.
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * fedfs-utils is free software; you can redistribute it and/or modify
Packit Service 4c70d1
 * it under the terms of the GNU General Public License version 2.0 as
Packit Service 4c70d1
 * published by the Free Software Foundation.
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * fedfs-utils is distributed in the hope that it will be useful, but
Packit Service 4c70d1
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 4c70d1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 4c70d1
 * GNU General Public License version 2.0 for more details.
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * You should have received a copy of the GNU General Public License
Packit Service 4c70d1
 * version 2.0 along with fedfs-utils.  If not, see:
Packit Service 4c70d1
 *
Packit Service 4c70d1
 *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
Packit Service 4c70d1
 */
Packit Service 4c70d1
Packit Service 4c70d1
#include <sys/types.h>
Packit Service 4c70d1
#include <sys/stat.h>
Packit Service 4c70d1
#include <sys/socket.h>
Packit Service 4c70d1
#include <sys/mount.h>
Packit Service 4c70d1
#include <sys/wait.h>
Packit Service 4c70d1
Packit Service 4c70d1
#include <stdbool.h>
Packit Service 4c70d1
#include <string.h>
Packit Service 4c70d1
#include <stdlib.h>
Packit Service 4c70d1
#include <unistd.h>
Packit Service 4c70d1
#include <stdio.h>
Packit Service 4c70d1
#include <libgen.h>
Packit Service 4c70d1
#include <errno.h>
Packit Service 4c70d1
#include <getopt.h>
Packit Service 4c70d1
#include <locale.h>
Packit Service 4c70d1
#include <netdb.h>
Packit Service 4c70d1
#include <langinfo.h>
Packit Service 4c70d1
Packit Service 4c70d1
#include "fedfs-nls.h"
Packit Service 4c70d1
#include "fedfs-getsrvinfo.h"
Packit Service 4c70d1
#include "fedfs-gpl-boiler.h"
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Top-level directory on client under which we mount NFSv4 domain roots
Packit Service 4c70d1
 */
Packit Service 4c70d1
#define FEDFS_NFS4_TLDIR		"nfs4"
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Name of SRV record containing NFSv4 FedFS root
Packit Service 4c70d1
 */
Packit Service 4c70d1
#define FEDFS_NFS_DOMAINROOT	"_nfs-domainroot._tcp"
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Export path of NFSv4 FedFS root
Packit Service 4c70d1
 */
Packit Service 4c70d1
#define FEDFS_NFS_EXPORTPATH	"/.domainroot"
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Pathname to mount.nfs
Packit Service 4c70d1
 */
Packit Service 4c70d1
#define MOUNT_NFS_EXECUTABLE		"/sbin/mount.nfs"
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Mount status values, lifted from util-linux
Packit Service 4c70d1
 */
Packit Service 4c70d1
enum {
Packit Service 4c70d1
	EX_SUCCESS	= 0,
Packit Service 4c70d1
	EX_USAGE	= 1,
Packit Service 4c70d1
	EX_FAIL		= 32,
Packit Service 4c70d1
};
Packit Service 4c70d1
Packit Service 4c70d1
static char *progname;
Packit Service 4c70d1
static int nomtab;
Packit Service 4c70d1
static int verbose;
Packit Service 4c70d1
static _Bool readonly;
Packit Service 4c70d1
static _Bool sloppy;
Packit Service 4c70d1
static _Bool fake;
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Short form command line options
Packit Service 4c70d1
 */
Packit Service 4c70d1
static const char fedfs_opts[] = "fhno:rsvVw";
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Long form command line options
Packit Service 4c70d1
 */
Packit Service 4c70d1
static const struct option fedfs_longopts[] =
Packit Service 4c70d1
{
Packit Service 4c70d1
	{ "fake", 0, NULL, 'f' },
Packit Service 4c70d1
	{ "help", 0, NULL, 'h' },
Packit Service 4c70d1
	{ "no-mtab", 0, NULL, 'n' },
Packit Service 4c70d1
	{ "options", 1, NULL, 'o' },
Packit Service 4c70d1
	{ "read-only", 0, NULL, 'r' },
Packit Service 4c70d1
	{ "read-write", 0, NULL, 'w' },
Packit Service 4c70d1
	{ "ro", 0, NULL, 'r' },
Packit Service 4c70d1
	{ "rw", 0, NULL, 'w' },
Packit Service 4c70d1
	{ "sloppy", 0, NULL, 's' },
Packit Service 4c70d1
	{ "verbose", 0, NULL, 'v' },
Packit Service 4c70d1
	{ "version", 0, NULL, 'V' },
Packit Service 4c70d1
	{ NULL, 0, NULL, 0 }
Packit Service 4c70d1
};
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Display mount.fedfs usage message
Packit Service 4c70d1
 */
Packit Service 4c70d1
static void
Packit Service 4c70d1
mount_usage(void)
Packit Service 4c70d1
{
Packit Service 4c70d1
	printf(_("\nUsage: %s remotedir localdir [-fhnrsvVw]\n\n"), progname);
Packit Service 4c70d1
	printf(_("options:\n"));
Packit Service 4c70d1
	printf(_("\t-f\t\tFake mount, do not actually mount\n"));
Packit Service 4c70d1
	printf(_("\t-h\t\tPrint this help\n"));
Packit Service 4c70d1
	printf(_("\t-n\t\tDo not update /etc/mtab\n"));
Packit Service 4c70d1
	printf(_("\t-r\t\tMount file system readonly\n"));
Packit Service 4c70d1
	printf(_("\t-s\t\tTolerate sloppy mount options\n"));
Packit Service 4c70d1
	printf(_("\t-v\t\tVerbose\n"));
Packit Service 4c70d1
	printf(_("\t-V\t\tPrint version\n"));
Packit Service 4c70d1
	printf(_("\t-w\t\tMount file system read-write\n"));
Packit Service 4c70d1
Packit Service 4c70d1
	printf("%s", fedfs_gpl_boilerplate);
Packit Service 4c70d1
}
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Concatenate three strings
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * @param s NUL-terminated C string
Packit Service 4c70d1
 * @param t NUL-terminated C string
Packit Service 4c70d1
 * @param u NUL-terminated C string
Packit Service 4c70d1
 * @return pointer to NUL-terminated C string or NULL
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * Caller must free the returned string with free(3).  Always frees
Packit Service 4c70d1
 * its first arg - typical use: s = xstrconcat3(s,t,u);
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * Lifted from util-linux.
Packit Service 4c70d1
 */
Packit Service 4c70d1
static char *
Packit Service 4c70d1
xstrconcat3(char *s, const char *t, const char *u)
Packit Service 4c70d1
{
Packit Service 4c70d1
	_Bool free_s = true;
Packit Service 4c70d1
	char *result;
Packit Service 4c70d1
Packit Service 4c70d1
	if (s == NULL) {
Packit Service 4c70d1
		s = "";
Packit Service 4c70d1
		free_s = false;
Packit Service 4c70d1
	}
Packit Service 4c70d1
	if (t == NULL)
Packit Service 4c70d1
		t = "";
Packit Service 4c70d1
	if (u == NULL)
Packit Service 4c70d1
		u = "";
Packit Service 4c70d1
	result = malloc(strlen(s) + strlen(t) + strlen(u) + 1);
Packit Service 4c70d1
	if (result == NULL)
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
Packit Service 4c70d1
	strcpy(result, s);
Packit Service 4c70d1
	strcat(result, t);
Packit Service 4c70d1
	strcat(result, u);
Packit Service 4c70d1
Packit Service 4c70d1
out:
Packit Service 4c70d1
	if (free_s)
Packit Service 4c70d1
		free(s);
Packit Service 4c70d1
	return result;
Packit Service 4c70d1
}
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Exec mount.nfs
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * @param server NUL-terminated C string containing name of NFS server
Packit Service 4c70d1
 * @param port server port to use when mounting
Packit Service 4c70d1
 * @param domainname NUL-terminated C string containing FedFS domain name
Packit Service 4c70d1
 * @param export_path NUL-terminated C string containing server export path
Packit Service 4c70d1
 * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
Packit Service 4c70d1
 * @param text_options NUL-terminated C string containing user's mount options
Packit Service 4c70d1
 *
Packit Service 4c70d1
 */
Packit Service 4c70d1
static void
Packit Service 4c70d1
exec_mount_nfs4(const char *server, unsigned short port,
Packit Service 4c70d1
		const char *domainname, const char *export_path,
Packit Service 4c70d1
		const char *mounted_on_dir, const char *text_options)
Packit Service 4c70d1
{
Packit Service 4c70d1
	static char special[2048];
Packit Service 4c70d1
	static char options[2048];
Packit Service 4c70d1
	char *args[16];
Packit Service 4c70d1
	int count = 0;
Packit Service 4c70d1
Packit Service 4c70d1
	snprintf(special, sizeof(special), "%s:%s/%s%s", server,
Packit Service 4c70d1
			FEDFS_NFS_EXPORTPATH, domainname, export_path);
Packit Service 4c70d1
Packit Service 4c70d1
	if (text_options != NULL && strcmp(text_options, "") != 0)
Packit Service 4c70d1
		snprintf(options, sizeof(options), "%s,vers=4,fg,port=%u",
Packit Service 4c70d1
				text_options, port);
Packit Service 4c70d1
	else
Packit Service 4c70d1
		snprintf(options, sizeof(options), "vers=4,fg,port=%u", port);
Packit Service 4c70d1
Packit Service 4c70d1
	if (verbose) {
Packit Service 4c70d1
		printf(_("%s: Special device:       %s\n"),
Packit Service 4c70d1
			progname, special);
Packit Service 4c70d1
		printf(_("%s: Mounted-on directory: %s\n"),
Packit Service 4c70d1
			progname, mounted_on_dir);
Packit Service 4c70d1
		printf(_("%s: Mount options:        %s\n"),
Packit Service 4c70d1
			progname, options);
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	args[count++] = MOUNT_NFS_EXECUTABLE;
Packit Service 4c70d1
	args[count++] = special;
Packit Service 4c70d1
	args[count++] = (char *)mounted_on_dir;
Packit Service 4c70d1
	if (verbose)
Packit Service 4c70d1
		args[count++] = "-v";
Packit Service 4c70d1
	if (fake)
Packit Service 4c70d1
		args[count++] = "-f";
Packit Service 4c70d1
	if (nomtab)
Packit Service 4c70d1
		args[count++] = "-n";
Packit Service 4c70d1
	if (readonly)
Packit Service 4c70d1
		args[count++] = "-r";
Packit Service 4c70d1
	if (sloppy)
Packit Service 4c70d1
		args[count++] = "-s";
Packit Service 4c70d1
	args[count++] = "-o";
Packit Service 4c70d1
	args[count++] = options;
Packit Service 4c70d1
Packit Service 4c70d1
	args[count] = NULL;
Packit Service 4c70d1
	execv(args[0], args);
Packit Service 4c70d1
}
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Mount a FedFS domain root via NFSv4
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * @param domainname NUL-terminated C string containing FedFS domain name
Packit Service 4c70d1
 * @param export_path NUL-terminated C string containing server export path
Packit Service 4c70d1
 * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
Packit Service 4c70d1
 * @param text_options NUL-terminated C string containing user's mount options
Packit Service 4c70d1
 * @return exit status code from the mount.nfs command
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * Construct the server:/export string and the mounted-on directory string
Packit Service 4c70d1
 * based on the DNS SRV query results, then fork and exec mount.nfs to do
Packit Service 4c70d1
 * the actual mount request.
Packit Service 4c70d1
 */
Packit Service 4c70d1
static int
Packit Service 4c70d1
nfs4_mount(const char *domainname, const char *export_path,
Packit Service 4c70d1
		const char *mounted_on_dir, const char *text_options)
Packit Service 4c70d1
{
Packit Service 4c70d1
	struct srvinfo *tmp, *si = NULL;
Packit Service 4c70d1
	int error, status;
Packit Service 4c70d1
Packit Service 4c70d1
	status = EX_FAIL;
Packit Service 4c70d1
Packit Service 4c70d1
	error = getsrvinfo(FEDFS_NFS_DOMAINROOT, domainname, &si);
Packit Service 4c70d1
	switch (error) {
Packit Service 4c70d1
	case ESI_SUCCESS:
Packit Service 4c70d1
		break;
Packit Service 4c70d1
	case ESI_NONAME:
Packit Service 4c70d1
		fprintf(stderr, _("%s: Domain name %s not found\n"),
Packit Service 4c70d1
			progname, domainname);
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	case ESI_SERVICE:
Packit Service 4c70d1
		fprintf(stderr, _("%s: No FedFS domain root available for %s\n"),
Packit Service 4c70d1
			progname, domainname);
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	default:
Packit Service 4c70d1
		fprintf(stderr, _("%s: Failed to resolve %s: %s\n"),
Packit Service 4c70d1
			progname, domainname, gsi_strerror(error));
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	/*
Packit Service 4c70d1
	 * The srvinfo list is already in RFC 2782 sorted order.  Try each
Packit Service 4c70d1
	 * SRV record once, in the foreground.  Go with the first one that
Packit Service 4c70d1
	 * works.
Packit Service 4c70d1
	 */
Packit Service 4c70d1
	for (tmp = si; tmp != NULL; tmp = tmp->si_next) {
Packit Service 4c70d1
		pid_t pid;
Packit Service 4c70d1
Packit Service 4c70d1
		pid = fork();
Packit Service 4c70d1
		switch (pid) {
Packit Service 4c70d1
		case 0:
Packit Service 4c70d1
			exec_mount_nfs4(tmp->si_target, tmp->si_port,
Packit Service 4c70d1
					domainname, export_path, mounted_on_dir,
Packit Service 4c70d1
					text_options);
Packit Service 4c70d1
			/*NOTREACHED*/
Packit Service 4c70d1
			fprintf(stderr, _("%s: Failed to exec: %s\n"),
Packit Service 4c70d1
				progname, strerror(errno));
Packit Service 4c70d1
			exit(EX_FAIL);
Packit Service 4c70d1
		case -1:
Packit Service 4c70d1
			fprintf(stderr, _("%s: Failed to fork: %s\n"),
Packit Service 4c70d1
				progname, strerror(errno));
Packit Service 4c70d1
			goto out;
Packit Service 4c70d1
		default:
Packit Service 4c70d1
			waitpid(pid, &status, 0);
Packit Service 4c70d1
			if (status == EX_SUCCESS)
Packit Service 4c70d1
				goto out;
Packit Service 4c70d1
		}
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
out:
Packit Service 4c70d1
	freesrvinfo(si);
Packit Service 4c70d1
	return status;
Packit Service 4c70d1
}
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Try one mount request
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * @param source NUL-terminated C string containing name of "special device"
Packit Service 4c70d1
 * @param target NUL-terminated C string containing local mounted-on directory
Packit Service 4c70d1
 * @param text_options NUL-terminated C string containing user's mount options
Packit Service 4c70d1
 * @return an exit status code
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * Parse the pathname in "source."  It contains the file system protocol
Packit Service 4c70d1
 * and FedFS domain name.  Then pass these arguments to the appropriate
Packit Service 4c70d1
 * mount helper subcommand.
Packit Service 4c70d1
 */
Packit Service 4c70d1
static int
Packit Service 4c70d1
try_mount(const char *source, const char *target, const char *text_options)
Packit Service 4c70d1
{
Packit Service 4c70d1
	char *global_name, *topdir, *domainname, *remaining;
Packit Service 4c70d1
	int result;
Packit Service 4c70d1
Packit Service 4c70d1
	remaining = NULL;
Packit Service 4c70d1
	result = EX_FAIL;
Packit Service 4c70d1
Packit Service 4c70d1
	global_name = strdup(source);
Packit Service 4c70d1
	if (global_name == NULL) {
Packit Service 4c70d1
		fprintf(stderr, _("%s: Unable to parse globally useful name\n"),
Packit Service 4c70d1
				progname);
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	topdir = strtok(global_name, "/");
Packit Service 4c70d1
	if (topdir == NULL) {
Packit Service 4c70d1
		fprintf(stderr, _("%s: Invalid globally useful name: %s\n"),
Packit Service 4c70d1
			progname, source);
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
	if (verbose)
Packit Service 4c70d1
		printf(_("%s: Top-level directory:  %s\n"),
Packit Service 4c70d1
			progname, topdir);
Packit Service 4c70d1
Packit Service 4c70d1
	domainname = strtok(NULL, "/");
Packit Service 4c70d1
	if (domainname == NULL) {
Packit Service 4c70d1
		fprintf(stderr, _("%s: Missing domain name in globally "
Packit Service 4c70d1
				"useful name: %s\n"), progname, source);
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
	if (verbose)
Packit Service 4c70d1
		printf(_("%s: Domain name:          %s\n"),
Packit Service 4c70d1
			progname, domainname);
Packit Service 4c70d1
Packit Service 4c70d1
	remaining = strtok(NULL, "/");
Packit Service 4c70d1
	if (remaining == NULL) {
Packit Service 4c70d1
		remaining = strdup("/");
Packit Service 4c70d1
		if (remaining == NULL) {
Packit Service 4c70d1
			fprintf(stderr, _("%s: No memory\n"), progname);
Packit Service 4c70d1
			goto out;
Packit Service 4c70d1
		}
Packit Service 4c70d1
	} else {
Packit Service 4c70d1
		char *tmp;
Packit Service 4c70d1
Packit Service 4c70d1
		tmp = malloc(strlen(remaining) + 1);
Packit Service 4c70d1
		if (tmp == NULL) {
Packit Service 4c70d1
			fprintf(stderr, _("%s: No memory\n"), progname);
Packit Service 4c70d1
			remaining = NULL;
Packit Service 4c70d1
			goto out;
Packit Service 4c70d1
		}
Packit Service 4c70d1
		strcpy(tmp, "/");
Packit Service 4c70d1
		strcat(tmp, remaining);
Packit Service 4c70d1
		remaining = tmp;
Packit Service 4c70d1
	}
Packit Service 4c70d1
	if (verbose)
Packit Service 4c70d1
		printf(_("%s: Export path:          %s\n"),
Packit Service 4c70d1
			progname, remaining);
Packit Service 4c70d1
Packit Service 4c70d1
	if (strcmp(topdir, FEDFS_NFS4_TLDIR) == 0)
Packit Service 4c70d1
		result = nfs4_mount(domainname, remaining, target, text_options);
Packit Service 4c70d1
#if 0
Packit Service 4c70d1
	/* example: SMB support plugs in here */
Packit Service 4c70d1
	else if (strcmp(topdir, FEDFS_SMB_TLDIR) == 0)
Packit Service 4c70d1
		result = smb_mount(domainname, remaining, target, text_options);
Packit Service 4c70d1
#endif
Packit Service 4c70d1
	else
Packit Service 4c70d1
		fprintf(stderr, _("%s: Unrecognized file system protocol\n"), progname);
Packit Service 4c70d1
Packit Service 4c70d1
out:
Packit Service 4c70d1
	free(global_name);
Packit Service 4c70d1
	free(remaining);
Packit Service 4c70d1
Packit Service 4c70d1
	return result;
Packit Service 4c70d1
}
Packit Service 4c70d1
Packit Service 4c70d1
/**
Packit Service 4c70d1
 * Program entry point
Packit Service 4c70d1
 *
Packit Service 4c70d1
 * @param argc count of command line arguments
Packit Service 4c70d1
 * @param argv array of NUL-terminated C strings containing command line arguments
Packit Service 4c70d1
 * @return program exit status
Packit Service 4c70d1
 */
Packit Service 4c70d1
int main(int argc, char *argv[])
Packit Service 4c70d1
{
Packit Service 4c70d1
	char *source, *target, *text_options;
Packit Service 4c70d1
	int c, mnt_err;
Packit Service 4c70d1
Packit Service 4c70d1
	(void)setlocale(LC_ALL, "");
Packit Service 4c70d1
Packit Service 4c70d1
	progname = basename(argv[0]);
Packit Service 4c70d1
Packit Service 4c70d1
	if (argv[1] && argv[1][0] == '-') {
Packit Service 4c70d1
		if(argv[1][1] == 'V')
Packit Service 4c70d1
			printf("%s (VERSION_STRING)\n", progname);
Packit Service 4c70d1
		else
Packit Service 4c70d1
			mount_usage();
Packit Service 4c70d1
		exit(EX_SUCCESS);
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	if (argc < 3) {
Packit Service 4c70d1
		mount_usage();
Packit Service 4c70d1
		exit(EX_USAGE);
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	source = argv[1];
Packit Service 4c70d1
	target = argv[2];
Packit Service 4c70d1
Packit Service 4c70d1
	mnt_err = EX_USAGE;
Packit Service 4c70d1
	text_options = NULL;
Packit Service 4c70d1
	readonly = false;
Packit Service 4c70d1
	sloppy = false;
Packit Service 4c70d1
	fake = false;
Packit Service 4c70d1
	argv[2] = argv[0]; /* so that getopt error messages are correct */
Packit Service 4c70d1
	while ((c = getopt_long(argc - 2, argv + 2, fedfs_opts,
Packit Service 4c70d1
				fedfs_longopts, NULL)) != -1) {
Packit Service 4c70d1
		switch (c) {
Packit Service 4c70d1
		case 'f':
Packit Service 4c70d1
			fake = true;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'n':
Packit Service 4c70d1
			++nomtab;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'o':
Packit Service 4c70d1
			/* Ugh. */
Packit Service 4c70d1
			if (text_options != NULL)
Packit Service 4c70d1
				text_options = xstrconcat3(text_options, ",", optarg);
Packit Service 4c70d1
			else
Packit Service 4c70d1
				text_options = strdup(optarg);
Packit Service 4c70d1
			if (text_options == NULL) {
Packit Service 4c70d1
				fprintf(stderr, _("%s: No memory\n"), progname);
Packit Service 4c70d1
				goto out;
Packit Service 4c70d1
			}
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'r':
Packit Service 4c70d1
			readonly = true;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 's':
Packit Service 4c70d1
			sloppy = true;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'v':
Packit Service 4c70d1
			++verbose;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'V':
Packit Service 4c70d1
			printf("%s: (VERSION_STRING)\n", progname);
Packit Service 4c70d1
			mnt_err = EX_SUCCESS;
Packit Service 4c70d1
			goto out;
Packit Service 4c70d1
		case 'w':
Packit Service 4c70d1
			readonly = false;
Packit Service 4c70d1
			break;
Packit Service 4c70d1
		case 'h':
Packit Service 4c70d1
		default:
Packit Service 4c70d1
			mount_usage();
Packit Service 4c70d1
			goto out;
Packit Service 4c70d1
		}
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	/* Extra non-option words at the end are bogus...  */
Packit Service 4c70d1
	if (optind != argc - 2) {
Packit Service 4c70d1
		mount_usage();
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	if (getuid() != 0 && geteuid() != 0) {
Packit Service 4c70d1
		fprintf(stderr, _("%s: Not installed setuid - "
Packit Service 4c70d1
			    "\"user\" FedFS mounts are not supported\n"), progname);
Packit Service 4c70d1
		mnt_err = EX_FAIL;
Packit Service 4c70d1
		goto out;
Packit Service 4c70d1
	}
Packit Service 4c70d1
Packit Service 4c70d1
	mnt_err = try_mount(source, target, text_options);
Packit Service 4c70d1
Packit Service 4c70d1
out:
Packit Service 4c70d1
	free(text_options);
Packit Service 4c70d1
	exit(mnt_err);
Packit Service 4c70d1
}