LCOV - code coverage report
Current view: top level - lib - string_helpers.c (source / functions) Hit Total Coverage
Test: Real Lines: 39 235 16.6 %
Date: 2020-10-17 15:46:43 Functions: 0 14 0.0 %
Legend: Neither, QEMU, Real, Both Branches: 0 0 -

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

Generated by: LCOV version 1.14