LCOV - code coverage report
Current view: top level - source3/lib - util_str.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 196 317 61.8 %
Date: 2024-04-21 15:09:00 Functions: 17 19 89.5 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Samba utility functions
       4             : 
       5             :    Copyright (C) Andrew Tridgell 1992-2001
       6             :    Copyright (C) Simo Sorce      2001-2002
       7             :    Copyright (C) Martin Pool     2003
       8             :    Copyright (C) James Peach     2006
       9             :    Copyright (C) Jeremy Allison  1992-2007
      10             : 
      11             :    This program is free software; you can redistribute it and/or modify
      12             :    it under the terms of the GNU General Public License as published by
      13             :    the Free Software Foundation; either version 3 of the License, or
      14             :    (at your option) any later version.
      15             : 
      16             :    This program is distributed in the hope that it will be useful,
      17             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      18             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      19             :    GNU General Public License for more details.
      20             : 
      21             :    You should have received a copy of the GNU General Public License
      22             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      23             : */
      24             : 
      25             : #include "includes.h"
      26             : #include "lib/param/loadparm.h"
      27             : #include "lib/util/smb_strtox.h"
      28             : 
      29             : static const char toupper_ascii_fast_table[128] = {
      30             :         0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
      31             :         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
      32             :         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
      33             :         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
      34             :         0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
      35             :         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
      36             :         0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
      37             :         0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
      38             : };
      39             : 
      40             : /**
      41             :  * Compare 2 strings up to and including the nth char.
      42             :  *
      43             :  * @note The comparison is case-insensitive.
      44             :  **/
      45     4079453 : bool strnequal(const char *s1,const char *s2,size_t n)
      46             : {
      47     4079453 :         if (s1 == s2)
      48           0 :                 return(true);
      49     4079453 :         if (!s1 || !s2 || !n)
      50           0 :                 return(false);
      51             : 
      52     4079453 :         return(strncasecmp_m(s1,s2,n)==0);
      53             : }
      54             : 
      55             : /**
      56             :  Skip past a string in a buffer. Buffer may not be
      57             :  null terminated. end_ptr points to the first byte after
      58             :  then end of the buffer.
      59             : **/
      60             : 
      61        1685 : char *skip_string(const char *base, size_t len, char *buf)
      62             : {
      63        1685 :         const char *end_ptr = base + len;
      64             : 
      65        1685 :         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
      66           0 :                 return NULL;
      67             :         }
      68             : 
      69             :         /* Skip the string */
      70       20636 :         while (*buf) {
      71       18951 :                 buf++;
      72       18951 :                 if (buf >= end_ptr) {
      73           0 :                         return NULL;
      74             :                 }
      75             :         }
      76             :         /* Skip the '\0' */
      77        1685 :         buf++;
      78        1685 :         return buf;
      79             : }
      80             : 
      81             : /**
      82             :  Count the number of characters in a string. Normally this will
      83             :  be the same as the number of bytes in a string for single byte strings,
      84             :  but will be different for multibyte.
      85             : **/
      86             : 
      87           6 : size_t str_charnum(const char *s)
      88             : {
      89           0 :         size_t ret, converted_size;
      90           6 :         smb_ucs2_t *tmpbuf2 = NULL;
      91           6 :         if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
      92           0 :                 return 0;
      93             :         }
      94           6 :         ret = strlen_w(tmpbuf2);
      95           6 :         TALLOC_FREE(tmpbuf2);
      96           6 :         return ret;
      97             : }
      98             : 
      99     3242559 : bool trim_char(char *s,char cfront,char cback)
     100             : {
     101     3242559 :         bool ret = false;
     102       37105 :         char *ep;
     103     3242559 :         char *fp = s;
     104             : 
     105             :         /* Ignore null or empty strings. */
     106     3242559 :         if (!s || (s[0] == '\0'))
     107     1295900 :                 return false;
     108             : 
     109     1932718 :         if (cfront) {
     110     1926035 :                 while (*fp && *fp == cfront)
     111         150 :                         fp++;
     112     1925885 :                 if (!*fp) {
     113             :                         /* We ate the string. */
     114           4 :                         s[0] = '\0';
     115           4 :                         return true;
     116             :                 }
     117     1925881 :                 if (fp != s)
     118          18 :                         ret = true;
     119             :         }
     120             : 
     121     1932714 :         ep = fp + strlen(fp) - 1;
     122     1932714 :         if (cback) {
     123             :                 /* Attempt ascii only. Bail for mb strings. */
     124     1950417 :                 while ((ep >= fp) && (*ep == cback)) {
     125       17721 :                         ret = true;
     126       17721 :                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
     127             :                                 /* Could be mb... bail back to tim_string. */
     128           0 :                                 char fs[2], bs[2];
     129           0 :                                 if (cfront) {
     130           0 :                                         fs[0] = cfront;
     131           0 :                                         fs[1] = '\0';
     132             :                                 }
     133           0 :                                 bs[0] = cback;
     134           0 :                                 bs[1] = '\0';
     135           0 :                                 return trim_string(s, cfront ? fs : NULL, bs);
     136             :                         } else {
     137       17721 :                                 ep--;
     138             :                         }
     139             :                 }
     140     1932696 :                 if (ep < fp) {
     141             :                         /* We ate the string. */
     142           0 :                         s[0] = '\0';
     143           0 :                         return true;
     144             :                 }
     145             :         }
     146             : 
     147     1932714 :         ep[1] = '\0';
     148     1932714 :         memmove(s, fp, ep-fp+2);
     149     1932714 :         return ret;
     150             : }
     151             : 
     152             : /**
     153             :  Check if a string is part of a list.
     154             : **/
     155             : 
     156       32027 : bool in_list(const char *s, const char *list, bool casesensitive)
     157             : {
     158       32027 :         char *tok = NULL;
     159       32027 :         bool ret = false;
     160         176 :         TALLOC_CTX *frame;
     161             : 
     162       32027 :         if (!list) {
     163         952 :                 return false;
     164             :         }
     165             : 
     166       31075 :         frame = talloc_stackframe();
     167       31075 :         while (next_token_talloc(frame, &list, &tok,LIST_SEP)) {
     168           0 :                 if (casesensitive) {
     169           0 :                         if (strcmp(tok,s) == 0) {
     170           0 :                                 ret = true;
     171           0 :                                 break;
     172             :                         }
     173             :                 } else {
     174           0 :                         if (strcasecmp_m(tok,s) == 0) {
     175           0 :                                 ret = true;
     176           0 :                                 break;
     177             :                         }
     178             :                 }
     179             :         }
     180       31075 :         TALLOC_FREE(frame);
     181       30899 :         return ret;
     182             : }
     183             : 
     184             : /**
     185             :  Truncate a string at a specified length.
     186             : **/
     187             : 
     188         746 : char *string_truncate(char *s, unsigned int length)
     189             : {
     190         746 :         if (s && strlen(s) > length)
     191           0 :                 s[length] = 0;
     192         746 :         return s;
     193             : }
     194             : 
     195             : 
     196             : /***********************************************************************
     197             :  Return the equivalent of doing strrchr 'n' times - always going
     198             :  backwards.
     199             : ***********************************************************************/
     200             : 
     201           0 : char *strnrchr_m(const char *s, char c, unsigned int n)
     202             : {
     203           0 :         smb_ucs2_t *ws = NULL;
     204           0 :         char *s2 = NULL;
     205           0 :         smb_ucs2_t *p;
     206           0 :         char *ret;
     207           0 :         size_t converted_size;
     208             : 
     209           0 :         if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
     210             :                 /* Too hard to try and get right. */
     211           0 :                 return NULL;
     212             :         }
     213           0 :         p = strnrchr_w(ws, UCS2_CHAR(c), n);
     214           0 :         if (!p) {
     215           0 :                 TALLOC_FREE(ws);
     216           0 :                 return NULL;
     217             :         }
     218           0 :         *p = 0;
     219           0 :         if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
     220           0 :                 TALLOC_FREE(ws);
     221             :                 /* Too hard to try and get right. */
     222           0 :                 return NULL;
     223             :         }
     224           0 :         ret = discard_const_p(char, (s+strlen(s2)));
     225           0 :         TALLOC_FREE(ws);
     226           0 :         TALLOC_FREE(s2);
     227           0 :         return ret;
     228             : }
     229             : 
     230           0 : static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
     231             : {
     232           0 :         size_t size;
     233           0 :         smb_ucs2_t *buffer = NULL;
     234           0 :         bool ret;
     235             : 
     236           0 :         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
     237             :                                    (void **)(void *)&buffer, &size))
     238             :         {
     239           0 :                 return false;
     240             :         }
     241           0 :         if (!strlower_w(buffer) && (dest == src)) {
     242           0 :                 TALLOC_FREE(buffer);
     243           0 :                 return true;
     244             :         }
     245           0 :         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
     246           0 :         TALLOC_FREE(buffer);
     247           0 :         return ret;
     248             : }
     249             : 
     250             : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
     251             : 
     252             : /**
     253             :  Convert a string to lower case.
     254             : **/
     255             : _PUBLIC_ void strlower_m(char *s)
     256             : {
     257             :         char *d;
     258             :         struct smb_iconv_handle *iconv_handle;
     259             : 
     260             :         iconv_handle = get_iconv_handle();
     261             : 
     262             :         d = s;
     263             : 
     264             :         while (*s) {
     265             :                 size_t c_size, c_size2;
     266             :                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
     267             :                 c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
     268             :                 if (c_size2 > c_size) {
     269             :                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
     270             :                                  c, tolower_m(c), (int)c_size, (int)c_size2));
     271             :                         smb_panic("codepoint expansion in strlower_m\n");
     272             :                 }
     273             :                 s += c_size;
     274             :                 d += c_size2;
     275             :         }
     276             :         *d = 0;
     277             : }
     278             : 
     279             : #endif
     280             : 
     281             : /**
     282             :  Convert a string to lower case.
     283             : **/
     284             : 
     285     4843200 : bool strlower_m(char *s)
     286             : {
     287        6209 :         size_t len;
     288        6209 :         int errno_save;
     289     4843200 :         bool ret = false;
     290             : 
     291             :         /* this is quite a common operation, so we want it to be
     292             :            fast. We optimise for the ascii case, knowing that all our
     293             :            supported multi-byte character sets are ascii-compatible
     294             :            (ie. they match for the first 128 chars) */
     295             : 
     296    55703266 :         while (*s && !(((unsigned char)s[0]) & 0x80)) {
     297    50860066 :                 *s = tolower_m((unsigned char)*s);
     298    50860066 :                 s++;
     299             :         }
     300             : 
     301     4843200 :         if (!*s)
     302     4836991 :                 return true;
     303             : 
     304             :         /* I assume that lowercased string takes the same number of bytes
     305             :          * as source string even in UTF-8 encoding. (VIV) */
     306           0 :         len = strlen(s) + 1;
     307           0 :         errno_save = errno;
     308           0 :         errno = 0;
     309           0 :         ret = unix_strlower(s,len,s,len);
     310             :         /* Catch mb conversion errors that may not terminate. */
     311           0 :         if (errno) {
     312           0 :                 s[len-1] = '\0';
     313             :         }
     314           0 :         errno = errno_save;
     315           0 :         return ret;
     316             : }
     317             : 
     318          44 : static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
     319             : {
     320           0 :         size_t size;
     321           0 :         smb_ucs2_t *buffer;
     322           0 :         bool ret;
     323             : 
     324          44 :         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
     325          40 :                 return false;
     326             :         }
     327             : 
     328           4 :         if (!strupper_w(buffer) && (dest == src)) {
     329           4 :                 TALLOC_FREE(buffer);
     330           4 :                 return true;
     331             :         }
     332             : 
     333           0 :         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
     334           0 :         TALLOC_FREE(buffer);
     335           0 :         return ret;
     336             : }
     337             : 
     338             : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
     339             : 
     340             : /**
     341             :  Convert a string to UPPER case.
     342             : **/
     343             : _PUBLIC_ void strupper_m(char *s)
     344             : {
     345             :         char *d;
     346             :         struct smb_iconv_handle *iconv_handle;
     347             : 
     348             :         iconv_handle = get_iconv_handle();
     349             : 
     350             :         d = s;
     351             : 
     352             :         while (*s) {
     353             :                 size_t c_size, c_size2;
     354             :                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
     355             :                 c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
     356             :                 if (c_size2 > c_size) {
     357             :                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
     358             :                                  c, toupper_m(c), (int)c_size, (int)c_size2));
     359             :                         smb_panic("codepoint expansion in strupper_m\n");
     360             :                 }
     361             :                 s += c_size;
     362             :                 d += c_size2;
     363             :         }
     364             :         *d = 0;
     365             : }
     366             : 
     367             : #endif
     368             : 
     369             : /**
     370             :  Convert a string to upper case.
     371             : **/
     372             : 
     373     7852362 : bool strupper_m(char *s)
     374             : {
     375        6700 :         size_t len;
     376     7852362 :         bool ret = false;
     377             : 
     378             :         /* this is quite a common operation, so we want it to be
     379             :            fast. We optimise for the ascii case, knowing that all our
     380             :            supported multi-byte character sets are ascii-compatible
     381             :            (ie. they match for the first 128 chars) */
     382             : 
     383   328829468 :         while (*s && !(((unsigned char)s[0]) & 0x80)) {
     384   320977106 :                 *s = toupper_ascii_fast_table[(unsigned char)s[0]];
     385   320977106 :                 s++;
     386             :         }
     387             : 
     388     7852362 :         if (!*s)
     389     7845618 :                 return true;
     390             : 
     391             :         /* I assume that uppercased string takes the same number of bytes
     392             :          * as source string even in multibyte encoding. (VIV) */
     393          44 :         len = strlen(s) + 1;
     394          44 :         ret = unix_strupper(s,len,s,len);
     395             :         /* Catch mb conversion errors that may not terminate. */
     396          44 :         if (!ret) {
     397          40 :                 s[len-1] = '\0';
     398             :         }
     399          44 :         return ret;
     400             : }
     401             : 
     402             : /**
     403             :  Just a typesafety wrapper for snprintf into a fstring.
     404             : **/
     405             : 
     406     2170119 : int fstr_sprintf(fstring s, const char *fmt, ...)
     407             : {
     408       18259 :         va_list ap;
     409       18259 :         int ret;
     410             : 
     411     2170119 :         va_start(ap, fmt);
     412     2170119 :         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
     413     2170119 :         va_end(ap);
     414     2170119 :         return ret;
     415             : }
     416             : 
     417             : /* read a SMB_BIG_UINT from a string */
     418        5948 : uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
     419             : {
     420             : 
     421        5948 :         uint64_t val = (uint64_t)-1;
     422        5948 :         const char *p = nptr;
     423             : 
     424        5948 :         if (!p) {
     425           0 :                 if (entptr) {
     426           0 :                         *entptr = p;
     427             :                 }
     428           0 :                 return val;
     429             :         }
     430             : 
     431        5948 :         while (*p && isspace(*p))
     432           0 :                 p++;
     433             : 
     434        5948 :         sscanf(p,"%"SCNu64,&val);
     435        5948 :         if (entptr) {
     436        8540 :                 while (*p && isdigit(*p))
     437        3024 :                         p++;
     438        5516 :                 *entptr = p;
     439             :         }
     440             : 
     441        5948 :         return val;
     442             : }
     443             : 
     444             : /* Convert a size specification to a count of bytes. We accept the following
     445             :  * suffixes:
     446             :  *          bytes if there is no suffix
     447             :  *      kK  kibibytes
     448             :  *      mM  mebibytes
     449             :  *      gG  gibibytes
     450             :  *      tT  tibibytes
     451             :  *      pP  whatever the ISO name for petabytes is
     452             :  *
     453             :  *  Returns 0 if the string can't be converted.
     454             :  */
     455          24 : uint64_t conv_str_size(const char * str)
     456             : {
     457           0 :         uint64_t lval;
     458           0 :         char *end;
     459          24 :         int error = 0;
     460             : 
     461          24 :         if (str == NULL || *str == '\0') {
     462          16 :                 return 0;
     463             :         }
     464             : 
     465           8 :         lval = smb_strtoull(str, &end, 10, &error, SMB_STR_STANDARD);
     466             : 
     467           8 :         if (error != 0) {
     468           0 :                 return 0;
     469             :         }
     470             : 
     471           8 :         if (*end == '\0') {
     472           0 :                 return lval;
     473             :         }
     474             : 
     475           8 :         if (strwicmp(end, "K") == 0) {
     476           8 :                 lval *= 1024ULL;
     477           0 :         } else if (strwicmp(end, "M") == 0) {
     478           0 :                 lval *= (1024ULL * 1024ULL);
     479           0 :         } else if (strwicmp(end, "G") == 0) {
     480           0 :                 lval *= (1024ULL * 1024ULL *
     481             :                          1024ULL);
     482           0 :         } else if (strwicmp(end, "T") == 0) {
     483           0 :                 lval *= (1024ULL * 1024ULL *
     484             :                          1024ULL * 1024ULL);
     485           0 :         } else if (strwicmp(end, "P") == 0) {
     486           0 :                 lval *= (1024ULL * 1024ULL *
     487             :                          1024ULL * 1024ULL *
     488             :                          1024ULL);
     489             :         } else {
     490           0 :                 return 0;
     491             :         }
     492             : 
     493           8 :         return lval;
     494             : }
     495             : 
     496      134768 : char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
     497             : {
     498        2010 :         va_list ap;
     499        2010 :         char *ret;
     500             : 
     501      134768 :         va_start(ap, fmt);
     502      134768 :         ret = talloc_vasprintf(t, fmt, ap);
     503      134768 :         va_end(ap);
     504             : 
     505      134768 :         if (ret == NULL) {
     506           0 :                 return NULL;
     507             :         }
     508      134768 :         if (!strupper_m(ret)) {
     509           0 :                 TALLOC_FREE(ret);
     510           0 :                 return NULL;
     511             :         }
     512      132758 :         return ret;
     513             : }
     514             : 
     515          28 : char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
     516             : {
     517           0 :         va_list ap;
     518           0 :         char *ret;
     519             : 
     520          28 :         va_start(ap, fmt);
     521          28 :         ret = talloc_vasprintf(t, fmt, ap);
     522          28 :         va_end(ap);
     523             : 
     524          28 :         if (ret == NULL) {
     525           0 :                 return NULL;
     526             :         }
     527          28 :         if (!strlower_m(ret)) {
     528           0 :                 TALLOC_FREE(ret);
     529           0 :                 return NULL;
     530             :         }
     531          28 :         return ret;
     532             : }
     533             : 
     534             : 
     535             : /********************************************************************
     536             :  Check a string for any occurrences of a specified list of invalid
     537             :  characters.
     538             : ********************************************************************/
     539             : 
     540         998 : bool validate_net_name( const char *name,
     541             :                 const char *invalid_chars,
     542             :                 int max_len)
     543             : {
     544           0 :         int i;
     545             : 
     546         998 :         if (!name) {
     547           0 :                 return false;
     548             :         }
     549             : 
     550       36172 :         for ( i=0; i<max_len && name[i]; i++ ) {
     551             :                 /* fail if strchr_m() finds one of the invalid characters */
     552       35286 :                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
     553         112 :                         return false;
     554             :                 }
     555             :         }
     556             : 
     557         886 :         return true;
     558             : }
     559             : 
     560             : 
     561             : /*******************************************************************
     562             :  Add a shell escape character '\' to any character not in a known list
     563             :  of characters. UNIX charset format.
     564             : *******************************************************************/
     565             : 
     566             : #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
     567             : #define INSIDE_DQUOTE_LIST "$`\n\"\\"
     568             : 
     569        1004 : char *escape_shell_string(const char *src)
     570             : {
     571        1004 :         size_t srclen = strlen(src);
     572        1004 :         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
     573        1004 :         char *dest = ret;
     574        1004 :         bool in_s_quote = false;
     575        1004 :         bool in_d_quote = false;
     576        1004 :         bool next_escaped = false;
     577             : 
     578        1004 :         if (!ret) {
     579           0 :                 return NULL;
     580             :         }
     581             : 
     582      229490 :         while (*src) {
     583           0 :                 size_t c_size;
     584      228486 :                 codepoint_t c = next_codepoint(src, &c_size);
     585             : 
     586      228486 :                 if (c == INVALID_CODEPOINT) {
     587           0 :                         SAFE_FREE(ret);
     588           0 :                         return NULL;
     589             :                 }
     590             : 
     591      228486 :                 if (c_size > 1) {
     592           0 :                         memcpy(dest, src, c_size);
     593           0 :                         src += c_size;
     594           0 :                         dest += c_size;
     595           0 :                         next_escaped = false;
     596        8676 :                         continue;
     597             :                 }
     598             : 
     599             :                 /*
     600             :                  * Deal with backslash escaped state.
     601             :                  * This only lasts for one character.
     602             :                  */
     603             : 
     604      228486 :                 if (next_escaped) {
     605          50 :                         *dest++ = *src++;
     606          50 :                         next_escaped = false;
     607          50 :                         continue;
     608             :                 }
     609             : 
     610             :                 /*
     611             :                  * Deal with single quote state. The
     612             :                  * only thing we care about is exiting
     613             :                  * this state.
     614             :                  */
     615             : 
     616      228436 :                 if (in_s_quote) {
     617           0 :                         if (*src == '\'') {
     618           0 :                                 in_s_quote = false;
     619             :                         }
     620           0 :                         *dest++ = *src++;
     621           0 :                         continue;
     622             :                 }
     623             : 
     624             :                 /*
     625             :                  * Deal with double quote state. The most
     626             :                  * complex state. We must cope with \, meaning
     627             :                  * possibly escape next char (depending what it
     628             :                  * is), ", meaning exit this state, and possibly
     629             :                  * add an \ escape to any unprotected character
     630             :                  * (listed in INSIDE_DQUOTE_LIST).
     631             :                  */
     632             : 
     633      228436 :                 if (in_d_quote) {
     634        8115 :                         if (*src == '\\') {
     635             :                                 /*
     636             :                                  * Next character might be escaped.
     637             :                                  * We have to peek. Inside double
     638             :                                  * quotes only INSIDE_DQUOTE_LIST
     639             :                                  * characters are escaped by a \.
     640             :                                  */
     641             : 
     642           0 :                                 char nextchar;
     643             : 
     644         100 :                                 c = next_codepoint(&src[1], &c_size);
     645         100 :                                 if (c == INVALID_CODEPOINT) {
     646           0 :                                         SAFE_FREE(ret);
     647           0 :                                         return NULL;
     648             :                                 }
     649         100 :                                 if (c_size > 1) {
     650             :                                         /*
     651             :                                          * Don't escape the next char.
     652             :                                          * Just copy the \.
     653             :                                          */
     654           0 :                                         *dest++ = *src++;
     655           0 :                                         continue;
     656             :                                 }
     657             : 
     658         100 :                                 nextchar = src[1];
     659             : 
     660         100 :                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
     661             :                                                         (int)nextchar)) {
     662          50 :                                         next_escaped = true;
     663             :                                 }
     664         100 :                                 *dest++ = *src++;
     665         100 :                                 continue;
     666             :                         }
     667             : 
     668        8015 :                         if (*src == '\"') {
     669             :                                 /* Exit double quote state. */
     670         511 :                                 in_d_quote = false;
     671         511 :                                 *dest++ = *src++;
     672         511 :                                 continue;
     673             :                         }
     674             : 
     675             :                         /*
     676             :                          * We know the character isn't \ or ",
     677             :                          * so escape it if it's any of the other
     678             :                          * possible unprotected characters.
     679             :                          */
     680             : 
     681        7504 :                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
     682           0 :                                 *dest++ = '\\';
     683             :                         }
     684        7504 :                         *dest++ = *src++;
     685        7504 :                         continue;
     686             :                 }
     687             : 
     688             :                 /*
     689             :                  * From here to the end of the loop we're
     690             :                  * not in the single or double quote state.
     691             :                  */
     692             : 
     693      220321 :                 if (*src == '\\') {
     694             :                         /* Next character must be escaped. */
     695           0 :                         next_escaped = true;
     696           0 :                         *dest++ = *src++;
     697           0 :                         continue;
     698             :                 }
     699             : 
     700      220321 :                 if (*src == '\'') {
     701             :                         /* Go into single quote state. */
     702           0 :                         in_s_quote = true;
     703           0 :                         *dest++ = *src++;
     704           0 :                         continue;
     705             :                 }
     706             : 
     707      220321 :                 if (*src == '\"') {
     708             :                         /* Go into double quote state. */
     709         511 :                         in_d_quote = true;
     710         511 :                         *dest++ = *src++;
     711         511 :                         continue;
     712             :                 }
     713             : 
     714             :                 /* Check if we need to escape the character. */
     715             : 
     716      219810 :                 if (!strchr(INCLUDE_LIST, (int)*src)) {
     717       13955 :                         *dest++ = '\\';
     718             :                 }
     719      219810 :                 *dest++ = *src++;
     720             :         }
     721        1004 :         *dest++ = '\0';
     722        1004 :         return ret;
     723             : }
     724             : 
     725             : /*
     726             :  * This routine improves performance for operations temporarily acting on a
     727             :  * full path. It is equivalent to the much more expensive
     728             :  *
     729             :  * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
     730             :  *
     731             :  * This actually does make a difference in metadata-heavy workloads (i.e. the
     732             :  * "standard" client.txt nbench run.
     733             :  */
     734             : 
     735     4822624 : ssize_t full_path_tos(const char *dir, const char *name,
     736             :                       char *tmpbuf, size_t tmpbuf_len,
     737             :                       char **pdst, char **to_free)
     738             : {
     739       29015 :         size_t dirlen, namelen, len;
     740       29015 :         char *dst;
     741             : 
     742     4822624 :         dirlen = strlen(dir);
     743     4822624 :         namelen = strlen(name);
     744     4822624 :         len = dirlen + namelen + 1;
     745             : 
     746     4822624 :         if (len < tmpbuf_len) {
     747     4822620 :                 dst = tmpbuf;
     748     4822620 :                 *to_free = NULL;
     749             :         } else {
     750           4 :                 dst = talloc_array(talloc_tos(), char, len+1);
     751           4 :                 if (dst == NULL) {
     752           0 :                         return -1;
     753             :                 }
     754           4 :                 *to_free = dst;
     755             :         }
     756             : 
     757     4822624 :         memcpy(dst, dir, dirlen);
     758     4822624 :         dst[dirlen] = '/';
     759     4822624 :         memcpy(dst+dirlen+1, name, namelen+1);
     760     4822624 :         *pdst = dst;
     761     4822624 :         return len;
     762             : }

Generated by: LCOV version 1.14