]> git.decadent.org.uk Git - nfs-utils.git/blobdiff - utils/mount/parse_opt.c
text-based mount command: make po_rightmost() work for N options
[nfs-utils.git] / utils / mount / parse_opt.c
index fb4a0e4e800553bb0e949274fb3699a4191bc932..493450859f2235714caaca5391496f8eed85a588 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
 #include <ctype.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -255,13 +259,12 @@ void po_replace(struct mount_options *target, struct mount_options *source)
  * Convert our mount options object back into a string that the
  * rest of the world can use.
  *
- * Returns 1 if the string was successfully created; otherwise
- * zero.  Upon return, @string contains the address of a
- * replacement C string containing a comma-delimited list of
- * mount options and values; or the passed-in string is freed
- * and NULL is returned if some failure occurred.
+ * Upon return, @string contains the address of a replacement
+ * C string containing a comma-delimited list of mount options
+ * and values; or the passed-in string is freed and NULL is
+ * returned if some failure occurred.
  */
-int po_join(struct mount_options *options, char **str)
+po_return_t po_join(struct mount_options *options, char **str)
 {
        size_t len = 0;
        struct mount_option *option;
@@ -310,10 +313,8 @@ int po_join(struct mount_options *options, char **str)
  * @options: pointer to mount options
  * @option: pointer to a C string containing the option to add
  *
- * Returns 1 if the list was successfully concatenated; otherwise
- * zero.
  */
-int po_append(struct mount_options *options, char *str)
+po_return_t po_append(struct mount_options *options, char *str)
 {
        struct mount_option *option = option_create(str);
 
@@ -329,9 +330,8 @@ int po_append(struct mount_options *options, char *str)
  * @options: pointer to mount options
  * @keyword: pointer to a C string containing option keyword for which to search
  *
- * Returns 1 if the option is present in the list; otherwise zero.
  */
-int po_contains(struct mount_options *options, char *keyword)
+po_found_t po_contains(struct mount_options *options, char *keyword)
 {
        struct mount_option *option;
 
@@ -370,37 +370,89 @@ char *po_get(struct mount_options *options, char *keyword)
 }
 
 /**
- * po_rightmost - determine the relative position of two options
+ * po_get_numeric - return numeric value of rightmost instance of keyword option
+ * @options: pointer to mount options
+ * @keyword: pointer to a C string containing option keyword for which to search
+ * @value: OUT: set to the value of the keyword
+ *
+ * This is specifically for parsing keyword options that take only a numeric
+ * value.  If multiple instances of the same option are present in a mount
+ * option list, the rightmost instance is always the effective one.
+ *
+ * Returns:
+ *     * PO_FOUND if the keyword was found and the value is numeric; @value is
+ *       set to the keyword's value
+ *     * PO_NOT_FOUND if the keyword was not found
+ *     * PO_BAD_VALUE if the keyword was found, but the value is not numeric
+ *
+ * These last two are separate in case the caller wants to warn about bad mount
+ * options instead of silently using a default.
+ */
+#ifdef HAVE_STRTOL
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
+{
+       char *option, *endptr;
+       long tmp;
+
+       option = po_get(options, keyword);
+       if (option == NULL)
+               return PO_NOT_FOUND;
+
+       errno = 0;
+       tmp = strtol(option, &endptr, 10);
+       if (errno == 0 && endptr != option) {
+               *value = tmp;
+               return PO_FOUND;
+       }
+       return PO_BAD_VALUE;
+}
+#else  /* HAVE_STRTOL */
+po_found_t po_get_numeric(struct mount_options *options, char *keyword, long *value)
+{
+       char *option;
+
+       option = po_get(options, keyword);
+       if (option == NULL)
+               return PO_NOT_FOUND;
+
+       *value = atoi(option);
+       return PO_FOUND;
+}
+#endif /* HAVE_STRTOL */
+
+/**
+ * po_rightmost - determine the relative position of several options
  * @options: pointer to mount options
- * @key1: pointer to a C string containing an option keyword
- * @key2: pointer to a C string containing another option keyword
+ * @keys: pointer to an array of C strings containing option keywords
+ *
+ * This function can be used to determine which of several similar
+ * options will be the one to take effect.
  *
  * The kernel parses the mount option string from left to right.
  * If an option is specified more than once (for example, "intr"
  * and "nointr", the rightmost option is the last to be parsed,
  * and it therefore takes precedence over previous similar options.
  *
- * This function can be used to determine which of two similar
- * options will be the one to take effect.
+ * This can also distinguish among multiple synonymous options, such
+ * as "proto=," "udp" and "tcp."
  *
- * Returns 1 if key2 is rightmost or key1 is not present.
- * Returns -1 if key1 is rightmost or key2 is not present.
- * Returns 0 if neither key is present.
+ * Returns the index into @keys of the option that is rightmost.
+ * If none of the options are present, returns zero.
  */
-int po_rightmost(struct mount_options *options, char *key1, char *key2)
+unsigned int po_rightmost(struct mount_options *options, const char *keys[])
 {
        struct mount_option *option;
+       unsigned int i;
 
        if (options) {
                for (option = options->tail; option; option = option->prev) {
-                       if (key2 && strcmp(option->keyword, key2) == 0)
-                               return 1;
-                       if (key1 && strcmp(option->keyword, key1) == 0)
-                               return -1;
+                       for (i = 0; keys[i] != NULL; i++)
+                               if (strcmp(option->keyword, keys[i]) == 0)
+                                       return i;
                }
        }
 
-       return PO_NOT_FOUND;
+       return 0;
 }
 
 /**
@@ -408,10 +460,9 @@ int po_rightmost(struct mount_options *options, char *key1, char *key2)
  * @options: pointer to mount options
  * @keyword: pointer to a C string containing an option keyword to remove
  *
- * Returns 1 if the option was found and removed; passed-in list is
- * truncated upon return; otherwise zero.
+ * Side-effect: the passed-in list is truncated on success.
  */
-int po_remove_all(struct mount_options *options, char *keyword)
+po_found_t po_remove_all(struct mount_options *options, char *keyword)
 {
        struct mount_option *option, *next;
        int found = PO_NOT_FOUND;