]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/mangle.c
include: add some missing licence stuff to header files
[thirdparty/util-linux.git] / lib / mangle.c
CommitLineData
21169393
KZ
1/*
2 * Functions for \oct encoding used in mtab/fstab/swaps/etc.
3 *
40f8c5e4
KZ
4 * No copyright is claimed. This code is in the public domain; do with
5 * it what you wish.
21169393
KZ
6 *
7 * Copyright (C) 2010 Karel Zak <kzak@redhat.com>
8 */
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include <ctype.h>
13
14#include "mangle.h"
eb76ca98 15#include "c.h"
21169393 16
95387b66
KZ
17#define isoctal(a) (((a) & ~7) == '0')
18
19#define from_hex(c) (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10)
20
21#define is_unwanted_char(x) (strchr(" \t\n\\", (unsigned int) x) != NULL)
21169393 22
21169393
KZ
23
24char *mangle(const char *s)
25{
26 char *ss, *sp;
21169393 27
7a539b29
KZ
28 if (!s)
29 return NULL;
30
95387b66 31 ss = sp = malloc(4 * strlen(s) + 1);
21169393
KZ
32 if (!sp)
33 return NULL;
34 while(1) {
ea178007
DR
35 if (!*s) {
36 *sp = '\0';
37 break;
38 }
95387b66
KZ
39 if (is_unwanted_char(*s)) {
40 *sp++ = '\\';
41 *sp++ = '0' + ((*s & 0300) >> 6);
42 *sp++ = '0' + ((*s & 070) >> 3);
43 *sp++ = '0' + (*s & 07);
ea178007 44 } else
95387b66 45 *sp++ = *s;
21169393
KZ
46 s++;
47 }
48 return ss;
49}
50
95387b66 51
3c5e4ef8 52void unmangle_to_buffer(const char *s, char *buf, size_t len)
21169393
KZ
53{
54 size_t sz = 0;
55
7a539b29
KZ
56 if (!s)
57 return;
58
21169393 59 while(*s && sz < len - 1) {
096db1ea 60 if (*s == '\\' && sz + 3 < len - 1 && isoctal(s[1]) &&
21169393
KZ
61 isoctal(s[2]) && isoctal(s[3])) {
62
63 *buf++ = 64*(s[1] & 7) + 8*(s[2] & 7) + (s[3] & 7);
64 s += 4;
65 sz += 4;
66 } else {
67 *buf++ = *s++;
68 sz++;
69 }
70 }
71 *buf = '\0';
72}
73
61b92339 74size_t unhexmangle_to_buffer(const char *s, char *buf, size_t len)
95387b66
KZ
75{
76 size_t sz = 0;
61b92339 77 const char *buf0 = buf;
95387b66
KZ
78
79 if (!s)
61b92339 80 return 0;
95387b66
KZ
81
82 while(*s && sz < len - 1) {
096db1ea 83 if (*s == '\\' && sz + 3 < len - 1 && s[1] == 'x' &&
95387b66
KZ
84 isxdigit(s[2]) && isxdigit(s[3])) {
85
86 *buf++ = from_hex(s[2]) << 4 | from_hex(s[3]);
87 s += 4;
88 sz += 4;
89 } else {
90 *buf++ = *s++;
91 sz++;
92 }
93 }
94 *buf = '\0';
61b92339 95 return buf - buf0 + 1;
95387b66
KZ
96}
97
78c66fc6 98static inline const char *skip_nonspaces(const char *s)
21169393 99{
36fcefa6 100 while (s && *s && !(*s == ' ' || *s == '\t'))
21169393 101 s++;
78c66fc6 102 return s;
21169393
KZ
103}
104
105/*
106 * Returns mallocated buffer or NULL in case of error.
107 */
78c66fc6 108char *unmangle(const char *s, const char **end)
21169393 109{
3c5e4ef8 110 char *buf;
78c66fc6 111 const char *e;
21169393
KZ
112 size_t sz;
113
7a539b29
KZ
114 if (!s)
115 return NULL;
116
dd369652
KZ
117 e = skip_nonspaces(s);
118 sz = e - s + 1;
119
120 if (end)
121 *end = e;
6c7f688b
KZ
122 if (e == s)
123 return NULL; /* empty string */
21169393
KZ
124
125 buf = malloc(sz);
126 if (!buf)
127 return NULL;
128
129 unmangle_to_buffer(s, buf, sz);
130 return buf;
131}
132
e8f7acb0 133#ifdef TEST_PROGRAM_MANGLE
21169393
KZ
134#include <errno.h>
135int main(int argc, char *argv[])
136{
a0b25068 137 char *p = NULL;
21169393 138 if (argc < 3) {
95387b66 139 fprintf(stderr, "usage: %s --mangle|unmangle <string>\n",
21169393
KZ
140 program_invocation_short_name);
141 return EXIT_FAILURE;
142 }
143
a0b25068
CW
144 if (!strcmp(argv[1], "--mangle")) {
145 p = mangle(argv[2]);
146 printf("mangled: '%s'\n", p);
147 free(p);
148 }
21169393
KZ
149
150 else if (!strcmp(argv[1], "--unmangle")) {
dd369652 151 char *x = unmangle(argv[2], NULL);
8f3f6383
KZ
152
153 if (x) {
21169393 154 printf("unmangled: '%s'\n", x);
8f3f6383
KZ
155 free(x);
156 }
157
158 x = strdup(argv[2]);
8f3f6383 159 if (x) {
4f807791
SK
160 unmangle_to_buffer(x, x, strlen(x) + 1);
161
8f3f6383
KZ
162 printf("self-unmangled: '%s'\n", x);
163 free(x);
164 }
21169393
KZ
165 }
166
167 return EXIT_SUCCESS;
168}
e8f7acb0 169#endif /* TEST_PROGRAM_MANGLE */