aboutsummaryrefslogtreecommitdiffstats
path: root/lib/string_helpers.c
diff options
context:
space:
mode:
authorAndy Shevchenko <andriy.shevchenko@linux.intel.com>2013-04-30 18:27:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-04-30 20:04:03 -0400
commit16c7fa05829e8b91db48e3539c5d6ff3c2b18a23 (patch)
tree6658e9f27c033e5f6de19284fe9a6b8485360aa6 /lib/string_helpers.c
parente1d12f327037a59e06c66520951ab4e0bd29f9c4 (diff)
lib/string_helpers: introduce generic string_unescape
There are several places in kernel where modules unescapes input to convert C-Style Escape Sequences into byte codes. The patch provides generic implementation of such approach. Test cases are also included into the patch. [akpm@linux-foundation.org: clarify comment] [akpm@linux-foundation.org: export get_random_int() to modules] Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Cc: Samuel Thibault <samuel.thibault@ens-lyon.org> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Cc: Jason Baron <jbaron@redhat.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: William Hubbs <w.d.hubbs@gmail.com> Cc: Chris Brannon <chris@the-brannons.com> Cc: Kirk Reiser <kirk@braille.uwo.ca> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'lib/string_helpers.c')
-rw-r--r--lib/string_helpers.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 1cffc223bff5..ed5c1454dd62 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -2,10 +2,12 @@
2 * Helpers for formatting and printing strings 2 * Helpers for formatting and printing strings
3 * 3 *
4 * Copyright 31 August 2008 James Bottomley 4 * Copyright 31 August 2008 James Bottomley
5 * Copyright (C) 2013, Intel Corporation
5 */ 6 */
6#include <linux/kernel.h> 7#include <linux/kernel.h>
7#include <linux/math64.h> 8#include <linux/math64.h>
8#include <linux/export.h> 9#include <linux/export.h>
10#include <linux/ctype.h>
9#include <linux/string_helpers.h> 11#include <linux/string_helpers.h>
10 12
11/** 13/**
@@ -66,3 +68,134 @@ int string_get_size(u64 size, const enum string_size_units units,
66 return 0; 68 return 0;
67} 69}
68EXPORT_SYMBOL(string_get_size); 70EXPORT_SYMBOL(string_get_size);
71
72static bool unescape_space(char **src, char **dst)
73{
74 char *p = *dst, *q = *src;
75
76 switch (*q) {
77 case 'n':
78 *p = '\n';
79 break;
80 case 'r':
81 *p = '\r';
82 break;
83 case 't':
84 *p = '\t';
85 break;
86 case 'v':
87 *p = '\v';
88 break;
89 case 'f':
90 *p = '\f';
91 break;
92 default:
93 return false;
94 }
95 *dst += 1;
96 *src += 1;
97 return true;
98}
99
100static bool unescape_octal(char **src, char **dst)
101{
102 char *p = *dst, *q = *src;
103 u8 num;
104
105 if (isodigit(*q) == 0)
106 return false;
107
108 num = (*q++) & 7;
109 while (num < 32 && isodigit(*q) && (q - *src < 3)) {
110 num <<= 3;
111 num += (*q++) & 7;
112 }
113 *p = num;
114 *dst += 1;
115 *src = q;
116 return true;
117}
118
119static bool unescape_hex(char **src, char **dst)
120{
121 char *p = *dst, *q = *src;
122 int digit;
123 u8 num;
124
125 if (*q++ != 'x')
126 return false;
127
128 num = digit = hex_to_bin(*q++);
129 if (digit < 0)
130 return false;
131
132 digit = hex_to_bin(*q);
133 if (digit >= 0) {
134 q++;
135 num = (num << 4) | digit;
136 }
137 *p = num;
138 *dst += 1;
139 *src = q;
140 return true;
141}
142
143static bool unescape_special(char **src, char **dst)
144{
145 char *p = *dst, *q = *src;
146
147 switch (*q) {
148 case '\"':
149 *p = '\"';
150 break;
151 case '\\':
152 *p = '\\';
153 break;
154 case 'a':
155 *p = '\a';
156 break;
157 case 'e':
158 *p = '\e';
159 break;
160 default:
161 return false;
162 }
163 *dst += 1;
164 *src += 1;
165 return true;
166}
167
168int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
169{
170 char *out = dst;
171
172 while (*src && --size) {
173 if (src[0] == '\\' && src[1] != '\0' && size > 1) {
174 src++;
175 size--;
176
177 if (flags & UNESCAPE_SPACE &&
178 unescape_space(&src, &out))
179 continue;
180
181 if (flags & UNESCAPE_OCTAL &&
182 unescape_octal(&src, &out))
183 continue;
184
185 if (flags & UNESCAPE_HEX &&
186 unescape_hex(&src, &out))
187 continue;
188
189 if (flags & UNESCAPE_SPECIAL &&
190 unescape_special(&src, &out))
191 continue;
192
193 *out++ = '\\';
194 }
195 *out++ = *src++;
196 }
197 *out = '\0';
198
199 return out - dst;
200}
201EXPORT_SYMBOL(string_unescape);