Skip to contentSkip to conversation

NFS Mount Configuration File (Vers 2)

PATCH In review Steve Dickson 2 participants 21 messages Aug 3, 2009 – Aug 5, 2009 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover NFS Mount Configuration File (Vers 2)

Hello,

This is an updated version of the mount configuration patches I sent out a few months ago... The main difference in these patches is this functionality is only enabled by a configuration flag (see patch 4/8 for details).

I have been convinced that its probably best to leave it up to the individual users or distros to decide if they want a system-wide mount configuration file and where the file should live.

The following patch set introduces a configuration file where mount options can be define. The options in the file can be applied globally or per server or per mount point.

The patch set reuses the configuration parsing code that idmapd uses. I did added a couple enhancements like ignoring blanks in certain definitions as well as at the beginning of assignment statements.

There are man pages include in the patch set but in a nut shell, the configuration file has three basic types of sections. A global section, server section and mount point section. There can only be one global section and multiple server and mount point sections.

The mount command prioritize these sections in the following way:
* Options on the command line are always used.

* Options defined in the mount point section are used as long a the options are not in the command line options.

* Options defined in the server section are used as long as they are not defined on the command line or in the mount point section.

* Options defined in the global section are used as long as the options are not on the command line or in the mount point section or in the server section.

This is the first step toward moving the default NFS version from 3 to 4 on the client. Having a configuration file which allows users to define the maximum and minimum NFS versions that should be negotiated is the right thing to do... IMHO.. Even though this patch does not does not do that, it does lay the ground work for that type of functionality.

The entire patch set is available at:
http://people.redhat.com/steved/mount-conf/ver02/

and on the 'mount_conf-ver02' branch on my experimental git tree:
git://linux-nfs.org/~steved/nfs-utils-exp.git

Comments?

steved.
_______________________________________________
NFSv4 mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

#1 lore raw

PATCH 1/8 NFS Mount Configuration File (Vers 2)

commit 6ac5162f456950052d2ae59f8d375ceee694d432

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:26:52 2009 -0400

Move idmapd's configuration file parsing routines into the shared libnfs.a library, making them available to\
other daemons and programs.
=

support/include/Makefile.am +2 -1
index 718abda..f5a77ec 100644
@@ -14,6 +14,7 @@ noinst_HEADERS =3D \
 	xio.h \
 	xlog.h \
 	xmalloc.h \
-	xcommon.h
+	xcommon.h \
+	conffile.h
 =
 

MAINTAINERCLEANFILES =3D Makefile.in

support/include/conffile.h new file +18 -0
new file mode 100644
index 0000000..3309788
@@ -0,0 +1,67 @@
+/* $OpenBSD: conf.h,v 1.30 2004/06/25 20:25:34 hshoexer Exp $	 */
+/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $	 */
+
+/*
+ * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
+ * Copyright (c) 2000, 2003 H=E5kan Olsson.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI=

ES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF US= E,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This code was written under funding by Ericsson Radio Systems.
+ */
+
+#ifndef _CONFFILE_H_
+#define _CONFFILE_H_
+
+#include <sys/queue.h>
+
+struct conf_list_node {
+ TAILQ_ENTRY(conf_list_node) link;
+ char *field;
+};
+
+struct conf_list {
+ size_t cnt;
+ TAILQ_HEAD(conf_list_fields_head, conf_list_node) fields;
+};
+
+extern char *conf_path;
+

+extern int      conf_begin(void);
+extern int      conf_decode_base64(u_int8_t *, u_int32_t *, u_char *);
+extern int      conf_end(int, int);
+extern void     conf_free_list(struct conf_list *);

+extern struct sockaddr *conf_get_address(char *, char *); +extern struct conf_list *conf_get_list(char *, char *); +extern struct conf_list *conf_get_tag_list(char *);
+extern int conf_get_num(char *, char *, int);
+extern char *conf_get_str(char *, char *);

+extern void     conf_init(void);
+extern int      conf_match_num(char *, char *, int);
+extern void     conf_reinit(void);
+extern int      conf_remove(int, char *, char *);
+extern int      conf_remove_section(int, char *);
+extern int      conf_set(int, char *, char *, char *, int, int);
+extern void     conf_report(void);

+
+#endif /* _CONFFILE_H_ */

support/nfs/Makefile.am +1 -1
index 86f52a1..63e1800 100644
@@ -4,7 +4,7 @@ noinst_LIBRARIES =3D libnfs.a
 libnfs_a_SOURCES =3D exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
 		   xlog.c xcommon.c wildmat.c nfssvc.c nfsclient.c \
 		   nfsexport.c getfh.c nfsctl.c rpc_socket.c getport.c \
-		   svc_socket.c cacheio.c closeall.c nfs_mntent.c
+		   svc_socket.c cacheio.c closeall.c nfs_mntent.c conffile.c
 =
 
 MAINTAINERCLEANFILES =3D Makefile.in

=

