]> err.no Git - util-linux/commitdiff
lib: add mangle.c for mtab (fstab or swaps) encoding
authorKarel Zak <kzak@redhat.com>
Wed, 10 Mar 2010 22:54:11 +0000 (23:54 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 10 Mar 2010 22:54:11 +0000 (23:54 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
include/Makefile.am
include/mangle.h [new file with mode: 0644]
lib/Makefile.am
lib/mangle.c [new file with mode: 0644]

index 525e3d2ee48941c4334abcc57aef81f883ae19df..1da31fe18f26cac43209499a99786d9b14396eaf 100644 (file)
@@ -20,4 +20,5 @@ dist_noinst_HEADERS = \
        wholedisk.h \
        widechar.h \
        crc32.h \
+       mangle.h \
        xstrncpy.h
diff --git a/include/mangle.h b/include/mangle.h
new file mode 100644 (file)
index 0000000..8ce3875
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef UTIL_LINUX_MANGLE_H
+#define UTIL_LINUX_MANGLE_H
+
+/*
+ * Functions for \oct encoding used in mtab/fstab/swaps/etc.
+ */
+
+extern char *mangle(const char *s);
+
+extern void unmangle_to_buffer(char *s, char *buf, size_t len);
+extern char *unmangle(char *s);
+
+#endif /* UTIL_LINUX_MANGLE_H */
+
index 5600d18c2bc932bc9d07179904694d89b9bd3351..0fddfb5edf26ff21251d8874f8ad4a459c3deaf7 100644 (file)
@@ -2,11 +2,12 @@ include $(top_srcdir)/config/include-Makefile.am
 
 AM_CPPFLAGS += -DTEST_PROGRAM
 
-noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk
+noinst_PROGRAMS = test_blkdev test_ismounted test_wholedisk test_mangle
 
 test_blkdev_SOURCES = blkdev.c
 test_ismounted_SOURCES = ismounted.c
 test_wholedisk_SOURCES = wholedisk.c
+test_mangle_SOURCES = mangle.c
 
 if LINUX
 test_blkdev_SOURCES += linux_version.c
diff --git a/lib/mangle.c b/lib/mangle.c
new file mode 100644 (file)
index 0000000..766d479
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Functions for \oct encoding used in mtab/fstab/swaps/etc.
+ *
+ * Based on code from mount(8).
+ *
+ * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mangle.h"
+
+#define isoctal(a) (((a) & ~7) == '0')
+
+static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
+
+char *mangle(const char *s)
+{
+       char *ss, *sp;
+       int n;
+
+       n = strlen(s);
+       ss = sp = malloc(4*n+1);
+       if (!sp)
+               return NULL;
+       while(1) {
+               for (n = 0; n < sizeof(need_escaping); n++) {
+                       if (*s == need_escaping[n]) {
+                               *sp++ = '\\';
+                               *sp++ = '0' + ((*s & 0300) >> 6);
+                               *sp++ = '0' + ((*s & 070) >> 3);
+                               *sp++ = '0' + (*s & 07);
+                               goto next;
+                       }
+               }
+               *sp++ = *s;
+               if (*s == 0)
+                       break;
+       next:
+               s++;
+       }
+       return ss;
+}
+
+void unmangle_to_buffer(char *s, char *buf, size_t len)
+{
+       size_t sz = 0;
+
+       while(*s && sz < len - 1) {
+               if (*s == '\\' && sz + 4 < len - 1 && isoctal(s[1]) &&
+                   isoctal(s[2]) && isoctal(s[3])) {
+
+                       *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
+                       s += 4;
+                       sz += 4;
+               } else {
+                       *buf++ = *s++;
+                       sz++;
+               }
+       }
+       *buf = '\0';
+}
+
+static inline char *skip_nonspaces(char *s)
+{
+       while (*s && !(*s == ' ' || *s == '\t'))
+               s++;
+       return s;
+}
+
+/*
+ * Returns mallocated buffer or NULL in case of error.
+ */
+char *unmangle(char *s)
+{
+       char *buf, *end;
+       size_t sz;
+
+       end = skip_nonspaces(s);
+       sz = end - s + 1;
+
+       buf = malloc(sz);
+       if (!buf)
+               return NULL;
+
+       unmangle_to_buffer(s, buf, sz);
+       return buf;
+}
+
+#ifdef TEST_PROGRAM
+#include <err.h>
+#include <errno.h>
+int main(int argc, char *argv[])
+{
+       if (argc < 3) {
+               fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n",
+                                               program_invocation_short_name);
+               return EXIT_FAILURE;
+       }
+
+       if (!strcmp(argv[1], "--mangle"))
+               printf("mangled: '%s'\n", mangle(argv[2]));
+
+       else if (!strcmp(argv[1], "--unmangle")) {
+               char *x = unmangle(argv[2]);
+               if (x)
+                       printf("unmangled: '%s'\n", x);
+               else
+                       err(EXIT_FAILURE, "unmangle failed");
+       }
+
+       return EXIT_SUCCESS;
+}
+#endif /* TEST_PROGRAM */