for (const char *word = opts;;) {
const char *end = word;
- /* Look for an *non-escaped* comma separator. Only commas can be escaped, so "\," is
- * the only valid escape sequence, so we can do a very simple test here. */
+ /* Look for a *non-escaped* comma separator. Only commas and backslashes can be
+ * escaped, so "\," and "\\" are the only valid escape sequences, and we can do a
+ * very simple test here. */
for (;;) {
- size_t n = strcspn(end, ",");
+ end += strcspn(end, ",\\");
- end += n;
- if (n > 0 && end[-1] == '\\')
- end++;
- else
+ if (IN_SET(*end, ',', '\0'))
break;
+ assert(*end == '\\');
+ end ++; /* Skip the backslash */
+ if (*end != '\0')
+ end ++; /* Skip the escaped char, but watch out for a trailing commma */
}
NULSTR_FOREACH(name, names) {
break;
}
} else {
- r = strv_split_full(&stor, opts, ",", EXTRACT_UNESCAPE_SEPARATORS);
+ /* For backwards compatibility, we need to pass-through escape characters.
+ * The only ones we "consume" are the ones used as "\," or "\\". */
+ r = strv_split_full(&stor, opts, ",", EXTRACT_UNESCAPE_SEPARATORS | EXTRACT_UNESCAPE_RELAX);
if (r < 0)
return r;
/* unnecessary comma separators */
do_fstab_filter_options("opt=x,,,,", "opt\0", 1, "opt", "x", "");
do_fstab_filter_options(",,,opt=x,,,,", "opt\0", 1, "opt", "x", "");
+
+ /* escaped characters */
+ do_fstab_filter_options("opt1=\\\\,opt2=\\xff", "opt1\0", 1, "opt1", "\\", "opt2=\\xff");
+ do_fstab_filter_options("opt1=\\\\,opt2=\\xff", "opt2\0", 1, "opt2", "\\xff", "opt1=\\");
}
static void test_fstab_find_pri(void) {