LCOV - code coverage report
Current view: top level - source3/lib - util_str.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 138 295 46.8 %
Date: 2024-06-13 04:01:37 Functions: 14 20 70.0 %

          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      102592 : bool strnequal(const char *s1,const char *s2,size_t n)
      46             : {
      47      102592 :         if (s1 == s2)
      48           0 :                 return(true);
      49      102592 :         if (!s1 || !s2 || !n)
      50           0 :                 return(false);
      51             : 
      52      102592 :         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         321 : char *skip_string(const char *base, size_t len, char *buf)
      62             : {
      63         321 :         const char *end_ptr = base + len;
      64             : 
      65         321 :         if (end_ptr < base || !base || !buf || buf >= end_ptr) {
      66           0 :                 return NULL;
      67             :         }
      68             : 
      69             :         /* Skip the string */
      70        5092 :         while (*buf) {
      71        4575 :                 buf++;
      72        4575 :                 if (buf >= end_ptr) {
      73           0 :                         return NULL;
      74             :                 }
      75             :         }
      76             :         /* Skip the '\0' */
      77         321 :         buf++;
      78         321 :         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           2 : size_t str_charnum(const char *s)
      88             : {
      89             :         size_t ret, converted_size;
      90           2 :         smb_ucs2_t *tmpbuf2 = NULL;
      91           2 :         if (!push_ucs2_talloc(talloc_tos(), &tmpbuf2, s, &converted_size)) {
      92           0 :                 return 0;
      93             :         }
      94           2 :         ret = strlen_w(tmpbuf2);
      95           2 :         TALLOC_FREE(tmpbuf2);
      96           2 :         return ret;
      97             : }
      98             : 
      99      340856 : bool trim_char(char *s,char cfront,char cback)
     100             : {
     101      340856 :         bool ret = false;
     102             :         char *ep;
     103      340856 :         char *fp = s;
     104             : 
     105             :         /* Ignore null or empty strings. */
     106      340856 :         if (!s || (s[0] == '\0'))
     107      132120 :                 return false;
     108             : 
     109      208736 :         if (cfront) {
     110      347154 :                 while (*fp && *fp == cfront)
     111        1651 :                         fp++;
     112      207772 :                 if (!*fp) {
     113             :                         /* We ate the string. */
     114           0 :                         s[0] = '\0';
     115           0 :                         return true;
     116             :                 }
     117      207772 :                 if (fp != s)
     118        1651 :                         ret = true;
     119             :         }
     120             : 
     121      208736 :         ep = fp + strlen(fp) - 1;
     122      208736 :         if (cback) {
     123             :                 /* Attempt ascii only. Bail for mb strings. */
     124      352727 :                 while ((ep >= fp) && (*ep == cback)) {
     125        5759 :                         ret = true;
     126        5759 :                         if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
     127             :                                 /* Could be mb... bail back to tim_string. */
     128             :                                 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        5759 :                                 ep--;
     138             :                         }
     139             :                 }
     140      208736 :                 if (ep < fp) {
     141             :                         /* We ate the string. */
     142           0 :                         s[0] = '\0';
     143           0 :                         return true;
     144             :                 }
     145             :         }
     146             : 
     147      208736 :         ep[1] = '\0';
     148      208736 :         memmove(s, fp, ep-fp+2);
     149      208736 :         return ret;
     150             : }
     151             : 
     152             : /**
     153             :  Check if a string is part of a list.
     154             : **/
     155             : 
     156        4687 : bool in_list(const char *s, const char *list, bool casesensitive)
     157             : {
     158        4687 :         char *tok = NULL;
     159        4687 :         bool ret = false;
     160             :         TALLOC_CTX *frame;
     161             : 
     162        4687 :         if (!list) {
     163         400 :                 return false;
     164             :         }
     165             : 
     166        4287 :         frame = talloc_stackframe();
     167        4287 :         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        4287 :         TALLOC_FREE(frame);
     181        4287 :         return ret;
     182             : }
     183             : 
     184             : /**
     185             :  Write an octal as a string.
     186             : **/
     187             : 
     188           0 : char *octal_string(int i)
     189             : {
     190             :         char *result;
     191           0 :         if (i == -1) {
     192           0 :                 result = talloc_strdup(talloc_tos(), "-1");
     193             :         }
     194             :         else {
     195           0 :                 result = talloc_asprintf(talloc_tos(), "0%o", i);
     196             :         }
     197           0 :         SMB_ASSERT(result != NULL);
     198           0 :         return result;
     199             : }
     200             : 
     201             : 
     202             : /**
     203             :  Truncate a string at a specified length.
     204             : **/
     205             : 
     206         167 : char *string_truncate(char *s, unsigned int length)
     207             : {
     208         167 :         if (s && strlen(s) > length)
     209           0 :                 s[length] = 0;
     210         167 :         return s;
     211             : }
     212             : 
     213             : 
     214             : /***********************************************************************
     215             :  Return the equivalent of doing strrchr 'n' times - always going
     216             :  backwards.
     217             : ***********************************************************************/
     218             : 
     219           0 : char *strnrchr_m(const char *s, char c, unsigned int n)
     220             : {
     221           0 :         smb_ucs2_t *ws = NULL;
     222           0 :         char *s2 = NULL;
     223             :         smb_ucs2_t *p;
     224             :         char *ret;
     225             :         size_t converted_size;
     226             : 
     227           0 :         if (!push_ucs2_talloc(talloc_tos(), &ws, s, &converted_size)) {
     228             :                 /* Too hard to try and get right. */
     229           0 :                 return NULL;
     230             :         }
     231           0 :         p = strnrchr_w(ws, UCS2_CHAR(c), n);
     232           0 :         if (!p) {
     233           0 :                 TALLOC_FREE(ws);
     234           0 :                 return NULL;
     235             :         }
     236           0 :         *p = 0;
     237           0 :         if (!pull_ucs2_talloc(talloc_tos(), &s2, ws, &converted_size)) {
     238           0 :                 TALLOC_FREE(ws);
     239             :                 /* Too hard to try and get right. */
     240           0 :                 return NULL;
     241             :         }
     242           0 :         ret = discard_const_p(char, (s+strlen(s2)));
     243           0 :         TALLOC_FREE(ws);
     244           0 :         TALLOC_FREE(s2);
     245           0 :         return ret;
     246             : }
     247             : 
     248           0 : static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
     249             : {
     250             :         size_t size;
     251           0 :         smb_ucs2_t *buffer = NULL;
     252             :         bool ret;
     253             : 
     254           0 :         if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
     255             :                                    (void **)(void *)&buffer, &size))
     256             :         {
     257           0 :                 return false;
     258             :         }
     259           0 :         if (!strlower_w(buffer) && (dest == src)) {
     260           0 :                 TALLOC_FREE(buffer);
     261           0 :                 return true;
     262             :         }
     263           0 :         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
     264           0 :         TALLOC_FREE(buffer);
     265           0 :         return ret;
     266             : }
     267             : 
     268             : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
     269             : 
     270             : /**
     271             :  Convert a string to lower case.
     272             : **/
     273             : _PUBLIC_ void strlower_m(char *s)
     274             : {
     275             :         char *d;
     276             :         struct smb_iconv_handle *iconv_handle;
     277             : 
     278             :         iconv_handle = get_iconv_handle();
     279             : 
     280             :         d = s;
     281             : 
     282             :         while (*s) {
     283             :                 size_t c_size, c_size2;
     284             :                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
     285             :                 c_size2 = push_codepoint_handle(iconv_handle, d, tolower_m(c));
     286             :                 if (c_size2 > c_size) {
     287             :                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m\n",
     288             :                                  c, tolower_m(c), (int)c_size, (int)c_size2));
     289             :                         smb_panic("codepoint expansion in strlower_m\n");
     290             :                 }
     291             :                 s += c_size;
     292             :                 d += c_size2;
     293             :         }
     294             :         *d = 0;
     295             : }
     296             : 
     297             : #endif
     298             : 
     299             : /**
     300             :  Convert a string to lower case.
     301             : **/
     302             : 
     303      383185 : bool strlower_m(char *s)
     304             : {
     305             :         size_t len;
     306             :         int errno_save;
     307      383185 :         bool ret = false;
     308             : 
     309             :         /* this is quite a common operation, so we want it to be
     310             :            fast. We optimise for the ascii case, knowing that all our
     311             :            supported multi-byte character sets are ascii-compatible
     312             :            (ie. they match for the first 128 chars) */
     313             : 
     314     4880343 :         while (*s && !(((unsigned char)s[0]) & 0x80)) {
     315     4279404 :                 *s = tolower_m((unsigned char)*s);
     316     4279404 :                 s++;
     317             :         }
     318             : 
     319      383185 :         if (!*s)
     320      383185 :                 return true;
     321             : 
     322             :         /* I assume that lowercased string takes the same number of bytes
     323             :          * as source string even in UTF-8 encoding. (VIV) */
     324           0 :         len = strlen(s) + 1;
     325           0 :         errno_save = errno;
     326           0 :         errno = 0;
     327           0 :         ret = unix_strlower(s,len,s,len);
     328             :         /* Catch mb conversion errors that may not terminate. */
     329           0 :         if (errno) {
     330           0 :                 s[len-1] = '\0';
     331             :         }
     332           0 :         errno = errno_save;
     333           0 :         return ret;
     334             : }
     335             : 
     336           8 : static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
     337             : {
     338             :         size_t size;
     339             :         smb_ucs2_t *buffer;
     340             :         bool ret;
     341             : 
     342           8 :         if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
     343           8 :                 return false;
     344             :         }
     345             : 
     346           0 :         if (!strupper_w(buffer) && (dest == src)) {
     347           0 :                 TALLOC_FREE(buffer);
     348           0 :                 return true;
     349             :         }
     350             : 
     351           0 :         ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
     352           0 :         TALLOC_FREE(buffer);
     353           0 :         return ret;
     354             : }
     355             : 
     356             : #if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
     357             : 
     358             : /**
     359             :  Convert a string to UPPER case.
     360             : **/
     361             : _PUBLIC_ void strupper_m(char *s)
     362             : {
     363             :         char *d;
     364             :         struct smb_iconv_handle *iconv_handle;
     365             : 
     366             :         iconv_handle = get_iconv_handle();
     367             : 
     368             :         d = s;
     369             : 
     370             :         while (*s) {
     371             :                 size_t c_size, c_size2;
     372             :                 codepoint_t c = next_codepoint_handle(iconv_handle, s, &c_size);
     373             :                 c_size2 = push_codepoint_handle(iconv_handle, d, toupper_m(c));
     374             :                 if (c_size2 > c_size) {
     375             :                         DEBUG(0,("FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m\n",
     376             :                                  c, toupper_m(c), (int)c_size, (int)c_size2));
     377             :                         smb_panic("codepoint expansion in strupper_m\n");
     378             :                 }
     379             :                 s += c_size;
     380             :                 d += c_size2;
     381             :         }
     382             :         *d = 0;
     383             : }
     384             : 
     385             : #endif
     386             : 
     387             : /**
     388             :  Convert a string to upper case.
     389             : **/
     390             : 
     391      503282 : bool strupper_m(char *s)
     392             : {
     393             :         size_t len;
     394      503282 :         bool ret = false;
     395             : 
     396             :         /* this is quite a common operation, so we want it to be
     397             :            fast. We optimise for the ascii case, knowing that all our
     398             :            supported multi-byte character sets are ascii-compatible
     399             :            (ie. they match for the first 128 chars) */
     400             : 
     401    19872786 :         while (*s && !(((unsigned char)s[0]) & 0x80)) {
     402    19070286 :                 *s = toupper_ascii_fast_table[(unsigned char)s[0]];
     403    19070286 :                 s++;
     404             :         }
     405             : 
     406      503282 :         if (!*s)
     407      503274 :                 return true;
     408             : 
     409             :         /* I assume that uppercased string takes the same number of bytes
     410             :          * as source string even in multibyte encoding. (VIV) */
     411           8 :         len = strlen(s) + 1;
     412           8 :         ret = unix_strupper(s,len,s,len);
     413             :         /* Catch mb conversion errors that may not terminate. */
     414           8 :         if (!ret) {
     415           8 :                 s[len-1] = '\0';
     416             :         }
     417           8 :         return ret;
     418             : }
     419             : 
     420             : /**
     421             :  Just a typesafety wrapper for snprintf into a fstring.
     422             : **/
     423             : 
     424      108477 : int fstr_sprintf(fstring s, const char *fmt, ...)
     425             : {
     426             :         va_list ap;
     427             :         int ret;
     428             : 
     429      108477 :         va_start(ap, fmt);
     430      108477 :         ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
     431      108477 :         va_end(ap);
     432      108477 :         return ret;
     433             : }
     434             : 
     435             : /* read a SMB_BIG_UINT from a string */
     436           0 : uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
     437             : {
     438             : 
     439           0 :         uint64_t val = (uint64_t)-1;
     440           0 :         const char *p = nptr;
     441             : 
     442           0 :         if (!p) {
     443           0 :                 if (entptr) {
     444           0 :                         *entptr = p;
     445             :                 }
     446           0 :                 return val;
     447             :         }
     448             : 
     449           0 :         while (*p && isspace(*p))
     450           0 :                 p++;
     451             : 
     452           0 :         sscanf(p,"%"SCNu64,&val);
     453           0 :         if (entptr) {
     454           0 :                 while (*p && isdigit(*p))
     455           0 :                         p++;
     456           0 :                 *entptr = p;
     457             :         }
     458             : 
     459           0 :         return val;
     460             : }
     461             : 
     462             : /* Convert a size specification to a count of bytes. We accept the following
     463             :  * suffixes:
     464             :  *          bytes if there is no suffix
     465             :  *      kK  kibibytes
     466             :  *      mM  mebibytes
     467             :  *      gG  gibibytes
     468             :  *      tT  tibibytes
     469             :  *      pP  whatever the ISO name for petabytes is
     470             :  *
     471             :  *  Returns 0 if the string can't be converted.
     472             :  */
     473           0 : uint64_t conv_str_size(const char * str)
     474             : {
     475             :         uint64_t lval;
     476             :         char *end;
     477           0 :         int error = 0;
     478             : 
     479           0 :         if (str == NULL || *str == '\0') {
     480           0 :                 return 0;
     481             :         }
     482             : 
     483           0 :         lval = smb_strtoull(str, &end, 10, &error, SMB_STR_STANDARD);
     484             : 
     485           0 :         if (error != 0) {
     486           0 :                 return 0;
     487             :         }
     488             : 
     489           0 :         if (*end == '\0') {
     490           0 :                 return lval;
     491             :         }
     492             : 
     493           0 :         if (strwicmp(end, "K") == 0) {
     494           0 :                 lval *= 1024ULL;
     495           0 :         } else if (strwicmp(end, "M") == 0) {
     496           0 :                 lval *= (1024ULL * 1024ULL);
     497           0 :         } else if (strwicmp(end, "G") == 0) {
     498           0 :                 lval *= (1024ULL * 1024ULL *
     499             :                          1024ULL);
     500           0 :         } else if (strwicmp(end, "T") == 0) {
     501           0 :                 lval *= (1024ULL * 1024ULL *
     502             :                          1024ULL * 1024ULL);
     503           0 :         } else if (strwicmp(end, "P") == 0) {
     504           0 :                 lval *= (1024ULL * 1024ULL *
     505             :                          1024ULL * 1024ULL *
     506             :                          1024ULL);
     507             :         } else {
     508           0 :                 return 0;
     509             :         }
     510             : 
     511           0 :         return lval;
     512             : }
     513             : 
     514       26410 : char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
     515             : {
     516             :         va_list ap;
     517             :         char *ret;
     518             : 
     519       26410 :         va_start(ap, fmt);
     520       26410 :         ret = talloc_vasprintf(t, fmt, ap);
     521       26410 :         va_end(ap);
     522             : 
     523       26410 :         if (ret == NULL) {
     524           0 :                 return NULL;
     525             :         }
     526       26410 :         if (!strupper_m(ret)) {
     527           0 :                 TALLOC_FREE(ret);
     528           0 :                 return NULL;
     529             :         }
     530       26410 :         return ret;
     531             : }
     532             : 
     533           0 : char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
     534             : {
     535             :         va_list ap;
     536             :         char *ret;
     537             : 
     538           0 :         va_start(ap, fmt);
     539           0 :         ret = talloc_vasprintf(t, fmt, ap);
     540           0 :         va_end(ap);
     541             : 
     542           0 :         if (ret == NULL) {
     543           0 :                 return NULL;
     544             :         }
     545           0 :         if (!strlower_m(ret)) {
     546           0 :                 TALLOC_FREE(ret);
     547           0 :                 return NULL;
     548             :         }
     549           0 :         return ret;
     550             : }
     551             : 
     552             : 
     553             : /********************************************************************
     554             :  Check a string for any occurrences of a specified list of invalid
     555             :  characters.
     556             : ********************************************************************/
     557             : 
     558         382 : bool validate_net_name( const char *name,
     559             :                 const char *invalid_chars,
     560             :                 int max_len)
     561             : {
     562             :         int i;
     563             : 
     564         382 :         if (!name) {
     565           0 :                 return false;
     566             :         }
     567             : 
     568       17106 :         for ( i=0; i<max_len && name[i]; i++ ) {
     569             :                 /* fail if strchr_m() finds one of the invalid characters */
     570       16780 :                 if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
     571          56 :                         return false;
     572             :                 }
     573             :         }
     574             : 
     575         326 :         return true;
     576             : }
     577             : 
     578             : 
     579             : /*******************************************************************
     580             :  Add a shell escape character '\' to any character not in a known list
     581             :  of characters. UNIX charset format.
     582             : *******************************************************************/
     583             : 
     584             : #define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_/ \t.,"
     585             : #define INSIDE_DQUOTE_LIST "$`\n\"\\"
     586             : 
     587          12 : char *escape_shell_string(const char *src)
     588             : {
     589          12 :         size_t srclen = strlen(src);
     590          12 :         char *ret = SMB_MALLOC_ARRAY(char, (srclen * 2) + 1);
     591          12 :         char *dest = ret;
     592          12 :         bool in_s_quote = false;
     593          12 :         bool in_d_quote = false;
     594          12 :         bool next_escaped = false;
     595             : 
     596          12 :         if (!ret) {
     597           0 :                 return NULL;
     598             :         }
     599             : 
     600        2640 :         while (*src) {
     601             :                 size_t c_size;
     602        2620 :                 codepoint_t c = next_codepoint(src, &c_size);
     603             : 
     604        2620 :                 if (c == INVALID_CODEPOINT) {
     605           0 :                         SAFE_FREE(ret);
     606           0 :                         return NULL;
     607             :                 }
     608             : 
     609        2620 :                 if (c_size > 1) {
     610           0 :                         memcpy(dest, src, c_size);
     611           0 :                         src += c_size;
     612           0 :                         dest += c_size;
     613           0 :                         next_escaped = false;
     614         425 :                         continue;
     615             :                 }
     616             : 
     617             :                 /*
     618             :                  * Deal with backslash escaped state.
     619             :                  * This only lasts for one character.
     620             :                  */
     621             : 
     622        2620 :                 if (next_escaped) {
     623           0 :                         *dest++ = *src++;
     624           0 :                         next_escaped = false;
     625           0 :                         continue;
     626             :                 }
     627             : 
     628             :                 /*
     629             :                  * Deal with single quote state. The
     630             :                  * only thing we care about is exiting
     631             :                  * this state.
     632             :                  */
     633             : 
     634        2620 :                 if (in_s_quote) {
     635           0 :                         if (*src == '\'') {
     636           0 :                                 in_s_quote = false;
     637             :                         }
     638           0 :                         *dest++ = *src++;
     639           0 :                         continue;
     640             :                 }
     641             : 
     642             :                 /*
     643             :                  * Deal with double quote state. The most
     644             :                  * complex state. We must cope with \, meaning
     645             :                  * possibly escape next char (depending what it
     646             :                  * is), ", meaning exit this state, and possibly
     647             :                  * add an \ escape to any unprotected character
     648             :                  * (listed in INSIDE_DQUOTE_LIST).
     649             :                  */
     650             : 
     651        2620 :                 if (in_d_quote) {
     652         414 :                         if (*src == '\\') {
     653             :                                 /*
     654             :                                  * Next character might be escaped.
     655             :                                  * We have to peek. Inside double
     656             :                                  * quotes only INSIDE_DQUOTE_LIST
     657             :                                  * characters are escaped by a \.
     658             :                                  */
     659             : 
     660             :                                 char nextchar;
     661             : 
     662           0 :                                 c = next_codepoint(&src[1], &c_size);
     663           0 :                                 if (c == INVALID_CODEPOINT) {
     664           0 :                                         SAFE_FREE(ret);
     665           0 :                                         return NULL;
     666             :                                 }
     667           0 :                                 if (c_size > 1) {
     668             :                                         /*
     669             :                                          * Don't escape the next char.
     670             :                                          * Just copy the \.
     671             :                                          */
     672           0 :                                         *dest++ = *src++;
     673           0 :                                         continue;
     674             :                                 }
     675             : 
     676           0 :                                 nextchar = src[1];
     677             : 
     678           0 :                                 if (nextchar && strchr(INSIDE_DQUOTE_LIST,
     679             :                                                         (int)nextchar)) {
     680           0 :                                         next_escaped = true;
     681             :                                 }
     682           0 :                                 *dest++ = *src++;
     683           0 :                                 continue;
     684             :                         }
     685             : 
     686         414 :                         if (*src == '\"') {
     687             :                                 /* Exit double quote state. */
     688          11 :                                 in_d_quote = false;
     689          11 :                                 *dest++ = *src++;
     690          11 :                                 continue;
     691             :                         }
     692             : 
     693             :                         /*
     694             :                          * We know the character isn't \ or ",
     695             :                          * so escape it if it's any of the other
     696             :                          * possible unprotected characters.
     697             :                          */
     698             : 
     699         403 :                         if (strchr(INSIDE_DQUOTE_LIST, (int)*src)) {
     700           0 :                                 *dest++ = '\\';
     701             :                         }
     702         403 :                         *dest++ = *src++;
     703         403 :                         continue;
     704             :                 }
     705             : 
     706             :                 /*
     707             :                  * From here to the end of the loop we're
     708             :                  * not in the single or double quote state.
     709             :                  */
     710             : 
     711        2206 :                 if (*src == '\\') {
     712             :                         /* Next character must be escaped. */
     713           0 :                         next_escaped = true;
     714           0 :                         *dest++ = *src++;
     715           0 :                         continue;
     716             :                 }
     717             : 
     718        2206 :                 if (*src == '\'') {
     719             :                         /* Go into single quote state. */
     720           0 :                         in_s_quote = true;
     721           0 :                         *dest++ = *src++;
     722           0 :                         continue;
     723             :                 }
     724             : 
     725        2206 :                 if (*src == '\"') {
     726             :                         /* Go into double quote state. */
     727          11 :                         in_d_quote = true;
     728          11 :                         *dest++ = *src++;
     729          11 :                         continue;
     730             :                 }
     731             : 
     732             :                 /* Check if we need to escape the character. */
     733             : 
     734        2195 :                 if (!strchr(INCLUDE_LIST, (int)*src)) {
     735         137 :                         *dest++ = '\\';
     736             :                 }
     737        2195 :                 *dest++ = *src++;
     738             :         }
     739          12 :         *dest++ = '\0';
     740          12 :         return ret;
     741             : }
     742             : 
     743             : /*
     744             :  * This routine improves performance for operations temporarily acting on a
     745             :  * full path. It is equivalent to the much more expensive
     746             :  *
     747             :  * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
     748             :  *
     749             :  * This actually does make a difference in metadata-heavy workloads (i.e. the
     750             :  * "standard" client.txt nbench run.
     751             :  */
     752             : 
     753       93865 : ssize_t full_path_tos(const char *dir, const char *name,
     754             :                       char *tmpbuf, size_t tmpbuf_len,
     755             :                       char **pdst, char **to_free)
     756             : {
     757             :         size_t dirlen, namelen, len;
     758             :         char *dst;
     759             : 
     760       93865 :         dirlen = strlen(dir);
     761       93865 :         namelen = strlen(name);
     762       93865 :         len = dirlen + namelen + 1;
     763             : 
     764       93865 :         if (len < tmpbuf_len) {
     765       93865 :                 dst = tmpbuf;
     766       93865 :                 *to_free = NULL;
     767             :         } else {
     768           0 :                 dst = talloc_array(talloc_tos(), char, len+1);
     769           0 :                 if (dst == NULL) {
     770           0 :                         return -1;
     771             :                 }
     772           0 :                 *to_free = dst;
     773             :         }
     774             : 
     775       93865 :         memcpy(dst, dir, dirlen);
     776       93865 :         dst[dirlen] = '/';
     777       93865 :         memcpy(dst+dirlen+1, name, namelen+1);
     778       93865 :         *pdst = dst;
     779       93865 :         return len;
     780             : }

Generated by: LCOV version 1.13