If we have blacklisted mmap() try to avoid using it accidentally by
[Samba/gebeck_regimport.git] / source / lib / util_str.c
blob15ac1639a9ae153eea8ffc9207fde3978b2b5cb2
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 %u (%u - %u) in safe_strcpy [%.50s]\n",
594 (unsigned int)(len-maxlength), len, maxlength, src));
595 len = maxlength;
598 memmove(dest, src, len);
599 dest[len] = 0;
600 return dest;
604 Safe string cat into a string. maxlength does not
605 include the terminating zero.
607 char *safe_strcat_fn(const char *fn, int line, char *dest, const char *src, size_t maxlength)
609 size_t src_len, dest_len;
611 if (!dest) {
612 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
613 return NULL;
616 if (!src)
617 return dest;
619 src_len = strnlen(src, maxlength + 1);
620 dest_len = strnlen(dest, maxlength + 1);
622 #ifdef DEVELOPER
623 clobber_region(fn, line, dest + dest_len, maxlength + 1 - dest_len);
624 #endif
626 if (src_len + dest_len > maxlength) {
627 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
628 (int)(src_len + dest_len - maxlength), src));
629 if (maxlength > dest_len) {
630 memcpy(&dest[dest_len], src, maxlength - dest_len);
632 dest[maxlength] = 0;
633 return NULL;
636 memcpy(&dest[dest_len], src, src_len);
637 dest[dest_len + src_len] = 0;
638 return dest;
642 Paranoid strcpy into a buffer of given length (includes terminating
643 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
644 and replaces with '_'. Deliberately does *NOT* check for multibyte
645 characters. Don't change it !
647 char *alpha_strcpy_fn(const char *fn, int line, char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
649 size_t len, i;
651 #ifdef DEVELOPER
652 clobber_region(fn, line, dest, maxlength);
653 #endif
655 if (!dest) {
656 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
657 return NULL;
660 if (!src) {
661 *dest = 0;
662 return dest;
665 len = strlen(src);
666 if (len >= maxlength)
667 len = maxlength - 1;
669 if (!other_safe_chars)
670 other_safe_chars = "";
672 for(i = 0; i < len; i++) {
673 int val = (src[i] & 0xff);
674 if (isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
675 dest[i] = src[i];
676 else
677 dest[i] = '_';
680 dest[i] = '\0';
682 return dest;
686 Like strncpy but always null terminates. Make sure there is room!
687 The variable n should always be one less than the available size.
689 char *StrnCpy_fn(const char *fn, int line,char *dest,const char *src,size_t n)
691 char *d = dest;
693 #ifdef DEVELOPER
694 clobber_region(fn, line, dest, n+1);
695 #endif
697 if (!dest)
698 return(NULL);
700 if (!src) {
701 *dest = 0;
702 return(dest);
705 while (n-- && (*d = *src)) {
706 d++;
707 src++;
710 *d = 0;
711 return(dest);
714 #if 0
716 Like strncpy but copies up to the character marker. always null terminates.
717 returns a pointer to the character marker in the source string (src).
720 static char *strncpyn(char *dest, const char *src, size_t n, char c)
722 char *p;
723 size_t str_len;
725 #ifdef DEVELOPER
726 clobber_region(dest, n+1);
727 #endif
728 p = strchr_m(src, c);
729 if (p == NULL) {
730 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
731 return NULL;
734 str_len = PTR_DIFF(p, src);
735 strncpy(dest, src, MIN(n, str_len));
736 dest[str_len] = '\0';
738 return p;
740 #endif
743 Routine to get hex characters and turn them into a 16 byte array.
744 the array can be variable length, and any non-hex-numeric
745 characters are skipped. "0xnn" or "0Xnn" is specially catered
746 for.
748 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
752 size_t strhex_to_str(char *p, size_t len, const char *strhex)
754 size_t i;
755 size_t num_chars = 0;
756 unsigned char lonybble, hinybble;
757 const char *hexchars = "0123456789ABCDEF";
758 char *p1 = NULL, *p2 = NULL;
760 for (i = 0; i < len && strhex[i] != 0; i++) {
761 if (strnequal(hexchars, "0x", 2)) {
762 i++; /* skip two chars */
763 continue;
766 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
767 break;
769 i++; /* next hex digit */
771 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
772 break;
774 /* get the two nybbles */
775 hinybble = PTR_DIFF(p1, hexchars);
776 lonybble = PTR_DIFF(p2, hexchars);
778 p[num_chars] = (hinybble << 4) | lonybble;
779 num_chars++;
781 p1 = NULL;
782 p2 = NULL;
784 return num_chars;
788 * Routine to print a buffer as HEX digits, into an allocated string.
791 void hex_encode(const unsigned char *buff_in, size_t len, char **out_hex_buffer)
793 int i;
794 char *hex_buffer;
796 *out_hex_buffer = smb_xmalloc((len*2)+1);
797 hex_buffer = *out_hex_buffer;
799 for (i = 0; i < len; i++)
800 slprintf(&hex_buffer[i*2], 3, "%02X", buff_in[i]);
804 Check if a string is part of a list.
807 BOOL in_list(char *s,char *list,BOOL casesensitive)
809 pstring tok;
810 const char *p=list;
812 if (!list)
813 return(False);
815 while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
816 if (casesensitive) {
817 if (strcmp(tok,s) == 0)
818 return(True);
819 } else {
820 if (StrCaseCmp(tok,s) == 0)
821 return(True);
824 return(False);
827 /* this is used to prevent lots of mallocs of size 1 */
828 static char *null_string = NULL;
831 Set a string value, allocing the space for the string
834 static BOOL string_init(char **dest,const char *src)
836 size_t l;
837 if (!src)
838 src = "";
840 l = strlen(src);
842 if (l == 0) {
843 if (!null_string) {
844 if((null_string = (char *)malloc(1)) == NULL) {
845 DEBUG(0,("string_init: malloc fail for null_string.\n"));
846 return False;
848 *null_string = 0;
850 *dest = null_string;
851 } else {
852 (*dest) = strdup(src);
853 if ((*dest) == NULL) {
854 DEBUG(0,("Out of memory in string_init\n"));
855 return False;
858 return(True);
862 Free a string value.
865 void string_free(char **s)
867 if (!s || !(*s))
868 return;
869 if (*s == null_string)
870 *s = NULL;
871 SAFE_FREE(*s);
875 Set a string value, deallocating any existing space, and allocing the space
876 for the string
879 BOOL string_set(char **dest,const char *src)
881 string_free(dest);
882 return(string_init(dest,src));
886 Substitute a string for a pattern in another string. Make sure there is
887 enough room!
889 This routine looks for pattern in s and replaces it with
890 insert. It may do multiple replacements.
892 Any of " ; ' $ or ` in the insert string are replaced with _
893 if len==0 then the string cannot be extended. This is different from the old
894 use of len==0 which was for no length checks to be done.
897 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
899 char *p;
900 ssize_t ls,lp,li, i;
902 if (!insert || !pattern || !*pattern || !s)
903 return;
905 ls = (ssize_t)strlen(s);
906 lp = (ssize_t)strlen(pattern);
907 li = (ssize_t)strlen(insert);
909 if (len == 0)
910 len = ls + 1; /* len is number of *bytes* */
912 while (lp <= ls && (p = strstr(s,pattern))) {
913 if (ls + (li-lp) >= len) {
914 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
915 (int)(ls + (li-lp) - len),
916 pattern, (int)len));
917 break;
919 if (li != lp) {
920 memmove(p+li,p+lp,strlen(p+lp)+1);
922 for (i=0;i<li;i++) {
923 switch (insert[i]) {
924 case '`':
925 case '"':
926 case '\'':
927 case ';':
928 case '$':
929 case '%':
930 case '\r':
931 case '\n':
932 p[i] = '_';
933 break;
934 default:
935 p[i] = insert[i];
938 s = p + li;
939 ls += (li-lp);
943 void fstring_sub(char *s,const char *pattern,const char *insert)
945 string_sub(s, pattern, insert, sizeof(fstring));
948 void pstring_sub(char *s,const char *pattern,const char *insert)
950 string_sub(s, pattern, insert, sizeof(pstring));
954 Similar to string_sub, but it will accept only allocated strings
955 and may realloc them so pay attention at what you pass on no
956 pointers inside strings, no pstrings or const may be passed
957 as string.
960 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
962 char *p, *in;
963 char *s;
964 ssize_t ls,lp,li,ld, i;
966 if (!insert || !pattern || !*pattern || !string || !*string)
967 return NULL;
969 s = string;
971 in = strdup(insert);
972 if (!in) {
973 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
974 return NULL;
976 ls = (ssize_t)strlen(s);
977 lp = (ssize_t)strlen(pattern);
978 li = (ssize_t)strlen(insert);
979 ld = li - lp;
980 for (i=0;i<li;i++) {
981 switch (in[i]) {
982 case '`':
983 case '"':
984 case '\'':
985 case ';':
986 case '$':
987 case '%':
988 case '\r':
989 case '\n':
990 in[i] = '_';
991 default:
992 /* ok */
993 break;
997 while ((p = strstr(s,pattern))) {
998 if (ld > 0) {
999 int offset = PTR_DIFF(s,string);
1000 char *t = Realloc(string, ls + ld + 1);
1001 if (!t) {
1002 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
1003 SAFE_FREE(in);
1004 return NULL;
1006 string = t;
1007 p = t + offset + (p - s);
1009 if (li != lp) {
1010 memmove(p+li,p+lp,strlen(p+lp)+1);
1012 memcpy(p, in, li);
1013 s = p + li;
1014 ls += ld;
1016 SAFE_FREE(in);
1017 return string;
1021 Similar to string_sub() but allows for any character to be substituted.
1022 Use with caution!
1023 if len==0 then the string cannot be extended. This is different from the old
1024 use of len==0 which was for no length checks to be done.
1027 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
1029 char *p;
1030 ssize_t ls,lp,li;
1032 if (!insert || !pattern || !s)
1033 return;
1035 ls = (ssize_t)strlen(s);
1036 lp = (ssize_t)strlen(pattern);
1037 li = (ssize_t)strlen(insert);
1039 if (!*pattern)
1040 return;
1042 if (len == 0)
1043 len = ls + 1; /* len is number of *bytes* */
1045 while (lp <= ls && (p = strstr(s,pattern))) {
1046 if (ls + (li-lp) >= len) {
1047 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
1048 (int)(ls + (li-lp) - len),
1049 pattern, (int)len));
1050 break;
1052 if (li != lp) {
1053 memmove(p+li,p+lp,strlen(p+lp)+1);
1055 memcpy(p, insert, li);
1056 s = p + li;
1057 ls += (li-lp);
1062 Similar to all_string_sub but for unicode strings.
1063 Return a new allocated unicode string.
1064 similar to string_sub() but allows for any character to be substituted.
1065 Use with caution!
1068 static smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
1069 const smb_ucs2_t *insert)
1071 smb_ucs2_t *r, *rp;
1072 const smb_ucs2_t *sp;
1073 size_t lr, lp, li, lt;
1075 if (!insert || !pattern || !*pattern || !s)
1076 return NULL;
1078 lt = (size_t)strlen_w(s);
1079 lp = (size_t)strlen_w(pattern);
1080 li = (size_t)strlen_w(insert);
1082 if (li > lp) {
1083 const smb_ucs2_t *st = s;
1084 int ld = li - lp;
1085 while ((sp = strstr_w(st, pattern))) {
1086 st = sp + lp;
1087 lt += ld;
1091 r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
1092 if (!r) {
1093 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
1094 return NULL;
1097 while ((sp = strstr_w(s, pattern))) {
1098 memcpy(rp, s, (sp - s));
1099 rp += ((sp - s) / sizeof(smb_ucs2_t));
1100 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
1101 s = sp + lp;
1102 rp += li;
1104 lr = ((rp - r) / sizeof(smb_ucs2_t));
1105 if (lr < lt) {
1106 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
1107 rp += (lt - lr);
1109 *rp = 0;
1111 return r;
1114 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
1115 const char *insert)
1117 wpstring p, i;
1119 if (!insert || !pattern || !s)
1120 return NULL;
1121 push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
1122 push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
1123 return all_string_sub_w(s, p, i);
1126 #if 0
1128 Splits out the front and back at a separator.
1131 static void split_at_last_component(char *path, char *front, char sep, char *back)
1133 char *p = strrchr_m(path, sep);
1135 if (p != NULL)
1136 *p = 0;
1138 if (front != NULL)
1139 pstrcpy(front, path);
1141 if (p != NULL) {
1142 if (back != NULL)
1143 pstrcpy(back, p+1);
1144 *p = '\\';
1145 } else {
1146 if (back != NULL)
1147 back[0] = 0;
1150 #endif
1153 Write an octal as a string.
1156 const char *octal_string(int i)
1158 static char ret[64];
1159 if (i == -1)
1160 return "-1";
1161 slprintf(ret, sizeof(ret)-1, "0%o", i);
1162 return ret;
1167 Truncate a string at a specified length.
1170 char *string_truncate(char *s, unsigned int length)
1172 if (s && strlen(s) > length)
1173 s[length] = 0;
1174 return s;
1178 Strchr and strrchr_m are very hard to do on general multi-byte strings.
1179 We convert via ucs2 for now.
1182 char *strchr_m(const char *src, char c)
1184 wpstring ws;
1185 pstring s2;
1186 smb_ucs2_t *p;
1187 const char *s;
1189 /* this is quite a common operation, so we want it to be
1190 fast. We optimise for the ascii case, knowing that all our
1191 supported multi-byte character sets are ascii-compatible
1192 (ie. they match for the first 128 chars) */
1194 for (s = src; *s && !(((unsigned char)s[0]) & 0x80); s++) {
1195 if (*s == c)
1196 return s;
1199 if (!*s)
1200 return NULL;
1202 #ifdef BROKEN_UNICODE_COMPOSE_CHARACTERS
1203 /* With compose characters we must restart from the beginning. JRA. */
1204 s = src;
1205 #endif
1207 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1208 p = strchr_w(ws, UCS2_CHAR(c));
1209 if (!p)
1210 return NULL;
1211 *p = 0;
1212 pull_ucs2_pstring(s2, ws);
1213 return (char *)(s+strlen(s2));
1216 char *strrchr_m(const char *s, char c)
1218 /* this is quite a common operation, so we want it to be
1219 fast. We optimise for the ascii case, knowing that all our
1220 supported multi-byte character sets are ascii-compatible
1221 (ie. they match for the first 128 chars). Also, in Samba
1222 we only search for ascii characters in 'c' and that
1223 in all mb character sets with a compound character
1224 containing c, if 'c' is not a match at position
1225 p, then p[-1] > 0x7f. JRA. */
1228 size_t len = strlen(s);
1229 const char *cp = s;
1230 BOOL got_mb = False;
1232 if (len == 0)
1233 return NULL;
1234 cp += (len - 1);
1235 do {
1236 if (c == *cp) {
1237 /* Could be a match. Part of a multibyte ? */
1238 if ((cp > s) && (((unsigned char)cp[-1]) & 0x80)) {
1239 /* Yep - go slow :-( */
1240 got_mb = True;
1241 break;
1243 /* No - we have a match ! */
1244 return cp;
1246 } while (cp-- != s);
1247 if (!got_mb)
1248 return NULL;
1251 /* String contained a non-ascii char. Slow path. */
1253 wpstring ws;
1254 pstring s2;
1255 smb_ucs2_t *p;
1257 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1258 p = strrchr_w(ws, UCS2_CHAR(c));
1259 if (!p)
1260 return NULL;
1261 *p = 0;
1262 pull_ucs2_pstring(s2, ws);
1263 return (char *)(s+strlen(s2));
1267 /***********************************************************************
1268 Return the equivalent of doing strrchr 'n' times - always going
1269 backwards.
1270 ***********************************************************************/
1272 char *strnrchr_m(const char *s, char c, unsigned int n)
1274 wpstring ws;
1275 pstring s2;
1276 smb_ucs2_t *p;
1278 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
1279 p = strnrchr_w(ws, UCS2_CHAR(c), n);
1280 if (!p)
1281 return NULL;
1282 *p = 0;
1283 pull_ucs2_pstring(s2, ws);
1284 return (char *)(s+strlen(s2));
1288 Convert a string to lower case.
1291 void strlower_m(char *s)
1293 /* this is quite a common operation, so we want it to be
1294 fast. We optimise for the ascii case, knowing that all our
1295 supported multi-byte character sets are ascii-compatible
1296 (ie. they match for the first 128 chars) */
1298 while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1299 *s = tolower((unsigned char)*s);
1300 s++;
1303 if (!*s)
1304 return;
1306 /* I assume that lowercased string takes the same number of bytes
1307 * as source string even in UTF-8 encoding. (VIV) */
1308 unix_strlower(s,strlen(s)+1,s,strlen(s)+1);
1312 Convert a string to upper case.
1315 void strupper_m(char *s)
1317 /* this is quite a common operation, so we want it to be
1318 fast. We optimise for the ascii case, knowing that all our
1319 supported multi-byte character sets are ascii-compatible
1320 (ie. they match for the first 128 chars) */
1322 while (*s && !(((unsigned char)s[0]) & 0x7F)) {
1323 *s = toupper((unsigned char)*s);
1324 s++;
1327 if (!*s)
1328 return;
1330 /* I assume that lowercased string takes the same number of bytes
1331 * as source string even in multibyte encoding. (VIV) */
1332 unix_strupper(s,strlen(s)+1,s,strlen(s)+1);
1336 Return a RFC2254 binary string representation of a buffer.
1337 Used in LDAP filters.
1338 Caller must free.
1341 char *binary_string(char *buf, int len)
1343 char *s;
1344 int i, j;
1345 const char *hex = "0123456789ABCDEF";
1346 s = malloc(len * 3 + 1);
1347 if (!s)
1348 return NULL;
1349 for (j=i=0;i<len;i++) {
1350 s[j] = '\\';
1351 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1352 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1353 j += 3;
1355 s[j] = 0;
1356 return s;
1360 Just a typesafety wrapper for snprintf into a pstring.
1363 int pstr_sprintf(pstring s, const char *fmt, ...)
1365 va_list ap;
1366 int ret;
1368 va_start(ap, fmt);
1369 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1370 va_end(ap);
1371 return ret;
1376 Just a typesafety wrapper for snprintf into a fstring.
1379 int fstr_sprintf(fstring s, const char *fmt, ...)
1381 va_list ap;
1382 int ret;
1384 va_start(ap, fmt);
1385 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1386 va_end(ap);
1387 return ret;
1391 #ifndef HAVE_STRNDUP
1393 Some platforms don't have strndup.
1396 char *strndup(const char *s, size_t n)
1398 char *ret;
1400 n = strnlen(s, n);
1401 ret = malloc(n+1);
1402 if (!ret)
1403 return NULL;
1404 memcpy(ret, s, n);
1405 ret[n] = 0;
1407 return ret;
1409 #endif
1411 #ifndef HAVE_STRNLEN
1413 Some platforms don't have strnlen
1416 size_t strnlen(const char *s, size_t n)
1418 int i;
1419 for (i=0; s[i] && i<n; i++)
1420 /* noop */ ;
1421 return i;
1423 #endif
1426 List of Strings manipulation functions
1429 #define S_LIST_ABS 16 /* List Allocation Block Size */
1431 char **str_list_make(const char *string, const char *sep)
1433 char **list, **rlist;
1434 const char *str;
1435 char *s;
1436 int num, lsize;
1437 pstring tok;
1439 if (!string || !*string)
1440 return NULL;
1441 s = strdup(string);
1442 if (!s) {
1443 DEBUG(0,("str_list_make: Unable to allocate memory"));
1444 return NULL;
1446 if (!sep) sep = LIST_SEP;
1448 num = lsize = 0;
1449 list = NULL;
1451 str = s;
1452 while (next_token(&str, tok, sep, sizeof(tok))) {
1453 if (num == lsize) {
1454 lsize += S_LIST_ABS;
1455 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1456 if (!rlist) {
1457 DEBUG(0,("str_list_make: Unable to allocate memory"));
1458 str_list_free(&list);
1459 SAFE_FREE(s);
1460 return NULL;
1461 } else
1462 list = rlist;
1463 memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1466 list[num] = strdup(tok);
1467 if (!list[num]) {
1468 DEBUG(0,("str_list_make: Unable to allocate memory"));
1469 str_list_free(&list);
1470 SAFE_FREE(s);
1471 return NULL;
1474 num++;
1477 SAFE_FREE(s);
1478 return list;
1481 BOOL str_list_copy(char ***dest, const char **src)
1483 char **list, **rlist;
1484 int num, lsize;
1486 *dest = NULL;
1487 if (!src)
1488 return False;
1490 num = lsize = 0;
1491 list = NULL;
1493 while (src[num]) {
1494 if (num == lsize) {
1495 lsize += S_LIST_ABS;
1496 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1497 if (!rlist) {
1498 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
1499 str_list_free(&list);
1500 return False;
1501 } else
1502 list = rlist;
1503 memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1506 list[num] = strdup(src[num]);
1507 if (!list[num]) {
1508 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1509 str_list_free(&list);
1510 return False;
1513 num++;
1516 *dest = list;
1517 return True;
1521 * Return true if all the elements of the list match exactly.
1523 BOOL str_list_compare(char **list1, char **list2)
1525 int num;
1527 if (!list1 || !list2)
1528 return (list1 == list2);
1530 for (num = 0; list1[num]; num++) {
1531 if (!list2[num])
1532 return False;
1533 if (!strcsequal(list1[num], list2[num]))
1534 return False;
1536 if (list2[num])
1537 return False; /* if list2 has more elements than list1 fail */
1539 return True;
1542 void str_list_free(char ***list)
1544 char **tlist;
1546 if (!list || !*list)
1547 return;
1548 tlist = *list;
1549 for(; *tlist; tlist++)
1550 SAFE_FREE(*tlist);
1551 SAFE_FREE(*list);
1554 /******************************************************************************
1555 version of standard_sub_basic() for string lists; uses alloc_sub_basic()
1556 for the work
1557 *****************************************************************************/
1559 BOOL str_list_sub_basic( char **list, const char *smb_name )
1561 char *s, *tmpstr;
1563 while ( *list ) {
1564 s = *list;
1565 tmpstr = alloc_sub_basic(smb_name, s);
1566 if ( !tmpstr ) {
1567 DEBUG(0,("str_list_sub_basic: alloc_sub_basic() return NULL!\n"));
1568 return False;
1571 *list = tmpstr;
1573 list++;
1576 return True;
1579 /******************************************************************************
1580 substritute a specific pattern in a string list
1581 *****************************************************************************/
1583 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1585 char *p, *s, *t;
1586 ssize_t ls, lp, li, ld, i, d;
1588 if (!list)
1589 return False;
1590 if (!pattern)
1591 return False;
1592 if (!insert)
1593 return False;
1595 lp = (ssize_t)strlen(pattern);
1596 li = (ssize_t)strlen(insert);
1597 ld = li -lp;
1599 while (*list) {
1600 s = *list;
1601 ls = (ssize_t)strlen(s);
1603 while ((p = strstr(s, pattern))) {
1604 t = *list;
1605 d = p -t;
1606 if (ld) {
1607 t = (char *) malloc(ls +ld +1);
1608 if (!t) {
1609 DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1610 return False;
1612 memcpy(t, *list, d);
1613 memcpy(t +d +li, p +lp, ls -d -lp +1);
1614 SAFE_FREE(*list);
1615 *list = t;
1616 ls += ld;
1617 s = t +d +li;
1620 for (i = 0; i < li; i++) {
1621 switch (insert[i]) {
1622 case '`':
1623 case '"':
1624 case '\'':
1625 case ';':
1626 case '$':
1627 case '%':
1628 case '\r':
1629 case '\n':
1630 t[d +i] = '_';
1631 break;
1632 default:
1633 t[d +i] = insert[i];
1639 list++;
1642 return True;
1646 #define IPSTR_LIST_SEP ","
1647 #define IPSTR_LIST_CHAR ','
1650 * Add ip string representation to ipstr list. Used also
1651 * as part of @function ipstr_list_make
1653 * @param ipstr_list pointer to string containing ip list;
1654 * MUST BE already allocated and IS reallocated if necessary
1655 * @param ipstr_size pointer to current size of ipstr_list (might be changed
1656 * as a result of reallocation)
1657 * @param ip IP address which is to be added to list
1658 * @return pointer to string appended with new ip and possibly
1659 * reallocated to new length
1662 char* ipstr_list_add(char** ipstr_list, const struct ip_service *service)
1664 char* new_ipstr = NULL;
1666 /* arguments checking */
1667 if (!ipstr_list || !service) return NULL;
1669 /* attempt to convert ip to a string and append colon separator to it */
1670 if (*ipstr_list) {
1671 asprintf(&new_ipstr, "%s%s%s:%d", *ipstr_list, IPSTR_LIST_SEP,
1672 inet_ntoa(service->ip), service->port);
1673 SAFE_FREE(*ipstr_list);
1674 } else {
1675 asprintf(&new_ipstr, "%s:%d", inet_ntoa(service->ip), service->port);
1677 *ipstr_list = new_ipstr;
1678 return *ipstr_list;
1683 * Allocate and initialise an ipstr list using ip adresses
1684 * passed as arguments.
1686 * @param ipstr_list pointer to string meant to be allocated and set
1687 * @param ip_list array of ip addresses to place in the list
1688 * @param ip_count number of addresses stored in ip_list
1689 * @return pointer to allocated ip string
1692 char* ipstr_list_make(char** ipstr_list, const struct ip_service* ip_list, int ip_count)
1694 int i;
1696 /* arguments checking */
1697 if (!ip_list && !ipstr_list) return 0;
1699 *ipstr_list = NULL;
1701 /* process ip addresses given as arguments */
1702 for (i = 0; i < ip_count; i++)
1703 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
1705 return (*ipstr_list);
1710 * Parse given ip string list into array of ip addresses
1711 * (as ip_service structures)
1712 * e.g. 192.168.1.100:389,192.168.1.78, ...
1714 * @param ipstr ip string list to be parsed
1715 * @param ip_list pointer to array of ip addresses which is
1716 * allocated by this function and must be freed by caller
1717 * @return number of succesfully parsed addresses
1720 int ipstr_list_parse(const char* ipstr_list, struct ip_service **ip_list)
1722 fstring token_str;
1723 size_t count;
1724 int i;
1726 if (!ipstr_list || !ip_list)
1727 return 0;
1729 count = count_chars(ipstr_list, IPSTR_LIST_CHAR) + 1;
1730 if ( (*ip_list = (struct ip_service*)malloc(count * sizeof(struct ip_service))) == NULL ) {
1731 DEBUG(0,("ipstr_list_parse: malloc failed for %lu entries\n", (unsigned long)count));
1732 return 0;
1735 for ( i=0;
1736 next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN) && i<count;
1737 i++ )
1739 struct in_addr addr;
1740 unsigned port = 0;
1741 char *p = strchr(token_str, ':');
1743 if (p) {
1744 *p = 0;
1745 port = atoi(p+1);
1748 /* convert single token to ip address */
1749 if ( (addr.s_addr = inet_addr(token_str)) == INADDR_NONE )
1750 break;
1752 (*ip_list)[i].ip = addr;
1753 (*ip_list)[i].port = port;
1756 return count;
1761 * Safely free ip string list
1763 * @param ipstr_list ip string list to be freed
1766 void ipstr_list_free(char* ipstr_list)
1768 SAFE_FREE(ipstr_list);
1773 Unescape a URL encoded string, in place.
1776 void rfc1738_unescape(char *buf)
1778 char *p=buf;
1780 while ((p=strchr_m(p,'+')))
1781 *p = ' ';
1783 p = buf;
1785 while (p && *p && (p=strchr_m(p,'%'))) {
1786 int c1 = p[1];
1787 int c2 = p[2];
1789 if (c1 >= '0' && c1 <= '9')
1790 c1 = c1 - '0';
1791 else if (c1 >= 'A' && c1 <= 'F')
1792 c1 = 10 + c1 - 'A';
1793 else if (c1 >= 'a' && c1 <= 'f')
1794 c1 = 10 + c1 - 'a';
1795 else {p++; continue;}
1797 if (c2 >= '0' && c2 <= '9')
1798 c2 = c2 - '0';
1799 else if (c2 >= 'A' && c2 <= 'F')
1800 c2 = 10 + c2 - 'A';
1801 else if (c2 >= 'a' && c2 <= 'f')
1802 c2 = 10 + c2 - 'a';
1803 else {p++; continue;}
1805 *p = (c1<<4) | c2;
1807 memmove(p+1, p+3, strlen(p+3)+1);
1808 p++;
1812 static const char *b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
1815 * Decode a base64 string into a DATA_BLOB - simple and slow algorithm
1817 DATA_BLOB base64_decode_data_blob(const char *s)
1819 int bit_offset, byte_offset, idx, i, n;
1820 DATA_BLOB decoded = data_blob(s, strlen(s)+1);
1821 unsigned char *d = decoded.data;
1822 char *p;
1824 n=i=0;
1826 while (*s && (p=strchr_m(b64,*s))) {
1827 idx = (int)(p - b64);
1828 byte_offset = (i*6)/8;
1829 bit_offset = (i*6)%8;
1830 d[byte_offset] &= ~((1<<(8-bit_offset))-1);
1831 if (bit_offset < 3) {
1832 d[byte_offset] |= (idx << (2-bit_offset));
1833 n = byte_offset+1;
1834 } else {
1835 d[byte_offset] |= (idx >> (bit_offset-2));
1836 d[byte_offset+1] = 0;
1837 d[byte_offset+1] |= (idx << (8-(bit_offset-2))) & 0xFF;
1838 n = byte_offset+2;
1840 s++; i++;
1843 /* fix up length */
1844 decoded.length = n;
1845 return decoded;
1849 * Decode a base64 string in-place - wrapper for the above
1851 void base64_decode_inplace(char *s)
1853 DATA_BLOB decoded = base64_decode_data_blob(s);
1854 memcpy(s, decoded.data, decoded.length);
1855 /* null terminate */
1856 s[decoded.length] = '\0';
1858 data_blob_free(&decoded);
1862 * Encode a base64 string into a malloc()ed string caller to free.
1864 *From SQUID: adopted from http://ftp.sunet.se/pub2/gnu/vm/base64-encode.c with adjustments
1866 char * base64_encode_data_blob(DATA_BLOB data)
1868 int bits = 0;
1869 int char_count = 0;
1870 size_t out_cnt = 0;
1871 size_t len = data.length;
1872 size_t output_len = data.length * 2;
1873 char *result = malloc(output_len); /* get us plenty of space */
1875 while (len-- && out_cnt < (data.length * 2) - 5) {
1876 int c = (unsigned char) *(data.data++);
1877 bits += c;
1878 char_count++;
1879 if (char_count == 3) {
1880 result[out_cnt++] = b64[bits >> 18];
1881 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1882 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1883 result[out_cnt++] = b64[bits & 0x3f];
1884 bits = 0;
1885 char_count = 0;
1886 } else {
1887 bits <<= 8;
1890 if (char_count != 0) {
1891 bits <<= 16 - (8 * char_count);
1892 result[out_cnt++] = b64[bits >> 18];
1893 result[out_cnt++] = b64[(bits >> 12) & 0x3f];
1894 if (char_count == 1) {
1895 result[out_cnt++] = '=';
1896 result[out_cnt++] = '=';
1897 } else {
1898 result[out_cnt++] = b64[(bits >> 6) & 0x3f];
1899 result[out_cnt++] = '=';
1902 result[out_cnt] = '\0'; /* terminate */
1903 return result;
1906 /* read a SMB_BIG_UINT from a string */
1907 SMB_BIG_UINT STR_TO_SMB_BIG_UINT(const char *nptr, const char **entptr)
1910 SMB_BIG_UINT val = -1;
1911 const char *p = nptr;
1913 while (p && *p && isspace(*p))
1914 p++;
1915 #ifdef LARGE_SMB_OFF_T
1916 sscanf(p,"%llu",&val);
1917 #else /* LARGE_SMB_OFF_T */
1918 sscanf(p,"%lu",&val);
1919 #endif /* LARGE_SMB_OFF_T */
1920 if (entptr) {
1921 while (p && *p && isdigit(*p))
1922 p++;
1923 *entptr = p;
1926 return val;