support/nfs/conffile.c new file +5 -0
new file mode 100644
index 0000000..eea888e
@@ -0,0 +1,850 @@
+/*	$OpenBSD: conf.c,v 1.55 2003/06/03 14:28:16 ho Exp $	*/
+/*	$EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $	*/
+
+/*
+ * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist.  All rights rese=

rved.
+ * Copyright (c) 2000, 2001, 2002 H=E5kan Olsson. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF US= E,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This code was written under funding by Ericsson Radio Systems.
+ */
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <err.h>
+#include <syslog.h>
+
+#include "conffile.h"
+#include "xlog.h"
+
+static void conf_load_defaults (int);
+#if 0
+static int conf_find_trans_xf (int, char *);
+#endif
+
+size_t strlcpy(char *, const char *, size_t);
+
+struct conf_trans {
+ TAILQ_ENTRY (conf_trans) link;
+ int trans;
+ enum conf_op { CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION } op;
+ char *section;
+ char *tag;
+ char *value;
+ int override;
+ int is_default;
+};
+
+TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue;
+
+/*
+ * Radix-64 Encoding.
+ */
+static const u_int8_t bin2asc[]
+ =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +
+static const u_int8_t asc2bin[] =3D
+{

+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255, 255, 255, 255, 255, 255,
+  255, 255, 255,  62, 255, 255, 255,  63,
+   52,  53,  54,  55,  56,  57,  58,  59,
+   60,  61, 255, 255, 255, 255, 255, 255,
+  255,   0,   1,   2,   3,   4,   5,   6,
+    7,   8,   9,  10,  11,  12,  13,  14,
+   15,  16,  17,  18,  19,  20,  21,  22,
+   23,  24,  25, 255, 255, 255, 255, 255,
+  255,  26,  27,  28,  29,  30,  31,  32,
+   33,  34,  35,  36,  37,  38,  39,  40,
+   41,  42,  43,  44,  45,  46,  47,  48,
+   49,  50,  51, 255, 255, 255, 255, 255
+};
+
+struct conf_binding {
+  LIST_ENTRY (conf_binding) link;
+  char *section;
+  char *tag;
+  char *value;
+  int is_default;

+};
+
+char *conf_path;
+LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256]; +
+static char *conf_addr;
+
+static __inline__ u_int8_t
+conf_hash(char *s)
+{
+ u_int8_t hash =3D 0;
+
+ while (*s) {
+ hash =3D ((hash << 1) | (hash >> 7)) ^ tolower (*s);
+ s++;
+ }
+ return hash;
+}
+
+/*
+ * Insert a tag-value combination from LINE (the equal sign is at POS)
+ */
+static int
+conf_remove_now(char *section, char *tag)
+{
+ struct conf_binding *cb, *next;
+
+ cb =3D LIST_FIRST(&conf_bindings[conf_hash (section)]);
+ for (; cb; cb =3D next) {
+ next =3D LIST_NEXT(cb, link);
+ if (strcasecmp(cb->section, section) =3D=3D 0
+ && strcasecmp(cb->tag, tag) =3D=3D 0) {
+ LIST_REMOVE(cb, link);
+ xlog(LOG_INFO,"[%s]:%s->%s removed", section, tag, cb->value);
+ free(cb->section);
+ free(cb->tag);
+ free(cb->value);
+ free(cb);
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int
+conf_remove_section_now(char *section)
+{
+ struct conf_binding *cb, *next;
+ int unseen =3D 1;
+
+ cb =3D LIST_FIRST(&conf_bindings[conf_hash (section)]);
+ for (; cb; cb =3D next) {
+ next =3D LIST_NEXT(cb, link);
+ if (strcasecmp(cb->section, section) =3D=3D 0) {
+ unseen =3D 0;
+ LIST_REMOVE(cb, link);
+ xlog(LOG_INFO, "[%s]:%s->%s removed", section, cb->tag, cb->value);
+ free(cb->section);
+ free(cb->tag);
+ free(cb->value);
+ free(cb);
+ }
+ }
+ return unseen;
+}
+
+/*
+ * Insert a tag-value combination from LINE (the equal sign is at POS)
+ * into SECTION of our configuration database.
+ */
+static int
+conf_set_now(char *section, char *tag, char *value, int override,
+ int is_default)
+{
+ struct conf_binding *node =3D 0;
+
+ if (override)
+ conf_remove_now(section, tag);
+ else if (conf_get_str(section, tag)) {
+ if (!is_default) {
+ xlog(LOG_INFO, "conf_set: duplicate tag [%s]:%s, ignoring...\n", =

+ section, tag);
+ }
+ return 1;
+ }
+
+ node =3D calloc(1, sizeof *node);
+ if (!node) {
+ xlog_warn("conf_set: calloc (1, %lu) failed", (unsigned long)sizeof *nod=
e);
+ return 1;
+ }
+ node->section =3D strdup(section);
+ node->tag =3D strdup(tag);
+ node->value =3D strdup(value);
+ node->is_default =3D is_default;
+
+ LIST_INSERT_HEAD(&conf_bindings[conf_hash (section)], node, link);
+ return 0;
+}
+
+/*
+ * Parse the line LINE of SZ bytes. Skip Comments, recognize section
+ * headers and feed tag-value pairs into our configuration database.
+ */
+static void
+conf_parse_line(int trans, char *line, size_t sz)
+{
+ char *val;
+ size_t i;
+ int j;
+ static char *section =3D 0;
+ static int ln =3D 0;
+
+ /* Lines starting with '#' or ';' are comments. */
+ ln++;
+ if (*line =3D=3D '#' || *line =3D=3D ';')
+ return;
+
+ /* '[section]' parsing... */
+ if (*line =3D=3D '[') {
+ for (i =3D 1; i < sz; i++)
+ if (line[i] =3D=3D ']')
+ break;
+ if (section)
+ free (section);
+ if (i =3D=3D sz) {
+ xlog_warn("conf_parse_line: %d:"
+ "non-matched ']', ignoring until next section", ln);
+ section =3D 0;
+ return;
+ }
+ section =3D malloc(i);
+ if (!section) {
+ xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
+ (unsigned long)i);
+ return;
+ }
+ strlcpy(section, line + 1, i);
+ return;
+ }
+
+ /* Deal with assignments. */
+ for (i =3D 0; i < sz; i++) {
+ if (line[i] =3D=3D '=3D') {
+ /* If no section, we are ignoring the lines. */
+ if (!section) {
+ xlog_warn("conf_parse_line: %d: ignoring line due to no section", =

+ ln);
+ return;
+ }
+ line[strcspn (line, " \t=3D")] =3D '\0';
+ val =3D line + i + 1 + strspn (line + i + 1, " \t");
+ /* Skip trailing whitespace, if any */
+ for (j =3D sz - (val - line) - 1; j > 0 && isspace(val[j]); j--)
+ val[j] =3D '\0';
+ /* XXX Perhaps should we not ignore errors? */
+ conf_set(trans, section, line, val, 0, 0);
+ return;
+ }
+ }
+ /* Other non-empty lines are weird. */
+ i =3D strspn(line, " \t");
+ if (line[i])
+ xlog_warn("conf_parse_line: %d: syntax error", ln);
+
+ return;
+}
+
+/* Parse the mapped configuration file. */
+static void
+conf_parse(int trans, char *buf, size_t sz)
+{
+ char *cp =3D buf;
+ char *bufend =3D buf + sz;
+ char *line;
+
+ line =3D cp;
+ while (cp < bufend) {
+ if (*cp =3D=3D '\n') {
+ /* Check for escaped newlines. */
+ if (cp > buf && *(cp - 1) =3D=3D '\\')
+ *(cp - 1) =3D *cp =3D ' ';
+ else {
+ *cp =3D '\0';
+ conf_parse_line(trans, line, cp - line);
+ line =3D cp + 1;
+ }
+ }
+ cp++;
+ }
+ if (cp !=3D line)
+ xlog_warn("conf_parse: last line non-terminated, ignored.");
+}
+
+static void
+conf_load_defaults(int tr)
+{
+ /* No defaults */
+ return;
+}
+
+void
+conf_init (void)
+{
+ unsigned int i;
+
+ for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
+ LIST_INIT (&conf_bindings[i]);
+
+ TAILQ_INIT (&conf_trans_queue);
+ conf_reinit();
+}
+
+/* Open the config file and map it into our address space, then parse it. =
*/
+void
+conf_reinit(void)
+{
+ struct conf_binding *cb =3D 0;
+ int fd, trans;
+ unsigned int i;
+ size_t sz;
+ char *new_conf_addr =3D 0;
+ struct stat sb;
+
+ if ((stat (conf_path, &sb) =3D=3D 0) || (errno !=3D ENOENT)) {
+ sz =3D sb.st_size;
+ fd =3D open (conf_path, O_RDONLY, 0);
+ if (fd =3D=3D -1) {
+ xlog_warn("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path);
+ return;
+ }
+
+ new_conf_addr =3D malloc(sz);
+ if (!new_conf_addr) {
+ xlog_warn("conf_reinit: malloc (%lu) failed", (unsigned long)sz);
+ goto fail;
+ }
+
+ /* XXX I assume short reads won't happen here. */
+ if (read (fd, new_conf_addr, sz) !=3D (int)sz) {
+ xlog_warn("conf_reinit: read (%d, %p, %lu) failed",
+ fd, new_conf_addr, (unsigned long)sz);
+ goto fail;
+ }
+ close(fd);
+
+ trans =3D conf_begin();
+ /* XXX Should we not care about errors and rollback? */
+ conf_parse(trans, new_conf_addr, sz);
+ }
+ else
+ trans =3D conf_begin();
+
+ /* Load default configuration values. */
+ conf_load_defaults(trans);
+
+ /* Free potential existing configuration. */
+ if (conf_addr) {
+ for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++) {
+ cb =3D LIST_FIRST (&conf_bindings[i]);
+ for (; cb; cb =3D LIST_FIRST (&conf_bindings[i]))
+ conf_remove_now(cb->section, cb->tag);
+ }
+ free (conf_addr);
+ }
+
+ conf_end(trans, 1);
+ conf_addr =3D new_conf_addr;
+ return;
+
+fail:
+ if (new_conf_addr)
+ free(new_conf_addr);
+ close (fd);
+}
+
+/*
+ * Return the numeric value denoted by TAG in section SECTION or DEF
+ * if that tag does not exist.
+ */
+int
+conf_get_num(char *section, char *tag, int def)
+{
+ char *value =3D conf_get_str(section, tag);
+
+ if (value)
+ return atoi(value);
+
+ return def;
+}
+
+/* Validate X according to the range denoted by TAG in section SECTION. */ +int
+conf_match_num(char *section, char *tag, int x)
+{
+ char *value =3D conf_get_str (section, tag);
+ int val, min, max, n;
+
+ if (!value)
+ return 0;
+ n =3D sscanf (value, "%d,%d:%d", &val, &min, &max);
+ switch (n) {
+ case 1:
+ xlog(LOG_INFO, "conf_match_num: %s:%s %d=3D=3D%d?", section, tag, val, x=
);
+ return x =3D=3D val;
+ case 3:
+ xlog(LOG_INFO, "conf_match_num: %s:%s %d<=3D%d<=3D%d?", section, =

+ tag, min, x, max);
+ return min <=3D x && max >=3D x;
+ default:
+ xlog(LOG_INFO, "conf_match_num: section %s tag %s: invalid number spec %=
s",
+ section, tag, value);
+ }
+ return 0;
+}
+
+/* Return the string value denoted by TAG in section SECTION. */ +char *
+conf_get_str(char *section, char *tag)
+{
+ struct conf_binding *cb;
+
+ cb =3D LIST_FIRST (&conf_bindings[conf_hash (section)]);
+ for (; cb; cb =3D LIST_NEXT (cb, link)) {
+ if (strcasecmp (section, cb->section) =3D=3D 0
+ && strcasecmp (tag, cb->tag) =3D=3D 0)
+ return cb->value;
+ }
+ return 0;
+}
+
+/*
+ * Build a list of string values out of the comma separated value denoted = by
+ * TAG in SECTION.
+ */
+struct conf_list *
+conf_get_list(char *section, char *tag)
+{
+ char *liststr =3D 0, *p, *field, *t;
+ struct conf_list *list =3D 0;
+ struct conf_list_node *node;
+
+ list =3D malloc (sizeof *list);
+ if (!list)
+ goto cleanup;
+ TAILQ_INIT (&list->fields);
+ list->cnt =3D 0;
+ liststr =3D conf_get_str(section, tag);
+ if (!liststr)
+ goto cleanup;
+ liststr =3D strdup (liststr);
+ if (!liststr)
+ goto cleanup;
+ p =3D liststr;
+ while ((field =3D strsep (&p, ",")) !=3D NULL) {
+ /* Skip leading whitespace */
+ while (isspace (*field))
+ field++;
+ /* Skip trailing whitespace */
+ if (p) {
+ for (t =3D p - 1; t > field && isspace (*t); t--)
+ *t =3D '\0';
+ }
+ if (*field =3D=3D '\0') {
+ xlog(LOG_INFO, "conf_get_list: empty field, ignoring...");
+ continue;
+ }
+ list->cnt++;
+ node =3D calloc (1, sizeof *node);
+ if (!node)
+ goto cleanup;
+ node->field =3D strdup (field);
+ if (!node->field) {
+ free(node);
+ goto cleanup;
+ }
+ TAILQ_INSERT_TAIL (&list->fields, node, link);
+ }
+ free (liststr);
+ return list;
+
+cleanup:
+ if (list)
+ conf_free_list(list);
+ if (liststr)
+ free(liststr);
+ return 0;
+}
+
+struct conf_list *
+conf_get_tag_list(char *section)
+{
+ struct conf_list *list =3D 0;
+ struct conf_list_node *node;
+ struct conf_binding *cb;
+
+ list =3D malloc(sizeof *list);
+ if (!list)
+ goto cleanup;
+ TAILQ_INIT(&list->fields);
+ list->cnt =3D 0;
+ cb =3D LIST_FIRST(&conf_bindings[conf_hash (section)]);
+ for (; cb; cb =3D LIST_NEXT(cb, link)) {
+ if (strcasecmp (section, cb->section) =3D=3D 0) {
+ list->cnt++;
+ node =3D calloc (1, sizeof *node);
+ if (!node)
+ goto cleanup;
+ node->field =3D strdup(cb->tag);
+ if (!node->field) {
+ free(node);
+ goto cleanup;
+ }
+ TAILQ_INSERT_TAIL(&list->fields, node, link);
+ }
+ }
+ return list;
+
+cleanup:
+ if (list)
+ conf_free_list(list);
+ return 0;
+}
+
+/* Decode a PEM encoded buffer. */
+int
+conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf) +{
+ u_int32_t c =3D 0;
+ u_int8_t c1, c2, c3, c4;
+
+ while (*buf) {
+ if (*buf > 127 || (c1 =3D asc2bin[*buf]) =3D=3D 255)
+ return 0;
+
+ buf++;
+ if (*buf > 127 || (c2 =3D asc2bin[*buf]) =3D=3D 255)
+ return 0;
+
+ buf++;
+ if (*buf =3D=3D '=3D') {
+ c3 =3D c4 =3D 0;
+ c++;
+
+ /* Check last four bit */
+ if (c2 & 0xF)
+ return 0;
+
+ if (strcmp((char *)buf, "=3D=3D") =3D=3D 0)
+ buf++;
+ else
+ return 0;
+ } else if (*buf > 127 || (c3 =3D asc2bin[*buf]) =3D=3D 255)
+ return 0;
+ else {
+ if (*++buf =3D=3D '=3D') {
+ c4 =3D 0;
+ c +=3D 2;
+
+ /* Check last two bit */
+ if (c3 & 3)
+ return 0;
+
+ if (strcmp((char *)buf, "=3D"))
+ return 0;
+ } else if (*buf > 127 || (c4 =3D asc2bin[*buf]) =3D=3D 255)
+ return 0;
+ else
+ c +=3D 3;
+ }
+
+ buf++;

+		*out++ =3D (c1 << 2) | (c2 >> 4);
+		*out++ =3D (c2 << 4) | (c3 >> 2);
+		*out++ =3D (c3 << 6) | c4;

+ }
+
+ *len =3D c;
+ return 1;
+}
+
+void
+conf_free_list(struct conf_list *list)
+{
+ struct conf_list_node *node =3D TAILQ_FIRST(&list->fields);
+
+ while (node) {
+ TAILQ_REMOVE(&list->fields, node, link);
+ if (node->field)
+ free(node->field);
+ free (node);
+ node =3D TAILQ_FIRST(&list->fields);
+ }
+ free (list);
+}
+
+int
+conf_begin (void)
+{
+ static int seq =3D 0;
+
+ return ++seq;
+}
+
+static struct conf_trans *
+conf_trans_node (int transaction, enum conf_op op) +{
+ struct conf_trans *node;
+
+ node =3D calloc (1, sizeof *node);
+ if (!node) {
+ xlog_warn("conf_trans_node: calloc (1, %lu) failed",
+ (unsigned long)sizeof *node);
+ return 0;
+ }
+ node->trans =3D transaction;
+ node->op =3D op;
+ TAILQ_INSERT_TAIL (&conf_trans_queue, node, link);
+ return node;
+}
+
+/* Queue a set operation. */
+int
+conf_set (int transaction, char *section, char *tag, =

+ char *value, int override, int is_default)
+{
+ struct conf_trans *node;
+
+ node =3D conf_trans_node(transaction, CONF_SET);
+ if (!node)
+ return 1;
+ node->section =3D strdup(section);
+ if (!node->section) {
+ xlog_warn("conf_set: strdup(\"%s\") failed", section);
+ goto fail;
+ }
+ node->tag =3D strdup(tag);
+ if (!node->tag) {
+ xlog_warn("conf_set: strdup(\"%s\") failed", tag);
+ goto fail;
+ }
+ node->value =3D strdup(value);
+ if (!node->value) {
+ xlog_warn("conf_set: strdup(\"%s\") failed", value);
+ goto fail;
+ }
+ node->override =3D override;
+ node->is_default =3D is_default;
+ return 0;
+
+fail:
+ if (node->tag)
+ free(node->tag);
+ if (node->section)
+ free(node->section);
+ if (node)
+ free(node);
+ return 1;
+}
+
+/* Queue a remove operation. */
+int
+conf_remove(int transaction, char *section, char *tag)
+{
+ struct conf_trans *node;
+
+ node =3D conf_trans_node(transaction, CONF_REMOVE);
+ if (!node)
+ goto fail;
+ node->section =3D strdup(section);
+ if (!node->section) {
+ xlog_warn("conf_remove: strdup(\"%s\") failed", section);
+ goto fail;
+ }
+ node->tag =3D strdup(tag);
+ if (!node->tag) {
+ xlog_warn("conf_remove: strdup(\"%s\") failed", tag);
+ goto fail;
+ }
+ return 0;
+
+fail:
+ if (node && node->section)
+ free (node->section);
+ if (node)
+ free (node);
+ return 1;
+}
+
+/* Queue a remove section operation. */
+int
+conf_remove_section(int transaction, char *section)
+{
+ struct conf_trans *node;
+
+ node =3D conf_trans_node(transaction, CONF_REMOVE_SECTION);
+ if (!node)
+ goto fail;
+ node->section =3D strdup(section);
+ if (!node->section) {
+ xlog_warn("conf_remove_section: strdup(\"%s\") failed", section);
+ goto fail;
+ }
+ return 0;
+
+fail:
+ if (node)
+ free(node);
+ return 1;
+}
+
+/* Execute all queued operations for this transaction. Cleanup. */ +int
+conf_end(int transaction, int commit)
+{
+ struct conf_trans *node, *next;
+
+ for (node =3D TAILQ_FIRST(&conf_trans_queue); node; node =3D next) {
+ next =3D TAILQ_NEXT(node, link);
+ if (node->trans =3D=3D transaction) {
+ if (commit) {
+ switch (node->op) {
+ case CONF_SET:
+ conf_set_now(node->section, node->tag, node->value,
+ node->override, node->is_default);
+ break;
+ case CONF_REMOVE:
+ conf_remove_now(node->section, node->tag);
+ break;
+ case CONF_REMOVE_SECTION:
+ conf_remove_section_now(node->section);
+ break;
+ default:
+ xlog(LOG_INFO, "conf_end: unknown operation: %d", node->op);
+ }
+ }
+ TAILQ_REMOVE (&conf_trans_queue, node, link);
+ if (node->section)
+ free(node->section);
+ if (node->tag)
+ free(node->tag);
+ if (node->value)
+ free(node->value);
+ free (node);
+ }
+ }
+ return 0;
+}
+
+/*
+ * Dump running configuration upon SIGUSR1.
+ * Configuration is "stored in reverse order", so reverse it again.
+ */
+struct dumper {
+ char *s, *v;
+ struct dumper *next;
+};
+
+static void
+conf_report_dump(struct dumper *node)
+{
+ /* Recursive, cleanup when we're done. */
+ if (node->next)
+ conf_report_dump(node->next);
+
+ if (node->v)
+ xlog(LOG_INFO, "%s=3D\t%s", node->s, node->v);
+ else if (node->s) {
+ xlog(LOG_INFO, "%s", node->s);
+ if (strlen(node->s) > 0)
+ free(node->s);
+ }
+
+ free (node);
+}
+
+void
+conf_report (void)
+{
+ struct conf_binding *cb, *last =3D 0;
+ unsigned int i, len;
+ char *current_section =3D (char *)0;
+ struct dumper *dumper, *dnode;
+
+ dumper =3D dnode =3D (struct dumper *)calloc(1, sizeof *dumper);
+ if (!dumper)
+ goto mem_fail;
+
+ xlog(LOG_INFO, "conf_report: dumping running configuration");
+
+ for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
+ for (cb =3D LIST_FIRST(&conf_bindings[i]); cb; cb =3D LIST_NEXT(cb, link=
)) {
+ if (!cb->is_default) {
+ /* Dump this entry. */
+ if (!current_section || strcmp(cb->section, current_section)) {
+ if (current_section) {
+ len =3D strlen (current_section) + 3;
+ dnode->s =3D malloc(len);
+ if (!dnode->s)
+ goto mem_fail;
+
+ snprintf(dnode->s, len, "[%s]", current_section);
+ dnode->next =3D =

+ (struct dumper *)calloc(1, sizeof (struct dumper));
+ dnode =3D dnode->next;
+ if (!dnode)
+ goto mem_fail;
+
+ dnode->s =3D "";
+ dnode->next =3D =

+ (struct dumper *)calloc(1, sizeof (struct dumper));
+ dnode =3D dnode->next;
+ if (!dnode)
+ goto mem_fail;
+ }
+ current_section =3D cb->section;
+ }
+ dnode->s =3D cb->tag;
+ dnode->v =3D cb->value;
+ dnode->next =3D (struct dumper *)calloc (1, sizeof (struct dumper));
+ dnode =3D dnode->next;
+ if (!dnode)
+ goto mem_fail;
+ last =3D cb;
+ }
+ }
+
+ if (last) {
+ len =3D strlen(last->section) + 3;
+ dnode->s =3D malloc(len);
+ if (!dnode->s)
+ goto mem_fail;
+ snprintf(dnode->s, len, "[%s]", last->section);
+ }
+ conf_report_dump(dumper);
+ return;
+
+mem_fail:
+ xlog_warn("conf_report: malloc/calloc failed");
+ while ((dnode =3D dumper) !=3D 0) {
+ dumper =3D dumper->next;
+ if (dnode->s)
+ free(dnode->s);
+ free(dnode);
+ }
+ return;
+}

utils/idmapd/Makefile.am +0 -1
index eb393df..4dabb3d 100644
@@ -14,7 +14,6 @@ EXTRA_DIST =3D \
 =
 
 idmapd_SOURCES =3D \
 	atomicio.c \
-	cfg.c \
 	idmapd.c \
 	strlcat.c \

strlcpy.c \

utils/idmapd/cfg.c deleted +0 -5
deleted file mode 100644
index 16d392a..0000000
@@ -1,893 +0,0 @@
-/*	$OpenBSD: conf.c,v 1.55 2003/06/03 14:28:16 ho Exp $	*/
-/*	$EOM: conf.c,v 1.48 2000/12/04 02:04:29 angelos Exp $	*/
-
-/*
- * Copyright (c) 1998, 1999, 2000, 2001 Niklas Hallqvist.  All rights rese=

rved.
- * Copyright (c) 2000, 2001, 2002 H=E5kan Olsson. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI= ES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF US= E,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code was written under funding by Ericsson Radio Systems.
- */
-
-#include <sys/param.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-#include <err.h>
-
-#include "cfg.h"
-
-static void conf_load_defaults (int);
-#if 0
-static int conf_find_trans_xf (int, char *);
-#endif
-
-size_t strlcpy(char *, const char *, size_t);
-
-struct conf_trans {

-  TAILQ_ENTRY (conf_trans) link;
-  int trans;
-  enum conf_op { CONF_SET, CONF_REMOVE, CONF_REMOVE_SECTION } op;
-  char *section;
-  char *tag;
-  char *value;
-  int override;
-  int is_default;

-};
-
-TAILQ_HEAD (conf_trans_head, conf_trans) conf_trans_queue;
-
-/*
- * Radix-64 Encoding.
- */
-const u_int8_t bin2asc[]
- =3D "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -
-const u_int8_t asc2bin[] =3D
-{

-  255, 255, 255, 255, 255, 255, 255, 255,
-  255, 255, 255, 255, 255, 255, 255, 255,
-  255, 255, 255, 255, 255, 255, 255, 255,
-  255, 255, 255, 255, 255, 255, 255, 255,
-  255, 255, 255, 255, 255, 255, 255, 255,
-  255, 255, 255,  62, 255, 255, 255,  63,
-   52,  53,  54,  55,  56,  57,  58,  59,
-   60,  61, 255, 255, 255, 255, 255, 255,
-  255,   0,   1,   2,   3,   4,   5,   6,
-    7,   8,   9,  10,  11,  12,  13,  14,
-   15,  16,  17,  18,  19,  20,  21,  22,
-   23,  24,  25, 255, 255, 255, 255, 255,
-  255,  26,  27,  28,  29,  30,  31,  32,
-   33,  34,  35,  36,  37,  38,  39,  40,
-   41,  42,  43,  44,  45,  46,  47,  48,
-   49,  50,  51, 255, 255, 255, 255, 255
-};
-
-struct conf_binding {
-  LIST_ENTRY (conf_binding) link;
-  char *section;
-  char *tag;
-  char *value;
-  int is_default;

-};
-
-char *conf_path;
-LIST_HEAD (conf_bindings, conf_binding) conf_bindings[256];
-
-static char *conf_addr;
-
-static __inline__ u_int8_t
-conf_hash (char *s)
-{
- u_int8_t hash =3D 0;
-
- while (*s)
- {
- hash =3D ((hash << 1) | (hash >> 7)) ^ tolower (*s);
- s++;
- }
- return hash;
-}
-
-/*
- * Insert a tag-value combination from LINE (the equal sign is at POS)
- */
-static int
-conf_remove_now (char *section, char *tag)
-{
- struct conf_binding *cb, *next;
-
- for (cb =3D LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb =3D= next)
- {
- next =3D LIST_NEXT (cb, link);
- if (strcasecmp (cb->section, section) =3D=3D 0
- && strcasecmp (cb->tag, tag) =3D=3D 0)
- {

-	  LIST_REMOVE (cb, link);
-	  warnx("[%s]:%s->%s removed", section, tag, cb->value);
-	  free (cb->section);
-	  free (cb->tag);
-	  free (cb->value);
-	  free (cb);
-	  return 0;

- }
- }
- return 1;
-}
-
-static int
-conf_remove_section_now (char *section)
-{
- struct conf_binding *cb, *next;
- int unseen =3D 1;
-
- for (cb =3D LIST_FIRST (&conf_bindings[conf_hash (section)]); cb; cb =3D= next)
- {
- next =3D LIST_NEXT (cb, link);
- if (strcasecmp (cb->section, section) =3D=3D 0)
- {

-	  unseen =3D 0;
-	  LIST_REMOVE (cb, link);
-	  warnx("[%s]:%s->%s removed", section, cb->tag, cb->value);
-	  free (cb->section);
-	  free (cb->tag);
-	  free (cb->value);
-	  free (cb);

- }
- }
- return unseen;
-}
-
-/*
- * Insert a tag-value combination from LINE (the equal sign is at POS)
- * into SECTION of our configuration database.
- */
-static int
-conf_set_now (char *section, char *tag, char *value, int override,
- int is_default)
-{
- struct conf_binding *node =3D 0;
-
- if (override)
- conf_remove_now (section, tag);
- else if (conf_get_str (section, tag))
- {
- if (!is_default)
- warnx("conf_set: duplicate tag [%s]:%s, ignoring...\n", section, tag);
- return 1;
- }
-
- node =3D calloc (1, sizeof *node);
- if (!node)
- {
- warnx("conf_set: calloc (1, %lu) failed", (unsigned long)sizeof *nod=
e);
- return 1;
- }

-  node->section =3D strdup (section);
-  node->tag =3D strdup (tag);
-  node->value =3D strdup (value);
-  node->is_default =3D is_default;

-
- LIST_INSERT_HEAD (&conf_bindings[conf_hash (section)], node, link);
- return 0;
-}
-
-/*
- * Parse the line LINE of SZ bytes. Skip Comments, recognize section
- * headers and feed tag-value pairs into our configuration database.
- */
-static void
-conf_parse_line (int trans, char *line, size_t sz)
-{

-  char *val;
-  size_t i;
-  int j;
-  static char *section =3D 0;
-  static int ln =3D 0;

-
- ln++;
-
- /* Lines starting with '#' or ';' are comments. */
- if (*line =3D=3D '#' || *line =3D=3D ';')
- return;
-
- /* '[section]' parsing... */
- if (*line =3D=3D '[')
- {
- for (i =3D 1; i < sz; i++)
- if (line[i] =3D=3D ']')
- break;
- if (section)
- free (section);
- if (i =3D=3D sz)
- {
- warnx("conf_parse_line: %d:"
- "non-matched ']', ignoring until next section", ln);
- section =3D 0;
- return;
- }
- section =3D malloc (i);
- if (!section)
- {
- warnx("conf_parse_line: %d: malloc (%lu) failed", ln,
- (unsigned long)i);
- return;
- }
- strlcpy (section, line + 1, i);
- return;
- }
-
- /* Deal with assignments. */
- for (i =3D 0; i < sz; i++)
- if (line[i] =3D=3D '=3D')
- {
- /* If no section, we are ignoring the lines. */
- if (!section)
- {
- warnx("conf_parse_line: %d: ignoring line due to no section", ln);
- return;
- }
- line[strcspn (line, " \t=3D")] =3D '\0';
- val =3D line + i + 1 + strspn (line + i + 1, " \t");
- /* Skip trailing whitespace, if any */
- for (j =3D sz - (val - line) - 1; j > 0 && isspace (val[j]); j--)
- val[j] =3D '\0';
- /* XXX Perhaps should we not ignore errors? */
- conf_set (trans, section, line, val, 0, 0);
- return;
- }
-

-  /* Other non-empty lines are weird.  */
-  i =3D strspn (line, " \t");
-  if (line[i])

- warnx("conf_parse_line: %d: syntax error", ln);
-
- return;
-}
-
-/* Parse the mapped configuration file. */
-static void
-conf_parse (int trans, char *buf, size_t sz)
-{

-  char *cp =3D buf;
-  char *bufend =3D buf + sz;
-  char *line;

-
- line =3D cp;
- while (cp < bufend)
- {
- if (*cp =3D=3D '\n')
- {
- /* Check for escaped newlines. */
- if (cp > buf && *(cp - 1) =3D=3D '\\')
- *(cp - 1) =3D *cp =3D ' ';
- else
- {

-	      *cp =3D '\0';
-	      conf_parse_line (trans, line, cp - line);
-	      line =3D cp + 1;

- }
- }
- cp++;
- }
- if (cp !=3D line)
- warnx("conf_parse: last line non-terminated, ignored.");
-}
-
-static void
-conf_load_defaults (int tr)
-{
- /* No defaults */
- return;
-}
-
-void
-conf_init (void)
-{
- unsigned int i;
-
- for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
- LIST_INIT (&conf_bindings[i]);
- TAILQ_INIT (&conf_trans_queue);
- conf_reinit ();
-}
-
-/* Open the config file and map it into our address space, then parse it. =
*/
-void
-conf_reinit (void)
-{

-  struct conf_binding *cb =3D 0;
-  int fd, trans;
-  unsigned int i;
-  size_t sz;
-  char *new_conf_addr =3D 0;
-  struct stat sb;
-
-  if ((stat (conf_path, &sb) =3D=3D 0) || (errno !=3D ENOENT))
-    {
-      sz =3D sb.st_size;
-      fd =3D open (conf_path, O_RDONLY, 0);
-      if (fd =3D=3D -1)

- {
- warnx("conf_reinit: open (\"%s\", O_RDONLY) failed", conf_path);
- return;
- }
-
- new_conf_addr =3D malloc (sz);
- if (!new_conf_addr)
- {
- warnx("conf_reinit: malloc (%lu) failed", (unsigned long)sz);
- goto fail;
- }
-
- /* XXX I assume short reads won't happen here. */
- if (read (fd, new_conf_addr, sz) !=3D (int)sz)
- {
- warnx("conf_reinit: read (%d, %p, %lu) failed",
- fd, new_conf_addr, (unsigned long)sz);
- goto fail;
- }
- close (fd);
-
- trans =3D conf_begin ();
-
- /* XXX Should we not care about errors and rollback? */
- conf_parse (trans, new_conf_addr, sz);
- }
- else
- trans =3D conf_begin ();
-
- /* Load default configuration values. */
- conf_load_defaults (trans);
-
- /* Free potential existing configuration. */
- if (conf_addr)
- {
- for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i+=
+)
- for (cb =3D LIST_FIRST (&conf_bindings[i]); cb;
- cb =3D LIST_FIRST (&conf_bindings[i]))
- conf_remove_now (cb->section, cb->tag);
- free (conf_addr);
- }
-

-  conf_end (trans, 1);
-  conf_addr =3D new_conf_addr;
-  return;

-
- fail:
- if (new_conf_addr)
- free (new_conf_addr);
- close (fd);
-}
-
-/*
- * Return the numeric value denoted by TAG in section SECTION or DEF
- * if that tag does not exist.
- */
-int
-conf_get_num (char *section, char *tag, int def)
-{
- char *value =3D conf_get_str (section, tag);
-
- if (value)
- return atoi (value);
- return def;
-}
-
-/* Validate X according to the range denoted by TAG in section SECTION. */ -int
-conf_match_num (char *section, char *tag, int x)
-{
- char *value =3D conf_get_str (section, tag);
- int val, min, max, n;
-
- if (!value)
- return 0;
- n =3D sscanf (value, "%d,%d:%d", &val, &min, &max);
- switch (n)
- {
- case 1:
- warnx("conf_match_num: %s:%s %d=3D=3D%d?", section, tag, val, x);
- return x =3D=3D val;
- case 3:
- warnx("conf_match_num: %s:%s %d<=3D%d<=3D%d?", section, tag, min, x,=
max);
- return min <=3D x && max >=3D x;
- default:
- warnx("conf_match_num: section %s tag %s: invalid number spec %s",
- section, tag, value);
- }
- return 0;
-}
-
-/* Return the string value denoted by TAG in section SECTION. */ -char *
-conf_get_str (char *section, char *tag)
-{
- struct conf_binding *cb;
-
- for (cb =3D LIST_FIRST (&conf_bindings[conf_hash (section)]); cb;
- cb =3D LIST_NEXT (cb, link))
- if (strcasecmp (section, cb->section) =3D=3D 0
- && strcasecmp (tag, cb->tag) =3D=3D 0)
- {
- return cb->value;
- }
- return 0;
-}
-
-/*
- * Build a list of string values out of the comma separated value denoted = by
- * TAG in SECTION.
- */
-struct conf_list *
-conf_get_list (char *section, char *tag)
-{

-  char *liststr =3D 0, *p, *field, *t;
-  struct conf_list *list =3D 0;
-  struct conf_list_node *node;

-
- list =3D malloc (sizeof *list);
- if (!list)
- goto cleanup;

-  TAILQ_INIT (&list->fields);
-  list->cnt =3D 0;
-  liststr =3D conf_get_str (section, tag);
-  if (!liststr)

- goto cleanup;
- liststr =3D strdup (liststr);
- if (!liststr)
- goto cleanup;
- p =3D liststr;
- while ((field =3D strsep (&p, ",")) !=3D NULL)
- {
- /* Skip leading whitespace */
- while (isspace (*field))
- field++;
- /* Skip trailing whitespace */
- if (p)
- for (t =3D p - 1; t > field && isspace (*t); t--)
- *t =3D '\0';
- if (*field =3D=3D '\0')
- {
- warnx("conf_get_list: empty field, ignoring...");
- continue;
- }

-      list->cnt++;
-      node =3D calloc (1, sizeof *node);
-      if (!node)

- goto cleanup;
- node->field =3D strdup (field);
- if (!node->field) {
- free(node);
- goto cleanup;
- }
- TAILQ_INSERT_TAIL (&list->fields, node, link);
- }
- free (liststr);
- return list;
-
- cleanup:
- if (list)
- conf_free_list (list);
- if (liststr)
- free (liststr);
- return 0;
-}
-
-struct conf_list *
-conf_get_tag_list (char *section)
-{

-  struct conf_list *list =3D 0;
-  struct conf_list_node *node;
-  struct conf_binding *cb;

-
- list =3D malloc (sizeof *list);
- if (!list)
- goto cleanup;

-  TAILQ_INIT (&list->fields);
-  list->cnt =3D 0;
-  for (cb =3D LIST_FIRST (&conf_bindings[conf_hash (section)]); cb;

- cb =3D LIST_NEXT (cb, link))
- if (strcasecmp (section, cb->section) =3D=3D 0)
- {
- list->cnt++;
- node =3D calloc (1, sizeof *node);
- if (!node)
- goto cleanup;
- node->field =3D strdup (cb->tag);
- if (!node->field) {
- free(node);
- goto cleanup;
- }
- TAILQ_INSERT_TAIL (&list->fields, node, link);
- }
- return list;
-
- cleanup:
- if (list)
- conf_free_list (list);
- return 0;
-}
-
-/* Decode a PEM encoded buffer. */
-int
-conf_decode_base64 (u_int8_t *out, u_int32_t *len, u_char *buf) -{
- u_int32_t c =3D 0;
- u_int8_t c1, c2, c3, c4;
-
- while (*buf)
- {
- if (*buf > 127 || (c1 =3D asc2bin[*buf]) =3D=3D 255)
- return 0;
- buf++;
-
- if (*buf > 127 || (c2 =3D asc2bin[*buf]) =3D=3D 255)
- return 0;
- buf++;
-
- if (*buf =3D=3D '=3D')
- {
- c3 =3D c4 =3D 0;
- c++;
-
- /* Check last four bit */
- if (c2 & 0xF)
- return 0;
-
- if (strcmp ((char *)buf, "=3D=3D") =3D=3D 0)
- buf++;
- else
- return 0;
- }
- else if (*buf > 127 || (c3 =3D asc2bin[*buf]) =3D=3D 255)
- return 0;
- else
- {
- if (*++buf =3D=3D '=3D')
- {
- c4 =3D 0;
- c +=3D 2;
-
- /* Check last two bit */
- if (c3 & 3)
- return 0;
-
- if (strcmp ((char *)buf, "=3D"))
- return 0;
-
- }
- else if (*buf > 127 || (c4 =3D asc2bin[*buf]) =3D=3D 255)
- return 0;
- else
- c +=3D 3;
- }
-

-      buf++;
-      *out++ =3D (c1 << 2) | (c2 >> 4);
-      *out++ =3D (c2 << 4) | (c3 >> 2);
-      *out++ =3D (c3 << 6) | c4;

- }
-
- *len =3D c;
- return 1;
-
-}
-
-void
-conf_free_list (struct conf_list *list)
-{
- struct conf_list_node *node =3D TAILQ_FIRST (&list->fields); -
- while (node)
- {
- TAILQ_REMOVE (&list->fields, node, link);
- if (node->field)
- free (node->field);
- free (node);
- node =3D TAILQ_FIRST (&list->fields);
- }
- free (list);
-}
-
-int
-conf_begin (void)
-{
- static int seq =3D 0;
-
- return ++seq;
-}
-
-static struct conf_trans *
-conf_trans_node (int transaction, enum conf_op op) -{
- struct conf_trans *node;
-
- node =3D calloc (1, sizeof *node);
- if (!node)
- {
- warnx("conf_trans_node: calloc (1, %lu) failed",
- (unsigned long)sizeof *node);
- return 0;
- }

-  node->trans =3D transaction;
-  node->op =3D op;
-  TAILQ_INSERT_TAIL (&conf_trans_queue, node, link);
-  return node;

-}
-
-/* Queue a set operation. */
-int
-conf_set (int transaction, char *section, char *tag, char *value, int over= ride,
- int is_default)
-{
- struct conf_trans *node;
-
- node =3D conf_trans_node (transaction, CONF_SET);
- if (!node)
- return 1;
- node->section =3D strdup (section);
- if (!node->section)
- {
- warnx("conf_set: strdup (\"%s\") failed", section);
- goto fail;
- }
- node->tag =3D strdup (tag);
- if (!node->tag)
- {
- warnx("conf_set: strdup (\"%s\") failed", tag);
- goto fail;
- }
- node->value =3D strdup (value);
- if (!node->value)
- {
- warnx("conf_set: strdup (\"%s\") failed", value);
- goto fail;
- }

-  node->override =3D override;
-  node->is_default =3D is_default;
-  return 0;

-
- fail:
- if (node->tag)
- free (node->tag);
- if (node->section)
- free (node->section);
- if (node)
- free (node);
- return 1;
-}
-
-/* Queue a remove operation. */
-int
-conf_remove (int transaction, char *section, char *tag)
-{
- struct conf_trans *node;
-
- node =3D conf_trans_node (transaction, CONF_REMOVE);
- if (!node)
- goto fail;
- node->section =3D strdup (section);
- if (!node->section)
- {
- warnx("conf_remove: strdup (\"%s\") failed", section);
- goto fail;
- }
- node->tag =3D strdup (tag);
- if (!node->tag)
- {
- warnx("conf_remove: strdup (\"%s\") failed", tag);
- goto fail;
- }
- return 0;
-
- fail:
- if (node && node->section)
- free (node->section);
- if (node)
- free (node);
- return 1;
-}
-
-/* Queue a remove section operation. */
-int
-conf_remove_section (int transaction, char *section)
-{
- struct conf_trans *node;
-
- node =3D conf_trans_node (transaction, CONF_REMOVE_SECTION);
- if (!node)
- goto fail;
- node->section =3D strdup (section);
- if (!node->section)
- {
- warnx("conf_remove_section: strdup (\"%s\") failed", section);
- goto fail;
- }
- return 0;
-
- fail:
- if (node)
- free (node);
- return 1;
-}
-
-/* Execute all queued operations for this transaction. Cleanup. */ -int
-conf_end (int transaction, int commit)
-{
- struct conf_trans *node, *next;
-
- for (node =3D TAILQ_FIRST (&conf_trans_queue); node; node =3D next)
- {
- next =3D TAILQ_NEXT (node, link);
- if (node->trans =3D=3D transaction)
- {
- if (commit)
- switch (node->op)
- {
- case CONF_SET:
- conf_set_now (node->section, node->tag, node->value,
- node->override, node->is_default);
- break;
- case CONF_REMOVE:
- conf_remove_now (node->section, node->tag);
- break;
- case CONF_REMOVE_SECTION:
- conf_remove_section_now (node->section);
- break;
- default:
- warnx("conf_end: unknown operation: %d", node->op);
- }
- TAILQ_REMOVE (&conf_trans_queue, node, link);
- if (node->section)
- free (node->section);
- if (node->tag)
- free (node->tag);
- if (node->value)
- free (node->value);
- free (node);
- }
- }
- return 0;
-}
-
-/*
- * Dump running configuration upon SIGUSR1.
- * Configuration is "stored in reverse order", so reverse it again.
- */
-struct dumper {
- char *s, *v;
- struct dumper *next;
-};
-
-static void
-conf_report_dump (struct dumper *node)
-{
- /* Recursive, cleanup when we're done. */
-
- if (node->next)
- conf_report_dump (node->next);
-
- if (node->v)
- warnx("%s=3D\t%s", node->s, node->v);
- else if (node->s)
- {
- warnx("%s", node->s);
- if (strlen (node->s) > 0)
- free (node->s);
- }
-
- free (node);
-}
-
-void
-conf_report (void)
-{

-  struct conf_binding *cb, *last =3D 0;
-  unsigned int i, len;
-  char *current_section =3D (char *)0;
-  struct dumper *dumper, *dnode;

-
- dumper =3D dnode =3D (struct dumper *)calloc (1, sizeof *dumper);
- if (!dumper)
- goto mem_fail;
-
- warnx("conf_report: dumping running configuration");
-
- for (i =3D 0; i < sizeof conf_bindings / sizeof conf_bindings[0]; i++)
- for (cb =3D LIST_FIRST (&conf_bindings[i]); cb;
- cb =3D LIST_NEXT (cb, link))
- {
- if (!cb->is_default)
- {

-	    /* Dump this entry.  */
-	    if (!current_section || strcmp (cb->section, current_section))
-	      {
-		if (current_section)
-		  {
-		    len =3D strlen (current_section) + 3;
-		    dnode->s =3D malloc (len);
-		    if (!dnode->s)

- goto mem_fail;
-
- snprintf (dnode->s, len, "[%s]", current_section);
- dnode->next
- =3D (struct dumper *)calloc (1, sizeof (struct dumper));
- dnode =3D dnode->next;
- if (!dnode)
- goto mem_fail;
-
- dnode->s =3D "";
- dnode->next
- =3D (struct dumper *)calloc (1, sizeof (struct dumper));
- dnode =3D dnode->next;
- if (!dnode)
- goto mem_fail;
- }
- current_section =3D cb->section;
- }

-	    dnode->s =3D cb->tag;
-	    dnode->v =3D cb->value;
-	    dnode->next =3D (struct dumper *)calloc (1, sizeof (struct dumper));
-	    dnode =3D dnode->next;
-	    if (!dnode)

- goto mem_fail;
- last =3D cb;
- }
- }
-
- if (last)
- {

-      len =3D strlen (last->section) + 3;
-      dnode->s =3D malloc (len);
-      if (!dnode->s)

- goto mem_fail;
- snprintf (dnode->s, len, "[%s]", last->section);
- }
-
- conf_report_dump (dumper);
-
- return;
-
- mem_fail:
- warnx("conf_report: malloc/calloc failed");
- while ((dnode =3D dumper) !=3D 0)
- {
- dumper =3D dumper->next;
- if (dnode->s)
- free (dnode->s);
- free (dnode);
- }
- return;
-}

