root/lib/util/util_str.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. safe_strcpy
  2. safe_strcat
  3. valgrind_strlen
  4. str_format_nbt_domain
  5. add_string_to_array
  6. conv_str_bool
  7. conv_str_size
  8. conv_str_u64
  9. strwicmp
  10. strequal
  11. ucs2_align
  12. string_replace

   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     2005
   9    
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 3 of the License, or
  13    (at your option) any later version.
  14    
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19    
  20    You should have received a copy of the GNU General Public License
  21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  22 */
  23 
  24 #include "includes.h"
  25 #include "system/locale.h"
  26 #undef strncasecmp
  27 #undef strcasemp
  28 
  29 /**
  30  * @file
  31  * @brief String utilities.
  32  **/
  33 
  34 /**
  35  Safe string copy into a known length string. maxlength does not
  36  include the terminating zero.
  37 **/
  38 _PUBLIC_ char *safe_strcpy(char *dest,const char *src, size_t maxlength)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         size_t len;
  41 
  42         if (!dest) {
  43                 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
  44                 return NULL;
  45         }
  46 
  47 #ifdef DEVELOPER
  48         /* We intentionally write out at the extremity of the destination
  49          * string.  If the destination is too short (e.g. pstrcpy into mallocd
  50          * or fstring) then this should cause an error under a memory
  51          * checker. */
  52         dest[maxlength] = '\0';
  53         if (PTR_DIFF(&len, dest) > 0) {  /* check if destination is on the stack, ok if so */
  54                 log_suspicious_usage("safe_strcpy", src);
  55         }
  56 #endif
  57 
  58         if (!src) {
  59                 *dest = 0;
  60                 return dest;
  61         }  
  62 
  63         len = strlen(src);
  64 
  65         if (len > maxlength) {
  66                 DEBUG(0,("ERROR: string overflow by %u (%u - %u) in safe_strcpy [%.50s]\n",
  67                          (uint_t)(len-maxlength), (unsigned)len, (unsigned)maxlength, src));
  68                 len = maxlength;
  69         }
  70       
  71         memmove(dest, src, len);
  72         dest[len] = 0;
  73         return dest;
  74 }  
  75 
  76 /**
  77  Safe string cat into a string. maxlength does not
  78  include the terminating zero.
  79 **/
  80 _PUBLIC_ char *safe_strcat(char *dest, const char *src, size_t maxlength)
     /* [<][>][^][v][top][bottom][index][help] */
  81 {
  82         size_t src_len, dest_len;
  83 
  84         if (!dest) {
  85                 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
  86                 return NULL;
  87         }
  88 
  89         if (!src)
  90                 return dest;
  91         
  92 #ifdef DEVELOPER
  93         if (PTR_DIFF(&src_len, dest) > 0) {  /* check if destination is on the stack, ok if so */
  94                 log_suspicious_usage("safe_strcat", src);
  95         }
  96 #endif
  97         src_len = strlen(src);
  98         dest_len = strlen(dest);
  99 
 100         if (src_len + dest_len > maxlength) {
 101                 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
 102                          (int)(src_len + dest_len - maxlength), src));
 103                 if (maxlength > dest_len) {
 104                         memcpy(&dest[dest_len], src, maxlength - dest_len);
 105                 }
 106                 dest[maxlength] = 0;
 107                 return NULL;
 108         }
 109         
 110         memcpy(&dest[dest_len], src, src_len);
 111         dest[dest_len + src_len] = 0;
 112         return dest;
 113 }
 114 
 115 #ifdef VALGRIND
 116 size_t valgrind_strlen(const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 117 {
 118         size_t count;
 119         for(count = 0; *s++; count++)
 120                 ;
 121         return count;
 122 }
 123 #endif
 124 
 125 
 126 /**
 127   format a string into length-prefixed dotted domain format, as used in NBT
 128   and in some ADS structures
 129 **/
 130 _PUBLIC_ const char *str_format_nbt_domain(TALLOC_CTX *mem_ctx, const char *s)
     /* [<][>][^][v][top][bottom][index][help] */
 131 {
 132         char *ret;
 133         int i;
 134         if (!s || !*s) {
 135                 return talloc_strdup(mem_ctx, "");
 136         }
 137         ret = talloc_array(mem_ctx, char, strlen(s)+2);
 138         if (!ret) {
 139                 return ret;
 140         }
 141         
 142         memcpy(ret+1, s, strlen(s)+1);
 143         ret[0] = '.';
 144 
 145         for (i=0;ret[i];i++) {
 146                 if (ret[i] == '.') {
 147                         char *p = strchr(ret+i+1, '.');
 148                         if (p) {
 149                                 ret[i] = p-(ret+i+1);
 150                         } else {
 151                                 ret[i] = strlen(ret+i+1);
 152                         }
 153                 }
 154         }
 155 
 156         talloc_set_name_const(ret, ret);
 157 
 158         return ret;
 159 }
 160 
 161 /**
 162  * Add a string to an array of strings.
 163  *
 164  * num should be a pointer to an integer that holds the current 
 165  * number of elements in strings. It will be updated by this function.
 166  */
 167 _PUBLIC_ bool add_string_to_array(TALLOC_CTX *mem_ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 168                          const char *str, const char ***strings, int *num)
 169 {
 170         char *dup_str = talloc_strdup(mem_ctx, str);
 171 
 172         *strings = talloc_realloc(mem_ctx,
 173                                     *strings,
 174                                     const char *, ((*num)+1));
 175 
 176         if ((*strings == NULL) || (dup_str == NULL))
 177                 return false;
 178 
 179         (*strings)[*num] = dup_str;
 180         *num += 1;
 181 
 182         return true;
 183 }
 184 
 185 /**
 186  * Parse a string containing a boolean value.
 187  *
 188  * val will be set to the read value.
 189  *
 190  * @retval true if a boolean value was parsed, false otherwise.
 191  */
 192 _PUBLIC_ bool conv_str_bool(const char * str, bool * val)
     /* [<][>][^][v][top][bottom][index][help] */
 193 {
 194         char *  end = NULL;
 195         long    lval;
 196 
 197         if (str == NULL || *str == '\0') {
 198                 return false;
 199         }
 200 
 201         lval = strtol(str, &end, 10 /* base */);
 202         if (end == NULL || *end != '\0' || end == str) {
 203                 return set_boolean(str, val);
 204         }
 205 
 206         *val = (lval) ? true : false;
 207         return true;
 208 }
 209 
 210 /**
 211  * Convert a size specification like 16K into an integral number of bytes. 
 212  **/
 213 _PUBLIC_ bool conv_str_size(const char * str, uint64_t * val)
     /* [<][>][^][v][top][bottom][index][help] */
 214 {
 215         char *              end = NULL;
 216         unsigned long long  lval;
 217 
 218         if (str == NULL || *str == '\0') {
 219                 return false;
 220         }
 221 
 222         lval = strtoull(str, &end, 10 /* base */);
 223         if (end == NULL || end == str) {
 224                 return false;
 225         }
 226 
 227         if (*end) {
 228                 if (strwicmp(end, "K") == 0) {
 229                         lval *= 1024ULL;
 230                 } else if (strwicmp(end, "M") == 0) {
 231                         lval *= (1024ULL * 1024ULL);
 232                 } else if (strwicmp(end, "G") == 0) {
 233                         lval *= (1024ULL * 1024ULL * 1024ULL);
 234                 } else if (strwicmp(end, "T") == 0) {
 235                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
 236                 } else if (strwicmp(end, "P") == 0) {
 237                         lval *= (1024ULL * 1024ULL * 1024ULL * 1024ULL * 1024ULL);
 238                 } else {
 239                         return false;
 240                 }
 241         }
 242 
 243         *val = (uint64_t)lval;
 244         return true;
 245 }
 246 
 247 /**
 248  * Parse a uint64_t value from a string
 249  *
 250  * val will be set to the value read.
 251  *
 252  * @retval true if parsing was successful, false otherwise
 253  */
 254 _PUBLIC_ bool conv_str_u64(const char * str, uint64_t * val)
     /* [<][>][^][v][top][bottom][index][help] */
 255 {
 256         char *              end = NULL;
 257         unsigned long long  lval;
 258 
 259         if (str == NULL || *str == '\0') {
 260                 return false;
 261         }
 262 
 263         lval = strtoull(str, &end, 10 /* base */);
 264         if (end == NULL || *end != '\0' || end == str) {
 265                 return false;
 266         }
 267 
 268         *val = (uint64_t)lval;
 269         return true;
 270 }
 271 
 272 /**
 273 Do a case-insensitive, whitespace-ignoring string compare.
 274 **/
 275 _PUBLIC_ int strwicmp(const char *psz1, const char *psz2)
     /* [<][>][^][v][top][bottom][index][help] */
 276 {
 277         /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
 278         /* appropriate value. */
 279         if (psz1 == psz2)
 280                 return (0);
 281         else if (psz1 == NULL)
 282                 return (-1);
 283         else if (psz2 == NULL)
 284                 return (1);
 285 
 286         /* sync the strings on first non-whitespace */
 287         while (1) {
 288                 while (isspace((int)*psz1))
 289                         psz1++;
 290                 while (isspace((int)*psz2))
 291                         psz2++;
 292                 if (toupper((unsigned char)*psz1) != toupper((unsigned char)*psz2) 
 293                     || *psz1 == '\0'
 294                     || *psz2 == '\0')
 295                         break;
 296                 psz1++;
 297                 psz2++;
 298         }
 299         return (*psz1 - *psz2);
 300 }
 301 
 302 /**
 303  * Compare 2 strings.
 304  *
 305  * @note The comparison is case-insensitive.
 306  **/
 307 _PUBLIC_ bool strequal(const char *s1, const char *s2)
     /* [<][>][^][v][top][bottom][index][help] */
 308 {
 309         if (s1 == s2)
 310                 return true;
 311         if (!s1 || !s2)
 312                 return false;
 313   
 314         return strcasecmp(s1,s2) == 0;
 315 }
 316 
 317 _PUBLIC_ size_t ucs2_align(const void *base_ptr, const void *p, int flags)
     /* [<][>][^][v][top][bottom][index][help] */
 318 {
 319         if (flags & (STR_NOALIGN|STR_ASCII))
 320                 return 0;
 321         return PTR_DIFF(p, base_ptr) & 1;
 322 }
 323 
 324 /**
 325  String replace.
 326 **/
 327 _PUBLIC_ void string_replace(char *s, char oldc, char newc)
     /* [<][>][^][v][top][bottom][index][help] */
 328 {
 329         while (*s) {
 330                 if (*s == oldc) *s = newc;
 331                 s++;
 332         }
 333 }
 334 
 335 

/* [<][>][^][v][top][bottom][index][help] */