d5dcad
autofs-5.1.4 - add mount.fedfs.c
d5dcad
d5dcad
From: Ian Kent <raven@themaw.net>
d5dcad
d5dcad
Add build and install of the mount.fedfs binary.
d5dcad
d5dcad
Signed-off-by: Ian Kent <raven@themaw.net>
d5dcad
---
d5dcad
 CHANGELOG                |    1 
d5dcad
 Makefile                 |    3 
d5dcad
 Makefile.rules           |    2 
d5dcad
 autofs.spec              |    1 
d5dcad
 fedfs/Makefile           |   36 +++
d5dcad
 fedfs/fedfs-gpl-boiler.h |   40 ++++
d5dcad
 fedfs/fedfs-nls.h        |   38 ++++
d5dcad
 fedfs/mount.fedfs.c      |  485 ++++++++++++++++++++++++++++++++++++++++++++++
d5dcad
 8 files changed, 605 insertions(+), 1 deletion(-)
d5dcad
 create mode 100644 fedfs/Makefile
d5dcad
 create mode 100644 fedfs/fedfs-gpl-boiler.h
d5dcad
 create mode 100644 fedfs/fedfs-nls.h
d5dcad
 create mode 100644 fedfs/mount.fedfs.c
d5dcad
d5dcad
diff --git a/CHANGELOG b/CHANGELOG
d5dcad
index 8d6c737c..88992147 100644
d5dcad
--- a/CHANGELOG
d5dcad
+++ b/CHANGELOG
d5dcad
@@ -15,6 +15,7 @@ xx/xx/2018 autofs-5.1.5
d5dcad
 - dont allow trailing slash in master map mount points.
d5dcad
 - fix libresolv configure check.
d5dcad
 - add fedfs-getsrvinfo.c.
d5dcad
+- add mount.fedfs.c.
d5dcad
 
d5dcad
 19/12/2017 autofs-5.1.4
d5dcad
 - fix spec file url.
d5dcad
diff --git a/Makefile b/Makefile
d5dcad
index e560a7cb..99db2c75 100644
d5dcad
--- a/Makefile
d5dcad
+++ b/Makefile
d5dcad
@@ -19,6 +19,9 @@ kernel:
d5dcad
 samples:
d5dcad
 	set -e; if [ -d samples ]; then $(MAKE) -C samples all; fi
d5dcad
 
d5dcad
+fedfs:
d5dcad
+	set -e; if [ -d fedfs ]; then $(MAKE) -C fedfs all; fi
d5dcad
+
d5dcad
 clean:
d5dcad
 	for i in $(SUBDIRS) samples; do \
d5dcad
 		if [ -d $$i ]; then $(MAKE) -C $$i clean; fi; done 	
d5dcad
diff --git a/Makefile.rules b/Makefile.rules
d5dcad
index 4deab3b9..fc9f6019 100644
d5dcad
--- a/Makefile.rules
d5dcad
+++ b/Makefile.rules
d5dcad
@@ -3,7 +3,7 @@
d5dcad
 #
d5dcad
 
d5dcad
 # Root directory contents
d5dcad
-SUBDIRS = lib daemon modules man
d5dcad
+SUBDIRS = lib daemon fedfs modules man
d5dcad
 INCDIRS = include
d5dcad
 INCFILES = COPYING COPYRIGHT NEWS README* TODO Makefile Makefile.rules \
d5dcad
 	   Makefile.conf.in .version .autofs-* configure.in aclocal.m4 \
d5dcad
diff --git a/autofs.spec b/autofs.spec
d5dcad
index 2464e741..2cc0e38f 100644
d5dcad
--- a/autofs.spec
d5dcad
+++ b/autofs.spec
d5dcad
@@ -191,6 +191,7 @@ fi
d5dcad
 %config(noreplace) /etc/sysconfig/autofs
d5dcad
 %config(noreplace) /etc/autofs_ldap_auth.conf
d5dcad
 %{_sbindir}/automount
d5dcad
+%{_sbindir}/mount.fedfs
d5dcad
 %dir %{_libdir}/autofs
d5dcad
 %{_libdir}/autofs/*
d5dcad
 %{_mandir}/*/*
