Merge of 64-bit printf warning fixes.
[Samba/gebeck_regimport.git] / source3 / lib / util_str.c
blobb6025a362d3443fc128812fcd5d0830a9295abda
1 /*
2 Unix SMB/CIFS implementation.
3 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-2001
6 Copyright (C) Simo Sorce 2001-2002
7 Copyright (C) Martin Pool 2003
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 /**
27 * @file
28 * @brief String utilities.
29 **/
31 /**
32 * Get the next token from a string, return False if none found.
33 * Handles double-quotes.
35 * Based on a routine by GJC@VILLAGE.COM.
36 * Extensively modified by Andrew.Tridgell@anu.edu.au
37 **/
38 BOOL next_token(const char **ptr,char *buff, const char *sep, size_t bufsize)
40 char *s;
41 char *pbuf;
42 BOOL quoted;
43 size_t len=1;
45 if (!ptr)
46 return(False);
48 s = (char *)*ptr;
50 /* default to simple separators */
51 if (!sep)
52 sep = " \t\n\r";
54 /* find the first non sep char */
55 while (*s && strchr_m(sep,*s))
56 s++;
58 /* nothing left? */
59 if (! *s)
60 return(False);
62 /* copy over the token */
63 pbuf = buff;
64 for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
65 if (*s == '\"') {
66 quoted = !quoted;
67 } else {
68 len++;
69 *pbuf++ = *s;
73 *ptr = (*s) ? s+1 : s;
74 *pbuf = 0;
76 return(True);
79 /**
80 This is like next_token but is not re-entrant and "remembers" the first
81 parameter so you can pass NULL. This is useful for user interface code
82 but beware the fact that it is not re-entrant!
83 **/
85 static const char *last_ptr=NULL;
87 BOOL next_token_nr(const char **ptr,char *buff, const char *sep, size_t bufsize)
89 BOOL ret;
90 if (!ptr)
91 ptr = &last_ptr;
93 ret = next_token(ptr, buff, sep, bufsize);
94 last_ptr = *ptr;
95 return ret;
98 static uint16 tmpbuf[sizeof(pstring)];
100 void set_first_token(char *ptr)
102 last_ptr = ptr;
106 Convert list of tokens to array; dependent on above routine.
107 Uses last_ptr from above - bit of a hack.
110 char **toktocliplist(int *ctok, const char *sep)
112 char *s=(char *)last_ptr;
113 int ictok=0;
114 char **ret, **iret;
116 if (!sep)
117 sep = " \t\n\r";
119 while(*s && strchr_m(sep,*s))
120 s++;
122 /* nothing left? */
123 if (!*s)
124 return(NULL);
126 do {
127 ictok++;
128 while(*s && (!strchr_m(sep,*s)))
129 s++;
130 while(*s && strchr_m(sep,*s))
131 *s++=0;
132 } while(*s);
134 *ctok=ictok;
135 s=(char *)last_ptr;
137 if (!(ret=iret=malloc(ictok*sizeof(char *))))
138 return NULL;
140 while(ictok--) {
141 *iret++=s;
142 while(*s++)
144 while(!*s)
145 s++;
148 return ret;
152 * Case insensitive string compararison.
154 * iconv does not directly give us a way to compare strings in
155 * arbitrary unix character sets -- all we can is convert and then
156 * compare. This is expensive.
158 * As an optimization, we do a first pass that considers only the
159 * prefix of the strings that is entirely 7-bit. Within this, we
160 * check whether they have the same value.
162 * Hopefully this will often give the answer without needing to copy.
163 * In particular it should speed comparisons to literal ascii strings
164 * or comparisons of strings that are "obviously" different.
166 * If we find a non-ascii character we fall back to converting via
167 * iconv.
169 * This should never be slower than convering the whole thing, and
170 * often faster.
172 * A different optimization would be to compare for bitwise equality
173 * in the binary encoding. (It would be possible thought hairy to do
174 * both simultaneously.) But in that case if they turn out to be
175 * different, we'd need to restart the whole thing.
177 * Even better is to implement strcasecmp for each encoding and use a
178 * function pointer.
180 int StrCaseCmp(const char *s, const char *t)
183 const char * ps, * pt;
184 size_t size;
185 smb_ucs2_t *buffer_s, *buffer_t;
186 int ret;
188 for (ps = s, pt = t; ; ps++, pt++) {
189 char us, ut;
191 if (!*ps && !*pt)
192 return 0; /* both ended */
193 else if (!*ps)
194 return -1; /* s is a prefix */
195 else if (!*pt)
196 return +1; /* t is a prefix */
197 else if ((*ps & 0x80) || (*pt & 0x80))
198 /* not ascii anymore, do it the hard way from here on in */
199 break;
201 us = toupper(*ps);
202 ut = toupper(*pt);
203 if (us == ut)
204 continue;
205 else if (us < ut)
206 return -1;
207 else if (us > ut)
208 return +1;
211 size = push_ucs2_allocate(&buffer_s, s);
212 if (size == (size_t)-1) {
213 return strcmp(s, t);
214 /* Not quite the right answer, but finding the right one
215 under this failure case is expensive, and it's pretty close */
218 size = push_ucs2_allocate(&buffer_t, t);
219 if (size == (size_t)-1) {
220 SAFE_FREE(buffer_s);
221 return strcmp(s, t);
222 /* Not quite the right answer, but finding the right one
223 under this failure case is expensive, and it's pretty close */
226 ret = strcasecmp_w(buffer_s, buffer_t);
227 SAFE_FREE(buffer_s);
228 SAFE_FREE(buffer_t);
229 return ret;
234 Case insensitive string compararison, length limited.
236 int StrnCaseCmp(const char *s, const char *t, size_t n)
238 pstring buf1, buf2;
239 unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
240 unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
241 return strncmp(buf1,buf2,n);
245 * Compare 2 strings.
247 * @note The comparison is case-insensitive.
249 BOOL strequal(const char *s1, const char *s2)
251 if (s1 == s2)
252 return(True);
253 if (!s1 || !s2)
254 return(False);
256 return(StrCaseCmp(s1,s2)==0);
260 * Compare 2 strings up to and including the nth char.
262 * @note The comparison is case-insensitive.
264 BOOL strnequal(const char *s1,const char *s2,size_t n)
266 if (s1 == s2)
267 return(True);
268 if (!s1 || !s2 || !n)
269 return(False);
271 return(StrnCaseCmp(s1,s2,n)==0);
275 Compare 2 strings (case sensitive).
278 BOOL strcsequal(const char *s1,const char *s2)
280 if (s1 == s2)
281 return(True);
282 if (!s1 || !s2)
283 return(False);
285 return(strcmp(s1,s2)==0);
289 Do a case-insensitive, whitespace-ignoring string compare.
292 int strwicmp(const char *psz1, const char *psz2)
294 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
295 /* appropriate value. */
296 if (psz1 == psz2)
297 return (0);
298 else if (psz1 == NULL)
299 return (-1);
300 else if (psz2 == NULL)
301 return (1);
303 /* sync the strings on first non-whitespace */
304 while (1) {
305 while (isspace((int)*psz1))
306 psz1++;
307 while (isspace((int)*psz2))
308 psz2++;
309 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
310 || *psz2 == '\0')
311 break;
312 psz1++;
313 psz2++;
315 return (*psz1 - *psz2);
320 Convert a string to upper case, but don't modify it.
323 char *strupper_static(const char *s)
325 static pstring str;
327 pstrcpy(str, s);
328 strupper_m(str);
330 return str;
334 Convert a string to "normal" form.
337 void strnorm(char *s)
339 extern int case_default;
340 if (case_default == CASE_UPPER)
341 strupper_m(s);
342 else
343 strlower_m(s);
347 Check if a string is in "normal" case.
350 BOOL strisnormal(const char *s)
352 extern int case_default;
353 if (case_default == CASE_UPPER)
354 return(!strhaslower(s));
356 return(!strhasupper(s));
361 String replace.
362 NOTE: oldc and newc must be 7 bit characters
365 void string_replace(pstring s,char oldc,char newc)
367 unsigned char *p;
369 /* this is quite a common operation, so we want it to be
370 fast. We optimise for the ascii case, knowing that all our
371 supported multi-byte character sets are ascii-compatible
372 (ie. they match for the first 128 chars) */
374 for (p = (unsigned char *)s; *p; p++) {
375 if (*p & 0x80) /* mb string - slow path. */
376 break;
377 if (*p == oldc)
378 *p = newc;
381 if (!*p)
382 return;
384 /* Slow (mb) path. */
385 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
386 /* With compose characters we must restart from the beginning. JRA. */
387 p = s;
388 #endif
389 push_ucs2(NULL, tmpbuf, p, sizeof(tmpbuf), STR_TERMINATE);
390 string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
391 pull_ucs2(NULL, p, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
395 Skip past some strings in a buffer.
398 char *skip_string(char *buf,size_t n)
400 while (n--)
401 buf += strlen(buf) + 1;
402 return(buf);
406 Count the number of characters in a string. Normally this will
407 be the same as the number of bytes in a string for single byte strings,
408 but will be different for multibyte.
411 size_t str_charnum(const char *s)
413 uint16 tmpbuf2[sizeof(pstring)];
414 push_ucs2(NULL, tmpbuf2,s, sizeof(tmpbuf2), STR_TERMINATE);
415 return strlen_w(tmpbuf2);
419 Count the number of characters in a string. Normally this will
420 be the same as the number of bytes in a string for single byte strings,
421 but will be different for multibyte.
424 size_t str_ascii_charnum(const char *s)
426 pstring tmpbuf2;
427 push_ascii(tmpbuf2, s, sizeof(tmpbuf2), STR_TERMINATE);
428 return strlen(tmpbuf2);
431 BOOL trim_char(char *s,char cfront,char cback)
433 BOOL ret = False;
434 char *ep;
435 char *fp = s;
437 /* Ignore null or empty strings. */
438 if (!s || (s[0] == '\0'))
439 return False;
441 if (cfront) {
442 while (*fp && *fp == cfront)
443 fp++;
444 if (!*fp) {
445 /* We ate the string. */
446 s[0] = '\0';
447 return True;
449 if (fp != s)
450 ret = True;
453 ep = fp + strlen(fp) - 1;
454 if (cback) {
455 /* Attempt ascii only. Bail for mb strings. */
456 while ((ep >= fp) && (*ep == cback)) {
457 ret = True;
458 if ((ep > fp) && (((unsigned char)ep[-1]) & 0x80)) {
459 /* Could be mb... bail back to tim_string. */
460 char fs[2], bs[2];
461 if (cfront) {
462 fs[0] = cfront;
463 fs[1] = '\0';
465 bs[0] = cback;
466 bs[1] = '\0';
467 return trim_string(s, cfront ? fs : NULL, bs);
468 } else {
469 ep--;
472 if (ep < fp) {
473 /* We ate the string. */
474 s[0] = '\0';
475 return True;
479 ep[1] = '\0';
480 memmove(s, fp, ep-fp+2);
481 return ret;
485 Trim the specified elements off the front and back of a string.
488 BOOL trim_string(char *s,const char *front,const char *back)
490 BOOL ret = False;
491 size_t front_len;
492 size_t back_len;
493 size_t len;
495 /* Ignore null or empty strings. */
496 if (!s || (s[0] == '\0'))
497 return False;
499 front_len = front? strlen(front) : 0;
500 back_len = back? strlen(back) : 0;
502 len = strlen(s);
504 if (front_len) {
505 while (len && strncmp(s, front, front_len)==0) {
506 /* Must use memmove here as src & dest can
507 * easily overlap. Found by valgrind. JRA. */
508 memmove(s, s+front_len, (len-front_len)+1);
509 len -= front_len;
510 ret=True;
514 if (back_len) {
515 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
516 s[len-back_len]='\0';
517 len -= back_len;
518 ret=True;
521 return ret;
525 Does a string have any uppercase chars in it?
528 BOOL strhasupper(const char *s)
530 smb_ucs2_t *ptr;
531 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
532 for(ptr=tmpbuf;*ptr;ptr++)
533 if(isupper_w(*ptr))
534 return True;
535 return(False);
539 Does a string have any lowercase chars in it?
542 BOOL strhaslower(const char *s)
544 smb_ucs2_t *ptr;
545 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
546 for(ptr=tmpbuf;*ptr;ptr++)
547 if(islower_w(*ptr))
548 return True;
549 return(False);
553 Find the number of 'c' chars in a string
556 size_t count_chars(const char *s,char c)
558 smb_ucs2_t *ptr;
559 int count;
560 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
561 for(count=0,ptr=tmpbuf;*ptr;ptr++)
562 if(*ptr==UCS2_CHAR(c))
563 count++;
564 return(count);
568 Safe string copy into a known length string. maxlength does not
569 include the terminating zero.
572 char *safe_strcpy_fn(const char *fn, int line, char *dest,const char *src, size_t maxlength)
574 size_t len;
576 if (!dest) {
577 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
578 return NULL;
581 #ifdef DEVELOPER
582 clobber_region(fn,line,dest, maxlength+1);
583 #endif
585 if (!src) {
586 *dest = 0;
587 return dest;
590 len = strnlen(src, maxlength+1);
592 if (len > maxlength) {
593 DEBUG(0,("ERROR: string overflow by %lu (%lu - %lu) in safe_strcpy [%.50s]\n",
594 (unsigned long)(len-maxlength), (unsigned long)len,
595 (unsigned long)maxlength, src));
596 len = maxlength;
599 memmove(dest, src, len);
600 dest[len] = 0;
601 return dest;
605 Safe string cat into a string. maxlength does not
606 include the terminating zero.
608 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
610 size_t src_len, dest_len;
612 if (!dest) {
613 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
614 return NULL;
617 if (!src)
618 return dest;
620 src_len = strnlen(src, maxlength + 1);
621 dest_len = strnlen(dest, maxlength + 1);
623 #ifdef DEVELOPER
624 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
625 #endif
627 if (src_len + dest_len > maxlength) {
628 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
629 (int)(src_len + dest_len - maxlength), src));
630 if (maxlength > dest_len) {
631 memcpy(&dest[dest_len], src, maxlength - dest_len);
633 dest[maxlength] = 0;
634 return NULL;
637 memcpy(&dest[dest_len], src, src_len);
638 dest[dest_len + src_len] = 0;
639 return dest;
643 Paranoid strcpy into a buffer of given length (includes terminating
644 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
645 and replaces with '_'. Deliberately does *NOT* check for multibyte
646 characters. Don't change it !
648 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
650 size_t len, i;
652 #ifdef DEVELOPER
653 clobber_region(fn, line, dest, maxlength);
654 #endif
656 if (!dest) {
657 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
658 return NULL;
661 if (!src) {
662 *dest = 0;
663 return dest;
666 len = strlen(src);
667 if (len >= maxlength)
668 len = maxlength - 1;
670 if (!other_safe_chars)
671 other_safe_chars = "";
673 for(i = 0; i < len; i++) {
674 int val = (src[i] & 0xff);
675 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
676 dest[i] = src[i];
677 else
678 dest[i] = '_';
681 dest[i] = '\0';
683 return dest;
687 Like strncpy but always null terminates. Make sure there is room!
688 The variable n should always be one less than the available size.
690 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
692 char *d = dest;
694 #ifdef DEVELOPER
695 clobber_region(fn, line, dest, n+1);
696 #endif
698 if (!dest)
699 return(NULL);
701 if (!src) {
702 *dest = 0;
703 return(dest);
706 while (n-- && (*d = *src)) {
707 d++;
708 src++;
711 *d = 0;
712 return(dest);
715 #if 0
717 Like strncpy but copies up to the character marker. always null terminates.
718 returns a pointer to the character marker in the source string (src).
721 static char *strncpyn(char *dest, const char *src, size_t n, char c)
723 char *p;
724 size_t str_len;
726 #ifdef DEVELOPER
727 clobber_region(dest, n+1);
728 #endif
729 p = strchr_m(src, c);
730 if (p == NULL) {
731 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
732 return NULL;
735 str_len = PTR_DIFF(p, src);
736 strncpy(dest, src, MIN(n, str_len));
737 dest[str_len] = '\0';
739 return p;
741 #endif
744 Routine to get hex characters and turn them into a 16 byte array.
745 the array can be variable length, and any non-hex-numeric
746 characters are skipped. "0xnn" or "0Xnn" is specially catered
747 for.
749 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
753 size_t strhex_to_str(char *p, size_t len, const char *strhex)
755 size_t i;
756 size_t num_chars = 0;
757 unsigned char lonybble, hinybble;
758 const char *hexchars = "0123456789ABCDEF";
759 char *p1 = NULL, *p2 = NULL;
761 for (i = 0; i < len && strhex[i] != 0; i++) {
762 if (strnequal(hexchars, "0x", 2)) {
763 i++; /* skip two chars */
764 continue;
767 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
768 break;
770 i++; /* next hex digit */
772 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
773 break;
775 /* get the two nybbles */
776 hinybble = PTR_DIFF(p1, hexchars);
777 lonybble = PTR_DIFF(p2, hexchars);
779 p[num_chars] = (hinybble << 4) | lonybble;
780 num_chars++;
782 p1 = NULL;
783 p2 = NULL;
785 return num_chars;
789 * Routine to print a buffer as HEX digits, into an allocated string.
792 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
794 int i;
795 char *hex_buffer;
797 *out_hex_buffer = smb_xmalloc((len*2)+1);
798 hex_buffer = *out_hex_buffer;
800 for (i = 0; i < len; i++)
801 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
805 Check if a string is part of a list.
808 BOOL in_list(char *s,char *list,BOOL casesensitive)
810 pstring tok;
811 const char *p=list;
813 if (!list)
814 return(False);
816 while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
817 if (casesensitive) {
818 if (strcmp(tok,s) == 0)
819 return(True);
820 } else {
821 if (StrCaseCmp(tok,s) == 0)
822 return(True);
825 return(False);
828 /* this is used to prevent lots of mallocs of size 1 */
829 static char *null_string = NULL;
832 Set a string value, allocing the space for the string
835 static BOOL string_init(char **dest,const char *src)
837 size_t l;
838 if (!src)
839 src = "";
841 l = strlen(src);
843 if (l == 0) {
844 if (!null_string) {
845 if((null_string = (char *)malloc(1)) == NULL) {
846 DEBUG(0,("string_init: malloc fail for null_string.\n"));
847 return False;
849 *null_string = 0;
851 *dest = null_string;
852 } else {
853 (*dest) = strdup(src);
854 if ((*dest) == NULL) {
855 DEBUG(0,("Out of memory in string_init\n"));
856 return False;
859 return(True);
863 Free a string value.
866 void string_free(char **s)
868 if (!s || !(*s))
869 return;
870 if (*s == null_string)
871 *s = NULL;
872 SAFE_FREE(*s);
876 Set a string value, deallocating any existing space, and allocing the space
877 for the string
880 BOOL string_set(char **dest,const char *src)
882 string_free(dest);
883 return(string_init(dest,src));
887 Substitute a string for a pattern in another string. Make sure there is
888 enough room!
890 This routine looks for pattern in s and replaces it with
891 insert. It may do multiple replacements.
893 Any of " ; ' $ or ` in the insert string are replaced with _
894 if len==0 then the string cannot be extended. This is different from the old
895 use of len==0 which was for no length checks to be done.
898 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
900 char *p;
901 ssize_t ls,lp,li, i;
903 if (!insert || !pattern || !*pattern || !s)
904 return;
906 ls = (ssize_t)strlen(s);
907 lp = (ssize_t)strlen(pattern);
908 li = (ssize_t)strlen(insert);
910 if (len == 0)
911 len = ls + 1; /* len is number of *bytes* */
913 while (lp <= ls && (p = strstr(s,pattern))) {
914 if (ls + (li-lp) >= len) {
915 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
916 (int)(ls + (li-lp) - len),
917 pattern, (int)len));
918 break;
920 if (li != lp) {
921 memmove(p+li,p+lp,strlen(p+lp)+1);
923 for (i=0;i<li;i++) {
924 switch (insert[i]) {
925 case '`':
926 case '"':
927 case '\'':
928 case ';':
929 case '$':
930 case '%':
931 case '\r':
932 case '\n':
933 p[i] = '_';
934 break;
935 default:
936 p[i] = insert[i];
939 s = p + li;
940 ls += (li-lp);
944 void fstring_sub(char *s,const char *pattern,const char *insert)
946 string_sub(s, pattern, insert, sizeof(fstring));
949 void pstring_sub(char *s,const char *pattern,const char *insert)
951 string_sub(s, pattern, insert, sizeof(pstring));
955 Similar to string_sub, but it will accept only allocated strings
956 and may realloc them so pay attention at what you pass on no
957 pointers inside strings, no pstrings or const may be passed
958 as string.
961 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
963 char *p, *in;
964 char *s;
965 ssize_t ls,lp,li,ld, i;
967 if (!insert || !pattern || !*pattern || !string || !*string)
968 return NULL;
970 s = string;
972 in = strdup(insert);
973 if (!in) {
974 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
975 return NULL;
977 ls = (ssize_t)strlen(s);
978 lp = (ssize_t)strlen(pattern);
979 li = (ssize_t)strlen(insert);
980 ld = li - lp;
981 for (i=0;i<li;i++) {
982 switch (in[i]) {
983 case '`':
984 case '"':
985 case '\'':
986 case ';':
987 case '$':
988 case '%':
989 case '\r':
990 case '\n':
991 in[i] = '_';
992 default:
993 /* ok */
994 break;
998 while ((p = strstr(s,pattern))) {
999 if (ld > 0) {
1000 int offset = PTR_DIFF(s,string);
1001 char *t = Realloc(string, ls + ld + 1);
1002 if (!t) {
1003 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1004 SAFE_FREE(in);
1005 return NULL;
1007 string = t;
1008 p = t + offset + (p - s);
1010 if (li != lp) {
1011 memmove(p+li,p+lp,strlen(p+lp)+1);
1013 memcpy(p, in, li);
1014 s = p + li;
1015 ls += ld;
1017 SAFE_FREE(in);
1018 return string;
1022 Similar to string_sub() but allows for any character to be substituted.
1023 Use with caution!
1024 if len==0 then the string cannot be extended. This is different from the old
1025 use of len==0 which was for no length checks to be done.
1028 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1030 char *p;
1031 ssize_t ls,lp,li;
1033 if (!insert || !pattern || !s)
1034 return;
1036 ls = (ssize_t)strlen(s);
1037 lp = (ssize_t)strlen(pattern);
1038 li = (ssize_t)strlen(insert);
1040 if (!*pattern)
1041 return;
1043 if (len == 0)
1044 len = ls + 1; /* len is number of *bytes* */
1046 while (lp <= ls && (p = strstr(s,pattern))) {
1047 if (ls + (li-lp) >= len) {
1048 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
1049 (int)(ls + (li-lp) - len),
1050 pattern, (int)len));
1051 break;
1053 if (li != lp) {
1054 memmove(p+li,p+lp,strlen(p+lp)+1);
1056 memcpy(p, insert, li);
1057 s = p + li;
1058 ls += (li-lp);
1063 Similar to all_string_sub but for unicode strings.
1064 Return a new allocated unicode string.
1065 similar to string_sub() but allows for any character to be substituted.
1066 Use with caution!
1069 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
1070 const smb_ucs2_t *insert)
1072 smb_ucs2_t *r, *rp;
1073 const smb_ucs2_t *sp;
1074 size_t lr, lp, li, lt;
1076 if (!insert || !pattern || !*pattern || !s)
1077 return NULL;
1079 lt = (size_t)strlen_w(s);
1080 lp = (size_t)strlen_w(pattern);
1081 li = (size_t)strlen_w(insert);
1083 if (li > lp) {
1084 const smb_ucs2_t *st = s;
1085 int ld = li - lp;
1086 while ((sp = strstr_w(st, pattern))) {
1087 st = sp + lp;
1088 lt += ld;
1092 r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
1093 if (!r) {
1094 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1095 return NULL;
1098 while ((sp = strstr_w(s, pattern))) {
1099 memcpy(rp, s, (sp - s));
1100 rp += ((sp - s) / sizeof(smb_ucs2_t));
1101 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1102 s = sp + lp;
1103 rp += li;
1105 lr = ((rp - r) / sizeof(smb_ucs2_t));
1106 if (lr < lt) {
1107 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1108 rp += (lt - lr);
1110 *rp = 0;
1112 return r;
1115 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1116 const char *insert)
1118 wpstring p, i;
1120 if (!insert || !pattern || !s)
1121 return NULL;
1122 push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1123 push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1124 return all_string_sub_w(s, p, i);
1127 #if 0
1129 Splits out the front and back at a separator.
1132 static void split_at_last_component(char *path, char *front, char sep, char *back)
1134 char *p = strrchr_m(path, sep);
1136 if (p != NULL)
1137 *p = 0;
1139 if (front != NULL)
1140 pstrcpy(front, path);
1142 if (p != NULL) {
1143 if (back != NULL)
1144 pstrcpy(back, p+1);
1145 *p = '\\';
1146 } else {
1147 if (back != NULL)
1148 back[0] = 0;
1151 #endif
1154 Write an octal as a string.
1157 const char *octal_string(int i)
1159 static char ret[64];
1160 if (i == -1)
1161 return "-1";
1162 slprintf(ret, sizeof(ret)-1, "0%o", i);
1163 return ret;
1168 Truncate a string at a specified length.
1171 char *string_truncate(char *s, unsigned int length)
1173 if (s && strlen(s) > length)
1174 s[length] = 0;
1175 return s;
1179 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1180 We convert via ucs2 for now.
1183 char *strchr_m(const char *src, char c)
1185 wpstring ws;
1186 pstring s2;
1187 smb_ucs2_t *p;
1188 const char *s;
1190 /* this is quite a common operation, so we want it to be
1191 fast. We optimise for the ascii case, knowing that all our
1192 supported multi-byte character sets are ascii-compatible
1193 (ie. they match for the first 128 chars) */
1195 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1196 if (*s == c)
1197 return s;
1200 if (!*s)
1201 return NULL;
1203 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1204 /* With compose characters we must restart from the beginning. JRA. */
1205 s = src;
1206 #endif
1208 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1209 p = strchr_w(ws, UCS2_CHAR(c));
1210 if (!p)
1211 return NULL;
1212 *p = 0;
1213 pull_ucs2_pstring(s2, ws);
1214 return (char *)(s+strlen(s2));
1217 char *strrchr_m(const char *s, char c)
1219 /* this is quite a common operation, so we want it to be
1220 fast. We optimise for the ascii case, knowing that all our
1221 supported multi-byte character sets are ascii-compatible
1222 (ie. they match for the first 128 chars). Also, in Samba
1223 we only search for ascii characters in 'c' and that
1224 in all mb character sets with a compound character
1225 containing c, if 'c' is not a match at position
1226 p, then p[-1] > 0x7f. JRA. */
1229 size_t len = strlen(s);
1230 const char *cp = s;
1231 BOOL got_mb = False;
1233 if (len == 0)
1234 return NULL;
1235 cp += (len - 1);
1236 do {
1237 if (c == *cp) {
1238 /* Could be a match. Part of a multibyte ? */
1239 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1240 /* Yep - go slow :-( */
1241 got_mb = True;
1242 break;
1244 /* No - we have a match ! */
1245 return cp;
1247 } while (cp-- != s);
1248 if (!got_mb)
1249 return NULL;
1252 /* String contained a non-ascii char. Slow path. */
1254 wpstring ws;
1255 pstring s2;
1256 smb_ucs2_t *p;
1258 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1259 p = strrchr_w(ws, UCS2_CHAR(c));
1260 if (!p)
1261 return NULL;
1262 *p = 0;
1263 pull_ucs2_pstring(s2, ws);
1264 return (char *)(s+strlen(s2));
1268 /***********************************************************************
1269 Return the equivalent of doing strrchr 'n' times - always going
1270 backwards.
1271 ***********************************************************************/
1273 char *strnrchr_m(const char *s, char c, unsigned int n)
1275 wpstring ws;
1276 pstring s2;
1277 smb_ucs2_t *p;
1279 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1280 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1281 if (!p)
1282 return NULL;
1283 *p = 0;
1284 pull_ucs2_pstring(s2, ws);
1285 return (char *)(s+strlen(s2));
1289 Convert a string to lower case.
1292 void strlower_m(char *s)
1294 /* this is quite a common operation, so we want it to be
1295 fast. We optimise for the ascii case, knowing that all our
1296 supported multi-byte character sets are ascii-compatible
1297 (ie. they match for the first 128 chars) */
1299 while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1300 *s = tolower((unsigned char)*s);
1301 s++;
1304 if (!*s)
1305 return;
1307 /* I assume that lowercased string takes the same number of bytes
1308 * as source string even in UTF-8 encoding. (VIV) */
1309 unix_strlower(s,strlen(s)+1,s,strlen(s)+1);
1313 Convert a string to upper case.
1316 void strupper_m(char *s)
1318 /* this is quite a common operation, so we want it to be
1319 fast. We optimise for the ascii case, knowing that all our
1320 supported multi-byte character sets are ascii-compatible
1321 (ie. they match for the first 128 chars) */
1323 while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1324 *s = toupper((unsigned char)*s);
1325 s++;
1328 if (!*s)
1329 return;
1331 /* I assume that lowercased string takes the same number of bytes
1332 * as source string even in multibyte encoding. (VIV) */
1333 unix_strupper(s,strlen(s)+1,s,strlen(s)+1);
1337 Return a RFC2254 binary string representation of a buffer.
1338 Used in LDAP filters.
1339 Caller must free.
1342 char *binary_string(char *buf, int len)
1344 char *s;
1345 int i, j;
1346 const char *hex = "0123456789ABCDEF";
1347 s = malloc(len * 3 + 1);
1348 if (!s)
1349 return NULL;
1350 for (j=i=0;i<len;i++) {
1351 s[j] = '\\';
1352 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1353 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1354 j += 3;
1356 s[j] = 0;
1357 return s;
1361 Just a typesafety wrapper for snprintf into a pstring.
1364 int pstr_sprintf(pstring s, const char *fmt, ...)
1366 va_list ap;
1367 int ret;
1369 va_start(ap, fmt);
1370 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1371 va_end(ap);
1372 return ret;
1377 Just a typesafety wrapper for snprintf into a fstring.
1380 int fstr_sprintf(fstring s, const char *fmt, ...)
1382 va_list ap;
1383 int ret;
1385 va_start(ap, fmt);
1386 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1387 va_end(ap);
1388 return ret;
1392 #ifndef HAVE_STRNDUP
1394 Some platforms don't have strndup.
1397 char *strndup(const char *s, size_t n)
1399 char *ret;
1401 n = strnlen(s, n);
1402 ret = malloc(n+1);
1403 if (!ret)
1404 return NULL;
1405 memcpy(ret, s, n);
1406 ret[n] = 0;
1408 return ret;
1410 #endif
1412 #ifndef HAVE_STRNLEN
1414 Some platforms don't have strnlen
1417 size_t strnlen(const char *s, size_t n)
1419 int i;
1420 for (i=0; s[i] && i<n; i++)
1421 /* noop */ ;
1422 return i;
1424 #endif
1427 List of Strings manipulation functions
1430 #define S_LIST_ABS 16 /* List Allocation Block Size */
1432 char **str_list_make(const char *string, const char *sep)
1434 char **list, **rlist;
1435 const char *str;
1436 char *s;
1437 int num, lsize;
1438 pstring tok;
1440 if (!string || !*string)
1441 return NULL;
1442 s = strdup(string);
1443 if (!s) {
1444 DEBUG(0,("str_list_make: Unable to allocate memory"));
1445 return NULL;
1447 if (!sep) sep = LIST_SEP;
1449 num = lsize = 0;
1450 list = NULL;
1452 str = s;
1453 while (next_token(&str, tok, sep, sizeof(tok))) {
1454 if (num == lsize) {
1455 lsize += S_LIST_ABS;
1456 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1457 if (!rlist) {
1458 DEBUG(0,("str_list_make: Unable to allocate memory"));
1459 str_list_free(&list);
1460 SAFE_FREE(s);
1461 return NULL;
1462 } else
1463 list = rlist;
1464 memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1467 list[num] = strdup(tok);
1468 if (!list[num]) {
1469 DEBUG(0,("str_list_make: Unable to allocate memory"));
1470 str_list_free(&list);
1471 SAFE_FREE(s);
1472 return NULL;
1475 num++;
1478 SAFE_FREE(s);
1479 return list;
1482 BOOL str_list_copy(char ***dest, const char **src)
1484 char **list, **rlist;
1485 int num, lsize;
1487 *dest = NULL;
1488 if (!src)
1489 return False;
1491 num = lsize = 0;
1492 list = NULL;
1494 while (src[num]) {
1495 if (num == lsize) {
1496 lsize += S_LIST_ABS;
1497 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1498 if (!rlist) {
1499 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1500 str_list_free(&list);
1501 return False;
1502 } else
1503 list = rlist;
1504 memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1507 list[num] = strdup(src[num]);
1508 if (!list[num]) {
1509 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1510 str_list_free(&list);
1511 return False;
1514 num++;
1517 *dest = list;
1518 return True;
1522 * Return true if all the elements of the list match exactly.
1524 BOOL str_list_compare(char **list1, char **list2)
1526 int num;
1528 if (!list1 || !list2)
1529 return (list1 == list2);
1531 for (num = 0; list1[num]; num++) {
1532 if (!list2[num])
1533 return False;
1534 if (!strcsequal(list1[num], list2[num]))
1535 return False;
1537 if (list2[num])
1538 return False; /* if list2 has more elements than list1 fail */
1540 return True;
1543 void str_list_free(char ***list)
1545 char **tlist;
1547 if (!list || !*list)
1548 return;
1549 tlist = *list;
1550 for(; *tlist; tlist++)
1551 SAFE_FREE(*tlist);
1552 SAFE_FREE(*list);
1555 /******************************************************************************
1556 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
1557 for the work
1558 *****************************************************************************/
1560 BOOL str_list_sub_basic( char **list, const char *smb_name )
1562 char *s, *tmpstr;
1564 while ( *list ) {
1565 s = *list;
1566 tmpstr = alloc_sub_basic(smb_name, s);
1567 if ( !tmpstr ) {
1568 DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1569 return False;
1572 *list = tmpstr;
1574 list++;
1577 return True;
1580 /******************************************************************************
1581 substritute a specific pattern in a string list
1582 *****************************************************************************/
1584 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1586 char *p, *s, *t;
1587 ssize_t ls, lp, li, ld, i, d;
1589 if (!list)
1590 return False;
1591 if (!pattern)
1592 return False;
1593 if (!insert)
1594 return False;
1596 lp = (ssize_t)strlen(pattern);
1597 li = (ssize_t)strlen(insert);
1598 ld = li -lp;
1600 while (*list) {
1601 s = *list;
1602 ls = (ssize_t)strlen(s);
1604 while ((p = strstr(s, pattern))) {
1605 t = *list;
1606 d = p -t;
1607 if (ld) {
1608 t = (char *) malloc(ls +ld +1);
1609 if (!t) {
1610 DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1611 return False;
1613 memcpy(t, *list, d);
1614 memcpy(t +d +li, p +lp, ls -d -lp +1);
1615 SAFE_FREE(*list);
1616 *list = t;
1617 ls += ld;
1618 s = t +d +li;
1621 for (i = 0; i < li; i++) {
1622 switch (insert[i]) {
1623 case '`':
1624 case '"':
1625 case '\'':
1626 case ';':
1627 case '$':
1628 case '%':
1629 case '\r':
1630 case '\n':
1631 t[d +i] = '_';
1632 break;
1633 default:
1634 t[d +i] = insert[i];
1640 list++;
1643 return True;
1647 #define IPSTR_LIST_SEP ","
1648 #define IPSTR_LIST_CHAR ','
1651 * Add ip string representation to ipstr list. Used also
1652 * as part of @function ipstr_list_make
1654 * @param ipstr_list pointer to string containing ip list;
1655 * MUST BE already allocated and IS reallocated if necessary
1656 * @param ipstr_size pointer to current size of ipstr_list (might be changed
1657 * as a result of reallocation)
1658 * @param ip IP address which is to be added to list
1659 * @return pointer to string appended with new ip and possibly
1660 * reallocated to new length
1663 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
1665 char* new_ipstr = NULL;
1667 /* arguments checking */
1668 if (!ipstr_list || !service) return NULL;
1670 /* attempt to convert ip to a string and append colon separator to it */
1671 if (*ipstr_list) {
1672 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
1673 inet_ntoa(service->ip), service->port);
1674 SAFE_FREE(*ipstr_list);
1675 } else {
1676 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
1678 *ipstr_list = new_ipstr;
1679 return *ipstr_list;
1684 * Allocate and initialise an ipstr list using ip adresses
1685 * passed as arguments.
1687 * @param ipstr_list pointer to string meant to be allocated and set
1688 * @param ip_list array of ip addresses to place in the list
1689 * @param ip_count number of addresses stored in ip_list
1690 * @return pointer to allocated ip string
1693 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
1695 int i;
1697 /* arguments checking */
1698 if (!ip_list && !ipstr_list) return 0;
1700 *ipstr_list = NULL;
1702 /* process ip addresses given as arguments */
1703 for (i = 0; i < ip_count; i++)
1704 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1706 return (*ipstr_list);
1711 * Parse given ip string list into array of ip addresses
1712 * (as ip_service structures)
1713 * e.g. 192.168.1.100:389,192.168.1.78, ...
1715 * @param ipstr ip string list to be parsed
1716 * @param ip_list pointer to array of ip addresses which is
1717 * allocated by this function and must be freed by caller
1718 * @return number of succesfully parsed addresses
1721 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
1723 fstring token_str;
1724 size_t count;
1725 int i;
1727 if (!ipstr_list || !ip_list)
1728 return 0;
1730 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1731 if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) {
1732 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
1733 return 0;
1736 for ( i=0;
1737 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count;
1738 i++ )
1740 struct in_addr addr;
1741 unsigned port = 0;
1742 char *p = strchr(token_str, ':');
1744 if (p) {
1745 *p = 0;
1746 port = atoi(p+1);
1749 /* convert single token to ip address */
1750 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1751 break;
1753 (*ip_list)[i].ip = addr;
1754 (*ip_list)[i].port = port;
1757 return count;
1762 * Safely free ip string list
1764 * @param ipstr_list ip string list to be freed
1767 void ipstr_list_free(char* ipstr_list)
1769 SAFE_FREE(ipstr_list);
1774 Unescape a URL encoded string, in place.
1777 void rfc1738_unescape(char *buf)
1779 char *p=buf;
1781 while ((p=strchr_m(p,'+')))
1782 *p = ' ';
1784 p = buf;
1786 while (p && *p && (p=strchr_m(p,'%'))) {
1787 int c1 = p[1];
1788 int c2 = p[2];
1790 if (c1 >= '0' && c1 <= '9')
1791 c1 = c1 - '0';
1792 else if (c1 >= 'A' && c1 <= 'F')
1793 c1 = 10 + c1 - 'A';
1794 else if (c1 >= 'a' && c1 <= 'f')
1795 c1 = 10 + c1 - 'a';
1796 else {p++; continue;}
1798 if (c2 >= '0' && c2 <= '9')
1799 c2 = c2 - '0';
1800 else if (c2 >= 'A' && c2 <= 'F')
1801 c2 = 10 + c2 - 'A';
1802 else if (c2 >= 'a' && c2 <= 'f')
1803 c2 = 10 + c2 - 'a';
1804 else {p++; continue;}
1806 *p = (c1<<4) | c2;
1808 memmove(p+1, p+3, strlen(p+3)+1);
1809 p++;
1813 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1816 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1818 DATA_BLOB base64_decode_data_blob(const char *s)
1820 int bit_offset, byte_offset, idx, i, n;
1821 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1822 unsigned char *d = decoded.data;
1823 char *p;
1825 n=i=0;
1827 while (*s && (p=strchr_m(b64,*s))) {
1828 idx = (int)(p - b64);
1829 byte_offset = (i*6)/8;
1830 bit_offset = (i*6)%8;
1831 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1832 if (bit_offset < 3) {
1833 d[byte_offset] |= (idx << (2-bit_offset));
1834 n = byte_offset+1;
1835 } else {
1836 d[byte_offset] |= (idx >> (bit_offset-2));
1837 d[byte_offset+1] = 0;
1838 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1839 n = byte_offset+2;
1841 s++; i++;
1844 /* fix up length */
1845 decoded.length = n;
1846 return decoded;
1850 * Decode a base64 string in-place - wrapper for the above
1852 void base64_decode_inplace(char *s)
1854 DATA_BLOB decoded = base64_decode_data_blob(s);
1855 memcpy(s, decoded.data, decoded.length);
1856 /* null terminate */
1857 s[decoded.length] = '\0';
1859 data_blob_free(&decoded);
1863 * Encode a base64 string into a malloc()ed string caller to free.
1865 *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1867 char * base64_encode_data_blob(DATA_BLOB data)
1869 int bits = 0;
1870 int char_count = 0;
1871 size_t out_cnt = 0;
1872 size_t len = data.length;
1873 size_t output_len = data.length * 2;
1874 char *result = malloc(output_len); /* get us plenty of space */
1876 while (len-- && out_cnt < (data.length * 2) - 5) {
1877 int c = (unsigned char) *(data.data++);
1878 bits += c;
1879 char_count++;
1880 if (char_count == 3) {
1881 result[out_cnt++] = b64[bits >> 18];
1882 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1883 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1884 result[out_cnt++] = b64[bits & 0x3f];
1885 bits = 0;
1886 char_count = 0;
1887 } else {
1888 bits <<= 8;
1891 if (char_count != 0) {
1892 bits <<= 16 - (8 * char_count);
1893 result[out_cnt++] = b64[bits >> 18];
1894 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1895 if (char_count == 1) {
1896 result[out_cnt++] = '=';
1897 result[out_cnt++] = '=';
1898 } else {
1899 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1900 result[out_cnt++] = '=';
1903 result[out_cnt] = '\0'; /* terminate */
1904 return result;
1907 /* read a SMB_BIG_UINT from a string */
1908 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1911 SMB_BIG_UINT val = -1;
1912 const char *p = nptr;
1914 while (p && *p && isspace(*p))
1915 p++;
1916 #ifdef LARGE_SMB_OFF_T
1917 sscanf(p,"%llu",&val);
1918 #else /* LARGE_SMB_OFF_T */
1919 sscanf(p,"%lu",&val);
1920 #endif /* LARGE_SMB_OFF_T */
1921 if (entptr) {
1922 while (p && *p && isdigit(*p))
1923 p++;
1924 *entptr = p;
1927 return val;