s3: utils: Don't directly manipulate errno inside strupper_m().
[samba.git] / source3 / lib / util_str.c
index 5755fc99a078b2b9bedb053287d17577789d9552..2b0830c2ff42cb56bf6b354c58d4fafbad1edf67 100644 (file)
@@ -23,6 +23,7 @@
 */
 
 #include "includes.h"
+#include "lib/param/loadparm.h"
 
 const char toupper_ascii_fast_table[128] = {
        0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf,
@@ -54,12 +55,12 @@ bool strnequal(const char *s1,const char *s2,size_t n)
  Convert a string to "normal" form.
 **/
 
-void strnorm(char *s, int case_default)
+bool strnorm(char *s, int case_default)
 {
        if (case_default == CASE_UPPER)
-               strupper_m(s);
+               return strupper_m(s);
        else
-               strlower_m(s);
+               return strlower_m(s);
 }
 
 /**
@@ -227,97 +228,6 @@ bool in_list(const char *s, const char *list, bool casesensitive)
        return ret;
 }
 
-void fstring_sub(char *s,const char *pattern,const char *insert)
-{
-       string_sub(s, pattern, insert, sizeof(fstring));
-}
-
-/**
- Similar to string_sub2, but it will accept only allocated strings
- and may realloc them so pay attention at what you pass on no
- pointers inside strings, no const may be passed
- as string.
-**/
-
-char *realloc_string_sub2(char *string,
-                       const char *pattern,
-                       const char *insert,
-                       bool remove_unsafe_characters,
-                       bool allow_trailing_dollar)
-{
-       char *p, *in;
-       char *s;
-       ssize_t ls,lp,li,ld, i;
-
-       if (!insert || !pattern || !*pattern || !string || !*string)
-               return NULL;
-
-       s = string;
-
-       in = SMB_STRDUP(insert);
-       if (!in) {
-               DEBUG(0, ("realloc_string_sub: out of memory!\n"));
-               return NULL;
-       }
-       ls = (ssize_t)strlen(s);
-       lp = (ssize_t)strlen(pattern);
-       li = (ssize_t)strlen(insert);
-       ld = li - lp;
-       for (i=0;i<li;i++) {
-               switch (in[i]) {
-                       case '$':
-                               /* allow a trailing $
-                                * (as in machine accounts) */
-                               if (allow_trailing_dollar && (i == li - 1 )) {
-                                       break;
-                               }
-                       case '`':
-                       case '"':
-                       case '\'':
-                       case ';':
-                       case '%':
-                       case '\r':
-                       case '\n':
-                               if ( remove_unsafe_characters ) {
-                                       in[i] = '_';
-                                       break;
-                               }
-                       default:
-                               /* ok */
-                               break;
-               }
-       }
-
-       while ((p = strstr_m(s,pattern))) {
-               if (ld > 0) {
-                       int offset = PTR_DIFF(s,string);
-                       string = (char *)SMB_REALLOC(string, ls + ld + 1);
-                       if (!string) {
-                               DEBUG(0, ("realloc_string_sub: "
-                                       "out of memory!\n"));
-                               SAFE_FREE(in);
-                               return NULL;
-                       }
-                       p = string + offset + (p - s);
-               }
-               if (li != lp) {
-                       memmove(p+li,p+lp,strlen(p+lp)+1);
-               }
-               memcpy(p, in, li);
-               s = p + li;
-               ls += ld;
-       }
-       SAFE_FREE(in);
-       return string;
-}
-
-char *realloc_string_sub(char *string,
-                       const char *pattern,
-                       const char *insert)
-{
-       return realloc_string_sub2(string, pattern, insert, true, false);
-}
-
 /*
  * Internal guts of talloc_string_sub and talloc_all_string_sub.
  * talloc version of string_sub2.
@@ -348,7 +258,7 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
 
        s = string;
 
-       in = SMB_STRDUP(insert);
+       in = talloc_strdup(mem_ctx, insert);
        if (!in) {
                DEBUG(0, ("talloc_string_sub2: ENOMEM\n"));
                return NULL;
@@ -391,7 +301,7 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
                        if (!string) {
                                DEBUG(0, ("talloc_string_sub: out of "
                                          "memory!\n"));
-                               SAFE_FREE(in);
+                               TALLOC_FREE(in);
                                return NULL;
                        }
                        p = string + offset + (p - s);
@@ -407,7 +317,7 @@ char *talloc_string_sub2(TALLOC_CTX *mem_ctx, const char *src,
                        break;
                }
        }
-       SAFE_FREE(in);
+       TALLOC_FREE(in);
        return string;
 }
 
@@ -504,11 +414,11 @@ static bool unix_strlower(const char *src, size_t srclen, char *dest, size_t des
        if (!convert_string_talloc(talloc_tos(), CH_UNIX, CH_UTF16LE, src, srclen,
                                   (void **)(void *)&buffer, &size))
        {
-               smb_panic("failed to create UCS2 buffer");
+               return false;
        }
        if (!strlower_w(buffer) && (dest == src)) {
                TALLOC_FREE(buffer);
-               return srclen;
+               return true;
        }
        ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
        TALLOC_FREE(buffer);
@@ -550,10 +460,11 @@ _PUBLIC_ void strlower_m(char *s)
  Convert a string to lower case.
 **/
 
-void strlower_m(char *s)
+bool strlower_m(char *s)
 {
        size_t len;
        int errno_save;
+       bool ret = false;
 
        /* this is quite a common operation, so we want it to be
           fast. We optimise for the ascii case, knowing that all our
@@ -561,23 +472,25 @@ void strlower_m(char *s)
           (ie. they match for the first 128 chars) */
 
        while (*s && !(((unsigned char)s[0]) & 0x80)) {
-               *s = tolower_ascii((unsigned char)*s);
+               *s = tolower_m((unsigned char)*s);
                s++;
        }
 
        if (!*s)
-               return;
+               return true;
 
        /* I assume that lowercased string takes the same number of bytes
         * as source string even in UTF-8 encoding. (VIV) */
        len = strlen(s) + 1;
        errno_save = errno;
        errno = 0;
-       unix_strlower(s,len,s,len);
+       ret = unix_strlower(s,len,s,len);
        /* Catch mb conversion errors that may not terminate. */
-       if (errno)
+       if (errno) {
                s[len-1] = '\0';
+       }
        errno = errno_save;
+       return ret;
 }
 
 static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t destlen)
