xref: /OK3568_Linux_fs/kernel/lib/string_helpers.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-only
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Helpers for formatting and printing strings
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 31 August 2008 James Bottomley
6*4882a593Smuzhiyun  * Copyright (C) 2013, Intel Corporation
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #include <linux/bug.h>
9*4882a593Smuzhiyun #include <linux/kernel.h>
10*4882a593Smuzhiyun #include <linux/math64.h>
11*4882a593Smuzhiyun #include <linux/export.h>
12*4882a593Smuzhiyun #include <linux/ctype.h>
13*4882a593Smuzhiyun #include <linux/errno.h>
14*4882a593Smuzhiyun #include <linux/fs.h>
15*4882a593Smuzhiyun #include <linux/limits.h>
16*4882a593Smuzhiyun #include <linux/mm.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/string.h>
19*4882a593Smuzhiyun #include <linux/string_helpers.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun /**
22*4882a593Smuzhiyun  * string_get_size - get the size in the specified units
23*4882a593Smuzhiyun  * @size:	The size to be converted in blocks
24*4882a593Smuzhiyun  * @blk_size:	Size of the block (use 1 for size in bytes)
25*4882a593Smuzhiyun  * @units:	units to use (powers of 1000 or 1024)
26*4882a593Smuzhiyun  * @buf:	buffer to format to
27*4882a593Smuzhiyun  * @len:	length of buffer
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * This function returns a string formatted to 3 significant figures
30*4882a593Smuzhiyun  * giving the size in the required units.  @buf should have room for
31*4882a593Smuzhiyun  * at least 9 bytes and will always be zero terminated.
32*4882a593Smuzhiyun  *
33*4882a593Smuzhiyun  */
string_get_size(u64 size,u64 blk_size,const enum string_size_units units,char * buf,int len)34*4882a593Smuzhiyun void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
35*4882a593Smuzhiyun 		     char *buf, int len)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun 	static const char *const units_10[] = {
38*4882a593Smuzhiyun 		"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
39*4882a593Smuzhiyun 	};
40*4882a593Smuzhiyun 	static const char *const units_2[] = {
41*4882a593Smuzhiyun 		"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
42*4882a593Smuzhiyun 	};
43*4882a593Smuzhiyun 	static const char *const *const units_str[] = {
44*4882a593Smuzhiyun 		[STRING_UNITS_10] = units_10,
45*4882a593Smuzhiyun 		[STRING_UNITS_2] = units_2,
46*4882a593Smuzhiyun 	};
47*4882a593Smuzhiyun 	static const unsigned int divisor[] = {
48*4882a593Smuzhiyun 		[STRING_UNITS_10] = 1000,
49*4882a593Smuzhiyun 		[STRING_UNITS_2] = 1024,
50*4882a593Smuzhiyun 	};
51*4882a593Smuzhiyun 	static const unsigned int rounding[] = { 500, 50, 5 };
52*4882a593Smuzhiyun 	int i = 0, j;
53*4882a593Smuzhiyun 	u32 remainder = 0, sf_cap;
54*4882a593Smuzhiyun 	char tmp[8];
55*4882a593Smuzhiyun 	const char *unit;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	tmp[0] = '\0';
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 	if (blk_size == 0)
60*4882a593Smuzhiyun 		size = 0;
61*4882a593Smuzhiyun 	if (size == 0)
62*4882a593Smuzhiyun 		goto out;
63*4882a593Smuzhiyun 
64*4882a593Smuzhiyun 	/* This is Napier's algorithm.  Reduce the original block size to
65*4882a593Smuzhiyun 	 *
66*4882a593Smuzhiyun 	 * coefficient * divisor[units]^i
67*4882a593Smuzhiyun 	 *
68*4882a593Smuzhiyun 	 * we do the reduction so both coefficients are just under 32 bits so
69*4882a593Smuzhiyun 	 * that multiplying them together won't overflow 64 bits and we keep
70*4882a593Smuzhiyun 	 * as much precision as possible in the numbers.
71*4882a593Smuzhiyun 	 *
72*4882a593Smuzhiyun 	 * Note: it's safe to throw away the remainders here because all the
73*4882a593Smuzhiyun 	 * precision is in the coefficients.
74*4882a593Smuzhiyun 	 */
75*4882a593Smuzhiyun 	while (blk_size >> 32) {
76*4882a593Smuzhiyun 		do_div(blk_size, divisor[units]);
77*4882a593Smuzhiyun 		i++;
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	while (size >> 32) {
81*4882a593Smuzhiyun 		do_div(size, divisor[units]);
82*4882a593Smuzhiyun 		i++;
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	/* now perform the actual multiplication keeping i as the sum of the
86*4882a593Smuzhiyun 	 * two logarithms */
87*4882a593Smuzhiyun 	size *= blk_size;
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun 	/* and logarithmically reduce it until it's just under the divisor */
90*4882a593Smuzhiyun 	while (size >= divisor[units]) {
91*4882a593Smuzhiyun 		remainder = do_div(size, divisor[units]);
92*4882a593Smuzhiyun 		i++;
93*4882a593Smuzhiyun 	}
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun 	/* work out in j how many digits of precision we need from the
96*4882a593Smuzhiyun 	 * remainder */
97*4882a593Smuzhiyun 	sf_cap = size;
98*4882a593Smuzhiyun 	for (j = 0; sf_cap*10 < 1000; j++)
99*4882a593Smuzhiyun 		sf_cap *= 10;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	if (units == STRING_UNITS_2) {
102*4882a593Smuzhiyun 		/* express the remainder as a decimal.  It's currently the
103*4882a593Smuzhiyun 		 * numerator of a fraction whose denominator is
104*4882a593Smuzhiyun 		 * divisor[units], which is 1 << 10 for STRING_UNITS_2 */
105*4882a593Smuzhiyun 		remainder *= 1000;
106*4882a593Smuzhiyun 		remainder >>= 10;
107*4882a593Smuzhiyun 	}
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	/* add a 5 to the digit below what will be printed to ensure
110*4882a593Smuzhiyun 	 * an arithmetical round up and carry it through to size */
111*4882a593Smuzhiyun 	remainder += rounding[j];
112*4882a593Smuzhiyun 	if (remainder >= 1000) {
113*4882a593Smuzhiyun 		remainder -= 1000;
114*4882a593Smuzhiyun 		size += 1;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	if (j) {
118*4882a593Smuzhiyun 		snprintf(tmp, sizeof(tmp), ".%03u", remainder);
119*4882a593Smuzhiyun 		tmp[j+1] = '\0';
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun  out:
123*4882a593Smuzhiyun 	if (i >= ARRAY_SIZE(units_2))
124*4882a593Smuzhiyun 		unit = "UNK";
125*4882a593Smuzhiyun 	else
126*4882a593Smuzhiyun 		unit = units_str[units][i];
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	snprintf(buf, len, "%u%s %s", (u32)size,
129*4882a593Smuzhiyun 		 tmp, unit);
130*4882a593Smuzhiyun }
131*4882a593Smuzhiyun EXPORT_SYMBOL(string_get_size);
132*4882a593Smuzhiyun 
unescape_space(char ** src,char ** dst)133*4882a593Smuzhiyun static bool unescape_space(char **src, char **dst)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	char *p = *dst, *q = *src;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	switch (*q) {
138*4882a593Smuzhiyun 	case 'n':
139*4882a593Smuzhiyun 		*p = '\n';
140*4882a593Smuzhiyun 		break;
141*4882a593Smuzhiyun 	case 'r':
142*4882a593Smuzhiyun 		*p = '\r';
143*4882a593Smuzhiyun 		break;
144*4882a593Smuzhiyun 	case 't':
145*4882a593Smuzhiyun 		*p = '\t';
146*4882a593Smuzhiyun 		break;
147*4882a593Smuzhiyun 	case 'v':
148*4882a593Smuzhiyun 		*p = '\v';
149*4882a593Smuzhiyun 		break;
150*4882a593Smuzhiyun 	case 'f':
151*4882a593Smuzhiyun 		*p = '\f';
152*4882a593Smuzhiyun 		break;
153*4882a593Smuzhiyun 	default:
154*4882a593Smuzhiyun 		return false;
155*4882a593Smuzhiyun 	}
156*4882a593Smuzhiyun 	*dst += 1;
157*4882a593Smuzhiyun 	*src += 1;
158*4882a593Smuzhiyun 	return true;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun 
unescape_octal(char ** src,char ** dst)161*4882a593Smuzhiyun static bool unescape_octal(char **src, char **dst)
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun 	char *p = *dst, *q = *src;
164*4882a593Smuzhiyun 	u8 num;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (isodigit(*q) == 0)
167*4882a593Smuzhiyun 		return false;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	num = (*q++) & 7;
170*4882a593Smuzhiyun 	while (num < 32 && isodigit(*q) && (q - *src < 3)) {
171*4882a593Smuzhiyun 		num <<= 3;
172*4882a593Smuzhiyun 		num += (*q++) & 7;
173*4882a593Smuzhiyun 	}
174*4882a593Smuzhiyun 	*p = num;
175*4882a593Smuzhiyun 	*dst += 1;
176*4882a593Smuzhiyun 	*src = q;
177*4882a593Smuzhiyun 	return true;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun 
unescape_hex(char ** src,char ** dst)180*4882a593Smuzhiyun static bool unescape_hex(char **src, char **dst)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun 	char *p = *dst, *q = *src;
183*4882a593Smuzhiyun 	int digit;
184*4882a593Smuzhiyun 	u8 num;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	if (*q++ != 'x')
187*4882a593Smuzhiyun 		return false;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	num = digit = hex_to_bin(*q++);
190*4882a593Smuzhiyun 	if (digit < 0)
191*4882a593Smuzhiyun 		return false;
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun 	digit = hex_to_bin(*q);
194*4882a593Smuzhiyun 	if (digit >= 0) {
195*4882a593Smuzhiyun 		q++;
196*4882a593Smuzhiyun 		num = (num << 4) | digit;
197*4882a593Smuzhiyun 	}
198*4882a593Smuzhiyun 	*p = num;
199*4882a593Smuzhiyun 	*dst += 1;
200*4882a593Smuzhiyun 	*src = q;
201*4882a593Smuzhiyun 	return true;
202*4882a593Smuzhiyun }
203*4882a593Smuzhiyun 
unescape_special(char ** src,char ** dst)204*4882a593Smuzhiyun static bool unescape_special(char **src, char **dst)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	char *p = *dst, *q = *src;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	switch (*q) {
209*4882a593Smuzhiyun 	case '\"':
210*4882a593Smuzhiyun 		*p = '\"';
211*4882a593Smuzhiyun 		break;
212*4882a593Smuzhiyun 	case '\\':
213*4882a593Smuzhiyun 		*p = '\\';
214*4882a593Smuzhiyun 		break;
215*4882a593Smuzhiyun 	case 'a':
216*4882a593Smuzhiyun 		*p = '\a';
217*4882a593Smuzhiyun 		break;
218*4882a593Smuzhiyun 	case 'e':
219*4882a593Smuzhiyun 		*p = '\e';
220*4882a593Smuzhiyun 		break;
221*4882a593Smuzhiyun 	default:
222*4882a593Smuzhiyun 		return false;
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 	*dst += 1;
225*4882a593Smuzhiyun 	*src += 1;
226*4882a593Smuzhiyun 	return true;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun /**
230*4882a593Smuzhiyun  * string_unescape - unquote characters in the given string
231*4882a593Smuzhiyun  * @src:	source buffer (escaped)
232*4882a593Smuzhiyun  * @dst:	destination buffer (unescaped)
233*4882a593Smuzhiyun  * @size:	size of the destination buffer (0 to unlimit)
234*4882a593Smuzhiyun  * @flags:	combination of the flags.
235*4882a593Smuzhiyun  *
236*4882a593Smuzhiyun  * Description:
237*4882a593Smuzhiyun  * The function unquotes characters in the given string.
238*4882a593Smuzhiyun  *
239*4882a593Smuzhiyun  * Because the size of the output will be the same as or less than the size of
240*4882a593Smuzhiyun  * the input, the transformation may be performed in place.
241*4882a593Smuzhiyun  *
242*4882a593Smuzhiyun  * Caller must provide valid source and destination pointers. Be aware that
243*4882a593Smuzhiyun  * destination buffer will always be NULL-terminated. Source string must be
244*4882a593Smuzhiyun  * NULL-terminated as well.  The supported flags are::
245*4882a593Smuzhiyun  *
246*4882a593Smuzhiyun  *	UNESCAPE_SPACE:
247*4882a593Smuzhiyun  *		'\f' - form feed
248*4882a593Smuzhiyun  *		'\n' - new line
249*4882a593Smuzhiyun  *		'\r' - carriage return
250*4882a593Smuzhiyun  *		'\t' - horizontal tab
251*4882a593Smuzhiyun  *		'\v' - vertical tab
252*4882a593Smuzhiyun  *	UNESCAPE_OCTAL:
253*4882a593Smuzhiyun  *		'\NNN' - byte with octal value NNN (1 to 3 digits)
254*4882a593Smuzhiyun  *	UNESCAPE_HEX:
255*4882a593Smuzhiyun  *		'\xHH' - byte with hexadecimal value HH (1 to 2 digits)
256*4882a593Smuzhiyun  *	UNESCAPE_SPECIAL:
257*4882a593Smuzhiyun  *		'\"' - double quote
258*4882a593Smuzhiyun  *		'\\' - backslash
259*4882a593Smuzhiyun  *		'\a' - alert (BEL)
260*4882a593Smuzhiyun  *		'\e' - escape
261*4882a593Smuzhiyun  *	UNESCAPE_ANY:
262*4882a593Smuzhiyun  *		all previous together
263*4882a593Smuzhiyun  *
264*4882a593Smuzhiyun  * Return:
265*4882a593Smuzhiyun  * The amount of the characters processed to the destination buffer excluding
266*4882a593Smuzhiyun  * trailing '\0' is returned.
267*4882a593Smuzhiyun  */
string_unescape(char * src,char * dst,size_t size,unsigned int flags)268*4882a593Smuzhiyun int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun 	char *out = dst;
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	while (*src && --size) {
273*4882a593Smuzhiyun 		if (src[0] == '\\' && src[1] != '\0' && size > 1) {
274*4882a593Smuzhiyun 			src++;
275*4882a593Smuzhiyun 			size--;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 			if (flags & UNESCAPE_SPACE &&
278*4882a593Smuzhiyun 					unescape_space(&src, &out))
279*4882a593Smuzhiyun 				continue;
280*4882a593Smuzhiyun 
281*4882a593Smuzhiyun 			if (flags & UNESCAPE_OCTAL &&
282*4882a593Smuzhiyun 					unescape_octal(&src, &out))
283*4882a593Smuzhiyun 				continue;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 			if (flags & UNESCAPE_HEX &&
286*4882a593Smuzhiyun 					unescape_hex(&src, &out))
287*4882a593Smuzhiyun 				continue;
288*4882a593Smuzhiyun 
289*4882a593Smuzhiyun 			if (flags & UNESCAPE_SPECIAL &&
290*4882a593Smuzhiyun 					unescape_special(&src, &out))
291*4882a593Smuzhiyun 				continue;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 			*out++ = '\\';
294*4882a593Smuzhiyun 		}
295*4882a593Smuzhiyun 		*out++ = *src++;
296*4882a593Smuzhiyun 	}
297*4882a593Smuzhiyun 	*out = '\0';
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	return out - dst;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun EXPORT_SYMBOL(string_unescape);
302*4882a593Smuzhiyun 
escape_passthrough(unsigned char c,char ** dst,char * end)303*4882a593Smuzhiyun static bool escape_passthrough(unsigned char c, char **dst, char *end)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	char *out = *dst;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	if (out < end)
308*4882a593Smuzhiyun 		*out = c;
309*4882a593Smuzhiyun 	*dst = out + 1;
310*4882a593Smuzhiyun 	return true;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
escape_space(unsigned char c,char ** dst,char * end)313*4882a593Smuzhiyun static bool escape_space(unsigned char c, char **dst, char *end)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun 	char *out = *dst;
316*4882a593Smuzhiyun 	unsigned char to;
317*4882a593Smuzhiyun 
318*4882a593Smuzhiyun 	switch (c) {
319*4882a593Smuzhiyun 	case '\n':
320*4882a593Smuzhiyun 		to = 'n';
321*4882a593Smuzhiyun 		break;
322*4882a593Smuzhiyun 	case '\r':
323*4882a593Smuzhiyun 		to = 'r';
324*4882a593Smuzhiyun 		break;
325*4882a593Smuzhiyun 	case '\t':
326*4882a593Smuzhiyun 		to = 't';
327*4882a593Smuzhiyun 		break;
328*4882a593Smuzhiyun 	case '\v':
329*4882a593Smuzhiyun 		to = 'v';
330*4882a593Smuzhiyun 		break;
331*4882a593Smuzhiyun 	case '\f':
332*4882a593Smuzhiyun 		to = 'f';
333*4882a593Smuzhiyun 		break;
334*4882a593Smuzhiyun 	default:
335*4882a593Smuzhiyun 		return false;
336*4882a593Smuzhiyun 	}
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (out < end)
339*4882a593Smuzhiyun 		*out = '\\';
340*4882a593Smuzhiyun 	++out;
341*4882a593Smuzhiyun 	if (out < end)
342*4882a593Smuzhiyun 		*out = to;
343*4882a593Smuzhiyun 	++out;
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	*dst = out;
346*4882a593Smuzhiyun 	return true;
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun 
escape_special(unsigned char c,char ** dst,char * end)349*4882a593Smuzhiyun static bool escape_special(unsigned char c, char **dst, char *end)
350*4882a593Smuzhiyun {
351*4882a593Smuzhiyun 	char *out = *dst;
352*4882a593Smuzhiyun 	unsigned char to;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 	switch (c) {
355*4882a593Smuzhiyun 	case '\\':
356*4882a593Smuzhiyun 		to = '\\';
357*4882a593Smuzhiyun 		break;
358*4882a593Smuzhiyun 	case '\a':
359*4882a593Smuzhiyun 		to = 'a';
360*4882a593Smuzhiyun 		break;
361*4882a593Smuzhiyun 	case '\e':
362*4882a593Smuzhiyun 		to = 'e';
363*4882a593Smuzhiyun 		break;
364*4882a593Smuzhiyun 	default:
365*4882a593Smuzhiyun 		return false;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	if (out < end)
369*4882a593Smuzhiyun 		*out = '\\';
370*4882a593Smuzhiyun 	++out;
371*4882a593Smuzhiyun 	if (out < end)
372*4882a593Smuzhiyun 		*out = to;
373*4882a593Smuzhiyun 	++out;
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	*dst = out;
376*4882a593Smuzhiyun 	return true;
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
escape_null(unsigned char c,char ** dst,char * end)379*4882a593Smuzhiyun static bool escape_null(unsigned char c, char **dst, char *end)
380*4882a593Smuzhiyun {
381*4882a593Smuzhiyun 	char *out = *dst;
382*4882a593Smuzhiyun 
383*4882a593Smuzhiyun 	if (c)
384*4882a593Smuzhiyun 		return false;
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun 	if (out < end)
387*4882a593Smuzhiyun 		*out = '\\';
388*4882a593Smuzhiyun 	++out;
389*4882a593Smuzhiyun 	if (out < end)
390*4882a593Smuzhiyun 		*out = '0';
391*4882a593Smuzhiyun 	++out;
392*4882a593Smuzhiyun 
393*4882a593Smuzhiyun 	*dst = out;
394*4882a593Smuzhiyun 	return true;
395*4882a593Smuzhiyun }
396*4882a593Smuzhiyun 
escape_octal(unsigned char c,char ** dst,char * end)397*4882a593Smuzhiyun static bool escape_octal(unsigned char c, char **dst, char *end)
398*4882a593Smuzhiyun {
399*4882a593Smuzhiyun 	char *out = *dst;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	if (out < end)
402*4882a593Smuzhiyun 		*out = '\\';
403*4882a593Smuzhiyun 	++out;
404*4882a593Smuzhiyun 	if (out < end)
405*4882a593Smuzhiyun 		*out = ((c >> 6) & 0x07) + '0';
406*4882a593Smuzhiyun 	++out;
407*4882a593Smuzhiyun 	if (out < end)
408*4882a593Smuzhiyun 		*out = ((c >> 3) & 0x07) + '0';
409*4882a593Smuzhiyun 	++out;
410*4882a593Smuzhiyun 	if (out < end)
411*4882a593Smuzhiyun 		*out = ((c >> 0) & 0x07) + '0';
412*4882a593Smuzhiyun 	++out;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	*dst = out;
415*4882a593Smuzhiyun 	return true;
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun 
escape_hex(unsigned char c,char ** dst,char * end)418*4882a593Smuzhiyun static bool escape_hex(unsigned char c, char **dst, char *end)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	char *out = *dst;
421*4882a593Smuzhiyun 
422*4882a593Smuzhiyun 	if (out < end)
423*4882a593Smuzhiyun 		*out = '\\';
424*4882a593Smuzhiyun 	++out;
425*4882a593Smuzhiyun 	if (out < end)
426*4882a593Smuzhiyun 		*out = 'x';
427*4882a593Smuzhiyun 	++out;
428*4882a593Smuzhiyun 	if (out < end)
429*4882a593Smuzhiyun 		*out = hex_asc_hi(c);
430*4882a593Smuzhiyun 	++out;
431*4882a593Smuzhiyun 	if (out < end)
432*4882a593Smuzhiyun 		*out = hex_asc_lo(c);
433*4882a593Smuzhiyun 	++out;
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 	*dst = out;
436*4882a593Smuzhiyun 	return true;
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
439*4882a593Smuzhiyun /**
440*4882a593Smuzhiyun  * string_escape_mem - quote characters in the given memory buffer
441*4882a593Smuzhiyun  * @src:	source buffer (unescaped)
442*4882a593Smuzhiyun  * @isz:	source buffer size
443*4882a593Smuzhiyun  * @dst:	destination buffer (escaped)
444*4882a593Smuzhiyun  * @osz:	destination buffer size
445*4882a593Smuzhiyun  * @flags:	combination of the flags
446*4882a593Smuzhiyun  * @only:	NULL-terminated string containing characters used to limit
447*4882a593Smuzhiyun  *		the selected escape class. If characters are included in @only
448*4882a593Smuzhiyun  *		that would not normally be escaped by the classes selected
449*4882a593Smuzhiyun  *		in @flags, they will be copied to @dst unescaped.
450*4882a593Smuzhiyun  *
451*4882a593Smuzhiyun  * Description:
452*4882a593Smuzhiyun  * The process of escaping byte buffer includes several parts. They are applied
453*4882a593Smuzhiyun  * in the following sequence.
454*4882a593Smuzhiyun  *
455*4882a593Smuzhiyun  *	1. The character is matched to the printable class, if asked, and in
456*4882a593Smuzhiyun  *	   case of match it passes through to the output.
457*4882a593Smuzhiyun  *	2. The character is not matched to the one from @only string and thus
458*4882a593Smuzhiyun  *	   must go as-is to the output.
459*4882a593Smuzhiyun  *	3. The character is checked if it falls into the class given by @flags.
460*4882a593Smuzhiyun  *	   %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
461*4882a593Smuzhiyun  *	   character. Note that they actually can't go together, otherwise
462*4882a593Smuzhiyun  *	   %ESCAPE_HEX will be ignored.
463*4882a593Smuzhiyun  *
464*4882a593Smuzhiyun  * Caller must provide valid source and destination pointers. Be aware that
465*4882a593Smuzhiyun  * destination buffer will not be NULL-terminated, thus caller have to append
466*4882a593Smuzhiyun  * it if needs.   The supported flags are::
467*4882a593Smuzhiyun  *
468*4882a593Smuzhiyun  *	%ESCAPE_SPACE: (special white space, not space itself)
469*4882a593Smuzhiyun  *		'\f' - form feed
470*4882a593Smuzhiyun  *		'\n' - new line
471*4882a593Smuzhiyun  *		'\r' - carriage return
472*4882a593Smuzhiyun  *		'\t' - horizontal tab
473*4882a593Smuzhiyun  *		'\v' - vertical tab
474*4882a593Smuzhiyun  *	%ESCAPE_SPECIAL:
475*4882a593Smuzhiyun  *		'\\' - backslash
476*4882a593Smuzhiyun  *		'\a' - alert (BEL)
477*4882a593Smuzhiyun  *		'\e' - escape
478*4882a593Smuzhiyun  *	%ESCAPE_NULL:
479*4882a593Smuzhiyun  *		'\0' - null
480*4882a593Smuzhiyun  *	%ESCAPE_OCTAL:
481*4882a593Smuzhiyun  *		'\NNN' - byte with octal value NNN (3 digits)
482*4882a593Smuzhiyun  *	%ESCAPE_ANY:
483*4882a593Smuzhiyun  *		all previous together
484*4882a593Smuzhiyun  *	%ESCAPE_NP:
485*4882a593Smuzhiyun  *		escape only non-printable characters (checked by isprint)
486*4882a593Smuzhiyun  *	%ESCAPE_ANY_NP:
487*4882a593Smuzhiyun  *		all previous together
488*4882a593Smuzhiyun  *	%ESCAPE_HEX:
489*4882a593Smuzhiyun  *		'\xHH' - byte with hexadecimal value HH (2 digits)
490*4882a593Smuzhiyun  *
491*4882a593Smuzhiyun  * Return:
492*4882a593Smuzhiyun  * The total size of the escaped output that would be generated for
493*4882a593Smuzhiyun  * the given input and flags. To check whether the output was
494*4882a593Smuzhiyun  * truncated, compare the return value to osz. There is room left in
495*4882a593Smuzhiyun  * dst for a '\0' terminator if and only if ret < osz.
496*4882a593Smuzhiyun  */
string_escape_mem(const char * src,size_t isz,char * dst,size_t osz,unsigned int flags,const char * only)497*4882a593Smuzhiyun int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
498*4882a593Smuzhiyun 		      unsigned int flags, const char *only)
499*4882a593Smuzhiyun {
500*4882a593Smuzhiyun 	char *p = dst;
501*4882a593Smuzhiyun 	char *end = p + osz;
502*4882a593Smuzhiyun 	bool is_dict = only && *only;
503*4882a593Smuzhiyun 
504*4882a593Smuzhiyun 	while (isz--) {
505*4882a593Smuzhiyun 		unsigned char c = *src++;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 		/*
508*4882a593Smuzhiyun 		 * Apply rules in the following sequence:
509*4882a593Smuzhiyun 		 *	- the character is printable, when @flags has
510*4882a593Smuzhiyun 		 *	  %ESCAPE_NP bit set
511*4882a593Smuzhiyun 		 *	- the @only string is supplied and does not contain a
512*4882a593Smuzhiyun 		 *	  character under question
513*4882a593Smuzhiyun 		 *	- the character doesn't fall into a class of symbols
514*4882a593Smuzhiyun 		 *	  defined by given @flags
515*4882a593Smuzhiyun 		 * In these cases we just pass through a character to the
516*4882a593Smuzhiyun 		 * output buffer.
517*4882a593Smuzhiyun 		 */
518*4882a593Smuzhiyun 		if ((flags & ESCAPE_NP && isprint(c)) ||
519*4882a593Smuzhiyun 		    (is_dict && !strchr(only, c))) {
520*4882a593Smuzhiyun 			/* do nothing */
521*4882a593Smuzhiyun 		} else {
522*4882a593Smuzhiyun 			if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
523*4882a593Smuzhiyun 				continue;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 			if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
526*4882a593Smuzhiyun 				continue;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun 			if (flags & ESCAPE_NULL && escape_null(c, &p, end))
529*4882a593Smuzhiyun 				continue;
530*4882a593Smuzhiyun 
531*4882a593Smuzhiyun 			/* ESCAPE_OCTAL and ESCAPE_HEX always go last */
532*4882a593Smuzhiyun 			if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
533*4882a593Smuzhiyun 				continue;
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 			if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
536*4882a593Smuzhiyun 				continue;
537*4882a593Smuzhiyun 		}
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 		escape_passthrough(c, &p, end);
540*4882a593Smuzhiyun 	}
541*4882a593Smuzhiyun 
542*4882a593Smuzhiyun 	return p - dst;
543*4882a593Smuzhiyun }
544*4882a593Smuzhiyun EXPORT_SYMBOL(string_escape_mem);
545*4882a593Smuzhiyun 
string_escape_mem_ascii(const char * src,size_t isz,char * dst,size_t osz)546*4882a593Smuzhiyun int string_escape_mem_ascii(const char *src, size_t isz, char *dst,
547*4882a593Smuzhiyun 					size_t osz)
548*4882a593Smuzhiyun {
549*4882a593Smuzhiyun 	char *p = dst;
550*4882a593Smuzhiyun 	char *end = p + osz;
551*4882a593Smuzhiyun 
552*4882a593Smuzhiyun 	while (isz--) {
553*4882a593Smuzhiyun 		unsigned char c = *src++;
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun 		if (!isprint(c) || !isascii(c) || c == '"' || c == '\\')
556*4882a593Smuzhiyun 			escape_hex(c, &p, end);
557*4882a593Smuzhiyun 		else
558*4882a593Smuzhiyun 			escape_passthrough(c, &p, end);
559*4882a593Smuzhiyun 	}
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	return p - dst;
562*4882a593Smuzhiyun }
563*4882a593Smuzhiyun EXPORT_SYMBOL(string_escape_mem_ascii);
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun /*
566*4882a593Smuzhiyun  * Return an allocated string that has been escaped of special characters
567*4882a593Smuzhiyun  * and double quotes, making it safe to log in quotes.
568*4882a593Smuzhiyun  */
kstrdup_quotable(const char * src,gfp_t gfp)569*4882a593Smuzhiyun char *kstrdup_quotable(const char *src, gfp_t gfp)
570*4882a593Smuzhiyun {
571*4882a593Smuzhiyun 	size_t slen, dlen;
572*4882a593Smuzhiyun 	char *dst;
573*4882a593Smuzhiyun 	const int flags = ESCAPE_HEX;
574*4882a593Smuzhiyun 	const char esc[] = "\f\n\r\t\v\a\e\\\"";
575*4882a593Smuzhiyun 
576*4882a593Smuzhiyun 	if (!src)
577*4882a593Smuzhiyun 		return NULL;
578*4882a593Smuzhiyun 	slen = strlen(src);
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	dlen = string_escape_mem(src, slen, NULL, 0, flags, esc);
581*4882a593Smuzhiyun 	dst = kmalloc(dlen + 1, gfp);
582*4882a593Smuzhiyun 	if (!dst)
583*4882a593Smuzhiyun 		return NULL;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	WARN_ON(string_escape_mem(src, slen, dst, dlen, flags, esc) != dlen);
586*4882a593Smuzhiyun 	dst[dlen] = '\0';
587*4882a593Smuzhiyun 
588*4882a593Smuzhiyun 	return dst;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(kstrdup_quotable);
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun /*
593*4882a593Smuzhiyun  * Returns allocated NULL-terminated string containing process
594*4882a593Smuzhiyun  * command line, with inter-argument NULLs replaced with spaces,
595*4882a593Smuzhiyun  * and other special characters escaped.
596*4882a593Smuzhiyun  */
kstrdup_quotable_cmdline(struct task_struct * task,gfp_t gfp)597*4882a593Smuzhiyun char *kstrdup_quotable_cmdline(struct task_struct *task, gfp_t gfp)
598*4882a593Smuzhiyun {
599*4882a593Smuzhiyun 	char *buffer, *quoted;
600*4882a593Smuzhiyun 	int i, res;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun 	buffer = kmalloc(PAGE_SIZE, GFP_KERNEL);
603*4882a593Smuzhiyun 	if (!buffer)
604*4882a593Smuzhiyun 		return NULL;
605*4882a593Smuzhiyun 
606*4882a593Smuzhiyun 	res = get_cmdline(task, buffer, PAGE_SIZE - 1);
607*4882a593Smuzhiyun 	buffer[res] = '\0';
608*4882a593Smuzhiyun 
609*4882a593Smuzhiyun 	/* Collapse trailing NULLs, leave res pointing to last non-NULL. */
610*4882a593Smuzhiyun 	while (--res >= 0 && buffer[res] == '\0')
611*4882a593Smuzhiyun 		;
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/* Replace inter-argument NULLs. */
614*4882a593Smuzhiyun 	for (i = 0; i <= res; i++)
615*4882a593Smuzhiyun 		if (buffer[i] == '\0')
616*4882a593Smuzhiyun 			buffer[i] = ' ';
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	/* Make sure result is printable. */
619*4882a593Smuzhiyun 	quoted = kstrdup_quotable(buffer, gfp);
620*4882a593Smuzhiyun 	kfree(buffer);
621*4882a593Smuzhiyun 	return quoted;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(kstrdup_quotable_cmdline);
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun /*
626*4882a593Smuzhiyun  * Returns allocated NULL-terminated string containing pathname,
627*4882a593Smuzhiyun  * with special characters escaped, able to be safely logged. If
628*4882a593Smuzhiyun  * there is an error, the leading character will be "<".
629*4882a593Smuzhiyun  */
kstrdup_quotable_file(struct file * file,gfp_t gfp)630*4882a593Smuzhiyun char *kstrdup_quotable_file(struct file *file, gfp_t gfp)
631*4882a593Smuzhiyun {
632*4882a593Smuzhiyun 	char *temp, *pathname;
633*4882a593Smuzhiyun 
634*4882a593Smuzhiyun 	if (!file)
635*4882a593Smuzhiyun 		return kstrdup("<unknown>", gfp);
636*4882a593Smuzhiyun 
637*4882a593Smuzhiyun 	/* We add 11 spaces for ' (deleted)' to be appended */
638*4882a593Smuzhiyun 	temp = kmalloc(PATH_MAX + 11, GFP_KERNEL);
639*4882a593Smuzhiyun 	if (!temp)
640*4882a593Smuzhiyun 		return kstrdup("<no_memory>", gfp);
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 	pathname = file_path(file, temp, PATH_MAX + 11);
643*4882a593Smuzhiyun 	if (IS_ERR(pathname))
644*4882a593Smuzhiyun 		pathname = kstrdup("<too_long>", gfp);
645*4882a593Smuzhiyun 	else
646*4882a593Smuzhiyun 		pathname = kstrdup_quotable(pathname, gfp);
647*4882a593Smuzhiyun 
648*4882a593Smuzhiyun 	kfree(temp);
649*4882a593Smuzhiyun 	return pathname;
650*4882a593Smuzhiyun }
651*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(kstrdup_quotable_file);
652*4882a593Smuzhiyun 
653*4882a593Smuzhiyun /**
654*4882a593Smuzhiyun  * kfree_strarray - free a number of dynamically allocated strings contained
655*4882a593Smuzhiyun  *                  in an array and the array itself
656*4882a593Smuzhiyun  *
657*4882a593Smuzhiyun  * @array: Dynamically allocated array of strings to free.
658*4882a593Smuzhiyun  * @n: Number of strings (starting from the beginning of the array) to free.
659*4882a593Smuzhiyun  *
660*4882a593Smuzhiyun  * Passing a non-NULL @array and @n == 0 as well as NULL @array are valid
661*4882a593Smuzhiyun  * use-cases. If @array is NULL, the function does nothing.
662*4882a593Smuzhiyun  */
kfree_strarray(char ** array,size_t n)663*4882a593Smuzhiyun void kfree_strarray(char **array, size_t n)
664*4882a593Smuzhiyun {
665*4882a593Smuzhiyun 	unsigned int i;
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 	if (!array)
668*4882a593Smuzhiyun 		return;
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	for (i = 0; i < n; i++)
671*4882a593Smuzhiyun 		kfree(array[i]);
672*4882a593Smuzhiyun 	kfree(array);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(kfree_strarray);
675