autofs-5.0.9 - mad lookup add merge_options() function From: Ian Kent --- include/parse_subs.h | 1 lib/parse_subs.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+) diff --git a/include/parse_subs.h b/include/parse_subs.h index c0da5ae..e57cf4a 100644 --- a/include/parse_subs.h +++ b/include/parse_subs.h @@ -41,6 +41,7 @@ int strmcmp(const char *, const char *, int); char *dequote(const char *, int, unsigned int); int span_space(const char *, unsigned int); char *sanitize_path(const char *, int, unsigned int, unsigned int); +char *merge_options(const char *, const char *); void free_map_type_info(struct map_type_info *); struct map_type_info *parse_map_type_info(const char *); diff --git a/lib/parse_subs.c b/lib/parse_subs.c index b77d890..99075b1 100644 --- a/lib/parse_subs.c +++ b/lib/parse_subs.c @@ -23,6 +23,9 @@ #include #include "automount.h" +#define MAX_OPTIONS_LEN 256 +#define MAX_OPTION_LEN 40 + #define MAX_NETWORK_LEN 255 #define MAX_IFC_BUF 2048 @@ -523,6 +526,116 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i return s_path; } +static char *hasopt(const char *str, const char *opt) +{ + const size_t optlen = strlen(opt); + char *rest = (char *) str, *p; + + while ((p = strstr(rest, opt)) != NULL) { + if ((p == rest || p[-1] == ',') && + (p[optlen] == '\0' || p[optlen] == '=' || + p[optlen] == ',')) + return p; + + rest = strchr (p, ','); + if (rest == NULL) + break; + ++rest; + } + + return NULL; +} + +char *merge_options(const char *opt1, const char *opt2) +{ + char str[MAX_OPTIONS_LEN]; + char result[MAX_OPTIONS_LEN]; + char neg[MAX_OPTION_LEN]; + char *tok, *ptr = NULL; + size_t len; + + if (!opt1 && !opt2) + return NULL; + + if (!opt2) + return strdup(opt1); + + if (!opt1) + return strdup(opt2); + + if (!strcmp(opt1, opt2)) + return strdup(opt1); + + memset(result, 0, sizeof(result)); + strcpy(str, opt1); + + tok = strtok_r(str, ",", &ptr); + while (tok) { + const char *this = (const char *) tok; + char *eq = strchr(this, '='); + if (eq) { + *eq = '\0'; + if (!hasopt(opt2, this)) { + *eq = '='; + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); + goto next; + } + } + + if (!strcmp(this, "rw") && hasopt(opt2, "ro")) + goto next; + if (!strcmp(this, "ro") && hasopt(opt2, "rw")) + goto next; + if (!strcmp(this, "bg") && hasopt(opt2, "fg")) + goto next; + if (!strcmp(this, "fg") && hasopt(opt2, "bg")) + goto next; + if (!strcmp(this, "bg") && hasopt(opt2, "fg")) + goto next; + if (!strcmp(this, "soft") && hasopt(opt2, "hard")) + goto next; + if (!strcmp(this, "hard") && hasopt(opt2, "soft")) + goto next; + + if (!strncmp(this, "no", 2)) { + strcpy(neg, this + 2); + if (hasopt(opt2, neg)) + goto next; + } else { + strcpy(neg, "no"); + strcat(neg, this); + if (hasopt(opt2, neg)) + goto next; + } + + if (hasopt(opt2, tok)) + goto next; + + if (!*result) + strcpy(result, this); + else + strcat(result, this); + strcat(result, ","); +next: + tok = strtok_r(NULL, ",", &ptr); + } + + if (!*result) + strcpy(result, opt2); + else + strcat(result, opt2); + + len = strlen(result); + if (len && result[len - 1] == ',') + result[len - 1] = '\0'; + + return strdup(result); +} + void free_map_type_info(struct map_type_info *info) { if (info->type)