]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/mangle.c
build-sys: provide alternatives for err, errx, warn and warnx
[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"
eb76ca98 14#include "c.h"
21169393
KZ
15
16#define isoctal(a) (((a) & ~7) == '0')
17
18static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
19
20char *mangle(const char *s)
21{
22 char *ss, *sp;
23 int n;
24
7a539b29
KZ
25 if (!s)
26 return NULL;
27
21169393
KZ
28 n = strlen(s);
29 ss = sp = malloc(4*n+1);
30 if (!sp)
31 return NULL;
32 while(1) {
33 for (n = 0; n < sizeof(need_escaping); n++) {
34 if (*s == need_escaping[n]) {
35 *sp++ = '\\';
36 *sp++ = '0' + ((*s & 0300) >> 6);
37 *sp++ = '0' + ((*s & 070) >> 3);
38 *sp++ = '0' + (*s & 07);
39 goto next;
40 }
41 }
42 *sp++ = *s;
43 if (*s == 0)
44 break;
45 next:
46 s++;
47 }
48 return ss;
49}
50
3c5e4ef8 51void unmangle_to_buffer(const char *s, char *buf, size_t len)
21169393
KZ
52{
53 size_t sz = 0;
54
7a539b29
KZ
55 if (!s)
56 return;
57
21169393
KZ
58 while(*s && sz < len - 1) {
59 if (*s == '\\' && sz + 4 < len - 1 && isoctal(s[1]) &&
60 isoctal(s[2]) && isoctal(s[3])) {
61
62 *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
63 s += 4;
64 sz += 4;
65 } else {
66 *buf++ = *s++;
67 sz++;
68 }
69 }
70 *buf = '\0';
71}
72
5ac6a133 73static inline char *skip_nonspaces(const char *s)
21169393
KZ
74{
75 while (*s && !(*s == ' ' || *s == '\t'))
76 s++;
5ac6a133 77 return (char *) s;
21169393
KZ
78}
79
80/*
81 * Returns mallocated buffer or NULL in case of error.
82 */
5ac6a133 83char *unmangle(const char *s, char **end)
21169393 84{
3c5e4ef8 85 char *buf;
5ac6a133 86 char *e;
21169393
KZ
87 size_t sz;
88
7a539b29
KZ
89 if (!s)
90 return NULL;
91
dd369652
KZ
92 e = skip_nonspaces(s);
93 sz = e - s + 1;
94
95 if (end)
96 *end = e;
21169393
KZ
97
98 buf = malloc(sz);
99 if (!buf)
100 return NULL;
101
102 unmangle_to_buffer(s, buf, sz);
103 return buf;
104}
105
106#ifdef TEST_PROGRAM
21169393
KZ
107#include <errno.h>
108int main(int argc, char *argv[])
109{
110 if (argc < 3) {
111 fprintf(stderr, "usage: %s --mangle | --unmangle <string>\n",
112 program_invocation_short_name);
113 return EXIT_FAILURE;
114 }
115
116 if (!strcmp(argv[1], "--mangle"))
117 printf("mangled: '%s'\n", mangle(argv[2]));
118
119 else if (!strcmp(argv[1], "--unmangle")) {
dd369652 120 char *x = unmangle(argv[2], NULL);
8f3f6383
KZ
121
122 if (x) {
21169393 123 printf("unmangled: '%s'\n", x);
8f3f6383
KZ
124 free(x);
125 }
126
127 x = strdup(argv[2]);
128 unmangle_to_buffer(x, x, strlen(x) + 1);
129
130 if (x) {
131 printf("self-unmangled: '%s'\n", x);
132 free(x);
133 }
21169393
KZ
134 }
135
136 return EXIT_SUCCESS;
137}
138#endif /* TEST_PROGRAM */