@@ -587,12 +500,12 @@ static bool unix_strupper(const char *src, size_t srclen, char *dest, size_t des
        bool ret;
 
        if (!push_ucs2_talloc(talloc_tos(), &buffer, src, &size)) {
-               return (size_t)-1;
+               return false;
        }
 
        if (!strupper_w(buffer) && (dest == src)) {
                TALLOC_FREE(buffer);
-               return srclen;
+               return true;
        }
 
        ret = convert_string(CH_UTF16LE, CH_UNIX, buffer, size, dest, destlen, &size);
@@ -635,10 +548,10 @@ _PUBLIC_ void strupper_m(char *s)
  Convert a string to upper case.
 **/
 
-void strupper_m(char *s)
+bool strupper_m(char *s)
 {
        size_t len;
-       int errno_save;
+       bool ret = false;
 
        /* this is quite a common operation, so we want it to be
           fast. We optimise for the ascii case, knowing that all our
@@ -651,18 +564,17 @@ void strupper_m(char *s)
        }
 
        if (!*s)
-               return;
+               return true;
 
        /* I assume that lowercased string takes the same number of bytes
         * as source string even in multibyte encoding. (VIV) */
        len = strlen(s) + 1;
-       errno_save = errno;
-       errno = 0;
-       unix_strupper(s,len,s,len);
+       ret = unix_strupper(s,len,s,len);
        /* Catch mb conversion errors that may not terminate. */
-       if (errno)
+       if (!ret) {
                s[len-1] = '\0';
-       errno = errno_save;
+       }
+       return ret;
 }
 
 /**
@@ -686,35 +598,6 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
 
 #define S_LIST_ABS 16 /* List Allocation Block Size */
 
-/******************************************************************************
- version of standard_sub_basic() for string lists; uses talloc_sub_basic()
- for the work
- *****************************************************************************/
-
-bool str_list_sub_basic( char **list, const char *smb_name,
-                        const char *domain_name )
-{
-       TALLOC_CTX *ctx = list;
-       char *s, *tmpstr;
-
-       while ( *list ) {
-               s = *list;
-               tmpstr = talloc_sub_basic(ctx, smb_name, domain_name, s);
-               if ( !tmpstr ) {
-                       DEBUG(0,("str_list_sub_basic: "
-                               "alloc_sub_basic() return NULL!\n"));
-                       return false;
-               }
-
-               TALLOC_FREE(*list);
-               *list = tmpstr;
-
-               list++;
-       }
-
-       return true;
-}
-
 /******************************************************************************
  substitute a specific pattern in a string list
  *****************************************************************************/
@@ -744,7 +627,7 @@ bool str_list_substitute(char **list, const char *pattern, const char *insert)
                        t = *list;
                        d = p -t;
                        if (ld) {
-                               t = TALLOC_ARRAY(ctx, char, ls +ld +1);
+                               t = talloc_array(ctx, char, ls +ld +1);
                                if (!t) {
                                        DEBUG(0,("str_list_substitute: "
                                                "Unable to allocate memory"));
@@ -965,7 +848,7 @@ uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
        while (*p && isspace(*p))
                p++;
 
-       sscanf(p,"%"PRIu64,&val);
+       sscanf(p,"%"SCNu64,&val);
        if (entptr) {
                while (*p && isdigit(*p))
                        p++;
@@ -988,7 +871,6 @@ uint64_t STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
  */
 uint64_t conv_str_size(const char * str)
 {
-       uint64_t lval_orig;
         uint64_t lval;
        char * end;
 
@@ -1006,8 +888,6 @@ uint64_t conv_str_size(const char * str)
                return lval;
        }
 
-       lval_orig = lval;
-
        if (strwicmp(end, "K") == 0) {
                lval *= 1024ULL;
        } else if (strwicmp(end, "M") == 0) {
@@ -1049,7 +929,7 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
                if (*bufsize == 0)
                        *bufsize = 128;
 
-               *string = TALLOC_ARRAY(mem_ctx, char, *bufsize);
+               *string = talloc_array(mem_ctx, char, *bufsize);
                if (*string == NULL)
                        goto error;
        }
@@ -1071,7 +951,7 @@ void sprintf_append(TALLOC_CTX *mem_ctx, char **string, ssize_t *len,
        }
 
        if (increased) {
-               *string = TALLOC_REALLOC_ARRAY(mem_ctx, *string, char,
+               *string = talloc_realloc(mem_ctx, *string, char,
                                               *bufsize);
                if (*string == NULL) {
                        goto error;
@@ -1105,7 +985,11 @@ int asprintf_strupper_m(char **strp, const char *fmt, ...)
        if (ret == -1)
                return -1;
 
-       strupper_m(result);
+       if (!strupper_m(result)) {
+               SAFE_FREE(result);
+               return -1;
+       }
+
        *strp = result;
        return ret;
 }
@@ -1122,7 +1006,10 @@ char *talloc_asprintf_strupper_m(TALLOC_CTX *t, const char *fmt, ...)
        if (ret == NULL) {
                return NULL;
        }
-       strupper_m(ret);
+       if (!strupper_m(ret)) {
+               TALLOC_FREE(ret);
+               return NULL;
+       }
        return ret;
 }
 
@@ -1138,7 +1025,10 @@ char *talloc_asprintf_strlower_m(TALLOC_CTX *t, const char *fmt, ...)
        if (ret == NULL) {
                return NULL;
        }
-       strlower_m(ret);
+       if (!strlower_m(ret)) {
+               TALLOC_FREE(ret);
+               return NULL;
+       }
        return ret;
 }
 
@@ -1333,78 +1223,41 @@ char *escape_shell_string(const char *src)
        return ret;
 }
 
-/***************************************************
- str_list_make, v3 version. The v4 version does not
- look at quoted strings with embedded blanks, so
- do NOT merge this function please!
-***************************************************/
-
-#define S_LIST_ABS 16 /* List Allocation Block Size */
+/*
+ * This routine improves performance for operations temporarily acting on a
+ * full path. It is equivalent to the much more expensive
+ *
+ * talloc_asprintf(talloc_tos(), "%s/%s", dir, name)
+ *
+ * This actually does make a difference in metadata-heavy workloads (i.e. the
+ * "standard" client.txt nbench run.
+ */
 
-char **str_list_make_v3(TALLOC_CTX *mem_ctx, const char *string,
-       const char *sep)
+ssize_t full_path_tos(const char *dir, const char *name,
+                     char *tmpbuf, size_t tmpbuf_len,
+                     char **pdst, char **to_free)
 {
-       char **list;
-       const char *str;
-       char *s, *tok;
-       int num, lsize;
-
-       if (!string || !*string)
-               return NULL;
-
-       list = TALLOC_ARRAY(mem_ctx, char *, S_LIST_ABS+1);
-       if (list == NULL) {
-               return NULL;
-       }
-       lsize = S_LIST_ABS;
+       size_t dirlen, namelen, len;
+       char *dst;
 
-       s = talloc_strdup(list, string);
-       if (s == NULL) {
-               DEBUG(0,("str_list_make: Unable to allocate memory"));
-               TALLOC_FREE(list);
-               return NULL;
-       }
-       if (!sep) sep = LIST_SEP;
-
-       num = 0;
-       str = s;
-
-       while (next_token_talloc(list, &str, &tok, sep)) {
-
-               if (num == lsize) {
-                       char **tmp;
-
-                       lsize += S_LIST_ABS;
-
-                       tmp = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *,
-                                                  lsize + 1);
-                       if (tmp == NULL) {
-                               DEBUG(0,("str_list_make: "
-                                       "Unable to allocate memory"));
-                               TALLOC_FREE(list);
-                               return NULL;
-                       }
+       dirlen = strlen(dir);
+       namelen = strlen(name);
+       len = dirlen + namelen + 1;
 
-                       list = tmp;
-
-                       memset (&list[num], 0,
-                               ((sizeof(char**)) * (S_LIST_ABS +1)));
+       if (len < tmpbuf_len) {
+               dst = tmpbuf;
+               *to_free = NULL;
+       } else {
+               dst = talloc_array(talloc_tos(), char, len+1);
+               if (dst == NULL) {
+                       return -1;
                }
-
-               list[num] = tok;
-               num += 1;
+               *to_free = dst;
        }
 
-       list[num] = NULL;
-
-       TALLOC_FREE(s);
-       return list;
-}
-
-char *sanitize_username(TALLOC_CTX *mem_ctx, const char *username)
-{
-       fstring tmp;
-
-       alpha_strcpy(tmp, username, ". _-$", sizeof(tmp));
-       return talloc_strdup(mem_ctx, tmp);
+       memcpy(dst, dir, dirlen);
+       dst[dirlen] = '/';
+       memcpy(dst+dirlen+1, name, namelen+1);
+       *pdst = dst;
+       return len;
 }