utils/idmapd/cfg.h deleted +0 -18
deleted file mode 100644
index c1ca940..0000000
@@ -1,67 +0,0 @@
-/* $OpenBSD: conf.h,v 1.30 2004/06/25 20:25:34 hshoexer Exp $	 */
-/* $EOM: conf.h,v 1.13 2000/09/18 00:01:47 ho Exp $	 */
-
-/*
- * Copyright (c) 1998, 1999, 2001 Niklas Hallqvist.  All rights reserved.
- * Copyright (c) 2000, 2003 H=E5kan Olsson.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTI=

ES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF US= E,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/*
- * This code was written under funding by Ericsson Radio Systems.
- */
-
-#ifndef _CONF_H_
-#define _CONF_H_
-
-#include "queue.h"
-
-struct conf_list_node {
- TAILQ_ENTRY(conf_list_node) link;
- char *field;
-};
-
-struct conf_list {
- size_t cnt;
- TAILQ_HEAD(conf_list_fields_head, conf_list_node) fields;
-};
-
-extern char *conf_path;
-

-extern int      conf_begin(void);
-extern int      conf_decode_base64(u_int8_t *, u_int32_t *, u_char *);
-extern int      conf_end(int, int);
-extern void     conf_free_list(struct conf_list *);

-extern struct sockaddr *conf_get_address(char *, char *); -extern struct conf_list *conf_get_list(char *, char *); -extern struct conf_list *conf_get_tag_list(char *);
-extern int conf_get_num(char *, char *, int);
-extern char *conf_get_str(char *, char *);

