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 "MountPoint"
41 #define NFSMOUNT_MOUNTPOINT "MountPoint"
44 #ifndef NFSMOUNT_SERVER "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;
89 * Convert numeric strings that end with 'k', 'm' or 'g'
90 * into numeric strings with the real value.
91 * Meaning '8k' becomes '8094'.
93 char *mountopts_convert(char *value)
95 unsigned long long factor, num;
99 ch = &value[strlen(value)-1];
100 switch (tolower(*ch)) {
105 factor = MEGABYTES(1);
108 factor = GIGABYTES(1);
114 if (strncmp(value, "0x", 2) == 0) {
115 num = strtol(value, (char **)NULL, 16);
116 } else if (strncmp(value, "0", 1) == 0) {
117 num = strtol(value, (char **)NULL, 8);
119 num = strtol(value, (char **)NULL, 10);
122 snprintf(buf, 64, "%lld", num);
128 SLIST_ENTRY(entry) entries;
131 static SLIST_HEAD(shead, entry) head = SLIST_HEAD_INITIALIZER(head);
132 static int list_size;
135 * Add option to the link list
142 entry = calloc(1, sizeof(struct entry));
144 xlog_warn("Unable calloc memory for mount configs");
147 entry->opt = strdup(opt);
148 if (entry->opt == NULL) {
149 xlog_warn("Unable calloc memory for mount opts");
153 SLIST_INSERT_HEAD(&head, entry, entries);
156 * See if the given entry exists if the link list,
157 * if so return that entry
160 char *lookup_entry(char *opt)
164 SLIST_FOREACH(entry, &head, entries) {
165 if (strcasecmp(entry->opt, opt) == 0)
171 * Free all entries on the link list
178 while (!SLIST_EMPTY(&head)) {
179 entry = SLIST_FIRST(&head);
180 SLIST_REMOVE_HEAD(&head, entries);
186 * Parse the given section of the configuration
187 * file to if there are any mount options set.
188 * If so, added them to link list.
191 conf_parse_mntopts(char *section, char *arg, char *opts)
193 struct conf_list *list;
194 struct conf_list_node *node;
195 char buf[BUFSIZ], *value, *field;
199 list = conf_get_tag_list(section);
200 TAILQ_FOREACH(node, &list->fields, link) {
202 * Do not overwrite options if already exists
204 snprintf(buf, BUFSIZ, "%s=", node->field);
205 if (opts && strstr(opts, buf) != NULL)
207 if (lookup_entry(node->field) != NULL)
210 value = conf_get_section(section, arg, node->field);
213 field = mountopts_alias(node->field, &argtype);
214 if (strcasecmp(value, "false") == 0) {
215 if (argtype != MNT_NOARG)
216 snprintf(buf, BUFSIZ, "no%s", field);
217 } else if (strcasecmp(value, "true") == 0) {
218 snprintf(buf, BUFSIZ, "%s", field);
220 nvalue = strdup(value);
221 ptr = mountopts_convert(nvalue);
222 snprintf(buf, BUFSIZ, "%s=%s", field, ptr);
228 * Keep a running tally of the list size adding
229 * one for the ',' that will be appened later
231 list_size += strlen(buf) + 1;
234 conf_free_list(list);
238 * Concatenate options from the configuration file with the
239 * given options by building a link list of options from the
240 * different sections in the conf file. Options that exists
241 * in the either the given options or link list are not
242 * overwritten so it matter which when each section is
245 char *conf_get_mntopts(char *spec, char *mount_point,
249 char *ptr, *server, *config_opts;
255 * First see if there are any mount options relative
256 * to the mount point.
258 conf_parse_mntopts(NFSMOUNT_MOUNTPOINT, mount_point, mount_opts);
261 * Next, see if there are any mount options relative
264 server = strdup(spec);
265 if (server == NULL) {
266 xlog_warn("conf_get_mountops: Unable calloc memory for server");
270 if ((ptr = strchr(server, ':')) != NULL)
272 conf_parse_mntopts(NFSMOUNT_SERVER, server, mount_opts);
276 * Finally process all the global mount options.
278 conf_parse_mntopts(NFSMOUNT_GLOBAL_OPTS, NULL, mount_opts);
281 * If no mount options were found in the configuration file
282 * just return what was passed in .
284 if (SLIST_EMPTY(&head))
288 * Found options in the configuration file. So
289 * concatenate the configuration options with the
290 * options that were passed in
293 optlen = strlen(mount_opts);
295 /* list_size + optlen + ',' + '\0' */
296 config_opts = calloc(1, (list_size+optlen+2));
297 if (server == NULL) {
298 xlog_warn("conf_get_mountops: Unable calloc memory for config_opts");
303 strcpy(config_opts, mount_opts);
304 strcat(config_opts, ",");
306 SLIST_FOREACH(entry, &head, entries) {
307 strcat(config_opts, entry->opt);
308 strcat(config_opts, ",");
310 *(strrchr(config_opts, ',')) = '\0';