1996-05-04 11:50:46 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
1996-05-04 11:50:46 +04:00
Samba system utilities
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1998
2005-05-09 18:05:10 +04:00
Copyright ( C ) Jeremy Allison 1998 - 2005
Copyright ( C ) Timur Bakeyev 2005
2007-08-10 13:44:13 +04:00
Copyright ( C ) Bjoern Jacke 2006 - 2007
1996-05-04 11:50:46 +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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
1996-05-04 11:50:46 +04:00
( 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
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
1996-05-04 11:50:46 +04:00
*/
# include "includes.h"
2006-03-23 02:49:09 +03:00
# ifdef HAVE_SYS_PRCTL_H
# include <sys/prctl.h>
# endif
1996-05-04 11:50:46 +04:00
/*
The idea is that this file will eventually have wrappers around all
1996-06-19 17:23:46 +04:00
important system calls in samba . The aims are :
1996-05-04 11:50:46 +04:00
- to enable easier porting by putting OS dependent stuff in here
- to allow for hooks into other " pseudo-filesystems "
- to allow easier integration of things like the japanese extensions
1996-06-19 17:23:46 +04:00
- to support the philosophy of Samba to expose the features of
the OS within the SMB model . In general whatever file / printer / variable
expansions / etc make sense to the OS should be acceptable to Samba .
1996-05-04 11:50:46 +04:00
*/
2000-06-11 09:57:58 +04:00
2007-02-24 15:40:43 +03:00
/*******************************************************************
A wrapper for memalign
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-03-07 01:01:03 +03:00
void * sys_memalign ( size_t align , size_t size )
2007-02-24 15:40:43 +03:00
{
2007-03-07 01:01:03 +03:00
# if defined(HAVE_POSIX_MEMALIGN)
void * p = NULL ;
2007-02-24 15:40:43 +03:00
int ret = posix_memalign ( & p , align , size ) ;
if ( ret = = 0 )
return p ;
return NULL ;
2007-03-07 01:01:03 +03:00
# elif defined(HAVE_MEMALIGN)
return memalign ( align , size ) ;
2007-02-24 15:40:43 +03:00
# else
2007-03-07 01:01:03 +03:00
/* 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 ) {
DEBUG ( 0 , ( " memalign functionalaity not available on this platform! \n " ) ) ;
return NULL ;
}
if ( size < pagesize ) {
size = pagesize ;
}
return SMB_MALLOC ( size ) ;
2007-02-24 15:40:43 +03:00
# endif
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
A wrapper for usleep in case we don ' t have one .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_usleep ( long usecs )
{
# ifndef HAVE_USLEEP
2002-01-10 03:28:09 +03:00
struct timeval tval ;
1999-12-13 16:27:58 +03:00
# endif
2002-01-10 03:28:09 +03:00
/*
* We need this braindamage as the glibc usleep
* is not SPEC1170 complient . . . grumble . . . JRA .
*/
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
if ( usecs < 0 | | usecs > 1000000 ) {
errno = EINVAL ;
return - 1 ;
}
1999-12-13 16:27:58 +03:00
# if HAVE_USLEEP
2002-01-10 03:28:09 +03:00
usleep ( usecs ) ;
return 0 ;
1999-12-13 16:27:58 +03:00
# else /* HAVE_USLEEP */
2002-01-10 03:28:09 +03:00
/*
* Fake it with select . . .
*/
tval . tv_sec = 0 ;
tval . tv_usec = usecs / 1000 ;
select ( 0 , NULL , NULL , NULL , & tval ) ;
return 0 ;
1999-12-13 16:27:58 +03:00
# endif /* HAVE_USLEEP */
}
2002-07-15 14:35:28 +04:00
/*******************************************************************
A read wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_read ( int fd , void * buf , size_t count )
{
ssize_t ret ;
do {
ret = read ( fd , buf , count ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
/*******************************************************************
A write wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_write ( int fd , const void * buf , size_t count )
{
ssize_t ret ;
do {
ret = write ( fd , buf , count ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
2004-01-06 04:22:14 +03:00
/*******************************************************************
A pread wrapper that will deal with EINTR and 64 - bit file offsets .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(HAVE_PREAD) || defined(HAVE_PREAD64)
ssize_t sys_pread ( int fd , void * buf , size_t count , SMB_OFF_T off )
{
ssize_t ret ;
do {
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PREAD64)
ret = pread64 ( fd , buf , count , off ) ;
# else
ret = pread ( fd , buf , count , off ) ;
# endif
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
# endif
/*******************************************************************
A write wrapper that will deal with EINTR and 64 - bit file offsets .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# if defined(HAVE_PWRITE) || defined(HAVE_PWRITE64)
ssize_t sys_pwrite ( int fd , const void * buf , size_t count , SMB_OFF_T off )
{
ssize_t ret ;
do {
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_PWRITE64)
ret = pwrite64 ( fd , buf , count , off ) ;
# else
ret = pwrite ( fd , buf , count , off ) ;
# endif
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
# endif
2002-07-15 14:35:28 +04:00
/*******************************************************************
A send wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_send ( int s , const void * msg , size_t len , int flags )
{
ssize_t ret ;
do {
ret = send ( s , msg , len , flags ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
/*******************************************************************
A sendto wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_sendto ( int s , const void * msg , size_t len , int flags , const struct sockaddr * to , socklen_t tolen )
{
ssize_t ret ;
do {
ret = sendto ( s , msg , len , flags , to , tolen ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
2006-10-05 16:33:59 +04:00
/*******************************************************************
2006-10-05 17:10:32 +04:00
A recv wrapper that will deal with EINTR .
2006-10-05 16:33:59 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_recv ( int fd , void * buf , size_t count , int flags )
{
ssize_t ret ;
do {
ret = recv ( fd , buf , count , flags ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
2002-07-15 14:35:28 +04:00
/*******************************************************************
A recvfrom wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_recvfrom ( int s , void * buf , size_t len , int flags , struct sockaddr * from , socklen_t * fromlen )
{
ssize_t ret ;
do {
ret = recvfrom ( s , buf , len , flags , from , fromlen ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
/*******************************************************************
A fcntl wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_fcntl_ptr ( int fd , int cmd , void * arg )
{
int ret ;
do {
ret = fcntl ( fd , cmd , arg ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
/*******************************************************************
A fcntl wrapper that will deal with EINTR .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_fcntl_long ( int fd , int cmd , long arg )
{
int ret ;
do {
ret = fcntl ( fd , cmd , arg ) ;
} while ( ret = = - 1 & & errno = = EINTR ) ;
return ret ;
}
1998-09-03 22:40:31 +04:00
/*******************************************************************
A stat ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-26 00:17:20 +03:00
int sys_stat ( const char * fname , SMB_STRUCT_STAT * sbuf )
1998-09-03 22:40:31 +04:00
{
1999-12-13 16:27:58 +03:00
int ret ;
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_STAT64)
ret = stat64 ( fname , sbuf ) ;
1998-09-03 22:40:31 +04:00
# else
1999-12-13 16:27:58 +03:00
ret = stat ( fname , sbuf ) ;
1998-09-03 22:40:31 +04:00
# endif
1999-12-13 16:27:58 +03:00
/* we always want directories to appear zero size */
if ( ret = = 0 & & S_ISDIR ( sbuf - > st_mode ) ) sbuf - > st_size = 0 ;
return ret ;
1998-09-03 22:40:31 +04:00
}
/*******************************************************************
An fstat ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_fstat ( int fd , SMB_STRUCT_STAT * sbuf )
{
1999-12-13 16:27:58 +03:00
int ret ;
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FSTAT64)
ret = fstat64 ( fd , sbuf ) ;
1998-09-03 22:40:31 +04:00
# else
1999-12-13 16:27:58 +03:00
ret = fstat ( fd , sbuf ) ;
1998-09-03 22:40:31 +04:00
# endif
1999-12-13 16:27:58 +03:00
/* we always want directories to appear zero size */
if ( ret = = 0 & & S_ISDIR ( sbuf - > st_mode ) ) sbuf - > st_size = 0 ;
return ret ;
1998-09-03 22:40:31 +04:00
}
/*******************************************************************
An lstat ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-26 00:17:20 +03:00
int sys_lstat ( const char * fname , SMB_STRUCT_STAT * sbuf )
1998-09-03 22:40:31 +04:00
{
1999-12-13 16:27:58 +03:00
int ret ;
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSTAT64)
ret = lstat64 ( fname , sbuf ) ;
1998-09-03 22:40:31 +04:00
# else
1999-12-13 16:27:58 +03:00
ret = lstat ( fname , sbuf ) ;
1998-09-03 22:40:31 +04:00
# endif
1999-12-13 16:27:58 +03:00
/* we always want directories to appear zero size */
if ( ret = = 0 & & S_ISDIR ( sbuf - > st_mode ) ) sbuf - > st_size = 0 ;
return ret ;
1998-09-03 22:40:31 +04:00
}
/*******************************************************************
An ftruncate ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_ftruncate ( int fd , SMB_OFF_T offset )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_FTRUNCATE64)
2002-01-10 03:28:09 +03:00
return ftruncate64 ( fd , offset ) ;
1998-09-03 22:40:31 +04:00
# else
2002-01-10 03:28:09 +03:00
return ftruncate ( fd , offset ) ;
1998-09-03 22:40:31 +04:00
# endif
}
/*******************************************************************
An lseek ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-09-12 01:42:18 +04:00
SMB_OFF_T sys_lseek ( int fd , SMB_OFF_T offset , int whence )
1998-09-03 22:40:31 +04:00
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_LSEEK64)
2002-01-10 03:28:09 +03:00
return lseek64 ( fd , offset , whence ) ;
1998-09-03 22:40:31 +04:00
# else
2002-01-10 03:28:09 +03:00
return lseek ( fd , offset , whence ) ;
1998-09-03 22:40:31 +04:00
# endif
}
1996-05-04 11:50:46 +04:00
1998-09-17 23:16:12 +04:00
/*******************************************************************
An fseek ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_fseek ( FILE * fp , SMB_OFF_T offset , int whence )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEK64)
2002-01-10 03:28:09 +03:00
return fseek64 ( fp , offset , whence ) ;
1999-12-13 16:27:58 +03:00
# elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FSEEKO64)
2002-01-10 03:28:09 +03:00
return fseeko64 ( fp , offset , whence ) ;
1998-09-17 23:16:12 +04:00
# else
2002-01-10 03:28:09 +03:00
return fseek ( fp , offset , whence ) ;
1998-09-17 23:16:12 +04:00
# endif
}
/*******************************************************************
An ftell ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
SMB_OFF_T sys_ftell ( FILE * fp )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELL64)
2002-01-10 03:28:09 +03:00
return ( SMB_OFF_T ) ftell64 ( fp ) ;
1999-12-13 16:27:58 +03:00
# elif defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(LARGE_SMB_OFF_T) && defined(HAVE_FTELLO64)
2002-01-10 03:28:09 +03:00
return ( SMB_OFF_T ) ftello64 ( fp ) ;
1998-09-17 23:16:12 +04:00
# else
2002-01-10 03:28:09 +03:00
return ( SMB_OFF_T ) ftell ( fp ) ;
1998-09-17 23:16:12 +04:00
# endif
}
1998-11-17 23:50:07 +03:00
/*******************************************************************
A creat ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_creat ( const char * path , mode_t mode )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CREAT64)
2002-01-10 03:28:09 +03:00
return creat64 ( path , mode ) ;
1998-11-17 23:50:07 +03:00
# else
2002-01-10 03:28:09 +03:00
/*
* If creat64 isn ' t defined then ensure we call a potential open64 .
* JRA .
*/
return sys_open ( path , O_WRONLY | O_CREAT | O_TRUNC , mode ) ;
1998-11-17 23:50:07 +03:00
# endif
}
/*******************************************************************
An open ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_open ( const char * path , int oflag , mode_t mode )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPEN64)
2002-01-10 03:28:09 +03:00
return open64 ( path , oflag , mode ) ;
1998-11-17 23:50:07 +03:00
# else
2002-01-10 03:28:09 +03:00
return open ( path , oflag , mode ) ;
1998-11-17 23:50:07 +03:00
# endif
}
/*******************************************************************
An fopen ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
FILE * sys_fopen ( const char * path , const char * type )
{
1999-12-13 16:27:58 +03:00
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_FOPEN64)
2002-01-10 03:28:09 +03:00
return fopen64 ( path , type ) ;
1998-11-17 23:50:07 +03:00
# else
2002-01-10 03:28:09 +03:00
return fopen ( path , type ) ;
1998-11-17 23:50:07 +03:00
# endif
}
2006-11-09 23:29:31 +03:00
/*******************************************************************
A flock ( ) wrapper that will perform the kernel flock .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void kernel_flock ( int fd , uint32 share_mode )
{
# if HAVE_KERNEL_SHARE_MODES
int kernel_mode = 0 ;
if ( share_mode = = FILE_SHARE_WRITE ) {
kernel_mode = LOCK_MAND | LOCK_WRITE ;
} else if ( share_mode = = FILE_SHARE_READ ) {
kernel_mode = LOCK_MAND | LOCK_READ ;
} else if ( share_mode = = FILE_SHARE_NONE ) {
kernel_mode = LOCK_MAND ;
}
if ( kernel_mode ) {
flock ( fd , kernel_mode ) ;
}
# endif
;
}
2004-11-10 01:49:28 +03:00
/*******************************************************************
An opendir wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
SMB_STRUCT_DIR * sys_opendir ( const char * name )
2004-11-10 01:49:28 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OPENDIR64)
return opendir64 ( name ) ;
# else
return opendir ( name ) ;
# endif
}
1999-12-13 16:27:58 +03:00
/*******************************************************************
A readdir wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
SMB_STRUCT_DIRENT * sys_readdir ( SMB_STRUCT_DIR * dirp )
1999-12-13 16:27:58 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_READDIR64)
2002-01-10 03:28:09 +03:00
return readdir64 ( dirp ) ;
# else
return readdir ( dirp ) ;
# endif
}
2004-11-10 01:49:28 +03:00
/*******************************************************************
A seekdir wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
void sys_seekdir ( SMB_STRUCT_DIR * dirp , long offset )
2004-11-10 01:49:28 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_SEEKDIR64)
seekdir64 ( dirp , offset ) ;
# else
seekdir ( dirp , offset ) ;
# endif
}
/*******************************************************************
A telldir wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
long sys_telldir ( SMB_STRUCT_DIR * dirp )
2004-11-10 01:49:28 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_TELLDIR64)
return ( long ) telldir64 ( dirp ) ;
# else
return ( long ) telldir ( dirp ) ;
# endif
}
/*******************************************************************
A rewinddir wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
void sys_rewinddir ( SMB_STRUCT_DIR * dirp )
2004-11-10 01:49:28 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_REWINDDIR64)
rewinddir64 ( dirp ) ;
# else
rewinddir ( dirp ) ;
# endif
}
/*******************************************************************
A close wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2005-08-22 22:03:08 +04:00
int sys_closedir ( SMB_STRUCT_DIR * dirp )
2004-11-10 01:49:28 +03:00
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_CLOSEDIR64)
return closedir64 ( dirp ) ;
# else
return closedir ( dirp ) ;
# endif
}
2002-01-10 03:28:09 +03:00
/*******************************************************************
An mknod ( ) wrapper that will deal with 64 bit filesizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_mknod ( const char * path , mode_t mode , SMB_DEV_T dev )
{
# if defined(HAVE_MKNOD) || defined(HAVE_MKNOD64)
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_MKNOD64) && defined(HAVE_DEV64_T)
return mknod64 ( path , mode , dev ) ;
# else
return mknod ( path , mode , dev ) ;
# endif
1999-12-13 16:27:58 +03:00
# else
2002-01-10 03:28:09 +03:00
/* No mknod system call. */
errno = ENOSYS ;
return - 1 ;
1999-12-13 16:27:58 +03:00
# endif
}
2002-03-19 05:32:39 +03:00
/*******************************************************************
Wrapper for realpath .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char * sys_realpath ( const char * path , char * resolved_path )
{
# if defined(HAVE_REALPATH)
return realpath ( path , resolved_path ) ;
# else
/* As realpath is not a system call we can't return ENOSYS. */
errno = EINVAL ;
return NULL ;
# endif
}
1996-10-05 06:54:37 +04:00
/*******************************************************************
The wait ( ) calls vary between systems
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-26 00:17:20 +03:00
1996-10-05 06:54:37 +04:00
int sys_waitpid ( pid_t pid , int * status , int options )
{
1998-07-29 07:08:05 +04:00
# ifdef HAVE_WAITPID
2002-01-10 03:28:09 +03:00
return waitpid ( pid , status , options ) ;
1998-07-29 07:08:05 +04:00
# else /* HAVE_WAITPID */
2002-01-10 03:28:09 +03:00
return wait4 ( pid , status , options , NULL ) ;
1998-07-29 07:08:05 +04:00
# endif /* HAVE_WAITPID */
1996-10-05 06:54:37 +04:00
}
1997-08-22 00:03:45 +04:00
/*******************************************************************
2002-01-10 03:28:09 +03:00
System wrapper for getwd
1997-08-22 00:03:45 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-10 03:28:09 +03:00
1998-10-02 16:35:28 +04:00
char * sys_getwd ( char * s )
1997-08-22 00:03:45 +04:00
{
2002-01-10 03:28:09 +03:00
char * wd ;
1998-07-29 07:08:05 +04:00
# ifdef HAVE_GETCWD
2007-09-13 01:48:20 +04:00
# ifdef PATH_MAX
wd = ( char * ) getcwd ( s , PATH_MAX ) ;
# else
2002-01-10 03:28:09 +03:00
wd = ( char * ) getcwd ( s , sizeof ( pstring ) ) ;
2007-09-13 01:48:20 +04:00
# endif
1997-08-22 00:03:45 +04:00
# else
2002-01-10 03:28:09 +03:00
wd = ( char * ) getwd ( s ) ;
1997-08-22 00:03:45 +04:00
# endif
2002-01-10 03:28:09 +03:00
return wd ;
1998-10-02 16:35:28 +04:00
}
2001-06-30 02:32:24 +04:00
/*******************************************************************
system wrapper for symlink
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_symlink ( const char * oldpath , const char * newpath )
{
# ifndef HAVE_SYMLINK
errno = ENOSYS ;
return - 1 ;
# else
return symlink ( oldpath , newpath ) ;
# endif
}
/*******************************************************************
system wrapper for readlink
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_readlink ( const char * path , char * buf , size_t bufsiz )
{
# ifndef HAVE_READLINK
errno = ENOSYS ;
return - 1 ;
# else
return readlink ( path , buf , bufsiz ) ;
# endif
}
2002-01-10 03:28:09 +03:00
/*******************************************************************
system wrapper for link
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_link ( const char * oldpath , const char * newpath )
{
# ifndef HAVE_LINK
errno = ENOSYS ;
return - 1 ;
# else
return link ( oldpath , newpath ) ;
# endif
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
chown isn ' t used much but OS / 2 doesn ' t have it
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1999-12-13 16:27:58 +03:00
1998-11-26 00:17:20 +03:00
int sys_chown ( const char * fname , uid_t uid , gid_t gid )
1996-05-04 11:50:46 +04:00
{
1998-07-29 07:08:05 +04:00
# ifndef HAVE_CHOWN
static int done ;
if ( ! done ) {
DEBUG ( 1 , ( " WARNING: no chown! \n " ) ) ;
done = 1 ;
}
2004-01-15 12:08:06 +03:00
errno = ENOSYS ;
return - 1 ;
1996-05-04 11:50:46 +04:00
# else
1998-07-29 07:08:05 +04:00
return ( chown ( fname , uid , gid ) ) ;
1996-05-04 11:50:46 +04:00
# endif
}
2007-05-24 03:55:12 +04:00
/*******************************************************************
Wrapper for lchown .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_lchown ( const char * fname , uid_t uid , gid_t gid )
{
# ifndef HAVE_LCHOWN
static int done ;
if ( ! done ) {
DEBUG ( 1 , ( " WARNING: no lchown! \n " ) ) ;
done = 1 ;
}
errno = ENOSYS ;
return - 1 ;
# else
return ( lchown ( fname , uid , gid ) ) ;
# endif
}
1996-05-04 11:50:46 +04:00
/*******************************************************************
os / 2 also doesn ' t have chroot
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
1998-11-26 00:17:20 +03:00
int sys_chroot ( const char * dname )
1996-05-04 11:50:46 +04:00
{
1998-07-29 07:08:05 +04:00
# ifndef HAVE_CHROOT
static int done ;
if ( ! done ) {
DEBUG ( 1 , ( " WARNING: no chroot! \n " ) ) ;
done = 1 ;
}
2000-06-10 17:38:07 +04:00
errno = ENOSYS ;
return - 1 ;
1996-05-04 11:50:46 +04:00
# else
1998-07-29 07:08:05 +04:00
return ( chroot ( dname ) ) ;
1996-05-04 11:50:46 +04:00
# endif
}
1997-02-23 08:18:09 +03:00
2006-03-21 05:56:49 +03:00
# if defined(HAVE_POSIX_CAPABILITIES)
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
# ifdef HAVE_SYS_CAPABILITY_H
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
# if defined(BROKEN_REDHAT_7_SYSTEM_HEADERS) && !defined(_I386_STATFS_H) && !defined(_PPC_STATFS_H)
# define _I386_STATFS_H
# define _PPC_STATFS_H
# define BROKEN_REDHAT_7_STATFS_WORKAROUND
# endif
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
# include <sys/capability.h>
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
# ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND
# undef _I386_STATFS_H
# undef _PPC_STATFS_H
# undef BROKEN_REDHAT_7_STATFS_WORKAROUND
# endif
1999-12-13 16:27:58 +03:00
2006-03-21 05:56:49 +03:00
# endif /* HAVE_SYS_CAPABILITY_H */
1998-09-26 03:40:49 +04:00
/**************************************************************************
2006-03-21 05:56:49 +03:00
Try and abstract process capabilities ( for systems that have them ) .
1998-09-26 03:40:49 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-03-21 05:56:49 +03:00
/* Set the POSIX capabilities needed for the given purpose into the effective
* capability set of the current process . Make sure they are always removed
* from the inheritable set , because there is no circumstance in which our
* children should inherit our elevated privileges .
*/
2007-10-19 04:40:25 +04:00
static bool set_process_capability ( enum smbd_capability capability ,
bool enable )
1998-09-26 03:40:49 +04:00
{
2006-03-21 05:56:49 +03:00
cap_value_t cap_vals [ 2 ] = { 0 } ;
int num_cap_vals = 0 ;
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
cap_t cap ;
1998-09-26 03:40:49 +04:00
2006-03-23 02:49:09 +03:00
# if defined(HAVE_PRCTL) && defined(PR_GET_KEEPCAPS) && defined(PR_SET_KEEPCAPS)
/* On Linux, make sure that any capabilities we grab are sticky
* across UID changes . We expect that this would allow us to keep both
* the effective and permitted capability sets , but as of circa 2.6 .16 ,
* only the permitted set is kept . It is a bug ( which we work around )
* that the effective set is lost , but we still require the effective
* set to be kept .
*/
if ( ! prctl ( PR_GET_KEEPCAPS ) ) {
prctl ( PR_SET_KEEPCAPS , 1 ) ;
}
# endif
2006-03-21 05:56:49 +03:00
cap = cap_get_proc ( ) ;
if ( cap = = NULL ) {
DEBUG ( 0 , ( " set_process_capability: cap_get_proc failed: %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
switch ( capability ) {
case KERNEL_OPLOCK_CAPABILITY :
# ifdef CAP_NETWORK_MGT
/* IRIX has CAP_NETWORK_MGT for oplocks. */
cap_vals [ num_cap_vals + + ] = CAP_NETWORK_MGT ;
2006-03-23 02:49:09 +03:00
# endif
break ;
case DMAPI_ACCESS_CAPABILITY :
# ifdef CAP_DEVICE_MGT
/* IRIX has CAP_DEVICE_MGT for DMAPI access. */
cap_vals [ num_cap_vals + + ] = CAP_DEVICE_MGT ;
# elif CAP_MKNOD
/* Linux has CAP_MKNOD for DMAPI access. */
cap_vals [ num_cap_vals + + ] = CAP_MKNOD ;
2006-03-21 05:56:49 +03:00
# endif
break ;
}
SMB_ASSERT ( num_cap_vals < = ARRAY_SIZE ( cap_vals ) ) ;
1998-09-26 03:40:49 +04:00
2006-03-21 05:56:49 +03:00
if ( num_cap_vals = = 0 ) {
2002-01-10 03:28:09 +03:00
cap_free ( cap ) ;
2006-03-21 05:56:49 +03:00
return True ;
}
1999-12-13 16:27:58 +03:00
2006-03-21 05:56:49 +03:00
cap_set_flag ( cap , CAP_EFFECTIVE , num_cap_vals , cap_vals ,
enable ? CAP_SET : CAP_CLEAR ) ;
2006-03-23 02:49:09 +03:00
/* We never want to pass capabilities down to our children, so make
* sure they are not inherited .
*/
2006-03-21 05:56:49 +03:00
cap_set_flag ( cap , CAP_INHERITABLE , num_cap_vals , cap_vals , CAP_CLEAR ) ;
if ( cap_set_proc ( cap ) = = - 1 ) {
DEBUG ( 0 , ( " set_process_capability: cap_set_proc failed: %s \n " ,
strerror ( errno ) ) ) ;
cap_free ( cap ) ;
return False ;
2002-01-10 03:28:09 +03:00
}
2006-03-21 05:56:49 +03:00
cap_free ( cap ) ;
2002-01-10 03:28:09 +03:00
return True ;
1998-09-26 03:40:49 +04:00
}
2006-03-21 05:56:49 +03:00
# endif /* HAVE_POSIX_CAPABILITIES */
2000-06-09 10:58:06 +04:00
/****************************************************************************
2002-01-10 03:28:09 +03:00
Gain the oplock capability from the kernel if possible .
2000-06-09 10:58:06 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-10 03:28:09 +03:00
2006-03-21 05:56:49 +03:00
void set_effective_capability ( enum smbd_capability capability )
2000-06-09 10:58:06 +04:00
{
2006-03-21 05:56:49 +03:00
# if defined(HAVE_POSIX_CAPABILITIES)
set_process_capability ( capability , True ) ;
# endif /* HAVE_POSIX_CAPABILITIES */
}
void drop_effective_capability ( enum smbd_capability capability )
{
# if defined(HAVE_POSIX_CAPABILITIES)
set_process_capability ( capability , False ) ;
# endif /* HAVE_POSIX_CAPABILITIES */
2000-06-09 10:58:06 +04:00
}
1998-09-26 03:40:49 +04:00
/**************************************************************************
Wrapper for random ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
long sys_random ( void )
{
# if defined(HAVE_RANDOM)
2002-01-10 03:28:09 +03:00
return ( long ) random ( ) ;
1998-09-26 03:40:49 +04:00
# elif defined(HAVE_RAND)
2002-01-10 03:28:09 +03:00
return ( long ) rand ( ) ;
1998-09-26 03:40:49 +04:00
# else
2002-01-10 03:28:09 +03:00
DEBUG ( 0 , ( " Error - no random function available ! \n " ) ) ;
exit ( 1 ) ;
1998-09-26 03:40:49 +04:00
# endif
}
/**************************************************************************
Wrapper for srandom ( ) .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void sys_srandom ( unsigned int seed )
{
# if defined(HAVE_SRANDOM)
2002-01-10 03:28:09 +03:00
srandom ( seed ) ;
1998-09-26 03:40:49 +04:00
# elif defined(HAVE_SRAND)
2002-01-10 03:28:09 +03:00
srand ( seed ) ;
1998-09-26 03:40:49 +04:00
# else
2002-01-10 03:28:09 +03:00
DEBUG ( 0 , ( " Error - no srandom function available ! \n " ) ) ;
exit ( 1 ) ;
1998-09-26 03:40:49 +04:00
# endif
}
1998-09-30 00:24:17 +04:00
2000-02-15 22:36:47 +03:00
/**************************************************************************
Returns equivalent to NGROUPS_MAX - using sysconf if needed .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int groups_max ( void )
{
# if defined(SYSCONF_SC_NGROUPS_MAX)
2002-01-10 03:28:09 +03:00
int ret = sysconf ( _SC_NGROUPS_MAX ) ;
return ( ret = = - 1 ) ? NGROUPS_MAX : ret ;
2000-02-15 22:36:47 +03:00
# else
2002-01-10 03:28:09 +03:00
return NGROUPS_MAX ;
2000-02-15 22:36:47 +03:00
# endif
}
1998-09-30 00:24:17 +04:00
/**************************************************************************
2007-06-09 02:25:55 +04:00
Wrap setgroups and getgroups for systems that declare getgroups ( ) as
returning an array of gid_t , but actuall return an array of int .
1998-09-30 00:24:17 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-09 02:25:55 +04:00
# if defined(HAVE_BROKEN_GETGROUPS)
static int sys_broken_getgroups ( int setlen , gid_t * gidset )
1998-09-30 00:24:17 +04:00
{
2002-01-10 03:28:09 +03:00
GID_T gid ;
GID_T * group_list ;
int i , ngroups ;
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
if ( setlen = = 0 ) {
return getgroups ( setlen , & gid ) ;
}
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
/*
* Broken case . We need to allocate a
* GID_T array of size setlen .
*/
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
if ( setlen < 0 ) {
errno = EINVAL ;
return - 1 ;
}
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
if ( setlen = = 0 )
setlen = groups_max ( ) ;
1998-10-05 12:42:41 +04:00
2007-06-09 02:25:55 +04:00
if ( ( group_list = SMB_MALLOC_ARRAY ( GID_T , setlen ) ) = = NULL ) {
2002-01-10 03:28:09 +03:00
DEBUG ( 0 , ( " sys_getgroups: Malloc fail. \n " ) ) ;
return - 1 ;
}
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
if ( ( ngroups = getgroups ( setlen , group_list ) ) < 0 ) {
int saved_errno = errno ;
SAFE_FREE ( group_list ) ;
errno = saved_errno ;
return - 1 ;
}
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
for ( i = 0 ; i < ngroups ; i + + )
gidset [ i ] = ( gid_t ) group_list [ i ] ;
1998-09-30 00:24:17 +04:00
2002-01-10 03:28:09 +03:00
SAFE_FREE ( group_list ) ;
return ngroups ;
1998-09-30 00:24:17 +04:00
}
1999-07-07 01:50:29 +04:00
2007-06-14 01:42:31 +04:00
static int sys_broken_setgroups ( int setlen , gid_t * gidset )
1999-12-13 16:27:58 +03:00
{
2002-01-10 03:28:09 +03:00
GID_T * group_list ;
int i ;
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
if ( setlen = = 0 )
return 0 ;
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
if ( setlen < 0 | | setlen > groups_max ( ) ) {
errno = EINVAL ;
return - 1 ;
}
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
/*
* Broken case . We need to allocate a
* GID_T array of size setlen .
*/
1999-12-13 16:27:58 +03:00
2007-06-09 02:25:55 +04:00
if ( ( group_list = SMB_MALLOC_ARRAY ( GID_T , setlen ) ) = = NULL ) {
2002-01-10 03:28:09 +03:00
DEBUG ( 0 , ( " sys_setgroups: Malloc fail. \n " ) ) ;
return - 1 ;
}
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
for ( i = 0 ; i < setlen ; i + + )
group_list [ i ] = ( GID_T ) gidset [ i ] ;
if ( setgroups ( setlen , group_list ) ! = 0 ) {
int saved_errno = errno ;
SAFE_FREE ( group_list ) ;
errno = saved_errno ;
return - 1 ;
}
1999-12-13 16:27:58 +03:00
2002-01-10 03:28:09 +03:00
SAFE_FREE ( group_list ) ;
return 0 ;
2007-06-09 02:25:55 +04:00
}
1999-12-13 16:27:58 +03:00
# endif /* HAVE_BROKEN_GETGROUPS */
2007-06-09 02:25:55 +04:00
/* This is a list of systems that require the first GID passed to setgroups(2)
* to be the effective GID . If your system is one of these , add it here .
*/
# if defined (FREEBSD) || defined (DARWINOS)
# define USE_BSD_SETGROUPS
# endif
# if defined(USE_BSD_SETGROUPS)
/* Depending on the particular BSD implementation, the first GID that is
* passed to setgroups ( 2 ) will either be ignored or will set the credential ' s
* effective GID . In either case , the right thing to do is to guarantee that
* gidset [ 0 ] is the effective GID .
*/
static int sys_bsd_setgroups ( gid_t primary_gid , int setlen , const gid_t * gidset )
{
gid_t * new_gidset = NULL ;
int max ;
int ret ;
/* setgroups(2) will fail with EINVAL if we pass too many groups. */
max = groups_max ( ) ;
/* No group list, just make sure we are setting the efective GID. */
if ( setlen = = 0 ) {
return setgroups ( 1 , & primary_gid ) ;
}
/* If the primary gid is not the first array element, grow the array
* and insert it at the front .
*/
if ( gidset [ 0 ] ! = primary_gid ) {
new_gidset = SMB_MALLOC_ARRAY ( gid_t , setlen + 1 ) ;
if ( new_gidset = = NULL ) {
return - 1 ;
}
2007-06-21 18:23:06 +04:00
memcpy ( new_gidset + 1 , gidset , ( setlen * sizeof ( gid_t ) ) ) ;
2007-06-09 02:25:55 +04:00
new_gidset [ 0 ] = primary_gid ;
setlen + + ;
}
2007-06-14 00:40:50 +04:00
if ( setlen > max ) {
2007-06-14 01:42:31 +04:00
DEBUG ( 3 , ( " forced to truncate group list from %d to %d \n " ,
2007-06-14 00:40:50 +04:00
setlen , max ) ) ;
setlen = max ;
}
2007-06-22 01:17:06 +04:00
# if defined(HAVE_BROKEN_GETGROUPS)
2007-06-14 00:40:50 +04:00
ret = sys_broken_setgroups ( setlen , new_gidset ? new_gidset : gidset ) ;
2007-06-09 02:25:55 +04:00
# else
2007-06-14 00:40:50 +04:00
ret = setgroups ( setlen , new_gidset ? new_gidset : gidset ) ;
2007-06-09 02:25:55 +04:00
# endif
if ( new_gidset ) {
int errsav = errno ;
SAFE_FREE ( new_gidset ) ;
errno = errsav ;
}
return ret ;
}
# endif /* USE_BSD_SETGROUPS */
/**************************************************************************
Wrapper for getgroups . Deals with broken ( int ) case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_getgroups ( int setlen , gid_t * gidset )
{
# if defined(HAVE_BROKEN_GETGROUPS)
return sys_broken_getgroups ( setlen , gidset ) ;
# else
return getgroups ( setlen , gidset ) ;
# endif
}
/**************************************************************************
Wrapper for setgroups . Deals with broken ( int ) case and BSD case .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_setgroups ( gid_t UNUSED ( primary_gid ) , int setlen , gid_t * gidset )
{
# if !defined(HAVE_SETGROUPS)
errno = ENOSYS ;
return - 1 ;
# endif /* HAVE_SETGROUPS */
2007-06-22 01:17:06 +04:00
# if defined(USE_BSD_SETGROUPS)
2007-06-09 02:25:55 +04:00
return sys_bsd_setgroups ( primary_gid , setlen , gidset ) ;
2007-06-22 01:17:06 +04:00
# elif defined(HAVE_BROKEN_GETGROUPS)
return sys_broken_setgroups ( setlen , gidset ) ;
2007-06-09 02:25:55 +04:00
# else
return setgroups ( setlen , gidset ) ;
# endif
1999-12-13 16:27:58 +03:00
}
2001-01-31 08:14:31 +03:00
/**************************************************************************
Wrappers for setpwent ( ) , getpwent ( ) and endpwent ( )
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void sys_setpwent ( void )
{
setpwent ( ) ;
}
struct passwd * sys_getpwent ( void )
{
2002-07-15 14:35:28 +04:00
return getpwent ( ) ;
2001-01-31 08:14:31 +03:00
}
void sys_endpwent ( void )
{
endpwent ( ) ;
}
1999-07-07 01:50:29 +04:00
/**************************************************************************
2002-07-15 14:35:28 +04:00
Wrappers for getpwnam ( ) , getpwuid ( ) , getgrnam ( ) , getgrgid ( )
1999-07-07 01:50:29 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2006-07-11 22:01:26 +04:00
# ifdef ENABLE_BUILD_FARM_HACKS
/*
* In the build farm we want to be able to join machines to the domain . As we
* don ' t have root access , we need to bypass direct access to / etc / passwd
* after a user has been created via samr . Fake those users .
*/
static struct passwd * fake_pwd ;
static int num_fake_pwd ;
struct passwd * sys_getpwnam ( const char * name )
{
int i ;
for ( i = 0 ; i < num_fake_pwd ; i + + ) {
if ( strcmp ( fake_pwd [ i ] . pw_name , name ) = = 0 ) {
DEBUG ( 10 , ( " Returning fake user %s \n " , name ) ) ;
return & fake_pwd [ i ] ;
}
}
return getpwnam ( name ) ;
}
struct passwd * sys_getpwuid ( uid_t uid )
{
int i ;
for ( i = 0 ; i < num_fake_pwd ; i + + ) {
if ( fake_pwd [ i ] . pw_uid = = uid ) {
DEBUG ( 10 , ( " Returning fake user %s \n " ,
fake_pwd [ i ] . pw_name ) ) ;
return & fake_pwd [ i ] ;
}
}
return getpwuid ( uid ) ;
}
void faked_create_user ( const char * name )
{
int i ;
uid_t uid ;
struct passwd new_pwd ;
for ( i = 0 ; i < 10 ; i + + ) {
generate_random_buffer ( ( unsigned char * ) & uid ,
sizeof ( uid ) ) ;
if ( getpwuid ( uid ) = = NULL ) {
break ;
}
}
if ( i = = 10 ) {
/* Weird. No free uid found... */
return ;
}
new_pwd . pw_name = SMB_STRDUP ( name ) ;
new_pwd . pw_passwd = SMB_STRDUP ( " x " ) ;
new_pwd . pw_uid = uid ;
new_pwd . pw_gid = 100 ;
new_pwd . pw_gecos = SMB_STRDUP ( " faked user " ) ;
new_pwd . pw_dir = SMB_STRDUP ( " /nodir " ) ;
new_pwd . pw_shell = SMB_STRDUP ( " /bin/false " ) ;
ADD_TO_ARRAY ( NULL , struct passwd , new_pwd , & fake_pwd ,
& num_fake_pwd ) ;
DEBUG ( 10 , ( " Added fake user %s, have %d fake users \n " ,
name , num_fake_pwd ) ) ;
}
# else
1999-07-07 01:50:29 +04:00
struct passwd * sys_getpwnam ( const char * name )
{
2002-07-15 14:35:28 +04:00
return getpwnam ( name ) ;
}
2001-01-24 18:47:31 +03:00
2002-07-15 14:35:28 +04:00
struct passwd * sys_getpwuid ( uid_t uid )
{
return getpwuid ( uid ) ;
1999-07-07 01:50:29 +04:00
}
2006-07-11 22:01:26 +04:00
# endif
2002-07-15 14:35:28 +04:00
struct group * sys_getgrnam ( const char * name )
{
return getgrnam ( name ) ;
}
1999-07-07 01:50:29 +04:00
2002-07-15 14:35:28 +04:00
struct group * sys_getgrgid ( gid_t gid )
1999-07-07 01:50:29 +04:00
{
2002-07-15 14:35:28 +04:00
return getgrgid ( gid ) ;
1999-07-07 01:50:29 +04:00
}
1999-12-22 04:29:22 +03:00
2000-02-15 22:36:47 +03:00
/**************************************************************************
2007-06-29 20:04:26 +04:00
Extract a command into an arg list .
2000-02-15 22:36:47 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2007-06-29 20:04:26 +04:00
static char * * extract_args ( TALLOC_CTX * mem_ctx , const char * command )
2000-02-15 22:36:47 +03:00
{
2007-06-29 20:04:26 +04:00
char * trunc_cmd ;
char * saveptr ;
2000-02-15 22:36:47 +03:00
char * ptr ;
int argcl ;
char * * argl = NULL ;
int i ;
2007-06-29 20:04:26 +04:00
if ( ! ( trunc_cmd = talloc_strdup ( mem_ctx , command ) ) ) {
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
goto nomem ;
}
2000-02-15 22:36:47 +03:00
2007-06-29 20:04:26 +04:00
if ( ! ( ptr = strtok_r ( trunc_cmd , " \t " , & saveptr ) ) ) {
TALLOC_FREE ( trunc_cmd ) ;
2000-02-15 22:36:47 +03:00
errno = EINVAL ;
return NULL ;
}
/*
* Count the args .
*/
2007-06-29 20:04:26 +04:00
for ( argcl = 1 ; ptr ; ptr = strtok_r ( NULL , " \t " , & saveptr ) )
2000-02-15 22:36:47 +03:00
argcl + + ;
2007-06-29 20:04:26 +04:00
TALLOC_FREE ( trunc_cmd ) ;
if ( ! ( argl = TALLOC_ARRAY ( mem_ctx , char * , argcl + 1 ) ) ) {
goto nomem ;
}
2000-02-15 22:36:47 +03:00
/*
* Now do the extraction .
*/
2007-06-29 20:04:26 +04:00
if ( ! ( trunc_cmd = talloc_strdup ( mem_ctx , command ) ) ) {
goto nomem ;
}
2000-02-15 22:36:47 +03:00
2007-06-29 20:04:26 +04:00
ptr = strtok_r ( trunc_cmd , " \t " , & saveptr ) ;
2000-02-15 22:36:47 +03:00
i = 0 ;
2007-06-29 20:04:26 +04:00
if ( ! ( argl [ i + + ] = talloc_strdup ( argl , ptr ) ) ) {
goto nomem ;
}
while ( ( ptr = strtok_r ( NULL , " \t " , & saveptr ) ) ! = NULL ) {
if ( ! ( argl [ i + + ] = talloc_strdup ( argl , ptr ) ) ) {
goto nomem ;
}
}
2000-02-15 22:36:47 +03:00
argl [ i + + ] = NULL ;
return argl ;
2007-06-29 20:04:26 +04:00
nomem :
DEBUG ( 0 , ( " talloc failed \n " ) ) ;
TALLOC_FREE ( trunc_cmd ) ;
TALLOC_FREE ( argl ) ;
errno = ENOMEM ;
return NULL ;
2000-02-15 22:36:47 +03:00
}
2000-05-02 06:23:41 +04:00
/**************************************************************************
Wrapper for fork . Ensures that mypid is reset . Used so we can write
a sys_getpid ( ) that only does a system call * once * .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static pid_t mypid = ( pid_t ) - 1 ;
pid_t sys_fork ( void )
{
pid_t forkret = fork ( ) ;
if ( forkret = = ( pid_t ) 0 ) /* Child - reset mypid so sys_getpid does a system call. */
mypid = ( pid_t ) - 1 ;
return forkret ;
}
/**************************************************************************
Wrapper for getpid . Ensures we only do a system call * once * .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
pid_t sys_getpid ( void )
{
if ( mypid = = ( pid_t ) - 1 )
mypid = getpid ( ) ;
return mypid ;
}
2000-02-15 22:36:47 +03:00
/**************************************************************************
Wrapper for popen . Safer as it doesn ' t search a path .
Modified from the glibc sources .
2000-04-16 15:00:21 +04:00
modified by tridge to return a file descriptor . We must kick our FILE * habit
2000-02-15 22:36:47 +03:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2000-05-02 06:23:41 +04:00
2000-02-15 22:36:47 +03:00
typedef struct _popen_list
{
2000-04-16 15:00:21 +04:00
int fd ;
2000-02-15 22:36:47 +03:00
pid_t child_pid ;
struct _popen_list * next ;
} popen_list ;
static popen_list * popen_chain ;
2000-04-16 15:00:21 +04:00
int sys_popen ( const char * command )
2000-02-15 22:36:47 +03:00
{
int parent_end , child_end ;
int pipe_fds [ 2 ] ;
2000-04-16 15:00:21 +04:00
popen_list * entry = NULL ;
2000-02-15 22:36:47 +03:00
char * * argl = NULL ;
if ( pipe ( pipe_fds ) < 0 )
2000-04-16 15:00:21 +04:00
return - 1 ;
2000-02-15 22:36:47 +03:00
2000-04-16 15:00:21 +04:00
parent_end = pipe_fds [ 0 ] ;
child_end = pipe_fds [ 1 ] ;
2000-02-15 22:36:47 +03:00
if ( ! * command ) {
errno = EINVAL ;
goto err_exit ;
}
2004-12-07 21:25:53 +03:00
if ( ( entry = SMB_MALLOC_P ( popen_list ) ) = = NULL )
2000-02-15 22:36:47 +03:00
goto err_exit ;
2000-10-09 01:21:27 +04:00
ZERO_STRUCTP ( entry ) ;
2000-02-15 22:36:47 +03:00
/*
* Extract the command and args into a NULL terminated array .
*/
2007-06-29 20:04:26 +04:00
if ( ! ( argl = extract_args ( NULL , command ) ) )
2000-02-15 22:36:47 +03:00
goto err_exit ;
2000-05-02 06:23:41 +04:00
entry - > child_pid = sys_fork ( ) ;
2000-02-15 22:36:47 +03:00
if ( entry - > child_pid = = - 1 ) {
goto err_exit ;
}
if ( entry - > child_pid = = 0 ) {
/*
* Child !
*/
2000-04-16 15:00:21 +04:00
int child_std_end = STDOUT_FILENO ;
2000-02-15 22:36:47 +03:00
popen_list * p ;
close ( parent_end ) ;
if ( child_end ! = child_std_end ) {
dup2 ( child_end , child_std_end ) ;
close ( child_end ) ;
}
/*
* POSIX .2 : " popen() shall ensure that any streams from previous
* popen ( ) calls that remain open in the parent process are closed
* in the new child process . "
*/
for ( p = popen_chain ; p ; p = p - > next )
2000-04-16 15:00:21 +04:00
close ( p - > fd ) ;
2000-02-15 22:36:47 +03:00
execv ( argl [ 0 ] , argl ) ;
_exit ( 127 ) ;
}
/*
* Parent .
*/
close ( child_end ) ;
2007-06-29 20:04:26 +04:00
TALLOC_FREE ( argl ) ;
2000-02-15 22:36:47 +03:00
/* Link into popen_chain. */
entry - > next = popen_chain ;
popen_chain = entry ;
2000-10-09 01:21:27 +04:00
entry - > fd = parent_end ;
2000-02-15 22:36:47 +03:00
2000-04-16 15:00:21 +04:00
return entry - > fd ;
2000-02-15 22:36:47 +03:00
err_exit :
2001-09-17 06:19:44 +04:00
SAFE_FREE ( entry ) ;
SAFE_FREE ( argl ) ;
2000-02-15 22:36:47 +03:00
close ( pipe_fds [ 0 ] ) ;
close ( pipe_fds [ 1 ] ) ;
2000-04-16 15:00:21 +04:00
return - 1 ;
2000-02-15 22:36:47 +03:00
}
/**************************************************************************
Wrapper for pclose . Modified from the glibc sources .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2002-01-10 03:28:09 +03:00
2000-04-16 15:00:21 +04:00
int sys_pclose ( int fd )
2000-02-15 22:36:47 +03:00
{
int wstatus ;
popen_list * * ptr = & popen_chain ;
popen_list * entry = NULL ;
pid_t wait_pid ;
int status = - 1 ;
/* Unlink from popen_chain. */
for ( ; * ptr ! = NULL ; ptr = & ( * ptr ) - > next ) {
2000-04-16 15:00:21 +04:00
if ( ( * ptr ) - > fd = = fd ) {
2000-02-15 22:36:47 +03:00
entry = * ptr ;
* ptr = ( * ptr ) - > next ;
status = 0 ;
break ;
}
}
2000-04-16 15:00:21 +04:00
if ( status < 0 | | close ( entry - > fd ) < 0 )
2000-02-15 22:36:47 +03:00
return - 1 ;
/*
* As Samba is catching and eating child process
* exits we don ' t really care about the child exit
* code , a - 1 with errno = ECHILD will do fine for us .
*/
do {
wait_pid = sys_waitpid ( entry - > child_pid , & wstatus , 0 ) ;
} while ( wait_pid = = - 1 & & errno = = EINTR ) ;
2001-09-17 06:19:44 +04:00
SAFE_FREE ( entry ) ;
2000-02-15 22:36:47 +03:00
if ( wait_pid = = - 1 )
return - 1 ;
return wstatus ;
}
2001-03-19 10:08:02 +03:00
/**************************************************************************
Wrappers for dlopen , dlsym , dlclose .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void * sys_dlopen ( const char * name , int flags )
{
2002-07-15 14:35:28 +04:00
# if defined(HAVE_DLOPEN)
2001-03-19 10:08:02 +03:00
return dlopen ( name , flags ) ;
# else
return NULL ;
# endif
}
2003-03-03 22:52:27 +03:00
void * sys_dlsym ( void * handle , const char * symbol )
2001-03-19 10:08:02 +03:00
{
2002-07-15 14:35:28 +04:00
# if defined(HAVE_DLSYM)
2001-03-19 10:08:02 +03:00
return dlsym ( handle , symbol ) ;
# else
return NULL ;
# endif
}
int sys_dlclose ( void * handle )
{
2002-07-15 14:35:28 +04:00
# if defined(HAVE_DLCLOSE)
2001-03-19 10:08:02 +03:00
return dlclose ( handle ) ;
# else
return 0 ;
# endif
}
2001-07-06 22:45:59 +04:00
const char * sys_dlerror ( void )
{
2002-07-15 14:35:28 +04:00
# if defined(HAVE_DLERROR)
2001-07-06 22:45:59 +04:00
return dlerror ( ) ;
# else
return NULL ;
# endif
}
2002-03-28 02:17:50 +03:00
2002-08-17 21:00:51 +04:00
int sys_dup2 ( int oldfd , int newfd )
{
# if defined(HAVE_DUP2)
return dup2 ( oldfd , newfd ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2002-03-28 02:17:50 +03:00
/**************************************************************************
Wrapper for Admin Logs .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2003-01-03 06:24:23 +03:00
void sys_adminlog ( int priority , const char * format_str , . . . )
2002-03-28 02:17:50 +03:00
{
va_list ap ;
int ret ;
2002-09-25 19:19:00 +04:00
char * msgbuf = NULL ;
2002-03-28 02:17:50 +03:00
va_start ( ap , format_str ) ;
2002-09-25 19:19:00 +04:00
ret = vasprintf ( & msgbuf , format_str , ap ) ;
2002-03-28 02:17:50 +03:00
va_end ( ap ) ;
if ( ret = = - 1 )
return ;
# if defined(HAVE_SYSLOG)
2002-09-25 19:19:00 +04:00
syslog ( priority , " %s " , msgbuf ) ;
2002-03-28 02:17:50 +03:00
# else
2002-09-25 19:19:00 +04:00
DEBUG ( 0 , ( " %s " , msgbuf ) ) ;
2002-03-28 02:17:50 +03:00
# endif
2002-09-25 19:19:00 +04:00
SAFE_FREE ( msgbuf ) ;
2002-03-28 02:17:50 +03:00
}
2003-06-06 00:29:55 +04:00
2007-08-10 13:44:13 +04:00
/******** Solaris EA helper function prototypes ********/
# ifdef HAVE_ATTROPEN
# define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
2007-08-19 23:52:18 +04:00
static int solaris_write_xattr ( int attrfd , const char * value , size_t size ) ;
static ssize_t solaris_read_xattr ( int attrfd , void * value , size_t size ) ;
static ssize_t solaris_list_xattr ( int attrdirfd , char * list , size_t size ) ;
static int solaris_unlinkat ( int attrdirfd , const char * name ) ;
static int solaris_attropen ( const char * path , const char * attrpath , int oflag , mode_t mode ) ;
static int solaris_openat ( int fildes , const char * path , int oflag , mode_t mode ) ;
2007-08-10 13:44:13 +04:00
# endif
2003-06-06 00:29:55 +04:00
/**************************************************************************
Wrappers for extented attribute calls . Based on the Linux package with
2005-10-29 02:22:23 +04:00
support for IRIX and ( Net | Free ) BSD also . Expand as other systems have them .
2003-06-06 00:29:55 +04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_getxattr ( const char * path , const char * name , void * value , size_t size )
{
# if defined(HAVE_GETXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return getxattr ( path , name , value , size ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return getxattr ( path , name , value , size , 0 , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_GETEA)
return getea ( path , name , value , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_GET_FILE)
char * s ;
2005-10-29 02:22:23 +04:00
ssize_t retval ;
2005-04-09 01:05:14 +04:00
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-10-29 02:22:23 +04:00
/*
* The BSD implementation has a nasty habit of silently truncating
* the returned value to the size of the buffer , so we have to check
* that the buffer is large enough to fit the returned value .
*/
2005-11-22 09:04:00 +03:00
if ( ( retval = extattr_get_file ( path , attrnamespace , attrname , NULL , 0 ) ) > = 0 ) {
if ( retval > size ) {
errno = ERANGE ;
return - 1 ;
}
if ( ( retval = extattr_get_file ( path , attrnamespace , attrname , value , size ) ) > = 0 )
return retval ;
2005-10-29 02:22:23 +04:00
}
2005-04-09 01:05:14 +04:00
2005-11-22 09:04:00 +03:00
DEBUG ( 10 , ( " sys_getxattr: extattr_get_file() failed with: %s \n " , strerror ( errno ) ) ) ;
return - 1 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_GET)
int retval , flags = 0 ;
int valuelength = ( int ) size ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
retval = attr_get ( path , attrname , ( char * ) value , & valuelength , flags ) ;
return retval ? retval : valuelength ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrfd = solaris_attropen ( path , name , O_RDONLY , 0 ) ;
if ( attrfd > = 0 ) {
ret = solaris_read_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
ssize_t sys_lgetxattr ( const char * path , const char * name , void * value , size_t size )
{
# if defined(HAVE_LGETXATTR)
return lgetxattr ( path , name , value , size ) ;
2006-10-11 15:41:39 +04:00
# elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
int options = XATTR_NOFOLLOW ;
return getxattr ( path , name , value , size , 0 , options ) ;
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_LGETEA)
return lgetea ( path , name , value , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_GET_LINK)
char * s ;
2005-10-29 02:22:23 +04:00
ssize_t retval ;
2005-04-09 01:05:14 +04:00
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-11-22 09:04:00 +03:00
if ( ( retval = extattr_get_link ( path , attrnamespace , attrname , NULL , 0 ) ) > = 0 ) {
if ( retval > size ) {
errno = ERANGE ;
return - 1 ;
}
if ( ( retval = extattr_get_link ( path , attrnamespace , attrname , value , size ) ) > = 0 )
return retval ;
2005-10-29 02:22:23 +04:00
}
2005-11-22 09:04:00 +03:00
DEBUG ( 10 , ( " sys_lgetxattr: extattr_get_link() failed with: %s \n " , strerror ( errno ) ) ) ;
return - 1 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_GET)
int retval , flags = ATTR_DONTFOLLOW ;
int valuelength = ( int ) size ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
retval = attr_get ( path , attrname , ( char * ) value , & valuelength , flags ) ;
return retval ? retval : valuelength ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrfd = solaris_attropen ( path , name , O_RDONLY | AT_SYMLINK_NOFOLLOW , 0 ) ;
if ( attrfd > = 0 ) {
ret = solaris_read_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
ssize_t sys_fgetxattr ( int filedes , const char * name , void * value , size_t size )
{
# if defined(HAVE_FGETXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return fgetxattr ( filedes , name , value , size ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return fgetxattr ( filedes , name , value , size , 0 , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_FGETEA)
return fgetea ( filedes , name , value , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_GET_FD)
char * s ;
2005-10-29 02:22:23 +04:00
ssize_t retval ;
2005-04-09 01:05:14 +04:00
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-11-22 09:04:00 +03:00
if ( ( retval = extattr_get_fd ( filedes , attrnamespace , attrname , NULL , 0 ) ) > = 0 ) {
if ( retval > size ) {
errno = ERANGE ;
return - 1 ;
}
if ( ( retval = extattr_get_fd ( filedes , attrnamespace , attrname , value , size ) ) > = 0 )
return retval ;
2005-10-29 02:22:23 +04:00
}
2005-11-22 09:04:00 +03:00
DEBUG ( 10 , ( " sys_fgetxattr: extattr_get_fd() failed with: %s \n " , strerror ( errno ) ) ) ;
return - 1 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_GETF)
int retval , flags = 0 ;
int valuelength = ( int ) size ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
retval = attr_getf ( filedes , attrname , ( char * ) value , & valuelength , flags ) ;
return retval ? retval : valuelength ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrfd = solaris_openat ( filedes , name , O_RDONLY | O_XATTR , 0 ) ;
if ( attrfd > = 0 ) {
ret = solaris_read_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2005-04-09 01:05:14 +04:00
# if defined(HAVE_EXTATTR_LIST_FILE)
# define EXTATTR_PREFIX(s) (s), (sizeof((s))-1)
static struct {
int space ;
const char * name ;
size_t len ;
}
extattr [ ] = {
{ EXTATTR_NAMESPACE_SYSTEM , EXTATTR_PREFIX ( " system. " ) } ,
{ EXTATTR_NAMESPACE_USER , EXTATTR_PREFIX ( " user. " ) } ,
} ;
typedef union {
const char * path ;
int filedes ;
} extattr_arg ;
static ssize_t bsd_attr_list ( int type , extattr_arg arg , char * list , size_t size )
{
ssize_t list_size , total_size = 0 ;
int i , t , len ;
char * buf ;
/* Iterate through extattr(2) namespaces */
for ( t = 0 ; t < ( sizeof ( extattr ) / sizeof ( extattr [ 0 ] ) ) ; t + + ) {
switch ( type ) {
# if defined(HAVE_EXTATTR_LIST_FILE)
case 0 :
list_size = extattr_list_file ( arg . path , extattr [ t ] . space , list , size ) ;
break ;
# endif
# if defined(HAVE_EXTATTR_LIST_LINK)
case 1 :
list_size = extattr_list_link ( arg . path , extattr [ t ] . space , list , size ) ;
break ;
# endif
# if defined(HAVE_EXTATTR_LIST_FD)
case 2 :
list_size = extattr_list_fd ( arg . filedes , extattr [ t ] . space , list , size ) ;
break ;
# endif
default :
errno = ENOSYS ;
return - 1 ;
}
/* Some error happend. Errno should be set by the previous call */
if ( list_size < 0 )
return - 1 ;
/* No attributes */
if ( list_size = = 0 )
continue ;
/* XXX: Call with an empty buffer may be used to calculate
necessary buffer size . Unfortunately , we can ' t say , how
many attributes were returned , so here is the potential
problem with the emulation .
*/
if ( list = = NULL ) {
/* Take the worse case of one char attribute names -
two bytes per name plus one more for sanity .
*/
total_size + = list_size + ( list_size / 2 + 1 ) * extattr [ t ] . len ;
continue ;
}
/* Count necessary offset to fit namespace prefixes */
len = 0 ;
for ( i = 0 ; i < list_size ; i + = list [ i ] + 1 )
len + = extattr [ t ] . len ;
total_size + = list_size + len ;
/* Buffer is too small to fit the results */
if ( total_size > size ) {
errno = ERANGE ;
return - 1 ;
}
2005-11-22 09:04:00 +03:00
/* Shift results back, so we can prepend prefixes */
2005-04-09 01:05:14 +04:00
buf = memmove ( list + len , list , list_size ) ;
for ( i = 0 ; i < list_size ; i + = len + 1 ) {
len = buf [ i ] ;
strncpy ( list , extattr [ t ] . name , extattr [ t ] . len + 1 ) ;
list + = extattr [ t ] . len ;
strncpy ( list , buf + i + 1 , len ) ;
list [ len ] = ' \0 ' ;
list + = len + 1 ;
}
size - = total_size ;
}
return total_size ;
}
# endif
2004-01-06 00:01:08 +03:00
# if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2003-08-15 05:29:08 +04:00
static char attr_buffer [ ATTR_MAX_VALUELEN ] ;
static ssize_t irix_attr_list ( const char * path , int filedes , char * list , size_t size , int flags )
{
int retval = 0 , index ;
attrlist_cursor_t * cursor = 0 ;
int total_size = 0 ;
attrlist_t * al = ( attrlist_t * ) attr_buffer ;
attrlist_ent_t * ae ;
size_t ent_size , left = size ;
char * bp = list ;
while ( True ) {
if ( filedes )
retval = attr_listf ( filedes , attr_buffer , ATTR_MAX_VALUELEN , flags , cursor ) ;
else
retval = attr_list ( path , attr_buffer , ATTR_MAX_VALUELEN , flags , cursor ) ;
if ( retval ) break ;
for ( index = 0 ; index < al - > al_count ; index + + ) {
ae = ATTR_ENTRY ( attr_buffer , index ) ;
ent_size = strlen ( ae - > a_name ) + sizeof ( " user. " ) ;
if ( left > = ent_size ) {
strncpy ( bp , " user. " , sizeof ( " user. " ) ) ;
strncat ( bp , ae - > a_name , ent_size - sizeof ( " user. " ) ) ;
bp + = ent_size ;
left - = ent_size ;
} else if ( size ) {
errno = ERANGE ;
retval = - 1 ;
break ;
}
total_size + = ent_size ;
}
if ( al - > al_more = = 0 ) break ;
}
if ( retval = = 0 ) {
flags | = ATTR_ROOT ;
cursor = 0 ;
while ( True ) {
if ( filedes )
retval = attr_listf ( filedes , attr_buffer , ATTR_MAX_VALUELEN , flags , cursor ) ;
else
retval = attr_list ( path , attr_buffer , ATTR_MAX_VALUELEN , flags , cursor ) ;
if ( retval ) break ;
for ( index = 0 ; index < al - > al_count ; index + + ) {
ae = ATTR_ENTRY ( attr_buffer , index ) ;
ent_size = strlen ( ae - > a_name ) + sizeof ( " system. " ) ;
if ( left > = ent_size ) {
strncpy ( bp , " system. " , sizeof ( " system. " ) ) ;
strncat ( bp , ae - > a_name , ent_size - sizeof ( " system. " ) ) ;
bp + = ent_size ;
left - = ent_size ;
} else if ( size ) {
errno = ERANGE ;
retval = - 1 ;
break ;
}
total_size + = ent_size ;
}
if ( al - > al_more = = 0 ) break ;
}
}
return ( ssize_t ) ( retval ? retval : total_size ) ;
}
# endif
2003-06-06 00:29:55 +04:00
ssize_t sys_listxattr ( const char * path , char * list , size_t size )
{
# if defined(HAVE_LISTXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return listxattr ( path , list , size ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return listxattr ( path , list , size , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_LISTEA)
return listea ( path , list , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_LIST_FILE)
extattr_arg arg ;
arg . path = path ;
return bsd_attr_list ( 0 , arg , list , size ) ;
2004-01-06 00:01:08 +03:00
# elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2003-08-15 05:29:08 +04:00
return irix_attr_list ( path , 0 , list , size , 0 ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrdirfd = solaris_attropen ( path , " . " , O_RDONLY , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_list_xattr ( attrdirfd , list , size ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
ssize_t sys_llistxattr ( const char * path , char * list , size_t size )
{
2003-08-15 05:29:08 +04:00
# if defined(HAVE_LLISTXATTR)
2003-06-06 00:29:55 +04:00
return llistxattr ( path , list , size ) ;
2006-10-11 15:41:39 +04:00
# elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
int options = XATTR_NOFOLLOW ;
return listxattr ( path , list , size , options ) ;
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_LLISTEA)
return llistea ( path , list , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_LIST_LINK)
extattr_arg arg ;
arg . path = path ;
return bsd_attr_list ( 1 , arg , list , size ) ;
2004-01-06 00:01:08 +03:00
# elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
2003-08-15 05:29:08 +04:00
return irix_attr_list ( path , 0 , list , size , ATTR_DONTFOLLOW ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrdirfd = solaris_attropen ( path , " . " , O_RDONLY | AT_SYMLINK_NOFOLLOW , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_list_xattr ( attrdirfd , list , size ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
ssize_t sys_flistxattr ( int filedes , char * list , size_t size )
{
# if defined(HAVE_FLISTXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return flistxattr ( filedes , list , size ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return flistxattr ( filedes , list , size , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_FLISTEA)
return flistea ( filedes , list , size ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_LIST_FD)
extattr_arg arg ;
arg . filedes = filedes ;
return bsd_attr_list ( 2 , arg , list , size ) ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_LISTF)
return irix_attr_list ( NULL , filedes , list , size , 0 ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
ssize_t ret = - 1 ;
int attrdirfd = solaris_openat ( filedes , " . " , O_RDONLY | O_XATTR , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_list_xattr ( attrdirfd , list , size ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
int sys_removexattr ( const char * path , const char * name )
{
# if defined(HAVE_REMOVEXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return removexattr ( path , name ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return removexattr ( path , name , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_REMOVEEA)
return removeea ( path , name ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_DELETE_FILE)
char * s ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
return extattr_delete_file ( path , attrnamespace , attrname ) ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_REMOVE)
int flags = 0 ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
return attr_remove ( path , attrname , flags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int attrdirfd = solaris_attropen ( path , " . " , O_RDONLY , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_unlinkat ( attrdirfd , name ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
int sys_lremovexattr ( const char * path , const char * name )
{
# if defined(HAVE_LREMOVEXATTR)
return lremovexattr ( path , name ) ;
2006-10-11 15:41:39 +04:00
# elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
int options = XATTR_NOFOLLOW ;
return removexattr ( path , name , options ) ;
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_LREMOVEEA)
return lremoveea ( path , name ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_DELETE_LINK)
char * s ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
return extattr_delete_link ( path , attrnamespace , attrname ) ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_REMOVE)
int flags = ATTR_DONTFOLLOW ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
return attr_remove ( path , attrname , flags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int attrdirfd = solaris_attropen ( path , " . " , O_RDONLY | AT_SYMLINK_NOFOLLOW , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_unlinkat ( attrdirfd , name ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
int sys_fremovexattr ( int filedes , const char * name )
{
# if defined(HAVE_FREMOVEXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return fremovexattr ( filedes , name ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return fremovexattr ( filedes , name , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_FREMOVEEA)
return fremoveea ( filedes , name ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_DELETE_FD)
char * s ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
return extattr_delete_fd ( filedes , attrnamespace , attrname ) ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_REMOVEF)
int flags = 0 ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) flags | = ATTR_ROOT ;
return attr_removef ( filedes , attrname , flags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int attrdirfd = solaris_openat ( filedes , " . " , O_RDONLY | O_XATTR , 0 ) ;
if ( attrdirfd > = 0 ) {
ret = solaris_unlinkat ( attrdirfd , name ) ;
close ( attrdirfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2003-08-15 05:29:08 +04:00
# if !defined(HAVE_SETXATTR)
# define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
# define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
# endif
2003-06-06 00:29:55 +04:00
int sys_setxattr ( const char * path , const char * name , const void * value , size_t size , int flags )
{
# if defined(HAVE_SETXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 00:29:55 +04:00
return setxattr ( path , name , value , size , flags ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return setxattr ( path , name , value , size , 0 , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_SETEA)
return setea ( path , name , value , size , flags ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_SET_FILE)
char * s ;
int retval = 0 ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-10-29 02:22:23 +04:00
if ( flags ) {
/* Check attribute existence */
retval = extattr_get_file ( path , attrnamespace , attrname , NULL , 0 ) ;
if ( retval < 0 ) {
/* REPLACE attribute, that doesn't exist */
if ( flags & XATTR_REPLACE & & errno = = ENOATTR ) {
errno = ENOATTR ;
return - 1 ;
}
2005-11-22 09:04:00 +03:00
/* Ignore other errors */
2005-10-29 02:22:23 +04:00
}
else {
/* CREATE attribute, that already exists */
if ( flags & XATTR_CREATE ) {
errno = EEXIST ;
return - 1 ;
}
}
}
2005-04-09 01:05:14 +04:00
retval = extattr_set_file ( path , attrnamespace , attrname , value , size ) ;
return ( retval < 0 ) ? - 1 : 0 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_SET)
int myflags = 0 ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) myflags | = ATTR_ROOT ;
if ( flags & XATTR_CREATE ) myflags | = ATTR_CREATE ;
if ( flags & XATTR_REPLACE ) myflags | = ATTR_REPLACE ;
return attr_set ( path , attrname , ( const char * ) value , size , myflags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int myflags = O_RDWR ;
if ( flags & XATTR_CREATE ) myflags | = O_EXCL ;
if ( ! ( flags & XATTR_REPLACE ) ) myflags | = O_CREAT ;
int attrfd = solaris_attropen ( path , name , myflags , ( mode_t ) SOLARIS_ATTRMODE ) ;
if ( attrfd > = 0 ) {
ret = solaris_write_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
int sys_lsetxattr ( const char * path , const char * name , const void * value , size_t size , int flags )
{
# if defined(HAVE_LSETXATTR)
return lsetxattr ( path , name , value , size , flags ) ;
2006-10-11 15:41:39 +04:00
# elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
int options = XATTR_NOFOLLOW ;
return setxattr ( path , name , value , size , 0 , options ) ;
2006-02-20 14:57:47 +03:00
# elif defined(LSETEA)
return lsetea ( path , name , value , size , flags ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_SET_LINK)
char * s ;
int retval = 0 ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-10-29 02:22:23 +04:00
if ( flags ) {
/* Check attribute existence */
retval = extattr_get_link ( path , attrnamespace , attrname , NULL , 0 ) ;
if ( retval < 0 ) {
/* REPLACE attribute, that doesn't exist */
if ( flags & XATTR_REPLACE & & errno = = ENOATTR ) {
errno = ENOATTR ;
return - 1 ;
}
2005-11-22 09:04:00 +03:00
/* Ignore other errors */
2005-10-29 02:22:23 +04:00
}
else {
/* CREATE attribute, that already exists */
if ( flags & XATTR_CREATE ) {
errno = EEXIST ;
return - 1 ;
}
}
}
2005-04-09 01:05:14 +04:00
retval = extattr_set_link ( path , attrnamespace , attrname , value , size ) ;
return ( retval < 0 ) ? - 1 : 0 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_SET)
int myflags = ATTR_DONTFOLLOW ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) myflags | = ATTR_ROOT ;
if ( flags & XATTR_CREATE ) myflags | = ATTR_CREATE ;
if ( flags & XATTR_REPLACE ) myflags | = ATTR_REPLACE ;
return attr_set ( path , attrname , ( const char * ) value , size , myflags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW ;
if ( flags & XATTR_CREATE ) myflags | = O_EXCL ;
if ( ! ( flags & XATTR_REPLACE ) ) myflags | = O_CREAT ;
int attrfd = solaris_attropen ( path , name , myflags , ( mode_t ) SOLARIS_ATTRMODE ) ;
if ( attrfd > = 0 ) {
ret = solaris_write_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
int sys_fsetxattr ( int filedes , const char * name , const void * value , size_t size , int flags )
{
# if defined(HAVE_FSETXATTR)
2006-10-11 15:41:39 +04:00
# ifndef XATTR_ADD_OPT
2003-06-06 11:06:30 +04:00
return fsetxattr ( filedes , name , value , size , flags ) ;
2006-10-11 15:41:39 +04:00
# else
int options = 0 ;
return fsetxattr ( filedes , name , value , size , 0 , options ) ;
# endif
2006-02-20 14:57:47 +03:00
# elif defined(HAVE_FSETEA)
return fsetea ( filedes , name , value , size , flags ) ;
2005-04-09 01:05:14 +04:00
# elif defined(HAVE_EXTATTR_SET_FD)
char * s ;
int retval = 0 ;
int attrnamespace = ( strncmp ( name , " system " , 6 ) = = 0 ) ?
EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER ;
const char * attrname = ( ( s = strchr_m ( name , ' . ' ) ) = = NULL ) ? name : s + 1 ;
2005-10-29 02:22:23 +04:00
if ( flags ) {
/* Check attribute existence */
retval = extattr_get_fd ( filedes , attrnamespace , attrname , NULL , 0 ) ;
if ( retval < 0 ) {
/* REPLACE attribute, that doesn't exist */
if ( flags & XATTR_REPLACE & & errno = = ENOATTR ) {
errno = ENOATTR ;
return - 1 ;
}
2005-11-22 09:04:00 +03:00
/* Ignore other errors */
2005-10-29 02:22:23 +04:00
}
else {
/* CREATE attribute, that already exists */
if ( flags & XATTR_CREATE ) {
errno = EEXIST ;
return - 1 ;
}
}
}
2005-04-09 01:05:14 +04:00
retval = extattr_set_fd ( filedes , attrnamespace , attrname , value , size ) ;
return ( retval < 0 ) ? - 1 : 0 ;
2003-08-15 05:29:08 +04:00
# elif defined(HAVE_ATTR_SETF)
int myflags = 0 ;
2005-04-09 01:05:14 +04:00
char * attrname = strchr ( name , ' . ' ) + 1 ;
2003-08-15 05:29:08 +04:00
if ( strncmp ( name , " system " , 6 ) = = 0 ) myflags | = ATTR_ROOT ;
if ( flags & XATTR_CREATE ) myflags | = ATTR_CREATE ;
if ( flags & XATTR_REPLACE ) myflags | = ATTR_REPLACE ;
return attr_setf ( filedes , attrname , ( const char * ) value , size , myflags ) ;
2007-08-10 13:44:13 +04:00
# elif defined(HAVE_ATTROPEN)
int ret = - 1 ;
int myflags = O_RDWR | O_XATTR ;
if ( flags & XATTR_CREATE ) myflags | = O_EXCL ;
if ( ! ( flags & XATTR_REPLACE ) ) myflags | = O_CREAT ;
int attrfd = solaris_openat ( filedes , name , myflags , ( mode_t ) SOLARIS_ATTRMODE ) ;
if ( attrfd > = 0 ) {
ret = solaris_write_xattr ( attrfd , value , size ) ;
close ( attrfd ) ;
}
return ret ;
2003-06-06 00:29:55 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
2004-09-26 10:27:54 +04:00
2007-08-10 13:44:13 +04:00
/**************************************************************************
helper functions for Solaris ' EA support
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifdef HAVE_ATTROPEN
static ssize_t solaris_read_xattr ( int attrfd , void * value , size_t size )
{
struct stat sbuf ;
if ( fstat ( attrfd , & sbuf ) = = - 1 ) {
errno = ENOATTR ;
return - 1 ;
}
/* This is to return the current size of the named extended attribute */
if ( size = = 0 ) {
return sbuf . st_size ;
}
/* check size and read xattr */
if ( sbuf . st_size > size ) {
errno = ERANGE ;
return - 1 ;
}
return read ( attrfd , value , sbuf . st_size ) ;
}
static ssize_t solaris_list_xattr ( int attrdirfd , char * list , size_t size )
{
ssize_t len = 0 ;
int stop = 0 ;
DIR * dirp ;
struct dirent * de ;
int newfd = dup ( attrdirfd ) ;
/* CAUTION: The originating file descriptor should not be
used again following the call to fdopendir ( ) .
For that reason we dup ( ) the file descriptor
here to make things more clear . */
dirp = fdopendir ( newfd ) ;
while ( ( de = readdir ( dirp ) ) ) {
size_t listlen = strlen ( de - > d_name ) ;
if ( ! strcmp ( de - > d_name , " . " ) | | ! strcmp ( de - > d_name , " .. " ) ) {
/* we don't want "." and ".." here: */
DEBUG ( 10 , ( " skipped EA %s \n " , de - > d_name ) ) ;
continue ;
}
if ( size = = 0 ) {
/* return the current size of the list of extended attribute names*/
len + = listlen + 1 ;
} else {
/* check size and copy entrieѕ + nul into list. */
if ( ( len + listlen + 1 ) > size ) {
errno = ERANGE ;
len = - 1 ;
break ;
} else {
safe_strcpy ( list + len , de - > d_name , listlen ) ;
pstrcpy ( list + len , de - > d_name ) ;
len + = listlen ;
list [ len ] = ' \0 ' ;
+ + len ;
}
}
}
if ( closedir ( dirp ) = = - 1 ) {
DEBUG ( 0 , ( " closedir dirp failed: %s \n " , strerror ( errno ) ) ) ;
return - 1 ;
}
return len ;
}
static int solaris_unlinkat ( int attrdirfd , const char * name )
{
if ( unlinkat ( attrdirfd , name , 0 ) = = - 1 ) {
if ( errno = = ENOENT ) {
errno = ENOATTR ;
}
return - 1 ;
}
return 0 ;
}
static int solaris_attropen ( const char * path , const char * attrpath , int oflag , mode_t mode )
{
int filedes = attropen ( path , attrpath , oflag , mode ) ;
if ( filedes = = - 1 ) {
DEBUG ( 10 , ( " attropen FAILED: path: %s, name: %s, errno: %s \n " , path , attrpath , strerror ( errno ) ) ) ;
if ( errno = = EINVAL ) {
errno = ENOTSUP ;
} else {
errno = ENOATTR ;
}
}
return filedes ;
}
static int solaris_openat ( int fildes , const char * path , int oflag , mode_t mode )
{
int filedes = openat ( fildes , path , oflag , mode ) ;
if ( filedes = = - 1 ) {
DEBUG ( 10 , ( " openat FAILED: fd: %s, path: %s, errno: %s \n " , filedes , path , strerror ( errno ) ) ) ;
if ( errno = = EINVAL ) {
errno = ENOTSUP ;
} else {
errno = ENOATTR ;
}
}
return filedes ;
}
static int solaris_write_xattr ( int attrfd , const char * value , size_t size )
{
if ( ( ftruncate ( attrfd , 0 ) = = 0 ) & & ( write ( attrfd , value , size ) = = size ) ) {
return 0 ;
} else {
DEBUG ( 10 , ( " solaris_write_xattr FAILED! \n " ) ) ;
return - 1 ;
}
}
# endif /*HAVE_ATTROPEN*/
2004-09-26 10:27:54 +04:00
/****************************************************************************
Return the major devicenumber for UNIX extensions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 unix_dev_major ( SMB_DEV_T dev )
{
# if defined(HAVE_DEVICE_MAJOR_FN)
return ( uint32 ) major ( dev ) ;
# else
return ( uint32 ) ( dev > > 8 ) ;
# endif
}
/****************************************************************************
Return the minor devicenumber for UNIX extensions .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
uint32 unix_dev_minor ( SMB_DEV_T dev )
{
# if defined(HAVE_DEVICE_MINOR_FN)
return ( uint32 ) minor ( dev ) ;
# else
return ( uint32 ) ( dev & 0xff ) ;
# endif
}
2005-06-28 02:53:56 +04:00
# if defined(WITH_AIO)
/*******************************************************************
An aio_read wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_read ( SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_READ64)
return aio_read64 ( aiocb ) ;
# elif defined(HAVE_AIO_READ)
return aio_read ( aiocb ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_write wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_write ( SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_WRITE64)
return aio_write64 ( aiocb ) ;
# elif defined(HAVE_AIO_WRITE)
return aio_write ( aiocb ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_return wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
ssize_t sys_aio_return ( SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_RETURN64)
return aio_return64 ( aiocb ) ;
# elif defined(HAVE_AIO_RETURN)
return aio_return ( aiocb ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_cancel wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_cancel ( int fd , SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_CANCEL64)
return aio_cancel64 ( fd , aiocb ) ;
# elif defined(HAVE_AIO_CANCEL)
return aio_cancel ( fd , aiocb ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_error wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_error ( const SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_ERROR64)
return aio_error64 ( aiocb ) ;
# elif defined(HAVE_AIO_ERROR)
return aio_error ( aiocb ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_fsync wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_fsync ( int op , SMB_STRUCT_AIOCB * aiocb )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_FSYNC64)
return aio_fsync64 ( op , aiocb ) ;
# elif defined(HAVE_AIO_FSYNC)
2005-07-22 09:00:27 +04:00
return aio_fsync ( op , aiocb ) ;
2005-06-28 02:53:56 +04:00
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
/*******************************************************************
An aio_fsync wrapper that will deal with 64 - bit sizes .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
int sys_aio_suspend ( const SMB_STRUCT_AIOCB * const cblist [ ] , int n , const struct timespec * timeout )
{
# if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_AIOCB64) && defined(HAVE_AIO_SUSPEND64)
return aio_suspend64 ( cblist , n , timeout ) ;
# elif defined(HAVE_AIO_FSYNC)
return aio_suspend ( cblist , n , timeout ) ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}
# else /* !WITH_AIO */
int sys_aio_read ( SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
int sys_aio_write ( SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
ssize_t sys_aio_return ( SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
int sys_aio_cancel ( int fd , SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
int sys_aio_error ( const SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
int sys_aio_fsync ( int op , SMB_STRUCT_AIOCB * aiocb )
{
errno = ENOSYS ;
return - 1 ;
}
int sys_aio_suspend ( const SMB_STRUCT_AIOCB * const cblist [ ] , int n , const struct timespec * timeout )
{
errno = ENOSYS ;
return - 1 ;
}
# endif /* WITH_AIO */
2006-08-19 05:04:54 +04:00
2006-08-21 00:05:49 +04:00
int sys_getpeereid ( int s , uid_t * uid )
2006-08-19 05:04:54 +04:00
{
# if defined(HAVE_PEERCRED)
struct ucred cred ;
socklen_t cred_len = sizeof ( struct ucred ) ;
int ret ;
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 ;
return 0 ;
# else
errno = ENOSYS ;
return - 1 ;
# endif
}