]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/mangle.c
libmount: correctly use "none" values
[thirdparty/util-linux.git] / lib / mangle.c
CommitLineData
21169393
KZ
1/*
2 * Functions for \oct encoding used in mtab/fstab/swaps/etc.
3 *
4 * Based on code from mount(8).
5 *
6 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
7 */
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <ctype.h>
12
13#include "mangle.h"
14
15#define isoctal(a) (((a) & ~7) == '0')
16
17static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
18
19char *mangle(const char *s)
20{
21 char *ss, *sp;
22 int n;
23
24 n = strlen(s);
25 ss = sp = malloc(4*n+1);
26 if (!sp)
27 return NULL;
28 while(1) {
29 for (n = 0; n < sizeof(need_escaping); n++) {
30 if (*s == need_escaping[n]) {
31 *sp++ = '\\';
32 *sp++ = '0' + ((*s & 0300) >> 6);
33 *sp++ = '0' + ((*s & 070) >> 3);
34 *sp++ = '0' + (*s & 07);
35 goto next;
36 }
37 }
38 *sp++ = *s;
39 if (*s == 0)
40 break;
41 next:
42 s++;
43 }
44 return ss;
45}
46
3c5e4ef8 47void unmangle_to_buffer(const char *s, char *buf, size_t len)
21169393
KZ
48{
49 size_t sz = 0;
50
51 while(*s && sz < len - 1) {
52 if (*s == '\\' && sz + 4 < len - 1 && isoctal(s[1]) &&
53 isoctal(s[2]) && isoctal(s[3])) {
54
55 *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
56 s += 4;
57 sz += 4;
58 } else {
59 *buf++ = *s++;
60 sz++;
61 }
62 }
63 *buf = '\0';
64}
65
3c5e4ef8 66static inline const char *skip_nonspaces(const char *s)
21169393
KZ
67{
68 while (*s && !(*s == ' ' || *s == '\t'))
69 s++;
70 return s;
71}
72
73/*
74 * Returns mallocated buffer or NULL in case of error.
75 */
3c5e4ef8 76char *unmangle(const char *s)
21169393 77{
3c5e4ef8
KZ
78 char *buf;
79 const char *end;
21169393
KZ
80 size_t sz;
81
82 end = skip_nonspaces(s);
83 sz = end - s + 1;
84
85 buf = malloc(sz);
86 if (!buf)
87 return NULL;
88
89 unmangle_to_buffer(s, buf, sz);
90 return buf;
91}
92
93#ifdef TEST_PROGRAM
94#include <err.h>
95#include <errno.h>
96int main(int argc, char *argv[])
97{
98 if (argc < 3) {
99 fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n",
100 program_invocation_short_name);
101 return EXIT_FAILURE;
102 }
103
104 if (!strcmp(argv[1], "--mangle"))
105 printf("mangled: '%s'\n", mangle(argv[2]));
106
107 else if (!strcmp(argv[1], "--unmangle")) {
108 char *x = unmangle(argv[2]);
109 if (x)
110 printf("unmangled: '%s'\n", x);
111 else
112 err(EXIT_FAILURE, "unmangle failed");
113 }
114
115 return EXIT_SUCCESS;
116}
117#endif /* TEST_PROGRAM */