string_helpers.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. /*
  2. * Helpers for formatting and printing strings
  3. *
  4. * Copyright 31 August 2008 James Bottomley
  5. * Copyright (C) 2013, Intel Corporation
  6. */
  7. #include <linux/bug.h>
  8. #include <linux/kernel.h>
  9. #include <linux/math64.h>
  10. #include <linux/export.h>
  11. #include <linux/ctype.h>
  12. #include <linux/errno.h>
  13. #include <linux/string.h>
  14. #include <linux/string_helpers.h>
  15. /**
  16. * string_get_size - get the size in the specified units
  17. * @size: The size to be converted in blocks
  18. * @blk_size: Size of the block (use 1 for size in bytes)
  19. * @units: units to use (powers of 1000 or 1024)
  20. * @buf: buffer to format to
  21. * @len: length of buffer
  22. *
  23. * This function returns a string formatted to 3 significant figures
  24. * giving the size in the required units. @buf should have room for
  25. * at least 9 bytes and will always be zero terminated.
  26. *
  27. */
  28. void string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
  29. char *buf, int len)
  30. {
  31. static const char *const units_10[] = {
  32. "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
  33. };
  34. static const char *const units_2[] = {
  35. "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
  36. };
  37. static const char *const *const units_str[] = {
  38. [STRING_UNITS_10] = units_10,
  39. [STRING_UNITS_2] = units_2,
  40. };
  41. static const unsigned int divisor[] = {
  42. [STRING_UNITS_10] = 1000,
  43. [STRING_UNITS_2] = 1024,
  44. };
  45. int i, j;
  46. u32 remainder = 0, sf_cap, exp;
  47. char tmp[8];
  48. const char *unit;
  49. tmp[0] = '\0';
  50. i = 0;
  51. if (!size)
  52. goto out;
  53. while (blk_size >= divisor[units]) {
  54. remainder = do_div(blk_size, divisor[units]);
  55. i++;
  56. }
  57. exp = divisor[units] / (u32)blk_size;
  58. /*
  59. * size must be strictly greater than exp here to ensure that remainder
  60. * is greater than divisor[units] coming out of the if below.
  61. */
  62. if (size > exp) {
  63. remainder = do_div(size, divisor[units]);
  64. remainder *= blk_size;
  65. i++;
  66. } else {
  67. remainder *= size;
  68. }
  69. size *= blk_size;
  70. size += remainder / divisor[units];
  71. remainder %= divisor[units];
  72. while (size >= divisor[units]) {
  73. remainder = do_div(size, divisor[units]);
  74. i++;
  75. }
  76. sf_cap = size;
  77. for (j = 0; sf_cap*10 < 1000; j++)
  78. sf_cap *= 10;
  79. if (j) {
  80. remainder *= 1000;
  81. remainder /= divisor[units];
  82. snprintf(tmp, sizeof(tmp), ".%03u", remainder);
  83. tmp[j+1] = '\0';
  84. }
  85. out:
  86. if (i >= ARRAY_SIZE(units_2))
  87. unit = "UNK";
  88. else
  89. unit = units_str[units][i];
  90. snprintf(buf, len, "%u%s %s", (u32)size,
  91. tmp, unit);
  92. }
  93. EXPORT_SYMBOL(string_get_size);
  94. static bool unescape_space(char **src, char **dst)
  95. {
  96. char *p = *dst, *q = *src;
  97. switch (*q) {
  98. case 'n':
  99. *p = '\n';
  100. break;
  101. case 'r':
  102. *p = '\r';
  103. break;
  104. case 't':
  105. *p = '\t';
  106. break;
  107. case 'v':
  108. *p = '\v';
  109. break;
  110. case 'f':
  111. *p = '\f';
  112. break;
  113. default:
  114. return false;
  115. }
  116. *dst += 1;
  117. *src += 1;
  118. return true;
  119. }
  120. static bool unescape_octal(char **src, char **dst)
  121. {
  122. char *p = *dst, *q = *src;
  123. u8 num;
  124. if (isodigit(*q) == 0)
  125. return false;
  126. num = (*q++) & 7;
  127. while (num < 32 && isodigit(*q) && (q - *src < 3)) {
  128. num <<= 3;
  129. num += (*q++) & 7;
  130. }
  131. *p = num;
  132. *dst += 1;
  133. *src = q;
  134. return true;
  135. }
  136. static bool unescape_hex(char **src, char **dst)
  137. {
  138. char *p = *dst, *q = *src;
  139. int digit;
  140. u8 num;
  141. if (*q++ != 'x')
  142. return false;
  143. num = digit = hex_to_bin(*q++);
  144. if (digit < 0)
  145. return false;
  146. digit = hex_to_bin(*q);
  147. if (digit >= 0) {
  148. q++;
  149. num = (num << 4) | digit;
  150. }
  151. *p = num;
  152. *dst += 1;
  153. *src = q;
  154. return true;
  155. }
  156. static bool unescape_special(char **src, char **dst)
  157. {
  158. char *p = *dst, *q = *src;
  159. switch (*q) {
  160. case '\"':
  161. *p = '\"';
  162. break;
  163. case '\\':
  164. *p = '\\';
  165. break;
  166. case 'a':
  167. *p = '\a';
  168. break;
  169. case 'e':
  170. *p = '\e';
  171. break;
  172. default:
  173. return false;
  174. }
  175. *dst += 1;
  176. *src += 1;
  177. return true;
  178. }
  179. /**
  180. * string_unescape - unquote characters in the given string
  181. * @src: source buffer (escaped)
  182. * @dst: destination buffer (unescaped)
  183. * @size: size of the destination buffer (0 to unlimit)
  184. * @flags: combination of the flags (bitwise OR):
  185. * %UNESCAPE_SPACE:
  186. * '\f' - form feed
  187. * '\n' - new line
  188. * '\r' - carriage return
  189. * '\t' - horizontal tab
  190. * '\v' - vertical tab
  191. * %UNESCAPE_OCTAL:
  192. * '\NNN' - byte with octal value NNN (1 to 3 digits)
  193. * %UNESCAPE_HEX:
  194. * '\xHH' - byte with hexadecimal value HH (1 to 2 digits)
  195. * %UNESCAPE_SPECIAL:
  196. * '\"' - double quote
  197. * '\\' - backslash
  198. * '\a' - alert (BEL)
  199. * '\e' - escape
  200. * %UNESCAPE_ANY:
  201. * all previous together
  202. *
  203. * Description:
  204. * The function unquotes characters in the given string.
  205. *
  206. * Because the size of the output will be the same as or less than the size of
  207. * the input, the transformation may be performed in place.
  208. *
  209. * Caller must provide valid source and destination pointers. Be aware that
  210. * destination buffer will always be NULL-terminated. Source string must be
  211. * NULL-terminated as well.
  212. *
  213. * Return:
  214. * The amount of the characters processed to the destination buffer excluding
  215. * trailing '\0' is returned.
  216. */
  217. int string_unescape(char *src, char *dst, size_t size, unsigned int flags)
  218. {
  219. char *out = dst;
  220. while (*src && --size) {
  221. if (src[0] == '\\' && src[1] != '\0' && size > 1) {
  222. src++;
  223. size--;
  224. if (flags & UNESCAPE_SPACE &&
  225. unescape_space(&src, &out))
  226. continue;
  227. if (flags & UNESCAPE_OCTAL &&
  228. unescape_octal(&src, &out))
  229. continue;
  230. if (flags & UNESCAPE_HEX &&
  231. unescape_hex(&src, &out))
  232. continue;
  233. if (flags & UNESCAPE_SPECIAL &&
  234. unescape_special(&src, &out))
  235. continue;
  236. *out++ = '\\';
  237. }
  238. *out++ = *src++;
  239. }
  240. *out = '\0';
  241. return out - dst;
  242. }
  243. EXPORT_SYMBOL(string_unescape);
  244. static bool escape_passthrough(unsigned char c, char **dst, char *end)
  245. {
  246. char *out = *dst;
  247. if (out < end)
  248. *out = c;
  249. *dst = out + 1;
  250. return true;
  251. }
  252. static bool escape_space(unsigned char c, char **dst, char *end)
  253. {
  254. char *out = *dst;
  255. unsigned char to;
  256. switch (c) {
  257. case '\n':
  258. to = 'n';
  259. break;
  260. case '\r':
  261. to = 'r';
  262. break;
  263. case '\t':
  264. to = 't';
  265. break;
  266. case '\v':
  267. to = 'v';
  268. break;
  269. case '\f':
  270. to = 'f';
  271. break;
  272. default:
  273. return false;
  274. }
  275. if (out < end)
  276. *out = '\\';
  277. ++out;
  278. if (out < end)
  279. *out = to;
  280. ++out;
  281. *dst = out;
  282. return true;
  283. }
  284. static bool escape_special(unsigned char c, char **dst, char *end)
  285. {
  286. char *out = *dst;
  287. unsigned char to;
  288. switch (c) {
  289. case '\\':
  290. to = '\\';
  291. break;
  292. case '\a':
  293. to = 'a';
  294. break;
  295. case '\e':
  296. to = 'e';
  297. break;
  298. default:
  299. return false;
  300. }
  301. if (out < end)
  302. *out = '\\';
  303. ++out;
  304. if (out < end)
  305. *out = to;
  306. ++out;
  307. *dst = out;
  308. return true;
  309. }
  310. static bool escape_null(unsigned char c, char **dst, char *end)
  311. {
  312. char *out = *dst;
  313. if (c)
  314. return false;
  315. if (out < end)
  316. *out = '\\';
  317. ++out;
  318. if (out < end)
  319. *out = '0';
  320. ++out;
  321. *dst = out;
  322. return true;
  323. }
  324. static bool escape_octal(unsigned char c, char **dst, char *end)
  325. {
  326. char *out = *dst;
  327. if (out < end)
  328. *out = '\\';
  329. ++out;
  330. if (out < end)
  331. *out = ((c >> 6) & 0x07) + '0';
  332. ++out;
  333. if (out < end)
  334. *out = ((c >> 3) & 0x07) + '0';
  335. ++out;
  336. if (out < end)
  337. *out = ((c >> 0) & 0x07) + '0';
  338. ++out;
  339. *dst = out;
  340. return true;
  341. }
  342. static bool escape_hex(unsigned char c, char **dst, char *end)
  343. {
  344. char *out = *dst;
  345. if (out < end)
  346. *out = '\\';
  347. ++out;
  348. if (out < end)
  349. *out = 'x';
  350. ++out;
  351. if (out < end)
  352. *out = hex_asc_hi(c);
  353. ++out;
  354. if (out < end)
  355. *out = hex_asc_lo(c);
  356. ++out;
  357. *dst = out;
  358. return true;
  359. }
  360. /**
  361. * string_escape_mem - quote characters in the given memory buffer
  362. * @src: source buffer (unescaped)
  363. * @isz: source buffer size
  364. * @dst: destination buffer (escaped)
  365. * @osz: destination buffer size
  366. * @flags: combination of the flags (bitwise OR):
  367. * %ESCAPE_SPACE: (special white space, not space itself)
  368. * '\f' - form feed
  369. * '\n' - new line
  370. * '\r' - carriage return
  371. * '\t' - horizontal tab
  372. * '\v' - vertical tab
  373. * %ESCAPE_SPECIAL:
  374. * '\\' - backslash
  375. * '\a' - alert (BEL)
  376. * '\e' - escape
  377. * %ESCAPE_NULL:
  378. * '\0' - null
  379. * %ESCAPE_OCTAL:
  380. * '\NNN' - byte with octal value NNN (3 digits)
  381. * %ESCAPE_ANY:
  382. * all previous together
  383. * %ESCAPE_NP:
  384. * escape only non-printable characters (checked by isprint)
  385. * %ESCAPE_ANY_NP:
  386. * all previous together
  387. * %ESCAPE_HEX:
  388. * '\xHH' - byte with hexadecimal value HH (2 digits)
  389. * @only: NULL-terminated string containing characters used to limit
  390. * the selected escape class. If characters are included in @only
  391. * that would not normally be escaped by the classes selected
  392. * in @flags, they will be copied to @dst unescaped.
  393. *
  394. * Description:
  395. * The process of escaping byte buffer includes several parts. They are applied
  396. * in the following sequence.
  397. * 1. The character is matched to the printable class, if asked, and in
  398. * case of match it passes through to the output.
  399. * 2. The character is not matched to the one from @only string and thus
  400. * must go as-is to the output.
  401. * 3. The character is checked if it falls into the class given by @flags.
  402. * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
  403. * character. Note that they actually can't go together, otherwise
  404. * %ESCAPE_HEX will be ignored.
  405. *
  406. * Caller must provide valid source and destination pointers. Be aware that
  407. * destination buffer will not be NULL-terminated, thus caller have to append
  408. * it if needs.
  409. *
  410. * Return:
  411. * The total size of the escaped output that would be generated for
  412. * the given input and flags. To check whether the output was
  413. * truncated, compare the return value to osz. There is room left in
  414. * dst for a '\0' terminator if and only if ret < osz.
  415. */
  416. int string_escape_mem(const char *src, size_t isz, char *dst, size_t osz,
  417. unsigned int flags, const char *only)
  418. {
  419. char *p = dst;
  420. char *end = p + osz;
  421. bool is_dict = only && *only;
  422. while (isz--) {
  423. unsigned char c = *src++;
  424. /*
  425. * Apply rules in the following sequence:
  426. * - the character is printable, when @flags has
  427. * %ESCAPE_NP bit set
  428. * - the @only string is supplied and does not contain a
  429. * character under question
  430. * - the character doesn't fall into a class of symbols
  431. * defined by given @flags
  432. * In these cases we just pass through a character to the
  433. * output buffer.
  434. */
  435. if ((flags & ESCAPE_NP && isprint(c)) ||
  436. (is_dict && !strchr(only, c))) {
  437. /* do nothing */
  438. } else {
  439. if (flags & ESCAPE_SPACE && escape_space(c, &p, end))
  440. continue;
  441. if (flags & ESCAPE_SPECIAL && escape_special(c, &p, end))
  442. continue;
  443. if (flags & ESCAPE_NULL && escape_null(c, &p, end))
  444. continue;
  445. /* ESCAPE_OCTAL and ESCAPE_HEX always go last */
  446. if (flags & ESCAPE_OCTAL && escape_octal(c, &p, end))
  447. continue;
  448. if (flags & ESCAPE_HEX && escape_hex(c, &p, end))
  449. continue;
  450. }
  451. escape_passthrough(c, &p, end);
  452. }
  453. return p - dst;
  454. }
  455. EXPORT_SYMBOL(string_escape_mem);