2 * configfile.c -- mount configuration file manipulation
3 * Copyright (C) 2008 Red Hat, Inc <nfs@redhat.com>
5 * - Routines use to create mount options from the mount
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
22 #include <sys/types.h>
32 #define KBYTES(x) ((x) * (1024))
33 #define MEGABYTES(x) ((x) * (1048576))
34 #define GIGABYTES(x) ((x) * (1073741824))
36 #ifndef NFSMOUNT_GLOBAL_OPTS
37 #define NFSMOUNT_GLOBAL_OPTS "NFSMount_Global_Options"
40 #ifndef NFSMOUNT_MOUNTPOINT
41 #define NFSMOUNT_MOUNTPOINT "MountPoint"
44 #ifndef NFSMOUNT_SERVER
45 #define NFSMOUNT_SERVER "Server"
48 #ifndef MOUNTOPTS_CONFFILE
49 #define MOUNTOPTS_CONFFILE "/etc/nfsmount.conf"
51 char *conf_path = MOUNTOPTS_CONFFILE;
64 {"background", "bg", MNT_NOARG},
65 {"foreground", "fg", MNT_NOARG},
66 {"sloppy", "sloppy", MNT_NOARG},
68 int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0]));
71 * See if the option is an alias, if so return the
72 * real mount option along with the argument type.
75 char *mountopts_alias(char *opt, int *argtype)
80 for (i=0; i < mnt_alias_sz; i++) {
81 if (strcasecmp(opt, mnt_alias_tab[i].alias) != 0)
83 *argtype = mnt_alias_tab[i].argtype;
84 return mnt_alias_tab[i].opt;
86 /* Make option names case-insensitive */
92 * Convert numeric strings that end with 'k', 'm' or 'g'
93 * into numeric strings with the real value.
94 * Meaning '8k' becomes '8094'.
96 char *mountopts_convert(char *value)
98 unsigned long long factor, num;
102 ch = &value[strlen(value)-1];
103 switch (tolower(*ch)) {
108 factor = MEGABYTES(1);
111 factor = GIGABYTES(1);
117 if (strncmp(value, "0x", 2) == 0) {
118 num = strtol(value, (char **)NULL, 16);
119 } else if (strncmp(value, "0", 1) == 0) {
120 num = strtol(value, (char **)NULL, 8);
122 num = strtol(value, (char **)NULL, 10);
125 snprintf(buf, 64, "%lld", num);
131 SLIST_ENTRY(entry) entries;
134 static SLIST_HEAD(shead, entry) head = SLIST_HEAD_INITIALIZER(head);
135 static int list_size;
138 * Add option to the link list
145 entry = calloc(1, sizeof(struct entry));
147 xlog_warn("Unable calloc memory for mount configs");
150 entry->opt = strdup(opt);
151 if (entry->opt == NULL) {
152 xlog_warn("Unable calloc memory for mount opts");
156 SLIST_INSERT_HEAD(&head, entry, entries);
159 * See if the given entry exists if the link list,
160 * if so return that entry
163 char *lookup_entry(char *opt)
167 SLIST_FOREACH(entry, &head, entries) {
168 if (strcasecmp(entry->opt, opt) == 0)
174 * Free all entries on the link list
181 while (!SLIST_EMPTY(&head)) {
182 entry = SLIST_FIRST(&head);
183 SLIST_REMOVE_HEAD(&head, entries);
189 * Parse the given section of the configuration
190 * file to if there are any mount options set.
191 * If so, added them to link list.
194 conf_parse_mntopts(char *section, char *arg, char *opts)
196 struct conf_list *list;
197 struct conf_list_node *node;
198 char buf[BUFSIZ], *value, *field;
202 list = conf_get_tag_list(section);
203 TAILQ_FOREACH(node, &list->fields, link) {
205 * Do not overwrite options if already exists
207 snprintf(buf, BUFSIZ, "%s=", node->field);
208 if (opts && strcasestr(opts, buf) != NULL)
210 if (lookup_entry(node->field) != NULL)
213 value = conf_get_section(section, arg, node->field);
216 field = mountopts_alias(node->field, &argtype);
217 if (strcasecmp(value, "false") == 0) {
218 if (argtype != MNT_NOARG)
219 snprintf(buf, BUFSIZ, "no%s", field);
220 } else if (strcasecmp(value, "true") == 0) {
221 snprintf(buf, BUFSIZ, "%s", field);
223 nvalue = strdup(value);
224 ptr = mountopts_convert(nvalue);
225 snprintf(buf, BUFSIZ, "%s=%s", field, ptr);
231 * Keep a running tally of the list size adding
232 * one for the ',' that will be appened later
234 list_size += strlen(buf) + 1;
237 conf_free_list(list);
241 * Concatenate options from the configuration file with the
242 * given options by building a link list of options from the
243 * different sections in the conf file. Options that exists
244 * in the either the given options or link list are not
245 * overwritten so it matter which when each section is
248 char *conf_get_mntopts(char *spec, char *mount_point,
252 char *ptr, *server, *config_opts;
258 * First see if there are any mount options relative
259 * to the mount point.
261 conf_parse_mntopts(NFSMOUNT_MOUNTPOINT, mount_point, mount_opts);
264 * Next, see if there are any mount options relative
267 server = strdup(spec);
268 if (server == NULL) {
269 xlog_warn("conf_get_mountops: Unable calloc memory for server");
273 if ((ptr = strchr(server, ':')) != NULL)
275 conf_parse_mntopts(NFSMOUNT_SERVER, server, mount_opts);
279 * Finally process all the global mount options.
281 conf_parse_mntopts(NFSMOUNT_GLOBAL_OPTS, NULL, mount_opts);
284 * If no mount options were found in the configuration file
285 * just return what was passed in .
287 if (SLIST_EMPTY(&head))
291 * Found options in the configuration file. So
292 * concatenate the configuration options with the
293 * options that were passed in
296 optlen = strlen(mount_opts);
298 /* list_size + optlen + ',' + '\0' */
299 config_opts = calloc(1, (list_size+optlen+2));
300 if (server == NULL) {
301 xlog_warn("conf_get_mountops: Unable calloc memory for config_opts");
306 strcpy(config_opts, mount_opts);
307 strcat(config_opts, ",");
309 SLIST_FOREACH(entry, &head, entries) {
310 strcat(config_opts, entry->opt);
311 strcat(config_opts, ",");
313 *(strrchr(config_opts, ',')) = '\0';