aboutsummaryrefslogtreecommitdiffstats
path: root/src/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/misc.c')
-rw-r--r--src/misc.c265
1 files changed, 225 insertions, 40 deletions
diff --git a/src/misc.c b/src/misc.c
index fdebff9..97ed214 100644
--- a/src/misc.c
+++ b/src/misc.c
@@ -24,6 +24,34 @@
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include "arena.h"
+
+static char *arena_strdup(struct arena *a, const char *s)
+{
+ size_t n = strlen(s) + 1;
+ char *p = (char *)arena_malloc(a, n);
+ if (!p) {
+ fprintf(stderr, "bindfs: arena allocation failed\n");
+ abort();
+ }
+ memcpy(p, s, n);
+ return p;
+}
+
+/* Konkateniert zwei Strings in der Arena: out = s1 + s2 */
+static char *arena_strcat2(struct arena *a, const char *s1, const char *s2)
+{
+ size_t n1 = strlen(s1);
+ size_t n2 = strlen(s2);
+ char *p = (char *)arena_malloc(a, n1 + n2 + 1);
+ if (!p) {
+ fprintf(stderr, "bindfs: arena allocation failed\n");
+ abort();
+ }
+ memcpy(p, s1, n1);
+ memcpy(p + n1, s2, n2 + 1);
+ return p;
+}
int count_chars(const char *s, char ch)
{
@@ -220,55 +248,212 @@ static void merge_o_args(
}
}
-void filter_o_opts(
- bool (*keep)(const char* opt),
- int orig_argc,
- const char * const *orig_argv,
- int *new_argc,
- char ***new_argv,
- struct arena* arena
-)
+char *strtok_escape_r(char *str, const char *delim, char escape, char **saveptr)
{
- int argc = orig_argc;
- char **argv = dup_argv(argc, orig_argv, arena);
+ char *r, *w, *start;
- merge_o_args(&argc, argv, arena);
+ if (str == NULL) {
+ if (saveptr == NULL || *saveptr == NULL) return NULL;
+ str = *saveptr;
+ }
- for (int i = 0; i < argc; i++) {
- char *arg = argv[i];
- if (strncmp(arg, "-o", 2) == 0) {
- char *filtered = arena_malloc(arena, strlen(arg) + 1);
- char *filtered_end = filtered;
-
- const char *tok = strtok(arg + 2, ",");
- while (tok != NULL) {
- size_t tok_len = strlen(tok);
- if ((*keep)(tok)) {
- if (filtered_end == filtered) {
- *(filtered_end++) = '-';
- *(filtered_end++) = 'o';
- } else {
- *(filtered_end++) = ',';
- }
- memcpy(filtered_end, tok, tok_len + 1);
- filtered_end += tok_len; // We'll overwrite the null terminator if we append more.
- }
- tok = strtok(NULL, ",");
- }
+ r = str;
+ while (*r && strchr(delim, *r) != NULL) {
+ r++;
+ }
+
+ if (*r == '\0') {
+ *saveptr = r;
+ return NULL;
+ }
- if (filtered != filtered_end) {
- argv[i] = filtered;
+ start = w = r;
+
+ for (;;)
+ {
+ if (*r == '\0') {
+ *w = '\0';
+ *saveptr = r;
+ return start;
+ }
+
+ if (*r == escape) {
+ if (r[1] != '\0') {
+ char c = r[1];
+ *w++ = c;
+ r += 2;
+ continue;
} else {
- for (int j = i; j < argc - 1; ++j) {
- argv[j] = argv[j + 1];
- }
- --argc;
+ r++;
+ continue;
+ }
+ }
+
+ if (strchr(delim, *r) != NULL) {
+ *w = '\0';
+ r++;
+ while (*r && strchr(delim, *r) != NULL) r++;
+ *saveptr = r;
+ return start;
+ }
+
+ *w++ = *r++;
+ }
+}
+
+char *strtok_escape(char *str, const char *delim, char escape)
+{
+ static char *save;
+ return strtok_escape_r(str, delim, escape, &save);
+}
+
+char *strtok_escape_preserve_r(char *str, const char *delim, char escape, char **saveptr)
+{
+ char *s = str ? str : *saveptr;
+ char *r = s;
+ char *w = s;
+
+ if (s == NULL) return NULL;
+
+ /* führende Delimiter überspringen (kollabieren) */
+ while (*r && strchr(delim, *r)) r++;
+ if (!*r) { *saveptr = r; return NULL; }
+
+ for (;;) {
+ if (*r == '\0') {
+ *w = '\0';
+ *saveptr = r;
+ return s;
+ }
+ if (*r == escape) {
+ if (r[1] == '\0') {
+ /* dangling escape: '\' wörtlich übernehmen */
+ *w++ = *r++;
+ *w = '\0';
+ *saveptr = r;
+ return s;
+ }
+ /* WICHTIG: Backslash BEHALTEN und nächstes Zeichen wörtlich kopieren */
+ *w++ = escape;
+ *w++ = r[1];
+ r += 2;
+ continue;
+ }
+ if (strchr(delim, *r)) {
+ /* Ende des Tokens; nachfolgende Delimiter kollabieren */
+ *w = '\0';
+ do { r++; } while (*r && strchr(delim, *r));
+ *saveptr = r;
+ return s;
+ }
+ *w++ = *r++;
+ }
+}
+
+char *strtok_escape_preserve(char *str, const char *delim, char escape)
+{
+ static char *saveptr_pres;
+ return strtok_escape_preserve_r(str, delim, escape, &saveptr_pres);
+}
+
+int join_strings(char **res, const char *a, const char *b, const char *sep)
+{
+ size_t la = a ? strlen(a) : 0;
+ size_t lb = b ? strlen(b) : 0;
+ size_t ls = sep ? strlen(sep) : 0;
+ size_t old = *res ? strlen(*res) : 0;
+ size_t extra = (old ? ls : 0) + la + lb;
+
+ char *d = realloc(*res, old + extra + 1);
+ if (!d) return -1;
+
+ char *p = d + old;
+ if (old && sep) { memcpy(p, sep, ls); p += ls; }
+ if (a) { memcpy(p, a, la); p += la; }
+ if (b) { memcpy(p, b, lb); p += lb; }
+ *p = '\0';
+ *res = d;
+ return 0;
+}
+
+int add_option(char ***argv, int *argc, const char *opt)
+{
+ char **newv = realloc(*argv, sizeof(char*) * (*argc + 2));
+ if (!newv) return -1;
+ newv[*argc] = strdup(opt);
+ if (!newv[*argc]) return -1;
+ (*argc)++;
+ newv[*argc] = NULL;
+ *argv = newv;
+ return 0;
+}
+
+int add_options(char ***argv, int *argc, const char *o1, const char *o2)
+{
+ if (add_option(argv, argc, o1) == -1) return -1;
+ if (o2) return add_option(argv, argc, o2);
+ return 0;
+}
+
+void remove_option(char **argv, int *argc, int idx)
+{
+ free(argv[idx]);
+ for (int i = idx; i + 1 < *argc; ++i) argv[i] = argv[i+1];
+ (*argc)--;
+ argv[*argc] = NULL;
+}
+
+void filter_o_opts(bool (*keep_option)(const char *opt),
+ int argc_in,
+ const char * const *argv_in,
+ int *argc_out,
+ char ***argv_out,
+ struct arena *arena)
+{
+ (void)keep_option; /* aktuell nicht genutzt; API bleibt stabil */
+
+ /* Worst-case: gleich viele Ausgabeargumente wie Eingabe.
+ (Bei Zusammenziehen von "-o" "<wert>" werden es sogar weniger.) */
+ char **outv = (char **)arena_malloc(arena,
+ (size_t)(argc_in > 0 ? argc_in : 1) * sizeof(char *));
+ if (!outv) {
+ fprintf(stderr, "bindfs: arena allocation failed\n");
+ abort();
+ }
+
+ int outc = 0;
+
+ for (int i = 0; i < argc_in; ++i) {
+ const char *arg = argv_in[i];
+
+ if (arg[0] == '-' && arg[1] == 'o') {
+ /* Fall A: "-o<wert>" -> unverändert übernehmen */
+ if (arg[2] != '\0') {
+ outv[outc++] = arena_strdup(arena, arg);
+ continue;
}
+
+ /* Fall B: separates "-o" + "<wert>" zusammenziehen */
+ if (i + 1 < argc_in) {
+ const char *val = argv_in[i + 1];
+ char *merged = arena_strcat2(arena, "-o", val);
+ outv[outc++] = merged;
+ ++i; /* den Wert haben wir verbraucht */
+ continue;
+ }
+
+ /* Edge case: nacktes "-o" am Ende – übernimm es trotzdem,
+ libfuse meldet später einen sinnvollen Fehler. */
+ outv[outc++] = arena_strdup(arena, arg);
+ continue;
}
+
+ /* alle anderen Argumente 1:1 durchreichen */
+ outv[outc++] = arena_strdup(arena, arg);
}
- *new_argc = argc;
- *new_argv = argv;
+ *argc_out = outc;
+ *argv_out = outv;
}
void grow_array_impl(void **array, int *capacity, int member_size)