From: Steve Dickson <SteveD@redhat.com>
To: Linux NFS Mailing list <linux-nfs@vger.kernel.org>,
Linux NFSv4 mailing list <nfsv4@linux-nfs.org>
Subject: [Patch 6/10] NFS Mount Configuration File (Vers 3)
Date: Thu, 06 Aug 2009 14:45:36 -0400 [thread overview]
Message-ID: <4A7B24D0.1060209@RedHat.com> (raw)
In-Reply-To: <4A7B2324.9090406@RedHat.com>
commit 8e88dd908d8b5ff07649c375ff638ee6ca964ead
Author: Steve Dickson <steved@redhat.com>
Date: Wed Aug 5 16:17:38 2009 -0400
Support routines used to read sections from the configuration file
and parse them into comma separated mount options.
Signed-off-by: Steve Dickson <steved@redhat.com>
diff --git a/utils/mount/Makefile.am b/utils/mount/Makefile.am
index 459fa45..a1b56ca 100644
--- a/utils/mount/Makefile.am
+++ b/utils/mount/Makefile.am
@@ -17,6 +17,10 @@ mount_nfs_SOURCES = mount.c error.c network.c fstab.c token.c \
parse_opt.h parse_dev.h \
nfs4_mount.h nfs_mount4.h stropts.h version.h
+if MOUNT_CONFIG
+mount_nfs_SOURCES += configfile.c
+endif
+
mount_nfs_LDADD = ../../support/nfs/libnfs.a \
../../support/export/libexport.a
diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c
new file mode 100644
index 0000000..cad8c52
--- /dev/null
+++ b/utils/mount/configfile.c
@@ -0,0 +1,317 @@
+/*
+ * configfile.c -- mount configuration file manipulation
+ * Copyright (C) 2008 Red Hat, Inc <nfs@redhat.com>
+ *
+ * - Routines use to create mount options from the mount
+ * configuration file.
+ *
+ * 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.
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "xlog.h"
+#include "conffile.h"
+
+#define KBYTES(x) ((x) * (1024))
+#define MEGABYTES(x) ((x) * (1048576))
+#define GIGABYTES(x) ((x) * (1073741824))
+
+#ifndef NFSMOUNT_GLOBAL_OPTS
+#define NFSMOUNT_GLOBAL_OPTS "NFSMount_Global_Options"
+#endif
+
+#ifndef NFSMOUNT_MOUNTPOINT "MountPoint"
+#define NFSMOUNT_MOUNTPOINT "MountPoint"
+#endif
+
+#ifndef NFSMOUNT_SERVER "Server"
+#define NFSMOUNT_SERVER "Server"
+#endif
+
+#ifndef MOUNTOPTS_CONFFILE
+#define MOUNTOPTS_CONFFILE "/etc/nfsmount.conf"
+#endif
+char *conf_path = MOUNTOPTS_CONFFILE;
+enum {
+ MNT_NOARG=0,
+ MNT_INTARG,
+ MNT_STRARG,
+ MNT_SPEC,
+ MNT_UNSET
+};
+struct mnt_alias {
+ char *alias;
+ char *opt;
+ int argtype;
+} mnt_alias_tab[] = {
+ {"background", "bg", MNT_NOARG},
+ {"foreground", "fg", MNT_NOARG},
+ {"sloppy", "sloppy", MNT_NOARG},
+};
+int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
+
+/*
+ * See if the option is an alias, if so return the
+ * real mount option along with the argument type.
+ */
+inline static
+char *mountopts_alias(char *opt, int *argtype)
+{
+ int i;
+
+ *argtype = MNT_UNSET;
+ for (i=0; i < mnt_alias_sz; i++) {
+ if (strcasecmp(opt, mnt_alias_tab[i].alias) != 0)
+ continue;
+ *argtype = mnt_alias_tab[i].argtype;
+ return mnt_alias_tab[i].opt;
+ }
+ return opt;
+}
+/*
+ * Convert numeric strings that end with 'k', 'm' or 'g'
+ * into numeric strings with the real value.
+ * Meaning '8k' becomes '8094'.
+ */
+char *mountopts_convert(char *value)
+{
+ unsigned long long factor, num;
+ static char buf[64];
+ char *ch;
+
+ ch = &value[strlen(value)-1];
+ switch (tolower(*ch)) {
+ case 'k':
+ factor = KBYTES(1);
+ break;
+ case 'm':
+ factor = MEGABYTES(1);
+ break;
+ case 'g':
+ factor = GIGABYTES(1);
+ break;
+ default:
+ return value;
+ }
+ *ch = '\0';
+ if (strncmp(value, "0x", 2) == 0) {
+ num = strtol(value, (char **)NULL, 16);
+ } else if (strncmp(value, "0", 1) == 0) {
+ num = strtol(value, (char **)NULL, 8);
+ } else {
+ num = strtol(value, (char **)NULL, 10);
+ }
+ num *= factor;
+ snprintf(buf, 64, "%lld", num);
+
+ return buf;
+}
+
+struct entry {
+ SLIST_ENTRY(entry) entries;
+ char *opt;
+};
+static SLIST_HEAD(shead, entry) head = SLIST_HEAD_INITIALIZER(head);
+static int list_size;
+
+/*
+ * Add option to the link list
+ */
+inline static void
+add_entry(char *opt)
+{
+ struct entry *entry;
+
+ entry = calloc(1, sizeof(struct entry));
+ if (entry == NULL) {
+ xlog_warn("Unable calloc memory for mount configs");
+ return;
+ }
+ entry->opt = strdup(opt);
+ if (entry->opt == NULL) {
+ xlog_warn("Unable calloc memory for mount opts");
+ free(entry);
+ return;
+ }
+ SLIST_INSERT_HEAD(&head, entry, entries);
+}
+/*
+ * See if the given entry exists if the link list,
+ * if so return that entry
+ */
+inline static
+char *lookup_entry(char *opt)
+{
+ struct entry *entry;
+
+ SLIST_FOREACH(entry, &head, entries) {
+ if (strcasecmp(entry->opt, opt) == 0)
+ return opt;
+ }
+ return NULL;
+}
+/*
+ * Free all entries on the link list
+ */
+inline static
+void free_all(void)
+{
+ struct entry *entry;
+
+ while (!SLIST_EMPTY(&head)) {
+ entry = SLIST_FIRST(&head);
+ SLIST_REMOVE_HEAD(&head, entries);
+ free(entry->opt);
+ free(entry);
+ }
+}
+/*
+ * Parse the given section of the configuration
+ * file to if there are any mount options set.
+ * If so, added them to link list.
+ */
+static void
+conf_parse_mntopts(char *section, char *arg, char *opts)
+{
+ struct conf_list *list;
+ struct conf_list_node *node;
+ char buf[BUFSIZ], *value, *field;
+ char *nvalue, *ptr;
+ int argtype;
+
+ list = conf_get_tag_list(section);
+ TAILQ_FOREACH(node, &list->fields, link) {
+ /*
+ * Do not overwrite options if already exists
+ */
+ snprintf(buf, BUFSIZ, "%s=", node->field);
+ if (opts && strstr(opts, buf) != NULL)
+ continue;
+ if (lookup_entry(node->field) != NULL)
+ continue;
+ buf[0] = '\0';
+ value = conf_get_section(section, arg, node->field);
+ if (value == NULL)
+ continue;
+ field = mountopts_alias(node->field, &argtype);
+ if (strcasecmp(value, "false") == 0) {
+ if (argtype != MNT_NOARG)
+ snprintf(buf, BUFSIZ, "no%s", field);
+ } else if (strcasecmp(value, "true") == 0) {
+ snprintf(buf, BUFSIZ, "%s", field);
+ } else {
+ nvalue = strdup(value);
+ ptr = mountopts_convert(nvalue);
+ snprintf(buf, BUFSIZ, "%s=%s", field, ptr);
+ free(nvalue);
+ }
+ if (buf[0] == '\0')
+ continue;
+ /*
+ * Keep a running tally of the list size adding
+ * one for the ',' that will be appened later
+ */
+ list_size += strlen(buf) + 1;
+ add_entry(buf);
+ }
+ conf_free_list(list);
+}
+
+/*
+ * Concatenate options from the configuration file with the
+ * given options by building a link list of options from the
+ * different sections in the conf file. Options that exists
+ * in the either the given options or link list are not
+ * overwritten so it matter which when each section is
+ * parsed.
+ */
+char *conf_get_mntopts(char *spec, char *mount_point,
+ char *mount_opts)
+{
+ struct entry *entry;
+ char *ptr, *server, *config_opts;
+ int optlen = 0;
+
+ SLIST_INIT(&head);
+ list_size = 0;
+ /*
+ * First see if there are any mount options relative
+ * to the mount point.
+ */
+ conf_parse_mntopts(NFSMOUNT_MOUNTPOINT, mount_point, mount_opts);
+
+ /*
+ * Next, see if there are any mount options relative
+ * to the server
+ */
+ server = strdup(spec);
+ if (server == NULL) {
+ xlog_warn("conf_get_mountops: Unable calloc memory for server");
+ free_all();
+ return mount_opts;
+ }
+ if ((ptr = strchr(server, ':')) != NULL)
+ *ptr='\0';
+ conf_parse_mntopts(NFSMOUNT_SERVER, server, mount_opts);
+ free(server);
+
+ /*
+ * Finally process all the global mount options.
+ */
+ conf_parse_mntopts(NFSMOUNT_GLOBAL_OPTS, NULL, mount_opts);
+
+ /*
+ * If no mount options were found in the configuration file
+ * just return what was passed in .
+ */
+ if (SLIST_EMPTY(&head))
+ return mount_opts;
+
+ /*
+ * Found options in the configuration file. So
+ * concatenate the configuration options with the
+ * options that were passed in
+ */
+ if (mount_opts)
+ optlen = strlen(mount_opts);
+
+ /* list_size + optlen + ',' + '\0' */
+ config_opts = calloc(1, (list_size+optlen+2));
+ if (server == NULL) {
+ xlog_warn("conf_get_mountops: Unable calloc memory for config_opts");
+ free_all();
+ return mount_opts;
+ }
+ if (mount_opts) {
+ strcpy(config_opts, mount_opts);
+ strcat(config_opts, ",");
+ }
+ SLIST_FOREACH(entry, &head, entries) {
+ strcat(config_opts, entry->opt);
+ strcat(config_opts, ",");
+ }
+ *(strrchr(config_opts, ',')) = '\0';
+
+ free_all();
+ if (mount_opts)
+ free(mount_opts);
+
+ return config_opts;
+}
next prev parent reply other threads:[~2009-08-06 18:45 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2009-08-06 18:38 [Patch 0/10] NFS Mount Configuration File (Vers 3) Steve Dickson
2009-08-06 18:40 ` [Patch 1/10] " Steve Dickson
2009-08-07 8:06 ` Benny Halevy
2009-08-07 17:09 ` Steve Dickson
[not found] ` <4A7B2324.9090406-AfCzQyP5zfLQT0dZR+AlfA@public.gmane.org>
2009-08-06 18:41 ` [Patch 2/10] " Steve Dickson
[not found] ` <4A7B23D2.6080900-AfCzQyP5zfLQT0dZR+AlfA@public.gmane.org>
2009-08-07 8:07 ` Benny Halevy
2009-08-07 17:11 ` Steve Dickson
[not found] ` <4A7C6032.4060301-AfCzQyP5zfLQT0dZR+AlfA@public.gmane.org>
2009-08-08 20:52 ` Benny Halevy
2009-08-06 18:44 ` [Patch 5/10] " Steve Dickson
2009-08-06 18:47 ` [Patch 8/10] " Steve Dickson
2009-08-06 18:42 ` [Patch 3/10] " Steve Dickson
2009-08-07 7:38 ` Benny Halevy
2009-08-07 17:13 ` Steve Dickson
2009-08-07 18:35 ` Steve Dickson
2009-08-08 20:54 ` Benny Halevy
2009-08-06 18:43 ` [Patch 4/10] " Steve Dickson
2009-08-06 18:45 ` Steve Dickson [this message]
2009-08-06 20:44 ` [Patch 6/10] " Chuck Lever
2009-08-07 17:34 ` Steve Dickson
2009-08-06 18:46 ` [Patch 7/10] " Steve Dickson
[not found] ` <4A7B2515.2040304-AfCzQyP5zfLQT0dZR+AlfA@public.gmane.org>
2009-08-06 20:35 ` Chuck Lever
2009-08-07 17:17 ` Steve Dickson
2009-08-07 18:37 ` Steve Dickson
2009-08-06 18:48 ` [Patch 9/10] " Steve Dickson
2009-08-06 18:49 ` [Patch 10/10] " Steve Dickson
2009-08-17 13:12 ` [Patch 0/10] " Steve Dickson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4A7B24D0.1060209@RedHat.com \
--to=steved@redhat.com \
--cc=linux-nfs@vger.kernel.org \
--cc=nfsv4@linux-nfs.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.