-extern void     conf_init(void);
-extern int      conf_match_num(char *, char *, int);
-extern void     conf_reinit(void);
-extern int      conf_remove(int, char *, char *);
-extern int      conf_remove_section(int, char *);
-extern int      conf_set(int, char *, char *, char *, int, int);
-extern void     conf_report(void);

-
-#endif /* _CONF_H_ */

utils/idmapd/idmapd.c +1 -1
index 9cbe96c..65a6a2a 100644
@@ -66,7 +66,7 @@
 #endif /* HAVE_CONFIG_H */
 =
 
 #include "xlog.h"
-#include "cfg.h"
+#include "conffile.h"
 #include "queue.h"
 #include "nfslib.h"

=

@@ -156,7 +156,7 @@ static char *nobodyuser, *nobodygroup;
static uid_t nobodyuid;
static gid_t nobodygid;
=

-/* Used by cfg.c */
+/* Used by conffile.c in libnfs.a */
char *conf_path;
=

static int

#2 lore raw

PATCH 2/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 0fd0fe271ae99ed0f863f4c9e846bf793a616468

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:55:25 2009 -0400

Taught conf_parse_line() to ignore spaces in the
'[section]' parsing and before the assignment statements

support/nfs/conffile.c +26 -9
index eea888e..b36200b 100644
@@ -50,11 +50,6 @@
 #include "xlog.h"
 
 static void conf_load_defaults (int);
