#!/usr/bin/env python APPNAME = 'libreplace' VERSION = '1.2.1' import sys import os # find the buildtools directory top = '.' while not os.path.exists(top+'/buildtools') and len(top.split('/')) < 5: top = top + '/..' sys.path.insert(0, top + '/buildtools/wafsamba') out = 'bin' import wafsamba from wafsamba import samba_dist from waflib import Options, Utils, Logs, Context samba_dist.DIST_DIRS('lib/replace buildtools:buildtools third_party/waf:third_party/waf') def options(opt): opt.BUILTIN_DEFAULT('NONE') opt.PRIVATE_EXTENSION_DEFAULT('') opt.RECURSE('buildtools/wafsamba') @Utils.run_once def configure(conf): conf.RECURSE('buildtools/wafsamba') conf.env.standalone_replace = conf.IN_LAUNCH_DIR() if sys.platform.rfind('linux') > -1: conf.DEFINE('LINUX', '1') conf.DEFINE('BOOL_DEFINED', 1) conf.DEFINE('HAVE_LIBREPLACE', 1) conf.DEFINE('LIBREPLACE_NETWORK_CHECKS', 1) conf.CHECK_HEADERS('linux/types.h crypt.h locale.h acl/libacl.h compat.h') conf.CHECK_HEADERS('acl/libacl.h attr/xattr.h compat.h ctype.h dustat.h') conf.CHECK_HEADERS('fcntl.h fnmatch.h glob.h history.h krb5.h langinfo.h') conf.CHECK_HEADERS('locale.h ndir.h pwd.h') conf.CHECK_HEADERS('shadow.h sys/acl.h') conf.CHECK_HEADERS('sys/attributes.h attr/attributes.h sys/capability.h sys/dir.h sys/epoll.h') conf.CHECK_HEADERS('sys/fcntl.h sys/filio.h sys/filsys.h sys/fs/s5param.h') conf.CHECK_HEADERS('sys/id.h sys/ioctl.h sys/ipc.h sys/mman.h sys/mode.h sys/ndir.h sys/priv.h') conf.CHECK_HEADERS('sys/resource.h sys/security.h sys/shm.h sys/statfs.h sys/statvfs.h sys/termio.h') conf.CHECK_HEADERS('sys/vfs.h sys/xattr.h termio.h termios.h sys/file.h') conf.CHECK_HEADERS('sys/ucontext.h sys/wait.h sys/stat.h') if not conf.CHECK_DECLS('malloc', headers='stdlib.h'): conf.CHECK_HEADERS('malloc.h') conf.CHECK_HEADERS('grp.h') conf.CHECK_HEADERS('sys/select.h setjmp.h utime.h sys/syslog.h syslog.h') conf.CHECK_HEADERS('stdarg.h vararg.h sys/mount.h mntent.h') conf.CHECK_HEADERS('stropts.h unix.h string.h strings.h sys/param.h limits.h') conf.CHECK_HEADERS('''sys/socket.h netinet/in.h netdb.h arpa/inet.h netinet/in_systm.h netinet/ip.h netinet/tcp.h netinet/in_ip.h sys/sockio.h sys/un.h''', together=True) conf.CHECK_HEADERS('sys/uio.h ifaddrs.h direct.h dirent.h') conf.CHECK_HEADERS('windows.h winsock2.h ws2tcpip.h') conf.CHECK_HEADERS('errno.h') conf.CHECK_HEADERS('getopt.h iconv.h') conf.CHECK_HEADERS('memory.h nss.h sasl/sasl.h') conf.CHECK_HEADERS('linux/openat2.h') conf.CHECK_FUNCS_IN('inotify_init', 'inotify', checklibc=True, headers='sys/inotify.h') conf.CHECK_HEADERS('security/pam_appl.h zlib.h asm/unistd.h') conf.CHECK_HEADERS('sys/unistd.h alloca.h float.h') conf.SET_TARGET_TYPE('tirpc', 'EMPTY') if conf.CHECK_CODE( '\n#ifndef _TIRPC_RPC_H\n#error "no tirpc headers in system path"\n#endif\n', 'HAVE_RPC_RPC_HEADERS', headers=['rpc/rpc.h', 'rpc/nettype.h'], msg='Checking for tirpc rpc headers in default system path'): if conf.CONFIG_SET('HAVE_RPC_RPC_H'): conf.undefine('HAVE_RPC_RPC_H') if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): if conf.CHECK_CFG(package='libtirpc', args='--cflags --libs', msg='Checking for libtirpc headers', uselib_store='TIRPC'): conf.CHECK_HEADERS('rpc/rpc.h rpc/nettype.h', lib='tirpc', together=True) conf.SET_TARGET_TYPE('tirpc', 'SYSLIB') if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): if conf.CHECK_CFG(package='libntirpc', args='--cflags', msg='Checking for libntirpc headers', uselib_store='TIRPC'): conf.CHECK_HEADERS('rpc/rpc.h rpc/nettype.h', lib='tirpc', together=True) conf.SET_TARGET_TYPE('tirpc', 'SYSLIB') if not conf.CONFIG_SET('HAVE_RPC_RPC_H'): Logs.warn('No rpc/rpc.h header found, tirpc or libntirpc missing?') # This file is decprecated with glibc >= 2.30 so we need to check if it # includes a deprecation warning: # #warning "The header is deprecated and will be removed." conf.CHECK_CODE(''' #include int main(void) { return 0; } ''', define='HAVE_SYS_SYSCTL_H', cflags=['-Werror=cpp'], addmain=False, msg='Checking for header sys/sysctl.h') conf.CHECK_HEADERS('sys/fileio.h sys/filesys.h sys/dustat.h sys/sysmacros.h') conf.CHECK_HEADERS('xfs/libxfs.h netgroup.h') conf.CHECK_HEADERS('valgrind.h valgrind/valgrind.h') conf.CHECK_HEADERS('valgrind/memcheck.h valgrind/helgrind.h valgrind/callgrind.h') conf.CHECK_HEADERS('nss_common.h nsswitch.h ns_api.h') conf.CHECK_HEADERS('sys/extattr.h sys/ea.h sys/proplist.h sys/cdefs.h') conf.CHECK_HEADERS('utmp.h utmpx.h lastlog.h') conf.CHECK_HEADERS('syscall.h sys/syscall.h inttypes.h') conf.CHECK_HEADERS('sys/atomic.h stdatomic.h') conf.CHECK_HEADERS('libgen.h') if conf.CHECK_CFLAGS('-Wno-format-truncation'): conf.define('HAVE_WNO_FORMAT_TRUNCATION', '1') if conf.CHECK_CFLAGS('-Wno-unused-function'): conf.define('HAVE_WNO_UNUSED_FUNCTION', '1') if conf.CHECK_CFLAGS('-Wno-strict-overflow'): conf.define('HAVE_WNO_STRICT_OVERFLOW', '1') if conf.CHECK_CFLAGS('-Wno-unused-but-set-variable'): conf.define('HAVE_WNO_UNUSED_BUT_SET_VARIABLE', '1') if conf.CHECK_CFLAGS('-Wuse-after-free=1'): conf.define('HAVE_WUSE_AFTER_FREE_1', '1') # Check for process set name support conf.CHECK_CODE(''' #include int main(void) { prctl(0); return 0; } ''', 'HAVE_PRCTL', addmain=False, headers='sys/prctl.h', msg='Checking for prctl syscall') conf.CHECK_CODE(''' #include #ifdef HAVE_FCNTL_H #include #endif int main(void) { int fd = open("/dev/null", O_DIRECT); } ''', define='HAVE_OPEN_O_DIRECT', addmain=False, msg='Checking for O_DIRECT flag to open(2)') conf.CHECK_TYPES('"long long" intptr_t uintptr_t ptrdiff_t comparison_fn_t') if not conf.CHECK_TYPE('bool', define='HAVE_BOOL', headers='stdbool.h'): raise Errors.WafError('Samba requires a genuine boolean type') conf.CHECK_TYPE('int8_t', 'char') conf.CHECK_TYPE('uint8_t', 'unsigned char') conf.CHECK_TYPE('int16_t', 'short') conf.CHECK_TYPE('uint16_t', 'unsigned short') conf.CHECK_TYPE('int32_t', 'int') conf.CHECK_TYPE('uint32_t', 'unsigned') conf.CHECK_TYPE('int64_t', 'long long') conf.CHECK_TYPE('uint64_t', 'unsigned long long') conf.CHECK_TYPE('size_t', 'unsigned int') conf.CHECK_TYPE('ssize_t', 'int') conf.CHECK_TYPE('ino_t', 'unsigned') conf.CHECK_TYPE('loff_t', 'off_t') conf.CHECK_TYPE('offset_t', 'loff_t') conf.CHECK_TYPE('volatile int', define='HAVE_VOLATILE') conf.CHECK_TYPE('uint_t', 'unsigned int') conf.CHECK_TYPE('blksize_t', 'long', headers='sys/types.h sys/stat.h unistd.h') conf.CHECK_TYPE('blkcnt_t', 'long', headers='sys/types.h sys/stat.h unistd.h') conf.CHECK_SIZEOF('bool char int "long long" long short size_t ssize_t') sizeof_int = conf.env["SIZEOF_INT"] if sizeof_int < 4: conf.fatal(f"Samba won't work with int of size {sizeof_int} (requires >= 4)") conf.CHECK_SIZEOF('int8_t uint8_t int16_t uint16_t int32_t uint32_t int64_t uint64_t') conf.CHECK_SIZEOF('void*', define='SIZEOF_VOID_P') conf.CHECK_SIZEOF('off_t dev_t ino_t time_t') conf.CHECK_TYPES('socklen_t', headers='sys/socket.h') conf.CHECK_TYPE_IN('struct ifaddrs', 'ifaddrs.h') conf.CHECK_TYPE_IN('struct addrinfo', 'netdb.h') conf.CHECK_TYPE_IN('struct sockaddr', 'sys/socket.h') conf.CHECK_CODE('struct sockaddr_in6 x', define='HAVE_STRUCT_SOCKADDR_IN6', headers='sys/socket.h netdb.h netinet/in.h') conf.CHECK_TYPE_IN('struct sockaddr_storage', 'sys/socket.h') conf.CHECK_TYPE_IN('sa_family_t', 'sys/socket.h') conf.CHECK_TYPE_IN('sig_atomic_t', 'signal.h', define='HAVE_SIG_ATOMIC_T_TYPE') conf.CHECK_FUNCS('sigsetmask siggetmask sigprocmask sigblock sigaction sigset') # Those functions are normally available in libc if not conf.CHECK_FUNCS(''' inet_ntoa inet_aton inet_ntop inet_pton connect gethostbyname getaddrinfo getnameinfo freeaddrinfo gai_strerror socketpair''', headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h'): conf.CHECK_FUNCS_IN(''' inet_ntoa inet_aton inet_ntop inet_pton connect gethostbyname getaddrinfo getnameinfo freeaddrinfo gai_strerror socketpair''', 'socket nsl', headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') conf.DEFINE('REPLACE_REQUIRES_LIBSOCKET_LIBNSL', 1) conf.CHECK_FUNCS('memset_s memset_explicit') conf.CHECK_CODE(''' #include int main(void) { char buf[] = "This is some content"; memset(buf, '\0', sizeof(buf)); __asm__ volatile("" : : "g"(&buf) : "memory"); return 0; } ''', define='HAVE_GCC_VOLATILE_MEMORY_PROTECTION', addmain=False, msg='Checking for volatile memory protection', local_include=False) # Some old Linux systems have broken header files and # miss the IPV6_V6ONLY define in netinet/in.h, # but have it in linux/in6.h. # We can't include both files so we just check if the value # if defined and do the replacement in system/network.h if not conf.CHECK_VARIABLE('IPV6_V6ONLY', headers='sys/socket.h netdb.h netinet/in.h'): conf.CHECK_CODE(''' #include #if (IPV6_V6ONLY != 26) #error no IPV6_V6ONLY support on linux #endif int main(void) { return IPV6_V6ONLY; } ''', define='HAVE_LINUX_IPV6_V6ONLY_26', addmain=False, msg='Checking for IPV6_V6ONLY in linux/in6.h', local_include=False) conf.CHECK_CODE(''' struct sockaddr_storage sa_store; struct addrinfo *ai = NULL; struct in6_addr in6addr; int idx = if_nametoindex("iface1"); int s = socket(AF_INET6, SOCK_STREAM, 0); int ret = getaddrinfo(NULL, NULL, NULL, &ai); if (ret != 0) { const char *es = gai_strerror(ret); } freeaddrinfo(ai); { int val = 1; #ifdef HAVE_LINUX_IPV6_V6ONLY_26 #define IPV6_V6ONLY 26 #endif ret = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, (const void *)&val, sizeof(val)); } ''', define='HAVE_IPV6', lib='nsl socket', headers='sys/socket.h netdb.h netinet/in.h net/if.h') if conf.CONFIG_SET('HAVE_SYS_UCONTEXT_H') and conf.CONFIG_SET('HAVE_SIGNAL_H'): conf.CHECK_CODE(''' ucontext_t uc; sigaddset(&uc.uc_sigmask, SIGUSR1); ''', 'HAVE_UCONTEXT_T', msg="Checking whether we have ucontext_t", headers='signal.h sys/ucontext.h') # Check for atomic builtins. */ conf.CHECK_CODE(''' int i; (void)__sync_fetch_and_add(&i, 1); ''', 'HAVE___SYNC_FETCH_AND_ADD', msg='Checking for __sync_fetch_and_add compiler builtin') conf.CHECK_CODE(''' int i; (void)__sync_add_and_fetch(&i, 1); ''', 'HAVE___SYNC_ADD_AND_FETCH', msg='Checking for __sync_add_and_fetch compiler builtin') conf.CHECK_CODE(''' int32_t i; atomic_add_32(&i, 1); ''', 'HAVE_ATOMIC_ADD_32', headers='stdint.h sys/atomic.h', msg='Checking for atomic_add_32 compiler builtin') conf.CHECK_CODE(''' uint32_t i,j; j = __atomic_add_fetch(&i,1,__ATOMIC_SEQ_CST) ''', 'HAVE___ATOMIC_ADD_FETCH', headers='stdint.h', msg='Checking for __atomic_add_fetch compiler builtin') conf.CHECK_CODE(''' uint32_t i,j; __atomic_load(&i,&j,__ATOMIC_SEQ_CST) ''', 'HAVE___ATOMIC_ADD_LOAD', headers='stdint.h', msg='Checking for __atomic_load compiler builtin') # Check for thread fence. */ tf = conf.CHECK_CODE('atomic_thread_fence(memory_order_seq_cst);', 'HAVE_ATOMIC_THREAD_FENCE', headers='stdatomic.h', msg='Checking for atomic_thread_fence(memory_order_seq_cst) in stdatomic.h') if not tf: tf = conf.CHECK_CODE('__atomic_thread_fence(__ATOMIC_SEQ_CST);', 'HAVE___ATOMIC_THREAD_FENCE', msg='Checking for __atomic_thread_fence(__ATOMIC_SEQ_CST)') if not tf: # __sync_synchronize() is available since 2005 in gcc. tf = conf.CHECK_CODE('__sync_synchronize();', 'HAVE___SYNC_SYNCHRONIZE', msg='Checking for __sync_synchronize') if tf: conf.DEFINE('HAVE_ATOMIC_THREAD_FENCE_SUPPORT', 1) conf.CHECK_CODE(''' #define FALL_THROUGH __attribute__((fallthrough)) enum direction_e { UP = 0, DOWN, }; int main(void) { enum direction_e key = UP; int i = 10; int j = 0; switch (key) { case UP: i = 5; FALL_THROUGH; case DOWN: j = i * 2; break; default: break; } if (j < i) { return 1; } return 0; } ''', 'HAVE_FALLTHROUGH_ATTRIBUTE', addmain=False, strict=True, cflags=['-Werror=missing-declarations'], msg='Checking for fallthrough attribute') # these may be builtins, so we need the link=False strategy conf.CHECK_FUNCS('strdup memmem printf memset memcpy memmove strcpy strncpy bzero', link=False) # See https://bugzilla.samba.org/show_bug.cgi?id=1097 # # Ported in from autoconf where it was added with this commit: # commit 804cfb20a067b4b687089dc72a8271b3abf20f31 # Author: Simo Sorce # Date: Wed Aug 25 14:24:16 2004 +0000 # r2070: Let's try to overload srnlen and strndup for AIX where they are natly broken. host_os = sys.platform if host_os.rfind('aix') > -1: conf.DEFINE('BROKEN_STRNLEN', 1) conf.DEFINE('BROKEN_STRNDUP', 1) conf.CHECK_FUNCS('shl_load shl_unload shl_findsym') conf.CHECK_FUNCS('pipe strftime srandom random srand rand usleep setbuffer') conf.CHECK_FUNCS('lstat getpgrp utime utimes setuid seteuid setreuid setresuid setgid setegid') conf.CHECK_FUNCS('setregid setresgid chroot strerror vsyslog setlinebuf mktime') conf.CHECK_FUNCS('ftruncate chsize rename waitpid wait4') conf.CHECK_FUNCS('initgroups pread pwrite strndup strcasestr strsep') conf.CHECK_FUNCS('strtok_r mkdtemp dup2 dprintf vdprintf isatty chown lchown') conf.CHECK_FUNCS('link readlink symlink realpath snprintf vsnprintf') conf.CHECK_FUNCS('asprintf vasprintf setenv unsetenv strnlen strtoull __strtoull') conf.CHECK_FUNCS('strtouq strtoll __strtoll strtoq memalign posix_memalign') conf.CHECK_FUNCS('fmemopen') if conf.CONFIG_SET('HAVE_MEMALIGN'): conf.CHECK_DECLS('memalign', headers='malloc.h') # glibc up to 2.3.6 had dangerously broken posix_fallocate(). DON'T USE IT. if conf.CHECK_CODE(''' #define _XOPEN_SOURCE 600 #include #if defined(__GLIBC__) && ((__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 4)) #error probably broken posix_fallocate #endif ''', '_POSIX_FALLOCATE_CAPABLE_LIBC', msg='Checking for posix_fallocate-capable libc'): conf.CHECK_FUNCS('posix_fallocate') conf.CHECK_FUNCS('prctl dirname basename') strlcpy_in_bsd = False # libbsd on some platforms provides strlcpy and strlcat if not conf.CHECK_FUNCS('strlcpy strlcat'): if conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h', checklibc=True): strlcpy_in_bsd = True elif conf.env.enable_fuzzing: # Just to complicate it more, some versions of Honggfuzz have # got strlcpy and strlcat in libc, but not in # (unless it is there coincidentally, on a BSD). Therefore we # can't use CHECK_FUNCS alone to decide whether to add the # headers to replace.h. # # As this is only known to happen on a fuzzing compiler, we'll # skip the check when not in fuzzing mode. conf.CHECK_HEADERS('bsd/string.h') if not conf.CHECK_FUNCS('getpeereid'): conf.CHECK_FUNCS_IN('getpeereid', 'bsd', headers='sys/types.h bsd/unistd.h') if not conf.CHECK_FUNCS_IN('setproctitle', 'setproctitle', headers='setproctitle.h'): conf.CHECK_FUNCS_IN('setproctitle', 'bsd', headers='sys/types.h bsd/unistd.h') if not conf.CHECK_FUNCS('setproctitle_init'): conf.CHECK_FUNCS_IN('setproctitle_init', 'bsd', headers='sys/types.h bsd/unistd.h') if not conf.CHECK_FUNCS('closefrom'): conf.CHECK_FUNCS_IN('closefrom', 'bsd', headers='bsd/unistd.h') conf.CHECK_CODE(''' struct ucred cred; socklen_t cred_len; int ret = getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len);''', 'HAVE_PEERCRED', msg="Checking whether we can use SO_PEERCRED to get socket credentials", headers='sys/types.h sys/socket.h') #Some OS (ie. freebsd) return EINVAL if the conversion could not be done, it's not what we expect #Let's detect those cases if conf.CONFIG_SET('HAVE_STRTOLL'): conf.CHECK_CODE(''' long long nb = strtoll("Text", NULL, 0); if (errno == EINVAL) { return 0; } else { return 1; } ''', msg="Checking correct behavior of strtoll", headers = 'errno.h', execute = True, define = 'HAVE_BSD_STRTOLL', ) conf.CHECK_FUNCS('if_nameindex if_nametoindex strerror_r') conf.CHECK_FUNCS('syslog') conf.CHECK_FUNCS('gai_strerror get_current_dir_name') conf.CHECK_FUNCS('timegm getifaddrs freeifaddrs mmap setgroups syscall setsid') conf.CHECK_FUNCS('getgrent_r getgrgid_r getgrnam_r getgrouplist getpagesize') conf.CHECK_FUNCS('getpwent_r getpwnam_r getpwuid_r epoll_create1') conf.CHECK_FUNCS('getprogname') if not conf.CHECK_FUNCS('copy_file_range'): conf.CHECK_CODE(''' syscall(SYS_copy_file_range,0,NULL,0,NULL,0,0); ''', 'HAVE_SYSCALL_COPY_FILE_RANGE', headers='sys/syscall.h unistd.h', msg='Checking whether we have copy_file_range system call') conf.SET_TARGET_TYPE('attr', 'EMPTY') xattr_headers='sys/attributes.h attr/xattr.h sys/xattr.h' # default to 1, we set it to 0 if we don't find any EA implementation below: conf.DEFINE('HAVE_XATTR_SUPPORT', 1) if conf.CHECK_FUNCS_IN('getxattr', 'attr', checklibc=True, headers=xattr_headers): conf.DEFINE('HAVE_XATTR_XATTR', 1) # Darwin has extra options to xattr-family functions conf.CHECK_CODE('getxattr(NULL, NULL, NULL, 0, 0, 0)', headers=xattr_headers, local_include=False, define='XATTR_ADDITIONAL_OPTIONS', msg="Checking whether xattr interface takes additional options") elif conf.CHECK_FUNCS_IN('attr_listf', 'attr', checklibc=True, headers=xattr_headers): conf.DEFINE('HAVE_XATTR_ATTR', 1) elif conf.CHECK_FUNCS('extattr_list_fd'): conf.DEFINE('HAVE_XATTR_EXTATTR', 1) elif conf.CHECK_FUNCS('flistea'): conf.DEFINE('HAVE_XATTR_EA', 1) elif not conf.CHECK_FUNCS('attropen'): conf.DEFINE('HAVE_XATTR_SUPPORT', 0) conf.CHECK_FUNCS_IN('dlopen dlsym dlerror dlclose', 'dl', checklibc=True, headers='dlfcn.h dl.h') conf.CHECK_C_PROTOTYPE('dlopen', 'void *dlopen(const char* filename, unsigned int flags)', define='DLOPEN_TAKES_UNSIGNED_FLAGS', headers='dlfcn.h dl.h') # # Check for clock_gettime and fdatasync # # First check libc to avoid linking libreplace against librt. # if conf.CHECK_FUNCS('fdatasync'): # some systems are missing the declaration conf.CHECK_DECLS('fdatasync') else: if conf.CHECK_FUNCS_IN('fdatasync', 'rt'): # some systems are missing the declaration conf.CHECK_DECLS('fdatasync') has_clock_gettime = False if conf.CHECK_FUNCS('clock_gettime'): has_clock_gettime = True if not has_clock_gettime: if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): has_clock_gettime = True if has_clock_gettime: for c in ['CLOCK_MONOTONIC', 'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME']: conf.CHECK_CODE(''' #if TIME_WITH_SYS_TIME # include # include #else # if HAVE_SYS_TIME_H # include # else # include # endif #endif clockid_t clk = %s''' % c, 'HAVE_%s' % c, msg='Checking whether the clock_gettime clock ID %s is available' % c) conf.CHECK_TYPE('struct timespec', headers='sys/time.h time.h') # these headers need to be tested as a group on freebsd conf.CHECK_HEADERS(headers='sys/socket.h net/if.h', together=True) conf.CHECK_HEADERS(headers='netinet/in.h arpa/nameser.h resolv.h', together=True) conf.CHECK_FUNCS_IN('res_search', 'resolv', checklibc=True, headers='netinet/in.h arpa/nameser.h resolv.h') # try to find libintl (if --without-gettext is not given) conf.env.intl_libs='' if not Options.options.disable_gettext: conf.CHECK_HEADERS('libintl.h') conf.CHECK_LIB('intl') conf.CHECK_DECLS('dgettext gettext bindtextdomain textdomain bind_textdomain_codeset', headers="libintl.h") # *textdomain functions are not strictly necessary conf.CHECK_FUNCS_IN('bindtextdomain textdomain bind_textdomain_codeset', '', checklibc=True, headers='libintl.h') # gettext and dgettext must exist # on some systems (the ones with glibc, those are in libc) if conf.CHECK_FUNCS_IN('dgettext gettext', '', checklibc=True, headers='libintl.h'): # save for dependency definitions conf.env.intl_libs='' # others (e.g. FreeBSD) have separate libintl elif conf.CHECK_FUNCS_IN('dgettext gettext', 'intl', checklibc=False, headers='libintl.h'): # save for dependency definitions conf.env.intl_libs='intl' # recheck with libintl conf.CHECK_FUNCS_IN('bindtextdomain textdomain bind_textdomain_codeset', 'intl', checklibc=False, headers='libintl.h') else: # Some hosts need lib iconv for linking with lib intl # So we try with flags just in case it helps. oldflags = list(conf.env['EXTRA_LDFLAGS']); conf.env['EXTRA_LDFLAGS'].extend(["-liconv"]) conf.CHECK_FUNCS_IN('dgettext gettext bindtextdomain textdomain bind_textdomain_codeset', 'intl', checklibc=False, headers='libintl.h') conf.env['EXTRA_LDFLAGS'] = oldflags if conf.env['HAVE_GETTEXT'] and conf.env['HAVE_DGETTEXT']: # save for dependency definitions conf.env.intl_libs='iconv intl' # did we find both prototypes and a library to link against? # if not, unset the detected values (see Bug #9911) if not (conf.env['HAVE_GETTEXT'] and conf.env['HAVE_DECL_GETTEXT']): conf.undefine('HAVE_GETTEXT') conf.undefine('HAVE_DECL_GETTEXT') if not (conf.env['HAVE_DGETTEXT'] and conf.env['HAVE_DECL_DGETTEXT']): conf.undefine('HAVE_DGETTEXT') conf.undefine('HAVE_DECL_DGETTEXT') conf.CHECK_FUNCS_IN('pthread_create', 'pthread', checklibc=True, headers='pthread.h') PTHREAD_CFLAGS='error' PTHREAD_LDFLAGS='error' if PTHREAD_LDFLAGS == 'error': # Check if pthread_attr_init() is provided by libc first! if conf.CHECK_FUNCS('pthread_attr_init'): PTHREAD_CFLAGS='-D_REENTRANT' PTHREAD_LDFLAGS='' if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS_IN('pthread_attr_init', 'pthread'): PTHREAD_CFLAGS='-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS' PTHREAD_LDFLAGS='-lpthread' if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS_IN('pthread_attr_init', 'pthreads'): PTHREAD_CFLAGS='-D_THREAD_SAFE' PTHREAD_LDFLAGS='-lpthreads' if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS_IN('pthread_attr_init', 'c_r'): PTHREAD_CFLAGS='-D_THREAD_SAFE -pthread' PTHREAD_LDFLAGS='-pthread' # especially for HP-UX, where the CHECK_FUNC macro fails to test for # pthread_attr_init. On pthread_mutex_lock it works there... if PTHREAD_LDFLAGS == 'error': if conf.CHECK_FUNCS_IN('pthread_mutex_lock', 'pthread'): PTHREAD_CFLAGS='-D_REENTRANT' PTHREAD_LDFLAGS='-lpthread' if PTHREAD_CFLAGS != 'error' and PTHREAD_LDFLAGS != 'error': if conf.CONFIG_SET('replace_add_global_pthread'): conf.ADD_CFLAGS(PTHREAD_CFLAGS) conf.ADD_LDFLAGS(PTHREAD_LDFLAGS) conf.CHECK_HEADERS('pthread.h') conf.DEFINE('HAVE_PTHREAD', '1') if conf.CONFIG_SET('HAVE_PTHREAD'): conf.CHECK_FUNCS_IN('pthread_mutexattr_setrobust', 'pthread', checklibc=True, headers='pthread.h') if not conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST'): conf.CHECK_FUNCS_IN('pthread_mutexattr_setrobust_np', 'pthread', checklibc=True, headers='pthread.h') conf.CHECK_DECLS('PTHREAD_MUTEX_ROBUST', headers='pthread.h') if not conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST'): conf.CHECK_DECLS('PTHREAD_MUTEX_ROBUST_NP', headers='pthread.h') conf.CHECK_FUNCS_IN('pthread_mutex_consistent', 'pthread', checklibc=True, headers='pthread.h') if not conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT'): conf.CHECK_FUNCS_IN('pthread_mutex_consistent_np', 'pthread', checklibc=True, headers='pthread.h') if ((conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST') or conf.CONFIG_SET('HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP')) and (conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST') or conf.CONFIG_SET('HAVE_DECL_PTHREAD_MUTEX_ROBUST_NP')) and (conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT') or conf.CONFIG_SET('HAVE_PTHREAD_MUTEX_CONSISTENT_NP'))): conf.DEFINE('HAVE_ROBUST_MUTEXES', 1) # __thread is available in Solaris Studio, IBM XL, # gcc, Clang and Intel C Compiler conf.CHECK_CODE(''' __thread int tls; int main(void) { return 0; } ''', 'HAVE___THREAD', addmain=False, msg='Checking for __thread local storage') if conf.CONFIG_SET('HAVE_PTHREAD') and not conf.CONFIG_SET('HAVE___THREAD'): conf.fatal('Missing required TLS support in pthread library') conf.CHECK_FUNCS_IN('crypt', 'crypt', checklibc=True) conf.CHECK_FUNCS_IN('crypt_r', 'crypt', checklibc=True) conf.CHECK_FUNCS_IN('crypt_rn', 'crypt', checklibc=True) conf.CHECK_VARIABLE('rl_event_hook', define='HAVE_DECL_RL_EVENT_HOOK', always=True, headers='readline.h readline/readline.h readline/history.h') conf.CHECK_VARIABLE('program_invocation_short_name', headers='errno.h') conf.CHECK_DECLS('snprintf vsnprintf asprintf vasprintf') conf.CHECK_DECLS('errno', headers='errno.h', reverse=True) conf.CHECK_DECLS('EWOULDBLOCK', headers='errno.h') conf.CHECK_DECLS('environ', reverse=True, headers='unistd.h') conf.CHECK_DECLS('getgrent_r getpwent_r', reverse=True, headers='pwd.h grp.h') conf.CHECK_DECLS('pread pwrite setenv setresgid setresuid', reverse=True) if conf.CONFIG_SET('HAVE_EPOLL_CREATE1') and conf.CONFIG_SET('HAVE_SYS_EPOLL_H'): conf.DEFINE('HAVE_EPOLL', 1) if conf.CHECK_FUNCS('eventfd', headers='sys/eventfd.h'): conf.DEFINE('HAVE_EVENTFD', 1) conf.CHECK_HEADERS('poll.h') conf.CHECK_FUNCS('poll') conf.CHECK_FUNCS('strptime') conf.CHECK_DECLS('strptime', headers='time.h') conf.CHECK_CODE('''#define LIBREPLACE_CONFIGURE_TEST_STRPTIME #include "tests/strptime.c"''', define='HAVE_WORKING_STRPTIME', execute=True, addmain=False, msg='Checking for working strptime') conf.CHECK_C_PROTOTYPE('gettimeofday', 'int gettimeofday(struct timeval *tv, struct timezone *tz)', define='HAVE_GETTIMEOFDAY_TZ', headers='sys/time.h') conf.CHECK_C_PROTOTYPE('gettimeofday', 'int gettimeofday(struct timeval *tv, void *tz)', define='HAVE_GETTIMEOFDAY_TZ_VOID', headers='sys/time.h') conf.CHECK_CODE('#include "tests/snprintf.c"', define="HAVE_C99_VSNPRINTF", execute=True, addmain=False, msg="Checking for C99 vsnprintf") conf.CHECK_CODE('#include "tests/shared_mmap.c"', addmain=False, add_headers=False, execute=True, define='HAVE_SHARED_MMAP', msg="Checking for HAVE_SHARED_MMAP") conf.CHECK_CODE('#include "tests/shared_mremap.c"', addmain=False, add_headers=False, execute=True, define='HAVE_MREMAP', msg="Checking for HAVE_MREMAP") # OpenBSD (and I've heard HPUX) doesn't sync between mmap and write. # FIXME: Anything other than a 0 or 1 exit code should abort configure! conf.CHECK_CODE('#include "tests/incoherent_mmap.c"', addmain=False, add_headers=False, execute=True, define='HAVE_INCOHERENT_MMAP', msg="Checking for HAVE_INCOHERENT_MMAP") conf.SAMBA_BUILD_ENV() conf.CHECK_CODE(''' typedef struct {unsigned x;} FOOBAR; #define X_FOOBAR(x) ((FOOBAR) { x }) #define FOO_ONE X_FOOBAR(1) FOOBAR f = FOO_ONE; static const struct { FOOBAR y; } f2[] = { {FOO_ONE} }; static const FOOBAR f3[] = {FOO_ONE}; ''', define='HAVE_IMMEDIATE_STRUCTURES') conf.CHECK_CODE('mkdir("foo",0777)', define='HAVE_MKDIR_MODE', headers='sys/stat.h') # we need the st_rdev test under two names conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_rdev', define='HAVE_STRUCT_STAT_ST_RDEV', headers='sys/stat.h') conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_rdev', define='HAVE_ST_RDEV', headers='sys/stat.h') conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_storage', 'ss_family', headers='sys/socket.h netinet/in.h') conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_storage', '__ss_family', headers='sys/socket.h netinet/in.h') if conf.CHECK_STRUCTURE_MEMBER('struct sockaddr', 'sa_len', headers='sys/socket.h netinet/in.h', define='HAVE_SOCKADDR_SA_LEN'): # the old build system produced both defines conf.DEFINE('HAVE_STRUCT_SOCKADDR_SA_LEN', 1) conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_in', 'sin_len', headers='sys/socket.h netinet/in.h', define='HAVE_SOCK_SIN_LEN') conf.CHECK_STRUCTURE_MEMBER('struct sockaddr_in6', 'sin6_len', headers='sys/socket.h netinet/in.h', define='HAVE_SOCK_SIN6_LEN') conf.CHECK_CODE('struct sockaddr_un sunaddr; sunaddr.sun_family = AF_UNIX;', define='HAVE_UNIXSOCKET', headers='sys/socket.h sys/un.h') conf.CHECK_CODE(''' struct stat st; char tpl[20]="/tmp/test.XXXXXX"; char tpl2[20]="/tmp/test.XXXXXX"; int fd = mkstemp(tpl); int fd2 = mkstemp(tpl2); if (fd == -1) { if (fd2 != -1) { unlink(tpl2); } exit(1); } if (fd2 == -1) exit(1); unlink(tpl); unlink(tpl2); if (fstat(fd, &st) != 0) exit(1); if ((st.st_mode & 0777) != 0600) exit(1); if (strcmp(tpl, "/tmp/test.XXXXXX") == 0) { exit(1); } if (strcmp(tpl, tpl2) == 0) { exit(1); } exit(0); ''', define='HAVE_SECURE_MKSTEMP', execute=True, mandatory=True) # lets see if we get a mandatory failure for this one # look for a method of finding the list of network interfaces for method in ['HAVE_IFACE_GETIFADDRS', 'HAVE_IFACE_AIX', 'HAVE_IFACE_IFCONF', 'HAVE_IFACE_IFREQ']: bsd_for_strlcpy = '' if strlcpy_in_bsd: bsd_for_strlcpy = ' bsd' if conf.CHECK_CODE(''' #define %s 1 #define NO_CONFIG_H 1 #define AUTOCONF_TEST 1 #include "replace.c" #include "inet_ntop.c" #include "snprintf.c" #include "getifaddrs.c" #define getifaddrs_test main #include "tests/getifaddrs.c" ''' % method, method, lib='nsl socket' + bsd_for_strlcpy, addmain=False, execute=True): break conf.RECURSE('system') conf.SAMBA_CONFIG_H() if conf.CHECK_FUNCS('strerror_r'): # Check if strerror_r is XSI-Compatable, the default GNU implementation # is not conf.CHECK_CODE('int strerror_r(int errnum, char *buf, size_t buflen);', 'STRERROR_R_XSI_NOT_GNU', headers='string.h', addmain=False, link=False, msg="Checking for XSI (rather than GNU) prototype for strerror_r") REPLACEMENT_FUNCTIONS = { 'replace.c': ['ftruncate', 'strlcpy', 'strlcat', 'mktime', 'initgroups', 'memmove', 'strdup', 'setlinebuf', 'vsyslog', 'strnlen', 'strndup', 'waitpid', 'seteuid', 'setegid', 'chroot', 'mkstemp', 'mkdtemp', 'pread', 'pwrite', 'strcasestr', 'strsep', 'strtok_r', 'strtoll', 'strtoull', 'setenv', 'unsetenv', 'utime', 'utimes', 'dup2', 'chown', 'link', 'readlink', 'symlink', 'lchown', 'realpath', 'memmem', 'vdprintf', 'dprintf', 'get_current_dir_name', 'copy_file_range', 'strerror_r', 'clock_gettime', 'memset_s'], 'timegm.c': ['timegm'], # Note: C99_VSNPRINTF is not a function, but a special condition # for replacement 'snprintf.c': ['C99_VSNPRINTF', 'snprintf', 'vsnprintf', 'asprintf', 'vasprintf'], # Note: WORKING_STRPTIME is not a function, but a special condition # for replacement 'strptime.c': ['WORKING_STRPTIME', 'strptime'], } def build(bld): bld.RECURSE('buildtools/wafsamba') REPLACE_HOSTCC_SOURCE = '' for filename in REPLACEMENT_FUNCTIONS.keys(): for function in REPLACEMENT_FUNCTIONS[filename]: if not bld.CONFIG_SET('HAVE_%s' % function.upper()): REPLACE_HOSTCC_SOURCE += ' %s' % filename break extra_libs = '' if bld.CONFIG_SET('HAVE_LIBBSD'): extra_libs += ' bsd' if bld.CONFIG_SET('HAVE_LIBRT'): extra_libs += ' rt' if bld.CONFIG_SET('REPLACE_REQUIRES_LIBSOCKET_LIBNSL'): extra_libs += ' socket nsl' if not bld.CONFIG_SET('HAVE_CLOSEFROM'): REPLACE_HOSTCC_SOURCE += ' closefrom.c' bld.SAMBA_SUBSYSTEM('LIBREPLACE_HOSTCC', REPLACE_HOSTCC_SOURCE, use_hostcc=True, use_global_deps=False, group='hostcc_base_build_main', deps = extra_libs ) REPLACE_SOURCE = REPLACE_HOSTCC_SOURCE if not bld.CONFIG_SET('HAVE_DLOPEN'): REPLACE_SOURCE += ' dlfcn.c' if not bld.CONFIG_SET('HAVE_POLL'): REPLACE_SOURCE += ' poll.c' if not bld.CONFIG_SET('HAVE_SOCKETPAIR'): REPLACE_SOURCE += ' socketpair.c' if not bld.CONFIG_SET('HAVE_CONNECT'): REPLACE_SOURCE += ' socket.c' if not bld.CONFIG_SET('HAVE_GETIFADDRS'): REPLACE_SOURCE += ' getifaddrs.c' if not bld.CONFIG_SET('HAVE_GETADDRINFO'): REPLACE_SOURCE += ' getaddrinfo.c' if not bld.CONFIG_SET('HAVE_INET_NTOA'): REPLACE_SOURCE += ' inet_ntoa.c' if not bld.CONFIG_SET('HAVE_INET_ATON'): REPLACE_SOURCE += ' inet_aton.c' if not bld.CONFIG_SET('HAVE_INET_NTOP'): REPLACE_SOURCE += ' inet_ntop.c' if not bld.CONFIG_SET('HAVE_INET_PTON'): REPLACE_SOURCE += ' inet_pton.c' if not bld.CONFIG_SET('HAVE_GETXATTR') or bld.CONFIG_SET('XATTR_ADDITIONAL_OPTIONS'): REPLACE_SOURCE += ' xattr.c' if not bld.CONFIG_SET('HAVE_CLOSEFROM'): REPLACE_SOURCE += ' closefrom.c' bld.SAMBA_LIBRARY('replace', source=REPLACE_SOURCE, group='base_libraries', # FIXME: Ideally symbols should be hidden here so they # don't appear in the global namespace when Samba # libraries are loaded, but this doesn't appear to work # at the moment: # hide_symbols=bld.BUILTIN_LIBRARY('replace'), private_library=True, provide_builtin_linking=True, deps='dl attr' + extra_libs) replace_test_cflags = '' if bld.CONFIG_SET('HAVE_WNO_FORMAT_TRUNCATION'): replace_test_cflags += " -Wno-format-truncation" bld.SAMBA_SUBSYSTEM('replace-test', source='''tests/testsuite.c tests/strptime.c tests/os2_delete.c tests/getifaddrs.c''', deps='replace', cflags=replace_test_cflags) bld.SAMBA_BINARY('replace_testsuite', source='tests/main.c', deps='replace replace-test', install=False) # build replacements for stdint.h and stdbool.h if needed bld.SAMBA_GENERATOR('replace_stdint_h', rule='cp ${SRC} ${TGT}', source='hdr_replace.h', target='stdint.h', enabled = not bld.CONFIG_SET('HAVE_STDINT_H')) bld.SAMBA_GENERATOR('replace_stdbool_h', rule='cp ${SRC} ${TGT}', source='hdr_replace.h', target='stdbool.h', enabled = not bld.CONFIG_SET('HAVE_STDBOOL_H')) bld.SAMBA_SUBSYSTEM('samba_intl', source='', use_global_deps=False,deps=bld.env.intl_libs) def testonly(ctx): '''run talloc testsuite''' import samba_utils samba_utils.ADD_LD_LIBRARY_PATH('bin/shared') samba_utils.ADD_LD_LIBRARY_PATH('bin/shared/private') cmd = os.path.join(Context.g_module.out, 'replace_testsuite') ret = samba_utils.RUN_COMMAND(cmd) print("testsuite returned %d" % ret) sys.exit(ret) # WAF doesn't build the unit tests for this, maybe because they don't link with talloc? # This forces it def test(ctx): Options.commands.append('build') Options.commands.append('testonly') def dist(): '''makes a tarball for distribution''' samba_dist.dist()