2007-10-17 23:10:12 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1998-11-05 19:48:35 +03:00
Samba utility functions
2007-10-17 23:10:12 +04:00
2001-07-04 11:15:53 +04:00
Copyright ( C ) Andrew Tridgell 1992 - 2001
2002-01-25 03:35:14 +03:00
Copyright ( C ) Simo Sorce 2001 - 2002
2003-03-19 00:21:21 +03:00
Copyright ( C ) Martin Pool 2003
2006-07-11 22:01:26 +04:00
Copyright ( C ) James Peach 2006
2007-09-13 05:10:01 +04:00
Copyright ( C ) Jeremy Allison 1992 - 2007
2007-10-17 23:10:12 +04:00
1998-11-05 19:48:35 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1998-11-05 19:48:35 +03:00
( at your option ) any later version .
2007-10-17 23:10:12 +04:00
1998-11-05 19:48:35 +03:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
2007-10-17 23:10:12 +04:00
1998-11-05 19:48:35 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1998-11-05 19:48:35 +03:00
*/
# include "includes.h"
2012-07-23 06:47:01 +04:00
# include "lib/param/loadparm.h"
2020-07-03 09:11:20 +03:00
# include "lib/util/smb_strtox.h"
1998-11-05 19:48:35 +03:00
2014-11-09 15:48:09 +03:00
static const char toupper_ascii_fast_table [ 128 ] = {
2008-01-10 04:32:26 +03:00
0x0 , 0x1 , 0x2 , 0x3 , 0x4 , 0x5 , 0x6 , 0x7 , 0x8 , 0x9 , 0xa , 0xb , 0xc , 0xd , 0xe , 0xf ,
0x10 , 0x11 , 0x12 , 0x13 , 0x14 , 0x15 , 0x16 , 0x17 , 0x18 , 0x19 , 0x1a , 0x1b , 0x1c , 0x1d , 0x1e , 0x1f ,
0x20 , 0x21 , 0x22 , 0x23 , 0x24 , 0x25 , 0x26 , 0x27 , 0x28 , 0x29 , 0x2a , 0x2b , 0x2c , 0x2d , 0x2e , 0x2f ,
0x30 , 0x31 , 0x32 , 0x33 , 0x34 , 0x35 , 0x36 , 0x37 , 0x38 , 0x39 , 0x3a , 0x3b , 0x3c , 0x3d , 0x3e , 0x3f ,
0x40 , 0x41 , 0x42 , 0x43 , 0x44 , 0x45 , 0x46 , 0x47 , 0x48 , 0x49 , 0x4a , 0x4b , 0x4c , 0x4d , 0x4e , 0x4f ,
0x50 , 0x51 , 0x52 , 0x53 , 0x54 , 0x55 , 0x56 , 0x57 , 0x58 , 0x59 , 0x5a , 0x5b , 0x5c , 0x5d , 0x5e , 0x5f ,
0x60 , 0x41 , 0x42 , 0x43 , 0x44 , 0x45 , 0x46 , 0x47 , 0x48 , 0x49 , 0x4a , 0x4b , 0x4c , 0x4d , 0x4e , 0x4f ,
0x50 , 0x51 , 0x52 , 0x53 , 0x54 , 0x55 , 0x56 , 0x57 , 0x58 , 0x59 , 0x5a , 0x7b , 0x7c , 0x7d , 0x7e , 0x7f
} ;
2003-02-24 06:09:08 +03:00
/**
2003-03-18 01:42:01 +03:00
* Compare 2 strings up to and including the nth char .
*
* @ note The comparison is case - insensitive .
* */
2007-10-17 23:10:12 +04:00
bool strnequal ( const char * s1 , const char * s2 , size_t n )
1998-11-05 19:48:35 +03:00
{
2005-08-13 02:59:35 +04:00
if ( s1 = = s2 )
2007-10-17 23:10:12 +04:00
return ( true ) ;
2005-08-13 02:59:35 +04:00
if ( ! s1 | | ! s2 | | ! n )
2007-10-17 23:10:12 +04:00
return ( false ) ;
2007-09-13 05:10:01 +04:00
2011-05-13 22:23:36 +04:00
return ( strncasecmp_m ( s1 , s2 , n ) = = 0 ) ;
1998-11-05 19:48:35 +03:00
}
2007-03-31 02:25:08 +04:00
/**
2007-04-03 00:10:21 +04:00
Skip past a string in a buffer . Buffer may not be
2007-03-31 02:25:08 +04:00
null terminated . end_ptr points to the first byte after
then end of the buffer .
* */
2007-04-03 00:10:21 +04:00
char * skip_string ( const char * base , size_t len , char * buf )
2007-03-31 02:25:08 +04:00
{
const char * end_ptr = base + len ;
if ( end_ptr < base | | ! base | | ! buf | | buf > = end_ptr ) {
return NULL ;
}
2007-04-03 00:10:21 +04:00
/* Skip the string */
while ( * buf ) {
2007-03-31 02:25:08 +04:00
buf + + ;
2007-04-03 00:10:21 +04:00
if ( buf > = end_ptr ) {
return NULL ;
}
2007-03-31 02:25:08 +04:00
}
2007-04-03 00:10:21 +04:00
/* Skip the '\0' */
buf + + ;
2007-03-31 02:25:08 +04:00
return buf ;
}
2003-02-24 06:09:08 +03:00
/**
1998-11-05 19:48:35 +03:00
Count the number of characters in a string . Normally this will
be the same as the number of bytes in a string for single byte strings ,
but will be different for multibyte .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
1998-11-17 23:50:07 +03:00
size_t str_charnum ( const char * s )
1998-11-05 19:48:35 +03:00
{
2008-04-30 01:36:24 +04:00
size_t ret , converted_size ;
2007-09-13 05:10:01 +04:00
smb_ucs2_t * tmpbuf2 = NULL ;
2009-07-17 05:13:46 +04:00
if ( ! push_ucs2_talloc ( talloc_tos ( ) , & tmpbuf2 , s , & converted_size ) ) {
2007-09-13 05:10:01 +04:00
return 0 ;
}
ret = strlen_w ( tmpbuf2 ) ;
2009-03-19 04:20:11 +03:00
TALLOC_FREE ( tmpbuf2 ) ;
2007-09-13 05:10:01 +04:00
return ret ;
2003-01-15 21:57:41 +03:00
}
2007-10-17 23:10:12 +04:00
bool trim_char ( char * s , char cfront , char cback )
2003-09-05 23:59:55 +04:00
{
2007-10-17 23:10:12 +04:00
bool ret = false ;
2003-09-05 23:59:55 +04:00
char * ep ;
char * fp = s ;
/* Ignore null or empty strings. */
if ( ! s | | ( s [ 0 ] = = ' \0 ' ) )
2007-10-17 23:10:12 +04:00
return false ;
2003-09-05 23:59:55 +04:00
if ( cfront ) {
while ( * fp & & * fp = = cfront )
fp + + ;
if ( ! * fp ) {
/* We ate the string. */
s [ 0 ] = ' \0 ' ;
2007-10-17 23:10:12 +04:00
return true ;
2003-09-05 23:59:55 +04:00
}
if ( fp ! = s )
2007-10-17 23:10:12 +04:00
ret = true ;
2003-09-05 23:59:55 +04:00
}
ep = fp + strlen ( fp ) - 1 ;
if ( cback ) {
/* Attempt ascii only. Bail for mb strings. */
while ( ( ep > = fp ) & & ( * ep = = cback ) ) {
2007-10-17 23:10:12 +04:00
ret = true ;
2003-09-05 23:59:55 +04:00
if ( ( ep > fp ) & & ( ( ( unsigned char ) ep [ - 1 ] ) & 0x80 ) ) {
/* Could be mb... bail back to tim_string. */
char fs [ 2 ] , bs [ 2 ] ;
if ( cfront ) {
fs [ 0 ] = cfront ;
fs [ 1 ] = ' \0 ' ;
}
bs [ 0 ] = cback ;
bs [ 1 ] = ' \0 ' ;
return trim_string ( s , cfront ? fs : NULL , bs ) ;
} else {
ep - - ;
}
}
if ( ep < fp ) {
/* We ate the string. */
s [ 0 ] = ' \0 ' ;
2007-10-17 23:10:12 +04:00
return true ;
2003-09-05 23:59:55 +04:00
}
}
ep [ 1 ] = ' \0 ' ;
memmove ( s , fp , ep - fp + 2 ) ;
return ret ;
}
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Check if a string is part of a list .
2003-02-24 06:09:08 +03:00
* */
2002-10-02 23:12:14 +04:00
2007-10-17 23:10:12 +04:00
bool in_list ( const char * s , const char * list , bool casesensitive )
1998-11-05 19:48:35 +03:00
{
2007-12-08 04:32:32 +03:00
char * tok = NULL ;
2007-10-17 23:10:12 +04:00
bool ret = false ;
2007-12-08 04:32:32 +03:00
TALLOC_CTX * frame ;
2002-10-02 23:12:14 +04:00
2007-12-08 04:32:32 +03:00
if ( ! list ) {
2007-10-17 23:10:12 +04:00
return false ;
2007-09-13 05:10:01 +04:00
}
2007-12-08 04:32:32 +03:00
frame = talloc_stackframe ( ) ;
while ( next_token_talloc ( frame , & list , & tok , LIST_SEP ) ) {
2002-10-02 23:12:14 +04:00
if ( casesensitive ) {
2007-09-13 05:10:01 +04:00
if ( strcmp ( tok , s ) = = 0 ) {
2007-10-17 23:10:12 +04:00
ret = true ;
2007-09-13 05:10:01 +04:00
break ;
}
2002-10-02 23:12:14 +04:00
} else {
2011-05-13 22:21:30 +04:00
if ( strcasecmp_m ( tok , s ) = = 0 ) {
2007-10-17 23:10:12 +04:00
ret = true ;
2007-09-13 05:10:01 +04:00
break ;
}
2002-10-02 23:12:14 +04:00
}
}
2007-12-08 04:32:32 +03:00
TALLOC_FREE ( frame ) ;
2007-09-13 05:10:01 +04:00
return ret ;
1998-11-05 19:48:35 +03:00
}
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Truncate a string at a specified length .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-03-18 04:48:11 +03:00
char * string_truncate ( char * s , unsigned int length )
1999-02-16 21:02:50 +03:00
{
2002-08-17 21:00:51 +04:00
if ( s & & strlen ( s ) > length )
1999-12-13 16:27:58 +03:00
s [ length ] = 0 ;
return s ;
1999-02-16 21:02:50 +03:00
}
2001-07-04 11:15:53 +04:00
2003-07-03 00:01:51 +04:00
/***********************************************************************
Return the equivalent of doing strrchr ' n ' times - always going
backwards .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * strnrchr_m ( const char * s , char c , unsigned int n )
{
2007-09-13 05:10:01 +04:00
smb_ucs2_t * ws = NULL ;
char * s2 = NULL ;
2003-07-03 00:01:51 +04:00
smb_ucs2_t * p ;
2007-09-13 05:10:01 +04:00
char * ret ;
2008-04-30 01:36:24 +04:00
size_t converted_size ;
2003-07-03 00:01:51 +04:00
2009-07-17 05:13:46 +04:00
if ( ! push_ucs2_talloc ( talloc_tos ( ) , & ws , s , & converted_size ) ) {
2007-09-13 05:10:01 +04:00
/* Too hard to try and get right. */
return NULL ;
}
2003-07-03 00:01:51 +04:00
p = strnrchr_w ( ws , UCS2_CHAR ( c ) , n ) ;
2007-09-13 05:10:01 +04:00
if ( ! p ) {
2009-03-19 04:20:11 +03:00
TALLOC_FREE ( ws ) ;
2003-07-03 00:01:51 +04:00
return NULL ;
2007-09-13 05:10:01 +04:00
}
2003-07-03 00:01:51 +04:00
* p = 0 ;
2009-07-17 05:13:46 +04:00
if ( ! pull_ucs2_talloc ( talloc_tos ( ) , & s2 , ws , & converted_size ) ) {
2009-03-19 04:20:11 +03:00
TALLOC_FREE ( ws ) ;
2007-09-13 05:10:01 +04:00
/* Too hard to try and get right. */
return NULL ;
}
2011-05-06 01:22:11 +04:00
ret = discard_const_p ( char , ( s + strlen ( s2 ) ) ) ;
2009-03-19 04:20:11 +03:00
TALLOC_FREE ( ws ) ;
TALLOC_FREE ( s2 ) ;
2007-09-13 05:10:01 +04:00
return ret ;
2003-07-03 00:01:51 +04:00
}
2011-04-14 06:42:52 +04:00
static bool unix_strlower ( const char * src , size_t srclen , char * dest , size_t destlen )
{
size_t size ;
smb_ucs2_t * buffer = NULL ;
bool ret ;
if ( ! convert_string_talloc ( talloc_tos ( ) , CH_UNIX , CH_UTF16LE , src , srclen ,
( void * * ) ( void * ) & buffer , & size ) )
{
2012-08-08 23:07:54 +04:00
return false ;
2011-04-14 06:42:52 +04:00
}
if ( ! strlower_w ( buffer ) & & ( dest = = src ) ) {
TALLOC_FREE ( buffer ) ;
2012-08-08 23:06:34 +04:00
return true ;
2011-04-14 06:42:52 +04:00
}
ret = convert_string ( CH_UTF16LE , CH_UNIX , buffer , size , dest , destlen , & size ) ;
TALLOC_FREE ( buffer ) ;
return ret ;
}
2011-05-03 06:16:16 +04:00
#if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
/**
Convert a string to lower case .
* */
_PUBLIC_ void strlower_m ( char * s )
{
char * d ;
struct smb_iconv_handle * iconv_handle ;
iconv_handle = get_iconv_handle ( ) ;
d = s ;
while ( * s ) {
size_t c_size , c_size2 ;
codepoint_t c = next_codepoint_handle ( iconv_handle , s , & c_size ) ;
c_size2 = push_codepoint_handle ( iconv_handle , d , tolower_m ( c ) ) ;
if ( c_size2 > c_size ) {
DEBUG ( 0 , ( " FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strlower_m \n " ,
c , tolower_m ( c ) , ( int ) c_size , ( int ) c_size2 ) ) ;
smb_panic ( " codepoint expansion in strlower_m \n " ) ;
}
s + = c_size ;
d + = c_size2 ;
}
* d = 0 ;
}
# endif
2011-04-14 06:42:52 +04:00
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Convert a string to lower case .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2012-08-09 02:56:58 +04:00
bool strlower_m ( char * s )
2001-07-04 11:15:53 +04:00
{
2004-02-04 23:28:51 +03:00
size_t len ;
2004-09-01 21:39:27 +04:00
int errno_save ;
2012-08-09 02:56:58 +04:00
bool ret = false ;
2004-02-04 23:28:51 +03:00
2002-04-11 13:56:38 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2002-08-17 21:00:51 +04:00
2004-01-08 02:21:36 +03:00
while ( * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ) {
2011-07-20 00:19:29 +04:00
* s = tolower_m ( ( unsigned char ) * s ) ;
2003-01-17 09:40:12 +03:00
s + + ;
}
2002-04-11 13:56:38 +04:00
2002-08-17 21:00:51 +04:00
if ( ! * s )
2012-08-09 02:56:58 +04:00
return true ;
2002-04-11 13:56:38 +04:00
2001-07-04 11:15:53 +04:00
/* I assume that lowercased string takes the same number of bytes
* as source string even in UTF - 8 encoding . ( VIV ) */
2004-02-04 23:28:51 +03:00
len = strlen ( s ) + 1 ;
2004-09-01 21:39:27 +04:00
errno_save = errno ;
2004-02-04 23:28:51 +03:00
errno = 0 ;
2012-08-09 02:56:58 +04:00
ret = unix_strlower ( s , len , s , len ) ;
2004-02-04 23:28:51 +03:00
/* Catch mb conversion errors that may not terminate. */
2012-08-09 02:56:58 +04:00
if ( errno ) {
2004-02-04 23:28:51 +03:00
s [ len - 1 ] = ' \0 ' ;
2012-08-09 02:56:58 +04:00
}
2004-09-01 21:39:27 +04:00
errno = errno_save ;
2012-08-09 02:56:58 +04:00
return ret ;
2001-07-04 11:15:53 +04:00
}
2011-04-14 06:42:52 +04:00
static bool unix_strupper ( const char * src , size_t srclen , char * dest , size_t destlen )
{
size_t size ;
smb_ucs2_t * buffer ;
bool ret ;
if ( ! push_ucs2_talloc ( talloc_tos ( ) , & buffer , src , & size ) ) {
2012-08-08 23:10:01 +04:00
return false ;
2011-04-14 06:42:52 +04:00
}
if ( ! strupper_w ( buffer ) & & ( dest = = src ) ) {
TALLOC_FREE ( buffer ) ;
2012-08-08 23:06:34 +04:00
return true ;
2011-04-14 06:42:52 +04:00
}
ret = convert_string ( CH_UTF16LE , CH_UNIX , buffer , size , dest , destlen , & size ) ;
TALLOC_FREE ( buffer ) ;
return ret ;
}
2011-05-03 06:16:16 +04:00
#if 0 /* Alternate function that avoid talloc calls for ASCII and non ASCII */
/**
Convert a string to UPPER case .
* */
_PUBLIC_ void strupper_m ( char * s )
{
char * d ;
struct smb_iconv_handle * iconv_handle ;
iconv_handle = get_iconv_handle ( ) ;
d = s ;
while ( * s ) {
size_t c_size , c_size2 ;
codepoint_t c = next_codepoint_handle ( iconv_handle , s , & c_size ) ;
c_size2 = push_codepoint_handle ( iconv_handle , d , toupper_m ( c ) ) ;
if ( c_size2 > c_size ) {
DEBUG ( 0 , ( " FATAL: codepoint 0x%x (0x%x) expanded from %d to %d bytes in strupper_m \n " ,
c , toupper_m ( c ) , ( int ) c_size , ( int ) c_size2 ) ) ;
smb_panic ( " codepoint expansion in strupper_m \n " ) ;
}
s + = c_size ;
d + = c_size2 ;
}
* d = 0 ;
}
# endif
2003-02-24 06:09:08 +03:00
/**
2002-08-17 21:00:51 +04:00
Convert a string to upper case .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2012-08-08 23:16:40 +04:00
bool strupper_m ( char * s )
2001-07-04 11:15:53 +04:00
{
2004-02-04 23:28:51 +03:00
size_t len ;
2012-08-08 23:16:40 +04:00
bool ret = false ;
2004-02-04 23:28:51 +03:00
2002-04-11 13:56:38 +04:00
/* this is quite a common operation, so we want it to be
fast . We optimise for the ascii case , knowing that all our
supported multi - byte character sets are ascii - compatible
( ie . they match for the first 128 chars ) */
2002-08-17 21:00:51 +04:00
2004-01-08 02:21:36 +03:00
while ( * s & & ! ( ( ( unsigned char ) s [ 0 ] ) & 0x80 ) ) {
2014-11-09 15:48:09 +03:00
* s = toupper_ascii_fast_table [ ( unsigned char ) s [ 0 ] ] ;
2003-01-17 09:40:12 +03:00
s + + ;
}
2002-04-11 13:56:38 +04:00
2002-08-17 21:00:51 +04:00
if ( ! * s )
2012-08-08 23:16:40 +04:00
return true ;
2002-04-11 13:56:38 +04:00
2015-05-03 13:12:23 +03:00
/* I assume that uppercased string takes the same number of bytes
2001-07-04 11:15:53 +04:00
* as source string even in multibyte encoding . ( VIV ) */
2004-02-04 23:28:51 +03:00
len = strlen ( s ) + 1 ;
2012-08-08 23:16:40 +04:00
ret = unix_strupper ( s , len , s , len ) ;
2004-02-04 23:28:51 +03:00
/* Catch mb conversion errors that may not terminate. */
2014-09-12 19:46:06 +04:00
if ( ! ret ) {
2004-02-04 23:28:51 +03:00
s [ len - 1 ] = ' \0 ' ;
2012-08-08 23:16:40 +04:00
}
return ret ;
2001-07-04 11:15:53 +04:00
}
2001-12-10 03:39:01 +03:00
2003-02-24 06:09:08 +03:00
/**
2002-10-02 23:12:14 +04:00
Just a typesafety wrapper for snprintf into a fstring .
2003-02-24 06:09:08 +03:00
* */
2002-08-17 21:00:51 +04:00
2003-04-15 23:51:17 +04:00
int fstr_sprintf ( fstring s , const char * fmt , . . . )
2002-01-15 04:37:12 +03:00
{
va_list ap ;
int ret ;
va_start ( ap , fmt ) ;
2002-01-16 05:42:07 +03:00
ret = vsnprintf ( s , FSTRING_LEN , fmt , ap ) ;
2002-01-15 04:37:12 +03:00
va_end ( ap ) ;
return ret ;
}
2003-04-15 23:51:17 +04:00
2003-05-12 05:20:17 +04:00
/* read a SMB_BIG_UINT from a string */
2008-10-14 03:59:36 +04:00
uint64_t STR_TO_SMB_BIG_UINT ( const char * nptr , const char * * entptr )
2003-05-12 05:20:17 +04:00
{
2011-02-09 21:43:56 +03:00
uint64_t val = ( uint64_t ) - 1 ;
2003-05-12 05:20:17 +04:00
const char * p = nptr ;
2007-10-17 23:10:12 +04:00
2006-06-20 03:19:24 +04:00
if ( ! p ) {
2006-08-28 05:48:04 +04:00
if ( entptr ) {
* entptr = p ;
}
2006-06-20 03:19:24 +04:00
return val ;
}
while ( * p & & isspace ( * p ) )
2003-05-12 05:20:17 +04:00
p + + ;
2006-06-20 03:19:24 +04:00
2013-04-16 14:39:39 +04:00
sscanf ( p , " % " SCNu64 , & val ) ;
2003-05-12 05:20:17 +04:00
if ( entptr ) {
2006-06-20 03:19:24 +04:00
while ( * p & & isdigit ( * p ) )
2003-05-12 05:20:17 +04:00
p + + ;
* entptr = p ;
}
return val ;
}
2004-04-07 16:43:44 +04:00
2006-07-11 22:01:26 +04:00
/* Convert a size specification to a count of bytes. We accept the following
* suffixes :
* bytes if there is no suffix
* kK kibibytes
* mM mebibytes
* gG gibibytes
* tT tibibytes
* pP whatever the ISO name for petabytes is
*
* Returns 0 if the string can ' t be converted .
*/
2011-04-30 06:52:11 +04:00
uint64_t conv_str_size ( const char * str )
2006-07-11 22:01:26 +04:00
{
2011-04-30 06:52:11 +04:00
uint64_t lval ;
2019-06-04 10:04:15 +03:00
char * end ;
2019-01-28 14:54:07 +03:00
int error = 0 ;
2006-07-11 22:01:26 +04:00
if ( str = = NULL | | * str = = ' \0 ' ) {
return 0 ;
}
2019-06-04 10:04:15 +03:00
lval = smb_strtoull ( str , & end , 10 , & error , SMB_STR_STANDARD ) ;
2006-07-11 22:01:26 +04:00
2019-03-06 11:07:13 +03:00
if ( error ! = 0 ) {
2006-07-11 22:01:26 +04:00
return 0 ;
}
2019-06-04 10:04:15 +03:00
if ( * end = = ' \0 ' ) {
2010-03-28 15:16:58 +04:00
return lval ;
}
if ( strwicmp ( end , " K " ) = = 0 ) {
2011-04-30 06:52:11 +04:00
lval * = 1024ULL ;
2010-03-28 15:16:58 +04:00
} else if ( strwicmp ( end , " M " ) = = 0 ) {
2011-04-30 06:52:11 +04:00
lval * = ( 1024ULL * 1024ULL ) ;
2010-03-28 15:16:58 +04:00
} else if ( strwicmp ( end , " G " ) = = 0 ) {
2011-04-30 06:52:11 +04:00
lval * = ( 1024ULL * 1024ULL *
1024ULL ) ;
2010-03-28 15:16:58 +04:00
} else if ( strwicmp ( end , " T " ) = = 0 ) {
2011-04-30 06:52:11 +04:00
lval * = ( 1024ULL * 1024ULL *
1024ULL * 1024ULL ) ;
2010-03-28 15:16:58 +04:00
} else if ( strwicmp ( end , " P " ) = = 0 ) {
2011-04-30 06:52:11 +04:00
lval * = ( 1024ULL * 1024ULL *
1024ULL * 1024ULL *
1024ULL ) ;
2010-03-28 15:16:58 +04:00
} else {
return 0 ;
}
2006-07-11 22:01:26 +04:00
return lval ;
}
2007-11-24 19:27:54 +03:00
char * talloc_asprintf_strupper_m ( TALLOC_CTX * t , const char * fmt , . . . )
{
va_list ap ;
char * ret ;
va_start ( ap , fmt ) ;
ret = talloc_vasprintf ( t , fmt , ap ) ;
va_end ( ap ) ;
if ( ret = = NULL ) {
return NULL ;
}
2012-08-09 02:35:28 +04:00
if ( ! strupper_m ( ret ) ) {
TALLOC_FREE ( ret ) ;
return NULL ;
}
2007-11-24 19:27:54 +03:00
return ret ;
}
2008-06-04 03:29:22 +04:00
char * talloc_asprintf_strlower_m ( TALLOC_CTX * t , const char * fmt , . . . )
{
va_list ap ;
char * ret ;
va_start ( ap , fmt ) ;
ret = talloc_vasprintf ( t , fmt , ap ) ;
va_end ( ap ) ;
if ( ret = = NULL ) {
return NULL ;
}
2012-08-09 04:01:00 +04:00
if ( ! strlower_m ( ret ) ) {
TALLOC_FREE ( ret ) ;
return NULL ;
}
2008-06-04 03:29:22 +04:00
return ret ;
}
2006-02-04 01:19:41 +03:00
/********************************************************************
Check a string for any occurrences of a specified list of invalid
characters .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-10-17 23:10:12 +04:00
bool validate_net_name ( const char * name ,
const char * invalid_chars ,
int max_len )
2006-02-04 01:19:41 +03:00
{
int i ;
2010-11-10 02:07:49 +03:00
if ( ! name ) {
return false ;
}
2006-02-04 01:19:41 +03:00
for ( i = 0 ; i < max_len & & name [ i ] ; i + + ) {
/* fail if strchr_m() finds one of the invalid characters */
if ( name [ i ] & & strchr_m ( invalid_chars , name [ i ] ) ) {
2007-10-17 23:10:12 +04:00
return false ;
2006-02-04 01:19:41 +03:00
}
}
2007-10-17 23:10:12 +04:00
return true ;
2006-02-04 01:19:41 +03:00
}
2006-07-11 22:01:26 +04:00
2007-05-14 18:23:51 +04:00
/*******************************************************************
Add a shell escape character ' \ ' to any character not in a known list
of characters . UNIX charset format .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-05 16:58:18 +04:00
# define INCLUDE_LIST "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_ / \t.,"
2007-05-14 18:23:51 +04:00
# define INSIDE_DQUOTE_LIST "$`\n\"\\"
char * escape_shell_string ( const char * src )
{
size_t srclen = strlen ( src ) ;
2007-06-16 15:48:11 +04:00
char * ret = SMB_MALLOC_ARRAY ( char , ( srclen * 2 ) + 1 ) ;
2007-05-14 18:23:51 +04:00
char * dest = ret ;
2007-10-17 23:10:12 +04:00
bool in_s_quote = false ;
bool in_d_quote = false ;
bool next_escaped = false ;
2007-05-14 18:23:51 +04:00
if ( ! ret ) {
return NULL ;
}
while ( * src ) {
size_t c_size ;
codepoint_t c = next_codepoint ( src , & c_size ) ;
if ( c = = INVALID_CODEPOINT ) {
SAFE_FREE ( ret ) ;
return NULL ;
}
if ( c_size > 1 ) {
memcpy ( dest , src , c_size ) ;
src + = c_size ;
dest + = c_size ;
2007-10-17 23:10:12 +04:00
next_escaped = false ;
2007-05-14 18:23:51 +04:00
continue ;
}
/*
* Deal with backslash escaped state .
* This only lasts for one character .
*/
if ( next_escaped ) {
* dest + + = * src + + ;
2007-10-17 23:10:12 +04:00
next_escaped = false ;
2007-05-14 18:23:51 +04:00
continue ;
}
/*
* Deal with single quote state . The
* only thing we care about is exiting
* this state .
*/
if ( in_s_quote ) {
if ( * src = = ' \' ' ) {
2007-10-17 23:10:12 +04:00
in_s_quote = false ;
2007-05-14 18:23:51 +04:00
}
* dest + + = * src + + ;
continue ;
}
2007-10-17 23:10:12 +04:00
/*
2007-05-14 18:23:51 +04:00
* Deal with double quote state . The most
* complex state . We must cope with \ , meaning
* possibly escape next char ( depending what it
* is ) , " , meaning exit this state, and possibly
* add an \ escape to any unprotected character
* ( listed in INSIDE_DQUOTE_LIST ) .
*/
if ( in_d_quote ) {
if ( * src = = ' \\ ' ) {
2007-10-17 23:10:12 +04:00
/*
2007-05-14 18:23:51 +04:00
* Next character might be escaped .
* We have to peek . Inside double
* quotes only INSIDE_DQUOTE_LIST
* characters are escaped by a \ .
*/
char nextchar ;
c = next_codepoint ( & src [ 1 ] , & c_size ) ;
if ( c = = INVALID_CODEPOINT ) {
SAFE_FREE ( ret ) ;
return NULL ;
}
if ( c_size > 1 ) {
/*
* Don ' t escape the next char .
* Just copy the \ .
*/
* dest + + = * src + + ;
continue ;
}
nextchar = src [ 1 ] ;
2007-10-17 23:10:12 +04:00
if ( nextchar & & strchr ( INSIDE_DQUOTE_LIST ,
( int ) nextchar ) ) {
next_escaped = true ;
2007-05-14 18:23:51 +04:00
}
* dest + + = * src + + ;
continue ;
}
if ( * src = = ' \" ' ) {
/* Exit double quote state. */
2007-10-17 23:10:12 +04:00
in_d_quote = false ;
2007-05-14 18:23:51 +04:00
* dest + + = * src + + ;
continue ;
}
/*
* We know the character isn ' t \ or " ,
* so escape it if it ' s any of the other
* possible unprotected characters .
*/
if ( strchr ( INSIDE_DQUOTE_LIST , ( int ) * src ) ) {
* dest + + = ' \\ ' ;
}
* dest + + = * src + + ;
continue ;
}
2007-10-17 23:10:12 +04:00
/*
2007-05-14 18:23:51 +04:00
* From here to the end of the loop we ' re
* not in the single or double quote state .
*/
if ( * src = = ' \\ ' ) {
/* Next character must be escaped. */
2007-10-17 23:10:12 +04:00
next_escaped = true ;
2007-05-14 18:23:51 +04:00
* dest + + = * src + + ;
continue ;
}
if ( * src = = ' \' ' ) {
/* Go into single quote state. */
2007-10-17 23:10:12 +04:00
in_s_quote = true ;
2007-05-14 18:23:51 +04:00
* dest + + = * src + + ;
continue ;
}
if ( * src = = ' \" ' ) {
/* Go into double quote state. */
2007-10-17 23:10:12 +04:00
in_d_quote = true ;
2007-05-14 18:23:51 +04:00
* dest + + = * src + + ;
continue ;
}
/* Check if we need to escape the character. */
if ( ! strchr ( INCLUDE_LIST , ( int ) * src ) ) {
* dest + + = ' \\ ' ;
}
* dest + + = * src + + ;
}
* dest + + = ' \0 ' ;
return ret ;
}
2008-11-07 05:53:00 +03:00
2013-12-29 16:56:44 +04:00
/*
* 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 .
*/
ssize_t full_path_tos ( const char * dir , const char * name ,
char * tmpbuf , size_t tmpbuf_len ,
char * * pdst , char * * to_free )
{
size_t dirlen , namelen , len ;
char * dst ;
dirlen = strlen ( dir ) ;
namelen = strlen ( name ) ;
len = dirlen + namelen + 1 ;
if ( len < tmpbuf_len ) {
dst = tmpbuf ;
* to_free = NULL ;
} else {
dst = talloc_array ( talloc_tos ( ) , char , len + 1 ) ;
if ( dst = = NULL ) {
return - 1 ;
}
* to_free = dst ;
}
memcpy ( dst , dir , dirlen ) ;
dst [ dirlen ] = ' / ' ;
memcpy ( dst + dirlen + 1 , name , namelen + 1 ) ;
* pdst = dst ;
return len ;
}