-#if 0
-static int conf_find_trans_xf (int, char *);
-#endif
-
-size_t  strlcpy(char *, const char *, size_t);
 
 struct conf_trans {
 	TAILQ_ENTRY (conf_trans) link;
@@ -219,26 +214,48 @@ conf_parse_line(int trans, char *line, size_t sz)
 	if (*line == '#' || *line == ';')
 		return;
 
+	/* Ignore blank lines */
+	if (*line == '\0')
+		return;
+
+	/* Strip off any leading blanks */
+	while (isblank(*line)) 
+		line++;
+
 	/* '[section]' parsing...  */
 	if (*line == '[') {
-		for (i = 1; i < sz; i++)
-			if (line[i] == ']')
+		line++;
+		/* Strip off any blanks after '[' */
+		while (isblank(*line)) 
+			line++;
+
+		for (i = 0; i < sz; i++) {
+			if (line[i] == ']') {
 				break;
+			}
+		}
 		if (section)
-			free (section);
+			free(section);
 		if (i == sz) {
 			xlog_warn("conf_parse_line: %d:"
  				"non-matched ']', ignoring until next section", ln);
 			section = 0;
 			return;
 		}
+		/* Strip off any blanks before ']' */
+		val = line;
+		while (*val && !isblank(*val)) 
+			val++, j++;
+		if (*val)
+			i = j;
+
 		section = malloc(i);
 		if (!section) {
 			xlog_warn("conf_parse_line: %d: malloc (%lu) failed", ln,
 						(unsigned long)i);
 			return;
 		}
-		strlcpy(section, line + 1, i);
+		strncpy(section, line, i);
 		return;
 	}
#3 lore raw

PATCH 3/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

support/nfs/conffile.c +20 -5
index b36200b..f5e0f79 100644
@@ -114,7 +114,16 @@ conf_hash(char *s)
 	}
 	return hash;
 }
