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