d5dcad
diff --git a/fedfs/Makefile b/fedfs/Makefile
d5dcad
new file mode 100644
d5dcad
index 00000000..cb325bed
d5dcad
--- /dev/null
d5dcad
+++ b/fedfs/Makefile
d5dcad
@@ -0,0 +1,36 @@
d5dcad
+#
d5dcad
+# Makefile for mount.fedfs
d5dcad
+#
d5dcad
+
d5dcad
+-include ../Makefile.conf
d5dcad
+include ../Makefile.rules
d5dcad
+
d5dcad
+SRCS = mount.fedfs.c
d5dcad
+HDRS = fedfs-getsrvinfo.h fedfs-gpl-boiler.h fedfs-nls.h
d5dcad
+
d5dcad
+fedfs-getsrvinfo_OBJ = fedfs-getsrvinfo.o
d5dcad
+
d5dcad
+mount_fedfs_OBJ = mount.fedfs.o
d5dcad
+
d5dcad
+version := $(shell cat ../.version)
d5dcad
+
d5dcad
+CFLAGS += -rdynamic $(DAEMON_CFLAGS) -D_GNU_SOURCE -I../include
d5dcad
+CFLAGS += -DVERSION_STRING=\"$(version)\"
d5dcad
+LDFLAGS += -rdynamic
d5dcad
+
d5dcad
+all: mount.fedfs
d5dcad
+
d5dcad
+mount.fedfs: $(mount_fedfs_OBJ) $(fedfs-getsrvinfo_OBJ) $(HDRS)
d5dcad
+	$(CC) -o mount.fedfs \
d5dcad
+	       $(mount_fedfs_OBJ) $(fedfs-getsrvinfo_OBJ) \
d5dcad
+	       $(LDFLAGS) $(LIBRESOLV) $(LIBS)
d5dcad
+
d5dcad
+clean:
d5dcad
+	rm -f *.o *.s *~ mount.fedfs
d5dcad
+
d5dcad
+install: all
d5dcad
+	install -d -m 755 $(INSTALLROOT)$(sbindir)
d5dcad
+	if ! test -x $(INSTALLROOT)$(sbindir)/mount.fedfs; \
d5dcad
+	then \
d5dcad
+		install -c mount.fedfs -m 755 $(INSTALLROOT)$(sbindir); \
d5dcad
+	fi
d5dcad
diff --git a/fedfs/fedfs-gpl-boiler.h b/fedfs/fedfs-gpl-boiler.h
d5dcad
new file mode 100644
d5dcad
index 00000000..1353e736
d5dcad
--- /dev/null
d5dcad
+++ b/fedfs/fedfs-gpl-boiler.h
d5dcad
@@ -0,0 +1,40 @@
d5dcad
+/*
d5dcad
+ * Copyright 2011 Oracle.  All rights reserved.
d5dcad
+ *
d5dcad
+ * This file is part of fedfs-utils.
d5dcad
+ *
d5dcad
+ * fedfs-utils is free software; you can redistribute it and/or modify
d5dcad
+ * it under the terms of the GNU General Public License version 2.0 as
d5dcad
+ * published by the Free Software Foundation.
d5dcad
+ *
d5dcad
+ * fedfs-utils is distributed in the hope that it will be useful, but
d5dcad
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
d5dcad
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d5dcad
+ * GNU General Public License version 2.0 for more details.
d5dcad
+ *
d5dcad
+ * You should have received a copy of the GNU General Public License
d5dcad
+ * version 2.0 along with fedfs-utils.  If not, see:
d5dcad
+ *
d5dcad
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
d5dcad
+ */
d5dcad
+
d5dcad
+#ifndef _GPL_BOILER_H_
d5dcad
+#define _GPL_BOILER_H_
d5dcad
+
d5dcad
+#ifdef HAVE_CONFIG_H
d5dcad
+#include <config.h>
d5dcad
+#endif
d5dcad
+
d5dcad
+/**
d5dcad
+ * GPLv2 boilerplate for usage messages
d5dcad
+ */
d5dcad
+static const char *fedfs_gpl_boilerplate =
d5dcad
+		"\nCopyright 2010, 2011, 2012, 2013 Oracle.  "
d5dcad
+		"All rights reserved.\n\n"
d5dcad
+		"License GPLv2: "
d5dcad
+		"<http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>\n"
d5dcad
+		"This is free software.  "
d5dcad
+			"You are free to change and redistribute it.\n"
d5dcad
+		"There is NO WARRANTY, to the extent permitted by law.\n";
d5dcad
+
d5dcad
+#endif	/* !_GPL_BOILER_H_ */
d5dcad
diff --git a/fedfs/fedfs-nls.h b/fedfs/fedfs-nls.h
d5dcad
new file mode 100644
d5dcad
index 00000000..92f968d3
d5dcad
--- /dev/null
d5dcad
+++ b/fedfs/fedfs-nls.h
d5dcad
@@ -0,0 +1,38 @@
d5dcad
+/*
d5dcad
+ * From util-linux/include/nls.h (GPLv2)
d5dcad
+ */
d5dcad
+
d5dcad
+#ifndef UTIL_LINUX_NLS_H
d5dcad
+#define UTIL_LINUX_NLS_H
d5dcad
+
d5dcad
+int main(int argc, char *argv[]);
d5dcad
+
d5dcad
+#ifndef LOCALEDIR
d5dcad
+#define LOCALEDIR "/usr/share/locale"
d5dcad
+#endif
d5dcad
+
d5dcad
+#ifdef HAVE_LOCALE_H
d5dcad
+# include <locale.h>
d5dcad
+#else
d5dcad
+# undef setlocale
d5dcad
+# define setlocale(Category, Locale) ({}) /* empty */
d5dcad
+#endif
d5dcad
+
d5dcad
+#ifdef ENABLE_NLS
d5dcad
+# include <libintl.h>
d5dcad
+# define _(Text) gettext (Text)
d5dcad
+# ifdef gettext_noop
d5dcad
+#  define N_(String) gettext_noop (String)
d5dcad
+# else
d5dcad
+#  define N_(String) (String)
d5dcad
+# endif
d5dcad
+#else
d5dcad
+# undef bindtextdomain
d5dcad
+# define bindtextdomain(Domain, Directory) /* empty */
d5dcad
+# undef textdomain
d5dcad
+# define textdomain(Domain) /* empty */
d5dcad
+# define _(Text) (Text)
d5dcad
+# define N_(Text) (Text)
d5dcad
+#endif
d5dcad
+
d5dcad
+#endif /* UTIL_LINUX_NLS_H */
d5dcad
diff --git a/fedfs/mount.fedfs.c b/fedfs/mount.fedfs.c
d5dcad
new file mode 100644
d5dcad
index 00000000..bd434395
d5dcad
--- /dev/null
d5dcad
+++ b/fedfs/mount.fedfs.c
d5dcad
@@ -0,0 +1,485 @@
d5dcad
+/*
d5dcad
+ * Copyright 2011 Oracle.  All rights reserved.
d5dcad
+ *
d5dcad
+ * This file is part of fedfs-utils.
d5dcad
+ *
d5dcad
+ * fedfs-utils is free software; you can redistribute it and/or modify
d5dcad
+ * it under the terms of the GNU General Public License version 2.0 as
d5dcad
+ * published by the Free Software Foundation.
d5dcad
+ *
d5dcad
+ * fedfs-utils is distributed in the hope that it will be useful, but
d5dcad
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
d5dcad
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
d5dcad
+ * GNU General Public License version 2.0 for more details.
d5dcad
+ *
d5dcad
+ * You should have received a copy of the GNU General Public License
d5dcad
+ * version 2.0 along with fedfs-utils.  If not, see:
d5dcad
+ *
d5dcad
+ *	http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
d5dcad
+ */
d5dcad
+
d5dcad
+#include <sys/types.h>
d5dcad
+#include <sys/stat.h>
d5dcad
+#include <sys/socket.h>
d5dcad
+#include <sys/mount.h>
d5dcad
+#include <sys/wait.h>
d5dcad
+
d5dcad
+#include <stdbool.h>
d5dcad
+#include <string.h>
d5dcad
+#include <stdlib.h>
d5dcad
+#include <unistd.h>
d5dcad
+#include <stdio.h>
d5dcad
+#include <libgen.h>
d5dcad
+#include <errno.h>
d5dcad
+#include <getopt.h>
d5dcad
+#include <locale.h>
d5dcad
+#include <netdb.h>
d5dcad
+#include <langinfo.h>
d5dcad
+
d5dcad
+#include "fedfs-nls.h"
d5dcad
+#include "fedfs-getsrvinfo.h"
d5dcad
+#include "fedfs-gpl-boiler.h"
d5dcad
+
d5dcad
+/**
d5dcad
+ * Top-level directory on client under which we mount NFSv4 domain roots
d5dcad
+ */
d5dcad
+#define FEDFS_NFS4_TLDIR		"nfs4"
d5dcad
+
d5dcad
+/**
d5dcad
+ * Name of SRV record containing NFSv4 FedFS root
d5dcad
+ */
d5dcad
+#define FEDFS_NFS_DOMAINROOT	"_nfs-domainroot._tcp"
d5dcad
+
d5dcad
+/**
d5dcad
+ * Export path of NFSv4 FedFS root
d5dcad
+ */
d5dcad
+#define FEDFS_NFS_EXPORTPATH	"/.domainroot"
d5dcad
+
d5dcad
+/**
d5dcad
+ * Pathname to mount.nfs
d5dcad
+ */
d5dcad
+#define MOUNT_NFS_EXECUTABLE		"/sbin/mount.nfs"
d5dcad
+
d5dcad
+/**
d5dcad
+ * Mount status values, lifted from util-linux
d5dcad
+ */
d5dcad
+enum {
d5dcad
+	EX_SUCCESS	= 0,
d5dcad
+	EX_USAGE	= 1,
d5dcad
+	EX_FAIL		= 32,
d5dcad
+};
d5dcad
+
d5dcad
+static char *progname;
d5dcad
+static int nomtab;
d5dcad
+static int verbose;
d5dcad
+static _Bool readonly;
d5dcad
+static _Bool sloppy;
d5dcad
+static _Bool fake;
d5dcad
+
d5dcad
+/**
d5dcad
+ * Short form command line options
d5dcad
+ */
d5dcad
+static const char fedfs_opts[] = "fhno:rsvVw";
d5dcad
+
d5dcad
+/**
d5dcad
+ * Long form command line options
d5dcad
+ */
d5dcad
+static const struct option fedfs_longopts[] =
d5dcad
+{
d5dcad
+	{ "fake", 0, NULL, 'f' },
d5dcad
+	{ "help", 0, NULL, 'h' },
d5dcad
+	{ "no-mtab", 0, NULL, 'n' },
d5dcad
+	{ "options", 1, NULL, 'o' },
d5dcad
+	{ "read-only", 0, NULL, 'r' },
d5dcad
+	{ "read-write", 0, NULL, 'w' },
d5dcad
+	{ "ro", 0, NULL, 'r' },
d5dcad
+	{ "rw", 0, NULL, 'w' },
d5dcad
+	{ "sloppy", 0, NULL, 's' },
d5dcad
+	{ "verbose", 0, NULL, 'v' },
d5dcad
+	{ "version", 0, NULL, 'V' },
d5dcad
+	{ NULL, 0, NULL, 0 }
d5dcad
+};
d5dcad
+
d5dcad
+/**
d5dcad
+ * Display mount.fedfs usage message
d5dcad
+ */
d5dcad
+static void
d5dcad
+mount_usage(void)
d5dcad
+{
d5dcad
+	printf(_("\nUsage: %s remotedir localdir [-fhnrsvVw]\n\n"), progname);
d5dcad
+	printf(_("options:\n"));
d5dcad
+	printf(_("\t-f\t\tFake mount, do not actually mount\n"));
d5dcad
+	printf(_("\t-h\t\tPrint this help\n"));
d5dcad
+	printf(_("\t-n\t\tDo not update /etc/mtab\n"));
d5dcad
+	printf(_("\t-r\t\tMount file system readonly\n"));
d5dcad
+	printf(_("\t-s\t\tTolerate sloppy mount options\n"));
d5dcad
+	printf(_("\t-v\t\tVerbose\n"));
d5dcad
+	printf(_("\t-V\t\tPrint version\n"));
d5dcad
+	printf(_("\t-w\t\tMount file system read-write\n"));
d5dcad
+
d5dcad
+	printf("%s", fedfs_gpl_boilerplate);
d5dcad
+}
d5dcad
+
d5dcad
+/**
d5dcad
+ * Concatenate three strings
d5dcad
+ *
d5dcad
+ * @param s NUL-terminated C string
d5dcad
+ * @param t NUL-terminated C string
d5dcad
+ * @param u NUL-terminated C string
d5dcad
+ * @return pointer to NUL-terminated C string or NULL
d5dcad
+ *
d5dcad
+ * Caller must free the returned string with free(3).  Always frees
d5dcad
+ * its first arg - typical use: s = xstrconcat3(s,t,u);
d5dcad
+ *
d5dcad
+ * Lifted from util-linux.
d5dcad
+ */
d5dcad
+static char *
d5dcad
+xstrconcat3(char *s, const char *t, const char *u)
d5dcad
+{
d5dcad
+	_Bool free_s = true;
d5dcad
+	char *result;
d5dcad
+
d5dcad
+	if (s == NULL) {
d5dcad
+		s = "";
d5dcad
+		free_s = false;
d5dcad
+	}
d5dcad
+	if (t == NULL)
d5dcad
+		t = "";
d5dcad
+	if (u == NULL)
d5dcad
+		u = "";
d5dcad
+	result = malloc(strlen(s) + strlen(t) + strlen(u) + 1);
d5dcad
+	if (result == NULL)
d5dcad
+		goto out;
d5dcad
+
d5dcad
+	strcpy(result, s);
d5dcad
+	strcat(result, t);
d5dcad
+	strcat(result, u);
d5dcad
+
d5dcad
+out:
d5dcad
+	if (free_s)
d5dcad
+		free(s);
d5dcad
+	return result;
d5dcad
+}
d5dcad
+
d5dcad
+/**
d5dcad
+ * Exec mount.nfs
d5dcad
+ *
d5dcad
+ * @param server NUL-terminated C string containing name of NFS server
d5dcad
+ * @param port server port to use when mounting
d5dcad
+ * @param domainname NUL-terminated C string containing FedFS domain name
d5dcad
+ * @param export_path NUL-terminated C string containing server export path
d5dcad
+ * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
d5dcad
+ * @param text_options NUL-terminated C string containing user's mount options
d5dcad
+ *
d5dcad
+ */
d5dcad
+static void
d5dcad
+exec_mount_nfs4(const char *server, unsigned short port,
d5dcad
+		const char *domainname, const char *export_path,
d5dcad
+		const char *mounted_on_dir, const char *text_options)
d5dcad
+{
d5dcad
+	static char special[2048];
d5dcad
+	static char options[2048];
d5dcad
+	char *args[16];
d5dcad
+	int count = 0;
d5dcad
+
d5dcad
+	snprintf(special, sizeof(special), "%s:%s/%s%s", server,
d5dcad
+			FEDFS_NFS_EXPORTPATH, domainname, export_path);
d5dcad
+
d5dcad
+	if (text_options != NULL && strcmp(text_options, "") != 0)
d5dcad
+		snprintf(options, sizeof(options), "%s,vers=4,fg,port=%u",
d5dcad
+				text_options, port);
d5dcad
+	else
d5dcad
+		snprintf(options, sizeof(options), "vers=4,fg,port=%u", port);
d5dcad
+
d5dcad
+	if (verbose) {
d5dcad
+		printf(_("%s: Special device:       %s\n"),
d5dcad
+			progname, special);
d5dcad
+		printf(_("%s: Mounted-on directory: %s\n"),
d5dcad
+			progname, mounted_on_dir);
d5dcad
+		printf(_("%s: Mount options:        %s\n"),
d5dcad
+			progname, options);
d5dcad
+	}
d5dcad
+
d5dcad
+	args[count++] = MOUNT_NFS_EXECUTABLE;
d5dcad
+	args[count++] = special;
d5dcad
+	args[count++] = (char *)mounted_on_dir;
d5dcad
+	if (verbose)
d5dcad
+		args[count++] = "-v";
d5dcad
+	if (fake)
d5dcad
+		args[count++] = "-f";
d5dcad
+	if (nomtab)
d5dcad
+		args[count++] = "-n";
d5dcad
+	if (readonly)
d5dcad
+		args[count++] = "-r";
d5dcad
+	if (sloppy)
d5dcad
+		args[count++] = "-s";
d5dcad
+	args[count++] = "-o";
d5dcad
+	args[count++] = options;
d5dcad
+
d5dcad
+	args[count] = NULL;
d5dcad
+	execv(args[0], args);
d5dcad
+}
d5dcad
+
d5dcad
+/**
d5dcad
+ * Mount a FedFS domain root via NFSv4
d5dcad
+ *
d5dcad
+ * @param domainname NUL-terminated C string containing FedFS domain name
d5dcad
+ * @param export_path NUL-terminated C string containing server export path
d5dcad
+ * @param mounted_on_dir NUL-terminated C string containing local mounted-on directory
d5dcad
+ * @param text_options NUL-terminated C string containing user's mount options
d5dcad
+ * @return exit status code from the mount.nfs command
d5dcad
+ *
d5dcad
+ * Construct the server:/export string and the mounted-on directory string
d5dcad
+ * based on the DNS SRV query results, then fork and exec mount.nfs to do
d5dcad
+ * the actual mount request.
d5dcad
+ */
d5dcad
+static int
d5dcad
+nfs4_mount(const char *domainname, const char *export_path,
d5dcad
+		const char *mounted_on_dir, const char *text_options)
d5dcad
+{
d5dcad
+	struct srvinfo *tmp, *si = NULL;
d5dcad
+	int error, status;
d5dcad
+
d5dcad
+	status = EX_FAIL;
d5dcad
+
d5dcad
+	error = getsrvinfo(FEDFS_NFS_DOMAINROOT, domainname, &si);
d5dcad
+	switch (error) {
d5dcad
+	case ESI_SUCCESS:
d5dcad
+		break;
d5dcad
+	case ESI_NONAME:
d5dcad
+		fprintf(stderr, _("%s: Domain name %s not found\n"),
d5dcad
+			progname, domainname);
d5dcad
+		goto out;
d5dcad
+	case ESI_SERVICE:
d5dcad
+		fprintf(stderr, _("%s: No FedFS domain root available for %s\n"),
d5dcad
+			progname, domainname);
d5dcad
+		goto out;
d5dcad
+	default:
d5dcad
+		fprintf(stderr, _("%s: Failed to resolve %s: %s\n"),
d5dcad
+			progname, domainname, gsi_strerror(error));
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+
d5dcad
+	/*
d5dcad
+	 * The srvinfo list is already in RFC 2782 sorted order.  Try each
d5dcad
+	 * SRV record once, in the foreground.  Go with the first one that
d5dcad
+	 * works.
d5dcad
+	 */
d5dcad
+	for (tmp = si; tmp != NULL; tmp = tmp->si_next) {
d5dcad
+		pid_t pid;
d5dcad
+
d5dcad
+		pid = fork();
d5dcad
+		switch (pid) {
d5dcad
+		case 0:
d5dcad
+			exec_mount_nfs4(tmp->si_target, tmp->si_port,
d5dcad
+					domainname, export_path, mounted_on_dir,
d5dcad
+					text_options);
d5dcad
+			/*NOTREACHED*/
d5dcad
+			fprintf(stderr, _("%s: Failed to exec: %s\n"),
d5dcad
+				progname, strerror(errno));
d5dcad
+			exit(EX_FAIL);
d5dcad
+		case -1:
d5dcad
+			fprintf(stderr, _("%s: Failed to fork: %s\n"),
d5dcad
+				progname, strerror(errno));
d5dcad
+			goto out;
d5dcad
+		default:
d5dcad
+			waitpid(pid, &status, 0);
d5dcad
+			if (status == EX_SUCCESS)
d5dcad
+				goto out;
d5dcad
+		}
d5dcad
+	}
d5dcad
+
d5dcad
+out:
d5dcad
+	freesrvinfo(si);
d5dcad
+	return status;
d5dcad
+}
d5dcad
+
d5dcad
+/**
d5dcad
+ * Try one mount request
d5dcad
+ *
d5dcad
+ * @param source NUL-terminated C string containing name of "special device"
d5dcad
+ * @param target NUL-terminated C string containing local mounted-on directory
d5dcad
+ * @param text_options NUL-terminated C string containing user's mount options
d5dcad
+ * @return an exit status code
d5dcad
+ *
d5dcad
+ * Parse the pathname in "source."  It contains the file system protocol
d5dcad
+ * and FedFS domain name.  Then pass these arguments to the appropriate
d5dcad
+ * mount helper subcommand.
d5dcad
+ */
d5dcad
+static int
d5dcad
+try_mount(const char *source, const char *target, const char *text_options)
d5dcad
+{
d5dcad
+	char *global_name, *topdir, *domainname, *remaining;
d5dcad
+	int result;
d5dcad
+
d5dcad
+	remaining = NULL;
d5dcad
+	result = EX_FAIL;
d5dcad
+
d5dcad
+	global_name = strdup(source);
d5dcad
+	if (global_name == NULL) {
d5dcad
+		fprintf(stderr, _("%s: Unable to parse globally useful name\n"),
d5dcad
+				progname);
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+
d5dcad
+	topdir = strtok(global_name, "/");
d5dcad
+	if (topdir == NULL) {
d5dcad
+		fprintf(stderr, _("%s: Invalid globally useful name: %s\n"),
d5dcad
+			progname, source);
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+	if (verbose)
d5dcad
+		printf(_("%s: Top-level directory:  %s\n"),
d5dcad
+			progname, topdir);
d5dcad
+
d5dcad
+	domainname = strtok(NULL, "/");
d5dcad
+	if (domainname == NULL) {
d5dcad
+		fprintf(stderr, _("%s: Missing domain name in globally "
d5dcad
+				"useful name: %s\n"), progname, source);
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+	if (verbose)
d5dcad
+		printf(_("%s: Domain name:          %s\n"),
d5dcad
+			progname, domainname);
d5dcad
+
d5dcad
+	remaining = strtok(NULL, "/");
d5dcad
+	if (remaining == NULL) {
d5dcad
+		remaining = strdup("/");
d5dcad
+		if (remaining == NULL) {
d5dcad
+			fprintf(stderr, _("%s: No memory\n"), progname);
d5dcad
+			goto out;
d5dcad
+		}
d5dcad
+	} else {
d5dcad
+		char *tmp;
d5dcad
+
d5dcad
+		tmp = malloc(strlen(remaining) + 1);
d5dcad
+		if (tmp == NULL) {
d5dcad
+			fprintf(stderr, _("%s: No memory\n"), progname);
d5dcad
+			remaining = NULL;
d5dcad
+			goto out;
d5dcad
+		}
d5dcad
+		strcpy(tmp, "/");
d5dcad
+		strcat(tmp, remaining);
d5dcad
+		remaining = tmp;
d5dcad
+	}
d5dcad
+	if (verbose)
d5dcad
+		printf(_("%s: Export path:          %s\n"),
d5dcad
+			progname, remaining);
d5dcad
+
d5dcad
+	if (strcmp(topdir, FEDFS_NFS4_TLDIR) == 0)
d5dcad
+		result = nfs4_mount(domainname, remaining, target, text_options);
d5dcad
+#if 0
d5dcad
+	/* example: SMB support plugs in here */
d5dcad
+	else if (strcmp(topdir, FEDFS_SMB_TLDIR) == 0)
d5dcad
+		result = smb_mount(domainname, remaining, target, text_options);
d5dcad
+#endif
d5dcad
+	else
d5dcad
+		fprintf(stderr, _("%s: Unrecognized file system protocol\n"), progname);
d5dcad
+
d5dcad
+out:
d5dcad
+	free(global_name);
d5dcad
+	free(remaining);
d5dcad
+
d5dcad
+	return result;
d5dcad
+}
d5dcad
+
d5dcad
+/**
d5dcad
+ * Program entry point
d5dcad
+ *
d5dcad
+ * @param argc count of command line arguments
d5dcad
+ * @param argv array of NUL-terminated C strings containing command line arguments
d5dcad
+ * @return program exit status
d5dcad
+ */
d5dcad
+int main(int argc, char *argv[])
d5dcad
+{
d5dcad
+	char *source, *target, *text_options;
d5dcad
+	int c, mnt_err;
d5dcad
+
d5dcad
+	(void)setlocale(LC_ALL, "");
d5dcad
+
d5dcad
+	progname = basename(argv[0]);
d5dcad
+
d5dcad
+	if (argv[1] && argv[1][0] == '-') {
d5dcad
+		if(argv[1][1] == 'V')
d5dcad
+			printf("%s (VERSION_STRING)\n", progname);
d5dcad
+		else
d5dcad
+			mount_usage();
d5dcad
+		exit(EX_SUCCESS);
d5dcad
+	}
d5dcad
+
d5dcad
+	if (argc < 3) {
d5dcad
+		mount_usage();
d5dcad
+		exit(EX_USAGE);
d5dcad
+	}
d5dcad
+
d5dcad
+	source = argv[1];
d5dcad
+	target = argv[2];
d5dcad
+
d5dcad
+	mnt_err = EX_USAGE;
d5dcad
+	text_options = NULL;
d5dcad
+	readonly = false;
d5dcad
+	sloppy = false;
d5dcad
+	fake = false;
d5dcad
+	argv[2] = argv[0]; /* so that getopt error messages are correct */
d5dcad
+	while ((c = getopt_long(argc - 2, argv + 2, fedfs_opts,
d5dcad
+				fedfs_longopts, NULL)) != -1) {
d5dcad
+		switch (c) {
d5dcad
+		case 'f':
d5dcad
+			fake = true;
d5dcad
+			break;
d5dcad
+		case 'n':
d5dcad
+			++nomtab;
d5dcad
+			break;
d5dcad
+		case 'o':
d5dcad
+			/* Ugh. */
d5dcad
+			if (text_options != NULL)
d5dcad
+				text_options = xstrconcat3(text_options, ",", optarg);
d5dcad
+			else
d5dcad
+				text_options = strdup(optarg);
d5dcad
+			if (text_options == NULL) {
d5dcad
+				fprintf(stderr, _("%s: No memory\n"), progname);
d5dcad
+				goto out;
d5dcad
+			}
d5dcad
+			break;
d5dcad
+		case 'r':
d5dcad
+			readonly = true;
d5dcad
+			break;
d5dcad
+		case 's':
d5dcad
+			sloppy = true;
d5dcad
+			break;
d5dcad
+		case 'v':
d5dcad
+			++verbose;
d5dcad
+			break;
d5dcad
+		case 'V':
d5dcad
+			printf("%s: (VERSION_STRING)\n", progname);
d5dcad
+			mnt_err = EX_SUCCESS;
d5dcad
+			goto out;
d5dcad
+		case 'w':
d5dcad
+			readonly = false;
d5dcad
+			break;
d5dcad
+		case 'h':
d5dcad
+		default:
d5dcad
+			mount_usage();
d5dcad
+			goto out;
d5dcad
+		}
d5dcad
+	}
d5dcad
+
d5dcad
+	/* Extra non-option words at the end are bogus...  */
d5dcad
+	if (optind != argc - 2) {
d5dcad
+		mount_usage();
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+
d5dcad
+	if (getuid() != 0 && geteuid() != 0) {
d5dcad
+		fprintf(stderr, _("%s: Not installed setuid - "
d5dcad
+			    "\"user\" FedFS mounts are not supported\n"), progname);
d5dcad
+		mnt_err = EX_FAIL;
d5dcad
+		goto out;
d5dcad
+	}
d5dcad
+
d5dcad
+	mnt_err = try_mount(source, target, text_options);
d5dcad
+
d5dcad
+out:
d5dcad
+	free(text_options);
d5dcad
+	exit(mnt_err);
d5dcad
+}