+/*
+ * Convert letter from upper case to lower case
+ */
+static inline upper2lower(char *str)
+{
+	char *ptr = str;
 
+	while (*ptr) 
+		*ptr++ = tolower(*ptr);
+}
 /*
  * Insert a tag-value combination from LINE (the equal sign is at POS)
  */
@@ -523,7 +532,7 @@ conf_get_tag_list(char *section)
 	for (; cb; cb = LIST_NEXT(cb, link)) {
 		if (strcasecmp (section, cb->section) == 0) {
 			list->cnt++;
-			node = calloc (1, sizeof *node);
+			node = calloc(1, sizeof *node);
 			if (!node)
 				goto cleanup;
 			node->field = strdup(cb->tag);
@@ -615,7 +624,7 @@ conf_free_list(struct conf_list *list)
 }
 
 int
-conf_begin (void)
+conf_begin(void)
 {
   static int seq = 0;
 
@@ -623,7 +632,7 @@ conf_begin (void)
 }
 
 static struct conf_trans *
-conf_trans_node (int transaction, enum conf_op op)
+conf_trans_node(int transaction, enum conf_op op)
 {
 	struct conf_trans *node;
 
@@ -639,9 +648,9 @@ conf_trans_node (int transaction, enum conf_op op)
 	return node;
 }
 
-/* Queue a set operation.  */
+/* Queue a set operation.  Store value in lower case */
 int
-conf_set (int transaction, char *section, char *tag, 
+conf_set(int transaction, char *section, char *tag, 
 	char *value, int override, int is_default)
 {
 	struct conf_trans *node;
@@ -654,16 +663,22 @@ conf_set (int transaction, char *section, char *tag,
 		xlog_warn("conf_set: strdup(\"%s\") failed", section);
 		goto fail;
 	}
+	upper2lower(node->section);
+
 	node->tag = strdup(tag);
 	if (!node->tag) {
 		xlog_warn("conf_set: strdup(\"%s\") failed", tag);
 		goto fail;
 	}
+	upper2lower(node->tag);
+
 	node->value = strdup(value);
 	if (!node->value) {
 		xlog_warn("conf_set: strdup(\"%s\") failed", value);
 		goto fail;
 	}
+	upper2lower(node->value);
+
 	node->override = override;
 	node->is_default = is_default;
 	return 0;
#4 lore raw
Quoted 6 lines · Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

Just curious--which parts of the configuration file (section headers, keys, values--looks like maybe all 3?) are you making case-insensitive, and why do they need to be?

E.g. the idmapd configuration file contains paths and user/group names, and both those still need to be case sensitive.

--b.

Quoted 91 lines
support/nfs/conffile.c +20 -5
index b36200b..f5e0f79 100644
@@ -114,7 +114,16 @@ conf_hash(char *s)
 	}
 	return hash;
 }
+/*
+ * Convert letter from upper case to lower case
+ */
+static inline upper2lower(char *str)
+{
+	char *ptr = str;
 
+	while (*ptr) 
+		*ptr++ = tolower(*ptr);
+}
 /*
  * Insert a tag-value combination from LINE (the equal sign is at POS)
  */
@@ -523,7 +532,7 @@ conf_get_tag_list(char *section)
 	for (; cb; cb = LIST_NEXT(cb, link)) {
 		if (strcasecmp (section, cb->section) == 0) {
 			list->cnt++;
-			node = calloc (1, sizeof *node);
+			node = calloc(1, sizeof *node);
 			if (!node)
 				goto cleanup;
 			node->field = strdup(cb->tag);
@@ -615,7 +624,7 @@ conf_free_list(struct conf_list *list)
 }
 
 int
-conf_begin (void)
+conf_begin(void)
 {
   static int seq = 0;
 
@@ -623,7 +632,7 @@ conf_begin (void)
 }
 
 static struct conf_trans *
-conf_trans_node (int transaction, enum conf_op op)
+conf_trans_node(int transaction, enum conf_op op)
 {
 	struct conf_trans *node;
 
@@ -639,9 +648,9 @@ conf_trans_node (int transaction, enum conf_op op)
 	return node;
 }
 
-/* Queue a set operation.  */
+/* Queue a set operation.  Store value in lower case */
 int
-conf_set (int transaction, char *section, char *tag, 
+conf_set(int transaction, char *section, char *tag, 
 	char *value, int override, int is_default)
 {
 	struct conf_trans *node;
@@ -654,16 +663,22 @@ conf_set (int transaction, char *section, char *tag,
 		xlog_warn("conf_set: strdup(\"%s\") failed", section);
 		goto fail;
 	}
+	upper2lower(node->section);
+
 	node->tag = strdup(tag);
 	if (!node->tag) {
 		xlog_warn("conf_set: strdup(\"%s\") failed", tag);
 		goto fail;
 	}
+	upper2lower(node->tag);
+
 	node->value = strdup(value);
 	if (!node->value) {
 		xlog_warn("conf_set: strdup(\"%s\") failed", value);
 		goto fail;
 	}
+	upper2lower(node->value);
+
 	node->override = override;
 	node->is_default = is_default;
 	return 0;

_______________________________________________
NFSv4 mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

#5 lore raw
Quoted 11 lines · J. Bruce Fields
Quoted 6 lines · Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

Just curious--which parts of the configuration file (section headers, keys, values--looks like maybe all 3?) are you making case-insensitive, and why do they need to be?

Yes all three of them...

Quoted 3 lines

E.g. the idmapd configuration file contains paths and user/group names, and both those still need to be case sensitive.

hmm... good point... I would suspect this might be the case for all users of these routines since pathnames and user/group names are always case-sensitive....

I would guess both the section and keys can be case-insensitive but the key probably say case-sensitive...

steved.

#6 lore raw
Quoted 16 lines · Steve Dickson
Quoted 11 lines · J. Bruce Fields
Quoted 6 lines · Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

Just curious--which parts of the configuration file (section headers, keys, values--looks like maybe all 3?) are you making case-insensitive, and why do they need to be?

Yes all three of them...

Quoted 1 line
Quoted 8 lines
Quoted 2 lines

E.g. the idmapd configuration file contains paths and user/group names, and both those still need to be case sensitive.

hmm... good point... I would suspect this might be the case for all users of these routines since pathnames and user/group names are always case-sensitive....

I would guess both the section and keys can be case-insensitive but the key probably say case-sensitive...

If you're using mount paths, for example, in the section names, then that part also needs to be case-sensitive.

Probably the right thing to do is to leave the core config-file code out of the business of playing with case, and let the callers do it in particular cases when it's appropriate.

--b.

#7 lore raw
Quoted 20 lines · J. Bruce Fields
Quoted 19 lines · Steve Dickson
Quoted 10 lines · J. Bruce Fields
Quoted 6 lines · Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

Just curious--which parts of the configuration file (section headers, keys, values--looks like maybe all 3?) are you making case-insensitive, and why do they need to be?

Yes all three of them...

Quoted 2 lines

E.g. the idmapd configuration file contains paths and user/group names, and both those still need to be case sensitive.

hmm... good point... I would suspect this might be the case for all users of these routines since pathnames and user/group names are always case-sensitive....

Quoted 5 lines
Quoted 2 lines

I would guess both the section and keys can be case-insensitive but the key probably say case-sensitive...

If you're using mount paths, for example, in the section names, then that part also needs to be case-sensitive.

Point...

Quoted 4 lines

Probably the right thing to do is to leave the core config-file code out of the business of playing with case, and let the callers do it in particular cases when it's appropriate.

I guess... but that leaves the disconnect between what the caller expects the sections/keys to be called and what is actually in the config file. If the only difference is case, I was thinking routines should be smart enough to figure that out...

steved.

#8 lore raw
In reply to J. Bruce Fields
Quoted 23 lines · J. Bruce Fields
Quoted 13 lines · Steve Dickson
Quoted 10 lines · J. Bruce Fields
Quoted 6 lines · Steve Dickson

commit 528e270be6bb3e4a072cbbb7f3a8b378b64b7fba

Author: Steve Dickson <[email protected]>
Date:   Mon Mar 9 13:57:10 2009 -0400

Store values in lower case. This makes it easier to do string comparisons when reading lists from the configuration file.

Just curious--which parts of the configuration file (section headers, keys, values--looks like maybe all 3?) are you making case-insensitive, and why do they need to be?

Yes all three of them...

Quoted 8 lines
Quoted 2 lines

E.g. the idmapd configuration file contains paths and user/group names, and both those still need to be case sensitive.

hmm... good point... I would suspect this might be the case for all users of these routines since pathnames and user/group names are always case-sensitive....

I would guess both the section and keys can be case-insensitive but the key probably say case-sensitive...

Quoted 6 lines

If you're using mount paths, for example, in the section names, then that part also needs to be case-sensitive.

Probably the right thing to do is to leave the core config-file code out of the business of playing with case, and let the callers do it in particular cases when it's appropriate.

After thinking about this.. I've convinced myself that the internal parsing routines should make the Section names case-insensitive but the rest of the data (i.e the tag, value) should be returned as is and let the callers deal with the case...

The reason being everything hangs off Section names. So making those easier to find I think is a good thing and hopefully it will make managing config files a bit less error prone....

steved.

#9 lore raw
Quoted 8 lines · Steve Dickson

After thinking about this.. I've convinced myself that the internal parsing routines should make the Section names case-insensitive but the rest of the data (i.e the tag, value) should be returned as is and let the callers deal with the case...

The reason being everything hangs off Section names. So making those easier to find I think is a good thing and hopefully it will make managing config files a bit less error prone....

That's probably not what I would do, but I could live with that, as long as we're preserving the case of paths and user/group names.

By the way, it looks like the git code to handle their extended section names (the [key "string"] thing) is in git's config.c:get_extended_base_var(), if that's a useful example.

--b.

#10 lore raw
Quoted 10 lines · J. Bruce Fields
Quoted 8 lines · Steve Dickson

After thinking about this.. I've convinced myself that the internal parsing routines should make the Section names case-insensitive but the rest of the data (i.e the tag, value) should be returned as is and let the callers deal with the case...

The reason being everything hangs off Section names. So making those easier to find I think is a good thing and hopefully it will make managing config files a bit less error prone....

Quoted 6 lines

That's probably not what I would do, but I could live with that, as long as we're preserving the case of paths and user/group names.

By the way, it looks like the git code to handle their extended section names (the [key "string"] thing) is in git's config.c:get_extended_base_var(), if that's a useful example.

(And, by the way, they agree with you on case-sensitivity: from the git-config man page:

"The file consists of sections and variables. A section begins with the name of the section in square brackets and continues until the next section begins. Section names are not case sensitive. Only alphanumeric characters, - and . are allowed in section names. Each variable must belong to some section, which means that there must be section header before first setting of a variable.

"Sections can be further divided into subsections. To begin a subsection put its name in double quotes, separated by space from the section name, in the section header, like in example below:

[section "subsection"]

"Subsection names can contain any characters except newline (doublequote " and backslash have to be escaped as \" and \\, respectively) and are case sensitive. Section header cannot span multiple lines."

)

--b.

#11 lore raw
Quoted 13 lines · J. Bruce Fields
Quoted 12 lines · J. Bruce Fields
Quoted 8 lines · Steve Dickson

After thinking about this.. I've convinced myself that the internal parsing routines should make the Section names case-insensitive but the rest of the data (i.e the tag, value) should be returned as is and let the callers deal with the case...

The reason being everything hangs off Section names. So making those easier to find I think is a good thing and hopefully it will make managing config files a bit less error prone....

That's probably not what I would do, but I could live with that, as long as we're preserving the case of paths and user/group names.

Quoted 6 lines
Quoted 3 lines

By the way, it looks like the git code to handle their extended section names (the [key "string"] thing) is in git's config.c:get_extended_base_var(), if that's a useful example.

(And, by the way, they agree with you on case-sensitivity: from the git-config man page:

Every dog has his day!! 8-)

steved.

#12 lore raw
In reply to J. Bruce Fields
Quoted 6 lines · J. Bruce Fields
Quoted 5 lines · Steve Dickson

After thinking about this.. I've convinced myself that the internal parsing routines should make the Section names case-insensitive but the rest of the data (i.e the tag, value) should be returned as is and let the callers deal with the case...

Quoted 6 lines
Quoted 3 lines

The reason being everything hangs off Section names. So making those easier to find I think is a good thing and hopefully it will make managing config files a bit less error prone....

That's probably not what I would do, but I could live with that, as long as we're preserving the case of paths and user/group names.

Cool...

Quoted 4 lines

By the way, it looks like the git code to handle their extended section names (the [key "string"] thing) is in git's config.c:get_extended_base_var(), if that's a useful example.

I did take a look that this... but thier parse appears to be much different than what we use....

For better or worse (I'll make an official release) there is what I've come up with...
commit fede9b293a8faf6c4214f6dabdb1d8664929901d

Author: Steve Dickson <[email protected]>
Date:   Wed Aug 5 16:02:33 2009 -0400

Added an conditional argument to the Section names with the format being:
[ Section <"argument"> ]
This will help group similar functioning Section together. The argument is conditional but must be surrounded by the '"' characters.

The new conf_get_section() interface can used to locate a Section by its Section name and/or argument.

support/include/conffile.h +1 -1
index 3309788..b263581 100644
@@ -56,12 +56,12 @@ extern struct conf_list *conf_get_list(char *, char *);
 extern struct conf_list *conf_get_tag_list(char *);
 extern int      conf_get_num(char *, char *, int);
 extern char    *conf_get_str(char *, char *);
+extern char    *conf_get_section(char *, char *, char *);
 extern void     conf_init(void);
 extern int      conf_match_num(char *, char *, int);
 extern void     conf_reinit(void);
 extern int      conf_remove(int, char *, char *);
 extern int      conf_remove_section(int, char *);
-extern int      conf_set(int, char *, char *, char *, int, int);
 extern void     conf_report(void);
 
 #endif				/* _CONFFILE_H_ */
support/nfs/conffile.c +96 -18

258 lines not on this page · raw message

#13 lore raw

PATCH 4/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 259bf96f9e2b6836529158ea1b7ee3a02e3266b7

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:28:19 2009 -0400

Adds '--enable-mountconf' configuration flag that will enabled mount to read from a configuration file. The default value is disabled (or no)

Adds '--with-mountfile' configuration flag that is used when mountconf is enabled to define the configuration file name. The default is /etc/nfsmount.conf.

configure.ac +25 -0
index e0ca70e..5d26345 100644
@@ -136,6 +136,31 @@ AC_ARG_ENABLE(ipv6,
 	AC_SUBST(enable_ipv6)
 	AM_CONDITIONAL(CONFIG_IPV6, [test "$enable_ipv6" = "yes"])
 
+if test "$enable_mount" = yes; then
+	AC_ARG_ENABLE(mountconfig,
+	[AC_HELP_STRING([--enable-mountconf],
+                        [enable mount to use a configuration file])],
+	mountconfig=$enableval,
+	mountconfig=no)
+	if test "$enable_mountconfig" = yes; then
+		AC_DEFINE(MOUNT_CONFIG, 1, 
+			[Define this if you want mount to read a configuration file])
+		AC_ARG_WITH(mountfile,
+			[AC_HELP_STRING([--with-mountfile=filename],
+			[Using filename as the NFS mount options file [/etc/nfsmounts.conf]]
+			)],
+		mountfile=$withval,
+		mountfile=/etc/nfsmount.conf)
+		AC_SUBST(mountfile)
+		AC_DEFINE_UNQUOTED(MOUNTOPTS_CONFFILE, "$mountfile", 
+			[This defines the location of the NFS mount configuration file])
+	else
+		enable_mountconfig=
+	fi
+	AC_SUBST(enable_mountconfig)
+	AM_CONDITIONAL(MOUNT_CONFIG, [test "$enable_mountconfig" = "yes"])
+fi
+
 dnl Check for TI-RPC library and headers
 AC_LIBTIRPC
#14 lore raw

PATCH 5/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit ad1e3c82962efd986ff1bc84f1d9097fd5dbec0d

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:33:01 2009 -0400

Support routines used to read sections from the configuration file and parse them into comma separated mount options.

utils/mount/Makefile.am +4 -0
index 459fa45..a1b56ca 100644
@@ -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
 
utils/mount/configfile.c new file +299 -0

299 lines not on this page · raw message

#15 lore raw

PATCH 6/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 5b16b70e47d37f51f377efffd23663cf86a35311

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:37:19 2009 -0400

Added hooks to the mount command that allow mount options to be set in a configuration file

utils/mount/mount.c +18 -0
index a668cd9..30d087e 100644
@@ -47,6 +47,11 @@
 #include "stropts.h"
 #include "version.h"
 
+#ifdef MOUNT_CONFIG
+#include "conffile.h"
+extern char *conf_get_mntopts(char *, char *, char *);
+#endif
+
 char *progname;
 int nfs_mount_data_version;
 int nomtab;
@@ -474,6 +479,13 @@ int main(int argc, char *argv[])
 	spec = argv[1];
 	mount_point = argv[2];
 
+#ifdef MOUNT_CONFIG
+	/*
+	 * Read the the default mount options
+	 */
+	conf_init();
+#endif
+
 	argv[2] = argv[0]; /* so that getopt error messages are correct */
 	while ((c = getopt_long(argc - 2, argv + 2, "rvVwfno:hs",
 				longopts, NULL)) != -1) {
@@ -559,6 +571,12 @@ int main(int argc, char *argv[])
 		mnt_err = EX_USAGE;
 		goto out;
 	}
+#ifdef MOUNT_CONFIG
+	/*
+	 * Concatenate mount options from the configuration file
+	 */
+	mount_opts = conf_get_mntopts(spec, mount_point, mount_opts);
+#endif
 
 	parse_opts(mount_opts, &flags, &extra_opts);
#16 lore raw

PATCH 7/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 92e623c74908ffcc76da72e7927ce4e237062c76

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:41:03 2009 -0400

The new nfsmount.conf(5) man page and the update to the nfs(5) man page

utils/mount/Makefile.am +1 -0
index a1b56ca..5c1e5ad 100644
@@ -19,6 +19,7 @@ mount_nfs_SOURCES = mount.c error.c network.c fstab.c token.c \
 
 if MOUNT_CONFIG
 mount_nfs_SOURCES += configfile.c
+man5_MANS += nfsmount.conf.man
 endif
 
 mount_nfs_LDADD = ../../support/nfs/libnfs.a \
utils/mount/nfs.man +38 -0
index 13de524..251b16f 100644
@@ -752,6 +752,44 @@ In the presence of multiple client network interfaces,
 special routing policies,
 or atypical network topologies,
 the exact address to use for callbacks may be nontrivial to determine. 
+.SH MOUNT CONFIGURATION FILE
+All of the mount options described in the previous section can also be configured in
+the 
+.I /etc/nfsmount.conf 
+file. This configuration file is made up of three
+different sections: Global, Server and MountPoint. See 
+.BR nfsmount.conf(5)
+for details.
+.PP
+The mount command parses section in a particular order, and will not use
+options that were set in previous sections.  The order of precedence is as follows:
+
+.B Command line option 
+.RS
+options set on the command line will always be used.
+.RE
+.B Mount Point options
+.RS
+options set in the 
+.B [<Mount_Point>]
+section  will
+be used only if they are not specified on the command line.
+.RE
+.B Server options
+.RS
+options set in the 
+.B [<Server_Name>] 
+section will be used
+if they are not specified on the command  line or  the
+mount point section.
+.RE
+.B Global options 
+.RS
+options set in the 
+.B [NFSMount_Global_Options] 
+will be used if they are not specified on the command line, mount point 
+section, or the server section.
+.RE
 .SH EXAMPLES
 To mount an export using NFS version 2,
 use the
utils/mount/nfsmount.conf.man new file +87 -0

87 lines not on this page · raw message

A message that is not in the archive (sent off-list or not yet received): [email protected]

#18 lore raw
Quoted 96 lines · Steve Dickson

commit 92e623c74908ffcc76da72e7927ce4e237062c76

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 12:41:03 2009 -0400

The new nfsmount.conf(5) man page and the update to the nfs(5) man page

utils/mount/Makefile.am +1 -0
index a1b56ca..5c1e5ad 100644
@@ -19,6 +19,7 @@ mount_nfs_SOURCES = mount.c error.c network.c fstab.c token.c \
 
 if MOUNT_CONFIG
 mount_nfs_SOURCES += configfile.c
+man5_MANS += nfsmount.conf.man
 endif
 
 mount_nfs_LDADD = ../../support/nfs/libnfs.a \
utils/mount/nfs.man +38 -0
index 13de524..251b16f 100644
@@ -752,6 +752,44 @@ In the presence of multiple client network interfaces,
 special routing policies,
 or atypical network topologies,
 the exact address to use for callbacks may be nontrivial to determine. 
+.SH MOUNT CONFIGURATION FILE
+All of the mount options described in the previous section can also be configured in
+the 
+.I /etc/nfsmount.conf 
+file. This configuration file is made up of three
+different sections: Global, Server and MountPoint. See 
+.BR nfsmount.conf(5)
+for details.
+.PP
+The mount command parses section in a particular order, and will not use
+options that were set in previous sections.  The order of precedence is as follows:
+
+.B Command line option 
+.RS
+options set on the command line will always be used.
+.RE
+.B Mount Point options
+.RS
+options set in the 
+.B [<Mount_Point>]
+section  will
+be used only if they are not specified on the command line.
+.RE
+.B Server options
+.RS
+options set in the 
+.B [<Server_Name>] 
+section will be used
+if they are not specified on the command  line or  the
+mount point section.
+.RE
+.B Global options 
+.RS
+options set in the 
+.B [NFSMount_Global_Options] 
+will be used if they are not specified on the command line, mount point 
+section, or the server section.
+.RE
 .SH EXAMPLES
 To mount an export using NFS version 2,
 use the
utils/mount/nfsmount.conf.man new file +20 -0
new file mode 100644
index 0000000..1a3bb68
@@ -0,0 +1,87 @@
+.\"@(#)nfsmount.conf.5"
+.TH NFSMOUNT.CONF 5 "9 Mar 2008"
+.SH NAME
+nfsmount.conf - Configuration file for NFS mounts
+.SH SYNOPSIS
+Configuration file for NFS mounts that allows options
+to be set globally, per server or per mount point.
+.SH DESCRIPTION
+The configuration file is made up of multiple sections 
+followed by variables associated with that section.
+A section is defined by a string enclosed by 
+.BR [
+and 
+.BR ]
+branches; for example, 
+.BR [nfsserver.foo.com] . 
+Variables are assignment statements that assign values 
+to particular variables using the  
+.BR = 
+operator, as in 

utils/mount/nfsmount.conf.man line 30

Quoted 10 lines
utils/mount/nfsmount.conf.man new file +10 -0
+.BR Proto=Tcp .
+Sections are broken up into three basic categories:
+Global options, Server options and Mount Point options.
+.HP
+.BR [NFSMount_Global_Options]
+- This statically named section
+defines all of the global mount options that can be 
+applied to every NFS mount.
+.HP
+.BR [<Server_Name>]

I notice the git configuration file uses a similar format, but allows section headers that looks like:

[remote "origin"]
url =
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "linux-nfs"]
url = ssh://linux-nfs.org/~bfields/exports/linux.git fetch = +refs/heads/*:refs/remotes/linux-nfs/*

That quoted part in the section name looks like it should allow arbitrary strings without the risk of clashing with section names that we might want to add in the future. That might be a better way to handle server and mount point names?

It looks like git's configuration-parsing code is in config.c (from
git://git.kernel.org/pub/scm/git/git.git).

--b.

Quoted 62 lines
utils/mount/nfsmount.conf.man new file +57 -0
+- This section defines all the mount options that should 
+be used on mounts to a particular NFS server. The 
+.BR <Server_Name>
+needs to be an exact match of the server
+name used in the 
+.B mount
+command. 
+.HP
+.BR [<Mount_Point>]
+- This section defines all the mount options that 
+should be used on a particular mount point.
+The 
+.BR <Mount_Point>
+string need to be an exact match of the
+path used in the 
+.BR mount 
+command.
+.SH EXAMPLES
+.PP
+These are some example lines of how sections and variables
+are defined in the configuration file.
+.PP
+.BR [NFSMount_Global_Options]
+.br
+.BR Proto=Tcp
+.RS
+.HP
+The TCP protocol will be used on every NFS mount.
+.HP
+.RE
+.BR [nfsserver.foo.com]
+.br
+.BR rsize=32k
+.br
+.BR wsize=32k
+.HP
+.RS
+A 33k (32768 bytes) block size will be used as the read and write
+size on all mounts to the 'nfsserver.foo.com' server.
+.HP
+.RE
+.BR [/export/home]
+.br
+.BR Background=True
+.RS
+.HP
+All mounts to the '/export/home' export will be performed in
+the background (i.e. done asynchronously).
+.HP
+.SH FILES
+.TP 10n
+.I /etc/nfsmount.conf
+Default NFS mount configuration file
+.PD
+.SH SEE ALSO
+.BR nfs (5),
+.BR mount (8),

_______________________________________________
NFSv4 mailing list
[email protected]
http://linux-nfs.org/cgi-bin/mailman/listinfo/nfsv4

#19 lore raw
Quoted 90 lines · J. Bruce Fields
Quoted 67 lines

+.SH MOUNT CONFIGURATION FILE

utils/mount/nfs.man +37 -0
+All of the mount options described in the previous section can also be configured in
+the 
+.I /etc/nfsmount.conf 
+file. This configuration file is made up of three
+different sections: Global, Server and MountPoint. See 
+.BR nfsmount.conf(5)
+for details.
+.PP
+The mount command parses section in a particular order, and will not use
+options that were set in previous sections.  The order of precedence is as follows:
+
+.B Command line option 
+.RS
+options set on the command line will always be used.
+.RE
+.B Mount Point options
+.RS
+options set in the 
+.B [<Mount_Point>]
+section  will
+be used only if they are not specified on the command line.
+.RE
+.B Server options
+.RS
+options set in the 
+.B [<Server_Name>] 
+section will be used
+if they are not specified on the command  line or  the
+mount point section.
+.RE
+.B Global options 
+.RS
+options set in the 
+.B [NFSMount_Global_Options] 
+will be used if they are not specified on the command line, mount point 
+section, or the server section.
+.RE
 .SH EXAMPLES
 To mount an export using NFS version 2,
 use the
utils/mount/nfsmount.conf.man new file +20 -0
new file mode 100644
index 0000000..1a3bb68
@@ -0,0 +1,87 @@
+.\"@(#)nfsmount.conf.5"
+.TH NFSMOUNT.CONF 5 "9 Mar 2008"
+.SH NAME
+nfsmount.conf - Configuration file for NFS mounts
+.SH SYNOPSIS
+Configuration file for NFS mounts that allows options
+to be set globally, per server or per mount point.
+.SH DESCRIPTION
+The configuration file is made up of multiple sections 
+followed by variables associated with that section.
+A section is defined by a string enclosed by 
+.BR [
+and 
+.BR ]
+branches; for example, 
+.BR [nfsserver.foo.com] . 
+Variables are assignment statements that assign values 
+to particular variables using the  
+.BR = 
+operator, as in 

utils/mount/nfsmount.conf.man line 30

Quoted 10 lines
utils/mount/nfsmount.conf.man new file +10 -0
+.BR Proto=Tcp .
+Sections are broken up into three basic categories:
+Global options, Server options and Mount Point options.
+.HP
+.BR [NFSMount_Global_Options]
+- This statically named section
+defines all of the global mount options that can be 
+applied to every NFS mount.
+.HP
+.BR [<Server_Name>]

I notice the git configuration file uses a similar format, but allows section headers that looks like:

[remote "origin"]
url =
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "linux-nfs"]
url = ssh://linux-nfs.org/~bfields/exports/linux.git fetch = +refs/heads/*:refs/remotes/linux-nfs/*

Quoted 4 lines

That quoted part in the section name looks like it should allow arbitrary strings without the risk of clashing with section names that we might want to add in the future. That might be a better way to handle server and mount point names?

Something similar to [Server "server_name"] or [MountPoint "directory" ] ??

steved.

A message that is not in the archive (sent off-list or not yet received): [email protected]

#21 lore raw
Quoted 93 lines · Steve Dickson
Quoted 90 lines · J. Bruce Fields
Quoted 67 lines

+.SH MOUNT CONFIGURATION FILE

utils/mount/nfs.man +37 -0
+All of the mount options described in the previous section can also be configured in
+the 
+.I /etc/nfsmount.conf 
+file. This configuration file is made up of three
+different sections: Global, Server and MountPoint. See 
+.BR nfsmount.conf(5)
+for details.
+.PP
+The mount command parses section in a particular order, and will not use
+options that were set in previous sections.  The order of precedence is as follows:
+
+.B Command line option 
+.RS
+options set on the command line will always be used.
+.RE
+.B Mount Point options
+.RS
+options set in the 
+.B [<Mount_Point>]
+section  will
+be used only if they are not specified on the command line.
+.RE
+.B Server options
+.RS
+options set in the 
+.B [<Server_Name>] 
+section will be used
+if they are not specified on the command  line or  the
+mount point section.
+.RE
+.B Global options 
+.RS
+options set in the 
+.B [NFSMount_Global_Options] 
+will be used if they are not specified on the command line, mount point 
+section, or the server section.
+.RE
 .SH EXAMPLES
 To mount an export using NFS version 2,
 use the
utils/mount/nfsmount.conf.man new file +20 -0
new file mode 100644
index 0000000..1a3bb68
@@ -0,0 +1,87 @@
+.\"@(#)nfsmount.conf.5"
+.TH NFSMOUNT.CONF 5 "9 Mar 2008"
+.SH NAME
+nfsmount.conf - Configuration file for NFS mounts
+.SH SYNOPSIS
+Configuration file for NFS mounts that allows options
+to be set globally, per server or per mount point.
+.SH DESCRIPTION
+The configuration file is made up of multiple sections 
+followed by variables associated with that section.
+A section is defined by a string enclosed by 
+.BR [
+and 
+.BR ]
+branches; for example, 
+.BR [nfsserver.foo.com] . 
+Variables are assignment statements that assign values 
+to particular variables using the  
+.BR = 
+operator, as in 

utils/mount/nfsmount.conf.man line 30

Quoted 10 lines
utils/mount/nfsmount.conf.man new file +10 -0
+.BR Proto=Tcp .
+Sections are broken up into three basic categories:
+Global options, Server options and Mount Point options.
+.HP
+.BR [NFSMount_Global_Options]
+- This statically named section
+defines all of the global mount options that can be 
+applied to every NFS mount.
+.HP
+.BR [<Server_Name>]

I notice the git configuration file uses a similar format, but allows section headers that looks like:

[remote "origin"]
url =
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "linux-nfs"]
url = ssh://linux-nfs.org/~bfields/exports/linux.git fetch = +refs/heads/*:refs/remotes/linux-nfs/*

Quoted 6 lines
Quoted 4 lines

That quoted part in the section name looks like it should allow arbitrary strings without the risk of clashing with section names that we might want to add in the future. That might be a better way to handle server and mount point names?

Something similar to [Server "server_name"] or [MountPoint "directory" ] ??

Right.

--b.

#22 lore raw

PATCH 8/8 NFS Mount Configuration File (Vers 2)

In reply to Steve Dickson

commit 7cc5b05f9f57ecaca08658debb4f13a0b639aa85

Author: Steve Dickson <[email protected]>
Date:   Sun Aug 2 15:31:36 2009 -0400

The example nfsmount.conf file

utils/mount/Makefile.am +1 -0
index 5c1e5ad..451ec90 100644
@@ -20,6 +20,7 @@ mount_nfs_SOURCES = mount.c error.c network.c fstab.c token.c \
 if MOUNT_CONFIG
 mount_nfs_SOURCES += configfile.c
 man5_MANS += nfsmount.conf.man
+EXTRA_DIST += nfsmount.conf
 endif
 
 mount_nfs_LDADD = ../../support/nfs/libnfs.a \
utils/mount/nfsmount.conf new file +120 -0

120 lines not on this page · raw message