2006-09-19 02:49:20 +04:00
/*
Unix SMB / CIFS implementation .
replacement routines for broken systems
Copyright ( C ) Andrew Tridgell 1992 - 1998
2008-11-01 05:27:45 +03:00
Copyright ( C ) Jelmer Vernooij 2005 - 2008
2010-10-21 00:13:54 +04:00
Copyright ( C ) Matthieu Patou 2010
2006-09-19 02:49:20 +04:00
* * NOTE ! The following LGPL license applies to the replace
* * library . This does NOT imply that all of Samba is released
* * under the LGPL
This library is free software ; you can redistribute it and / or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation ; either
2007-07-10 05:44:42 +04:00
version 3 of the License , or ( at your option ) any later version .
2006-09-19 02:49:20 +04:00
This library 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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public
2007-07-10 07:42:26 +04:00
License along with this library ; if not , see < http : //www.gnu.org/licenses/>.
2006-09-19 02:49:20 +04:00
*/
# include "replace.h"
# include "system/filesys.h"
# include "system/time.h"
2012-03-24 19:50:37 +04:00
# include "system/network.h"
2006-09-19 02:49:20 +04:00
# include "system/passwd.h"
# include "system/syslog.h"
# include "system/locale.h"
# include "system/wait.h"
2009-04-20 17:39:48 +04:00
# ifdef _WIN32
# define mkdir(d,m) _mkdir(d)
# endif
2006-09-19 02:49:20 +04:00
void replace_dummy ( void ) ;
void replace_dummy ( void ) { }
# ifndef HAVE_FTRUNCATE
/*******************************************************************
ftruncate for operating systems that don ' t have it
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int rep_ftruncate ( int f , off_t l )
{
# ifdef HAVE_CHSIZE
return chsize ( f , l ) ;
# elif defined(F_FREESP)
struct flock fl ;
fl . l_whence = 0 ;
fl . l_len = 0 ;
fl . l_start = l ;
fl . l_type = F_WRLCK ;
return fcntl ( f , F_FREESP , & fl ) ;
# else
# error "you must have a ftruncate function"
# endif
}
# endif /* HAVE_FTRUNCATE */
# ifndef HAVE_STRLCPY
2015-03-26 14:21:44 +03:00
/*
* Like strncpy but does not 0 fill the buffer and always null
* terminates . bufsize is the size of the destination buffer .
* Returns the length of s .
*/
2006-09-19 02:49:20 +04:00
size_t rep_strlcpy ( char * d , const char * s , size_t bufsize )
{
size_t len = strlen ( s ) ;
size_t ret = len ;
2015-03-26 14:21:44 +03:00
if ( bufsize < = 0 ) {
return 0 ;
}
if ( len > = bufsize ) {
len = bufsize - 1 ;
}
2006-09-19 02:49:20 +04:00
memcpy ( d , s , len ) ;
d [ len ] = 0 ;
return ret ;
}
# endif
# ifndef HAVE_STRLCAT
/* like strncat but does not 0 fill the buffer and always null
terminates . bufsize is the length of the buffer , which should
be one more than the maximum resulting string length */
size_t rep_strlcat ( char * d , const char * s , size_t bufsize )
{
2013-11-28 18:56:58 +04:00
size_t len1 = strnlen ( d , bufsize ) ;
2006-09-19 02:49:20 +04:00
size_t len2 = strlen ( s ) ;
size_t ret = len1 + len2 ;
if ( len1 + len2 > = bufsize ) {
2008-07-02 22:57:13 +04:00
if ( bufsize < ( len1 + 1 ) ) {
return ret ;
}
2006-09-19 02:49:20 +04:00
len2 = bufsize - ( len1 + 1 ) ;
}
if ( len2 > 0 ) {
memcpy ( d + len1 , s , len2 ) ;
d [ len1 + len2 ] = 0 ;
}
return ret ;
}
# endif
# ifndef HAVE_MKTIME
/*******************************************************************
a mktime ( ) replacement for those who don ' t have it - contributed by
C . A . Lademann < cal @ zls . com >
Corrections by richard . kettlewell @ kewill . com
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# define MINUTE 60
# define HOUR 60*MINUTE
# define DAY 24*HOUR
# define YEAR 365*DAY
time_t rep_mktime ( struct tm * t )
{
struct tm * u ;
time_t epoch = 0 ;
int n ;
int mon [ ] = { 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 , 30 , 31 } ,
y , m , i ;
if ( t - > tm_year < 70 )
return ( ( time_t ) - 1 ) ;
n = t - > tm_year + 1900 - 1 ;
epoch = ( t - > tm_year - 70 ) * YEAR +
( ( n / 4 - n / 100 + n / 400 ) - ( 1969 / 4 - 1969 / 100 + 1969 / 400 ) ) * DAY ;
y = t - > tm_year + 1900 ;
m = 0 ;
for ( i = 0 ; i < t - > tm_mon ; i + + ) {
epoch + = mon [ m ] * DAY ;
if ( m = = 1 & & y % 4 = = 0 & & ( y % 100 ! = 0 | | y % 400 = = 0 ) )
epoch + = DAY ;
if ( + + m > 11 ) {
m = 0 ;
y + + ;
}
}
epoch + = ( t - > tm_mday - 1 ) * DAY ;
epoch + = t - > tm_hour * HOUR + t - > tm_min * MINUTE + t - > tm_sec ;
if ( ( u = localtime ( & epoch ) ) ! = NULL ) {
t - > tm_sec = u - > tm_sec ;
t - > tm_min = u - > tm_min ;
t - > tm_hour = u - > tm_hour ;
t - > tm_mday = u - > tm_mday ;
t - > tm_mon = u - > tm_mon ;
t - > tm_year = u - > tm_year ;
t - > tm_wday = u - > tm_wday ;
t - > tm_yday = u - > tm_yday ;
t - > tm_isdst = u - > tm_isdst ;
}
return ( epoch ) ;
}
# endif /* !HAVE_MKTIME */
# ifndef HAVE_INITGROUPS
/****************************************************************************
some systems don ' t have an initgroups call
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int rep_initgroups ( char * name , gid_t id )
{
# ifndef HAVE_SETGROUPS
/* yikes! no SETGROUPS or INITGROUPS? how can this work? */
errno = ENOSYS ;
return - 1 ;
# else /* HAVE_SETGROUPS */
# include <grp.h>
gid_t * grouplst = NULL ;
2008-08-08 21:32:15 +04:00
int max_gr = NGROUPS_MAX ;
2006-09-19 02:49:20 +04:00
int ret ;
int i , j ;
struct group * g ;
char * gr ;
if ( ( grouplst = malloc ( sizeof ( gid_t ) * max_gr ) ) = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
grouplst [ 0 ] = id ;
i = 1 ;
while ( i < max_gr & & ( ( g = ( struct group * ) getgrent ( ) ) ! = ( struct group * ) NULL ) ) {
if ( g - > gr_gid = = id )
continue ;
j = 0 ;
gr = g - > gr_mem [ 0 ] ;
while ( gr & & ( * gr ! = ( char ) NULL ) ) {
if ( strcmp ( name , gr ) = = 0 ) {
grouplst [ i ] = g - > gr_gid ;
i + + ;
gr = ( char * ) NULL ;
break ;
}
gr = g - > gr_mem [ + + j ] ;
}
}
endgrent ( ) ;
ret = setgroups ( i , grouplst ) ;
free ( grouplst ) ;
return ret ;
# endif /* HAVE_SETGROUPS */
}
# endif /* HAVE_INITGROUPS */
# ifndef HAVE_MEMMOVE
/*******************************************************************
safely copies memory , ensuring no overlap problems .
2007-11-26 17:28:13 +03:00
this is only used if the machine does not have its own memmove ( ) .
2006-09-19 02:49:20 +04:00
this is not the fastest algorithm in town , but it will do for our
needs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void * rep_memmove ( void * dest , const void * src , int size )
{
unsigned long d , s ;
int i ;
if ( dest = = src | | ! size ) return ( dest ) ;
d = ( unsigned long ) dest ;
s = ( unsigned long ) src ;
if ( ( d > = ( s + size ) ) | | ( s > = ( d + size ) ) ) {
/* no overlap */
memcpy ( dest , src , size ) ;
return ( dest ) ;
}
if ( d < s ) {
/* we can forward copy */
if ( s - d > = sizeof ( int ) & &
! ( s % sizeof ( int ) ) & &
! ( d % sizeof ( int ) ) & &
! ( size % sizeof ( int ) ) ) {
/* do it all as words */
int * idest = ( int * ) dest ;
int * isrc = ( int * ) src ;
size / = sizeof ( int ) ;
for ( i = 0 ; i < size ; i + + ) idest [ i ] = isrc [ i ] ;
} else {
/* simplest */
char * cdest = ( char * ) dest ;
char * csrc = ( char * ) src ;
for ( i = 0 ; i < size ; i + + ) cdest [ i ] = csrc [ i ] ;
}
} else {
/* must backward copy */
if ( d - s > = sizeof ( int ) & &
! ( s % sizeof ( int ) ) & &
! ( d % sizeof ( int ) ) & &
! ( size % sizeof ( int ) ) ) {
/* do it all as words */
int * idest = ( int * ) dest ;
int * isrc = ( int * ) src ;
size / = sizeof ( int ) ;
for ( i = size - 1 ; i > = 0 ; i - - ) idest [ i ] = isrc [ i ] ;
} else {
/* simplest */
char * cdest = ( char * ) dest ;
char * csrc = ( char * ) src ;
for ( i = size - 1 ; i > = 0 ; i - - ) cdest [ i ] = csrc [ i ] ;
}
}
return ( dest ) ;
}
# endif /* HAVE_MEMMOVE */
# ifndef HAVE_STRDUP
/****************************************************************************
duplicate a string
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * rep_strdup ( const char * s )
{
size_t len ;
char * ret ;
if ( ! s ) return ( NULL ) ;
len = strlen ( s ) + 1 ;
ret = ( char * ) malloc ( len ) ;
if ( ! ret ) return ( NULL ) ;
memcpy ( ret , s , len ) ;
return ( ret ) ;
}
# endif /* HAVE_STRDUP */
# ifndef HAVE_SETLINEBUF
void rep_setlinebuf ( FILE * stream )
{
setvbuf ( stream , ( char * ) NULL , _IOLBF , 0 ) ;
}
# endif /* HAVE_SETLINEBUF */
# ifndef HAVE_VSYSLOG
# ifdef HAVE_SYSLOG
2006-09-29 16:30:14 +04:00
void rep_vsyslog ( int facility_priority , const char * format , va_list arglist )
2006-09-19 02:49:20 +04:00
{
char * msg = NULL ;
vasprintf ( & msg , format , arglist ) ;
if ( ! msg )
return ;
syslog ( facility_priority , " %s " , msg ) ;
free ( msg ) ;
}
# endif /* HAVE_SYSLOG */
# endif /* HAVE_VSYSLOG */
# ifndef HAVE_STRNLEN
/**
Some platforms don ' t have strnlen
* */
size_t rep_strnlen ( const char * s , size_t max )
{
size_t len ;
for ( len = 0 ; len < max ; len + + ) {
if ( s [ len ] = = ' \0 ' ) {
break ;
}
}
return len ;
}
# endif
# ifndef HAVE_STRNDUP
/**
Some platforms don ' t have strndup .
* */
char * rep_strndup ( const char * s , size_t n )
{
char * ret ;
n = strnlen ( s , n ) ;
ret = malloc ( n + 1 ) ;
if ( ! ret )
return NULL ;
memcpy ( ret , s , n ) ;
ret [ n ] = 0 ;
return ret ;
}
# endif
2009-04-20 17:47:19 +04:00
# if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4)
2006-09-19 02:49:20 +04:00
int rep_waitpid ( pid_t pid , int * status , int options )
{
return wait4 ( pid , status , options , NULL ) ;
}
# endif
# ifndef HAVE_SETEUID
int rep_seteuid ( uid_t euid )
{
# ifdef HAVE_SETRESUID
return setresuid ( - 1 , euid , - 1 ) ;
# else
2009-04-20 17:54:02 +04:00
errno = ENOSYS ;
return - 1 ;
2006-09-19 02:49:20 +04:00
# endif
}
# endif
# ifndef HAVE_SETEGID
int rep_setegid ( gid_t egid )
{
# ifdef HAVE_SETRESGID
return setresgid ( - 1 , egid , - 1 ) ;
# else
2009-04-20 17:54:02 +04:00
errno = ENOSYS ;
return - 1 ;
2006-09-19 02:49:20 +04:00
# endif
}
# endif
/*******************************************************************
os / 2 also doesn ' t have chroot
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef HAVE_CHROOT
int rep_chroot ( const char * dname )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
/*****************************************************************
Possibly replace mkstemp if it is broken .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef HAVE_SECURE_MKSTEMP
int rep_mkstemp ( char * template )
{
/* have a reasonable go at emulating it. Hope that
2010-02-21 08:35:10 +03:00
the system mktemp ( ) isn ' t completely hopeless */
2012-04-26 02:55:46 +04:00
mktemp ( template ) ;
if ( template [ 0 ] = = 0 )
2006-09-19 02:49:20 +04:00
return - 1 ;
2013-01-04 16:03:58 +04:00
return open ( template , O_CREAT | O_EXCL | O_RDWR , 0600 ) ;
2006-09-19 02:49:20 +04:00
}
# endif
# ifndef HAVE_MKDTEMP
char * rep_mkdtemp ( char * template )
{
char * dname ;
if ( ( dname = mktemp ( template ) ) ) {
if ( mkdir ( dname , 0700 ) > = 0 ) {
return dname ;
}
}
return NULL ;
}
# endif
2007-06-06 13:27:43 +04:00
/*****************************************************************
Watch out : this is not thread safe .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-19 02:49:20 +04:00
# ifndef HAVE_PREAD
ssize_t rep_pread ( int __fd , void * __buf , size_t __nbytes , off_t __offset )
{
if ( lseek ( __fd , __offset , SEEK_SET ) ! = __offset ) {
return - 1 ;
}
return read ( __fd , __buf , __nbytes ) ;
}
# endif
2007-06-06 13:27:43 +04:00
/*****************************************************************
Watch out : this is not thread safe .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-09-19 02:49:20 +04:00
# ifndef HAVE_PWRITE
ssize_t rep_pwrite ( int __fd , const void * __buf , size_t __nbytes , off_t __offset )
{
if ( lseek ( __fd , __offset , SEEK_SET ) ! = __offset ) {
return - 1 ;
}
return write ( __fd , __buf , __nbytes ) ;
}
# endif
# ifndef HAVE_STRCASESTR
char * rep_strcasestr ( const char * haystack , const char * needle )
{
const char * s ;
size_t nlen = strlen ( needle ) ;
for ( s = haystack ; * s ; s + + ) {
if ( toupper ( * needle ) = = toupper ( * s ) & &
strncasecmp ( s , needle , nlen ) = = 0 ) {
2008-04-18 11:30:50 +04:00
return ( char * ) ( ( uintptr_t ) s ) ;
2006-09-19 02:49:20 +04:00
}
}
return NULL ;
}
# endif
2015-07-15 20:43:56 +03:00
# ifndef HAVE_STRSEP
char * rep_strsep ( char * * pps , const char * delim )
{
char * ret = * pps ;
char * p = * pps ;
if ( p = = NULL ) {
return NULL ;
}
p + = strcspn ( p , delim ) ;
if ( * p = = ' \0 ' ) {
* pps = NULL ;
} else {
* p = ' \0 ' ;
* pps = p + 1 ;
}
return ret ;
}
# endif
2006-09-19 02:49:20 +04:00
# ifndef HAVE_STRTOK_R
/* based on GLIBC version, copyright Free Software Foundation */
char * rep_strtok_r ( char * s , const char * delim , char * * save_ptr )
{
char * token ;
if ( s = = NULL ) s = * save_ptr ;
s + = strspn ( s , delim ) ;
if ( * s = = ' \0 ' ) {
* save_ptr = s ;
return NULL ;
}
token = s ;
s = strpbrk ( token , delim ) ;
if ( s = = NULL ) {
* save_ptr = token + strlen ( token ) ;
} else {
* s = ' \0 ' ;
* save_ptr = s + 1 ;
}
return token ;
}
# endif
2010-10-21 00:13:54 +04:00
2006-09-19 02:49:20 +04:00
# ifndef HAVE_STRTOLL
long long int rep_strtoll ( const char * str , char * * endptr , int base )
{
# ifdef HAVE_STRTOQ
return strtoq ( str , endptr , base ) ;
# elif defined(HAVE___STRTOLL)
return __strtoll ( str , endptr , base ) ;
# elif SIZEOF_LONG == SIZEOF_LONG_LONG
return ( long long int ) strtol ( str , endptr , base ) ;
# else
# error "You need a strtoll function"
# endif
}
2010-10-21 00:13:54 +04:00
# else
# ifdef HAVE_BSD_STRTOLL
2015-08-18 21:57:27 +03:00
# undef strtoll
2010-10-21 00:13:54 +04:00
long long int rep_strtoll ( const char * str , char * * endptr , int base )
{
2015-10-22 13:37:55 +03:00
int saved_errno = errno ;
2015-06-21 13:03:56 +03:00
long long int nb = strtoll ( str , endptr , base ) ;
/* With glibc EINVAL is only returned if base is not ok */
2010-10-21 00:13:54 +04:00
if ( errno = = EINVAL ) {
if ( base = = 0 | | ( base > 1 & & base < 37 ) ) {
/* Base was ok so it's because we were not
2019-08-29 22:31:07 +03:00
* able to make the conversion .
2010-10-21 00:13:54 +04:00
* Let ' s reset errno .
*/
2015-10-22 13:37:55 +03:00
errno = saved_errno ;
2010-10-21 00:13:54 +04:00
}
}
return nb ;
}
# endif /* HAVE_BSD_STRTOLL */
# endif /* HAVE_STRTOLL */
2006-09-19 02:49:20 +04:00
# ifndef HAVE_STRTOULL
unsigned long long int rep_strtoull ( const char * str , char * * endptr , int base )
{
# ifdef HAVE_STRTOUQ
return strtouq ( str , endptr , base ) ;
# elif defined(HAVE___STRTOULL)
return __strtoull ( str , endptr , base ) ;
# elif SIZEOF_LONG == SIZEOF_LONG_LONG
return ( unsigned long long int ) strtoul ( str , endptr , base ) ;
# else
# error "You need a strtoull function"
# endif
}
2010-10-21 00:13:54 +04:00
# else
# ifdef HAVE_BSD_STRTOLL
2015-10-22 13:32:48 +03:00
# undef strtoull
2010-10-22 10:44:29 +04:00
unsigned long long int rep_strtoull ( const char * str , char * * endptr , int base )
2010-10-21 00:13:54 +04:00
{
2015-10-22 13:37:55 +03:00
int saved_errno = errno ;
2015-10-22 13:32:48 +03:00
unsigned long long int nb = strtoull ( str , endptr , base ) ;
/* With glibc EINVAL is only returned if base is not ok */
2010-10-21 00:13:54 +04:00
if ( errno = = EINVAL ) {
if ( base = = 0 | | ( base > 1 & & base < 37 ) ) {
/* Base was ok so it's because we were not
2019-08-29 22:31:07 +03:00
* able to make the conversion .
2010-10-21 00:13:54 +04:00
* Let ' s reset errno .
*/
2015-10-22 13:37:55 +03:00
errno = saved_errno ;
2010-10-21 00:13:54 +04:00
}
}
return nb ;
}
# endif /* HAVE_BSD_STRTOLL */
# endif /* HAVE_STRTOULL */
2006-09-19 02:49:20 +04:00
# ifndef HAVE_SETENV
int rep_setenv ( const char * name , const char * value , int overwrite )
{
char * p ;
size_t l1 , l2 ;
int ret ;
if ( ! overwrite & & getenv ( name ) ) {
return 0 ;
}
l1 = strlen ( name ) ;
l2 = strlen ( value ) ;
p = malloc ( l1 + l2 + 2 ) ;
if ( p = = NULL ) {
return - 1 ;
}
memcpy ( p , name , l1 ) ;
p [ l1 ] = ' = ' ;
memcpy ( p + l1 + 1 , value , l2 ) ;
p [ l1 + l2 + 1 ] = 0 ;
ret = putenv ( p ) ;
if ( ret ! = 0 ) {
free ( p ) ;
}
return ret ;
}
# endif
2007-04-16 00:12:09 +04:00
# ifndef HAVE_UNSETENV
int rep_unsetenv ( const char * name )
{
extern char * * environ ;
size_t len = strlen ( name ) ;
2007-06-02 13:10:08 +04:00
size_t i , count ;
2007-04-16 00:12:09 +04:00
2007-06-02 13:10:08 +04:00
if ( environ = = NULL | | getenv ( name ) = = NULL ) {
return 0 ;
}
2007-04-16 00:12:09 +04:00
2007-06-02 13:10:08 +04:00
for ( i = 0 ; environ [ i ] ; i + + ) /* noop */ ;
count = i ;
for ( i = 0 ; i < count ; ) {
2007-04-16 00:12:09 +04:00
if ( strncmp ( environ [ i ] , name , len ) = = 0 & & environ [ i ] [ len ] = = ' = ' ) {
2007-06-02 13:10:08 +04:00
/* note: we do _not_ free the old variable here. It is unsafe to
do so , as the pointer may not have come from malloc */
memmove ( & environ [ i ] , & environ [ i + 1 ] , ( count - i ) * sizeof ( char * ) ) ;
count - - ;
} else {
i + + ;
2007-04-16 00:12:09 +04:00
}
}
return 0 ;
}
# endif
2008-05-07 15:10:31 +04:00
# ifndef HAVE_UTIME
int rep_utime ( const char * filename , const struct utimbuf * buf )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
# ifndef HAVE_UTIMES
int rep_utimes ( const char * filename , const struct timeval tv [ 2 ] )
{
struct utimbuf u ;
u . actime = tv [ 0 ] . tv_sec ;
if ( tv [ 0 ] . tv_usec > 500000 ) {
u . actime + = 1 ;
}
u . modtime = tv [ 1 ] . tv_sec ;
if ( tv [ 1 ] . tv_usec > 500000 ) {
u . modtime + = 1 ;
}
return utime ( filename , & u ) ;
}
# endif
2008-11-01 05:58:14 +03:00
# ifndef HAVE_DUP2
int rep_dup2 ( int oldfd , int newfd )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:27:45 +03:00
# ifndef HAVE_CHOWN
/**
chown isn ' t used much but OS / 2 doesn ' t have it
* */
int rep_chown ( const char * fname , uid_t uid , gid_t gid )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:30:47 +03:00
# ifndef HAVE_LINK
int rep_link ( const char * oldpath , const char * newpath )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:33:39 +03:00
# ifndef HAVE_READLINK
int rep_readlink ( const char * path , char * buf , size_t bufsiz )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:35:58 +03:00
# ifndef HAVE_SYMLINK
int rep_symlink ( const char * oldpath , const char * newpath )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:39:20 +03:00
# ifndef HAVE_LCHOWN
int rep_lchown ( const char * fname , uid_t uid , gid_t gid )
{
errno = ENOSYS ;
return - 1 ;
}
# endif
2008-11-01 05:42:27 +03:00
# ifndef HAVE_REALPATH
char * rep_realpath ( const char * path , char * resolved_path )
{
/* As realpath is not a system call we can't return ENOSYS. */
errno = EINVAL ;
return NULL ;
}
# endif
2010-01-02 02:01:11 +03:00
# ifndef HAVE_MEMMEM
void * rep_memmem ( const void * haystack , size_t haystacklen ,
const void * needle , size_t needlelen )
{
if ( needlelen = = 0 ) {
return discard_const ( haystack ) ;
}
while ( haystacklen > = needlelen ) {
2010-01-03 20:46:21 +03:00
char * p = ( char * ) memchr ( haystack , * ( const char * ) needle ,
haystacklen - ( needlelen - 1 ) ) ;
2010-01-02 02:01:11 +03:00
if ( ! p ) return NULL ;
if ( memcmp ( p , needle , needlelen ) = = 0 ) {
return p ;
}
haystack = p + 1 ;
haystacklen - = ( p - ( const char * ) haystack ) + 1 ;
}
return NULL ;
}
# endif
2012-11-13 17:07:11 +04:00
# if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF)
2010-03-23 21:06:25 +03:00
int rep_vdprintf ( int fd , const char * format , va_list ap )
2010-02-11 12:18:50 +03:00
{
char * s = NULL ;
int ret ;
vasprintf ( & s , format , ap ) ;
if ( s = = NULL ) {
errno = ENOMEM ;
return - 1 ;
}
ret = write ( fd , s , strlen ( s ) ) ;
free ( s ) ;
return ret ;
}
# endif
2012-11-13 17:07:11 +04:00
# if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF)
2010-03-23 21:06:25 +03:00
int rep_dprintf ( int fd , const char * format , . . . )
2010-02-11 12:18:50 +03:00
{
int ret ;
va_list ap ;
va_start ( ap , format ) ;
ret = vdprintf ( fd , format , ap ) ;
va_end ( ap ) ;
return ret ;
}
# endif
2010-03-05 14:45:27 +03:00
# ifndef HAVE_GET_CURRENT_DIR_NAME
char * rep_get_current_dir_name ( void )
{
char buf [ PATH_MAX + 1 ] ;
char * p ;
p = getcwd ( buf , sizeof ( buf ) ) ;
if ( p = = NULL ) {
return NULL ;
}
return strdup ( p ) ;
}
# endif
2010-03-26 08:50:24 +03:00
2012-11-19 16:25:45 +04:00
# ifndef HAVE_STRERROR_R
2010-03-29 13:53:16 +04:00
int rep_strerror_r ( int errnum , char * buf , size_t buflen )
2010-03-26 08:50:24 +03:00
{
2010-03-29 13:53:16 +04:00
char * s = strerror ( errnum ) ;
if ( strlen ( s ) + 1 > buflen ) {
errno = ERANGE ;
return - 1 ;
}
strncpy ( buf , s , buflen ) ;
return 0 ;
2010-03-26 08:50:24 +03:00
}
2017-06-01 04:26:38 +03:00
# elif (!defined(STRERROR_R_XSI_NOT_GNU))
# undef strerror_r
int rep_strerror_r ( int errnum , char * buf , size_t buflen )
{
char * s = strerror_r ( errnum , buf , buflen ) ;
if ( s = = NULL ) {
/* Shouldn't happen, should always get a string */
return EINVAL ;
}
if ( s ! = buf ) {
strlcpy ( buf , s , buflen ) ;
if ( strlen ( s ) > buflen - 1 ) {
return ERANGE ;
}
}
return 0 ;
}
2010-03-26 08:50:24 +03:00
# endif
2010-08-19 21:07:04 +04:00
# ifndef HAVE_CLOCK_GETTIME
int rep_clock_gettime ( clockid_t clk_id , struct timespec * tp )
{
struct timeval tval ;
switch ( clk_id ) {
case 0 : /* CLOCK_REALTIME :*/
2015-09-27 01:57:50 +03:00
# if defined(HAVE_GETTIMEOFDAY_TZ) || defined(HAVE_GETTIMEOFDAY_TZ_VOID)
2010-08-19 21:07:04 +04:00
gettimeofday ( & tval , NULL ) ;
# else
gettimeofday ( & tval ) ;
# endif
tp - > tv_sec = tval . tv_sec ;
tp - > tv_nsec = tval . tv_usec * 1000 ;
break ;
default :
2010-09-10 23:03:17 +04:00
errno = EINVAL ;
return - 1 ;
2010-08-19 21:07:04 +04:00
}
return 0 ;
}
# endif
2012-03-24 17:43:21 +04:00
# ifndef HAVE_MEMALIGN
void * rep_memalign ( size_t align , size_t size )
{
# if defined(HAVE_POSIX_MEMALIGN)
void * p = NULL ;
int ret = posix_memalign ( & p , align , size ) ;
if ( ret = = 0 )
return p ;
return NULL ;
# else
/* On *BSD systems memaligns doesn't exist, but memory will
* be aligned on allocations of > pagesize . */
# if defined(SYSCONF_SC_PAGESIZE)
size_t pagesize = ( size_t ) sysconf ( _SC_PAGESIZE ) ;
# elif defined(HAVE_GETPAGESIZE)
size_t pagesize = ( size_t ) getpagesize ( ) ;
# else
size_t pagesize = ( size_t ) - 1 ;
# endif
if ( pagesize = = ( size_t ) - 1 ) {
2012-03-25 00:18:55 +04:00
errno = ENOSYS ;
2012-03-24 17:43:21 +04:00
return NULL ;
}
if ( size < pagesize ) {
size = pagesize ;
}
return malloc ( size ) ;
# endif
}
# endif
2012-03-24 19:00:36 +04:00
# ifndef HAVE_GETPEEREID
int rep_getpeereid ( int s , uid_t * uid , gid_t * gid )
{
# if defined(HAVE_PEERCRED)
struct ucred cred ;
socklen_t cred_len = sizeof ( struct ucred ) ;
int ret ;
2012-03-24 20:05:29 +04:00
# undef getsockopt
2012-03-24 19:00:36 +04:00
ret = getsockopt ( s , SOL_SOCKET , SO_PEERCRED , ( void * ) & cred , & cred_len ) ;
if ( ret ! = 0 ) {
return - 1 ;
}
if ( cred_len ! = sizeof ( struct ucred ) ) {
errno = EINVAL ;
return - 1 ;
}
* uid = cred . uid ;
* gid = cred . gid ;
return 0 ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
# endif
2012-03-25 00:17:56 +04:00
# ifndef HAVE_USLEEP
int rep_usleep ( useconds_t sec )
{
struct timeval tval ;
/*
* Fake it with select . . .
*/
tval . tv_sec = 0 ;
tval . tv_usec = usecs / 1000 ;
select ( 0 , NULL , NULL , NULL , & tval ) ;
return 0 ;
}
# endif /* HAVE_USLEEP */
2012-09-24 11:20:46 +04:00
# ifndef HAVE_SETPROCTITLE
void rep_setproctitle ( const char * fmt , . . . )
{
}
# endif
2017-09-14 00:36:21 +03:00
# ifndef HAVE_SETPROCTITLE_INIT
void rep_setproctitle_init ( int argc , char * argv [ ] , char * envp [ ] )
{
}
# endif
2018-10-10 17:05:46 +03:00
# ifndef HAVE_MEMSET_S
# ifndef RSIZE_MAX
# define RSIZE_MAX (SIZE_MAX >> 1)
# endif
int rep_memset_s ( void * dest , size_t destsz , int ch , size_t count )
{
if ( dest = = NULL ) {
return EINVAL ;
}
if ( destsz > RSIZE_MAX | |
count > RSIZE_MAX | |
count > destsz ) {
return ERANGE ;
}
# if defined(HAVE_MEMSET_EXPLICIT)
memset_explicit ( dest , destsz , ch , count ) ;
# else /* HAVE_MEMSET_EXPLICIT */
memset ( dest , ch , count ) ;
# if defined(HAVE_GCC_VOLATILE_MEMORY_PROTECTION)
/* See http://llvm.org/bugs/show_bug.cgi?id=15495 */
__asm__ volatile ( " " : : " g " ( dest ) : " memory " ) ;
# endif /* HAVE_GCC_VOLATILE_MEMORY_PROTECTION */
# endif /* HAVE_MEMSET_EXPLICIT */
return 0 ;
}
# endif /* HAVE_MEMSET_S */
2018-11-02 20:04:28 +03:00
# ifndef HAVE_GETPROGNAME
2018-11-13 02:05:21 +03:00
# ifndef HAVE_PROGRAM_INVOCATION_SHORT_NAME
2018-11-02 20:04:28 +03:00
# define PROGNAME_SIZE 32
static char rep_progname [ PROGNAME_SIZE ] ;
2018-11-13 02:05:21 +03:00
# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
2018-11-02 20:04:28 +03:00
const char * rep_getprogname ( void )
{
2018-11-13 02:05:21 +03:00
# ifdef HAVE_PROGRAM_INVOCATION_SHORT_NAME
2018-11-02 20:04:28 +03:00
return program_invocation_short_name ;
2018-11-13 02:05:21 +03:00
# else /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
2018-11-02 20:04:28 +03:00
FILE * fp = NULL ;
char cmdline [ 4096 ] = { 0 } ;
char * p = NULL ;
pid_t pid ;
size_t nread ;
int len ;
2018-11-12 17:31:09 +03:00
int rc ;
2018-11-02 20:04:28 +03:00
if ( rep_progname [ 0 ] ! = ' \0 ' ) {
return rep_progname ;
}
len = snprintf ( rep_progname , sizeof ( rep_progname ) , " %s " , " <unknown> " ) ;
if ( len < = 0 ) {
2018-11-12 17:31:09 +03:00
return NULL ;
2018-11-02 20:04:28 +03:00
}
pid = getpid ( ) ;
if ( pid < = 1 | | pid = = ( pid_t ) - 1 ) {
2018-11-12 17:31:09 +03:00
return NULL ;
2018-11-02 20:04:28 +03:00
}
len = snprintf ( cmdline ,
sizeof ( cmdline ) ,
" /proc/%u/cmdline " ,
( unsigned int ) pid ) ;
if ( len < = 0 | | len = = sizeof ( cmdline ) ) {
2018-11-12 17:31:09 +03:00
return NULL ;
2018-11-02 20:04:28 +03:00
}
fp = fopen ( cmdline , " r " ) ;
if ( fp = = NULL ) {
2018-11-12 17:31:09 +03:00
return NULL ;
2018-11-02 20:04:28 +03:00
}
nread = fread ( cmdline , 1 , sizeof ( cmdline ) - 1 , fp ) ;
2018-11-12 17:31:09 +03:00
rc = fclose ( fp ) ;
if ( rc ! = 0 ) {
return NULL ;
}
2018-11-02 20:04:28 +03:00
if ( nread = = 0 ) {
2018-11-12 17:31:09 +03:00
return NULL ;
2018-11-02 20:04:28 +03:00
}
cmdline [ nread ] = ' \0 ' ;
p = strrchr ( cmdline , ' / ' ) ;
if ( p ! = NULL ) {
p + + ;
} else {
p = cmdline ;
}
len = strlen ( p ) ;
if ( len > PROGNAME_SIZE ) {
p [ PROGNAME_SIZE - 1 ] = ' \0 ' ;
}
( void ) snprintf ( rep_progname , sizeof ( rep_progname ) , " %s " , p ) ;
return rep_progname ;
2018-11-13 02:05:21 +03:00
# endif /* HAVE_PROGRAM_INVOCATION_SHORT_NAME */
2018-11-02 20:04:28 +03:00
}
# endif /* HAVE_GETPROGNAME */
2021-06-24 15:13:50 +03:00
# ifndef HAVE_COPY_FILE_RANGE
# ifdef HAVE_SYSCALL_COPY_FILE_RANGE
# include <sys / syscall.h>
# endif
ssize_t rep_copy_file_range ( int fd_in ,
loff_t * off_in ,
int fd_out ,
loff_t * off_out ,
size_t len ,
unsigned int flags )
{
# ifdef HAVE_SYSCALL_COPY_FILE_RANGE
return syscall ( __NR_copy_file_range ,
fd_in ,
off_in ,
fd_out ,
off_out ,
len ,
flags ) ;
# endif /* HAVE_SYSCALL_COPY_FILE_RANGE */
errno = ENOSYS ;
return - 1 ;
}
# endif /* HAVE_COPY_FILE_RANGE */