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

Generated by: LCOV version 1.13