aboutsummaryrefslogtreecommitdiffstats
path: root/lib/fuse_opt.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fuse_opt.c')
-rw-r--r--lib/fuse_opt.c100
1 files changed, 68 insertions, 32 deletions
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index 3bacf74..a2999f3 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include <stdbool.h>
struct fuse_opt_context {
void *data;
@@ -292,46 +293,81 @@ static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
return call_proc(ctx, arg, FUSE_OPT_KEY_OPT, iso);
}
-static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
+/* ---- Neue robuste -o-Aufspaltung mit Escape/Quotes -------------------- */
+
+static void unescape_commas(char *s)
{
- char *s = opts;
- char *d = s;
- int end = 0;
-
- while (!end) {
- if (*s == '\0')
- end = 1;
- if (*s == ',' || end) {
- int res;
+ char *w = s, *r = s;
+ while (*r) {
+ if (r[0] == '\\' && r[1] == ',') { *w++ = ','; r += 2; continue; }
+ if (r[0] == '\\' && r[1] == '\\'){ *w++ = '\\'; r += 2; continue; }
+ *w++ = *r++;
+ }
+ *w = '\0';
+}
- *d = '\0';
- res = process_gopt(ctx, opts, 1);
- if (res == -1)
- return -1;
- d = opts;
- } else {
- if (s[0] == '\\' && s[1] != '\0') {
- s++;
- if (s[0] >= '0' && s[0] <= '3' &&
- s[1] >= '0' && s[1] <= '7' &&
- s[2] >= '0' && s[2] <= '7') {
- *d++ = (s[0] - '0') * 0100 +
- (s[1] - '0') * 0010 +
- (s[2] - '0');
- s += 2;
- } else {
- *d++ = *s;
- }
- } else {
- *d++ = *s;
+static void foreach_o_subopt(const char *oarg,
+ void (*cb)(const char *opt, void *user),
+ void *user)
+{
+ const char *p = oarg, *start = oarg;
+ bool esc = false, in_sq = false, in_dq = false;
+
+ for (; *p; ++p) {
+ if (esc) { esc = false; continue; }
+ if (*p == '\\') { esc = true; continue; }
+ if (*p == '\'' && !in_dq) { in_sq = !in_sq; continue; }
+ if (*p == '\"' && !in_sq) { in_dq = !in_dq; continue; }
+
+ /* Nur ein nicht gequotetes und nicht ge-escaptes Komma trennt */
+ if (*p == ',' && !in_sq && !in_dq) {
+ size_t len = (size_t)(p - start);
+ if (len) {
+ char *tmp = (char*)malloc(len + 1);
+ memcpy(tmp, start, len);
+ tmp[len] = '\0';
+ unescape_commas(tmp);
+ cb(tmp, user);
+ free(tmp);
}
+ start = p + 1;
}
- s++;
}
- return 0;
+ if (p > start) {
+ size_t len = (size_t)(p - start);
+ char *tmp = (char*)malloc(len + 1);
+ memcpy(tmp, start, len);
+ tmp[len] = '\0';
+ unescape_commas(tmp);
+ cb(tmp, user);
+ free(tmp);
+ }
}
+struct oproc_ctx {
+ struct fuse_opt_context *ctx;
+ int rc;
+};
+
+static void process_o_subopt_cb(const char *opt, void *user)
+{
+ struct oproc_ctx *st = (struct oproc_ctx*)user;
+ if (st->rc != 0) return; /* vorheriger Fehler? */
+ if (opt[0] == '\0') return; /* leere Teil-Option ignorieren */
+ st->rc = process_gopt(st->ctx, opt, 1);
+}
+
+static int process_real_option_group(struct fuse_opt_context *ctx, char *opts)
+{
+ struct oproc_ctx st = { ctx, 0 };
+ /* Robustes Splitting: beachtet \, sowie '...' und "..." */
+ foreach_o_subopt(opts, process_o_subopt_cb, &st);
+ return st.rc;
+}
+
+/* ---------------------------------------------------------------------- */
+
static int process_option_group(struct fuse_opt_context *ctx, const char *opts)
{
int res;