2003-08-13 01:53:07 +00:00
/*
* Unix SMB / CIFS implementation .
* SMB parameters and setup
* Copyright ( C ) Andrew Tridgell 1992 - 1998 Modified by Jeremy Allison 1995.
2005-09-28 21:54:29 +00:00
*
* Added afdgets ( ) Jelmer Vernooij 2005
2014-12-07 14:13:51 +01:00
*
2003-08-13 01:53:07 +00: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 the Free
2007-07-10 03:04:16 +00:00
* Software Foundation ; either version 3 of the License , or ( at your option )
2003-08-13 01:53:07 +00:00
* any later version .
2014-12-07 14:13:51 +01:00
*
2003-08-13 01:53:07 +00: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 .
2014-12-07 14:13:51 +01:00
*
2003-08-13 01:53:07 +00:00
* You should have received a copy of the GNU General Public License along with
2007-07-10 05:23:25 +00:00
* this program ; if not , see < http : //www.gnu.org/licenses/>.
2003-08-13 01:53:07 +00:00
*/
2011-10-21 13:42:34 +02:00
# include "replace.h"
2004-11-02 00:24:21 +00:00
# include "system/shmem.h"
2005-02-10 05:09:35 +00:00
# include "system/filesys.h"
2011-10-21 13:42:34 +02:00
# include <talloc.h>
# include "lib/util/samba_util.h"
2018-12-27 04:25:47 -05:00
# include "lib/util/sys_popen.h"
# include "lib/util/sys_rw.h"
2011-10-21 13:42:34 +02:00
# include "lib/util/debug.h"
2003-08-13 01:53:07 +00:00
2006-02-28 13:12:39 +00:00
/**
2014-12-07 14:13:51 +01:00
* Read one line ( data until next newline or eof ) and allocate it
2006-02-28 13:12:39 +00:00
*/
2006-03-05 17:15:19 +00:00
_PUBLIC_ char * afdgets ( int fd , TALLOC_CTX * mem_ctx , size_t hint )
2005-09-28 21:54:29 +00:00
{
char * data = NULL ;
ssize_t alloc_size = 0 , offset = 0 , ret ;
int p ;
if ( hint < = 0 ) hint = 0x100 ;
do {
alloc_size + = hint ;
data = talloc_realloc ( mem_ctx , data , char , alloc_size ) ;
if ( ! data )
return NULL ;
ret = read ( fd , data + offset , hint ) ;
2006-08-20 21:57:08 +00:00
if ( ret = = 0 ) {
return NULL ;
}
2005-09-28 21:54:29 +00:00
if ( ret = = - 1 ) {
talloc_free ( data ) ;
return NULL ;
}
/* Find newline */
for ( p = 0 ; p < ret ; p + + ) {
if ( data [ offset + p ] = = ' \n ' )
break ;
}
if ( p < ret ) {
data [ offset + p ] = ' \0 ' ;
/* Go back to position of newline */
lseek ( fd , p - ret + 1 , SEEK_CUR ) ;
return data ;
}
offset + = ret ;
2019-06-21 15:11:49 +10:00
} while ( ( size_t ) ret = = hint ) ;
2005-09-28 21:54:29 +00:00
data [ offset ] = ' \0 ' ;
return data ;
}
2003-08-13 01:53:07 +00:00
2018-03-21 12:49:38 +01:00
char * fgets_slash ( TALLOC_CTX * mem_ctx , char * s2 , size_t maxlen , FILE * f )
2016-11-21 19:20:10 +01:00
{
char * s = s2 ;
2018-03-21 12:49:38 +01:00
size_t len = 0 ;
2016-11-21 19:20:10 +01:00
int c ;
bool start_of_line = true ;
if ( feof ( f ) ) {
return NULL ;
}
if ( maxlen < 2 ) {
return NULL ;
}
if ( s2 = = NULL ) {
maxlen = MIN ( maxlen , 8 ) ;
s = talloc_array ( mem_ctx , char , maxlen ) ;
}
if ( s = = NULL ) {
return NULL ;
}
* s = 0 ;
while ( len < maxlen - 1 ) {
c = getc ( f ) ;
switch ( c )
{
case ' \r ' :
break ;
case ' \n ' :
while ( len > 0 & & s [ len - 1 ] = = ' ' ) {
s [ - - len ] = 0 ;
}
if ( len > 0 & & s [ len - 1 ] = = ' \\ ' ) {
s [ - - len ] = 0 ;
start_of_line = true ;
break ;
}
return s ;
case EOF :
if ( len < = 0 & & ( s2 = = NULL ) ) {
TALLOC_FREE ( s ) ;
}
return ( len > 0 ) ? s : NULL ;
case ' ' :
if ( start_of_line ) {
break ;
}
2017-07-26 18:41:25 +02:00
FALL_THROUGH ;
2016-11-21 19:20:10 +01:00
default :
start_of_line = false ;
s [ len + + ] = c ;
s [ len ] = 0 ;
}
if ( ( s2 = = NULL ) & & ( len > maxlen - 3 ) ) {
2019-06-21 15:10:19 +10:00
size_t m ;
2016-11-21 19:20:10 +01:00
char * t ;
m = maxlen * 2 ;
if ( m < maxlen ) {
DBG_ERR ( " length overflow " ) ;
TALLOC_FREE ( s ) ;
return NULL ;
}
maxlen = m ;
t = talloc_realloc ( mem_ctx , s , char , maxlen ) ;
if ( t = = NULL ) {
DBG_ERR ( " failed to expand buffer! \n " ) ;
TALLOC_FREE ( s ) ;
return NULL ;
}
s = t ;
}
}
return s ;
}
2003-08-13 01:53:07 +00:00
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
load a file into memory from a fd .
2006-02-28 13:12:39 +00:00
* */
2008-10-12 17:34:43 +02:00
_PUBLIC_ char * fd_load ( int fd , size_t * psize , size_t maxsize , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
2019-02-21 18:37:08 +01:00
FILE * file ;
char * p = NULL ;
size_t size = 0 ;
size_t chunk = 1024 ;
int err ;
if ( maxsize = = 0 ) {
maxsize = SIZE_MAX ;
}
2003-08-13 01:53:07 +00:00
2019-02-21 18:37:08 +01:00
file = fdopen ( fd , " r " ) ;
if ( file = = NULL ) {
return NULL ;
}
2003-08-13 01:53:07 +00:00
2019-02-21 18:37:08 +01:00
while ( size < maxsize ) {
size_t newbufsize ;
size_t nread ;
2008-10-12 17:34:43 +02:00
2019-02-21 18:37:08 +01:00
chunk = MIN ( chunk , ( maxsize - size ) ) ;
2008-10-12 17:34:43 +02:00
2019-02-21 18:37:08 +01:00
newbufsize = size + ( chunk + 1 ) ; /* chunk+1 can't overflow */
if ( newbufsize < size ) {
goto fail ; /* overflow */
}
2003-08-13 01:53:07 +00:00
2019-02-21 18:37:08 +01:00
p = talloc_realloc ( mem_ctx , p , char , newbufsize ) ;
if ( p = = NULL ) {
goto fail ;
}
nread = fread ( p + size , 1 , chunk , file ) ;
size + = nread ;
if ( nread ! = chunk ) {
break ;
}
2003-08-13 01:53:07 +00:00
}
2019-02-21 18:37:08 +01:00
err = ferror ( file ) ;
if ( err ! = 0 ) {
goto fail ;
}
2003-08-13 01:53:07 +00:00
2019-02-21 18:37:08 +01:00
p [ size ] = ' \0 ' ;
if ( psize ! = NULL ) {
* psize = size ;
}
fclose ( file ) ;
2003-08-13 01:53:07 +00:00
return p ;
2019-02-21 18:37:08 +01:00
fail :
TALLOC_FREE ( p ) ;
fclose ( file ) ;
return NULL ;
2003-08-13 01:53:07 +00:00
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
load a file into memory
2006-02-28 13:12:39 +00:00
* */
2008-10-12 17:34:43 +02:00
_PUBLIC_ char * file_load ( const char * fname , size_t * size , size_t maxsize , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
int fd ;
char * p ;
if ( ! fname | | ! * fname ) return NULL ;
2014-12-07 14:13:51 +01:00
2003-08-13 01:53:07 +00:00
fd = open ( fname , O_RDONLY ) ;
if ( fd = = - 1 ) return NULL ;
2008-10-12 17:34:43 +02:00
p = fd_load ( fd , size , maxsize , mem_ctx ) ;
2003-08-13 01:53:07 +00:00
close ( fd ) ;
return p ;
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
parse a buffer into lines
2006-10-28 06:06:15 +00:00
' p ' will be freed on error , and otherwise will be made a child of the returned array
2006-02-28 13:12:39 +00:00
* */
2008-10-12 17:34:43 +02:00
char * * file_lines_parse ( char * p , size_t size , int * numlines , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
2018-12-14 14:43:57 +11:00
unsigned int i ;
2003-08-13 01:53:07 +00:00
char * s , * * ret ;
if ( ! p ) return NULL ;
for ( s = p , i = 0 ; s < p + size ; s + + ) {
if ( s [ 0 ] = = ' \n ' ) i + + ;
}
2014-12-26 19:41:23 +00:00
ret = talloc_zero_array ( mem_ctx , char * , i + 2 ) ;
2003-08-13 01:53:07 +00:00
if ( ! ret ) {
2005-08-30 17:21:41 +00:00
talloc_free ( p ) ;
2003-08-13 01:53:07 +00:00
return NULL ;
2014-12-07 14:13:51 +01:00
}
2006-10-28 06:06:15 +00:00
talloc_steal ( ret , p ) ;
2014-12-07 14:13:51 +01:00
2003-08-13 01:53:07 +00:00
ret [ 0 ] = p ;
2018-12-14 14:43:57 +11:00
for ( s = p , i = 1 ; s < p + size ; s + + ) {
2003-08-13 01:53:07 +00:00
if ( s [ 0 ] = = ' \n ' ) {
s [ 0 ] = 0 ;
ret [ i ] = s + 1 ;
2018-12-14 14:43:57 +11:00
i + + ;
2003-08-13 01:53:07 +00:00
}
if ( s [ 0 ] = = ' \r ' ) s [ 0 ] = 0 ;
}
2006-12-09 03:12:33 +00:00
/* remove any blank lines at the end */
while ( i > 0 & & ret [ i - 1 ] [ 0 ] = = 0 ) {
i - - ;
}
if ( numlines ) * numlines = i ;
2003-08-13 01:53:07 +00:00
return ret ;
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
load a file into memory and return an array of pointers to lines in the file
2014-12-07 14:13:51 +01:00
must be freed with talloc_free ( ) .
2006-02-28 13:12:39 +00:00
* */
2008-10-12 17:34:43 +02:00
_PUBLIC_ char * * file_lines_load ( const char * fname , int * numlines , size_t maxsize , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
char * p ;
size_t size ;
2008-10-12 17:34:43 +02:00
p = file_load ( fname , & size , maxsize , mem_ctx ) ;
2003-08-13 01:53:07 +00:00
if ( ! p ) return NULL ;
2006-10-28 06:06:15 +00:00
return file_lines_parse ( p , size , numlines , mem_ctx ) ;
2003-08-13 01:53:07 +00:00
}
2006-02-28 13:12:39 +00:00
/**
2003-08-13 01:53:07 +00:00
load a fd into memory and return an array of pointers to lines in the file
2005-08-30 17:21:41 +00:00
must be freed with talloc_free ( ) . If convert is true calls unix_to_dos on
2003-08-13 01:53:07 +00:00
the list .
2006-02-28 13:12:39 +00:00
* */
2008-10-12 17:34:43 +02:00
_PUBLIC_ char * * fd_lines_load ( int fd , int * numlines , size_t maxsize , TALLOC_CTX * mem_ctx )
2003-08-13 01:53:07 +00:00
{
char * p ;
size_t size ;
2008-10-12 17:34:43 +02:00
p = fd_load ( fd , & size , maxsize , mem_ctx ) ;
2003-08-13 01:53:07 +00:00
if ( ! p ) return NULL ;
2006-10-28 06:06:15 +00:00
return file_lines_parse ( p , size , numlines , mem_ctx ) ;
2003-08-13 01:53:07 +00:00
}
2013-10-29 17:48:11 +01:00
_PUBLIC_ bool file_save_mode ( const char * fname , const void * packet ,
size_t length , mode_t mode )
2003-08-13 01:53:07 +00:00
{
2019-06-21 15:11:49 +10:00
ssize_t num_written ;
2003-08-13 01:53:07 +00:00
int fd ;
2019-11-11 13:52:22 +13:00
fd = open ( fname , O_WRONLY | O_CREAT | O_EXCL , mode ) ;
2003-08-13 01:53:07 +00:00
if ( fd = = - 1 ) {
2007-08-27 17:21:16 +00:00
return false ;
2003-08-13 01:53:07 +00:00
}
2019-06-21 15:11:49 +10:00
num_written = write ( fd , packet , length ) ;
if ( num_written = = - 1 | | ( size_t ) num_written ! = length ) {
2009-07-18 16:28:53 +07:00
close ( fd ) ;
2007-08-27 17:21:16 +00:00
return false ;
2003-08-13 01:53:07 +00:00
}
close ( fd ) ;
2007-08-27 17:21:16 +00:00
return true ;
2003-08-13 01:53:07 +00:00
}
2005-04-14 08:24:36 +00:00
2013-10-29 17:48:11 +01:00
/**
save a lump of data into a file . Mostly used for debugging
*/
_PUBLIC_ bool file_save ( const char * fname , const void * packet , size_t length )
{
return file_save_mode ( fname , packet , length , 0644 ) ;
}
2008-04-02 04:53:27 +02:00
_PUBLIC_ int vfdprintf ( int fd , const char * format , va_list ap )
2005-09-15 19:52:13 +00:00
{
char * p ;
int len , ret ;
va_list ap2 ;
2006-04-08 16:05:21 +00:00
va_copy ( ap2 , ap ) ;
2005-09-15 19:52:13 +00:00
len = vasprintf ( & p , format , ap2 ) ;
2007-02-06 05:26:25 +00:00
va_end ( ap2 ) ;
2005-09-15 19:52:13 +00:00
if ( len < = 0 ) return len ;
ret = write ( fd , p , len ) ;
SAFE_FREE ( p ) ;
return ret ;
}
2008-04-02 04:53:27 +02:00
_PUBLIC_ int fdprintf ( int fd , const char * format , . . . )
2005-09-15 19:52:13 +00:00
{
va_list ap ;
int ret ;
va_start ( ap , format ) ;
ret = vfdprintf ( fd , format , ap ) ;
va_end ( ap ) ;
return ret ;
}
2006-10-28 06:06:15 +00:00
2010-02-11 20:19:40 +11:00
/*
compare two files , return true if the two files have the same content
*/
bool file_compare ( const char * path1 , const char * path2 )
{
2019-05-01 15:34:22 +02:00
FILE * f1 = NULL , * f2 = NULL ;
uint8_t buf1 [ 1024 ] , buf2 [ 1024 ] ;
bool ret = false ;
f1 = fopen ( path1 , " r " ) ;
if ( f1 = = NULL ) {
goto done ;
2010-02-11 20:19:40 +11:00
}
2019-05-01 15:34:22 +02:00
f2 = fopen ( path2 , " r " ) ;
if ( f2 = = NULL ) {
goto done ;
2010-02-11 20:19:40 +11:00
}
2019-05-01 15:34:22 +02:00
while ( ! feof ( f1 ) ) {
size_t n1 = fread ( buf1 , 1 , sizeof ( buf1 ) , f1 ) ;
size_t n2 = fread ( buf2 , 1 , sizeof ( buf2 ) , f2 ) ;
if ( n1 ! = n2 ) {
goto done ;
}
if ( n1 = = 0 ) {
ret = ( feof ( f1 ) & & feof ( f2 ) ) ;
goto done ;
}
if ( memcmp ( buf1 , buf2 , n1 ) ! = 0 ) {
goto done ;
}
if ( n1 < sizeof ( buf1 ) ) {
bool has_error = ( ferror ( f1 ) | | ferror ( f2 ) ) ;
if ( has_error ) {
goto done ;
}
}
}
ret = true ;
done :
if ( f2 ! = NULL ) {
fclose ( f2 ) ;
}
if ( f1 ! = NULL ) {
fclose ( f1 ) ;
}
return ret ;
2010-02-11 20:19:40 +11:00
}
2018-12-27 04:25:47 -05:00
2019-05-16 21:56:13 -07:00
/**
Load from a pipe into memory .
* */
char * file_ploadv ( char * const argl [ ] , size_t * size )
{
int fd , n ;
char * p = NULL ;
char buf [ 1024 ] ;
size_t total ;
fd = sys_popenv ( argl ) ;
if ( fd = = - 1 ) {
return NULL ;
}
total = 0 ;
while ( ( n = sys_read ( fd , buf , sizeof ( buf ) ) ) > 0 ) {
p = talloc_realloc ( NULL , p , char , total + n + 1 ) ;
if ( p = = NULL ) {
DBG_ERR ( " failed to expand buffer! \n " ) ;
close ( fd ) ;
return NULL ;
}
memcpy ( p + total , buf , n ) ;
total + = n ;
}
if ( p ! = NULL ) {
p [ total ] = 0 ;
}
/*
* FIXME : Perhaps ought to check that the command completed
* successfully ( returned 0 ) ; if not the data may be
* truncated .
*/
sys_pclose ( fd ) ;
if ( size ) {
* size = total ;
}
return p ;
}