2003-08-13 05:53:07 +04:00
/*
* Unix SMB / CIFS implementation .
* SMB parameters and setup
* Copyright ( C ) Andrew Tridgell 1992 - 1998 Modified by Jeremy Allison 1995.
2005-09-29 01:54:29 +04:00
*
* Added afdgets ( ) Jelmer Vernooij 2005
2003-08-13 05:53:07 +04: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
* Software Foundation ; either version 2 of the License , or ( at your option )
* any later version .
*
* 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 .
*
* You should have received a copy of the GNU General Public License along with
* this program ; if not , write to the Free Software Foundation , Inc . , 675
* Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-02 03:24:21 +03:00
# include "system/shmem.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2003-08-13 05:53:07 +04:00
2006-02-28 16:12:39 +03:00
/**
* @ file
* @ brief File - related utility functions
*/
/**
2003-08-13 05:53:07 +04:00
read a line from a file with possible \ continuation chars .
Blanks at the start or end of a line are stripped .
The string will be allocated if s2 is NULL
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * fgets_slash ( char * s2 , int maxlen , XFILE * f )
2003-08-13 05:53:07 +04:00
{
char * s = s2 ;
int len = 0 ;
int c ;
BOOL start_of_line = True ;
if ( x_feof ( f ) )
return ( NULL ) ;
if ( maxlen < 2 ) return ( NULL ) ;
if ( ! s2 )
{
maxlen = MIN ( maxlen , 8 ) ;
s = ( char * ) malloc ( maxlen ) ;
}
if ( ! s ) return ( NULL ) ;
* s = 0 ;
while ( len < maxlen - 1 )
{
c = x_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 )
SAFE_FREE ( s ) ;
return ( len > 0 ? s : NULL ) ;
case ' ' :
if ( start_of_line )
break ;
2006-04-08 06:40:15 +04:00
/* fall through */
2003-08-13 05:53:07 +04:00
default :
start_of_line = False ;
s [ len + + ] = c ;
s [ len ] = 0 ;
}
if ( ! s2 & & len > maxlen - 3 )
{
char * t ;
maxlen * = 2 ;
2004-12-03 09:42:06 +03:00
t = realloc_p ( s , char , maxlen ) ;
2003-08-13 05:53:07 +04:00
if ( ! t ) {
DEBUG ( 0 , ( " fgets_slash: failed to expand buffer! \n " ) ) ;
SAFE_FREE ( s ) ;
return ( NULL ) ;
} else s = t ;
}
}
return ( s ) ;
}
2006-02-28 16:12:39 +03:00
/**
* Read one line ( data until next newline or eof ) and allocate it
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * afdgets ( int fd , TALLOC_CTX * mem_ctx , size_t hint )
2005-09-29 01:54:29 +04: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 ) ;
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 ;
} while ( ret = = hint ) ;
data [ offset ] = ' \0 ' ;
return data ;
}
2003-08-13 05:53:07 +04:00
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
load a file into memory from a fd .
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * fd_load ( int fd , size_t * size , TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
2004-11-01 23:21:54 +03:00
struct stat sbuf ;
2003-08-13 05:53:07 +04:00
char * p ;
2004-11-01 23:21:54 +03:00
if ( fstat ( fd , & sbuf ) ! = 0 ) return NULL ;
2003-08-13 05:53:07 +04:00
2005-07-10 05:10:09 +04:00
p = ( char * ) talloc_size ( mem_ctx , sbuf . st_size + 1 ) ;
2003-08-13 05:53:07 +04:00
if ( ! p ) return NULL ;
if ( read ( fd , p , sbuf . st_size ) ! = sbuf . st_size ) {
2005-07-10 05:10:09 +04:00
talloc_free ( p ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
p [ sbuf . st_size ] = 0 ;
if ( size ) * size = sbuf . st_size ;
return p ;
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
load a file into memory
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * file_load ( const char * fname , size_t * size , TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
int fd ;
char * p ;
if ( ! fname | | ! * fname ) return NULL ;
fd = open ( fname , O_RDONLY ) ;
if ( fd = = - 1 ) return NULL ;
2005-07-10 05:10:09 +04:00
p = fd_load ( fd , size , mem_ctx ) ;
2003-08-13 05:53:07 +04:00
close ( fd ) ;
return p ;
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
mmap ( if possible ) or read a file
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ void * map_file ( const char * fname , size_t size )
2003-08-13 05:53:07 +04:00
{
size_t s2 = 0 ;
void * p = NULL ;
# ifdef HAVE_MMAP
2004-08-31 12:21:29 +04:00
int fd ;
fd = open ( fname , O_RDONLY , 0 ) ;
if ( fd = = - 1 ) {
DEBUG ( 2 , ( " Failed to load %s - %s \n " , fname , strerror ( errno ) ) ) ;
return NULL ;
}
p = mmap ( NULL , size , PROT_READ , MAP_SHARED | MAP_FILE , fd , 0 ) ;
close ( fd ) ;
if ( p = = MAP_FAILED ) {
DEBUG ( 1 , ( " Failed to mmap %s - %s \n " , fname , strerror ( errno ) ) ) ;
return NULL ;
2003-08-13 05:53:07 +04:00
}
# endif
if ( ! p ) {
2005-07-10 05:10:09 +04:00
p = file_load ( fname , & s2 , talloc_autofree_context ( ) ) ;
2003-08-13 05:53:07 +04:00
if ( ! p ) return NULL ;
if ( s2 ! = size ) {
DEBUG ( 1 , ( " incorrect size for %s - got %d expected %d \n " ,
2005-07-17 13:20:52 +04:00
fname , ( int ) s2 , ( int ) size ) ) ;
2005-07-10 05:10:09 +04:00
talloc_free ( p ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
}
return p ;
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
parse a buffer into lines
2006-02-28 16:12:39 +03:00
* */
2005-08-30 21:21:41 +04:00
static char * * file_lines_parse ( char * p , size_t size , int * numlines , TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
int i ;
char * s , * * ret ;
if ( ! p ) return NULL ;
for ( s = p , i = 0 ; s < p + size ; s + + ) {
if ( s [ 0 ] = = ' \n ' ) i + + ;
}
2005-08-30 21:21:41 +04:00
ret = talloc_array ( mem_ctx , char * , i + 2 ) ;
2003-08-13 05:53:07 +04:00
if ( ! ret ) {
2005-08-30 21:21:41 +04:00
talloc_free ( p ) ;
2003-08-13 05:53:07 +04:00
return NULL ;
}
2005-08-30 21:21:41 +04:00
talloc_reference ( ret , p ) ;
2003-08-13 05:53:07 +04:00
memset ( ret , 0 , sizeof ( ret [ 0 ] ) * ( i + 2 ) ) ;
if ( numlines ) * numlines = i ;
ret [ 0 ] = p ;
for ( s = p , i = 0 ; s < p + size ; s + + ) {
if ( s [ 0 ] = = ' \n ' ) {
s [ 0 ] = 0 ;
i + + ;
ret [ i ] = s + 1 ;
}
if ( s [ 0 ] = = ' \r ' ) s [ 0 ] = 0 ;
}
return ret ;
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
load a file into memory and return an array of pointers to lines in the file
2005-08-30 21:21:41 +04:00
must be freed with talloc_free ( ) .
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * * file_lines_load ( const char * fname , int * numlines , TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
char * p ;
2005-08-30 21:21:41 +04:00
char * * lines ;
2003-08-13 05:53:07 +04:00
size_t size ;
2005-07-10 05:10:09 +04:00
p = file_load ( fname , & size , mem_ctx ) ;
2003-08-13 05:53:07 +04:00
if ( ! p ) return NULL ;
2005-08-30 21:21:41 +04:00
lines = file_lines_parse ( p , size , numlines , mem_ctx ) ;
talloc_free ( p ) ;
return lines ;
2003-08-13 05:53:07 +04:00
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
load a fd into memory and return an array of pointers to lines in the file
2005-08-30 21:21:41 +04:00
must be freed with talloc_free ( ) . If convert is true calls unix_to_dos on
2003-08-13 05:53:07 +04:00
the list .
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ char * * fd_lines_load ( int fd , int * numlines , TALLOC_CTX * mem_ctx )
2003-08-13 05:53:07 +04:00
{
char * p ;
2005-08-30 21:21:41 +04:00
char * * lines ;
2003-08-13 05:53:07 +04:00
size_t size ;
2005-07-10 05:10:09 +04:00
p = fd_load ( fd , & size , mem_ctx ) ;
2003-08-13 05:53:07 +04:00
if ( ! p ) return NULL ;
2005-08-30 21:21:41 +04:00
lines = file_lines_parse ( p , size , numlines , mem_ctx ) ;
talloc_free ( p ) ;
return lines ;
2003-08-13 05:53:07 +04:00
}
2006-02-28 16:12:39 +03:00
/**
2005-09-16 00:03:35 +04:00
take a list of lines and modify them to produce a list where \ continues
2003-08-13 05:53:07 +04:00
a line
2006-02-28 16:12:39 +03:00
* */
2006-03-05 20:15:19 +03:00
_PUBLIC_ void file_lines_slashcont ( char * * lines )
2003-08-13 05:53:07 +04:00
{
int i , j ;
for ( i = 0 ; lines [ i ] ; ) {
int len = strlen ( lines [ i ] ) ;
if ( lines [ i ] [ len - 1 ] = = ' \\ ' ) {
lines [ i ] [ len - 1 ] = ' ' ;
if ( lines [ i + 1 ] ) {
char * p = & lines [ i ] [ len ] ;
while ( p < lines [ i + 1 ] ) * p + + = ' ' ;
for ( j = i + 1 ; lines [ j ] ; j + + ) lines [ j ] = lines [ j + 1 ] ;
}
} else {
i + + ;
}
}
}
2006-02-28 16:12:39 +03:00
/**
2003-08-13 05:53:07 +04:00
save a lump of data into a file . Mostly used for debugging
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ BOOL file_save ( const char * fname , const void * packet , size_t length )
2003-08-13 05:53:07 +04:00
{
int fd ;
fd = open ( fname , O_WRONLY | O_CREAT | O_TRUNC , 0644 ) ;
if ( fd = = - 1 ) {
return False ;
}
if ( write ( fd , packet , length ) ! = ( size_t ) length ) {
return False ;
}
close ( fd ) ;
return True ;
}
2005-04-14 12:24:36 +04:00
2006-02-28 16:12:39 +03:00
/**
2005-04-14 12:24:36 +04:00
see if a file exists
*/
2006-03-05 20:15:19 +03:00
_PUBLIC_ BOOL file_exists ( const char * path )
2005-04-14 12:24:36 +04:00
{
struct stat st ;
return ( stat ( path , & st ) = = 0 ) ;
}
2005-09-15 23:52:13 +04:00
2006-03-07 19:37:35 +03:00
_PUBLIC_ int vfdprintf ( int fd , const char * format , va_list ap ) _PRINTF_ATTRIBUTE ( 2 , 0 )
2005-09-15 23:52:13 +04:00
{
char * p ;
int len , ret ;
va_list ap2 ;
VA_COPY ( ap2 , ap ) ;
len = vasprintf ( & p , format , ap2 ) ;
if ( len < = 0 ) return len ;
ret = write ( fd , p , len ) ;
SAFE_FREE ( p ) ;
return ret ;
}
2006-03-07 19:37:35 +03:00
_PUBLIC_ int fdprintf ( int fd , const char * format , . . . ) _PRINTF_ATTRIBUTE ( 2 , 3 )
2005-09-15 23:52:13 +04:00
{
va_list ap ;
int ret ;
va_start ( ap , format ) ;
ret = vfdprintf ( fd , format , ap ) ;
va_end ( ap ) ;
return ret ;
}