diff options
Diffstat (limited to 'ctdb/lib/replace')
72 files changed, 15062 insertions, 0 deletions
diff --git a/ctdb/lib/replace/.checker_innocent b/ctdb/lib/replace/.checker_innocent new file mode 100644 index 0000000000..e619176540 --- /dev/null +++ b/ctdb/lib/replace/.checker_innocent @@ -0,0 +1,4 @@ +>>>MISTAKE21_create_files_6a9e68ada99a97cb +>>>MISTAKE21_os2_delete_9b2bfa7f38711d09 +>>>MISTAKE21_os2_delete_2fcc29aaa99a97cb +>>>SECURITY2_os2_delete_9b2bfa7f1c9396ca diff --git a/ctdb/lib/replace/Makefile b/ctdb/lib/replace/Makefile new file mode 100644 index 0000000000..364990153e --- /dev/null +++ b/ctdb/lib/replace/Makefile @@ -0,0 +1,63 @@ +# simple makefile wrapper to run waf + +WAF=WAF_MAKE=1 PATH=buildtools/bin:../../buildtools/bin:$$PATH waf + +all: + $(WAF) build + +install: + $(WAF) install + +uninstall: + $(WAF) uninstall + +test: + $(WAF) test $(TEST_OPTIONS) + +testenv: + $(WAF) test --testenv $(TEST_OPTIONS) + +quicktest: + $(WAF) test --quick $(TEST_OPTIONS) + +dist: + touch .tmplock + WAFLOCK=.tmplock $(WAF) dist + +distcheck: + touch .tmplock + WAFLOCK=.tmplock $(WAF) distcheck + +clean: + $(WAF) clean + +distclean: + $(WAF) distclean + +reconfigure: configure + $(WAF) reconfigure + +show_waf_options: + $(WAF) --help + +# some compatibility make targets +everything: all + +testsuite: all + +check: test + +torture: all + +# this should do an install as well, once install is finished +installcheck: test + +etags: + $(WAF) etags + +ctags: + $(WAF) ctags + +bin/%:: FORCE + $(WAF) --targets=`basename $@` +FORCE: diff --git a/ctdb/lib/replace/README b/ctdb/lib/replace/README new file mode 100644 index 0000000000..9dd4f7305f --- /dev/null +++ b/ctdb/lib/replace/README @@ -0,0 +1,127 @@ +This subsystem ensures that we can always use a certain core set of +functions and types, that are either provided by the OS or by replacement +functions / definitions in this subsystem. The aim is to try to stick +to POSIX functions in here as much as possible. Convenience functions +that are available on no platform at all belong in other subsystems +(such as LIBUTIL). + +The following functions are guaranteed: + +ftruncate +strlcpy +strlcat +mktime +rename +initgroups +memmove +strdup +setlinebuf +vsyslog +timegm +setenv +unsetenv +strndup +strnlen +waitpid +seteuid +setegid +asprintf +snprintf +vasprintf +vsnprintf +opendir +readdir +telldir +seekdir +clock_gettime +closedir +dlopen +dlclose +dlsym +dlerror +chroot +bzero +strerror +errno +mkdtemp +mkstemp (a secure one!) +pread +pwrite +chown +lchown +readline (the library) +inet_ntoa +inet_ntop +inet_pton +inet_aton +strtoll +strtoull +socketpair +strptime +getaddrinfo +freeaddrinfo +getnameinfo +gai_strerror +getifaddrs +freeifaddrs +utime +utimes +dup2 +link +readlink +symlink +realpath +poll +setproctitle + +Types: +bool +socklen_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t +sig_atomic_t +blksize_t +blkcnt_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +RTLD_LAZY +HOST_NAME_MAX +UINT16_MAX +UINT32_MAX +UINT64_MAX +CHAR_BIT + +Macros: +va_copy +__FUNCTION__ +__FILE__ +__LINE__ +__LINESTR__ +__location__ +__STRING +__STRINGSTRING +MIN +MAX +QSORT_CAST +ZERO_STRUCT +ZERO_STRUCTP +ZERO_STRUCTPN +ZERO_ARRAY +ARRAY_SIZE +PTR_DIFF + +Headers: +stdint.h +stdbool.h + +Optional C keywords: +volatile + +Prerequisites: +memset (for bzero) +syslog (for vsyslog) +mktemp (for mkstemp and mkdtemp) diff --git a/ctdb/lib/replace/autoconf-2.60.m4 b/ctdb/lib/replace/autoconf-2.60.m4 new file mode 100644 index 0000000000..b2694fde62 --- /dev/null +++ b/ctdb/lib/replace/autoconf-2.60.m4 @@ -0,0 +1,236 @@ +# AC_GNU_SOURCE +# -------------- +AC_DEFUN([AC_GNU_SOURCE], +[AH_VERBATIM([_GNU_SOURCE], +[/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif])dnl +AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl +AC_BEFORE([$0], [AC_RUN_IFELSE])dnl +AC_DEFINE([_GNU_SOURCE]) +]) + +# _AC_C_STD_TRY(STANDARD, TEST-PROLOGUE, TEST-BODY, OPTION-LIST, +# ACTION-IF-AVAILABLE, ACTION-IF-UNAVAILABLE) +# -------------------------------------------------------------- +# Check whether the C compiler accepts features of STANDARD (e.g `c89', `c99') +# by trying to compile a program of TEST-PROLOGUE and TEST-BODY. If this fails, +# try again with each compiler option in the space-separated OPTION-LIST; if one +# helps, append it to CC. If eventually successful, run ACTION-IF-AVAILABLE, +# else ACTION-IF-UNAVAILABLE. +AC_DEFUN([_AC_C_STD_TRY], +[AC_MSG_CHECKING([for $CC option to accept ISO ]m4_translit($1, [c], [C])) +AC_CACHE_VAL(ac_cv_prog_cc_$1, +[ac_cv_prog_cc_$1=no +ac_save_CC=$CC +AC_LANG_CONFTEST([AC_LANG_PROGRAM([$2], [$3])]) +for ac_arg in '' $4 +do + CC="$ac_save_CC $ac_arg" + _AC_COMPILE_IFELSE([], [ac_cv_prog_cc_$1=$ac_arg]) + test "x$ac_cv_prog_cc_$1" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC +])# AC_CACHE_VAL +case "x$ac_cv_prog_cc_$1" in + x) + AC_MSG_RESULT([none needed]) ;; + xno) + AC_MSG_RESULT([unsupported]) ;; + *) + CC="$CC $ac_cv_prog_cc_$1" + AC_MSG_RESULT([$ac_cv_prog_cc_$1]) ;; +esac +AS_IF([test "x$ac_cv_prog_cc_$1" != xno], [$5], [$6]) +])# _AC_C_STD_TRY + +# _AC_PROG_CC_C99 ([ACTION-IF-AVAILABLE], [ACTION-IF-UNAVAILABLE]) +# ---------------------------------------------------------------- +# If the C compiler is not in ISO C99 mode by default, try to add an +# option to output variable CC to make it so. This macro tries +# various options that select ISO C99 on some system or another. It +# considers the compiler to be in ISO C99 mode if it handles mixed +# code and declarations, _Bool, inline and restrict. +AC_DEFUN([_AC_PROG_CC_C99], +[_AC_C_STD_TRY([c99], +[[#include <stdarg.h> +#include <stdbool.h> +#include <stdlib.h> +#include <wchar.h> +#include <stdio.h> + +struct incomplete_array +{ + int datasize; + double data[]; +}; + +struct named_init { + int number; + const wchar_t *name; + double average; +}; + +typedef const char *ccp; + +static inline int +test_restrict(ccp restrict text) +{ + // See if C++-style comments work. + // Iterate through items via the restricted pointer. + // Also check for declarations in for loops. + for (unsigned int i = 0; *(text+i) != '\0'; ++i) + continue; + return 0; +} + +// Check varargs and va_copy work. +static void +test_varargs(const char *format, ...) +{ + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + + const char *str; + int number; + float fnumber; + + while (*format) + { + switch (*format++) + { + case 's': // string + str = va_arg(args_copy, const char *); + break; + case 'd': // int + number = va_arg(args_copy, int); + break; + case 'f': // float + fnumber = (float) va_arg(args_copy, double); + break; + default: + break; + } + } + va_end(args_copy); + va_end(args); +} +]], +[[ + // Check bool and long long datatypes. + _Bool success = false; + long long int bignum = -1234567890LL; + unsigned long long int ubignum = 1234567890uLL; + + // Check restrict. + if (test_restrict("String literal") != 0) + success = true; + char *restrict newvar = "Another string"; + + // Check varargs. + test_varargs("s, d' f .", "string", 65, 34.234); + + // Check incomplete arrays work. + struct incomplete_array *ia = + malloc(sizeof(struct incomplete_array) + (sizeof(double) * 10)); + ia->datasize = 10; + for (int i = 0; i < ia->datasize; ++i) + ia->data[i] = (double) i * 1.234; + + // Check named initialisers. + struct named_init ni = { + .number = 34, + .name = L"Test wide string", + .average = 543.34343, + }; + + ni.number = 58; + + int dynamic_array[ni.number]; + dynamic_array[43] = 543; + + // work around unused variable warnings + return bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'; +]], +dnl Try +dnl GCC -std=gnu99 (unused restrictive modes: -std=c99 -std=iso9899:1999) +dnl AIX -qlanglvl=extc99 (unused restrictive mode: -qlanglvl=stdc99) +dnl Intel ICC -c99 +dnl IRIX -c99 +dnl Solaris (unused because it causes the compiler to assume C99 semantics for +dnl library functions, and this is invalid before Solaris 10: -xc99) +dnl Tru64 -c99 +dnl with extended modes being tried first. +[[-std=gnu99 -c99 -qlanglvl=extc99]], [$1], [$2])[]dnl +])# _AC_PROG_CC_C99 + +# AC_PROG_CC_C99 +# -------------- +AC_DEFUN([AC_PROG_CC_C99], +[ AC_REQUIRE([AC_PROG_CC])dnl + _AC_PROG_CC_C99 +]) + +# AC_USE_SYSTEM_EXTENSIONS +# ------------------------ +# Enable extensions on systems that normally disable them, +# typically due to standards-conformance issues. +m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[ +AC_DEFUN([AC_USE_SYSTEM_EXTENSIONS], +[AC_BEFORE([$0], [AC_COMPILE_IFELSE])dnl +AC_BEFORE([$0], [AC_RUN_IFELSE])dnl + + AC_CHECK_HEADER([minix/config.h], [MINIX=yes], [MINIX=]) + if test "$MINIX" = yes; then + AC_DEFINE([_POSIX_SOURCE], [1], + [Define to 1 if you need to in order for `stat' and other + things to work.]) + AC_DEFINE([_POSIX_1_SOURCE], [2], + [Define to 2 if the system does not provide POSIX.1 features + except with this defined.]) + AC_DEFINE([_MINIX], [1], + [Define to 1 if on MINIX.]) + fi + + AH_VERBATIM([__EXTENSIONS__], +[/* Enable extensions on AIX 3, Interix. */ +#ifndef _ALL_SOURCE +# undef _ALL_SOURCE +#endif +/* Enable GNU extensions on systems that have them. */ +#ifndef _GNU_SOURCE +# undef _GNU_SOURCE +#endif +/* Enable threading extensions on Solaris. */ +#ifndef _POSIX_PTHREAD_SEMANTICS +# undef _POSIX_PTHREAD_SEMANTICS +#endif +/* Enable extensions on HP NonStop. */ +#ifndef _TANDEM_SOURCE +# undef _TANDEM_SOURCE +#endif +/* Enable general extensions on Solaris. */ +#ifndef __EXTENSIONS__ +# undef __EXTENSIONS__ +#endif +]) + AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__], + [ac_cv_safe_to_define___extensions__], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[ +# define __EXTENSIONS__ 1 + ]AC_INCLUDES_DEFAULT])], + [ac_cv_safe_to_define___extensions__=yes], + [ac_cv_safe_to_define___extensions__=no])]) + test $ac_cv_safe_to_define___extensions__ = yes && + AC_DEFINE([__EXTENSIONS__]) + AC_DEFINE([_ALL_SOURCE]) + AC_DEFINE([_GNU_SOURCE]) + AC_DEFINE([_POSIX_PTHREAD_SEMANTICS]) + AC_DEFINE([_TANDEM_SOURCE]) +])# AC_USE_SYSTEM_EXTENSIONS +]) diff --git a/ctdb/lib/replace/configure b/ctdb/lib/replace/configure new file mode 100755 index 0000000000..6a9f875511 --- /dev/null +++ b/ctdb/lib/replace/configure @@ -0,0 +1,21 @@ +#!/bin/sh + +PREVPATH=`dirname $0` + +if [ -f $PREVPATH/../../buildtools/bin/waf ]; then + WAF=../../buildtools/bin/waf +elif [ -f $PREVPATH/buildtools/bin/waf ]; then + WAF=./buildtools/bin/waf +else + echo "replace: Unable to find waf" + exit 1 +fi + +# using JOBS=1 gives maximum compatibility with +# systems like AIX which have broken threading in python +JOBS=1 +export JOBS + +cd . || exit 1 +$WAF configure "$@" || exit 1 +cd $PREVPATH diff --git a/ctdb/lib/replace/crypt.c b/ctdb/lib/replace/crypt.c new file mode 100644 index 0000000000..3a067bcc77 --- /dev/null +++ b/ctdb/lib/replace/crypt.c @@ -0,0 +1,770 @@ +/* + This bit of code was derived from the UFC-crypt package which + carries the following copyright + + Modified for use by Samba by Andrew Tridgell, October 1994 + + Note that this routine is only faster on some machines. Under Linux 1.1.51 + libc 4.5.26 I actually found this routine to be slightly slower. + + Under SunOS I found a huge speedup by using these routines + (a factor of 20 or so) + + Warning: I've had a report from Steve Kennedy <steve@gbnet.org> + that this crypt routine may sometimes get the wrong answer. Only + use UFC_CRYT if you really need it. + +*/ + +#include "replace.h" + +#ifndef HAVE_CRYPT + +/* + * UFC-crypt: ultra fast crypt(3) implementation + * + * Copyright (C) 1991-1998, Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + * + * @(#)crypt_util.c 2.31 02/08/92 + * + * Support routines + * + */ + + +#ifndef long32 +#define long32 int32_t +#endif + +#ifndef long64 +#define long64 int64_t +#endif + +#ifndef ufc_long +#define ufc_long unsigned +#endif + +#ifndef _UFC_64_ +#define _UFC_32_ +#endif + +/* + * Permutation done once on the 56 bit + * key derived from the original 8 byte ASCII key. + */ +static int pc1[56] = { + 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4 +}; + +/* + * How much to rotate each 28 bit half of the pc1 permutated + * 56 bit key before using pc2 to give the i' key + */ +static int rots[16] = { + 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1 +}; + +/* + * Permutation giving the key + * of the i' DES round + */ +static int pc2[48] = { + 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32 +}; + +/* + * The E expansion table which selects + * bits from the 32 bit intermediate result. + */ +static int esel[48] = { + 32, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, 28, 29, 30, 31, 32, 1 +}; +static int e_inverse[64]; + +/* + * Permutation done on the + * result of sbox lookups + */ +static int perm32[32] = { + 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10, + 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25 +}; + +/* + * The sboxes + */ +static int sbox[8][4][16]= { + { { 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7 }, + { 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8 }, + { 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0 }, + { 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 } + }, + + { { 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10 }, + { 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5 }, + { 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15 }, + { 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 } + }, + + { { 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8 }, + { 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1 }, + { 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7 }, + { 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 } + }, + + { { 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15 }, + { 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9 }, + { 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4 }, + { 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 } + }, + + { { 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9 }, + { 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6 }, + { 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14 }, + { 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 } + }, + + { { 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11 }, + { 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8 }, + { 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6 }, + { 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 } + }, + + { { 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1 }, + { 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6 }, + { 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2 }, + { 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 } + }, + + { { 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7 }, + { 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2 }, + { 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8 }, + { 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 } + } +}; + +/* + * This is the final + * permutation matrix + */ +static int final_perm[64] = { + 40, 8, 48, 16, 56, 24, 64, 32, 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, 33, 1, 41, 9, 49, 17, 57, 25 +}; + +/* + * The 16 DES keys in BITMASK format + */ +#ifdef _UFC_32_ +long32 _ufc_keytab[16][2]; +#endif + +#ifdef _UFC_64_ +long64 _ufc_keytab[16]; +#endif + + +#define ascii_to_bin(c) ((c)>='a'?(c-59):(c)>='A'?((c)-53):(c)-'.') +#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') + +/* Macro to set a bit (0..23) */ +#define BITMASK(i) ( (1<<(11-(i)%12+3)) << ((i)<12?16:0) ) + +/* + * sb arrays: + * + * Workhorses of the inner loop of the DES implementation. + * They do sbox lookup, shifting of this value, 32 bit + * permutation and E permutation for the next round. + * + * Kept in 'BITMASK' format. + */ + +#ifdef _UFC_32_ +long32 _ufc_sb0[8192], _ufc_sb1[8192], _ufc_sb2[8192], _ufc_sb3[8192]; +static long32 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; +#endif + +#ifdef _UFC_64_ +long64 _ufc_sb0[4096], _ufc_sb1[4096], _ufc_sb2[4096], _ufc_sb3[4096]; +static long64 *sb[4] = {_ufc_sb0, _ufc_sb1, _ufc_sb2, _ufc_sb3}; +#endif + +/* + * eperm32tab: do 32 bit permutation and E selection + * + * The first index is the byte number in the 32 bit value to be permuted + * - second - is the value of this byte + * - third - selects the two 32 bit values + * + * The table is used and generated internally in init_des to speed it up + */ +static ufc_long eperm32tab[4][256][2]; + +/* + * do_pc1: permform pc1 permutation in the key schedule generation. + * + * The first index is the byte number in the 8 byte ASCII key + * - second - - the two 28 bits halfs of the result + * - third - selects the 7 bits actually used of each byte + * + * The result is kept with 28 bit per 32 bit with the 4 most significant + * bits zero. + */ +static ufc_long do_pc1[8][2][128]; + +/* + * do_pc2: permform pc2 permutation in the key schedule generation. + * + * The first index is the septet number in the two 28 bit intermediate values + * - second - - - septet values + * + * Knowledge of the structure of the pc2 permutation is used. + * + * The result is kept with 28 bit per 32 bit with the 4 most significant + * bits zero. + */ +static ufc_long do_pc2[8][128]; + +/* + * efp: undo an extra e selection and do final + * permutation giving the DES result. + * + * Invoked 6 bit a time on two 48 bit values + * giving two 32 bit longs. + */ +static ufc_long efp[16][64][2]; + +static unsigned char bytemask[8] = { + 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 +}; + +static ufc_long longmask[32] = { + 0x80000000, 0x40000000, 0x20000000, 0x10000000, + 0x08000000, 0x04000000, 0x02000000, 0x01000000, + 0x00800000, 0x00400000, 0x00200000, 0x00100000, + 0x00080000, 0x00040000, 0x00020000, 0x00010000, + 0x00008000, 0x00004000, 0x00002000, 0x00001000, + 0x00000800, 0x00000400, 0x00000200, 0x00000100, + 0x00000080, 0x00000040, 0x00000020, 0x00000010, + 0x00000008, 0x00000004, 0x00000002, 0x00000001 +}; + + +/* + * Silly rewrite of 'bzero'. I do so + * because some machines don't have + * bzero and some don't have memset. + */ + +static void clearmem(char *start, int cnt) + { while(cnt--) + *start++ = '\0'; + } + +static int initialized = 0; + +/* lookup a 6 bit value in sbox */ + +#define s_lookup(i,s) sbox[(i)][(((s)>>4) & 0x2)|((s) & 0x1)][((s)>>1) & 0xf]; + +/* + * Initialize unit - may be invoked directly + * by fcrypt users. + */ + +static void ufc_init_des(void) + { int comes_from_bit; + int bit, sg; + ufc_long j; + ufc_long mask1, mask2; + + /* + * Create the do_pc1 table used + * to affect pc1 permutation + * when generating keys + */ + for(bit = 0; bit < 56; bit++) { + comes_from_bit = pc1[bit] - 1; + mask1 = bytemask[comes_from_bit % 8 + 1]; + mask2 = longmask[bit % 28 + 4]; + for(j = 0; j < 128; j++) { + if(j & mask1) + do_pc1[comes_from_bit / 8][bit / 28][j] |= mask2; + } + } + + /* + * Create the do_pc2 table used + * to affect pc2 permutation when + * generating keys + */ + for(bit = 0; bit < 48; bit++) { + comes_from_bit = pc2[bit] - 1; + mask1 = bytemask[comes_from_bit % 7 + 1]; + mask2 = BITMASK(bit % 24); + for(j = 0; j < 128; j++) { + if(j & mask1) + do_pc2[comes_from_bit / 7][j] |= mask2; + } + } + + /* + * Now generate the table used to do combined + * 32 bit permutation and e expansion + * + * We use it because we have to permute 16384 32 bit + * longs into 48 bit in order to initialize sb. + * + * Looping 48 rounds per permutation becomes + * just too slow... + * + */ + + clearmem((char*)eperm32tab, sizeof(eperm32tab)); + + for(bit = 0; bit < 48; bit++) { + ufc_long inner_mask1,comes_from; + + comes_from = perm32[esel[bit]-1]-1; + inner_mask1 = bytemask[comes_from % 8]; + + for(j = 256; j--;) { + if(j & inner_mask1) + eperm32tab[comes_from / 8][j][bit / 24] |= BITMASK(bit % 24); + } + } + + /* + * Create the sb tables: + * + * For each 12 bit segment of an 48 bit intermediate + * result, the sb table precomputes the two 4 bit + * values of the sbox lookups done with the two 6 + * bit halves, shifts them to their proper place, + * sends them through perm32 and finally E expands + * them so that they are ready for the next + * DES round. + * + */ + for(sg = 0; sg < 4; sg++) { + int j1, j2; + int s1, s2; + + for(j1 = 0; j1 < 64; j1++) { + s1 = s_lookup(2 * sg, j1); + for(j2 = 0; j2 < 64; j2++) { + ufc_long to_permute, inx; + + s2 = s_lookup(2 * sg + 1, j2); + to_permute = ((s1 << 4) | s2) << (24 - 8 * sg); + +#ifdef _UFC_32_ + inx = ((j1 << 6) | j2) << 1; + sb[sg][inx ] = eperm32tab[0][(to_permute >> 24) & 0xff][0]; + sb[sg][inx+1] = eperm32tab[0][(to_permute >> 24) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[1][(to_permute >> 16) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[1][(to_permute >> 16) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[2][(to_permute >> 8) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[2][(to_permute >> 8) & 0xff][1]; + sb[sg][inx ] |= eperm32tab[3][(to_permute) & 0xff][0]; + sb[sg][inx+1] |= eperm32tab[3][(to_permute) & 0xff][1]; +#endif +#ifdef _UFC_64_ + inx = ((j1 << 6) | j2); + sb[sg][inx] = + ((long64)eperm32tab[0][(to_permute >> 24) & 0xff][0] << 32) | + (long64)eperm32tab[0][(to_permute >> 24) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[1][(to_permute >> 16) & 0xff][0] << 32) | + (long64)eperm32tab[1][(to_permute >> 16) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[2][(to_permute >> 8) & 0xff][0] << 32) | + (long64)eperm32tab[2][(to_permute >> 8) & 0xff][1]; + sb[sg][inx] |= + ((long64)eperm32tab[3][(to_permute) & 0xff][0] << 32) | + (long64)eperm32tab[3][(to_permute) & 0xff][1]; +#endif + } + } + } + + /* + * Create an inverse matrix for esel telling + * where to plug out bits if undoing it + */ + for(bit=48; bit--;) { + e_inverse[esel[bit] - 1 ] = bit; + e_inverse[esel[bit] - 1 + 32] = bit + 48; + } + + /* + * create efp: the matrix used to + * undo the E expansion and effect final permutation + */ + clearmem((char*)efp, sizeof efp); + for(bit = 0; bit < 64; bit++) { + int o_bit, o_long; + ufc_long word_value, inner_mask1, inner_mask2; + int comes_from_f_bit, comes_from_e_bit; + int comes_from_word, bit_within_word; + + /* See where bit i belongs in the two 32 bit long's */ + o_long = bit / 32; /* 0..1 */ + o_bit = bit % 32; /* 0..31 */ + + /* + * And find a bit in the e permutated value setting this bit. + * + * Note: the e selection may have selected the same bit several + * times. By the initialization of e_inverse, we only look + * for one specific instance. + */ + comes_from_f_bit = final_perm[bit] - 1; /* 0..63 */ + comes_from_e_bit = e_inverse[comes_from_f_bit]; /* 0..95 */ + comes_from_word = comes_from_e_bit / 6; /* 0..15 */ + bit_within_word = comes_from_e_bit % 6; /* 0..5 */ + + inner_mask1 = longmask[bit_within_word + 26]; + inner_mask2 = longmask[o_bit]; + + for(word_value = 64; word_value--;) { + if(word_value & inner_mask1) + efp[comes_from_word][word_value][o_long] |= inner_mask2; + } + } + initialized++; + } + +/* + * Process the elements of the sb table permuting the + * bits swapped in the expansion by the current salt. + */ + +#ifdef _UFC_32_ +static void shuffle_sb(long32 *k, ufc_long saltbits) + { ufc_long j; + long32 x; + for(j=4096; j--;) { + x = (k[0] ^ k[1]) & (long32)saltbits; + *k++ ^= x; + *k++ ^= x; + } + } +#endif + +#ifdef _UFC_64_ +static void shuffle_sb(long64 *k, ufc_long saltbits) + { ufc_long j; + long64 x; + for(j=4096; j--;) { + x = ((*k >> 32) ^ *k) & (long64)saltbits; + *k++ ^= (x << 32) | x; + } + } +#endif + +/* + * Setup the unit for a new salt + * Hopefully we'll not see a new salt in each crypt call. + */ + +static unsigned char current_salt[3] = "&&"; /* invalid value */ +static ufc_long current_saltbits = 0; +static int direction = 0; + +static void setup_salt(const char *s1) + { ufc_long i, j, saltbits; + const unsigned char *s2 = (const unsigned char *)s1; + + if(!initialized) + ufc_init_des(); + + if(s2[0] == current_salt[0] && s2[1] == current_salt[1]) + return; + current_salt[0] = s2[0]; current_salt[1] = s2[1]; + + /* + * This is the only crypt change to DES: + * entries are swapped in the expansion table + * according to the bits set in the salt. + */ + saltbits = 0; + for(i = 0; i < 2; i++) { + long c=ascii_to_bin(s2[i]); + if(c < 0 || c > 63) + c = 0; + for(j = 0; j < 6; j++) { + if((c >> j) & 0x1) + saltbits |= BITMASK(6 * i + j); + } + } + + /* + * Permute the sb table values + * to reflect the changed e + * selection table + */ + shuffle_sb(_ufc_sb0, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb1, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb2, current_saltbits ^ saltbits); + shuffle_sb(_ufc_sb3, current_saltbits ^ saltbits); + + current_saltbits = saltbits; + } + +static void ufc_mk_keytab(char *key) + { ufc_long v1, v2, *k1; + int i; +#ifdef _UFC_32_ + long32 v, *k2 = &_ufc_keytab[0][0]; +#endif +#ifdef _UFC_64_ + long64 v, *k2 = &_ufc_keytab[0]; +#endif + + v1 = v2 = 0; k1 = &do_pc1[0][0][0]; + for(i = 8; i--;) { + v1 |= k1[*key & 0x7f]; k1 += 128; + v2 |= k1[*key++ & 0x7f]; k1 += 128; + } + + for(i = 0; i < 16; i++) { + k1 = &do_pc2[0][0]; + + v1 = (v1 << rots[i]) | (v1 >> (28 - rots[i])); + v = k1[(v1 >> 21) & 0x7f]; k1 += 128; + v |= k1[(v1 >> 14) & 0x7f]; k1 += 128; + v |= k1[(v1 >> 7) & 0x7f]; k1 += 128; + v |= k1[(v1 ) & 0x7f]; k1 += 128; + +#ifdef _UFC_32_ + *k2++ = v; + v = 0; +#endif +#ifdef _UFC_64_ + v <<= 32; +#endif + + v2 = (v2 << rots[i]) | (v2 >> (28 - rots[i])); + v |= k1[(v2 >> 21) & 0x7f]; k1 += 128; + v |= k1[(v2 >> 14) & 0x7f]; k1 += 128; + v |= k1[(v2 >> 7) & 0x7f]; k1 += 128; + v |= k1[(v2 ) & 0x7f]; + + *k2++ = v; + } + + direction = 0; + } + +/* + * Undo an extra E selection and do final permutations + */ + +ufc_long *_ufc_dofinalperm(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2) + { ufc_long v1, v2, x; + static ufc_long ary[2]; + + x = (l1 ^ l2) & current_saltbits; l1 ^= x; l2 ^= x; + x = (r1 ^ r2) & current_saltbits; r1 ^= x; r2 ^= x; + + v1=v2=0; l1 >>= 3; l2 >>= 3; r1 >>= 3; r2 >>= 3; + + v1 |= efp[15][ r2 & 0x3f][0]; v2 |= efp[15][ r2 & 0x3f][1]; + v1 |= efp[14][(r2 >>= 6) & 0x3f][0]; v2 |= efp[14][ r2 & 0x3f][1]; + v1 |= efp[13][(r2 >>= 10) & 0x3f][0]; v2 |= efp[13][ r2 & 0x3f][1]; + v1 |= efp[12][(r2 >>= 6) & 0x3f][0]; v2 |= efp[12][ r2 & 0x3f][1]; + + v1 |= efp[11][ r1 & 0x3f][0]; v2 |= efp[11][ r1 & 0x3f][1]; + v1 |= efp[10][(r1 >>= 6) & 0x3f][0]; v2 |= efp[10][ r1 & 0x3f][1]; + v1 |= efp[ 9][(r1 >>= 10) & 0x3f][0]; v2 |= efp[ 9][ r1 & 0x3f][1]; + v1 |= efp[ 8][(r1 >>= 6) & 0x3f][0]; v2 |= efp[ 8][ r1 & 0x3f][1]; + + v1 |= efp[ 7][ l2 & 0x3f][0]; v2 |= efp[ 7][ l2 & 0x3f][1]; + v1 |= efp[ 6][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 6][ l2 & 0x3f][1]; + v1 |= efp[ 5][(l2 >>= 10) & 0x3f][0]; v2 |= efp[ 5][ l2 & 0x3f][1]; + v1 |= efp[ 4][(l2 >>= 6) & 0x3f][0]; v2 |= efp[ 4][ l2 & 0x3f][1]; + + v1 |= efp[ 3][ l1 & 0x3f][0]; v2 |= efp[ 3][ l1 & 0x3f][1]; + v1 |= efp[ 2][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 2][ l1 & 0x3f][1]; + v1 |= efp[ 1][(l1 >>= 10) & 0x3f][0]; v2 |= efp[ 1][ l1 & 0x3f][1]; + v1 |= efp[ 0][(l1 >>= 6) & 0x3f][0]; v2 |= efp[ 0][ l1 & 0x3f][1]; + + ary[0] = v1; ary[1] = v2; + return ary; + } + +/* + * crypt only: convert from 64 bit to 11 bit ASCII + * prefixing with the salt + */ + +static char *output_conversion(ufc_long v1, ufc_long v2, const char *salt) + { static char outbuf[14]; + int i, s; + + outbuf[0] = salt[0]; + outbuf[1] = salt[1] ? salt[1] : salt[0]; + + for(i = 0; i < 5; i++) + outbuf[i + 2] = bin_to_ascii((v1 >> (26 - 6 * i)) & 0x3f); + + s = (v2 & 0xf) << 2; + v2 = (v2 >> 2) | ((v1 & 0x3) << 30); + + for(i = 5; i < 10; i++) + outbuf[i + 2] = bin_to_ascii((v2 >> (56 - 6 * i)) & 0x3f); + + outbuf[12] = bin_to_ascii(s); + outbuf[13] = 0; + + return outbuf; + } + +/* + * UNIX crypt function + */ + +static ufc_long *_ufc_doit(ufc_long , ufc_long, ufc_long, ufc_long, ufc_long); + +char *ufc_crypt(const char *key,const char *salt) + { ufc_long *s; + char ktab[9]; + + /* + * Hack DES tables according to salt + */ + setup_salt(salt); + + /* + * Setup key schedule + */ + clearmem(ktab, sizeof ktab); + strncpy(ktab, key, 8); + ufc_mk_keytab(ktab); + + /* + * Go for the 25 DES encryptions + */ + s = _ufc_doit((ufc_long)0, (ufc_long)0, + (ufc_long)0, (ufc_long)0, (ufc_long)25); + + /* + * And convert back to 6 bit ASCII + */ + return output_conversion(s[0], s[1], salt); + } + + +#ifdef _UFC_32_ + +/* + * 32 bit version + */ + +extern long32 _ufc_keytab[16][2]; +extern long32 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; + +#define SBA(sb, v) (*(long32*)((char*)(sb)+(v))) + +static ufc_long *_ufc_doit(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2, ufc_long itr) + { int i; + long32 s, *k; + + while(itr--) { + k = &_ufc_keytab[0][0]; + for(i=8; i--; ) { + s = *k++ ^ r1; + l1 ^= SBA(_ufc_sb1, s & 0xffff); l2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); + l1 ^= SBA(_ufc_sb0, s >>= 16); l2 ^= SBA(_ufc_sb0, (s) +4); + s = *k++ ^ r2; + l1 ^= SBA(_ufc_sb3, s & 0xffff); l2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); + l1 ^= SBA(_ufc_sb2, s >>= 16); l2 ^= SBA(_ufc_sb2, (s) +4); + + s = *k++ ^ l1; + r1 ^= SBA(_ufc_sb1, s & 0xffff); r2 ^= SBA(_ufc_sb1, (s & 0xffff)+4); + r1 ^= SBA(_ufc_sb0, s >>= 16); r2 ^= SBA(_ufc_sb0, (s) +4); + s = *k++ ^ l2; + r1 ^= SBA(_ufc_sb3, s & 0xffff); r2 ^= SBA(_ufc_sb3, (s & 0xffff)+4); + r1 ^= SBA(_ufc_sb2, s >>= 16); r2 ^= SBA(_ufc_sb2, (s) +4); + } + s=l1; l1=r1; r1=s; s=l2; l2=r2; r2=s; + } + return _ufc_dofinalperm(l1, l2, r1, r2); + } + +#endif + +#ifdef _UFC_64_ + +/* + * 64 bit version + */ + +extern long64 _ufc_keytab[16]; +extern long64 _ufc_sb0[], _ufc_sb1[], _ufc_sb2[], _ufc_sb3[]; + +#define SBA(sb, v) (*(long64*)((char*)(sb)+(v))) + +static ufc_long *_ufc_doit(ufc_long l1, ufc_long l2, ufc_long r1, ufc_long r2, ufc_long itr) + { int i; + long64 l, r, s, *k; + + l = (((long64)l1) << 32) | ((long64)l2); + r = (((long64)r1) << 32) | ((long64)r2); + + while(itr--) { + k = &_ufc_keytab[0]; + for(i=8; i--; ) { + s = *k++ ^ r; + l ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); + l ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); + l ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); + l ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); + + s = *k++ ^ l; + r ^= SBA(_ufc_sb3, (s >> 0) & 0xffff); + r ^= SBA(_ufc_sb2, (s >> 16) & 0xffff); + r ^= SBA(_ufc_sb1, (s >> 32) & 0xffff); + r ^= SBA(_ufc_sb0, (s >> 48) & 0xffff); + } + s=l; l=r; r=s; + } + + l1 = l >> 32; l2 = l & 0xffffffff; + r1 = r >> 32; r2 = r & 0xffffffff; + return _ufc_dofinalperm(l1, l2, r1, r2); + } + +#endif + + +#else + int ufc_dummy_procedure(void); + int ufc_dummy_procedure(void) {return 0;} +#endif diff --git a/ctdb/lib/replace/crypt.m4 b/ctdb/lib/replace/crypt.m4 new file mode 100644 index 0000000000..fae2a58685 --- /dev/null +++ b/ctdb/lib/replace/crypt.m4 @@ -0,0 +1,6 @@ +############################################### +# test for where we get crypt() from +AC_CHECK_HEADERS(crypt.h) +AC_SEARCH_LIBS_EXT(crypt, [crypt], CRYPT_LIBS, + [ AC_DEFINE(HAVE_CRYPT,1,[Whether the system has the crypt() function]) ], + [ LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/crypt.o" ]) diff --git a/ctdb/lib/replace/dlfcn.c b/ctdb/lib/replace/dlfcn.c new file mode 100644 index 0000000000..88431ed576 --- /dev/null +++ b/ctdb/lib/replace/dlfcn.c @@ -0,0 +1,76 @@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2002 + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#ifdef HAVE_DL_H +#include <dl.h> +#endif + +#ifndef HAVE_DLOPEN +#ifdef DLOPEN_TAKES_UNSIGNED_FLAGS +void *rep_dlopen(const char *name, unsigned int flags) +#else +void *rep_dlopen(const char *name, int flags) +#endif +{ +#ifdef HAVE_SHL_LOAD + if (name == NULL) + return PROG_HANDLE; + return (void *)shl_load(name, flags, 0); +#else + return NULL; +#endif +} +#endif + +#ifndef HAVE_DLSYM +void *rep_dlsym(void *handle, const char *symbol) +{ +#ifdef HAVE_SHL_FINDSYM + void *sym_addr; + if (!shl_findsym((shl_t *)&handle, symbol, TYPE_UNDEFINED, &sym_addr)) + return sym_addr; +#endif + return NULL; +} +#endif + +#ifndef HAVE_DLERROR +char *rep_dlerror(void) +{ + return "dynamic loading of objects not supported on this platform"; +} +#endif + +#ifndef HAVE_DLCLOSE +int rep_dlclose(void *handle) +{ +#ifdef HAVE_SHL_CLOSE + return shl_unload((shl_t)handle); +#else + return 0; +#endif +} +#endif diff --git a/ctdb/lib/replace/dlfcn.m4 b/ctdb/lib/replace/dlfcn.m4 new file mode 100644 index 0000000000..722e0246b7 --- /dev/null +++ b/ctdb/lib/replace/dlfcn.m4 @@ -0,0 +1,31 @@ +dnl dummies provided by dlfcn.c if not available +save_LIBS="$LIBS" +LIBS="" + +libreplace_cv_dlfcn=no +AC_SEARCH_LIBS(dlopen, dl) + +AC_CHECK_HEADERS(dlfcn.h) +AC_CHECK_FUNCS([dlopen dlsym dlerror dlclose],[],[libreplace_cv_dlfcn=yes]) + +libreplace_cv_shl=no +AC_SEARCH_LIBS(shl_load, sl) +AC_CHECK_HEADERS(dl.h) +AC_CHECK_FUNCS([shl_load shl_unload shl_findsym],[],[libreplace_cv_shl=yes]) + +AC_VERIFY_C_PROTOTYPE([void *dlopen(const char* filename, unsigned int flags)], + [ + return 0; + ],[ + AC_DEFINE(DLOPEN_TAKES_UNSIGNED_FLAGS, 1, [Whether dlopen takes unsigned int flags]) + ],[],[ + #include <dlfcn.h> + ]) + +if test x"${libreplace_cv_dlfcn}" = x"yes";then + LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/dlfcn.o" +fi + +LIBDL="$LIBS" +AC_SUBST(LIBDL) +LIBS="$save_LIBS" diff --git a/ctdb/lib/replace/getaddrinfo.c b/ctdb/lib/replace/getaddrinfo.c new file mode 100644 index 0000000000..c5cd52be93 --- /dev/null +++ b/ctdb/lib/replace/getaddrinfo.c @@ -0,0 +1,497 @@ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this paragraph +and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, +EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +*/ + +/*------------------------------------------------------------------------- + * + * getaddrinfo.c + * Support getaddrinfo() on platforms that don't have it. + * + * We also supply getnameinfo() here, assuming that the platform will have + * it if and only if it has getaddrinfo(). If this proves false on some + * platform, we'll need to split this file and provide a separate configure + * test for getnameinfo(). + * + * Copyright (c) 2003-2007, PostgreSQL Global Development Group + * + * Copyright (C) 2007 Jeremy Allison. + * Modified to return multiple IPv4 addresses for Samba. + * + *------------------------------------------------------------------------- + */ + +#include "replace.h" +#include "system/network.h" + +#ifndef SMB_MALLOC +#define SMB_MALLOC(s) malloc(s) +#endif + +#ifndef SMB_STRDUP +#define SMB_STRDUP(s) strdup(s) +#endif + +static int check_hostent_err(struct hostent *hp) +{ + if (!hp) { + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + return EAI_NONAME; + case TRY_AGAIN: + return EAI_AGAIN; + case NO_RECOVERY: + default: + return EAI_FAIL; + } + } + if (!hp->h_name || hp->h_addrtype != AF_INET) { + return EAI_FAIL; + } + return 0; +} + +static char *canon_name_from_hostent(struct hostent *hp, + int *perr) +{ + char *ret = NULL; + + *perr = check_hostent_err(hp); + if (*perr) { + return NULL; + } + ret = SMB_STRDUP(hp->h_name); + if (!ret) { + *perr = EAI_MEMORY; + } + return ret; +} + +static char *get_my_canon_name(int *perr) +{ + char name[HOST_NAME_MAX+1]; + + if (gethostname(name, HOST_NAME_MAX) == -1) { + *perr = EAI_FAIL; + return NULL; + } + /* Ensure null termination. */ + name[HOST_NAME_MAX] = '\0'; + return canon_name_from_hostent(gethostbyname(name), perr); +} + +static char *get_canon_name_from_addr(struct in_addr ip, + int *perr) +{ + return canon_name_from_hostent( + gethostbyaddr(&ip, sizeof(ip), AF_INET), + perr); +} + +static struct addrinfo *alloc_entry(const struct addrinfo *hints, + struct in_addr ip, + unsigned short port) +{ + struct sockaddr_in *psin = NULL; + struct addrinfo *ai = SMB_MALLOC(sizeof(*ai)); + + if (!ai) { + return NULL; + } + memset(ai, '\0', sizeof(*ai)); + + psin = SMB_MALLOC(sizeof(*psin)); + if (!psin) { + free(ai); + return NULL; + } + + memset(psin, '\0', sizeof(*psin)); + + psin->sin_family = AF_INET; + psin->sin_port = htons(port); + psin->sin_addr = ip; + + ai->ai_flags = 0; + ai->ai_family = AF_INET; + ai->ai_socktype = hints->ai_socktype; + ai->ai_protocol = hints->ai_protocol; + ai->ai_addrlen = sizeof(*psin); + ai->ai_addr = (struct sockaddr *) psin; + ai->ai_canonname = NULL; + ai->ai_next = NULL; + + return ai; +} + +/* + * get address info for a single ipv4 address. + * + * Bugs: - servname can only be a number, not text. + */ + +static int getaddr_info_single_addr(const char *service, + uint32_t addr, + const struct addrinfo *hints, + struct addrinfo **res) +{ + + struct addrinfo *ai = NULL; + struct in_addr ip; + unsigned short port = 0; + + if (service) { + port = (unsigned short)atoi(service); + } + ip.s_addr = htonl(addr); + + ai = alloc_entry(hints, ip, port); + if (!ai) { + return EAI_MEMORY; + } + + /* If we're asked for the canonical name, + * make sure it returns correctly. */ + if (!(hints->ai_flags & AI_NUMERICSERV) && + hints->ai_flags & AI_CANONNAME) { + int err; + if (addr == INADDR_LOOPBACK || addr == INADDR_ANY) { + ai->ai_canonname = get_my_canon_name(&err); + } else { + ai->ai_canonname = + get_canon_name_from_addr(ip,&err); + } + if (ai->ai_canonname == NULL) { + freeaddrinfo(ai); + return err; + } + } + + *res = ai; + return 0; +} + +/* + * get address info for multiple ipv4 addresses. + * + * Bugs: - servname can only be a number, not text. + */ + +static int getaddr_info_name(const char *node, + const char *service, + const struct addrinfo *hints, + struct addrinfo **res) +{ + struct addrinfo *listp = NULL, *prevp = NULL; + char **pptr = NULL; + int err; + struct hostent *hp = NULL; + unsigned short port = 0; + + if (service) { + port = (unsigned short)atoi(service); + } + + hp = gethostbyname(node); + err = check_hostent_err(hp); + if (err) { + return err; + } + + for(pptr = hp->h_addr_list; *pptr; pptr++) { + struct in_addr ip = *(struct in_addr *)*pptr; + struct addrinfo *ai = alloc_entry(hints, ip, port); + + if (!ai) { + freeaddrinfo(listp); + return EAI_MEMORY; + } + + if (!listp) { + listp = ai; + prevp = ai; + ai->ai_canonname = SMB_STRDUP(hp->h_name); + if (!ai->ai_canonname) { + freeaddrinfo(listp); + return EAI_MEMORY; + } + } else { + prevp->ai_next = ai; + prevp = ai; + } + } + *res = listp; + return 0; +} + +/* + * get address info for ipv4 sockets. + * + * Bugs: - servname can only be a number, not text. + */ + +int rep_getaddrinfo(const char *node, + const char *service, + const struct addrinfo * hintp, + struct addrinfo ** res) +{ + struct addrinfo hints; + + /* Setup the hints struct. */ + if (hintp == NULL) { + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_STREAM; + } else { + memcpy(&hints, hintp, sizeof(hints)); + } + + if (hints.ai_family != AF_INET && hints.ai_family != AF_UNSPEC) { + return EAI_FAMILY; + } + + if (hints.ai_socktype == 0) { + hints.ai_socktype = SOCK_STREAM; + } + + if (!node && !service) { + return EAI_NONAME; + } + + if (node) { + if (node[0] == '\0') { + return getaddr_info_single_addr(service, + INADDR_ANY, + &hints, + res); + } else if (hints.ai_flags & AI_NUMERICHOST) { + struct in_addr ip; + if (!inet_aton(node, &ip)) { + return EAI_FAIL; + } + return getaddr_info_single_addr(service, + ntohl(ip.s_addr), + &hints, + res); + } else { + return getaddr_info_name(node, + service, + &hints, + res); + } + } else if (hints.ai_flags & AI_PASSIVE) { + return getaddr_info_single_addr(service, + INADDR_ANY, + &hints, + res); + } + return getaddr_info_single_addr(service, + INADDR_LOOPBACK, + &hints, + res); +} + + +void rep_freeaddrinfo(struct addrinfo *res) +{ + struct addrinfo *next = NULL; + + for (;res; res = next) { + next = res->ai_next; + if (res->ai_canonname) { + free(res->ai_canonname); + } + if (res->ai_addr) { + free(res->ai_addr); + } + free(res); + } +} + + +const char *rep_gai_strerror(int errcode) +{ +#ifdef HAVE_HSTRERROR + int hcode; + + switch (errcode) + { + case EAI_NONAME: + hcode = HOST_NOT_FOUND; + break; + case EAI_AGAIN: + hcode = TRY_AGAIN; + break; + case EAI_FAIL: + default: + hcode = NO_RECOVERY; + break; + } + + return hstrerror(hcode); +#else /* !HAVE_HSTRERROR */ + + switch (errcode) + { + case EAI_NONAME: + return "Unknown host"; + case EAI_AGAIN: + return "Host name lookup failure"; +#ifdef EAI_BADFLAGS + case EAI_BADFLAGS: + return "Invalid argument"; +#endif +#ifdef EAI_FAMILY + case EAI_FAMILY: + return "Address family not supported"; +#endif +#ifdef EAI_MEMORY + case EAI_MEMORY: + return "Not enough memory"; +#endif +#ifdef EAI_NODATA + case EAI_NODATA: + return "No host data of that type was found"; +#endif +#ifdef EAI_SERVICE + case EAI_SERVICE: + return "Class type not found"; +#endif +#ifdef EAI_SOCKTYPE + case EAI_SOCKTYPE: + return "Socket type not supported"; +#endif + default: + return "Unknown server error"; + } +#endif /* HAVE_HSTRERROR */ +} + +static int gethostnameinfo(const struct sockaddr *sa, + char *node, + size_t nodelen, + int flags) +{ + int ret = -1; + char *p = NULL; + + if (!(flags & NI_NUMERICHOST)) { + struct hostent *hp = gethostbyaddr( + &((struct sockaddr_in *)sa)->sin_addr, + sizeof(struct in_addr), + sa->sa_family); + ret = check_hostent_err(hp); + if (ret == 0) { + /* Name looked up successfully. */ + ret = snprintf(node, nodelen, "%s", hp->h_name); + if (ret < 0 || (size_t)ret >= nodelen) { + return EAI_MEMORY; + } + if (flags & NI_NOFQDN) { + p = strchr(node,'.'); + if (p) { + *p = '\0'; + } + } + return 0; + } + + if (flags & NI_NAMEREQD) { + /* If we require a name and didn't get one, + * automatically fail. */ + return ret; + } + /* Otherwise just fall into the numeric host code... */ + } + p = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); + ret = snprintf(node, nodelen, "%s", p); + if (ret < 0 || (size_t)ret >= nodelen) { + return EAI_MEMORY; + } + return 0; +} + +static int getservicenameinfo(const struct sockaddr *sa, + char *service, + size_t servicelen, + int flags) +{ + int ret = -1; + int port = ntohs(((struct sockaddr_in *)sa)->sin_port); + + if (!(flags & NI_NUMERICSERV)) { + struct servent *se = getservbyport( + port, + (flags & NI_DGRAM) ? "udp" : "tcp"); + if (se && se->s_name) { + /* Service name looked up successfully. */ + ret = snprintf(service, servicelen, "%s", se->s_name); + if (ret < 0 || (size_t)ret >= servicelen) { + return EAI_MEMORY; + } + return 0; + } + /* Otherwise just fall into the numeric service code... */ + } + ret = snprintf(service, servicelen, "%d", port); + if (ret < 0 || (size_t)ret >= servicelen) { + return EAI_MEMORY; + } + return 0; +} + +/* + * Convert an ipv4 address to a hostname. + * + * Bugs: - No IPv6 support. + */ +int rep_getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *node, size_t nodelen, + char *service, size_t servicelen, int flags) +{ + + /* Invalid arguments. */ + if (sa == NULL || (node == NULL && service == NULL)) { + return EAI_FAIL; + } + + if (sa->sa_family != AF_INET) { + return EAI_FAIL; + } + + if (salen < sizeof(struct sockaddr_in)) { + return EAI_FAIL; + } + + if (node) { + return gethostnameinfo(sa, node, nodelen, flags); + } + + if (service) { + return getservicenameinfo(sa, service, servicelen, flags); + } + return 0; +} diff --git a/ctdb/lib/replace/getaddrinfo.h b/ctdb/lib/replace/getaddrinfo.h new file mode 100644 index 0000000000..cf040da2db --- /dev/null +++ b/ctdb/lib/replace/getaddrinfo.h @@ -0,0 +1,91 @@ +/* +PostgreSQL Database Management System +(formerly known as Postgres, then as Postgres95) + +Portions Copyright (c) 1996-2005, The PostgreSQL Global Development Group + +Portions Copyright (c) 1994, The Regents of the University of California + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose, without fee, and without a written agreement +is hereby granted, provided that the above copyright notice and this paragraph +and the following two paragraphs appear in all copies. + +IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING +LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, +EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. + +THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS +ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS +TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +*/ + +/*------------------------------------------------------------------------- + * + * getaddrinfo.h + * Support getaddrinfo() on platforms that don't have it. + * + * Note: we use our own routines on platforms that don't HAVE_STRUCT_ADDRINFO, + * whether or not the library routine getaddrinfo() can be found. This + * policy is needed because on some platforms a manually installed libbind.a + * may provide getaddrinfo(), yet the system headers may not provide the + * struct definitions needed to call it. To avoid conflict with the libbind + * definition in such cases, we rename our routines to pg_xxx() via macros. + * + +in lib/replace we use rep_xxx() + + * This code will also work on platforms where struct addrinfo is defined + * in the system headers but no getaddrinfo() can be located. + * + * Copyright (c) 2003-2007, PostgreSQL Global Development Group + * + *------------------------------------------------------------------------- + */ +#ifndef GETADDRINFO_H +#define GETADDRINFO_H + +#ifndef HAVE_GETADDRINFO + +/* Rename private copies per comments above */ +#ifdef getaddrinfo +#undef getaddrinfo +#endif +#define getaddrinfo rep_getaddrinfo +#define HAVE_GETADDRINFO + +#ifdef freeaddrinfo +#undef freeaddrinfo +#endif +#define freeaddrinfo rep_freeaddrinfo +#define HAVE_FREEADDRINFO + +#ifdef gai_strerror +#undef gai_strerror +#endif +#define gai_strerror rep_gai_strerror +#define HAVE_GAI_STRERROR + +#ifdef getnameinfo +#undef getnameinfo +#endif +#define getnameinfo rep_getnameinfo +#ifndef HAVE_GETNAMEINFO +#define HAVE_GETNAMEINFO +#endif + +extern int rep_getaddrinfo(const char *node, const char *service, + const struct addrinfo * hints, struct addrinfo ** res); +extern void rep_freeaddrinfo(struct addrinfo * res); +extern const char *rep_gai_strerror(int errcode); +extern int rep_getnameinfo(const struct sockaddr * sa, socklen_t salen, + char *node, size_t nodelen, + char *service, size_t servicelen, int flags); +#endif /* HAVE_GETADDRINFO */ + +#endif /* GETADDRINFO_H */ diff --git a/ctdb/lib/replace/getifaddrs.c b/ctdb/lib/replace/getifaddrs.c new file mode 100644 index 0000000000..84d790689d --- /dev/null +++ b/ctdb/lib/replace/getifaddrs.c @@ -0,0 +1,352 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Jeremy Allison 2007 + Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2007 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#define SOCKET_WRAPPER_NOT_REPLACE + +#include "replace.h" +#include "system/network.h" + +#include <unistd.h> +#include <stdio.h> +#include <sys/types.h> + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +#ifndef SIOCGIFCONF +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif +#endif + +#ifdef HAVE_IFACE_GETIFADDRS +#define _FOUND_IFACE_ANY +#else + +void rep_freeifaddrs(struct ifaddrs *ifp) +{ + if (ifp != NULL) { + free(ifp->ifa_name); + free(ifp->ifa_addr); + free(ifp->ifa_netmask); + free(ifp->ifa_dstaddr); + freeifaddrs(ifp->ifa_next); + free(ifp); + } +} + +static struct sockaddr *sockaddr_dup(struct sockaddr *sa) +{ + struct sockaddr *ret; + socklen_t socklen; +#ifdef HAVE_SOCKADDR_SA_LEN + socklen = sa->sa_len; +#else + socklen = sizeof(struct sockaddr_storage); +#endif + ret = calloc(1, socklen); + if (ret == NULL) + return NULL; + memcpy(ret, sa, socklen); + return ret; +} +#endif + +#if HAVE_IFACE_IFCONF + +/* this works for Linux 2.2, Solaris 2.5, SunOS4, HPUX 10.20, OSF1 + V4.0, Ultrix 4.4, SCO Unix 3.2, IRIX 6.4 and FreeBSD 3.2. + + It probably also works on any BSD style system. */ + +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifconf ifc; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + n = ifc.ifc_len / sizeof(struct ifreq); + + /* Loop through interfaces, looking for given IP address */ + for (i=n-1; i>=0; i--) { + if (ioctl(fd, SIOCGIFFLAGS, &ifr[i]) == -1) { + freeifaddrs(*ifap); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + curif->ifa_name = strdup(ifr[i].ifr_name); + curif->ifa_flags = ifr[i].ifr_flags; + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + + curif->ifa_addr = NULL; + if (ioctl(fd, SIOCGIFADDR, &ifr[i]) != -1) { + curif->ifa_addr = sockaddr_dup(&ifr[i].ifr_addr); + } + + curif->ifa_netmask = NULL; + if (ioctl(fd, SIOCGIFNETMASK, &ifr[i]) != -1) { + curif->ifa_netmask = sockaddr_dup(&ifr[i].ifr_addr); + } + + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFCONF */ +#ifdef HAVE_IFACE_IFREQ + +#ifndef I_STR +#include <sys/stropts.h> +#endif + +/**************************************************************************** +this should cover most of the streams based systems +Thanks to Andrej.Borsenkow@mow.siemens.ru for several ideas in this code +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + struct ifreq ifreq; + struct strioctl strioctl; + char buff[8192]; + int fd, i, n; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + strioctl.ic_cmd = SIOCGIFCONF; + strioctl.ic_dp = buff; + strioctl.ic_len = sizeof(buff); + if (ioctl(fd, I_STR, &strioctl) < 0) { + close(fd); + return -1; + } + + /* we can ignore the possible sizeof(int) here as the resulting + number of interface structures won't change */ + n = strioctl.ic_len / sizeof(struct ifreq); + + /* we will assume that the kernel returns the length as an int + at the start of the buffer if the offered size is a + multiple of the structure size plus an int */ + if (n*sizeof(struct ifreq) + sizeof(int) == strioctl.ic_len) { + ifr = (struct ifreq *)(buff + sizeof(int)); + } else { + ifr = (struct ifreq *)buff; + } + + /* Loop through interfaces */ + + for (i = 0; i<n; i++) { + ifreq = ifr[i]; + + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + strioctl.ic_cmd = SIOCGIFFLAGS; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_flags = ifreq.ifr_flags; + + strioctl.ic_cmd = SIOCGIFADDR; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_name = strdup(ifreq.ifr_name); + curif->ifa_addr = sockaddr_dup(&ifreq.ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_next = NULL; + curif->ifa_netmask = NULL; + + strioctl.ic_cmd = SIOCGIFNETMASK; + strioctl.ic_dp = (char *)&ifreq; + strioctl.ic_len = sizeof(struct ifreq); + if (ioctl(fd, I_STR, &strioctl) != 0) { + freeifaddrs(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifreq.ifr_addr); + + lastif = curif; + } + + close(fd); + + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_IFREQ */ +#ifdef HAVE_IFACE_AIX + +/**************************************************************************** +this one is for AIX (tested on 4.2) +****************************************************************************/ +int rep_getifaddrs(struct ifaddrs **ifap) +{ + char buff[8192]; + int fd, i; + struct ifconf ifc; + struct ifreq *ifr=NULL; + struct ifaddrs *curif; + struct ifaddrs *lastif = NULL; + + *ifap = NULL; + + if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) { + return -1; + } + + ifc.ifc_len = sizeof(buff); + ifc.ifc_buf = buff; + + if (ioctl(fd, SIOCGIFCONF, &ifc) != 0) { + close(fd); + return -1; + } + + ifr = ifc.ifc_req; + + /* Loop through interfaces */ + i = ifc.ifc_len; + + while (i > 0) { + unsigned int inc; + + inc = ifr->ifr_addr.sa_len; + + if (ioctl(fd, SIOCGIFADDR, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif = calloc(1, sizeof(struct ifaddrs)); + if (lastif == NULL) { + *ifap = curif; + } else { + lastif->ifa_next = curif; + } + + curif->ifa_name = strdup(ifr->ifr_name); + curif->ifa_addr = sockaddr_dup(&ifr->ifr_addr); + curif->ifa_dstaddr = NULL; + curif->ifa_data = NULL; + curif->ifa_netmask = NULL; + curif->ifa_next = NULL; + + if (ioctl(fd, SIOCGIFFLAGS, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_flags = ifr->ifr_flags; + + if (ioctl(fd, SIOCGIFNETMASK, ifr) != 0) { + freeaddrinfo(*ifap); + return -1; + } + + curif->ifa_netmask = sockaddr_dup(&ifr->ifr_addr); + + lastif = curif; + + next: + /* + * Patch from Archie Cobbs (archie@whistle.com). The + * addresses in the SIOCGIFCONF interface list have a + * minimum size. Usually this doesn't matter, but if + * your machine has tunnel interfaces, etc. that have + * a zero length "link address", this does matter. */ + + if (inc < sizeof(ifr->ifr_addr)) + inc = sizeof(ifr->ifr_addr); + inc += IFNAMSIZ; + + ifr = (struct ifreq*) (((char*) ifr) + inc); + i -= inc; + } + + close(fd); + return 0; +} + +#define _FOUND_IFACE_ANY +#endif /* HAVE_IFACE_AIX */ +#ifndef _FOUND_IFACE_ANY +int rep_getifaddrs(struct ifaddrs **ifap) +{ + errno = ENOSYS; + return -1; +} +#endif diff --git a/ctdb/lib/replace/hdr_replace.h b/ctdb/lib/replace/hdr_replace.h new file mode 100644 index 0000000000..6cfa50f809 --- /dev/null +++ b/ctdb/lib/replace/hdr_replace.h @@ -0,0 +1,2 @@ +/* this is a replacement header for a missing system header */ +#include "replace.h" diff --git a/ctdb/lib/replace/inet_aton.c b/ctdb/lib/replace/inet_aton.c new file mode 100644 index 0000000000..c6b3bb11a7 --- /dev/null +++ b/ctdb/lib/replace/inet_aton.c @@ -0,0 +1,33 @@ +/* + * Unix SMB/CIFS implementation. + * replacement functions + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +/** + * We know that we have inet_pton from earlier libreplace checks. + */ +int rep_inet_aton(const char *src, struct in_addr *dst) +{ + return (inet_pton(AF_INET, src, dst) > 0) ? 1 : 0; +} diff --git a/ctdb/lib/replace/inet_ntoa.c b/ctdb/lib/replace/inet_ntoa.c new file mode 100644 index 0000000000..e3b80ebef8 --- /dev/null +++ b/ctdb/lib/replace/inet_ntoa.c @@ -0,0 +1,39 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Andrew Tridgell 2003 + * Copyright (C) Michael Adam 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +/** + * NOTE: this is not thread safe, but it can't be, either + * since it returns a pointer to static memory. + */ +char *rep_inet_ntoa(struct in_addr ip) +{ + uint8_t *p = (uint8_t *)&ip.s_addr; + static char buf[18]; + slprintf(buf, 17, "%d.%d.%d.%d", + (int)p[0], (int)p[1], (int)p[2], (int)p[3]); + return buf; +} diff --git a/ctdb/lib/replace/inet_ntop.c b/ctdb/lib/replace/inet_ntop.c new file mode 100644 index 0000000000..fb3d8e90c8 --- /dev/null +++ b/ctdb/lib/replace/inet_ntop.c @@ -0,0 +1,191 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + + +#include "replace.h" +#include "system/network.h" + +#define NS_INT16SZ 2 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4(const unsigned char *src, char *dst, + socklen_t size); + +#ifdef AF_INET6 +static const char *inet_ntop6(const unsigned char *src, char *dst, + socklen_t size); +#endif + +/* char * + * isc_net_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +rep_inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a unsigned char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, socklen_t size) +{ + static const char *fmt = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + size_t len; + + len = snprintf(tmp, sizeof tmp, fmt, src[0], src[1], src[2], src[3]); + if (len >= size) { + errno = ENOSPC; + return (NULL); + } + memcpy(dst, tmp, len + 1); + + return (dst); +} + +/* const char * + * isc_inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +#ifdef AF_INET6 +static const char * +inet_ntop6(const unsigned char *src, char *dst, socklen_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i, inc; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + inc = snprintf(tp, 5, "%x", words[i]); + if (inc >= 5) { + abort(); + } + tp += inc; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + memcpy(dst, tmp, tp - tmp); + return (dst); +} +#endif /* AF_INET6 */ diff --git a/ctdb/lib/replace/inet_pton.c b/ctdb/lib/replace/inet_pton.c new file mode 100644 index 0000000000..80e4865ef4 --- /dev/null +++ b/ctdb/lib/replace/inet_pton.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 1996-2001 Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM + * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL + * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "replace.h" +#include "system/network.h" + +#define NS_INT16SZ 2 +#define NS_INADDRSZ 4 +#define NS_IN6ADDRSZ 16 + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4(const char *src, unsigned char *dst); +#ifdef AF_INET6 +static int inet_pton6(const char *src, unsigned char *dst); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +rep_inet_pton(int af, + const char *src, + void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#ifdef AF_INET6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + unsigned char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + unsigned int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, NS_INADDRSZ); + return (1); +} + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +#ifdef AF_INET6 +static int +inet_pton6(src, dst) + const char *src; + unsigned char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + NS_INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, NS_IN6ADDRSZ); + return (1); +} +#endif diff --git a/ctdb/lib/replace/install-sh b/ctdb/lib/replace/install-sh new file mode 100755 index 0000000000..58719246f0 --- /dev/null +++ b/ctdb/lib/replace/install-sh @@ -0,0 +1,238 @@ +#! /bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. +# + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + true +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + else + instcmd=mkdir + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + true + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + true + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + true + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' +' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + true + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + true + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/ctdb/lib/replace/libreplace.m4 b/ctdb/lib/replace/libreplace.m4 new file mode 100644 index 0000000000..f4ae715340 --- /dev/null +++ b/ctdb/lib/replace/libreplace.m4 @@ -0,0 +1,490 @@ +AC_DEFUN_ONCE(AC_LIBREPLACE_LOCATION_CHECKS, +[ +echo "LIBREPLACE_LOCATION_CHECKS: START" + +dnl find the libreplace sources. This is meant to work both for +dnl libreplace standalone builds, and builds of packages using libreplace +libreplacedir="" +libreplacepaths="$srcdir $srcdir/lib/replace $srcdir/libreplace $srcdir/../libreplace $srcdir/../replace $srcdir/../lib/replace $srcdir/../../../lib/replace" +for d in $libreplacepaths; do + if test -f "$d/replace.c"; then + libreplacedir="$d" + AC_SUBST(libreplacedir) + break; + fi +done +if test x"$libreplacedir" = "x"; then + AC_MSG_ERROR([cannot find libreplace in $libreplacepaths]) +fi +LIBREPLACEOBJ="$libreplacedir/replace.o" +AC_SUBST(LIBREPLACEOBJ) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +echo "LIBREPLACE_LOCATION_CHECKS: END" +]) dnl end AC_LIBREPLACE_LOCATION_CHECKS + + +AC_DEFUN_ONCE(AC_LIBREPLACE_BROKEN_CHECKS, +[ +echo "LIBREPLACE_BROKEN_CHECKS: START" + +dnl find the libreplace sources. This is meant to work both for +dnl libreplace standalone builds, and builds of packages using libreplace +libreplacedir="" +libreplacepaths="$srcdir $srcdir/lib/replace $srcdir/libreplace $srcdir/../libreplace $srcdir/../replace $srcdir/../lib/replace $srcdir/../../../lib/replace" +for d in $libreplacepaths; do + if test -f "$d/replace.c"; then + libreplacedir="$d" + AC_SUBST(libreplacedir) + break; + fi +done +if test x"$libreplacedir" = "x"; then + AC_MSG_ERROR([cannot find libreplace in $libreplacepaths]) +fi + +LIBREPLACEOBJ="$libreplacedir/replace.o" +AC_SUBST(LIBREPLACEOBJ) + +LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/snprintf.o $libreplacedir/xattr.o" + +AC_TYPE_UID_T +AC_TYPE_MODE_T +AC_TYPE_OFF_T +AC_TYPE_SIZE_T +AC_TYPE_PID_T +AC_STRUCT_ST_RDEV +AC_CHECK_TYPE(ino_t,unsigned) +AC_CHECK_TYPE(loff_t,off_t) +AC_CHECK_TYPE(offset_t,loff_t) +AC_CHECK_TYPE(blksize_t,long) +AC_CHECK_TYPE(blkcnt_t,long) + +AC_FUNC_MEMCMP + +AC_CHECK_FUNCS([pipe strftime srandom random srand rand usleep setbuffer lstat getpgrp utime utimes]) + +AC_CHECK_HEADERS(stdbool.h stdint.h sys/select.h) +AC_CHECK_HEADERS(setjmp.h utime.h sys/wait.h) + +LIBREPLACE_PROVIDE_HEADER([stdint.h]) +LIBREPLACE_PROVIDE_HEADER([stdbool.h]) + +AC_DEFINE(HAVE_LIBREPLACE, 1, [We have libreplace]) + +AC_CHECK_TYPE(bool, +[AC_DEFINE(HAVE_BOOL, 1, [Whether the bool type is available])],, +[ +AC_INCLUDES_DEFAULT +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif] +) + +AC_CHECK_TYPE(_Bool, +[AC_DEFINE(HAVE__Bool, 1, [Whether the _Bool type is available])],, +[ +AC_INCLUDES_DEFAULT +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif] +) + +AC_CHECK_HEADERS(linux/types.h) + +AC_CACHE_CHECK([for working mmap],libreplace_cv_HAVE_MMAP,[ +AC_TRY_RUN([#include "$libreplacedir/test/shared_mmap.c"], + libreplace_cv_HAVE_MMAP=yes,libreplace_cv_HAVE_MMAP=no,libreplace_cv_HAVE_MMAP=cross)]) +if test x"$libreplace_cv_HAVE_MMAP" = x"yes"; then + AC_DEFINE(HAVE_MMAP,1,[Whether mmap works]) +fi + +AC_CACHE_CHECK([for working mremap],libreplace_cv_HAVE_MREMAP,[ +AC_TRY_RUN([#include "$libreplacedir/test/shared_mremap.c"], + libreplace_cv_HAVE_MREMAP=yes,libreplace_cv_HAVE_MREMAP=no,libreplace_cv_HAVE_MREMAP=cross)]) +if test x"$libreplace_cv_HAVE_MREMAP" = x"yes"; then + AC_DEFINE(HAVE_MREMAP,1,[Whether mremap works]) +fi + +AC_CACHE_CHECK([for incoherent mmap],libreplace_cv_HAVE_INCOHERENT_MMAP,[ +AC_TRY_RUN([#include "$libreplacedir/test/incoherent_mmap.c"], + libreplace_cv_HAVE_INCOHERENT_MMAP=yes,libreplace_cv_HAVE_INCOHERENT_MMAP=no,libreplace_cv_HAVE_INCOHERENT_MMAP=cross)]) +if test x"$libreplace_cv_HAVE_INCOHERENT_MMAP" = x"yes"; then + AC_DEFINE(HAVE_INCOHERENT_MMAP,1,[Whether mmap is incoherent against write]) +fi + + +AC_CHECK_HEADERS(sys/syslog.h syslog.h) +AC_CHECK_HEADERS(sys/time.h time.h) +AC_CHECK_HEADERS(stdarg.h vararg.h) +AC_CHECK_HEADERS(sys/mount.h mntent.h) +AC_CHECK_HEADERS(stropts.h) +AC_CHECK_HEADERS(unix.h) +AC_CHECK_HEADERS(malloc.h) +AC_CHECK_HEADERS(syscall.h) +AC_CHECK_HEADERS(sys/syscall.h) +AC_CHECK_HEADERS(sys/ucontext.h) + +AC_CHECK_FUNCS(syscall setuid seteuid setreuid setresuid setgid setegid setregid setresgid setgroups) +AC_CHECK_FUNCS(chroot bzero strerror strerror_r memalign posix_memalign getpagesize) +AC_CHECK_FUNCS(vsyslog setlinebuf mktime ftruncate chsize rename) +AC_CHECK_FUNCS(waitpid wait4 strlcpy strlcat initgroups memmove strdup) +AC_CHECK_FUNCS(pread pwrite strndup strcasestr strtok_r mkdtemp dup2 dprintf vdprintf) +AC_CHECK_FUNCS(isatty chown lchown link readlink symlink realpath) +AC_CHECK_FUNCS(fdatasync,,[ + # if we didn't find it, look in librt (Solaris hides it there...) + AC_CHECK_LIB(rt, fdatasync, + [libreplace_cv_HAVE_FDATASYNC_IN_LIBRT=yes + AC_DEFINE(HAVE_FDATASYNC, 1, Define to 1 if there is support for fdatasync)]) +]) +AC_HAVE_DECL(fdatasync, [#include <unistd.h>]) +AC_CHECK_FUNCS(clock_gettime,libreplace_cv_have_clock_gettime=yes,[ + AC_CHECK_LIB(rt, clock_gettime, + [libreplace_cv_HAVE_CLOCK_GETTIME_IN_LIBRT=yes + libreplace_cv_have_clock_gettime=yes + AC_DEFINE(HAVE_CLOCK_GETTIME, 1, Define to 1 if there is support for clock_gettime)]) +]) + +AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h) +AC_CHECK_HEADERS(sys/ea.h sys/proplist.h) + +LIBREPLACE_FILESYS_LIBS="" + +############################################ +# Check for EA implementations +case "$host_os" in + *freebsd4* | *dragonfly* ) + AC_DEFINE(BROKEN_EXTATTR, 1, [Does extattr API work]) + ;; + *) + AC_SEARCH_LIBS(getxattr, [attr]) + AC_CHECK_FUNCS(attr_get attr_getf attr_list attr_listf attropen attr_remove) + AC_CHECK_FUNCS(attr_removef attr_set attr_setf extattr_delete_fd extattr_delete_file) + AC_CHECK_FUNCS(extattr_get_fd extattr_get_file extattr_list_fd extattr_list_file) + AC_CHECK_FUNCS(extattr_set_fd extattr_set_file fgetea fgetxattr flistea flistxattr) + AC_CHECK_FUNCS(fremoveea fremovexattr fsetea fsetxattr getea getxattr listea) + AC_CHECK_FUNCS(listxattr removeea removexattr setea setxattr) + + AC_CHECK_LIB_EXT(attr, LIBREPLACE_FILESYS_LIBS, flistea) + AC_CHECK_LIB_EXT(attr, LIBREPLACE_FILESYS_LIBS, flistxattr) + AC_CHECK_LIB_EXT(attr, LIBREPLACE_FILESYS_LIBS, attr_listf) + AC_CHECK_LIB_EXT(attr, LIBREPLACE_FILESYS_LIBS, extattr_list_fd) + + ;; +esac + + +######################################################## +# Do xattr functions take additional options like on Darwin? +if test x"$ac_cv_func_getxattr" = x"yes" ; then + AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, [ + old_LIBS=$LIBS + LIBS="$LIBS $LIBREPLACE_FILESYS_LIBS" + AC_TRY_COMPILE([ + #include <sys/types.h> + #if HAVE_ATTR_XATTR_H + #include <attr/xattr.h> + #elif HAVE_SYS_XATTR_H + #include <sys/xattr.h> + #endif + ],[ + getxattr(0, 0, 0, 0, 0, 0); + ], + [smb_attr_cv_xattr_add_opt=yes], + [smb_attr_cv_xattr_add_opt=no;LIBS=$old_LIBS]) + ]) + if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then + AC_DEFINE(XATTR_ADDITIONAL_OPTIONS, 1, [xattr functions have additional options]) + fi +fi + +AC_CHECK_FUNCS(get_current_dir_name) +AC_HAVE_DECL(setresuid, [#include <unistd.h>]) +AC_HAVE_DECL(setresgid, [#include <unistd.h>]) +AC_HAVE_DECL(errno, [#include <errno.h>]) + +AC_CACHE_CHECK([for secure mkstemp],libreplace_cv_HAVE_SECURE_MKSTEMP,[ +AC_TRY_RUN([#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +main() { + 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); +}], +libreplace_cv_HAVE_SECURE_MKSTEMP=yes, +libreplace_cv_HAVE_SECURE_MKSTEMP=no, +libreplace_cv_HAVE_SECURE_MKSTEMP=cross)]) +if test x"$libreplace_cv_HAVE_SECURE_MKSTEMP" = x"yes"; then + AC_DEFINE(HAVE_SECURE_MKSTEMP,1,[Whether mkstemp is secure]) +fi + +dnl Provided by snprintf.c: +AC_CHECK_HEADERS(stdio.h strings.h) +AC_CHECK_DECLS([snprintf, vsnprintf, asprintf, vasprintf]) +AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf) + +AC_CACHE_CHECK([for C99 vsnprintf],libreplace_cv_HAVE_C99_VSNPRINTF,[ +AC_TRY_RUN([ +#include <sys/types.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdlib.h> +void foo(const char *format, ...) { + va_list ap; + int len; + char buf[20]; + long long l = 1234567890; + l *= 100; + + va_start(ap, format); + len = vsnprintf(buf, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) exit(2); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(3); + + if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(4); + if (snprintf(buf, 20, "%zu", 123456789) != 9 || strcmp(buf, "123456789") != 0) exit(5); + if (snprintf(buf, 20, "%2\$d %1\$d", 3, 4) != 3 || strcmp(buf, "4 3") != 0) exit(6); + if (snprintf(buf, 20, "%s", 0) < 3) exit(7); + + exit(0); +} +main() { foo("hello"); } +], +libreplace_cv_HAVE_C99_VSNPRINTF=yes,libreplace_cv_HAVE_C99_VSNPRINTF=no,libreplace_cv_HAVE_C99_VSNPRINTF=cross)]) +if test x"$libreplace_cv_HAVE_C99_VSNPRINTF" = x"yes"; then + AC_DEFINE(HAVE_C99_VSNPRINTF,1,[Whether there is a C99 compliant vsnprintf]) +fi + + +dnl VA_COPY +AC_CACHE_CHECK([for va_copy],libreplace_cv_HAVE_VA_COPY,[ +AC_TRY_LINK([#include <stdarg.h> +va_list ap1,ap2;], [va_copy(ap1,ap2);], +libreplace_cv_HAVE_VA_COPY=yes,libreplace_cv_HAVE_VA_COPY=no)]) +if test x"$libreplace_cv_HAVE_VA_COPY" = x"yes"; then + AC_DEFINE(HAVE_VA_COPY,1,[Whether va_copy() is available]) +fi + +if test x"$libreplace_cv_HAVE_VA_COPY" != x"yes"; then +AC_CACHE_CHECK([for __va_copy],libreplace_cv_HAVE___VA_COPY,[ +AC_TRY_LINK([#include <stdarg.h> +va_list ap1,ap2;], [__va_copy(ap1,ap2);], +libreplace_cv_HAVE___VA_COPY=yes,libreplace_cv_HAVE___VA_COPY=no)]) +if test x"$libreplace_cv_HAVE___VA_COPY" = x"yes"; then + AC_DEFINE(HAVE___VA_COPY,1,[Whether __va_copy() is available]) +fi +fi + +dnl __FUNCTION__ macro +AC_CACHE_CHECK([for __FUNCTION__ macro],libreplace_cv_HAVE_FUNCTION_MACRO,[ +AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __FUNCTION__);], +libreplace_cv_HAVE_FUNCTION_MACRO=yes,libreplace_cv_HAVE_FUNCTION_MACRO=no)]) +if test x"$libreplace_cv_HAVE_FUNCTION_MACRO" = x"yes"; then + AC_DEFINE(HAVE_FUNCTION_MACRO,1,[Whether there is a __FUNCTION__ macro]) +else + dnl __func__ macro + AC_CACHE_CHECK([for __func__ macro],libreplace_cv_HAVE_func_MACRO,[ + AC_TRY_COMPILE([#include <stdio.h>], [printf("%s\n", __func__);], + libreplace_cv_HAVE_func_MACRO=yes,libreplace_cv_HAVE_func_MACRO=no)]) + if test x"$libreplace_cv_HAVE_func_MACRO" = x"yes"; then + AC_DEFINE(HAVE_func_MACRO,1,[Whether there is a __func__ macro]) + fi +fi + +AC_CHECK_HEADERS([sys/param.h limits.h]) + +AC_CHECK_TYPE(comparison_fn_t, +[AC_DEFINE(HAVE_COMPARISON_FN_T, 1,[Whether or not we have comparison_fn_t])]) + +AC_HAVE_DECL(setenv, [#include <stdlib.h>]) +AC_CHECK_FUNCS(setenv unsetenv) +AC_HAVE_DECL(environ, [#include <unistd.h>]) + +AC_CHECK_FUNCS(strnlen) +AC_CHECK_FUNCS(strtoull __strtoull strtouq strtoll __strtoll strtoq) + +AC_CHECK_FUNCS(memmem) + +# this test disabled as we don't actually need __VA_ARGS__ yet +AC_TRY_CPP([ +#define eprintf(...) fprintf(stderr, __VA_ARGS__) +eprintf("bla", "bar"); +], AC_DEFINE(HAVE__VA_ARGS__MACRO, 1, [Whether the __VA_ARGS__ macro is available])) + + +AC_CACHE_CHECK([for sig_atomic_t type],libreplace_cv_sig_atomic_t, [ + AC_TRY_COMPILE([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <signal.h>],[sig_atomic_t i = 0], + libreplace_cv_sig_atomic_t=yes,libreplace_cv_sig_atomic_t=no)]) +if test x"$libreplace_cv_sig_atomic_t" = x"yes"; then + AC_DEFINE(HAVE_SIG_ATOMIC_T_TYPE,1,[Whether we have the atomic_t variable type]) +fi + + +dnl Check if the C compiler understands volatile (it should, being ANSI). +AC_CACHE_CHECK([that the C compiler understands volatile],libreplace_cv_volatile, [ + AC_TRY_COMPILE([#include <sys/types.h>],[volatile int i = 0], + libreplace_cv_volatile=yes,libreplace_cv_volatile=no)]) +if test x"$libreplace_cv_volatile" = x"yes"; then + AC_DEFINE(HAVE_VOLATILE, 1, [Whether the C compiler understands volatile]) +fi + +m4_include(system/config.m4) + +AC_CACHE_CHECK([for O_DIRECT flag to open(2)],libreplace_cv_HAVE_OPEN_O_DIRECT,[ +AC_TRY_COMPILE([ +#include <unistd.h> +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif], +[int fd = open("/dev/null", O_DIRECT);], +libreplace_cv_HAVE_OPEN_O_DIRECT=yes,libreplace_cv_HAVE_OPEN_O_DIRECT=no)]) +if test x"$libreplace_cv_HAVE_OPEN_O_DIRECT" = x"yes"; then + AC_DEFINE(HAVE_OPEN_O_DIRECT,1,[Whether the open(2) accepts O_DIRECT]) +fi + +m4_include(dlfcn.m4) +m4_include(strptime.m4) +m4_include(win32.m4) +m4_include(timegm.m4) +m4_include(repdir.m4) +m4_include(crypt.m4) + +if test x$libreplace_cv_have_clock_gettime = xyes ; then + SMB_CHECK_CLOCK_ID(CLOCK_MONOTONIC) + SMB_CHECK_CLOCK_ID(CLOCK_PROCESS_CPUTIME_ID) + SMB_CHECK_CLOCK_ID(CLOCK_REALTIME) +fi + +AC_CACHE_CHECK([for struct timespec type],libreplace_cv_struct_timespec, [ + AC_TRY_COMPILE([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif +],[struct timespec ts;], + libreplace_cv_struct_timespec=yes,libreplace_cv_struct_timespec=no)]) +if test x"$libreplace_cv_struct_timespec" = x"yes"; then + AC_DEFINE(HAVE_STRUCT_TIMESPEC,1,[Whether we have struct timespec]) +fi + +AC_CACHE_CHECK([for ucontext_t type],libreplace_cv_ucontext_t, [ + AC_TRY_COMPILE([ +#include <signal.h> +#if HAVE_SYS_UCONTEXT_H +#include <sys/ucontext.h> +# endif +],[ucontext_t uc; sigaddset(&uc.uc_sigmask, SIGUSR1);], + libreplace_cv_ucontext_t=yes,libreplace_cv_ucontext_t=no)]) +if test x"$libreplace_cv_ucontext_t" = x"yes"; then + AC_DEFINE(HAVE_UCONTEXT_T,1,[Whether we have ucontext_t]) +fi + +AC_CHECK_FUNCS([printf memset memcpy],,[AC_MSG_ERROR([Required function not found])]) + +echo "LIBREPLACE_BROKEN_CHECKS: END" +]) dnl end AC_LIBREPLACE_BROKEN_CHECKS + +AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_START, +[ +#LIBREPLACE_ALL_CHECKS: START" +]) +AC_DEFUN_ONCE(AC__LIBREPLACE_ALL_CHECKS_END, +[ +#LIBREPLACE_ALL_CHECKS: END" +]) +m4_define(AC_LIBREPLACE_ALL_CHECKS, +[ +AC__LIBREPLACE_ALL_CHECKS_START +AC_LIBREPLACE_LOCATION_CHECKS +AC_LIBREPLACE_CC_CHECKS +AC_LIBREPLACE_BROKEN_CHECKS +AC__LIBREPLACE_ALL_CHECKS_END +CFLAGS="$CFLAGS -I$libreplacedir" +]) + +m4_include(libreplace_cc.m4) +m4_include(libreplace_ld.m4) +m4_include(libreplace_network.m4) +m4_include(libreplace_macros.m4) + + +dnl SMB_CHECK_CLOCK_ID(clockid) +dnl Test whether the specified clock_gettime clock ID is available. If it +dnl is, we define HAVE_clockid +AC_DEFUN([SMB_CHECK_CLOCK_ID], +[ + AC_MSG_CHECKING(for $1) + AC_TRY_LINK([ +#if TIME_WITH_SYS_TIME +# include <sys/time.h> +# include <time.h> +#else +# if HAVE_SYS_TIME_H +# include <sys/time.h> +# else +# include <time.h> +# endif +#endif + ], + [ +clockid_t clk = $1; + ], + [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_$1, 1, + [Whether the clock_gettime clock ID $1 is available]) + ], + [ + AC_MSG_RESULT(no) + ]) +]) +m4_ifndef([AC_USE_SYSTEM_EXTENSIONS],[m4_include(autoconf-2.60.m4)]) diff --git a/ctdb/lib/replace/libreplace_cc.m4 b/ctdb/lib/replace/libreplace_cc.m4 new file mode 100644 index 0000000000..50cb73583b --- /dev/null +++ b/ctdb/lib/replace/libreplace_cc.m4 @@ -0,0 +1,197 @@ + +AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_START, +[ +echo "LIBREPLACE_CC_CHECKS: START" +]) + +AC_DEFUN_ONCE(AC__LIBREPLACE_ONLY_CC_CHECKS_END, +[ +echo "LIBREPLACE_CC_CHECKS: END" +]) + +dnl +dnl +dnl AC_LIBREPLACE_CC_CHECKS +dnl +dnl Note: we need to use m4_define instead of AC_DEFUN because +dnl of the ordering of tests +dnl +dnl +m4_define(AC_LIBREPLACE_CC_CHECKS, +[ +AC__LIBREPLACE_ONLY_CC_CHECKS_START + +dnl stop the C89 attempt by autoconf - if autoconf detects -Ae it will enable it +dnl which conflicts with C99 on HPUX +ac_cv_prog_cc_Ae=no + +savedCFLAGS=$CFLAGS +AC_PROG_CC +CFLAGS=$savedCFLAGS + +dnl don't try for C99 if we are using gcc, as otherwise we +dnl lose immediate structure constants +if test x"$GCC" != x"yes" ; then +AC_PROG_CC_C99 +fi + +if test x"$GCC" = x"yes" ; then + AC_MSG_CHECKING([for version of gcc]) + GCC_VERSION=`$CC -dumpversion` + AC_MSG_RESULT(${GCC_VERSION}) +fi +AC_USE_SYSTEM_EXTENSIONS +AC_C_BIGENDIAN +AC_C_INLINE +LIBREPLACE_C99_STRUCT_INIT([],[AC_MSG_WARN([c99 structure initializer are not supported])]) + +AC_PROG_INSTALL + +AC_ISC_POSIX +AC_N_DEFINE(_XOPEN_SOURCE_EXTENDED) + +AC_MSG_CHECKING(checking getconf LFS_CFLAGS for large file support flags) +LFS_CFLAGS=`(getconf LFS_CFLAGS) 2>/dev/null` || LFS_CFLAGS="" + +AC_MSG_RESULT(${LFS_CFLAGS}) +if test "x$LFS_CFLAGS" != 'x-1' || test "x$LFS_CFLAGS" != "xundefined"; then + CFLAGS="$CFLAGS $LFS_CFLAGS" +fi + +AC_SYS_LARGEFILE + +dnl Add #include for broken IRIX header files +case "$host_os" in + *irix6*) AC_ADD_INCLUDE(<standards.h>) + AC_N_DEFINE(_XOPEN_SOURCE,600) + AC_N_DEFINE(_BSD_TYPES) + ;; + *hpux*) + # mmap on HPUX is completely broken... + AC_DEFINE(MMAP_BLACKLIST, 1, [Whether MMAP is broken]) + if test "`uname -r`" = "B.11.00" -o "`uname -r`" = "B.11.11"; then + AC_MSG_WARN([Enabling HPUX 11.00/11.11 header bug workaround]) + CFLAGS="$CFLAGS -Dpread=pread64 -Dpwrite=pwrite64" + fi + if test "`uname -r`" = "B.11.23"; then + AC_MSG_WARN([Enabling HPUX 11.23 machine/sys/getppdp.h bug workaround]) + CFLAGS="$CFLAGS -D_MACHINE_SYS_GETPPDP_INCLUDED" + fi + ;; + *aix*) + AC_DEFINE(BROKEN_STRNDUP, 1, [Whether strndup is broken]) + AC_DEFINE(BROKEN_STRNLEN, 1, [Whether strnlen is broken]) + if test "${GCC}" != "yes"; then + ## for funky AIX compiler using strncpy() + CFLAGS="$CFLAGS -D_LINUX_SOURCE_COMPAT -qmaxmem=32000" + fi + ;; + *osf*) + # this brings in socklen_t + AC_N_DEFINE(_XOPEN_SOURCE,600) + AC_N_DEFINE(_OSF_SOURCE) + ;; + # + # VOS may need to have POSIX support and System V compatibility enabled. + # + *vos*) + case "$CFLAGS" in + *-D_POSIX_C_SOURCE*);; + *) + CFLAGS="$CFLAGS -D_POSIX_C_SOURCE=200112L" + AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Whether to enable POSIX support]) + ;; + esac + case "$CFLAGS" in + *-D_SYSV*|*-D_SVID_SOURCE*);; + *) + CFLAGS="$CFLAGS -D_SYSV" + AC_DEFINE(_SYSV, 1, [Whether to enable System V compatibility]) + ;; + esac + ;; +esac + +# Do not check for standards.h on darwin, we get nasty warnings on +# OS/X Lion. Probably a positive-list of OS'es like IRIX and AIX +# would be the better choice, but this seems to work fine + +case "$host_os" in + *darwin*) + ;; + *) + AC_CHECK_HEADERS([standards.h]) + ;; +esac + +# Solaris needs HAVE_LONG_LONG defined +AC_CHECK_TYPES(long long) + +AC_CHECK_SIZEOF(int) +AC_CHECK_SIZEOF(char) +AC_CHECK_SIZEOF(short) +AC_CHECK_SIZEOF(long) +AC_CHECK_SIZEOF(long long) + +AC_CHECK_TYPE(int8_t, char) +AC_CHECK_TYPE(uint8_t, unsigned char) +AC_CHECK_TYPE(int16_t, short) +AC_CHECK_TYPE(uint16_t, unsigned short) + +if test $ac_cv_sizeof_int -eq 4 ; then +AC_CHECK_TYPE(int32_t, int) +AC_CHECK_TYPE(uint32_t, unsigned int) +elif test $ac_cv_size_long -eq 4 ; then +AC_CHECK_TYPE(int32_t, long) +AC_CHECK_TYPE(uint32_t, unsigned long) +else +AC_MSG_ERROR([LIBREPLACE no 32-bit type found]) +fi + +AC_CHECK_TYPE(int64_t, long long) +AC_CHECK_TYPE(uint64_t, unsigned long long) + +AC_CHECK_TYPE(size_t, unsigned int) +AC_CHECK_TYPE(ssize_t, int) + +AC_CHECK_SIZEOF(off_t) +AC_CHECK_SIZEOF(size_t) +AC_CHECK_SIZEOF(ssize_t) + +AC_CHECK_TYPES([intptr_t, uintptr_t, ptrdiff_t]) + +if test x"$ac_cv_type_long_long" != x"yes";then + AC_MSG_ERROR([LIBREPLACE needs type 'long long']) +fi +if test $ac_cv_sizeof_long_long -lt 8;then + AC_MSG_ERROR([LIBREPLACE needs sizeof(long long) >= 8]) +fi + +############################################ +# check if the compiler can do immediate structures +AC_SUBST(libreplace_cv_immediate_structures) +AC_CACHE_CHECK([for immediate structures],libreplace_cv_immediate_structures,[ + AC_TRY_COMPILE([ + #include <stdio.h> + ],[ + 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}; + ], + libreplace_cv_immediate_structures=yes, + libreplace_cv_immediate_structures=no, + libreplace_cv_immediate_structures=cross) +]) +if test x"$libreplace_cv_immediate_structures" = x"yes"; then + AC_DEFINE(HAVE_IMMEDIATE_STRUCTURES,1,[Whether the compiler supports immediate structures]) +fi + +AC__LIBREPLACE_ONLY_CC_CHECKS_END +]) dnl end AC_LIBREPLACE_CC_CHECKS diff --git a/ctdb/lib/replace/libreplace_ld.m4 b/ctdb/lib/replace/libreplace_ld.m4 new file mode 100644 index 0000000000..bf0df6186d --- /dev/null +++ b/ctdb/lib/replace/libreplace_ld.m4 @@ -0,0 +1,337 @@ +# +# This offers a nice overview how to build shared libraries on all platforms +# http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html +# + +AC_DEFUN([AC_LIBREPLACE_STLD], +[ + AC_PATH_PROG(PROG_AR, ar) + + STLD=${PROG_AR} + + AC_SUBST(STLD) +]) + +AC_DEFUN([AC_LIBREPLACE_STLD_FLAGS], +[ + STLD_FLAGS="-rcs" + AC_SUBST(STLD_FLAGS) +]) + +AC_DEFUN([AC_LD_EXPORT_DYNAMIC], +[ +saved_LDFLAGS="$LDFLAGS" +if AC_TRY_COMMAND([${CC-cc} $CFLAGS -Wl,--version 2>&1 | grep "GNU ld" >/dev/null]); then + LD_EXPORT_DYNAMIC="-Wl,-export-dynamic" +else + case "$host_os" in + hpux* ) + LD_EXPORT_DYNAMIC="-Wl,-E" + ;; + *) + LD_EXPORT_DYNAMIC="" + ;; + esac +fi +AC_SUBST(LD_EXPORT_DYNAMIC) +LDFLAGS="$saved_LDFLAGS" +]) + +AC_DEFUN([AC_LD_PICFLAG], +[ +case "$host_os" in + *linux*|*gnu*) + PICFLAG="-fPIC" + ;; + *solaris*) + if test "${GCC}" = "yes"; then + PICFLAG="-fPIC" + else + PICFLAG="-KPIC" + fi + ;; + *sunos*) + PICFLAG="-KPIC" # Is this correct for SunOS + ;; + *netbsd* | *freebsd* | *dragonfly* ) + PICFLAG="-fPIC -DPIC" + ;; + *openbsd*) + PICFLAG="-fPIC" + ;; + *irix*) + if test "${GCC}" = "yes"; then + PICFLAG="-fPIC" + else + PICFLAG="-KPIC" + fi + ;; + *aix*) + # as AIX code is always position independent... + PICFLAG="-O2" + ;; + *hpux*) + if test "${GCC}" = "yes"; then + PICFLAG="-fPIC" + elif test "$host_cpu" = "ia64"; then + PICFLAG="+z" + elif test $ac_cv_prog_cc_Ae = yes; then + PICFLAG="+z +ESnolit" + fi + ;; + *osf*) + PICFLAG="-fPIC" + ;; + *unixware*) + PICFLAG="-KPIC" + ;; + *darwin*) + PICFLAG="-fno-common" + ;; +esac +AC_SUBST(PICFLAG) +]) + +AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_LINKER], +[ + LD_SHLIB_LINKER="${CC}" + + case "$host_os" in + *irix*) + LD_SHLIB_LINKER="${PROG_LD}" + ;; + esac + + AC_SUBST(LD_SHLIB_LINKER) +]) + +AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_FLAGS], +[ + LD_SHLIB_FLAGS="-shared" + + case "$host_os" in + *linux*|*gnu*) + LD_SHLIB_FLAGS="-shared -Wl,-Bsymbolic" + ;; + *solaris*) + LD_SHLIB_FLAGS="-G" + if test "${GCC}" = "no"; then + ## ${CFLAGS} added for building 64-bit shared + ## libs using Sun's Compiler + LD_SHLIB_FLAGS="-G \${CFLAGS}" + fi + ;; + *sunos*) + LD_SHLIB_FLAGS="-G" + ;; + *irix*) + LD_SHLIB_FLAGS="-shared" + ;; + *aix*) + LD_SHLIB_FLAGS="-Wl,-G,-bexpall,-bbigtoc" + ;; + *hpux*) + if test "${GCC}" = "yes"; then + LD_SHLIB_FLAGS="-shared" + else + LD_SHLIB_FLAGS="-b" + fi + ;; + *osf*) + LD_SHLIB_FLAGS="-shared" + ;; + *darwin*) + LD_SHLIB_FLAGS="-dynamiclib -Wl,-search_paths_first" + ;; + esac + + AC_SUBST(LD_SHLIB_FLAGS) +]) + +AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_DISALLOW_UNDEF_FLAG], +[ + LD_SHLIB_DISALLOW_UNDEF_FLAG="" + + # + # TODO: enforce error not only warnings + # + # NOTE: -Wl,--no-allow-shlib-undefined isn't what we want... + # as it bails out on broken system libraries + # + case "$host_os" in + *osf*) + LD_SHLIB_DISALLOW_UNDEF_FLAG="-warning_unresolved" + ;; + *darwin*) + LD_SHLIB_DISALLOW_UNDEF_FLAG="-undefined error" + ;; + esac + + AC_SUBST(LD_SHLIB_DISALLOW_UNDEF_FLAG) +]) + +AC_DEFUN([AC_LIBREPLACE_SHLD], +[ + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_LINKER]) + SHLD="$LD_SHLIB_LINKER" + AC_SUBST(SHLD) +]) + +AC_DEFUN([AC_LIBREPLACE_SHLD_FLAGS], +[ + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_FLAGS]) + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_DISALLOW_UNDEF_FLAG]) + SHLD_FLAGS="$LD_SHLIB_FLAGS $LD_SHLIB_DISALLOW_UNDEF_FLAG" + AC_SUBST(SHLD_FLAGS) +]) + +AC_DEFUN([AC_LD_SHLIBEXT], +[ + SHLIBEXT="so" + case "$host_os" in + *hpux*) + if test "$host_cpu" = "ia64"; then + SHLIBEXT="so" + else + SHLIBEXT="sl" + fi + ;; + *darwin*) + SHLIBEXT="dylib" + ;; + esac + AC_SUBST(SHLIBEXT) +]) + +AC_DEFUN([AC_LD_SONAMEFLAG], +[ + AC_SUBST(SONAMEFLAG) + SONAMEFLAG="" + case "$host_os" in + *linux*|*gnu*|*qnx*) + SONAMEFLAG="-Wl,-soname=" + ;; + *solaris*) + SONAMEFLAG="-h " + if test "${GCC}" = "yes"; then + SONAMEFLAG="-Wl,-soname=" + fi + ;; + *sunos*) + SONAMEFLAG="-Wl,-h," + ;; + *netbsd* | *freebsd* | *dragonfly* ) + SONAMEFLAG="-Wl,-soname," + ;; + *openbsd*) + SONAMEFLAG="-Wl,-soname," + ;; + *irix*) + SONAMEFLAG="-Wl,-soname," + ;; + *hpux*) + SONAMEFLAG="-Wl,+h," + ;; + *osf*) + SONAMEFLAG="-Wl,-soname," + ;; + *unixware*) + SONAMEFLAG="-Wl,-soname," + ;; + *darwin*) + SONAMEFLAG="#" + ;; + *aix*) + # Not supported + SONAMEFLAG="#" + ;; + esac +]) + +AC_DEFUN([AC_LD_VERSIONSCRIPT], +[ + AC_SUBST(VERSIONSCRIPT) + VERSIONSCRIPT="" + case "$host_os" in + *linux*|*gnu*) + VERSIONSCRIPT="-Wl,--version-script" + ;; + *solaris*) + if test "${GCC}" = "yes"; then + VERSIONSCRIPT="-Wl,--version-script" + fi + ;; + esac +]) + +AC_DEFUN([AC_LIBREPLACE_MDLD], +[ + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_LINKER]) + MDLD="$LD_SHLIB_LINKER" + AC_SUBST(MDLD) +]) + +AC_DEFUN([AC_LIBREPLACE_LD_SHLIB_ALLOW_UNDEF_FLAG], +[ + LD_ALLOW_SHLIB_UNDEF_FLAG="" + + case "$host_os" in + *linux*|*gnu*) + LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,--allow-shlib-undefined" + ;; + *osf*) + LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,-expect_unresolved,\"*\"" + ;; + *darwin*) + LD_SHLIB_ALLOW_UNDEF_FLAG="-undefined dynamic_lookup" + ;; + *aix*) + LD_SHLIB_ALLOW_UNDEF_FLAG="-Wl,-bnoentry" + ;; + esac + + AC_SUBST(LD_SHLIB_ALLOW_UNDEF_FLAG) +]) + +AC_DEFUN([AC_LIBREPLACE_MDLD_FLAGS], +[ + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_FLAGS]) + AC_REQUIRE([AC_LIBREPLACE_LD_SHLIB_ALLOW_UNDEF_FLAG]) + MDLD_FLAGS="$LD_SHLIB_FLAGS $LD_SHLIB_ALLOW_UNDEF_FLAG" + AC_SUBST(MDLD_FLAGS) +]) + +AC_DEFUN([AC_LIBREPLACE_RUNTIME_LIB_PATH_VAR], +[ + case "$host_os" in + *linux*|*gnu*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + *bsd*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + *solaris*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + *hpux*) + LIB_PATH_VAR=SHLIB_PATH + ;; + *osf*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + *aix*) + LIB_PATH_VAR=LIBPATH + ;; + *irix*) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + *darwin*) + LIB_PATH_VAR=DYLD_LIBRARY_PATH + ;; + *) + LIB_PATH_VAR=LD_LIBRARY_PATH + ;; + esac + + AC_SUBST(LIB_PATH_VAR) +]) diff --git a/ctdb/lib/replace/libreplace_macros.m4 b/ctdb/lib/replace/libreplace_macros.m4 new file mode 100644 index 0000000000..f3753c47c2 --- /dev/null +++ b/ctdb/lib/replace/libreplace_macros.m4 @@ -0,0 +1,347 @@ +# +# This is a collection of useful autoconf macros +# + +############################################ +# Check if the compiler handles c99 struct initialization, and if not try -AC99 and -c99 flags +# Usage: LIBREPLACE_C99_STRUCT_INIT(success-action,failure-action) +# changes CFLAGS to add -AC99 or -c99 if needed +AC_DEFUN([LIBREPLACE_C99_STRUCT_INIT], +[ +saved_CFLAGS="$CFLAGS"; +c99_init=no +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers) + CFLAGS="$saved_CFLAGS"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -AC99) + CFLAGS="$saved_CFLAGS -AC99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=extc99) + CFLAGS="$saved_CFLAGS -qlanglvl=extc99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -qlanglvl=stdc99) + CFLAGS="$saved_CFLAGS -qlanglvl=stdc99"; + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi +if test x"$c99_init" = x"no"; then + AC_MSG_CHECKING(for C99 designated initializers with -c99) + CFLAGS="$saved_CFLAGS -c99" + AC_TRY_COMPILE([#include <stdio.h>], + [ struct foo {int x;char y;}; + struct foo bar = { .y = 'X', .x = 1 }; + ], + [AC_MSG_RESULT(yes); c99_init=yes],[AC_MSG_RESULT(no)]) +fi + +if test "`uname`" = "HP-UX"; then + if test "$ac_cv_c_compiler_gnu" = no; then + # special override for broken HP-UX compiler - I can't find a way to test + # this properly (its a compiler bug) + CFLAGS="$CFLAGS -AC99"; + c99_init=yes; + fi +fi + +if test x"$c99_init" = x"yes"; then + saved_CFLAGS="" + $1 +else + CFLAGS="$saved_CFLAGS" + saved_CFLAGS="" + $2 +fi +]) + +dnl AC_PROG_CC_FLAG(flag) +AC_DEFUN(AC_PROG_CC_FLAG, +[AC_CACHE_CHECK(whether ${CC-cc} accepts -$1, ac_cv_prog_cc_$1, +[echo 'void f(){}' > conftest.c +if test -z "`${CC-cc} -$1 -c conftest.c 2>&1`"; then + ac_cv_prog_cc_$1=yes +else + ac_cv_prog_cc_$1=no +fi +rm -f conftest* +])]) + +dnl see if a declaration exists for a function or variable +dnl defines HAVE_function_DECL if it exists +dnl AC_HAVE_DECL(var, includes) +AC_DEFUN(AC_HAVE_DECL, +[ + AC_CACHE_CHECK([for $1 declaration],ac_cv_have_$1_decl,[ + AC_TRY_COMPILE([$2],[int i = (int)$1], + ac_cv_have_$1_decl=yes,ac_cv_have_$1_decl=no)]) + if test x"$ac_cv_have_$1_decl" = x"yes"; then + AC_DEFINE([HAVE_]translit([$1], [a-z], [A-Z])[_DECL],1,[Whether $1() is available]) + fi +]) + + +# AC_CHECK_LIB_EXT(LIBRARY, [EXT_LIBS], [FUNCTION], +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +# [ADD-ACTION-IF-FOUND],[OTHER-LIBRARIES]) +# ------------------------------------------------------ +# +# Use a cache variable name containing both the library and function name, +# because the test really is for library $1 defining function $3, not +# just for library $1. Separate tests with the same $1 and different $3s +# may have different results. +# +# Note that using directly AS_VAR_PUSHDEF([ac_Lib], [ac_cv_lib_$1_$3]) +# is asking for trouble, since AC_CHECK_LIB($lib, fun) would give +# ac_cv_lib_$lib_fun, which is definitely not what was meant. Hence +# the AS_LITERAL_IF indirection. +# +# FIXME: This macro is extremely suspicious. It DEFINEs unconditionally, +# whatever the FUNCTION, in addition to not being a *S macro. Note +# that the cache does depend upon the function we are looking for. +# +# It is on purpose we used `ac_check_lib_ext_save_LIBS' and not just +# `ac_save_LIBS': there are many macros which don't want to see `LIBS' +# changed but still want to use AC_CHECK_LIB_EXT, so they save `LIBS'. +# And ``ac_save_LIBS' is too tempting a name, so let's leave them some +# freedom. +AC_DEFUN([AC_CHECK_LIB_EXT], +[ +AH_CHECK_LIB_EXT([$1]) +ac_check_lib_ext_save_LIBS=$LIBS +LIBS="-l$1 $$2 $7 $LIBS" +AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1])], + [AS_VAR_PUSHDEF([ac_Lib_ext], [ac_cv_lib_ext_$1''])])dnl + +m4_ifval([$3], + [ + AH_CHECK_FUNC_EXT([$3]) + AS_LITERAL_IF([$1], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1_$3])], + [AS_VAR_PUSHDEF([ac_Lib_func], [ac_cv_lib_ext_$1''_$3])])dnl + AC_CACHE_CHECK([for $3 in -l$1], ac_Lib_func, + [AC_TRY_LINK_FUNC($3, + [AS_VAR_SET(ac_Lib_func, yes); + AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_func, no); + AS_VAR_SET(ac_Lib_ext, no)]) + ]) + AS_IF([test AS_VAR_GET(ac_Lib_func) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_$3))])dnl + AS_VAR_POPDEF([ac_Lib_func])dnl + ],[ + AC_CACHE_CHECK([for -l$1], ac_Lib_ext, + [AC_TRY_LINK_FUNC([main], + [AS_VAR_SET(ac_Lib_ext, yes)], + [AS_VAR_SET(ac_Lib_ext, no)]) + ]) + ]) +LIBS=$ac_check_lib_ext_save_LIBS + +AS_IF([test AS_VAR_GET(ac_Lib_ext) = yes], + [m4_default([$4], + [AC_DEFINE_UNQUOTED(AS_TR_CPP(HAVE_LIB$1)) + case "$$2" in + *-l$1*) + ;; + *) + $2="-l$1 $$2" + ;; + esac]) + [$6] + ], + [$5])dnl +AS_VAR_POPDEF([ac_Lib_ext])dnl +])# AC_CHECK_LIB_EXT + +# AH_CHECK_LIB_EXT(LIBNAME) +# --------------------- +m4_define([AH_CHECK_LIB_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_LIB$1), + [Define to 1 if you have the `]$1[' library (-l]$1[).])]) + +dnl AC_SEARCH_LIBS_EXT(FUNCTION, SEARCH-LIBS, EXT_LIBS, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND], +dnl [OTHER-LIBRARIES]) +dnl -------------------------------------------------------- +dnl Search for a library defining FUNC, if it's not already available. +AC_DEFUN([AC_SEARCH_LIBS_EXT], +[AC_CACHE_CHECK([for library containing $1], [ac_cv_search_ext_$1], +[ +ac_func_search_ext_save_LIBS=$LIBS +ac_cv_search_ext_$1=no +AC_LINK_IFELSE([AC_LANG_CALL([], [$1])], + [ac_cv_search_ext_$1="none required"]) +if test "$ac_cv_search_ext_$1" = no; then + for ac_lib in $2; do + LIBS="-l$ac_lib $$3 $6 $ac_func_search_save_ext_LIBS" + AC_LINK_IFELSE([AC_LANG_CALL([], [$1])], + [ac_cv_search_ext_$1="-l$ac_lib" +break]) + done +fi +LIBS=$ac_func_search_ext_save_LIBS]) +AS_IF([test "$ac_cv_search_ext_$1" != no], + [test "$ac_cv_search_ext_$1" = "none required" || $3="$ac_cv_search_ext_$1 $$3" + $4], + [$5])dnl +]) + +dnl check for a function in a $LIBS and $OTHER_LIBS libraries variable. +dnl AC_CHECK_FUNC_EXT(func,OTHER_LIBS,IF-TRUE,IF-FALSE) +AC_DEFUN([AC_CHECK_FUNC_EXT], +[ + AH_CHECK_FUNC_EXT($1) + ac_check_func_ext_save_LIBS=$LIBS + LIBS="$2 $LIBS" + AS_VAR_PUSHDEF([ac_var], [ac_cv_func_ext_$1])dnl + AC_CACHE_CHECK([for $1], ac_var, + [AC_LINK_IFELSE([AC_LANG_FUNC_LINK_TRY([$1])], + [AS_VAR_SET(ac_var, yes)], + [AS_VAR_SET(ac_var, no)])]) + LIBS=$ac_check_func_ext_save_LIBS + AS_IF([test AS_VAR_GET(ac_var) = yes], + [AC_DEFINE_UNQUOTED(AS_TR_CPP([HAVE_$1])) $3], + [$4])dnl +AS_VAR_POPDEF([ac_var])dnl +])# AC_CHECK_FUNC + +# AH_CHECK_FUNC_EXT(FUNCNAME) +# --------------------- +m4_define([AH_CHECK_FUNC_EXT], +[AH_TEMPLATE(AS_TR_CPP(HAVE_$1), + [Define to 1 if you have the `]$1[' function.])]) + +dnl Define an AC_DEFINE with ifndef guard. +dnl AC_N_DEFINE(VARIABLE [, VALUE]) +AC_DEFUN([AC_N_DEFINE], +[ +AH_VERBATIM([$1], [ +#ifndef $1 +# undef $1 +#endif +]) + + cat >>confdefs.h <<\EOF +#ifndef $1 +[#define] $1 m4_if($#, 1, 1, [$2]) +#endif +EOF +]) + +dnl Add an #include +dnl AC_ADD_INCLUDE(VARIABLE) +define(AC_ADD_INCLUDE, +[cat >> confdefs.h <<\EOF +[#include] $1 +EOF +]) + +dnl remove an #include +dnl AC_REMOVE_INCLUDE(VARIABLE) +define(AC_REMOVE_INCLUDE, +[ +grep -v '[#include] $1' confdefs.h >confdefs.h.tmp +cat confdefs.h.tmp > confdefs.h +rm confdefs.h.tmp +]) + +dnl remove an #define +dnl AC_REMOVE_DEFINE(VARIABLE) +define(AC_REMOVE_DEFINE, +[ +grep -v '[#define] $1 ' confdefs.h |grep -v '[#define] $1[$]'>confdefs.h.tmp +cat confdefs.h.tmp > confdefs.h +rm confdefs.h.tmp +]) + +dnl AS_HELP_STRING is not available in autoconf 2.57, and AC_HELP_STRING is deprecated +dnl in autoconf 2.59, so define AS_HELP_STRING to be AC_HELP_STRING unless it is already +dnl defined. +m4_ifdef([AS_HELP_STRING], , [m4_define([AS_HELP_STRING], m4_defn([AC_HELP_STRING]))]) + +dnl check if the prototype in the header matches the given one +dnl AC_VERIFY_C_PROTOTYPE(prototype,functionbody,[IF-TRUE].[IF-FALSE],[extraheaders]) +AC_DEFUN(AC_VERIFY_C_PROTOTYPE, +[AC_CACHE_CHECK([for prototype $1], AS_TR_SH([ac_cv_c_prototype_$1]), + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + AC_INCLUDES_DEFAULT + $5 + $1 + { + $2 + } + ])],[ + eval AS_TR_SH([ac_cv_c_prototype_$1])=yes + ],[ + eval AS_TR_SH([ac_cv_c_prototype_$1])=no + ]) +) +AS_IF([eval test $AS_TR_SH([ac_cv_c_prototype_$1]) = yes],[$3],[$4]) +]) + +AC_DEFUN(LIBREPLACE_PROVIDE_HEADER, +[AC_CHECK_HEADER([$1], + [ AC_CONFIG_COMMANDS(rm-$1, [rm -f $libreplacedir/$1], [libreplacedir=$libreplacedir]) ], + [ AC_CONFIG_COMMANDS(mk-$1, [echo "#include \"replace.h\"" > $libreplacedir/$1], [libreplacedir=$libreplacedir]) ] + ) +]) + +dnl AC_HAVE_TYPE(TYPE,INCLUDES) +AC_DEFUN([AC_HAVE_TYPE], [ +AC_REQUIRE([AC_HEADER_STDC]) +cv=`echo "$1" | sed 'y%./+- %__p__%'` +AC_MSG_CHECKING(for $1) +AC_CACHE_VAL([ac_cv_type_$cv], +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +AC_INCLUDES_DEFAULT +$2]], +[[$1 foo;]])], +[eval "ac_cv_type_$cv=yes"], +[eval "ac_cv_type_$cv=no"]))dnl +ac_foo=`eval echo \\$ac_cv_type_$cv` +AC_MSG_RESULT($ac_foo) +if test "$ac_foo" = yes; then + ac_tr_hdr=HAVE_`echo $1 | sed 'y%abcdefghijklmnopqrstuvwxyz./- %ABCDEFGHIJKLMNOPQRSTUVWXYZ____%'` +if false; then + AC_CHECK_TYPES($1) +fi + AC_DEFINE_UNQUOTED($ac_tr_hdr, 1, [Define if you have type `$1']) +fi +]) + +# AC_CHECK_VALUEOF(TYPE, [INCLUDES = DEFAULT-INCLUDES]) +# --------------------------------------------------------------- +AC_DEFUN([AC_CHECK_VALUEOF], +[AS_LITERAL_IF(m4_translit([[$1]], [*], [p]), [], + [m4_fatal([$0: requires literal arguments])])]dnl +[ +_AC_CACHE_CHECK_INT([value of $1], [AS_TR_SH([ac_cv_valueof_$1])], + [(long int) ($1)], + [AC_INCLUDES_DEFAULT([$2])], + []) + +AC_DEFINE_UNQUOTED(AS_TR_CPP(valueof_$1), $AS_TR_SH([ac_cv_valueof_$1]), + [The value of `$1'.]) +])# AC_CHECK_VALUEOF diff --git a/ctdb/lib/replace/libreplace_network.m4 b/ctdb/lib/replace/libreplace_network.m4 new file mode 100644 index 0000000000..bb2a84324e --- /dev/null +++ b/ctdb/lib/replace/libreplace_network.m4 @@ -0,0 +1,503 @@ +AC_DEFUN_ONCE(AC_LIBREPLACE_NETWORK_CHECKS, +[ +echo "LIBREPLACE_NETWORK_CHECKS: START" + +AC_DEFINE(LIBREPLACE_NETWORK_CHECKS, 1, [LIBREPLACE_NETWORK_CHECKS were used]) +LIBREPLACE_NETWORK_OBJS="" +LIBREPLACE_NETWORK_LIBS="" + +AC_CHECK_HEADERS(sys/socket.h netinet/in.h netdb.h arpa/inet.h) +AC_CHECK_HEADERS(netinet/in_systm.h) +AC_CHECK_HEADERS([netinet/ip.h], [], [],[ + #include <sys/types.h> + #ifdef HAVE_NETINET_IN_H + #include <netinet/in.h> + #endif + #ifdef HAVE_NETINET_IN_SYSTM_H + #include <netinet/in_systm.h> + #endif +]) +AC_CHECK_HEADERS(netinet/tcp.h netinet/in_ip.h) +AC_CHECK_HEADERS(sys/sockio.h sys/un.h) +AC_CHECK_HEADERS(sys/uio.h) + +dnl we need to check that net/if.h really can be used, to cope with hpux +dnl where including it always fails +AC_CACHE_CHECK([for usable net/if.h],libreplace_cv_USABLE_NET_IF_H,[ + AC_COMPILE_IFELSE([AC_LANG_SOURCE([ + AC_INCLUDES_DEFAULT + #if HAVE_SYS_SOCKET_H + # include <sys/socket.h> + #endif + #include <net/if.h> + int main(void) {return 0;}])], + [libreplace_cv_USABLE_NET_IF_H=yes], + [libreplace_cv_USABLE_NET_IF_H=no] + ) +]) +if test x"$libreplace_cv_USABLE_NET_IF_H" = x"yes";then + AC_DEFINE(HAVE_NET_IF_H, 1, usability of net/if.h) +fi + +AC_HAVE_TYPE([socklen_t],[#include <sys/socket.h>]) +AC_HAVE_TYPE([sa_family_t],[#include <sys/socket.h>]) +AC_HAVE_TYPE([struct addrinfo], [#include <netdb.h>]) +AC_HAVE_TYPE([struct sockaddr], [#include <sys/socket.h>]) +AC_HAVE_TYPE([struct sockaddr_storage], [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +]) +AC_HAVE_TYPE([struct sockaddr_in6], [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> +]) + +if test x"$ac_cv_type_struct_sockaddr_storage" = x"yes"; then +AC_CHECK_MEMBER(struct sockaddr_storage.ss_family, + AC_DEFINE(HAVE_SS_FAMILY, 1, [Defined if struct sockaddr_storage has ss_family field]),, + [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + ]) + +if test x"$ac_cv_member_struct_sockaddr_storage_ss_family" != x"yes"; then +AC_CHECK_MEMBER(struct sockaddr_storage.__ss_family, + AC_DEFINE(HAVE___SS_FAMILY, 1, [Defined if struct sockaddr_storage has __ss_family field]),, + [ +#include <sys/socket.h> +#include <sys/types.h> +#include <netinet/in.h> + ]) +fi +fi + +AC_CACHE_CHECK([for sin_len in sock],libreplace_cv_HAVE_SOCK_SIN_LEN,[ + AC_TRY_COMPILE( + [ +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> + ],[ +struct sockaddr_in sock; sock.sin_len = sizeof(sock); + ],[ + libreplace_cv_HAVE_SOCK_SIN_LEN=yes + ],[ + libreplace_cv_HAVE_SOCK_SIN_LEN=no + ]) +]) +if test x"$libreplace_cv_HAVE_SOCK_SIN_LEN" = x"yes"; then + AC_DEFINE(HAVE_SOCK_SIN_LEN,1,[Whether the sockaddr_in struct has a sin_len property]) +fi + +############################################ +# check for unix domain sockets +AC_CACHE_CHECK([for unix domain sockets],libreplace_cv_HAVE_UNIXSOCKET,[ + AC_TRY_COMPILE([ +#include <sys/types.h> +#include <stdlib.h> +#include <stddef.h> +#include <sys/socket.h> +#include <sys/un.h> + ],[ +struct sockaddr_un sunaddr; +sunaddr.sun_family = AF_UNIX; + ],[ + libreplace_cv_HAVE_UNIXSOCKET=yes + ],[ + libreplace_cv_HAVE_UNIXSOCKET=no + ]) +]) +if test x"$libreplace_cv_HAVE_UNIXSOCKET" = x"yes"; then + AC_DEFINE(HAVE_UNIXSOCKET,1,[If we need to build with unixscoket support]) +fi + +dnl The following test is roughly taken from the cvs sources. +dnl +dnl If we can't find connect, try looking in -lsocket, -lnsl, and -linet. +dnl The Irix 5 libc.so has connect and gethostbyname, but Irix 5 also has +dnl libsocket.so which has a bad implementation of gethostbyname (it +dnl only looks in /etc/hosts), so we only look for -lsocket if we need +dnl it. +AC_CHECK_FUNCS(connect) +if test x"$ac_cv_func_connect" = x"no"; then + AC_CHECK_LIB_EXT(nsl_s, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(nsl, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(socket, LIBREPLACE_NETWORK_LIBS, connect) + AC_CHECK_LIB_EXT(inet, LIBREPLACE_NETWORK_LIBS, connect) + dnl We can't just call AC_CHECK_FUNCS(connect) here, + dnl because the value has been cached. + if test x"$ac_cv_lib_ext_nsl_s_connect" = x"yes" || + test x"$ac_cv_lib_ext_nsl_connect" = x"yes" || + test x"$ac_cv_lib_ext_socket_connect" = x"yes" || + test x"$ac_cv_lib_ext_inet_connect" = x"yes" + then + AC_DEFINE(HAVE_CONNECT,1,[Whether the system has connect()]) + fi +fi + +AC_CHECK_FUNCS(gethostbyname) +if test x"$ac_cv_func_gethostbyname" = x"no"; then + AC_CHECK_LIB_EXT(nsl_s, LIBREPLACE_NETWORK_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(nsl, LIBREPLACE_NETWORK_LIBS, gethostbyname) + AC_CHECK_LIB_EXT(socket, LIBREPLACE_NETWORK_LIBS, gethostbyname) + dnl We can't just call AC_CHECK_FUNCS(gethostbyname) here, + dnl because the value has been cached. + if test x"$ac_cv_lib_ext_nsl_s_gethostbyname" = x"yes" || + test x"$ac_cv_lib_ext_nsl_gethostbyname" = x"yes" || + test x"$ac_cv_lib_ext_socket_gethostbyname" = x"yes" + then + AC_DEFINE(HAVE_GETHOSTBYNAME,1, + [Whether the system has gethostbyname()]) + fi +fi + +dnl HP-UX has if_nametoindex in -lipv6 +AC_CHECK_FUNCS(if_nametoindex) +if test x"$ac_cv_func_if_nametoindex" = x"no"; then + AC_CHECK_LIB_EXT(ipv6, LIBREPLACE_NETWORK_LIBS, if_nametoindex) + dnl We can't just call AC_CHECK_FUNCS(if_nametoindex) here, + dnl because the value has been cached. + if test x"$ac_cv_lib_ext_ipv6_if_nametoindex" = x"yes" + then + AC_DEFINE(HAVE_IF_NAMETOINDEX, 1, + [Whether the system has if_nametoindex()]) + fi +fi + +# The following tests need LIBS="${LIBREPLACE_NETWORK_LIBS}" +old_LIBS=$LIBS +LIBS="${LIBREPLACE_NETWORK_LIBS}" +libreplace_SAVE_CPPFLAGS="$CPPFLAGS" +CPPFLAGS="$CPPFLAGS -I$libreplacedir" + +AC_CHECK_FUNCS(socketpair,[],[LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/socketpair.o"]) + +AC_CACHE_CHECK([for broken inet_ntoa],libreplace_cv_REPLACE_INET_NTOA,[ +AC_TRY_RUN([ +#include <stdio.h> +#include <unistd.h> +#include <sys/types.h> +#include <netinet/in.h> +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif +main() { struct in_addr ip; ip.s_addr = 0x12345678; +if (strcmp(inet_ntoa(ip),"18.52.86.120") && + strcmp(inet_ntoa(ip),"120.86.52.18")) { exit(0); } +exit(1);}], + libreplace_cv_REPLACE_INET_NTOA=yes,libreplace_cv_REPLACE_INET_NTOA=no,libreplace_cv_REPLACE_INET_NTOA=cross)]) + +AC_CHECK_FUNCS(inet_ntoa,[],[libreplace_cv_REPLACE_INET_NTOA=yes]) +if test x"$libreplace_cv_REPLACE_INET_NTOA" = x"yes"; then + AC_DEFINE(REPLACE_INET_NTOA,1,[Whether inet_ntoa should be replaced]) + LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/inet_ntoa.o" +fi + +AC_CHECK_FUNCS(inet_aton,[],[LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/inet_aton.o"]) + +AC_CHECK_FUNCS(inet_ntop,[],[LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/inet_ntop.o"]) + +AC_CHECK_FUNCS(inet_pton,[],[LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/inet_pton.o"]) + +dnl test for getaddrinfo/getnameinfo +AC_CACHE_CHECK([for getaddrinfo],libreplace_cv_HAVE_GETADDRINFO,[ +AC_TRY_LINK([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <sys/socket.h> +#include <netdb.h>], +[ +struct sockaddr sa; +struct addrinfo *ai = NULL; +int ret = getaddrinfo(NULL, NULL, NULL, &ai); +if (ret != 0) { + const char *es = gai_strerror(ret); +} +freeaddrinfo(ai); +ret = getnameinfo(&sa, sizeof(sa), + NULL, 0, + NULL, 0, 0); + +], +libreplace_cv_HAVE_GETADDRINFO=yes,libreplace_cv_HAVE_GETADDRINFO=no)]) + +if test x"$libreplace_cv_HAVE_GETADDRINFO" = x"yes"; then + # getaddrinfo is broken on some AIX systems + # see bug 5910, use our replacements if we detect + # a broken system. + AC_TRY_RUN([ + #include <stddef.h> + #include <sys/types.h> + #include <sys/socket.h> + #include <netdb.h> + int main(int argc, const char *argv[]) + { + struct addrinfo hints = {0,}; + struct addrinfo *ppres; + const char hostname1[] = "0.0.0.0"; + const char hostname2[] = "127.0.0.1"; + const char hostname3[] = "::"; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = + AI_NUMERICHOST|AI_PASSIVE|AI_ADDRCONFIG; + /* Test for broken flag combination on AIX. */ + if (getaddrinfo(hostname1, NULL, &hints, &ppres) == EAI_BADFLAGS) { + /* This fails on an IPv6-only box, but not with + the EAI_BADFLAGS error. */ + return 1; + } + if (getaddrinfo(hostname2, NULL, &hints, &ppres) == 0) { + /* IPv4 lookup works - good enough. */ + return 0; + } + /* Uh-oh, no IPv4. Are we IPv6-only ? */ + return getaddrinfo(hostname3, NULL, &hints, &ppres) != 0 ? 1 : 0; + }], + libreplace_cv_HAVE_GETADDRINFO=yes, + libreplace_cv_HAVE_GETADDRINFO=no) +fi + +if test x"$libreplace_cv_HAVE_GETADDRINFO" = x"yes"; then + AC_DEFINE(HAVE_GETADDRINFO,1,[Whether the system has getaddrinfo]) + AC_DEFINE(HAVE_GETNAMEINFO,1,[Whether the system has getnameinfo]) + AC_DEFINE(HAVE_FREEADDRINFO,1,[Whether the system has freeaddrinfo]) + AC_DEFINE(HAVE_GAI_STRERROR,1,[Whether the system has gai_strerror]) +else + LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/getaddrinfo.o" +fi + +AC_CHECK_HEADERS([ifaddrs.h]) + +dnl Used when getifaddrs is not available +AC_CHECK_MEMBERS([struct sockaddr.sa_len], + [AC_DEFINE(HAVE_SOCKADDR_SA_LEN, 1, [Whether struct sockaddr has a sa_len member])], + [], + [#include <sys/socket.h>]) + +dnl test for getifaddrs and freeifaddrs +AC_CACHE_CHECK([for getifaddrs and freeifaddrs],libreplace_cv_HAVE_GETIFADDRS,[ +AC_TRY_LINK([ +#include <sys/types.h> +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <ifaddrs.h> +#include <netdb.h>], +[ +struct ifaddrs *ifp = NULL; +int ret = getifaddrs (&ifp); +freeifaddrs(ifp); +], +libreplace_cv_HAVE_GETIFADDRS=yes,libreplace_cv_HAVE_GETIFADDRS=no)]) +if test x"$libreplace_cv_HAVE_GETIFADDRS" = x"yes"; then + AC_DEFINE(HAVE_GETIFADDRS,1,[Whether the system has getifaddrs]) + AC_DEFINE(HAVE_FREEIFADDRS,1,[Whether the system has freeifaddrs]) + AC_DEFINE(HAVE_STRUCT_IFADDRS,1,[Whether struct ifaddrs is available]) +fi + +################## +# look for a method of finding the list of network interfaces +iface=no; +AC_CACHE_CHECK([for iface getifaddrs],libreplace_cv_HAVE_IFACE_GETIFADDRS,[ +AC_TRY_RUN([ +#define HAVE_IFACE_GETIFADDRS 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_GETIFADDRS=yes,libreplace_cv_HAVE_IFACE_GETIFADDRS=no,libreplace_cv_HAVE_IFACE_GETIFADDRS=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_GETIFADDRS" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_GETIFADDRS,1,[Whether iface getifaddrs is available]) +else + LIBREPLACE_NETWORK_OBJS="${LIBREPLACE_NETWORK_OBJS} $libreplacedir/getifaddrs.o" +fi + + +if test $iface = no; then +AC_CACHE_CHECK([for iface AIX],libreplace_cv_HAVE_IFACE_AIX,[ +AC_TRY_RUN([ +#define HAVE_IFACE_AIX 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#undef _XOPEN_SOURCE_EXTENDED +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_AIX=yes,libreplace_cv_HAVE_IFACE_AIX=no,libreplace_cv_HAVE_IFACE_AIX=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_AIX" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_AIX,1,[Whether iface AIX is available]) +fi +fi + + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifconf],libreplace_cv_HAVE_IFACE_IFCONF,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFCONF 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_IFCONF=yes,libreplace_cv_HAVE_IFACE_IFCONF=no,libreplace_cv_HAVE_IFACE_IFCONF=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_IFCONF" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFCONF,1,[Whether iface ifconf is available]) +fi +fi + +if test $iface = no; then +AC_CACHE_CHECK([for iface ifreq],libreplace_cv_HAVE_IFACE_IFREQ,[ +AC_TRY_RUN([ +#define HAVE_IFACE_IFREQ 1 +#define NO_CONFIG_H 1 +#define AUTOCONF_TEST 1 +#define SOCKET_WRAPPER_NOT_REPLACE +#include "$libreplacedir/replace.c" +#include "$libreplacedir/inet_ntop.c" +#include "$libreplacedir/snprintf.c" +#include "$libreplacedir/getifaddrs.c" +#define getifaddrs_test main +#include "$libreplacedir/test/getifaddrs.c"], + libreplace_cv_HAVE_IFACE_IFREQ=yes,libreplace_cv_HAVE_IFACE_IFREQ=no,libreplace_cv_HAVE_IFACE_IFREQ=cross)]) +if test x"$libreplace_cv_HAVE_IFACE_IFREQ" = x"yes"; then + iface=yes;AC_DEFINE(HAVE_IFACE_IFREQ,1,[Whether iface ifreq is available]) +fi +fi + +dnl Some old Linux systems have broken header files and +dnl miss the IPV6_V6ONLY define in netinet/in.h, +dnl but have it in linux/in6.h. +dnl We can't include both files so we just check if the value +dnl if defined and do the replacement in system/network.h +AC_CACHE_CHECK([for IPV6_V6ONLY support],libreplace_cv_HAVE_IPV6_V6ONLY,[ + AC_TRY_COMPILE([ +#include <stdlib.h> /* for NULL */ +#include <sys/socket.h> +#include <sys/types.h> +#include <netdb.h> +#include <netinet/in.h> + ], + [ +#ifndef IPV6_V6ONLY +#error no IPV6_V6ONLY +#endif + ],[ + libreplace_cv_HAVE_IPV6_V6ONLY=yes + ],[ + libreplace_cv_HAVE_IPV6_V6ONLY=no + ]) +]) +if test x"$libreplace_cv_HAVE_IPV6_V6ONLY" != x"yes"; then + dnl test for IPV6_V6ONLY + AC_CACHE_CHECK([for IPV6_V6ONLY in linux/in6.h],libreplace_cv_HAVE_LINUX_IPV6_V6ONLY_26,[ + AC_TRY_COMPILE([ + #include <linux/in6.h> + ], + [ + #if (IPV6_V6ONLY != 26) + #error no linux IPV6_V6ONLY + #endif + ],[ + libreplace_cv_HAVE_LINUX_IPV6_V6ONLY_26=yes + ],[ + libreplace_cv_HAVE_LINUX_IPV6_V6ONLY_26=no + ]) + ]) + if test x"$libreplace_cv_HAVE_LINUX_IPV6_V6ONLY_26" = x"yes"; then + AC_DEFINE(HAVE_LINUX_IPV6_V6ONLY_26,1,[Whether the system has IPV6_V6ONLY in linux/in6.h]) + fi +fi + +dnl test for ipv6 +AC_CACHE_CHECK([for ipv6 support],libreplace_cv_HAVE_IPV6,[ + AC_TRY_LINK([ +#include <stdlib.h> /* for NULL */ +#include <sys/socket.h> +#include <sys/types.h> +#include <netdb.h> +#include <netinet/in.h> + ], + [ +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)); +} + ],[ + libreplace_cv_HAVE_IPV6=yes + ],[ + libreplace_cv_HAVE_IPV6=no + ]) +]) +if test x"$libreplace_cv_HAVE_IPV6" = x"yes"; then + AC_DEFINE(HAVE_IPV6,1,[Whether the system has IPv6 support]) +fi + +LIBS=$old_LIBS +CPPFLAGS="$libreplace_SAVE_CPPFLAGS" + +AC_CACHE_CHECK([for SO_PEERCRED],libreplace_cv_HAVE_PEERCRED,[ +AC_TRY_COMPILE([#include <sys/types.h> +#include <sys/socket.h>], +[struct ucred cred; + socklen_t cred_len; + int ret = getsockopt(0, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len); +], +libreplace_cv_HAVE_PEERCRED=yes,libreplace_cv_HAVE_PEERCRED=no,libreplace_cv_HAVE_PEERCRED=cross)]) +if test x"$libreplace_cv_HAVE_PEERCRED" = x"yes"; then + AC_DEFINE(HAVE_PEERCRED,1,[Whether we can use SO_PEERCRED to get socket credentials]) +fi + +AC_CACHE_CHECK([for getpeereid],libreplace_cv_HAVE_GETPEEREID,[ +AC_TRY_LINK([#include <sys/types.h> +#include <unistd.h>], +[uid_t uid; gid_t gid; int ret; + ret = getpeereid(0, &uid, &gid); +], +libreplace_cv_HAVE_GETPEEREID=yes,libreplace_cv_HAVE_GETPEEREID=no)]) +if test x"$libreplace_cv_HAVE_GETPEEREID" = xyes; then + AC_DEFINE(HAVE_GETPEEREID,1, + [Whether we have getpeereid to get socket credentials]) +fi + +LIBREPLACEOBJ="${LIBREPLACEOBJ} ${LIBREPLACE_NETWORK_OBJS}" + +echo "LIBREPLACE_NETWORK_CHECKS: END" +]) dnl end AC_LIBREPLACE_NETWORK_CHECKS diff --git a/ctdb/lib/replace/poll.c b/ctdb/lib/replace/poll.c new file mode 100644 index 0000000000..1105617b63 --- /dev/null +++ b/ctdb/lib/replace/poll.c @@ -0,0 +1,139 @@ +/* + Unix SMB/CIFS implementation. + poll.c - poll wrapper + + This file is based on code from libssh (LGPLv2.1+ at the time it + was downloaded), thus the following copyrights: + + Copyright (c) 2009-2010 by Andreas Schneider <mail@cynapses.org> + Copyright (c) 2003-2009 by Aris Adamantiadis + Copyright (c) 2009 Aleksandar Kanchev + Copyright (C) Volker Lendecke 2011 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/select.h" +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + + +int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout) +{ + fd_set rfds, wfds, efds; + struct timeval tv, *ptv; + int max_fd; + int rc; + nfds_t i; + + if ((fds == NULL) && (nfds != 0)) { + errno = EFAULT; + return -1; + } + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + rc = 0; + max_fd = 0; + + /* compute fd_sets and find largest descriptor */ + for (i = 0; i < nfds; i++) { + if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) { + fds[i].revents = POLLNVAL; + continue; + } + + if (fds[i].events & (POLLIN | POLLRDNORM)) { + FD_SET(fds[i].fd, &rfds); + } + if (fds[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND)) { + FD_SET(fds[i].fd, &wfds); + } + if (fds[i].events & (POLLPRI | POLLRDBAND)) { + FD_SET(fds[i].fd, &efds); + } + if (fds[i].fd > max_fd && + (fds[i].events & (POLLIN | POLLOUT | POLLPRI | + POLLRDNORM | POLLRDBAND | + POLLWRNORM | POLLWRBAND))) { + max_fd = fds[i].fd; + } + } + + if (timeout < 0) { + ptv = NULL; + } else { + ptv = &tv; + if (timeout == 0) { + tv.tv_sec = 0; + tv.tv_usec = 0; + } else { + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + } + } + + rc = select(max_fd + 1, &rfds, &wfds, &efds, ptv); + if (rc < 0) { + return -1; + } + + for (rc = 0, i = 0; i < nfds; i++) { + if ((fds[i].fd < 0) || (fds[i].fd >= FD_SETSIZE)) { + continue; + } + + fds[i].revents = 0; + + if (FD_ISSET(fds[i].fd, &rfds)) { + int err = errno; + int available = 0; + int ret; + + /* support for POLLHUP */ + ret = ioctl(fds[i].fd, FIONREAD, &available); + if ((ret == -1) || (available == 0)) { + fds[i].revents |= POLLHUP; + } else { + fds[i].revents |= fds[i].events + & (POLLIN | POLLRDNORM); + } + + errno = err; + } + if (FD_ISSET(fds[i].fd, &wfds)) { + fds[i].revents |= fds[i].events + & (POLLOUT | POLLWRNORM | POLLWRBAND); + } + if (FD_ISSET(fds[i].fd, &efds)) { + fds[i].revents |= fds[i].events + & (POLLPRI | POLLRDBAND); + } + if (fds[i].revents & ~POLLHUP) { + rc++; + } + } + return rc; +} diff --git a/ctdb/lib/replace/repdir.m4 b/ctdb/lib/replace/repdir.m4 new file mode 100644 index 0000000000..682ab44c56 --- /dev/null +++ b/ctdb/lib/replace/repdir.m4 @@ -0,0 +1,81 @@ +AC_CACHE_CHECK([for broken readdir],libreplace_cv_READDIR_NEEDED,[ + AC_TRY_RUN([ +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_NEEDED=no], + [libreplace_cv_READDIR_NEEDED=yes], + [libreplace_cv_READDIR_NEEDED="assuming not"]) +]) + +AC_CHECK_FUNCS(dirfd) +AC_HAVE_DECL(dirfd, [#include <dirent.h>]) + +# +# try to replace with getdirentries() if needed +# +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then +AC_CHECK_FUNCS(getdirentries) +AC_VERIFY_C_PROTOTYPE([long telldir(const DIR *dir)], + [ + return 0; + ],[ + AC_DEFINE(TELLDIR_TAKES_CONST_DIR, 1, [Whether telldir takes a const pointer]) + ],[],[ + #include <dirent.h> + ]) + +AC_VERIFY_C_PROTOTYPE([int seekdir(DIR *dir, long ofs)], + [ + return 0; + ],[ + AC_DEFINE(SEEKDIR_RETURNS_INT, 1, [Whether seekdir returns an int]) + ],[],[ + #include <dirent.h> + ]) +AC_CACHE_CHECK([for replacing readdir using getdirentries()],libreplace_cv_READDIR_GETDIRENTRIES,[ + AC_TRY_RUN([ +#define _LIBREPLACE_REPLACE_H +#include "$libreplacedir/repdir_getdirentries.c" +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_GETDIRENTRIES=yes], + [libreplace_cv_READDIR_GETDIRENTRIES=no]) +]) +fi +if test x"$libreplace_cv_READDIR_GETDIRENTRIES" = x"yes"; then + AC_DEFINE(REPLACE_READDIR,1,[replace readdir]) + AC_DEFINE(REPLACE_READDIR_GETDIRENTRIES,1,[replace readdir using getdirentries()]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/repdir_getdirentries.o" + libreplace_cv_READDIR_NEEDED=no +fi + +# +# try to replace with getdents() if needed +# +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then +AC_CHECK_FUNCS(getdents) +AC_CACHE_CHECK([for replacing readdir using getdents()],libreplace_cv_READDIR_GETDENTS,[ + AC_TRY_RUN([ +#define _LIBREPLACE_REPLACE_H +#error _donot_use_getdents_replacement_anymore +#include "$libreplacedir/repdir_getdents.c" +#define test_readdir_os2_delete main +#include "$libreplacedir/test/os2_delete.c"], + [libreplace_cv_READDIR_GETDENTS=yes], + [libreplace_cv_READDIR_GETDENTS=no]) +]) +fi +if test x"$libreplace_cv_READDIR_GETDENTS" = x"yes"; then + AC_DEFINE(REPLACE_READDIR,1,[replace readdir]) + AC_DEFINE(REPLACE_READDIR_GETDENTS,1,[replace readdir using getdents()]) + LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/repdir_getdents.o" + libreplace_cv_READDIR_NEEDED=no +fi + +AC_MSG_CHECKING([a usable readdir()]) +if test x"$libreplace_cv_READDIR_NEEDED" = x"yes"; then + AC_MSG_RESULT(no) + AC_MSG_WARN([the provided readdir() is broken]) +else + AC_MSG_RESULT(yes) +fi diff --git a/ctdb/lib/replace/repdir_getdents.c b/ctdb/lib/replace/repdir_getdents.c new file mode 100644 index 0000000000..afc634a796 --- /dev/null +++ b/ctdb/lib/replace/repdir_getdents.c @@ -0,0 +1,166 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +/* + a replacement for opendir/readdir/telldir/seekdir/closedir for BSD systems + + This is needed because the existing directory handling in FreeBSD + and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() + on files in a directory where telldir() has been used. On a block + boundary it will occasionally miss a file when seekdir() is used to + return to a position previously recorded with telldir(). + + This also fixes a severe performance and memory usage problem with + telldir() on BSD systems. Each call to telldir() in BSD adds an + entry to a linked list, and those entries are cleaned up on + closedir(). This means with a large directory closedir() can take an + arbitrary amount of time, causing network timeouts as millions of + telldir() entries are freed + + Note! This replacement code is not portable. It relies on getdents() + always leaving the file descriptor at a seek offset that is a + multiple of DIR_BUF_SIZE. If the code detects that this doesn't + happen then it will abort(). It also does not handle directories + with offsets larger than can be stored in a long, + + This code is available under other free software licenses as + well. Contact the author. +*/ + +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> + +#define DIR_BUF_BITS 9 +#define DIR_BUF_SIZE (1<<DIR_BUF_BITS) + +struct dir_buf { + int fd; + int nbytes, ofs; + off_t seekpos; + char buf[DIR_BUF_SIZE]; +}; + +DIR *opendir(const char *dname) +{ + struct dir_buf *d; + struct stat sb; + d = malloc(sizeof(*d)); + if (d == NULL) { + errno = ENOMEM; + return NULL; + } + d->fd = open(dname, O_RDONLY); + if (d->fd == -1) { + free(d); + return NULL; + } + if (fstat(d->fd, &sb) < 0) { + close(d->fd); + free(d); + return NULL; + } + if (!S_ISDIR(sb.st_mode)) { + close(d->fd); + free(d); + errno = ENOTDIR; + return NULL; + } + d->ofs = 0; + d->seekpos = 0; + d->nbytes = 0; + return (DIR *)d; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + struct dirent *de; + + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + } + if (d->ofs >= d->nbytes) { + return NULL; + } + de = (struct dirent *)&d->buf[d->ofs]; + d->ofs += de->d_reclen; + return de; +} + +long telldir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->ofs = 0; + d->nbytes = 0; + } + /* this relies on seekpos always being a multiple of + DIR_BUF_SIZE. Is that always true on BSD systems? */ + if (d->seekpos & (DIR_BUF_SIZE-1)) { + abort(); + } + return d->seekpos + d->ofs; +} + +void seekdir(DIR *dir, long ofs) +{ + struct dir_buf *d = (struct dir_buf *)dir; + d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); + d->nbytes = getdents(d->fd, d->buf, DIR_BUF_SIZE); + d->ofs = 0; + while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { + if (readdir(dir) == NULL) break; + } +} + +void rewinddir(DIR *dir) +{ + seekdir(dir, 0); +} + +int closedir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + int r = close(d->fd); + if (r != 0) { + return r; + } + free(d); + return 0; +} + +#ifndef dirfd +/* darn, this is a macro on some systems. */ +int dirfd(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + return d->fd; +} +#endif diff --git a/ctdb/lib/replace/repdir_getdirentries.c b/ctdb/lib/replace/repdir_getdirentries.c new file mode 100644 index 0000000000..197e5931fc --- /dev/null +++ b/ctdb/lib/replace/repdir_getdirentries.c @@ -0,0 +1,183 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2005 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ +/* + a replacement for opendir/readdir/telldir/seekdir/closedir for BSD + systems using getdirentries + + This is needed because the existing directory handling in FreeBSD + and OpenBSD (and possibly NetBSD) doesn't correctly handle unlink() + on files in a directory where telldir() has been used. On a block + boundary it will occasionally miss a file when seekdir() is used to + return to a position previously recorded with telldir(). + + This also fixes a severe performance and memory usage problem with + telldir() on BSD systems. Each call to telldir() in BSD adds an + entry to a linked list, and those entries are cleaned up on + closedir(). This means with a large directory closedir() can take an + arbitrary amount of time, causing network timeouts as millions of + telldir() entries are freed + + Note! This replacement code is not portable. It relies on + getdirentries() always leaving the file descriptor at a seek offset + that is a multiple of DIR_BUF_SIZE. If the code detects that this + doesn't happen then it will abort(). It also does not handle + directories with offsets larger than can be stored in a long, + + This code is available under other free software licenses as + well. Contact the author. +*/ + +#include "replace.h" +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> + +#define DIR_BUF_BITS 9 +#define DIR_BUF_SIZE (1<<DIR_BUF_BITS) + +struct dir_buf { + int fd; + int nbytes, ofs; + off_t seekpos; + char buf[DIR_BUF_SIZE]; +}; + +DIR *opendir(const char *dname) +{ + struct dir_buf *d; + struct stat sb; + d = malloc(sizeof(*d)); + if (d == NULL) { + errno = ENOMEM; + return NULL; + } + d->fd = open(dname, O_RDONLY); + if (d->fd == -1) { + free(d); + return NULL; + } + if (fstat(d->fd, &sb) < 0) { + close(d->fd); + free(d); + return NULL; + } + if (!S_ISDIR(sb.st_mode)) { + close(d->fd); + free(d); + errno = ENOTDIR; + return NULL; + } + d->ofs = 0; + d->seekpos = 0; + d->nbytes = 0; + return (DIR *)d; +} + +struct dirent *readdir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + struct dirent *de; + + if (d->ofs >= d->nbytes) { + long pos; + d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos); + d->seekpos = pos; + d->ofs = 0; + } + if (d->ofs >= d->nbytes) { + return NULL; + } + de = (struct dirent *)&d->buf[d->ofs]; + d->ofs += de->d_reclen; + return de; +} + +#ifdef TELLDIR_TAKES_CONST_DIR +long telldir(const DIR *dir) +#else +long telldir(DIR *dir) +#endif +{ + struct dir_buf *d = (struct dir_buf *)dir; + if (d->ofs >= d->nbytes) { + d->seekpos = lseek(d->fd, 0, SEEK_CUR); + d->ofs = 0; + d->nbytes = 0; + } + /* this relies on seekpos always being a multiple of + DIR_BUF_SIZE. Is that always true on BSD systems? */ + if (d->seekpos & (DIR_BUF_SIZE-1)) { + abort(); + } + return d->seekpos + d->ofs; +} + +#ifdef SEEKDIR_RETURNS_INT +int seekdir(DIR *dir, long ofs) +#else +void seekdir(DIR *dir, long ofs) +#endif +{ + struct dir_buf *d = (struct dir_buf *)dir; + long pos; + d->seekpos = lseek(d->fd, ofs & ~(DIR_BUF_SIZE-1), SEEK_SET); + d->nbytes = getdirentries(d->fd, d->buf, DIR_BUF_SIZE, &pos); + d->ofs = 0; + while (d->ofs < (ofs & (DIR_BUF_SIZE-1))) { + if (readdir(dir) == NULL) break; + } +#ifdef SEEKDIR_RETURNS_INT + return -1; +#endif +} + +void rewinddir(DIR *dir) +{ + seekdir(dir, 0); +} + +int closedir(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + int r = close(d->fd); + if (r != 0) { + return r; + } + free(d); + return 0; +} + +#ifndef dirfd +/* darn, this is a macro on some systems. */ +int dirfd(DIR *dir) +{ + struct dir_buf *d = (struct dir_buf *)dir; + return d->fd; +} +#endif + + diff --git a/ctdb/lib/replace/replace-test.h b/ctdb/lib/replace/replace-test.h new file mode 100644 index 0000000000..ed8e75e3b1 --- /dev/null +++ b/ctdb/lib/replace/replace-test.h @@ -0,0 +1,9 @@ +#ifndef __LIB_REPLACE_REPLACE_TEST_H__ +#define __LIB_REPLACE_REPLACE_TEST_H__ + +int libreplace_test_strptime(void); +int test_readdir_os2_delete(void); +int getifaddrs_test(void); + +#endif /* __LIB_REPLACE_REPLACE_TEST_H__ */ + diff --git a/ctdb/lib/replace/replace-testsuite.h b/ctdb/lib/replace/replace-testsuite.h new file mode 100644 index 0000000000..b28dbec067 --- /dev/null +++ b/ctdb/lib/replace/replace-testsuite.h @@ -0,0 +1,10 @@ +#ifndef __LIB_REPLACE_REPLACE_TESTSUITE_H__ +#define __LIB_REPLACE_REPLACE_TESTSUITE_H__ + +#include <stdbool.h> +struct torture_context; + +bool torture_local_replace(struct torture_context *ctx); + +#endif /* __LIB_REPLACE_REPLACE_TESTSUITE_H__ */ + diff --git a/ctdb/lib/replace/replace.c b/ctdb/lib/replace/replace.c new file mode 100644 index 0000000000..37edb310c5 --- /dev/null +++ b/ctdb/lib/replace/replace.c @@ -0,0 +1,902 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for broken systems + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jelmer Vernooij 2005-2008 + Copyright (C) Matthieu Patou 2010 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" + +#include "system/filesys.h" +#include "system/time.h" +#include "system/network.h" +#include "system/passwd.h" +#include "system/syslog.h" +#include "system/locale.h" +#include "system/wait.h" + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +void replace_dummy(void); +void replace_dummy(void) {} + +#ifndef HAVE_FTRUNCATE + /******************************************************************* +ftruncate for operating systems that don't have it +********************************************************************/ +int rep_ftruncate(int f, off_t l) +{ +#ifdef HAVE_CHSIZE + return chsize(f,l); +#elif defined(F_FREESP) + struct flock fl; + + fl.l_whence = 0; + fl.l_len = 0; + fl.l_start = l; + fl.l_type = F_WRLCK; + return fcntl(f, F_FREESP, &fl); +#else +#error "you must have a ftruncate function" +#endif +} +#endif /* HAVE_FTRUNCATE */ + + +#ifndef HAVE_STRLCPY +/* like strncpy but does not 0 fill the buffer and always null + terminates. bufsize is the size of the destination buffer */ +size_t rep_strlcpy(char *d, const char *s, size_t bufsize) +{ + size_t len = strlen(s); + size_t ret = len; + if (bufsize <= 0) return 0; + if (len >= bufsize) len = bufsize-1; + memcpy(d, s, len); + d[len] = 0; + return ret; +} +#endif + +#ifndef HAVE_STRLCAT +/* like strncat but does not 0 fill the buffer and always null + terminates. bufsize is the length of the buffer, which should + be one more than the maximum resulting string length */ +size_t rep_strlcat(char *d, const char *s, size_t bufsize) +{ + size_t len1 = strlen(d); + size_t len2 = strlen(s); + size_t ret = len1 + len2; + + if (len1+len2 >= bufsize) { + if (bufsize < (len1+1)) { + return ret; + } + len2 = bufsize - (len1+1); + } + if (len2 > 0) { + memcpy(d+len1, s, len2); + d[len1+len2] = 0; + } + return ret; +} +#endif + +#ifndef HAVE_MKTIME +/******************************************************************* +a mktime() replacement for those who don't have it - contributed by +C.A. Lademann <cal@zls.com> +Corrections by richard.kettlewell@kewill.com +********************************************************************/ + +#define MINUTE 60 +#define HOUR 60*MINUTE +#define DAY 24*HOUR +#define YEAR 365*DAY +time_t rep_mktime(struct tm *t) +{ + struct tm *u; + time_t epoch = 0; + int n; + int mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, + y, m, i; + + if(t->tm_year < 70) + return((time_t)-1); + + n = t->tm_year + 1900 - 1; + epoch = (t->tm_year - 70) * YEAR + + ((n / 4 - n / 100 + n / 400) - (1969 / 4 - 1969 / 100 + 1969 / 400)) * DAY; + + y = t->tm_year + 1900; + m = 0; + + for(i = 0; i < t->tm_mon; i++) { + epoch += mon [m] * DAY; + if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) + epoch += DAY; + + if(++m > 11) { + m = 0; + y++; + } + } + + epoch += (t->tm_mday - 1) * DAY; + epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec; + + if((u = localtime(&epoch)) != NULL) { + t->tm_sec = u->tm_sec; + t->tm_min = u->tm_min; + t->tm_hour = u->tm_hour; + t->tm_mday = u->tm_mday; + t->tm_mon = u->tm_mon; + t->tm_year = u->tm_year; + t->tm_wday = u->tm_wday; + t->tm_yday = u->tm_yday; + t->tm_isdst = u->tm_isdst; + } + + return(epoch); +} +#endif /* !HAVE_MKTIME */ + + +#ifndef HAVE_INITGROUPS +/**************************************************************************** + some systems don't have an initgroups call +****************************************************************************/ +int rep_initgroups(char *name, gid_t id) +{ +#ifndef HAVE_SETGROUPS + /* yikes! no SETGROUPS or INITGROUPS? how can this work? */ + errno = ENOSYS; + return -1; +#else /* HAVE_SETGROUPS */ + +#include <grp.h> + + gid_t *grouplst = NULL; + int max_gr = NGROUPS_MAX; + int ret; + int i,j; + struct group *g; + char *gr; + + if((grouplst = malloc(sizeof(gid_t) * max_gr)) == NULL) { + errno = ENOMEM; + return -1; + } + + grouplst[0] = id; + i = 1; + while (i < max_gr && ((g = (struct group *)getgrent()) != (struct group *)NULL)) { + if (g->gr_gid == id) + continue; + j = 0; + gr = g->gr_mem[0]; + while (gr && (*gr != (char)NULL)) { + if (strcmp(name,gr) == 0) { + grouplst[i] = g->gr_gid; + i++; + gr = (char *)NULL; + break; + } + gr = g->gr_mem[++j]; + } + } + endgrent(); + ret = setgroups(i, grouplst); + free(grouplst); + return ret; +#endif /* HAVE_SETGROUPS */ +} +#endif /* HAVE_INITGROUPS */ + + +#ifndef HAVE_MEMMOVE +/******************************************************************* +safely copies memory, ensuring no overlap problems. +this is only used if the machine does not have its own memmove(). +this is not the fastest algorithm in town, but it will do for our +needs. +********************************************************************/ +void *rep_memmove(void *dest,const void *src,int size) +{ + unsigned long d,s; + int i; + if (dest==src || !size) return(dest); + + d = (unsigned long)dest; + s = (unsigned long)src; + + if ((d >= (s+size)) || (s >= (d+size))) { + /* no overlap */ + memcpy(dest,src,size); + return(dest); + } + + if (d < s) { + /* we can forward copy */ + if (s-d >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=0;i<size;i++) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=0;i<size;i++) cdest[i] = csrc[i]; + } + } else { + /* must backward copy */ + if (d-s >= sizeof(int) && + !(s%sizeof(int)) && + !(d%sizeof(int)) && + !(size%sizeof(int))) { + /* do it all as words */ + int *idest = (int *)dest; + int *isrc = (int *)src; + size /= sizeof(int); + for (i=size-1;i>=0;i--) idest[i] = isrc[i]; + } else { + /* simplest */ + char *cdest = (char *)dest; + char *csrc = (char *)src; + for (i=size-1;i>=0;i--) cdest[i] = csrc[i]; + } + } + return(dest); +} +#endif /* HAVE_MEMMOVE */ + +#ifndef HAVE_STRDUP +/**************************************************************************** +duplicate a string +****************************************************************************/ +char *rep_strdup(const char *s) +{ + size_t len; + char *ret; + + if (!s) return(NULL); + + len = strlen(s)+1; + ret = (char *)malloc(len); + if (!ret) return(NULL); + memcpy(ret,s,len); + return(ret); +} +#endif /* HAVE_STRDUP */ + +#ifndef HAVE_SETLINEBUF +void rep_setlinebuf(FILE *stream) +{ + setvbuf(stream, (char *)NULL, _IOLBF, 0); +} +#endif /* HAVE_SETLINEBUF */ + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) +{ + char *msg = NULL; + vasprintf(&msg, format, arglist); + if (!msg) + return; + syslog(facility_priority, "%s", msg); + free(msg); +} +#endif /* HAVE_SYSLOG */ +#endif /* HAVE_VSYSLOG */ + +#ifndef HAVE_STRNLEN +/** + Some platforms don't have strnlen +**/ + size_t rep_strnlen(const char *s, size_t max) +{ + size_t len; + + for (len = 0; len < max; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} +#endif + +#ifndef HAVE_STRNDUP +/** + Some platforms don't have strndup. +**/ +char *rep_strndup(const char *s, size_t n) +{ + char *ret; + + n = strnlen(s, n); + ret = malloc(n+1); + if (!ret) + return NULL; + memcpy(ret, s, n); + ret[n] = 0; + + return ret; +} +#endif + +#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4) +int rep_waitpid(pid_t pid,int *status,int options) +{ + return wait4(pid, status, options, NULL); +} +#endif + +#ifndef HAVE_SETEUID +int rep_seteuid(uid_t euid) +{ +#ifdef HAVE_SETRESUID + return setresuid(-1, euid, -1); +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +#ifndef HAVE_SETEGID +int rep_setegid(gid_t egid) +{ +#ifdef HAVE_SETRESGID + return setresgid(-1, egid, -1); +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +/******************************************************************* +os/2 also doesn't have chroot +********************************************************************/ +#ifndef HAVE_CHROOT +int rep_chroot(const char *dname) +{ + errno = ENOSYS; + return -1; +} +#endif + +/***************************************************************** + Possibly replace mkstemp if it is broken. +*****************************************************************/ + +#ifndef HAVE_SECURE_MKSTEMP +int rep_mkstemp(char *template) +{ + /* have a reasonable go at emulating it. Hope that + the system mktemp() isn't completely hopeless */ + mktemp(template); + if (template[0] == 0) + return -1; + return open(template, O_CREAT|O_EXCL|O_RDWR, 0600); +} +#endif + +#ifndef HAVE_MKDTEMP +char *rep_mkdtemp(char *template) +{ + char *dname; + + if ((dname = mktemp(template))) { + if (mkdir(dname, 0700) >= 0) { + return dname; + } + } + + return NULL; +} +#endif + +/***************************************************************** + Watch out: this is not thread safe. +*****************************************************************/ + +#ifndef HAVE_PREAD +ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return read(__fd, __buf, __nbytes); +} +#endif + +/***************************************************************** + Watch out: this is not thread safe. +*****************************************************************/ + +#ifndef HAVE_PWRITE +ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset) +{ + if (lseek(__fd, __offset, SEEK_SET) != __offset) { + return -1; + } + return write(__fd, __buf, __nbytes); +} +#endif + +#ifndef HAVE_STRCASESTR +char *rep_strcasestr(const char *haystack, const char *needle) +{ + const char *s; + size_t nlen = strlen(needle); + for (s=haystack;*s;s++) { + if (toupper(*needle) == toupper(*s) && + strncasecmp(s, needle, nlen) == 0) { + return (char *)((uintptr_t)s); + } + } + return NULL; +} +#endif + +#ifndef HAVE_STRTOK_R +/* based on GLIBC version, copyright Free Software Foundation */ +char *rep_strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) s = *save_ptr; + + s += strspn(s, delim); + if (*s == '\0') { + *save_ptr = s; + return NULL; + } + + token = s; + s = strpbrk(token, delim); + if (s == NULL) { + *save_ptr = token + strlen(token); + } else { + *s = '\0'; + *save_ptr = s + 1; + } + + return token; +} +#endif + + +#ifndef HAVE_STRTOLL +long long int rep_strtoll(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOQ + return strtoq(str, endptr, base); +#elif defined(HAVE___STRTOLL) + return __strtoll(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (long long int) strtol(str, endptr, base); +#else +# error "You need a strtoll function" +#endif +} +#else +#ifdef HAVE_BSD_STRTOLL +#ifdef HAVE_STRTOQ +long long int rep_strtoll(const char *str, char **endptr, int base) +{ + long long int nb = strtoq(str, endptr, base); + /* In linux EINVAL is only returned if base is not ok */ + if (errno == EINVAL) { + if (base == 0 || (base >1 && base <37)) { + /* Base was ok so it's because we were not + * able to make the convertion. + * Let's reset errno. + */ + errno = 0; + } + } + return nb; +} +#else +#error "You need the strtoq function" +#endif /* HAVE_STRTOQ */ +#endif /* HAVE_BSD_STRTOLL */ +#endif /* HAVE_STRTOLL */ + + +#ifndef HAVE_STRTOULL +unsigned long long int rep_strtoull(const char *str, char **endptr, int base) +{ +#ifdef HAVE_STRTOUQ + return strtouq(str, endptr, base); +#elif defined(HAVE___STRTOULL) + return __strtoull(str, endptr, base); +#elif SIZEOF_LONG == SIZEOF_LONG_LONG + return (unsigned long long int) strtoul(str, endptr, base); +#else +# error "You need a strtoull function" +#endif +} +#else +#ifdef HAVE_BSD_STRTOLL +#ifdef HAVE_STRTOUQ +unsigned long long int rep_strtoull(const char *str, char **endptr, int base) +{ + unsigned long long int nb = strtouq(str, endptr, base); + /* In linux EINVAL is only returned if base is not ok */ + if (errno == EINVAL) { + if (base == 0 || (base >1 && base <37)) { + /* Base was ok so it's because we were not + * able to make the convertion. + * Let's reset errno. + */ + errno = 0; + } + } + return nb; +} +#else +#error "You need the strtouq function" +#endif /* HAVE_STRTOUQ */ +#endif /* HAVE_BSD_STRTOLL */ +#endif /* HAVE_STRTOULL */ + +#ifndef HAVE_SETENV +int rep_setenv(const char *name, const char *value, int overwrite) +{ + char *p; + size_t l1, l2; + int ret; + + if (!overwrite && getenv(name)) { + return 0; + } + + l1 = strlen(name); + l2 = strlen(value); + + p = malloc(l1+l2+2); + if (p == NULL) { + return -1; + } + memcpy(p, name, l1); + p[l1] = '='; + memcpy(p+l1+1, value, l2); + p[l1+l2+1] = 0; + + ret = putenv(p); + if (ret != 0) { + free(p); + } + + return ret; +} +#endif + +#ifndef HAVE_UNSETENV +int rep_unsetenv(const char *name) +{ + extern char **environ; + size_t len = strlen(name); + size_t i, count; + + if (environ == NULL || getenv(name) == NULL) { + return 0; + } + + for (i=0;environ[i];i++) /* noop */ ; + + count=i; + + for (i=0;i<count;) { + if (strncmp(environ[i], name, len) == 0 && environ[i][len] == '=') { + /* note: we do _not_ free the old variable here. It is unsafe to + do so, as the pointer may not have come from malloc */ + memmove(&environ[i], &environ[i+1], (count-i)*sizeof(char *)); + count--; + } else { + i++; + } + } + + return 0; +} +#endif + +#ifndef HAVE_UTIME +int rep_utime(const char *filename, const struct utimbuf *buf) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_UTIMES +int rep_utimes(const char *filename, const struct timeval tv[2]) +{ + struct utimbuf u; + + u.actime = tv[0].tv_sec; + if (tv[0].tv_usec > 500000) { + u.actime += 1; + } + + u.modtime = tv[1].tv_sec; + if (tv[1].tv_usec > 500000) { + u.modtime += 1; + } + + return utime(filename, &u); +} +#endif + +#ifndef HAVE_DUP2 +int rep_dup2(int oldfd, int newfd) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_CHOWN +/** +chown isn't used much but OS/2 doesn't have it +**/ +int rep_chown(const char *fname, uid_t uid, gid_t gid) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_LINK +int rep_link(const char *oldpath, const char *newpath) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_READLINK +int rep_readlink(const char *path, char *buf, size_t bufsiz) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_SYMLINK +int rep_symlink(const char *oldpath, const char *newpath) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_LCHOWN +int rep_lchown(const char *fname,uid_t uid,gid_t gid) +{ + errno = ENOSYS; + return -1; +} +#endif + +#ifndef HAVE_REALPATH +char *rep_realpath(const char *path, char *resolved_path) +{ + /* As realpath is not a system call we can't return ENOSYS. */ + errno = EINVAL; + return NULL; +} +#endif + + +#ifndef HAVE_MEMMEM +void *rep_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen) +{ + if (needlelen == 0) { + return discard_const(haystack); + } + while (haystacklen >= needlelen) { + char *p = (char *)memchr(haystack, *(const char *)needle, + haystacklen-(needlelen-1)); + if (!p) return NULL; + if (memcmp(p, needle, needlelen) == 0) { + return p; + } + haystack = p+1; + haystacklen -= (p - (const char *)haystack) + 1; + } + return NULL; +} +#endif + +#if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF) +int rep_vdprintf(int fd, const char *format, va_list ap) +{ + char *s = NULL; + int ret; + + vasprintf(&s, format, ap); + if (s == NULL) { + errno = ENOMEM; + return -1; + } + ret = write(fd, s, strlen(s)); + free(s); + return ret; +} +#endif + +#if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF) +int rep_dprintf(int fd, const char *format, ...) +{ + int ret; + va_list ap; + + va_start(ap, format); + ret = vdprintf(fd, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifndef HAVE_GET_CURRENT_DIR_NAME +char *rep_get_current_dir_name(void) +{ + char buf[PATH_MAX+1]; + char *p; + p = getcwd(buf, sizeof(buf)); + if (p == NULL) { + return NULL; + } + return strdup(p); +} +#endif + +#ifndef HAVE_STRERROR_R +int rep_strerror_r(int errnum, char *buf, size_t buflen) +{ + char *s = strerror(errnum); + if (strlen(s)+1 > buflen) { + errno = ERANGE; + return -1; + } + strncpy(buf, s, buflen); + return 0; +} +#endif + +#ifndef HAVE_CLOCK_GETTIME +int rep_clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + struct timeval tval; + switch (clk_id) { + case 0: /* CLOCK_REALTIME :*/ +#ifdef HAVE_GETTIMEOFDAY_TZ + gettimeofday(&tval,NULL); +#else + gettimeofday(&tval); +#endif + tp->tv_sec = tval.tv_sec; + tp->tv_nsec = tval.tv_usec * 1000; + break; + default: + errno = EINVAL; + return -1; + } + return 0; +} +#endif + +#ifndef HAVE_MEMALIGN +void *rep_memalign( size_t align, size_t size ) +{ +#if defined(HAVE_POSIX_MEMALIGN) + void *p = NULL; + int ret = posix_memalign( &p, align, size ); + if ( ret == 0 ) + return p; + + return NULL; +#else + /* On *BSD systems memaligns doesn't exist, but memory will + * be aligned on allocations of > pagesize. */ +#if defined(SYSCONF_SC_PAGESIZE) + size_t pagesize = (size_t)sysconf(_SC_PAGESIZE); +#elif defined(HAVE_GETPAGESIZE) + size_t pagesize = (size_t)getpagesize(); +#else + size_t pagesize = (size_t)-1; +#endif + if (pagesize == (size_t)-1) { + errno = ENOSYS; + return NULL; + } + if (size < pagesize) { + size = pagesize; + } + return malloc(size); +#endif +} +#endif + +#ifndef HAVE_GETPEEREID +int rep_getpeereid(int s, uid_t *uid, gid_t *gid) +{ +#if defined(HAVE_PEERCRED) + struct ucred cred; + socklen_t cred_len = sizeof(struct ucred); + int ret; + +#undef getsockopt + ret = getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&cred, &cred_len); + if (ret != 0) { + return -1; + } + + if (cred_len != sizeof(struct ucred)) { + errno = EINVAL; + return -1; + } + + *uid = cred.uid; + *gid = cred.gid; + return 0; +#else + errno = ENOSYS; + return -1; +#endif +} +#endif + +#ifndef HAVE_USLEEP +int rep_usleep(useconds_t sec) +{ + struct timeval tval; + /* + * Fake it with select... + */ + tval.tv_sec = 0; + tval.tv_usec = usecs/1000; + select(0,NULL,NULL,NULL,&tval); + return 0; +} +#endif /* HAVE_USLEEP */ + +#ifndef HAVE_SETPROCTITLE +void rep_setproctitle(const char *fmt, ...) +{ +} +#endif diff --git a/ctdb/lib/replace/replace.h b/ctdb/lib/replace/replace.h new file mode 100644 index 0000000000..c0b799763a --- /dev/null +++ b/ctdb/lib/replace/replace.h @@ -0,0 +1,902 @@ +/* + Unix SMB/CIFS implementation. + + macros to go along with the lib/replace/ portability layer code + + Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2006-2008 + Copyright (C) Jeremy Allison 2007. + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _LIBREPLACE_REPLACE_H +#define _LIBREPLACE_REPLACE_H + +#ifndef NO_CONFIG_H +#include "config.h" +#endif + +#ifdef HAVE_STANDARDS_H +#include <standards.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <errno.h> + +#if defined(_MSC_VER) || defined(__MINGW32__) +#include "win32_replace.h" +#endif + + +#ifdef HAVE_INTTYPES_H +#define __STDC_FORMAT_MACROS +#include <inttypes.h> +#elif HAVE_STDINT_H +#include <stdint.h> +/* force off HAVE_INTTYPES_H so that roken doesn't try to include both, + which causes a warning storm on irix */ +#undef HAVE_INTTYPES_H +#endif + +#ifdef HAVE_MALLOC_H +#include <malloc.h> +#endif + +#ifndef __PRI64_PREFIX +# if __WORDSIZE == 64 && ! defined __APPLE__ +# define __PRI64_PREFIX "l" +# else +# define __PRI64_PREFIX "ll" +# endif +#endif + +/* Decimal notation. */ +#ifndef PRId8 +# define PRId8 "d" +#endif +#ifndef PRId16 +# define PRId16 "d" +#endif +#ifndef PRId32 +# define PRId32 "d" +#endif +#ifndef PRId64 +# define PRId64 __PRI64_PREFIX "d" +#endif + +#ifndef PRIi8 +# define PRIi8 "i" +#endif +#ifndef PRIi16 +# define PRIi16 "i" +#endif +#ifndef PRIi32 +# define PRIi32 "i" +#endif +#ifndef PRIi64 +# define PRIi64 __PRI64_PREFIX "i" +#endif + +#ifndef PRIu8 +# define PRIu8 "u" +#endif +#ifndef PRIu16 +# define PRIu16 "u" +#endif +#ifndef PRIu32 +# define PRIu32 "u" +#endif +#ifndef PRIu64 +# define PRIu64 __PRI64_PREFIX "u" +#endif + +#ifndef SCNd8 +# define SCNd8 "hhd" +#endif +#ifndef SCNd16 +# define SCNd16 "hd" +#endif +#ifndef SCNd32 +# define SCNd32 "d" +#endif +#ifndef SCNd64 +# define SCNd64 __PRI64_PREFIX "d" +#endif + +#ifndef SCNi8 +# define SCNi8 "hhi" +#endif +#ifndef SCNi16 +# define SCNi16 "hi" +#endif +#ifndef SCNi32 +# define SCNi32 "i" +#endif +#ifndef SCNi64 +# define SCNi64 __PRI64_PREFIX "i" +#endif + +#ifndef SCNu8 +# define SCNu8 "hhu" +#endif +#ifndef SCNu16 +# define SCNu16 "hu" +#endif +#ifndef SCNu32 +# define SCNu32 "u" +#endif +#ifndef SCNu64 +# define SCNu64 __PRI64_PREFIX "u" +#endif + +#ifdef HAVE_BSD_STRING_H +#include <bsd/string.h> +#endif + +#ifdef HAVE_BSD_UNISTD_H +#include <bsd/unistd.h> +#endif + +#ifdef HAVE_STRING_H +#include <string.h> +#endif + +#ifdef HAVE_STRINGS_H +#include <strings.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + +#ifdef HAVE_SETPROCTITLE_H +#include <setproctitle.h> +#endif + +#if STDC_HEADERS +#include <stdlib.h> +#include <stddef.h> +#endif + +#ifdef HAVE_LINUX_TYPES_H +/* + * This is needed as some broken header files require this to be included early + */ +#include <linux/types.h> +#endif + +#ifndef HAVE_STRERROR +extern char *sys_errlist[]; +#define strerror(i) sys_errlist[i] +#endif + +#ifndef HAVE_ERRNO_DECL +extern int errno; +#endif + +#ifndef HAVE_STRDUP +#define strdup rep_strdup +char *rep_strdup(const char *s); +#endif + +#ifndef HAVE_MEMMOVE +#define memmove rep_memmove +void *rep_memmove(void *dest,const void *src,int size); +#endif + +#ifndef HAVE_MEMMEM +#define memmem rep_memmem +void *rep_memmem(const void *haystack, size_t haystacklen, + const void *needle, size_t needlelen); +#endif + +#ifndef HAVE_MEMALIGN +#define memalign rep_memalign +void *rep_memalign(size_t boundary, size_t size); +#endif + +#ifndef HAVE_MKTIME +#define mktime rep_mktime +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_TIMEGM +#define timegm rep_timegm +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_UTIME +#define utime rep_utime +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_UTIMES +#define utimes rep_utimes +/* prototype is in "system/time.h" */ +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy rep_strlcpy +size_t rep_strlcpy(char *d, const char *s, size_t bufsize); +#endif + +#ifndef HAVE_STRLCAT +#define strlcat rep_strlcat +size_t rep_strlcat(char *d, const char *s, size_t bufsize); +#endif + +#if (defined(BROKEN_STRNDUP) || !defined(HAVE_STRNDUP)) +#undef HAVE_STRNDUP +#define strndup rep_strndup +char *rep_strndup(const char *s, size_t n); +#endif + +#if (defined(BROKEN_STRNLEN) || !defined(HAVE_STRNLEN)) +#undef HAVE_STRNLEN +#define strnlen rep_strnlen +size_t rep_strnlen(const char *s, size_t n); +#endif + +#if !HAVE_DECL_ENVIRON +#ifdef __APPLE__ +#include <crt_externs.h> +#define environ (*_NSGetEnviron()) +#else +extern char **environ; +#endif +#endif + +#ifndef HAVE_SETENV +#define setenv rep_setenv +int rep_setenv(const char *name, const char *value, int overwrite); +#else +#ifndef HAVE_SETENV_DECL +int setenv(const char *name, const char *value, int overwrite); +#endif +#endif + +#ifndef HAVE_UNSETENV +#define unsetenv rep_unsetenv +int rep_unsetenv(const char *name); +#endif + +#ifndef HAVE_SETEUID +#define seteuid rep_seteuid +int rep_seteuid(uid_t); +#endif + +#ifndef HAVE_SETEGID +#define setegid rep_setegid +int rep_setegid(gid_t); +#endif + +#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESUID_DECL)) +/* stupid glibc */ +int setresuid(uid_t ruid, uid_t euid, uid_t suid); +#endif +#if (defined(USE_SETRESUID) && !defined(HAVE_SETRESGID_DECL)) +int setresgid(gid_t rgid, gid_t egid, gid_t sgid); +#endif + +#ifndef HAVE_CHOWN +#define chown rep_chown +int rep_chown(const char *path, uid_t uid, gid_t gid); +#endif + +#ifndef HAVE_CHROOT +#define chroot rep_chroot +int rep_chroot(const char *dirname); +#endif + +#ifndef HAVE_LINK +#define link rep_link +int rep_link(const char *oldpath, const char *newpath); +#endif + +#ifndef HAVE_READLINK +#define readlink rep_readlink +ssize_t rep_readlink(const char *path, char *buf, size_t bufsize); +#endif + +#ifndef HAVE_SYMLINK +#define symlink rep_symlink +int rep_symlink(const char *oldpath, const char *newpath); +#endif + +#ifndef HAVE_REALPATH +#define realpath rep_realpath +char *rep_realpath(const char *path, char *resolved_path); +#endif + +#ifndef HAVE_LCHOWN +#define lchown rep_lchown +int rep_lchown(const char *fname,uid_t uid,gid_t gid); +#endif + +#ifdef HAVE_UNIX_H +#include <unix.h> +#endif + +#ifndef HAVE_SETLINEBUF +#define setlinebuf rep_setlinebuf +void rep_setlinebuf(FILE *); +#endif + +#ifndef HAVE_STRCASESTR +#define strcasestr rep_strcasestr +char *rep_strcasestr(const char *haystack, const char *needle); +#endif + +#ifndef HAVE_STRTOK_R +#define strtok_r rep_strtok_r +char *rep_strtok_r(char *s, const char *delim, char **save_ptr); +#endif + + + +#ifndef HAVE_STRTOLL +#define strtoll rep_strtoll +long long int rep_strtoll(const char *str, char **endptr, int base); +#else +#ifdef HAVE_BSD_STRTOLL +#define strtoll rep_strtoll +long long int rep_strtoll(const char *str, char **endptr, int base); +#endif +#endif + +#ifndef HAVE_STRTOULL +#define strtoull rep_strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base); +#else +#ifdef HAVE_BSD_STRTOLL /* yes, it's not HAVE_BSD_STRTOULL */ +#define strtoull rep_strtoull +unsigned long long int rep_strtoull(const char *str, char **endptr, int base); +#endif +#endif + +#ifndef HAVE_FTRUNCATE +#define ftruncate rep_ftruncate +int rep_ftruncate(int,off_t); +#endif + +#ifndef HAVE_INITGROUPS +#define initgroups rep_initgroups +int rep_initgroups(char *name, gid_t id); +#endif + +#if !defined(HAVE_BZERO) && defined(HAVE_MEMSET) +#define bzero(a,b) memset((a),'\0',(b)) +#endif + +#ifndef HAVE_DLERROR +#define dlerror rep_dlerror +char *rep_dlerror(void); +#endif + +#ifndef HAVE_DLOPEN +#define dlopen rep_dlopen +#ifdef DLOPEN_TAKES_UNSIGNED_FLAGS +void *rep_dlopen(const char *name, unsigned int flags); +#else +void *rep_dlopen(const char *name, int flags); +#endif +#endif + +#ifndef HAVE_DLSYM +#define dlsym rep_dlsym +void *rep_dlsym(void *handle, const char *symbol); +#endif + +#ifndef HAVE_DLCLOSE +#define dlclose rep_dlclose +int rep_dlclose(void *handle); +#endif + +#ifndef HAVE_SOCKETPAIR +#define socketpair rep_socketpair +/* prototype is in system/network.h */ +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +/** Use gcc attribute to check printf fns. a1 is the 1-based index of + * the parameter containing the format, and a2 the index of the first + * argument. Note that some gcc 2.x versions don't handle this + * properly **/ +#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) +#else +#define PRINTF_ATTRIBUTE(a1, a2) +#endif +#endif + +#ifndef _DEPRECATED_ +#if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 1 ) +#define _DEPRECATED_ __attribute__ ((deprecated)) +#else +#define _DEPRECATED_ +#endif +#endif + +#if !defined(HAVE_VDPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vdprintf rep_vdprintf +int rep_vdprintf(int fd, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +#endif + +#if !defined(HAVE_DPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define dprintf rep_dprintf +int rep_dprintf(int fd, const char *format, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#if !defined(HAVE_VASPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vasprintf rep_vasprintf +int rep_vasprintf(char **ptr, const char *format, va_list ap) PRINTF_ATTRIBUTE(2,0); +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define snprintf rep_snprintf +int rep_snprintf(char *,size_t ,const char *, ...) PRINTF_ATTRIBUTE(3,4); +#endif + +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define vsnprintf rep_vsnprintf +int rep_vsnprintf(char *,size_t ,const char *, va_list ap) PRINTF_ATTRIBUTE(3,0); +#endif + +#if !defined(HAVE_ASPRINTF) || !defined(HAVE_C99_VSNPRINTF) +#define asprintf rep_asprintf +int rep_asprintf(char **,const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#if !defined(HAVE_C99_VSNPRINTF) +#ifdef REPLACE_BROKEN_PRINTF +/* + * We do not redefine printf by default + * as it breaks the build if system headers + * use __attribute__((format(printf, 3, 0))) + * instead of __attribute__((format(__printf__, 3, 0))) + */ +#define printf rep_printf +#endif +int rep_printf(const char *, ...) PRINTF_ATTRIBUTE(1,2); +#endif + +#if !defined(HAVE_C99_VSNPRINTF) +#define fprintf rep_fprintf +int rep_fprintf(FILE *stream, const char *, ...) PRINTF_ATTRIBUTE(2,3); +#endif + +#ifndef HAVE_VSYSLOG +#ifdef HAVE_SYSLOG +#define vsyslog rep_vsyslog +void rep_vsyslog (int facility_priority, const char *format, va_list arglist) PRINTF_ATTRIBUTE(2,0); +#endif +#endif + +/* we used to use these fns, but now we have good replacements + for snprintf and vsnprintf */ +#define slprintf snprintf + + +#ifndef HAVE_VA_COPY +#undef va_copy +#ifdef HAVE___VA_COPY +#define va_copy(dest, src) __va_copy(dest, src) +#else +#define va_copy(dest, src) (dest) = (src) +#endif +#endif + +#ifndef HAVE_VOLATILE +#define volatile +#endif + +#ifndef HAVE_COMPARISON_FN_T +typedef int (*comparison_fn_t)(const void *, const void *); +#endif + +#ifndef HAVE_WORKING_STRPTIME +#define strptime rep_strptime +struct tm; +char *rep_strptime(const char *buf, const char *format, struct tm *tm); +#endif + +#ifndef HAVE_DUP2 +#define dup2 rep_dup2 +int rep_dup2(int oldfd, int newfd); +#endif + +/* Load header file for dynamic linking stuff */ +#ifdef HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif +#ifndef RTLD_NOW +#define RTLD_NOW 0 +#endif +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +#ifndef HAVE_SECURE_MKSTEMP +#define mkstemp(path) rep_mkstemp(path) +int rep_mkstemp(char *temp); +#endif + +#ifndef HAVE_MKDTEMP +#define mkdtemp rep_mkdtemp +char *rep_mkdtemp(char *template); +#endif + +#ifndef HAVE_PREAD +#define pread rep_pread +ssize_t rep_pread(int __fd, void *__buf, size_t __nbytes, off_t __offset); +#define LIBREPLACE_PREAD_REPLACED 1 +#else +#define LIBREPLACE_PREAD_NOT_REPLACED 1 +#endif + +#ifndef HAVE_PWRITE +#define pwrite rep_pwrite +ssize_t rep_pwrite(int __fd, const void *__buf, size_t __nbytes, off_t __offset); +#define LIBREPLACE_PWRITE_REPLACED 1 +#else +#define LIBREPLACE_PWRITE_NOT_REPLACED 1 +#endif + +#if !defined(HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) +#define inet_ntoa rep_inet_ntoa +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_PTON +#define inet_pton rep_inet_pton +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_NTOP +#define inet_ntop rep_inet_ntop +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_INET_ATON +#define inet_aton rep_inet_aton +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_CONNECT +#define connect rep_connect +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETHOSTBYNAME +#define gethostbyname rep_gethostbyname +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETIFADDRS +#define getifaddrs rep_getifaddrs +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_FREEIFADDRS +#define freeifaddrs rep_freeifaddrs +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GET_CURRENT_DIR_NAME +#define get_current_dir_name rep_get_current_dir_name +char *rep_get_current_dir_name(void); +#endif + +#ifndef HAVE_STRERROR_R +#define strerror_r rep_strerror_r +int rep_strerror_r(int errnum, char *buf, size_t buflen); +#endif + +#if !defined(HAVE_CLOCK_GETTIME) +#define clock_gettime rep_clock_gettime +#endif + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +/* The extra casts work around common compiler bugs. */ +#define _TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) +/* The outer cast is needed to work around a bug in Cray C 5.0.3.0. + It is necessary at least when t == time_t. */ +#define _TYPE_MINIMUM(t) ((t) (_TYPE_SIGNED (t) \ + ? ~ (t) 0 << (sizeof (t) * CHAR_BIT - 1) : (t) 0)) +#define _TYPE_MAXIMUM(t) ((t) (~ (t) 0 - _TYPE_MINIMUM (t))) + +#ifndef UINT16_MAX +#define UINT16_MAX 65535 +#endif + +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#ifndef UINT64_MAX +#define UINT64_MAX ((uint64_t)-1) +#endif + +#ifndef INT64_MAX +#define INT64_MAX 9223372036854775807LL +#endif + +#ifndef CHAR_BIT +#define CHAR_BIT 8 +#endif + +#ifndef INT32_MAX +#define INT32_MAX _TYPE_MAXIMUM(int32_t) +#endif + +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#endif + +#if !defined(HAVE_BOOL) +#ifdef HAVE__Bool +#define bool _Bool +#else +typedef int bool; +#endif +#endif + +#if !defined(HAVE_INTPTR_T) +typedef long long intptr_t ; +#endif + +#if !defined(HAVE_UINTPTR_T) +typedef unsigned long long uintptr_t ; +#endif + +#if !defined(HAVE_PTRDIFF_T) +typedef unsigned long long ptrdiff_t ; +#endif + +/* + * to prevent <rpcsvc/yp_prot.h> from doing a redefine of 'bool' + * + * IRIX, HPUX, MacOS 10 and Solaris need BOOL_DEFINED + * Tru64 needs _BOOL_EXISTS + * AIX needs _BOOL,_TRUE,_FALSE + */ +#ifndef BOOL_DEFINED +#define BOOL_DEFINED +#endif +#ifndef _BOOL_EXISTS +#define _BOOL_EXISTS +#endif +#ifndef _BOOL +#define _BOOL +#endif + +#ifndef __bool_true_false_are_defined +#define __bool_true_false_are_defined +#endif + +#ifndef true +#define true (1) +#endif +#ifndef false +#define false (0) +#endif + +#ifndef _TRUE +#define _TRUE true +#endif +#ifndef _FALSE +#define _FALSE false +#endif + +#ifndef HAVE_FUNCTION_MACRO +#ifdef HAVE_func_MACRO +#define __FUNCTION__ __func__ +#else +#define __FUNCTION__ ("") +#endif +#endif + + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +#if !defined(HAVE_VOLATILE) +#define volatile +#endif + +/** + this is a warning hack. The idea is to use this everywhere that we + get the "discarding const" warning from gcc. That doesn't actually + fix the problem of course, but it means that when we do get to + cleaning them up we can do it by searching the code for + discard_const. + + It also means that other error types aren't as swamped by the noise + of hundreds of const warnings, so we are more likely to notice when + we get new errors. + + Please only add more uses of this macro when you find it + _really_ hard to fix const warnings. Our aim is to eventually use + this function in only a very few places. + + Also, please call this via the discard_const_p() macro interface, as that + makes the return type safe. +*/ +#define discard_const(ptr) ((void *)((uintptr_t)(ptr))) + +/** Type-safe version of discard_const */ +#define discard_const_p(type, ptr) ((type *)discard_const(ptr)) + +#ifndef __STRING +#define __STRING(x) #x +#endif + +#ifndef __STRINGSTRING +#define __STRINGSTRING(x) __STRING(x) +#endif + +#ifndef __LINESTR__ +#define __LINESTR__ __STRINGSTRING(__LINE__) +#endif + +#ifndef __location__ +#define __location__ __FILE__ ":" __LINESTR__ +#endif + +/** + * zero a structure + */ +#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) + +/** + * zero a structure given a pointer to the structure + */ +#define ZERO_STRUCTP(x) do { if ((x) != NULL) memset((char *)(x), 0, sizeof(*(x))); } while(0) + +/** + * zero a structure given a pointer to the structure - no zero check + */ +#define ZERO_STRUCTPN(x) memset((char *)(x), 0, sizeof(*(x))) + +/* zero an array - note that sizeof(array) must work - ie. it must not be a + pointer */ +#define ZERO_ARRAY(x) memset((char *)(x), 0, sizeof(x)) + +/** + * work out how many elements there are in a static array + */ +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +/** + * pointer difference macro + */ +#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2))) + +#if MMAP_BLACKLIST +#undef HAVE_MMAP +#endif + +#ifdef __COMPAR_FN_T +#define QSORT_CAST (__compar_fn_t) +#endif + +#ifndef QSORT_CAST +#define QSORT_CAST (int (*)(const void *, const void *)) +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef MAX_DNS_NAME_LENGTH +#define MAX_DNS_NAME_LENGTH 256 /* Actually 255 but +1 for terminating null. */ +#endif + +#ifndef HAVE_CRYPT +char *ufc_crypt(const char *key, const char *salt); +#define crypt ufc_crypt +#else +#ifdef HAVE_CRYPT_H +#include <crypt.h> +#endif +#endif + +/* these macros gain us a few percent of speed on gcc */ +#if (__GNUC__ >= 3) +/* the strange !! is to ensure that __builtin_expect() takes either 0 or 1 + as its first argument */ +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif +#else +#ifndef likely +#define likely(x) (x) +#endif +#ifndef unlikely +#define unlikely(x) (x) +#endif +#endif + +#ifndef HAVE_FDATASYNC +#define fdatasync(fd) fsync(fd) +#elif !defined(HAVE_DECL_FDATASYNC) +int fdatasync(int ); +#endif + +/* these are used to mark symbols as local to a shared lib, or + * publicly available via the shared lib API */ +#ifndef _PUBLIC_ +#ifdef HAVE_VISIBILITY_ATTR +#define _PUBLIC_ __attribute__((visibility("default"))) +#else +#define _PUBLIC_ +#endif +#endif + +#ifndef _PRIVATE_ +#ifdef HAVE_VISIBILITY_ATTR +# define _PRIVATE_ __attribute__((visibility("hidden"))) +#else +# define _PRIVATE_ +#endif +#endif + +#ifndef HAVE_POLL +#define poll rep_poll +/* prototype is in "system/network.h" */ +#endif + +#ifndef HAVE_GETPEEREID +#define getpeereid rep_getpeereid +int rep_getpeereid(int s, uid_t *uid, gid_t *gid); +#endif + +#ifndef HAVE_USLEEP +#define usleep rep_usleep +typedef long useconds_t; +int usleep(useconds_t); +#endif + +#ifndef HAVE_SETPROCTITLE +#define setproctitle rep_setproctitle +void rep_setproctitle(const char *fmt, ...) PRINTF_ATTRIBUTE(1, 2); +#endif + +#endif /* _LIBREPLACE_REPLACE_H */ diff --git a/ctdb/lib/replace/snprintf.c b/ctdb/lib/replace/snprintf.c new file mode 100644 index 0000000000..6b4a711045 --- /dev/null +++ b/ctdb/lib/replace/snprintf.c @@ -0,0 +1,1530 @@ +/* + * NOTE: If you change this file, please merge it into rsync, samba, etc. + */ + +/* + * Copyright Patrick Powell 1995 + * This code is based on code written by Patrick Powell (papowell@astart.com) + * It may be used for any purpose as long as this notice remains intact + * on all source code distributions + */ + +/************************************************************** + * Original: + * Patrick Powell Tue Apr 11 09:48:21 PDT 1995 + * A bombproof version of doprnt (dopr) included. + * Sigh. This sort of thing is always nasty do deal with. Note that + * the version here does not include floating point... + * + * snprintf() is used instead of sprintf() as it does limit checks + * for string length. This covers a nasty loophole. + * + * The other functions are there to prevent NULL pointers from + * causing nast effects. + * + * More Recently: + * Brandon Long <blong@fiction.net> 9/15/96 for mutt 0.43 + * This was ugly. It is still ugly. I opted out of floating point + * numbers, but the formatter understands just about everything + * from the normal C string format, at least as far as I can tell from + * the Solaris 2.5 printf(3S) man page. + * + * Brandon Long <blong@fiction.net> 10/22/97 for mutt 0.87.1 + * Ok, added some minimal floating point support, which means this + * probably requires libm on most operating systems. Don't yet + * support the exponent (e,E) and sigfig (g,G). Also, fmtint() + * was pretty badly broken, it just wasn't being exercised in ways + * which showed it, so that's been fixed. Also, formated the code + * to mutt conventions, and removed dead code left over from the + * original. Also, there is now a builtin-test, just compile with: + * gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm + * and run snprintf for results. + * + * Thomas Roessler <roessler@guug.de> 01/27/98 for mutt 0.89i + * The PGP code was using unsigned hexadecimal formats. + * Unfortunately, unsigned formats simply didn't work. + * + * Michael Elkins <me@cs.hmc.edu> 03/05/98 for mutt 0.90.8 + * The original code assumed that both snprintf() and vsnprintf() were + * missing. Some systems only have snprintf() but not vsnprintf(), so + * the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF. + * + * Andrew Tridgell (tridge@samba.org) Oct 1998 + * fixed handling of %.0f + * added test for HAVE_LONG_DOUBLE + * + * tridge@samba.org, idra@samba.org, April 2001 + * got rid of fcvt code (twas buggy and made testing harder) + * added C99 semantics + * + * date: 2002/12/19 19:56:31; author: herb; state: Exp; lines: +2 -0 + * actually print args for %g and %e + * + * date: 2002/06/03 13:37:52; author: jmcd; state: Exp; lines: +8 -0 + * Since includes.h isn't included here, VA_COPY has to be defined here. I don't + * see any include file that is guaranteed to be here, so I'm defining it + * locally. Fixes AIX and Solaris builds. + * + * date: 2002/06/03 03:07:24; author: tridge; state: Exp; lines: +5 -13 + * put the ifdef for HAVE_VA_COPY in one place rather than in lots of + * functions + * + * date: 2002/05/17 14:51:22; author: jmcd; state: Exp; lines: +21 -4 + * Fix usage of va_list passed as an arg. Use __va_copy before using it + * when it exists. + * + * date: 2002/04/16 22:38:04; author: idra; state: Exp; lines: +20 -14 + * Fix incorrect zpadlen handling in fmtfp. + * Thanks to Ollie Oldham <ollie.oldham@metro-optix.com> for spotting it. + * few mods to make it easier to compile the tests. + * addedd the "Ollie" test to the floating point ones. + * + * Martin Pool (mbp@samba.org) April 2003 + * Remove NO_CONFIG_H so that the test case can be built within a source + * tree with less trouble. + * Remove unnecessary SAFE_FREE() definition. + * + * Martin Pool (mbp@samba.org) May 2003 + * Put in a prototype for dummy_snprintf() to quiet compiler warnings. + * + * Move #endif to make sure VA_COPY, LDOUBLE, etc are defined even + * if the C library has some snprintf functions already. + * + * Darren Tucker (dtucker@zip.com.au) 2005 + * Fix bug allowing read overruns of the source string with "%.*s" + * Usually harmless unless the read runs outside the process' allocation + * (eg if your malloc does guard pages) in which case it will segfault. + * From OpenSSH. Also added test for same. + * + * Simo Sorce (idra@samba.org) Jan 2006 + * + * Add support for position independent parameters + * fix fmtstr now it conforms to sprintf wrt min.max + * + **************************************************************/ + +#include "replace.h" +#include "system/locale.h" + +#ifdef TEST_SNPRINTF /* need math library headers for testing */ + +/* In test mode, we pretend that this system doesn't have any snprintf + * functions, regardless of what config.h says. */ +# undef HAVE_SNPRINTF +# undef HAVE_VSNPRINTF +# undef HAVE_C99_VSNPRINTF +# undef HAVE_ASPRINTF +# undef HAVE_VASPRINTF +# include <math.h> +#endif /* TEST_SNPRINTF */ + +#if defined(HAVE_SNPRINTF) && defined(HAVE_VSNPRINTF) && defined(HAVE_C99_VSNPRINTF) +/* only include stdio.h if we are not re-defining snprintf or vsnprintf */ +#include <stdio.h> + /* make the compiler happy with an empty file */ + void dummy_snprintf(void); + void dummy_snprintf(void) {} +#endif /* HAVE_SNPRINTF, etc */ + +/* yes this really must be a ||. Don't muck with this (tridge) */ +#if !defined(HAVE_VSNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + +#ifdef HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif + +#ifdef HAVE_LONG_LONG +#define LLONG long long +#else +#define LLONG long +#endif + +#ifndef VA_COPY +#ifdef HAVE_VA_COPY +#define VA_COPY(dest, src) va_copy(dest, src) +#else +#ifdef HAVE___VA_COPY +#define VA_COPY(dest, src) __va_copy(dest, src) +#else +#define VA_COPY(dest, src) (dest) = (src) +#endif +#endif + +/* + * dopr(): poor man's version of doprintf + */ + +/* format read states */ +#define DP_S_DEFAULT 0 +#define DP_S_FLAGS 1 +#define DP_S_MIN 2 +#define DP_S_DOT 3 +#define DP_S_MAX 4 +#define DP_S_MOD 5 +#define DP_S_CONV 6 +#define DP_S_DONE 7 + +/* format flags - Bits */ +#define DP_F_MINUS (1 << 0) +#define DP_F_PLUS (1 << 1) +#define DP_F_SPACE (1 << 2) +#define DP_F_NUM (1 << 3) +#define DP_F_ZERO (1 << 4) +#define DP_F_UP (1 << 5) +#define DP_F_UNSIGNED (1 << 6) + +/* Conversion Flags */ +#define DP_C_CHAR 1 +#define DP_C_SHORT 2 +#define DP_C_LONG 3 +#define DP_C_LDOUBLE 4 +#define DP_C_LLONG 5 +#define DP_C_SIZET 6 + +/* Chunk types */ +#define CNK_FMT_STR 0 +#define CNK_INT 1 +#define CNK_OCTAL 2 +#define CNK_UINT 3 +#define CNK_HEX 4 +#define CNK_FLOAT 5 +#define CNK_CHAR 6 +#define CNK_STRING 7 +#define CNK_PTR 8 +#define CNK_NUM 9 +#define CNK_PRCNT 10 + +#define char_to_int(p) ((p)- '0') +#ifndef MAX +#define MAX(p,q) (((p) >= (q)) ? (p) : (q)) +#endif + +struct pr_chunk { + int type; /* chunk type */ + int num; /* parameter number */ + int min; + int max; + int flags; + int cflags; + int start; + int len; + LLONG value; + LDOUBLE fvalue; + char *strvalue; + void *pnum; + struct pr_chunk *min_star; + struct pr_chunk *max_star; + struct pr_chunk *next; +}; + +struct pr_chunk_x { + struct pr_chunk **chunks; + int num; +}; + +static int dopr(char *buffer, size_t maxlen, const char *format, + va_list args_in); +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max); +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags); +static void fmtfp(char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags); +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c); +static struct pr_chunk *new_chunk(void); +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk); + +static int dopr(char *buffer, size_t maxlen, const char *format, va_list args_in) +{ + char ch; + int state; + int pflag; + int pnum; + int pfirst; + size_t currlen; + va_list args; + const char *base; + struct pr_chunk *chunks = NULL; + struct pr_chunk *cnk = NULL; + struct pr_chunk_x *clist = NULL; + int max_pos; + int ret = -1; + + VA_COPY(args, args_in); + + state = DP_S_DEFAULT; + pfirst = 1; + pflag = 0; + pnum = 0; + + max_pos = 0; + base = format; + ch = *format++; + + /* retrieve the string structure as chunks */ + while (state != DP_S_DONE) { + if (ch == '\0') + state = DP_S_DONE; + + switch(state) { + case DP_S_DEFAULT: + + if (cnk) { + cnk->next = new_chunk(); + cnk = cnk->next; + } else { + cnk = new_chunk(); + } + if (!cnk) goto done; + if (!chunks) chunks = cnk; + + if (ch == '%') { + state = DP_S_FLAGS; + ch = *format++; + } else { + cnk->type = CNK_FMT_STR; + cnk->start = format - base -1; + while ((ch != '\0') && (ch != '%')) ch = *format++; + cnk->len = format - base - cnk->start -1; + } + break; + case DP_S_FLAGS: + switch (ch) { + case '-': + cnk->flags |= DP_F_MINUS; + ch = *format++; + break; + case '+': + cnk->flags |= DP_F_PLUS; + ch = *format++; + break; + case ' ': + cnk->flags |= DP_F_SPACE; + ch = *format++; + break; + case '#': + cnk->flags |= DP_F_NUM; + ch = *format++; + break; + case '0': + cnk->flags |= DP_F_ZERO; + ch = *format++; + break; + case 'I': + /* internationalization not supported yet */ + ch = *format++; + break; + default: + state = DP_S_MIN; + break; + } + break; + case DP_S_MIN: + if (isdigit((unsigned char)ch)) { + cnk->min = 10 * cnk->min + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (pfirst) { + pfirst = 0; + pflag = 1; + } + if (cnk->min == 0) /* what ?? */ + goto done; + cnk->num = cnk->min; + cnk->min = 0; + ch = *format++; + } else if (ch == '*') { + if (pfirst) pfirst = 0; + cnk->min_star = new_chunk(); + if (!cnk->min_star) /* out of memory :-( */ + goto done; + cnk->min_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->min_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->min_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->min_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + ch = *format++; + state = DP_S_DOT; + } else { + if (pfirst) pfirst = 0; + state = DP_S_DOT; + } + break; + case DP_S_DOT: + if (ch == '.') { + state = DP_S_MAX; + ch = *format++; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MAX: + if (isdigit((unsigned char)ch)) { + if (cnk->max < 0) + cnk->max = 0; + cnk->max = 10 * cnk->max + char_to_int (ch); + ch = *format++; + } else if (ch == '$') { + if (!pfirst && !pflag) { + /* parameters must be all positioned or none */ + goto done; + } + if (cnk->max <= 0) /* what ?? */ + goto done; + cnk->num = cnk->max; + cnk->max = -1; + ch = *format++; + } else if (ch == '*') { + cnk->max_star = new_chunk(); + if (!cnk->max_star) /* out of memory :-( */ + goto done; + cnk->max_star->type = CNK_INT; + if (pflag) { + int num; + ch = *format++; + if (!isdigit((unsigned char)ch)) { + /* parameters must be all positioned or none */ + goto done; + } + for (num = 0; isdigit((unsigned char)ch); ch = *format++) { + num = 10 * num + char_to_int(ch); + } + cnk->max_star->num = num; + if (ch != '$') /* what ?? */ + goto done; + } else { + cnk->max_star->num = ++pnum; + } + max_pos = add_cnk_list_entry(&clist, max_pos, cnk->max_star); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + ch = *format++; + state = DP_S_MOD; + } else { + state = DP_S_MOD; + } + break; + case DP_S_MOD: + switch (ch) { + case 'h': + cnk->cflags = DP_C_SHORT; + ch = *format++; + if (ch == 'h') { + cnk->cflags = DP_C_CHAR; + ch = *format++; + } + break; + case 'l': + cnk->cflags = DP_C_LONG; + ch = *format++; + if (ch == 'l') { /* It's a long long */ + cnk->cflags = DP_C_LLONG; + ch = *format++; + } + break; + case 'L': + cnk->cflags = DP_C_LDOUBLE; + ch = *format++; + break; + case 'z': + cnk->cflags = DP_C_SIZET; + ch = *format++; + break; + default: + break; + } + state = DP_S_CONV; + break; + case DP_S_CONV: + if (cnk->num == 0) cnk->num = ++pnum; + max_pos = add_cnk_list_entry(&clist, max_pos, cnk); + if (max_pos == 0) /* out of memory :-( */ + goto done; + + switch (ch) { + case 'd': + case 'i': + cnk->type = CNK_INT; + break; + case 'o': + cnk->type = CNK_OCTAL; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'u': + cnk->type = CNK_UINT; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'X': + cnk->flags |= DP_F_UP; + case 'x': + cnk->type = CNK_HEX; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'A': + /* hex float not supported yet */ + case 'E': + case 'G': + case 'F': + cnk->flags |= DP_F_UP; + case 'a': + /* hex float not supported yet */ + case 'e': + case 'f': + case 'g': + cnk->type = CNK_FLOAT; + break; + case 'c': + cnk->type = CNK_CHAR; + break; + case 's': + cnk->type = CNK_STRING; + break; + case 'p': + cnk->type = CNK_PTR; + cnk->flags |= DP_F_UNSIGNED; + break; + case 'n': + cnk->type = CNK_NUM; + break; + case '%': + cnk->type = CNK_PRCNT; + break; + default: + /* Unknown, bail out*/ + goto done; + } + ch = *format++; + state = DP_S_DEFAULT; + break; + case DP_S_DONE: + break; + default: + /* hmm? */ + break; /* some picky compilers need this */ + } + } + + /* retrieve the format arguments */ + for (pnum = 0; pnum < max_pos; pnum++) { + int i; + + if (clist[pnum].num == 0) { + /* ignoring a parameter should not be permitted + * all parameters must be matched at least once + * BUT seem some system ignore this rule ... + * at least my glibc based system does --SSS + */ +#ifdef DEBUG_SNPRINTF + printf("parameter at position %d not used\n", pnum+1); +#endif + /* eat the parameter */ + va_arg (args, int); + continue; + } + for (i = 1; i < clist[pnum].num; i++) { + if (clist[pnum].chunks[0]->type != clist[pnum].chunks[i]->type) { + /* nooo noo no! + * all the references to a parameter + * must be of the same type + */ + goto done; + } + } + cnk = clist[pnum].chunks[0]; + switch (cnk->type) { + case CNK_INT: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = va_arg (args, long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = va_arg (args, LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = va_arg (args, ssize_t); + else + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_OCTAL: + case CNK_UINT: + case CNK_HEX: + if (cnk->cflags == DP_C_SHORT) + cnk->value = va_arg (args, unsigned int); + else if (cnk->cflags == DP_C_LONG) + cnk->value = (unsigned long int)va_arg (args, unsigned long int); + else if (cnk->cflags == DP_C_LLONG) + cnk->value = (LLONG)va_arg (args, unsigned LLONG); + else if (cnk->cflags == DP_C_SIZET) + cnk->value = (size_t)va_arg (args, size_t); + else + cnk->value = (unsigned int)va_arg (args, unsigned int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_FLOAT: + if (cnk->cflags == DP_C_LDOUBLE) + cnk->fvalue = va_arg (args, LDOUBLE); + else + cnk->fvalue = va_arg (args, double); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->fvalue = cnk->fvalue; + } + break; + + case CNK_CHAR: + cnk->value = va_arg (args, int); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->value = cnk->value; + } + break; + + case CNK_STRING: + cnk->strvalue = va_arg (args, char *); + if (!cnk->strvalue) cnk->strvalue = "(NULL)"; + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_PTR: + cnk->strvalue = va_arg (args, void *); + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->strvalue = cnk->strvalue; + } + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + cnk->pnum = va_arg (args, char *); + else if (cnk->cflags == DP_C_SHORT) + cnk->pnum = va_arg (args, short int *); + else if (cnk->cflags == DP_C_LONG) + cnk->pnum = va_arg (args, long int *); + else if (cnk->cflags == DP_C_LLONG) + cnk->pnum = va_arg (args, LLONG *); + else if (cnk->cflags == DP_C_SIZET) + cnk->pnum = va_arg (args, ssize_t *); + else + cnk->pnum = va_arg (args, int *); + + for (i = 1; i < clist[pnum].num; i++) { + clist[pnum].chunks[i]->pnum = cnk->pnum; + } + break; + + case CNK_PRCNT: + break; + + default: + /* what ?? */ + goto done; + } + } + /* print out the actual string from chunks */ + currlen = 0; + cnk = chunks; + while (cnk) { + int len, min, max; + + if (cnk->min_star) min = cnk->min_star->value; + else min = cnk->min; + if (cnk->max_star) max = cnk->max_star->value; + else max = cnk->max; + + switch (cnk->type) { + + case CNK_FMT_STR: + if (maxlen != 0 && maxlen > currlen) { + if (maxlen > (currlen + cnk->len)) len = cnk->len; + else len = maxlen - currlen; + + memcpy(&(buffer[currlen]), &(base[cnk->start]), len); + } + currlen += cnk->len; + + break; + + case CNK_INT: + case CNK_UINT: + fmtint (buffer, &currlen, maxlen, cnk->value, 10, min, max, cnk->flags); + break; + + case CNK_OCTAL: + fmtint (buffer, &currlen, maxlen, cnk->value, 8, min, max, cnk->flags); + break; + + case CNK_HEX: + fmtint (buffer, &currlen, maxlen, cnk->value, 16, min, max, cnk->flags); + break; + + case CNK_FLOAT: + fmtfp (buffer, &currlen, maxlen, cnk->fvalue, min, max, cnk->flags); + break; + + case CNK_CHAR: + dopr_outch (buffer, &currlen, maxlen, cnk->value); + break; + + case CNK_STRING: + if (max == -1) { + max = strlen(cnk->strvalue); + } + fmtstr (buffer, &currlen, maxlen, cnk->strvalue, cnk->flags, min, max); + break; + + case CNK_PTR: + fmtint (buffer, &currlen, maxlen, (long)(cnk->strvalue), 16, min, max, cnk->flags); + break; + + case CNK_NUM: + if (cnk->cflags == DP_C_CHAR) + *((char *)(cnk->pnum)) = (char)currlen; + else if (cnk->cflags == DP_C_SHORT) + *((short int *)(cnk->pnum)) = (short int)currlen; + else if (cnk->cflags == DP_C_LONG) + *((long int *)(cnk->pnum)) = (long int)currlen; + else if (cnk->cflags == DP_C_LLONG) + *((LLONG *)(cnk->pnum)) = (LLONG)currlen; + else if (cnk->cflags == DP_C_SIZET) + *((ssize_t *)(cnk->pnum)) = (ssize_t)currlen; + else + *((int *)(cnk->pnum)) = (int)currlen; + break; + + case CNK_PRCNT: + dopr_outch (buffer, &currlen, maxlen, '%'); + break; + + default: + /* what ?? */ + goto done; + } + cnk = cnk->next; + } + if (maxlen != 0) { + if (currlen < maxlen - 1) + buffer[currlen] = '\0'; + else if (maxlen > 0) + buffer[maxlen - 1] = '\0'; + } + ret = currlen; + +done: + va_end(args); + + while (chunks) { + cnk = chunks->next; + free(chunks); + chunks = cnk; + } + if (clist) { + for (pnum = 0; pnum < max_pos; pnum++) { + if (clist[pnum].chunks) free(clist[pnum].chunks); + } + free(clist); + } + return ret; +} + +static void fmtstr(char *buffer, size_t *currlen, size_t maxlen, + char *value, int flags, int min, int max) +{ + int padlen, strln; /* amount to pad */ + int cnt = 0; + +#ifdef DEBUG_SNPRINTF + printf("fmtstr min=%d max=%d s=[%s]\n", min, max, value); +#endif + if (value == 0) { + value = "<NULL>"; + } + + for (strln = 0; strln < max && value[strln]; ++strln); /* strlen */ + padlen = min - strln; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justify */ + + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + while (*value && (cnt < max)) { + dopr_outch (buffer, currlen, maxlen, *value++); + ++cnt; + } + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +/* Have to handle DP_F_NUM (ie 0x and 0 alternates) */ + +static void fmtint(char *buffer, size_t *currlen, size_t maxlen, + LLONG value, int base, int min, int max, int flags) +{ + int signvalue = 0; + unsigned LLONG uvalue; + char convert[20]; + int place = 0; + int spadlen = 0; /* amount to space pad */ + int zpadlen = 0; /* amount to zero pad */ + int caps = 0; + + if (max < 0) + max = 0; + + uvalue = value; + + if(!(flags & DP_F_UNSIGNED)) { + if( value < 0 ) { + signvalue = '-'; + uvalue = -value; + } else { + if (flags & DP_F_PLUS) /* Do a sign (+/i) */ + signvalue = '+'; + else if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ + + do { + convert[place++] = + (caps? "0123456789ABCDEF":"0123456789abcdef") + [uvalue % (unsigned)base ]; + uvalue = (uvalue / (unsigned)base ); + } while(uvalue && (place < 20)); + if (place == 20) place--; + convert[place] = 0; + + zpadlen = max - place; + spadlen = min - MAX (max, place) - (signvalue ? 1 : 0); + if (zpadlen < 0) zpadlen = 0; + if (spadlen < 0) spadlen = 0; + if (flags & DP_F_ZERO) { + zpadlen = MAX(zpadlen, spadlen); + spadlen = 0; + } + if (flags & DP_F_MINUS) + spadlen = -spadlen; /* Left Justifty */ + +#ifdef DEBUG_SNPRINTF + printf("zpad: %d, spad: %d, min: %d, max: %d, place: %d\n", + zpadlen, spadlen, min, max, place); +#endif + + /* Spaces */ + while (spadlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --spadlen; + } + + /* Sign */ + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + /* Zeros */ + if (zpadlen > 0) { + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + } + + /* Digits */ + while (place > 0) + dopr_outch (buffer, currlen, maxlen, convert[--place]); + + /* Left Justified spaces */ + while (spadlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++spadlen; + } +} + +static LDOUBLE abs_val(LDOUBLE value) +{ + LDOUBLE result = value; + + if (value < 0) + result = -value; + + return result; +} + +static LDOUBLE POW10(int exp) +{ + LDOUBLE result = 1; + + while (exp) { + result *= 10; + exp--; + } + + return result; +} + +static LLONG ROUND(LDOUBLE value) +{ + LLONG intpart; + + intpart = (LLONG)value; + value = value - intpart; + if (value >= 0.5) intpart++; + + return intpart; +} + +/* a replacement for modf that doesn't need the math library. Should + be portable, but slow */ +static double my_modf(double x0, double *iptr) +{ + int i; + LLONG l=0; + double x = x0; + double f = 1.0; + + for (i=0;i<100;i++) { + l = (long)x; + if (l <= (x+1) && l >= (x-1)) break; + x *= 0.1; + f *= 10.0; + } + + if (i == 100) { + /* yikes! the number is beyond what we can handle. What do we do? */ + (*iptr) = 0; + return 0; + } + + if (i != 0) { + double i2; + double ret; + + ret = my_modf(x0-l*f, &i2); + (*iptr) = l*f + i2; + return ret; + } + + (*iptr) = l; + return x - (*iptr); +} + + +static void fmtfp (char *buffer, size_t *currlen, size_t maxlen, + LDOUBLE fvalue, int min, int max, int flags) +{ + int signvalue = 0; + double ufvalue; + char iconvert[311]; + char fconvert[311]; + int iplace = 0; + int fplace = 0; + int padlen = 0; /* amount to pad */ + int zpadlen = 0; + int caps = 0; + int idx; + double intpart; + double fracpart; + double temp; + + /* + * AIX manpage says the default is 0, but Solaris says the default + * is 6, and sprintf on AIX defaults to 6 + */ + if (max < 0) + max = 6; + + ufvalue = abs_val (fvalue); + + if (fvalue < 0) { + signvalue = '-'; + } else { + if (flags & DP_F_PLUS) { /* Do a sign (+/i) */ + signvalue = '+'; + } else { + if (flags & DP_F_SPACE) + signvalue = ' '; + } + } + +#if 0 + if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */ +#endif + +#if 0 + if (max == 0) ufvalue += 0.5; /* if max = 0 we must round */ +#endif + + /* + * Sorry, we only support 9 digits past the decimal because of our + * conversion method + */ + if (max > 9) + max = 9; + + /* We "cheat" by converting the fractional part to integer by + * multiplying by a factor of 10 + */ + + temp = ufvalue; + my_modf(temp, &intpart); + + fracpart = ROUND((POW10(max)) * (ufvalue - intpart)); + + if (fracpart >= POW10(max)) { + intpart++; + fracpart -= POW10(max); + } + + + /* Convert integer part */ + do { + temp = intpart*0.1; + my_modf(temp, &intpart); + idx = (int) ((temp -intpart +0.05)* 10.0); + /* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */ + /* printf ("%llf, %f, %x\n", temp, intpart, idx); */ + iconvert[iplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while (intpart && (iplace < 311)); + if (iplace == 311) iplace--; + iconvert[iplace] = 0; + + /* Convert fractional part */ + if (fracpart) + { + do { + temp = fracpart*0.1; + my_modf(temp, &fracpart); + idx = (int) ((temp -fracpart +0.05)* 10.0); + /* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */ + /* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */ + fconvert[fplace++] = + (caps? "0123456789ABCDEF":"0123456789abcdef")[idx]; + } while(fracpart && (fplace < 311)); + if (fplace == 311) fplace--; + } + fconvert[fplace] = 0; + + /* -1 for decimal point, another -1 if we are printing a sign */ + padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0); + zpadlen = max - fplace; + if (zpadlen < 0) zpadlen = 0; + if (padlen < 0) + padlen = 0; + if (flags & DP_F_MINUS) + padlen = -padlen; /* Left Justifty */ + + if ((flags & DP_F_ZERO) && (padlen > 0)) { + if (signvalue) { + dopr_outch (buffer, currlen, maxlen, signvalue); + --padlen; + signvalue = 0; + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --padlen; + } + } + while (padlen > 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + --padlen; + } + if (signvalue) + dopr_outch (buffer, currlen, maxlen, signvalue); + + while (iplace > 0) + dopr_outch (buffer, currlen, maxlen, iconvert[--iplace]); + +#ifdef DEBUG_SNPRINTF + printf("fmtfp: fplace=%d zpadlen=%d\n", fplace, zpadlen); +#endif + + /* + * Decimal point. This should probably use locale to find the correct + * char to print out. + */ + if (max > 0) { + dopr_outch (buffer, currlen, maxlen, '.'); + + while (zpadlen > 0) { + dopr_outch (buffer, currlen, maxlen, '0'); + --zpadlen; + } + + while (fplace > 0) + dopr_outch (buffer, currlen, maxlen, fconvert[--fplace]); + } + + while (padlen < 0) { + dopr_outch (buffer, currlen, maxlen, ' '); + ++padlen; + } +} + +static void dopr_outch(char *buffer, size_t *currlen, size_t maxlen, char c) +{ + if (*currlen < maxlen) { + buffer[(*currlen)] = c; + } + (*currlen)++; +} + +static struct pr_chunk *new_chunk(void) { + struct pr_chunk *new_c = (struct pr_chunk *)malloc(sizeof(struct pr_chunk)); + + if (!new_c) + return NULL; + + new_c->type = 0; + new_c->num = 0; + new_c->min = 0; + new_c->min_star = NULL; + new_c->max = -1; + new_c->max_star = NULL; + new_c->flags = 0; + new_c->cflags = 0; + new_c->start = 0; + new_c->len = 0; + new_c->value = 0; + new_c->fvalue = 0; + new_c->strvalue = NULL; + new_c->pnum = NULL; + new_c->next = NULL; + + return new_c; +} + +static int add_cnk_list_entry(struct pr_chunk_x **list, + int max_num, struct pr_chunk *chunk) { + struct pr_chunk_x *l; + struct pr_chunk **c; + int max; + int cnum; + int i, pos; + + if (chunk->num > max_num) { + max = chunk->num; + + if (*list == NULL) { + l = (struct pr_chunk_x *)malloc(sizeof(struct pr_chunk_x) * max); + pos = 0; + } else { + l = (struct pr_chunk_x *)realloc(*list, sizeof(struct pr_chunk_x) * max); + pos = max_num; + } + if (l == NULL) { + for (i = 0; i < max; i++) { + if ((*list)[i].chunks) free((*list)[i].chunks); + } + return 0; + } + for (i = pos; i < max; i++) { + l[i].chunks = NULL; + l[i].num = 0; + } + } else { + l = *list; + max = max_num; + } + + i = chunk->num - 1; + cnum = l[i].num + 1; + if (l[i].chunks == NULL) { + c = (struct pr_chunk **)malloc(sizeof(struct pr_chunk *) * cnum); + } else { + c = (struct pr_chunk **)realloc(l[i].chunks, sizeof(struct pr_chunk *) * cnum); + } + if (c == NULL) { + for (i = 0; i < max; i++) { + if (l[i].chunks) free(l[i].chunks); + } + return 0; + } + c[l[i].num] = chunk; + l[i].chunks = c; + l[i].num = cnum; + + *list = l; + return max; +} + + int rep_vsnprintf (char *str, size_t count, const char *fmt, va_list args) +{ + return dopr(str, count, fmt, args); +} +#endif + +/* yes this really must be a ||. Don't muck with this (tridge) + * + * The logic for these two is that we need our own definition if the + * OS *either* has no definition of *sprintf, or if it does have one + * that doesn't work properly according to the autoconf test. + */ +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_snprintf(char *str,size_t count,const char *fmt,...) +{ + size_t ret; + va_list ap; + + va_start(ap, fmt); + ret = vsnprintf(str, count, fmt, ap); + va_end(ap); + return ret; +} +#endif + +#ifndef HAVE_C99_VSNPRINTF + int rep_printf(const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stdout); + } + free(s); + + return ret; +} +#endif + +#ifndef HAVE_C99_VSNPRINTF + int rep_fprintf(FILE *stream, const char *fmt, ...) +{ + va_list ap; + int ret; + char *s; + + s = NULL; + va_start(ap, fmt); + ret = vasprintf(&s, fmt, ap); + va_end(ap); + + if (s) { + fwrite(s, 1, strlen(s), stream); + } + free(s); + + return ret; +} +#endif + +#endif + +#if !defined(HAVE_VASPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_vasprintf(char **ptr, const char *format, va_list ap) +{ + int ret; + va_list ap2; + + VA_COPY(ap2, ap); + ret = vsnprintf(NULL, 0, format, ap2); + va_end(ap2); + if (ret < 0) return ret; + + (*ptr) = (char *)malloc(ret+1); + if (!*ptr) return -1; + + VA_COPY(ap2, ap); + ret = vsnprintf(*ptr, ret+1, format, ap2); + va_end(ap2); + + return ret; +} +#endif + +#if !defined(HAVE_ASPRINTF) || !defined(HAVE_C99_VSNPRINTF) + int rep_asprintf(char **ptr, const char *format, ...) +{ + va_list ap; + int ret; + + *ptr = NULL; + va_start(ap, format); + ret = vasprintf(ptr, format, ap); + va_end(ap); + + return ret; +} +#endif + +#ifdef TEST_SNPRINTF + + int sprintf(char *str,const char *fmt,...); + int printf(const char *fmt,...); + + int main (void) +{ + char buf1[1024]; + char buf2[1024]; + char *buf3; + char *fp_fmt[] = { + "%1.1f", + "%-1.5f", + "%1.5f", + "%123.9f", + "%10.5f", + "% 10.5f", + "%+22.9f", + "%+4.9f", + "%01.3f", + "%4f", + "%3.1f", + "%3.2f", + "%.0f", + "%f", + "%-8.8f", + "%-9.9f", + NULL + }; + double fp_nums[] = { 6442452944.1234, -1.5, 134.21, 91340.2, 341.1234, 203.9, 0.96, 0.996, + 0.9996, 1.996, 4.136, 5.030201, 0.00205, + /* END LIST */ 0}; + char *int_fmt[] = { + "%-1.5d", + "%1.5d", + "%123.9d", + "%5.5d", + "%10.5d", + "% 10.5d", + "%+22.33d", + "%01.3d", + "%4d", + "%d", + NULL + }; + long int_nums[] = { -1, 134, 91340, 341, 0203, 1234567890, 0}; + char *str_fmt[] = { + "%10.5s", + "%-10.5s", + "%5.10s", + "%-5.10s", + "%10.1s", + "%0.10s", + "%10.0s", + "%1.10s", + "%s", + "%.1s", + "%.10s", + "%10s", + NULL + }; + char *str_vals[] = {"hello", "a", "", "a longer string", NULL}; +#ifdef HAVE_LONG_LONG + char *ll_fmt[] = { + "%llu", + NULL + }; + LLONG ll_nums[] = { 134, 91340, 341, 0203, 1234567890, 128006186140000000LL, 0}; +#endif + int x, y; + int fail = 0; + int num = 0; + int l1, l2; + char *ss_fmt[] = { + "%zd", + "%zu", + NULL + }; + size_t ss_nums[] = {134, 91340, 123456789, 0203, 1234567890, 0}; + + printf ("Testing snprintf format codes against system sprintf...\n"); + + for (x = 0; fp_fmt[x] ; x++) { + for (y = 0; fp_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), fp_fmt[x], fp_nums[y]); + l2 = sprintf (buf2, fp_fmt[x], fp_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + fp_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; int_fmt[x] ; x++) { + for (y = 0; int_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), int_fmt[x], int_nums[y]); + l2 = sprintf (buf2, int_fmt[x], int_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + int_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + + for (x = 0; str_fmt[x] ; x++) { + for (y = 0; str_vals[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), str_fmt[x], str_vals[y]); + l2 = sprintf (buf2, str_fmt[x], str_vals[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + str_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } + +#ifdef HAVE_LONG_LONG + for (x = 0; ll_fmt[x] ; x++) { + for (y = 0; ll_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), ll_fmt[x], ll_nums[y]); + l2 = sprintf (buf2, ll_fmt[x], ll_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + ll_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } +#endif + +#define BUFSZ 2048 + + buf1[0] = buf2[0] = '\0'; + if ((buf3 = malloc(BUFSZ)) == NULL) { + fail++; + } else { + num++; + memset(buf3, 'a', BUFSZ); + snprintf(buf1, sizeof(buf1), "%.*s", 1, buf3); + buf1[1023] = '\0'; + if (strcmp(buf1, "a") != 0) { + printf("length limit buf1 '%s' expected 'a'\n", buf1); + fail++; + } + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*1$d %2$s %3$*1$.*1$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + l2 = sprintf(buf2, "%4$*4$d %2$s %3$*4$.*4$f", 3, "pos test", 12.3456, 9); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%4$*1$d %2$s %3$*1$.*1$f", l1, buf1, l2, buf2); + fail++; + } + + for (x = 0; ss_fmt[x] ; x++) { + for (y = 0; ss_nums[y] != 0 ; y++) { + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), ss_fmt[x], ss_nums[y]); + l2 = sprintf (buf2, ss_fmt[x], ss_nums[y]); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp (buf1, buf2) || (l1 != l2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + ss_fmt[x], l1, buf1, l2, buf2); + fail++; + } + num++; + } + } +#if 0 + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%lld", (LLONG)1234567890); + l2 = sprintf(buf2, "%lld", (LLONG)1234567890); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%lld", l1, buf1, l2, buf2); + fail++; + } + + buf1[0] = buf2[0] = '\0'; + l1 = snprintf(buf1, sizeof(buf1), "%Lf", (LDOUBLE)890.1234567890123); + l2 = sprintf(buf2, "%Lf", (LDOUBLE)890.1234567890123); + buf1[1023] = buf2[1023] = '\0'; + if (strcmp(buf1, buf2)) { + printf("snprintf doesn't match Format: %s\n\tsnprintf(%d) = [%s]\n\t sprintf(%d) = [%s]\n", + "%Lf", l1, buf1, l2, buf2); + fail++; + } +#endif + printf ("%d tests failed out of %d.\n", fail, num); + + printf("seeing how many digits we support\n"); + { + double v0 = 0.12345678901234567890123456789012345678901; + for (x=0; x<100; x++) { + double p = pow(10, x); + double r = v0*p; + snprintf(buf1, sizeof(buf1), "%1.1f", r); + sprintf(buf2, "%1.1f", r); + if (strcmp(buf1, buf2)) { + printf("we seem to support %d digits\n", x-1); + break; + } + } + } + + return 0; +} +#endif /* TEST_SNPRINTF */ diff --git a/ctdb/lib/replace/socket.c b/ctdb/lib/replace/socket.c new file mode 100644 index 0000000000..35e975fce7 --- /dev/null +++ b/ctdb/lib/replace/socket.c @@ -0,0 +1,35 @@ +/* + * Unix SMB/CIFS implementation. + * + * Dummy replacements for socket functions. + * + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +int rep_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + errno = ENOSYS; + return -1; +} + +struct hostent *rep_gethostbyname(const char *name) +{ + errno = ENOSYS; + return NULL; +} diff --git a/ctdb/lib/replace/socketpair.c b/ctdb/lib/replace/socketpair.c new file mode 100644 index 0000000000..c775730952 --- /dev/null +++ b/ctdb/lib/replace/socketpair.c @@ -0,0 +1,46 @@ +/* + * Unix SMB/CIFS implementation. + * replacement routines for broken systems + * Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2006 + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * ** NOTE! The following LGPL license applies to the replace + * ** library. This does NOT imply that all of Samba is released + * ** under the LGPL + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "system/network.h" + +int rep_socketpair(int d, int type, int protocol, int sv[2]) +{ + if (d != AF_UNIX) { + errno = EAFNOSUPPORT; + return -1; + } + + if (protocol != 0) { + errno = EPROTONOSUPPORT; + return -1; + } + + if (type != SOCK_STREAM) { + errno = EOPNOTSUPP; + return -1; + } + + return pipe(sv); +} diff --git a/ctdb/lib/replace/strptime.c b/ctdb/lib/replace/strptime.c new file mode 100644 index 0000000000..20e5d8c39b --- /dev/null +++ b/ctdb/lib/replace/strptime.c @@ -0,0 +1,993 @@ +/* Convert a string representation of time to a time value. + Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 3 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + see <http://www.gnu.org/licenses/>. */ + +/* XXX This version of the implementation is not really complete. + Some of the fields cannot add information alone. But if seeing + some of them in the same format (such as year, week and weekday) + this is enough information for determining the date. */ + +#include "replace.h" +#include "system/locale.h" +#include "system/time.h" + +#ifndef __P +# if defined (__GNUC__) || (defined (__STDC__) && __STDC__) +# define __P(args) args +# else +# define __P(args) () +# endif /* GCC. */ +#endif /* Not __P. */ + +#if ! HAVE_LOCALTIME_R && ! defined localtime_r +# ifdef _LIBC +# define localtime_r __localtime_r +# else +/* Approximate localtime_r as best we can in its absence. */ +# define localtime_r my_localtime_r +static struct tm *localtime_r __P ((const time_t *, struct tm *)); +static struct tm * +localtime_r (t, tp) + const time_t *t; + struct tm *tp; +{ + struct tm *l = localtime (t); + if (! l) + return 0; + *tp = *l; + return tp; +} +# endif /* ! _LIBC */ +#endif /* ! HAVE_LOCALTIME_R && ! defined (localtime_r) */ + + +#define match_char(ch1, ch2) if (ch1 != ch2) return NULL +#if defined __GNUC__ && __GNUC__ >= 2 +# define match_string(cs1, s2) \ + ({ size_t len = strlen (cs1); \ + int result = strncasecmp ((cs1), (s2), len) == 0; \ + if (result) (s2) += len; \ + result; }) +#else +/* Oh come on. Get a reasonable compiler. */ +# define match_string(cs1, s2) \ + (strncasecmp ((cs1), (s2), strlen (cs1)) ? 0 : ((s2) += strlen (cs1), 1)) +#endif +/* We intentionally do not use isdigit() for testing because this will + lead to problems with the wide character version. */ +#define get_number(from, to, n) \ + do { \ + int __n = n; \ + val = 0; \ + while (*rp == ' ') \ + ++rp; \ + if (*rp < '0' || *rp > '9') \ + return NULL; \ + do { \ + val *= 10; \ + val += *rp++ - '0'; \ + } while (--__n > 0 && val * 10 <= to && *rp >= '0' && *rp <= '9'); \ + if (val < from || val > to) \ + return NULL; \ + } while (0) +#ifdef _NL_CURRENT +# define get_alt_number(from, to, n) \ + ({ \ + __label__ do_normal; \ + if (*decided != raw) \ + { \ + const char *alts = _NL_CURRENT (LC_TIME, ALT_DIGITS); \ + int __n = n; \ + int any = 0; \ + while (*rp == ' ') \ + ++rp; \ + val = 0; \ + do { \ + val *= 10; \ + while (*alts != '\0') \ + { \ + size_t len = strlen (alts); \ + if (strncasecmp (alts, rp, len) == 0) \ + break; \ + alts += len + 1; \ + ++val; \ + } \ + if (*alts == '\0') \ + { \ + if (*decided == not && ! any) \ + goto do_normal; \ + /* If we haven't read anything it's an error. */ \ + if (! any) \ + return NULL; \ + /* Correct the premature multiplication. */ \ + val /= 10; \ + break; \ + } \ + else \ + *decided = loc; \ + } while (--__n > 0 && val * 10 <= to); \ + if (val < from || val > to) \ + return NULL; \ + } \ + else \ + { \ + do_normal: \ + get_number (from, to, n); \ + } \ + 0; \ + }) +#else +# define get_alt_number(from, to, n) \ + /* We don't have the alternate representation. */ \ + get_number(from, to, n) +#endif +#define recursive(new_fmt) \ + (*(new_fmt) != '\0' \ + && (rp = strptime_internal (rp, (new_fmt), tm, decided, era_cnt)) != NULL) + + +#ifdef _LIBC +/* This is defined in locale/C-time.c in the GNU libc. */ +extern const struct locale_data _nl_C_LC_TIME; +extern const unsigned short int __mon_yday[2][13]; + +# define weekday_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (DAY_1)].string) +# define ab_weekday_name \ + (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABDAY_1)].string) +# define month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (MON_1)].string) +# define ab_month_name (&_nl_C_LC_TIME.values[_NL_ITEM_INDEX (ABMON_1)].string) +# define HERE_D_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_T_FMT)].string) +# define HERE_D_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (D_FMT)].string) +# define HERE_AM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (AM_STR)].string) +# define HERE_PM_STR (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (PM_STR)].string) +# define HERE_T_FMT_AMPM \ + (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT_AMPM)].string) +# define HERE_T_FMT (_nl_C_LC_TIME.values[_NL_ITEM_INDEX (T_FMT)].string) + +# define strncasecmp(s1, s2, n) __strncasecmp (s1, s2, n) +#else +static char const weekday_name[][10] = + { + "Sunday", "Monday", "Tuesday", "Wednesday", + "Thursday", "Friday", "Saturday" + }; +static char const ab_weekday_name[][4] = + { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; +static char const month_name[][10] = + { + "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December" + }; +static char const ab_month_name[][4] = + { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; +# define HERE_D_T_FMT "%a %b %e %H:%M:%S %Y" +# define HERE_D_FMT "%m/%d/%y" +# define HERE_AM_STR "AM" +# define HERE_PM_STR "PM" +# define HERE_T_FMT_AMPM "%I:%M:%S %p" +# define HERE_T_FMT "%H:%M:%S" + +static const unsigned short int __mon_yday[2][13] = + { + /* Normal years. */ + { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }, + /* Leap years. */ + { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } + }; +#endif + +/* Status of lookup: do we use the locale data or the raw data? */ +enum locale_status { not, loc, raw }; + + +#ifndef __isleap +/* Nonzero if YEAR is a leap year (every 4 years, + except every 100th isn't, and every 400th is). */ +# define __isleap(year) \ + ((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0)) +#endif + +/* Compute the day of the week. */ +static void +day_of_the_week (struct tm *tm) +{ + /* We know that January 1st 1970 was a Thursday (= 4). Compute the + the difference between this data in the one on TM and so determine + the weekday. */ + int corr_year = 1900 + tm->tm_year - (tm->tm_mon < 2); + int wday = (-473 + + (365 * (tm->tm_year - 70)) + + (corr_year / 4) + - ((corr_year / 4) / 25) + ((corr_year / 4) % 25 < 0) + + (((corr_year / 4) / 25) / 4) + + __mon_yday[0][tm->tm_mon] + + tm->tm_mday - 1); + tm->tm_wday = ((wday % 7) + 7) % 7; +} + +/* Compute the day of the year. */ +static void +day_of_the_year (struct tm *tm) +{ + tm->tm_yday = (__mon_yday[__isleap (1900 + tm->tm_year)][tm->tm_mon] + + (tm->tm_mday - 1)); +} + +static char * +#ifdef _LIBC +internal_function +#endif +strptime_internal __P ((const char *rp, const char *fmt, struct tm *tm, + enum locale_status *decided, int era_cnt)); + +static char * +#ifdef _LIBC +internal_function +#endif +strptime_internal (rp, fmt, tm, decided, era_cnt) + const char *rp; + const char *fmt; + struct tm *tm; + enum locale_status *decided; + int era_cnt; +{ + int cnt; + size_t val; + int have_I, is_pm; + int century, want_century; + int want_era; + int have_wday, want_xday; + int have_yday; + int have_mon, have_mday; +#ifdef _NL_CURRENT + const char *rp_backup; + size_t num_eras; + struct era_entry *era; + + era = NULL; +#endif + + have_I = is_pm = 0; + century = -1; + want_century = 0; + want_era = 0; + + have_wday = want_xday = have_yday = have_mon = have_mday = 0; + + while (*fmt != '\0') + { + /* A white space in the format string matches 0 more or white + space in the input string. */ + if (isspace (*fmt)) + { + while (isspace (*rp)) + ++rp; + ++fmt; + continue; + } + + /* Any character but `%' must be matched by the same character + in the iput string. */ + if (*fmt != '%') + { + match_char (*fmt++, *rp++); + continue; + } + + ++fmt; +#ifndef _NL_CURRENT + /* We need this for handling the `E' modifier. */ + start_over: +#endif + +#ifdef _NL_CURRENT + /* Make back up of current processing pointer. */ + rp_backup = rp; +#endif + + switch (*fmt++) + { + case '%': + /* Match the `%' character itself. */ + match_char ('%', *rp++); + break; + case 'a': + case 'A': + /* Match day of week. */ + for (cnt = 0; cnt < 7; ++cnt) + { +#ifdef _NL_CURRENT + if (*decided !=raw) + { + if (match_string (_NL_CURRENT (LC_TIME, DAY_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, DAY_1 + cnt), + weekday_name[cnt])) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, ABDAY_1 + cnt), + ab_weekday_name[cnt])) + *decided = loc; + break; + } + } +#endif + if (*decided != loc + && (match_string (weekday_name[cnt], rp) + || match_string (ab_weekday_name[cnt], rp))) + { + *decided = raw; + break; + } + } + if (cnt == 7) + /* Does not match a weekday name. */ + return NULL; + tm->tm_wday = cnt; + have_wday = 1; + break; + case 'b': + case 'B': + case 'h': + /* Match month name. */ + for (cnt = 0; cnt < 12; ++cnt) + { +#ifdef _NL_CURRENT + if (*decided !=raw) + { + if (match_string (_NL_CURRENT (LC_TIME, MON_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, MON_1 + cnt), + month_name[cnt])) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), rp)) + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, ABMON_1 + cnt), + ab_month_name[cnt])) + *decided = loc; + break; + } + } +#endif + if (match_string (month_name[cnt], rp) + || match_string (ab_month_name[cnt], rp)) + { + *decided = raw; + break; + } + } + if (cnt == 12) + /* Does not match a month name. */ + return NULL; + tm->tm_mon = cnt; + want_xday = 1; + break; + case 'c': + /* Match locale's date and time format. */ +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, D_T_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not && + strcmp (_NL_CURRENT (LC_TIME, D_T_FMT), HERE_D_T_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } +#endif + if (!recursive (HERE_D_T_FMT)) + return NULL; + want_xday = 1; + break; + case 'C': + /* Match century number. */ +#ifdef _NL_CURRENT + match_century: +#endif + get_number (0, 99, 2); + century = val; + want_xday = 1; + break; + case 'd': + case 'e': + /* Match day of month. */ + get_number (1, 31, 2); + tm->tm_mday = val; + have_mday = 1; + want_xday = 1; + break; + case 'F': + if (!recursive ("%Y-%m-%d")) + return NULL; + want_xday = 1; + break; + case 'x': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, D_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not + && strcmp (_NL_CURRENT (LC_TIME, D_FMT), HERE_D_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } +#endif + /* Fall through. */ + case 'D': + /* Match standard day format. */ + if (!recursive (HERE_D_FMT)) + return NULL; + want_xday = 1; + break; + case 'k': + case 'H': + /* Match hour in 24-hour clock. */ + get_number (0, 23, 2); + tm->tm_hour = val; + have_I = 0; + break; + case 'I': + /* Match hour in 12-hour clock. */ + get_number (1, 12, 2); + tm->tm_hour = val % 12; + have_I = 1; + break; + case 'j': + /* Match day number of year. */ + get_number (1, 366, 3); + tm->tm_yday = val - 1; + have_yday = 1; + break; + case 'm': + /* Match number of month. */ + get_number (1, 12, 2); + tm->tm_mon = val - 1; + have_mon = 1; + want_xday = 1; + break; + case 'M': + /* Match minute. */ + get_number (0, 59, 2); + tm->tm_min = val; + break; + case 'n': + case 't': + /* Match any white space. */ + while (isspace (*rp)) + ++rp; + break; + case 'p': + /* Match locale's equivalent of AM/PM. */ +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (match_string (_NL_CURRENT (LC_TIME, AM_STR), rp)) + { + if (strcmp (_NL_CURRENT (LC_TIME, AM_STR), HERE_AM_STR)) + *decided = loc; + break; + } + if (match_string (_NL_CURRENT (LC_TIME, PM_STR), rp)) + { + if (strcmp (_NL_CURRENT (LC_TIME, PM_STR), HERE_PM_STR)) + *decided = loc; + is_pm = 1; + break; + } + *decided = raw; + } +#endif + if (!match_string (HERE_AM_STR, rp)) { + if (match_string (HERE_PM_STR, rp)) { + is_pm = 1; + } else { + return NULL; + } + } + break; + case 'r': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, T_FMT_AMPM))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (*decided == not && + strcmp (_NL_CURRENT (LC_TIME, T_FMT_AMPM), + HERE_T_FMT_AMPM)) + *decided = loc; + break; + } + *decided = raw; + } +#endif + if (!recursive (HERE_T_FMT_AMPM)) + return NULL; + break; + case 'R': + if (!recursive ("%H:%M")) + return NULL; + break; + case 's': + { + /* The number of seconds may be very high so we cannot use + the `get_number' macro. Instead read the number + character for character and construct the result while + doing this. */ + time_t secs = 0; + if (*rp < '0' || *rp > '9') + /* We need at least one digit. */ + return NULL; + + do + { + secs *= 10; + secs += *rp++ - '0'; + } + while (*rp >= '0' && *rp <= '9'); + + if (localtime_r (&secs, tm) == NULL) + /* Error in function. */ + return NULL; + } + break; + case 'S': + get_number (0, 61, 2); + tm->tm_sec = val; + break; + case 'X': +#ifdef _NL_CURRENT + if (*decided != raw) + { + if (!recursive (_NL_CURRENT (LC_TIME, T_FMT))) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (_NL_CURRENT (LC_TIME, T_FMT), HERE_T_FMT)) + *decided = loc; + break; + } + *decided = raw; + } +#endif + /* Fall through. */ + case 'T': + if (!recursive (HERE_T_FMT)) + return NULL; + break; + case 'u': + get_number (1, 7, 1); + tm->tm_wday = val % 7; + have_wday = 1; + break; + case 'g': + get_number (0, 99, 2); + /* XXX This cannot determine any field in TM. */ + break; + case 'G': + if (*rp < '0' || *rp > '9') + return NULL; + /* XXX Ignore the number since we would need some more + information to compute a real date. */ + do + ++rp; + while (*rp >= '0' && *rp <= '9'); + break; + case 'U': + case 'V': + case 'W': + get_number (0, 53, 2); + /* XXX This cannot determine any field in TM without some + information. */ + break; + case 'w': + /* Match number of weekday. */ + get_number (0, 6, 1); + tm->tm_wday = val; + have_wday = 1; + break; + case 'y': +#ifdef _NL_CURRENT + match_year_in_century: +#endif + /* Match year within century. */ + get_number (0, 99, 2); + /* The "Year 2000: The Millennium Rollover" paper suggests that + values in the range 69-99 refer to the twentieth century. */ + tm->tm_year = val >= 69 ? val : val + 100; + /* Indicate that we want to use the century, if specified. */ + want_century = 1; + want_xday = 1; + break; + case 'Y': + /* Match year including century number. */ + get_number (0, 9999, 4); + tm->tm_year = val - 1900; + want_century = 0; + want_xday = 1; + break; + case 'Z': + /* XXX How to handle this? */ + break; + case 'E': +#ifdef _NL_CURRENT + switch (*fmt++) + { + case 'c': + /* Match locale's alternate date and time format. */ + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_T_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, D_T_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_D_T_FMT)) + *decided = loc; + want_xday = 1; + break; + } + *decided = raw; + } + /* The C locale has no era information, so use the + normal representation. */ + if (!recursive (HERE_D_T_FMT)) + return NULL; + want_xday = 1; + break; + case 'C': + if (*decided != raw) + { + if (era_cnt >= 0) + { + era = _nl_select_era_entry (era_cnt); + if (match_string (era->era_name, rp)) + { + *decided = loc; + break; + } + else + return NULL; + } + else + { + num_eras = _NL_CURRENT_WORD (LC_TIME, + _NL_TIME_ERA_NUM_ENTRIES); + for (era_cnt = 0; era_cnt < (int) num_eras; + ++era_cnt, rp = rp_backup) + { + era = _nl_select_era_entry (era_cnt); + if (match_string (era->era_name, rp)) + { + *decided = loc; + break; + } + } + if (era_cnt == (int) num_eras) + { + era_cnt = -1; + if (*decided == loc) + return NULL; + } + else + break; + } + + *decided = raw; + } + /* The C locale has no era information, so use the + normal representation. */ + goto match_century; + case 'y': + if (*decided == raw) + goto match_year_in_century; + + get_number(0, 9999, 4); + tm->tm_year = val; + want_era = 1; + want_xday = 1; + break; + case 'Y': + if (*decided != raw) + { + num_eras = _NL_CURRENT_WORD (LC_TIME, + _NL_TIME_ERA_NUM_ENTRIES); + for (era_cnt = 0; era_cnt < (int) num_eras; + ++era_cnt, rp = rp_backup) + { + era = _nl_select_era_entry (era_cnt); + if (recursive (era->era_format)) + break; + } + if (era_cnt == (int) num_eras) + { + era_cnt = -1; + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + *decided = loc; + era_cnt = -1; + break; + } + + *decided = raw; + } + get_number (0, 9999, 4); + tm->tm_year = val - 1900; + want_century = 0; + want_xday = 1; + break; + case 'x': + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_D_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, D_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_D_FMT)) + *decided = loc; + break; + } + *decided = raw; + } + if (!recursive (HERE_D_FMT)) + return NULL; + break; + case 'X': + if (*decided != raw) + { + const char *fmt = _NL_CURRENT (LC_TIME, ERA_T_FMT); + + if (*fmt == '\0') + fmt = _NL_CURRENT (LC_TIME, T_FMT); + + if (!recursive (fmt)) + { + if (*decided == loc) + return NULL; + else + rp = rp_backup; + } + else + { + if (strcmp (fmt, HERE_T_FMT)) + *decided = loc; + break; + } + *decided = raw; + } + if (!recursive (HERE_T_FMT)) + return NULL; + break; + default: + return NULL; + } + break; +#else + /* We have no information about the era format. Just use + the normal format. */ + if (*fmt != 'c' && *fmt != 'C' && *fmt != 'y' && *fmt != 'Y' + && *fmt != 'x' && *fmt != 'X') + /* This is an illegal format. */ + return NULL; + + goto start_over; +#endif + case 'O': + switch (*fmt++) + { + case 'd': + case 'e': + /* Match day of month using alternate numeric symbols. */ + get_alt_number (1, 31, 2); + tm->tm_mday = val; + have_mday = 1; + want_xday = 1; + break; + case 'H': + /* Match hour in 24-hour clock using alternate numeric + symbols. */ + get_alt_number (0, 23, 2); + tm->tm_hour = val; + have_I = 0; + break; + case 'I': + /* Match hour in 12-hour clock using alternate numeric + symbols. */ + get_alt_number (1, 12, 2); + tm->tm_hour = val - 1; + have_I = 1; + break; + case 'm': + /* Match month using alternate numeric symbols. */ + get_alt_number (1, 12, 2); + tm->tm_mon = val - 1; + have_mon = 1; + want_xday = 1; + break; + case 'M': + /* Match minutes using alternate numeric symbols. */ + get_alt_number (0, 59, 2); + tm->tm_min = val; + break; + case 'S': + /* Match seconds using alternate numeric symbols. */ + get_alt_number (0, 61, 2); + tm->tm_sec = val; + break; + case 'U': + case 'V': + case 'W': + get_alt_number (0, 53, 2); + /* XXX This cannot determine any field in TM without + further information. */ + break; + case 'w': + /* Match number of weekday using alternate numeric symbols. */ + get_alt_number (0, 6, 1); + tm->tm_wday = val; + have_wday = 1; + break; + case 'y': + /* Match year within century using alternate numeric symbols. */ + get_alt_number (0, 99, 2); + tm->tm_year = val >= 69 ? val : val + 100; + want_xday = 1; + break; + default: + return NULL; + } + break; + default: + return NULL; + } + } + + if (have_I && is_pm) + tm->tm_hour += 12; + + if (century != -1) + { + if (want_century) + tm->tm_year = tm->tm_year % 100 + (century - 19) * 100; + else + /* Only the century, but not the year. Strange, but so be it. */ + tm->tm_year = (century - 19) * 100; + } + +#ifdef _NL_CURRENT + if (era_cnt != -1) + { + era = _nl_select_era_entry(era_cnt); + if (want_era) + tm->tm_year = (era->start_date[0] + + ((tm->tm_year - era->offset) + * era->absolute_direction)); + else + /* Era start year assumed. */ + tm->tm_year = era->start_date[0]; + } + else +#endif + if (want_era) + return NULL; + + if (want_xday && !have_wday) + { + if ( !(have_mon && have_mday) && have_yday) + { + /* We don't have tm_mon and/or tm_mday, compute them. */ + int t_mon = 0; + while (__mon_yday[__isleap(1900 + tm->tm_year)][t_mon] <= tm->tm_yday) + t_mon++; + if (!have_mon) + tm->tm_mon = t_mon - 1; + if (!have_mday) + tm->tm_mday = + (tm->tm_yday + - __mon_yday[__isleap(1900 + tm->tm_year)][t_mon - 1] + 1); + } + day_of_the_week (tm); + } + if (want_xday && !have_yday) + day_of_the_year (tm); + + return discard_const_p(char, rp); +} + + +char *rep_strptime(const char *buf, const char *format, struct tm *tm) +{ + enum locale_status decided; + +#ifdef _NL_CURRENT + decided = not; +#else + decided = raw; +#endif + return strptime_internal (buf, format, tm, &decided, -1); +} diff --git a/ctdb/lib/replace/strptime.m4 b/ctdb/lib/replace/strptime.m4 new file mode 100644 index 0000000000..8ac22f6342 --- /dev/null +++ b/ctdb/lib/replace/strptime.m4 @@ -0,0 +1,16 @@ +AC_CHECK_FUNCS(strptime) +AC_CHECK_DECLS(strptime, [], [], [#include <time.h>]) +AC_CACHE_CHECK([whether strptime is available and works],libreplace_cv_STRPTIME_OK,[ + AC_TRY_RUN([ + #define LIBREPLACE_CONFIGURE_TEST_STRPTIME + #include "$libreplacedir/test/strptime.c" + ], + [libreplace_cv_STRPTIME_OK=yes], + [libreplace_cv_STRPTIME_OK=no], + [libreplace_cv_STRPTIME_OK="assuming not"]) +]) +if test x"$libreplace_cv_STRPTIME_OK" != x"yes"; then + LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/strptime.o" +else + AC_DEFINE(HAVE_WORKING_STRPTIME,1,[Whether strptime is working correct]) +fi diff --git a/ctdb/lib/replace/system/README b/ctdb/lib/replace/system/README new file mode 100644 index 0000000000..69a2b80b56 --- /dev/null +++ b/ctdb/lib/replace/system/README @@ -0,0 +1,4 @@ +This directory contains wrappers around logical groups of system +include files. The idea is to avoid #ifdef blocks in the main code, +and instead put all the necessary conditional includes in subsystem +specific header files in this directory. diff --git a/ctdb/lib/replace/system/aio.h b/ctdb/lib/replace/system/aio.h new file mode 100644 index 0000000000..784d77fa28 --- /dev/null +++ b/ctdb/lib/replace/system/aio.h @@ -0,0 +1,32 @@ +#ifndef _system_aio_h +#define _system_aio_h +/* + Unix SMB/CIFS implementation. + + AIO system include wrappers + + Copyright (C) Andrew Tridgell 2006 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_LIBAIO_H +#include <libaio.h> +#endif + +#endif diff --git a/ctdb/lib/replace/system/capability.h b/ctdb/lib/replace/system/capability.h new file mode 100644 index 0000000000..a7b78f0275 --- /dev/null +++ b/ctdb/lib/replace/system/capability.h @@ -0,0 +1,55 @@ +#ifndef _system_capability_h +#define _system_capability_h +/* + Unix SMB/CIFS implementation. + + capability system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#ifdef HAVE_SYS_CAPABILITY_H + +#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 + +#if defined(BROKEN_RHEL5_SYS_CAP_HEADER) && !defined(_LINUX_TYPES_H) +#define BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#endif + +#include <sys/capability.h> + +#ifdef BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#undef _LINUX_TYPES_H +#undef BROKEN_RHEL5_SYS_CAP_HEADER_WORKAROUND +#endif + +#ifdef BROKEN_REDHAT_7_STATFS_WORKAROUND +#undef _PPC_STATFS_H +#undef _I386_STATFS_H +#undef BROKEN_REDHAT_7_STATFS_WORKAROUND +#endif + +#endif + +#endif diff --git a/ctdb/lib/replace/system/config.m4 b/ctdb/lib/replace/system/config.m4 new file mode 100644 index 0000000000..b7cdf1414a --- /dev/null +++ b/ctdb/lib/replace/system/config.m4 @@ -0,0 +1,145 @@ +# filesys +AC_HEADER_DIRENT +AC_CHECK_HEADERS(fcntl.h sys/fcntl.h sys/resource.h sys/ioctl.h sys/mode.h sys/filio.h sys/fs/s5param.h sys/filsys.h) +AC_CHECK_HEADERS(sys/acl.h acl/libacl.h sys/file.h) + +# select +AC_CHECK_HEADERS(sys/select.h) + +# poll +AC_CHECK_HEADERS(poll.h) +AC_CHECK_FUNCS(poll,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/poll.o"]) + +# time +AC_CHECK_HEADERS(sys/time.h utime.h) +AC_HEADER_TIME +AC_CHECK_FUNCS(utime utimes) + +AC_CACHE_CHECK([if gettimeofday takes TZ argument],libreplace_cv_HAVE_GETTIMEOFDAY_TZ,[ +AC_TRY_RUN([ +#include <sys/time.h> +#include <unistd.h> +main() { struct timeval tv; exit(gettimeofday(&tv, NULL));}], + libreplace_cv_HAVE_GETTIMEOFDAY_TZ=yes,libreplace_cv_HAVE_GETTIMEOFDAY_TZ=no,libreplace_cv_HAVE_GETTIMEOFDAY_TZ=yes)]) +if test x"$libreplace_cv_HAVE_GETTIMEOFDAY_TZ" = x"yes"; then + AC_DEFINE(HAVE_GETTIMEOFDAY_TZ,1,[Whether gettimeofday() is available]) +fi + +# wait +AC_HEADER_SYS_WAIT + +# capability +AC_CHECK_HEADERS(sys/capability.h) + +case "$host_os" in +*linux*) +AC_CACHE_CHECK([for broken RedHat 7.2 system header files],libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS,[ +AC_TRY_COMPILE([ + #ifdef HAVE_SYS_VFS_H + #include <sys/vfs.h> + #endif + #ifdef HAVE_SYS_CAPABILITY_H + #include <sys/capability.h> + #endif + ],[ + int i; + ], + libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=no, + libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS=yes +)]) +if test x"$libreplace_cv_BROKEN_REDHAT_7_SYSTEM_HEADERS" = x"yes"; then + AC_DEFINE(BROKEN_REDHAT_7_SYSTEM_HEADERS,1,[Broken RedHat 7.2 system header files]) +fi + +AC_CACHE_CHECK([for broken RHEL5 sys/capability.h],libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER,[ +AC_TRY_COMPILE([ + #ifdef HAVE_SYS_CAPABILITY_H + #include <sys/capability.h> + #endif + #include <linux/types.h> + ],[ + __s8 i; + ], + libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER=no, + libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER=yes +)]) +if test x"$libreplace_cv_BROKEN_RHEL5_SYS_CAP_HEADER" = x"yes"; then + AC_DEFINE(BROKEN_RHEL5_SYS_CAP_HEADER,1,[Broken RHEL5 sys/capability.h]) +fi +;; +esac + +# passwd +AC_CHECK_HEADERS(grp.h sys/id.h compat.h shadow.h sys/priv.h pwd.h sys/security.h) +AC_CHECK_FUNCS(getpwnam_r getpwuid_r getpwent_r) +AC_HAVE_DECL(getpwent_r, [ + #include <unistd.h> + #include <pwd.h> + ]) +AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)], + [ + #ifndef HAVE_GETPWENT_R_DECL + #error missing getpwent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETPWENT_R, 1, [getpwent_r solaris function prototype]) + ],[],[ + #include <unistd.h> + #include <pwd.h> + ]) +AC_VERIFY_C_PROTOTYPE([struct passwd *getpwent_r(struct passwd *src, char *buf, size_t buflen)], + [ + #ifndef HAVE_GETPWENT_R_DECL + #error missing getpwent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETPWENT_R, 1, [getpwent_r irix (similar to solaris) function prototype]) + ],[],[ + #include <unistd.h> + #include <pwd.h> + ]) +AC_CHECK_FUNCS(getgrnam_r getgrgid_r getgrent_r) +AC_HAVE_DECL(getgrent_r, [ + #include <unistd.h> + #include <grp.h> + ]) +AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, int buflen)], + [ + #ifndef HAVE_GETGRENT_R_DECL + #error missing getgrent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETGRENT_R, 1, [getgrent_r solaris function prototype]) + ],[],[ + #include <unistd.h> + #include <grp.h> + ]) + +AC_VERIFY_C_PROTOTYPE([struct group *getgrent_r(struct group *src, char *buf, size_t buflen)], + [ + #ifndef HAVE_GETGRENT_R_DECL + #error missing getgrent_r prototype + #endif + return NULL; + ],[ + AC_DEFINE(SOLARIS_GETGRENT_R, 1, [getgrent_r irix (similar to solaris) function prototype]) + ],[],[ + #include <unistd.h> + #include <grp.h> + ]) +AC_CHECK_FUNCS(getgrouplist) + +# locale +AC_CHECK_HEADERS(ctype.h locale.h langinfo.h) + +# glob +AC_CHECK_HEADERS(fnmatch.h) + +# shmem +AC_CHECK_HEADERS(sys/ipc.h sys/mman.h sys/shm.h ) + +# terminal +AC_CHECK_HEADERS(termios.h termio.h sys/termio.h ) diff --git a/ctdb/lib/replace/system/dir.h b/ctdb/lib/replace/system/dir.h new file mode 100644 index 0000000000..dec2d54649 --- /dev/null +++ b/ctdb/lib/replace/system/dir.h @@ -0,0 +1,67 @@ +#ifndef _system_dir_h +#define _system_dir_h +/* + Unix SMB/CIFS implementation. + + directory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#if HAVE_DIRENT_H +# include <dirent.h> +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include <sys/ndir.h> +# endif +# if HAVE_SYS_DIR_H +# include <sys/dir.h> +# endif +# if HAVE_NDIR_H +# include <ndir.h> +# endif +#endif + +#ifndef HAVE_MKDIR_MODE +#define mkdir(dir, mode) mkdir(dir) +#endif + +/* Test whether a file name is the "." or ".." directory entries. + * These really should be inline functions. + */ +#ifndef ISDOT +#define ISDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '\0' \ + ) +#endif + +#ifndef ISDOTDOT +#define ISDOTDOT(path) ( \ + *((const char *)(path)) == '.' && \ + *(((const char *)(path)) + 1) == '.' && \ + *(((const char *)(path)) + 2) == '\0' \ + ) +#endif + +#endif diff --git a/ctdb/lib/replace/system/filesys.h b/ctdb/lib/replace/system/filesys.h new file mode 100644 index 0000000000..c8ac2b4f74 --- /dev/null +++ b/ctdb/lib/replace/system/filesys.h @@ -0,0 +1,277 @@ +#ifndef _system_filesys_h +#define _system_filesys_h +/* + Unix SMB/CIFS implementation. + + filesystem system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#include <unistd.h> +#include <sys/stat.h> + +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_SYS_MOUNT_H +#include <sys/mount.h> +#endif + +#ifdef HAVE_MNTENT_H +#include <mntent.h> +#endif + +#ifdef HAVE_SYS_VFS_H +#include <sys/vfs.h> +#endif + +#ifdef HAVE_SYS_ACL_H +#include <sys/acl.h> +#endif + +#ifdef HAVE_ACL_LIBACL_H +#include <acl/libacl.h> +#endif + +#ifdef HAVE_SYS_FS_S5PARAM_H +#include <sys/fs/s5param.h> +#endif + +#if defined (HAVE_SYS_FILSYS_H) && !defined (_CRAY) +#include <sys/filsys.h> +#endif + +#ifdef HAVE_SYS_STATFS_H +# include <sys/statfs.h> +#endif + +#ifdef HAVE_DUSTAT_H +#include <sys/dustat.h> +#endif + +#ifdef HAVE_SYS_STATVFS_H +#include <sys/statvfs.h> +#endif + +#ifdef HAVE_SYS_FILIO_H +#include <sys/filio.h> +#endif + +#ifdef HAVE_SYS_FILE_H +#include <sys/file.h> +#endif + +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#else +#ifdef HAVE_SYS_FCNTL_H +#include <sys/fcntl.h> +#endif +#endif + +#ifdef HAVE_SYS_MODE_H +/* apparently AIX needs this for S_ISLNK */ +#ifndef S_ISLNK +#include <sys/mode.h> +#endif +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif + +/* + * Veritas File System. Often in addition to native. + * Quotas different. + */ +#if defined(HAVE_SYS_FS_VX_QUOTA_H) +#define VXFS_QUOTA +#endif + +#if HAVE_SYS_ATTRIBUTES_H +#include <sys/attributes.h> +#elif HAVE_ATTR_ATTRIBUTES_H +#include <attr/attributes.h> +#endif + +/* mutually exclusive (SuSE 8.2) */ +#if HAVE_ATTR_XATTR_H +#include <attr/xattr.h> +#elif HAVE_SYS_XATTR_H +#include <sys/xattr.h> +#endif + +#ifdef HAVE_SYS_EA_H +#include <sys/ea.h> +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include <sys/extattr.h> +#endif + +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#ifndef XATTR_CREATE +#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ +#endif + +#ifndef XATTR_REPLACE +#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ +#endif + +/* Some POSIX definitions for those without */ + +#ifndef S_IFDIR +#define S_IFDIR 0x4000 +#endif +#ifndef S_ISDIR +#define S_ISDIR(mode) ((mode & 0xF000) == S_IFDIR) +#endif +#ifndef S_IRWXU +#define S_IRWXU 00700 /* read, write, execute: owner */ +#endif +#ifndef S_IRUSR +#define S_IRUSR 00400 /* read permission: owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 00200 /* write permission: owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 00100 /* execute permission: owner */ +#endif +#ifndef S_IRWXG +#define S_IRWXG 00070 /* read, write, execute: group */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 00040 /* read permission: group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 00020 /* write permission: group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 00010 /* execute permission: group */ +#endif +#ifndef S_IRWXO +#define S_IRWXO 00007 /* read, write, execute: other */ +#endif +#ifndef S_IROTH +#define S_IROTH 00004 /* read permission: other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 00002 /* write permission: other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 00001 /* execute permission: other */ +#endif + +#ifndef O_ACCMODE +#define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) +#endif + +#ifndef MAXPATHLEN +#define MAXPATHLEN 256 +#endif + +#ifndef SEEK_SET +#define SEEK_SET 0 +#endif + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +#ifdef UID_WRAPPER +# ifndef UID_WRAPPER_DISABLE +# ifndef UID_WRAPPER_NOT_REPLACE +# define UID_WRAPPER_REPLACE +# endif /* UID_WRAPPER_NOT_REPLACE */ +# include "../uid_wrapper/uid_wrapper.h" +# endif /* UID_WRAPPER_DISABLE */ +#else /* UID_WRAPPER */ +# define uwrap_enabled() 0 +#endif /* UID_WRAPPER */ + +/* + this allows us to use a uniform error handling for our xattr + wrappers +*/ +#ifndef ENOATTR +#define ENOATTR ENODATA +#endif + + +#if !defined(HAVE_GETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size); +#define getxattr(path, name, value, size) rep_getxattr(path, name, value, size) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_FGETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size); +#define fgetxattr(filedes, name, value, size) rep_fgetxattr(filedes, name, value, size) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_LISTXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +ssize_t rep_listxattr (const char *path, char *list, size_t size); +#define listxattr(path, list, size) rep_listxattr(path, list, size) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_FLISTXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +ssize_t rep_flistxattr (int filedes, char *list, size_t size); +#define flistxattr(filedes, value, size) rep_flistxattr(filedes, value, size) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_REMOVEXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +int rep_removexattr (const char *path, const char *name); +#define removexattr(path, name) rep_removexattr(path, name) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_FREMOVEXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +int rep_fremovexattr (int filedes, const char *name); +#define fremovexattr(filedes, name) rep_fremovexattr(filedes, name) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_SETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +int rep_setxattr (const char *path, const char *name, const void *value, size_t size, int flags); +#define setxattr(path, name, value, size, flags) rep_setxattr(path, name, value, size, flags) +/* define is in "replace.h" */ +#endif + +#if !defined(HAVE_FSETXATTR) || defined(XATTR_ADDITIONAL_OPTIONS) +int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags); +#define fsetxattr(filedes, name, value, size, flags) rep_fsetxattr(filedes, name, value, size, flags) +/* define is in "replace.h" */ +#endif + +#endif diff --git a/ctdb/lib/replace/system/glob.h b/ctdb/lib/replace/system/glob.h new file mode 100644 index 0000000000..3e23db6828 --- /dev/null +++ b/ctdb/lib/replace/system/glob.h @@ -0,0 +1,37 @@ +#ifndef _system_glob_h +#define _system_glob_h +/* + Unix SMB/CIFS implementation. + + glob system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_GLOB_H +#include <glob.h> +#endif + +#ifdef HAVE_FNMATCH_H +#include <fnmatch.h> +#endif + +#endif diff --git a/ctdb/lib/replace/system/gssapi.h b/ctdb/lib/replace/system/gssapi.h new file mode 100644 index 0000000000..6386c7b21a --- /dev/null +++ b/ctdb/lib/replace/system/gssapi.h @@ -0,0 +1,53 @@ +#ifndef _system_gssapi_h +#define _system_gssapi_h + +/* + Unix SMB/CIFS implementation. + + GSSAPI system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_GSSAPI + +#ifdef HAVE_GSSAPI_GSSAPI_EXT_H +#include <gssapi/gssapi_ext.h> +#elif HAVE_GSSAPI_GSSAPI_H +#include <gssapi/gssapi.h> +#elif HAVE_GSSAPI_GSSAPI_GENERIC_H +#include <gssapi/gssapi_generic.h> +#elif HAVE_GSSAPI_H +#include <gssapi.h> +#endif + +#if HAVE_GSSAPI_GSSAPI_KRB5_H +#include <gssapi/gssapi_krb5.h> +#endif + +#if HAVE_GSSAPI_GSSAPI_SPNEGO_H +#include <gssapi/gssapi_spnego.h> +#elif HAVE_GSSAPI_SPNEGO_H +#include <gssapi_spnego.h> +#endif + +#endif +#endif diff --git a/ctdb/lib/replace/system/iconv.h b/ctdb/lib/replace/system/iconv.h new file mode 100644 index 0000000000..3c8a71f2f7 --- /dev/null +++ b/ctdb/lib/replace/system/iconv.h @@ -0,0 +1,57 @@ +#ifndef _system_iconv_h +#define _system_iconv_h +/* + Unix SMB/CIFS implementation. + + iconv memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#if !defined(HAVE_ICONV) && defined(HAVE_ICONV_H) +#define HAVE_ICONV +#endif + +#if !defined(HAVE_GICONV) && defined(HAVE_GICONV_H) +#define HAVE_GICONV +#endif + +#if !defined(HAVE_BICONV) && defined(HAVE_BICONV_H) +#define HAVE_BICONV +#endif + +#ifdef HAVE_NATIVE_ICONV +#if defined(HAVE_ICONV) +#include <iconv.h> +#elif defined(HAVE_GICONV) +#include <giconv.h> +#elif defined(HAVE_BICONV) +#include <biconv.h> +#endif +#endif /* HAVE_NATIVE_ICONV */ + +/* needed for some systems without iconv. Doesn't really matter + what error code we use */ +#ifndef EILSEQ +#define EILSEQ EIO +#endif + +#endif diff --git a/ctdb/lib/replace/system/kerberos.h b/ctdb/lib/replace/system/kerberos.h new file mode 100644 index 0000000000..636ce0f2e0 --- /dev/null +++ b/ctdb/lib/replace/system/kerberos.h @@ -0,0 +1,41 @@ +#ifndef _system_kerberos_h +#define _system_kerberos_h + +/* + Unix SMB/CIFS implementation. + + kerberos system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_KRB5 + +#if HAVE_KRB5_H +#include <krb5.h> +#endif + +#if HAVE_COM_ERR_H +#include <com_err.h> +#endif + +#endif +#endif diff --git a/ctdb/lib/replace/system/locale.h b/ctdb/lib/replace/system/locale.h new file mode 100644 index 0000000000..504a3bb470 --- /dev/null +++ b/ctdb/lib/replace/system/locale.h @@ -0,0 +1,42 @@ +#ifndef _system_locale_h +#define _system_locale_h + +/* + Unix SMB/CIFS implementation. + + locale include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_CTYPE_H +#include <ctype.h> +#endif + +#ifdef HAVE_LOCALE_H +#include <locale.h> +#endif + +#ifdef HAVE_LANGINFO_H +#include <langinfo.h> +#endif + +#endif diff --git a/ctdb/lib/replace/system/network.h b/ctdb/lib/replace/system/network.h new file mode 100644 index 0000000000..7cb8d7becf --- /dev/null +++ b/ctdb/lib/replace/system/network.h @@ -0,0 +1,390 @@ +#ifndef _system_network_h +#define _system_network_h +/* + Unix SMB/CIFS implementation. + + networking system include wrappers + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Jelmer Vernooij 2007 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifndef LIBREPLACE_NETWORK_CHECKS +#error "AC_LIBREPLACE_NETWORK_CHECKS missing in configure" +#endif + +#include <unistd.h> + +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif + +#ifdef HAVE_UNIXSOCKET +#include <sys/un.h> +#endif + +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef HAVE_NETINET_TCP_H +#include <netinet/tcp.h> +#endif + +/* + * The next three defines are needed to access the IPTOS_* options + * on some systems. + */ + +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif + +#ifdef HAVE_NETINET_IN_IP_H +#include <netinet/in_ip.h> +#endif + +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#ifdef HAVE_NET_IF_H +#include <net/if.h> +#endif + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#ifdef HAVE_SYS_IOCTL_H +#include <sys/ioctl.h> +#endif + +#ifdef HAVE_SYS_UIO_H +#include <sys/uio.h> +#endif + +#ifdef HAVE_STROPTS_H +#include <stropts.h> +#endif + +#ifndef HAVE_SOCKLEN_T +#define HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + +#if !defined (HAVE_INET_NTOA) || defined(REPLACE_INET_NTOA) +/* define is in "replace.h" */ +char *rep_inet_ntoa(struct in_addr ip); +#endif + +#ifndef HAVE_INET_PTON +/* define is in "replace.h" */ +int rep_inet_pton(int af, const char *src, void *dst); +#endif + +#ifndef HAVE_INET_NTOP +/* define is in "replace.h" */ +const char *rep_inet_ntop(int af, const void *src, char *dst, socklen_t size); +#endif + +#ifndef HAVE_INET_ATON +/* define is in "replace.h" */ +int rep_inet_aton(const char *src, struct in_addr *dst); +#endif + +#ifndef HAVE_CONNECT +/* define is in "replace.h" */ +int rep_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +#endif + +#ifndef HAVE_GETHOSTBYNAME +/* define is in "replace.h" */ +struct hostent *rep_gethostbyname(const char *name); +#endif + +#ifdef HAVE_IFADDRS_H +#include <ifaddrs.h> +#endif + +#ifndef HAVE_STRUCT_IFADDRS +struct ifaddrs { + struct ifaddrs *ifa_next; /* Pointer to next struct */ + char *ifa_name; /* Interface name */ + unsigned int ifa_flags; /* Interface flags */ + struct sockaddr *ifa_addr; /* Interface address */ + struct sockaddr *ifa_netmask; /* Interface netmask */ +#undef ifa_dstaddr + struct sockaddr *ifa_dstaddr; /* P2P interface destination */ + void *ifa_data; /* Address specific data */ +}; +#endif + +#ifndef HAVE_GETIFADDRS +int rep_getifaddrs(struct ifaddrs **); +#endif + +#ifndef HAVE_FREEIFADDRS +void rep_freeifaddrs(struct ifaddrs *); +#endif + +#ifndef HAVE_SOCKETPAIR +/* define is in "replace.h" */ +int rep_socketpair(int d, int type, int protocol, int sv[2]); +#endif + +/* + * Some systems have getaddrinfo but not the + * defines needed to use it. + */ + +/* Various macros that ought to be in <netdb.h>, but might not be */ + +#ifndef EAI_FAIL +#define EAI_BADFLAGS (-1) +#define EAI_NONAME (-2) +#define EAI_AGAIN (-3) +#define EAI_FAIL (-4) +#define EAI_FAMILY (-6) +#define EAI_SOCKTYPE (-7) +#define EAI_SERVICE (-8) +#define EAI_MEMORY (-10) +#define EAI_SYSTEM (-11) +#endif /* !EAI_FAIL */ + +#ifndef AI_PASSIVE +#define AI_PASSIVE 0x0001 +#endif + +#ifndef AI_CANONNAME +#define AI_CANONNAME 0x0002 +#endif + +#ifndef AI_NUMERICHOST +/* + * some platforms don't support AI_NUMERICHOST; define as zero if using + * the system version of getaddrinfo... + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_NUMERICHOST 0 +#else +#define AI_NUMERICHOST 0x0004 +#endif +#endif + +/* + * Some of the functions in source3/lib/util_sock.c use AI_ADDRCONFIG. On QNX + * 6.3.0, this macro is defined but, if it's used, getaddrinfo will fail. This + * prevents smbd from opening any sockets. + * + * If I undefine AI_ADDRCONFIG on such systems and define it to be 0, + * this works around the issue. + */ +#ifdef __QNX__ +#include <sys/neutrino.h> +#if _NTO_VERSION == 630 +#undef AI_ADDRCONFIG +#endif +#endif +#ifndef AI_ADDRCONFIG +/* + * logic copied from AI_NUMERICHOST + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_ADDRCONFIG 0 +#else +#define AI_ADDRCONFIG 0x0020 +#endif +#endif + +#ifndef AI_NUMERICSERV +/* + * logic copied from AI_NUMERICHOST + */ +#if defined(HAVE_STRUCT_ADDRINFO) && defined(HAVE_GETADDRINFO) +#define AI_NUMERICSERV 0 +#else +#define AI_NUMERICSERV 0x0400 +#endif +#endif + +#ifndef NI_NUMERICHOST +#define NI_NUMERICHOST 1 +#endif + +#ifndef NI_NUMERICSERV +#define NI_NUMERICSERV 2 +#endif + +#ifndef NI_NOFQDN +#define NI_NOFQDN 4 +#endif + +#ifndef NI_NAMEREQD +#define NI_NAMEREQD 8 +#endif + +#ifndef NI_DGRAM +#define NI_DGRAM 16 +#endif + + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#endif + +#ifndef NI_MAXSERV +#define NI_MAXSERV 32 +#endif + +/* + * glibc on linux doesn't seem to have MSG_WAITALL + * defined. I think the kernel has it though.. + */ +#ifndef MSG_WAITALL +#define MSG_WAITALL 0 +#endif + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK 0x7f000001 +#endif + +#ifndef INADDR_NONE +#define INADDR_NONE 0xffffffff +#endif + +#ifndef EAFNOSUPPORT +#define EAFNOSUPPORT EINVAL +#endif + +#ifndef INET_ADDRSTRLEN +#define INET_ADDRSTRLEN 16 +#endif + +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +#ifndef HOST_NAME_MAX +#define HOST_NAME_MAX 255 +#endif + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN HOST_NAME_MAX +#endif + +#ifndef HAVE_SA_FAMILY_T +#define HAVE_SA_FAMILY_T +typedef unsigned short int sa_family_t; +#endif + +#ifndef HAVE_STRUCT_SOCKADDR_STORAGE +#define HAVE_STRUCT_SOCKADDR_STORAGE +#ifdef HAVE_STRUCT_SOCKADDR_IN6 +#define sockaddr_storage sockaddr_in6 +#define ss_family sin6_family +#define HAVE_SS_FAMILY 1 +#else /*HAVE_STRUCT_SOCKADDR_IN6*/ +#define sockaddr_storage sockaddr_in +#define ss_family sin_family +#define HAVE_SS_FAMILY 1 +#endif /*HAVE_STRUCT_SOCKADDR_IN6*/ +#endif /*HAVE_STRUCT_SOCKADDR_STORAGE*/ + +#ifndef HAVE_SS_FAMILY +#ifdef HAVE___SS_FAMILY +#define ss_family __ss_family +#define HAVE_SS_FAMILY 1 +#endif +#endif + +#ifndef IOV_MAX +# ifdef UIO_MAXIOV +# define IOV_MAX UIO_MAXIOV +# else +# ifdef __sgi + /* + * IRIX 6.5 has sysconf(_SC_IOV_MAX) + * which might return 512 or bigger + */ +# define IOV_MAX 512 +# endif +# endif +#endif + +#ifndef HAVE_STRUCT_ADDRINFO +#define HAVE_STRUCT_ADDRINFO +struct addrinfo { + int ai_flags; + int ai_family; + int ai_socktype; + int ai_protocol; + socklen_t ai_addrlen; + struct sockaddr *ai_addr; + char *ai_canonname; + struct addrinfo *ai_next; +}; +#endif /* HAVE_STRUCT_ADDRINFO */ + +#if !defined(HAVE_GETADDRINFO) +#include "getaddrinfo.h" +#endif + +/* Needed for some systems that don't define it (Solaris). */ +#ifndef ifr_netmask +#define ifr_netmask ifr_addr +#endif + +/* Some old Linux systems have broken header files */ +#ifdef HAVE_IPV6 +#ifdef HAVE_LINUX_IPV6_V6ONLY_26 +#define IPV6_V6ONLY 26 +#endif /* HAVE_LINUX_IPV6_V6ONLY_26 */ +#endif /* HAVE_IPV6 */ + +#ifdef SOCKET_WRAPPER +#ifndef SOCKET_WRAPPER_DISABLE +#ifndef SOCKET_WRAPPER_NOT_REPLACE +#define SOCKET_WRAPPER_REPLACE +#endif /* SOCKET_WRAPPER_NOT_REPLACE */ +#include "../socket_wrapper/socket_wrapper.h" +#endif /* SOCKET_WRAPPER_DISABLE */ +#endif /* SOCKET_WRAPPER */ + +#ifdef UID_WRAPPER +# ifndef UID_WRAPPER_DISABLE +# ifndef UID_WRAPPER_NOT_REPLACE +# define UID_WRAPPER_REPLACE +# endif /* UID_WRAPPER_NOT_REPLACE */ +# include "../uid_wrapper/uid_wrapper.h" +# endif /* UID_WRAPPER_DISABLE */ +#else /* UID_WRAPPER */ +# define uwrap_enabled() 0 +#endif /* UID_WRAPPER */ + +#endif diff --git a/ctdb/lib/replace/system/passwd.h b/ctdb/lib/replace/system/passwd.h new file mode 100644 index 0000000000..8257e066ac --- /dev/null +++ b/ctdb/lib/replace/system/passwd.h @@ -0,0 +1,114 @@ +#ifndef _system_passwd_h +#define _system_passwd_h + +/* + Unix SMB/CIFS implementation. + + passwd system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +/* this needs to be included before nss_wrapper.h on some systems */ +#include <unistd.h> + +#ifdef HAVE_PWD_H +#include <pwd.h> +#endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif +#ifdef HAVE_SYS_PRIV_H +#include <sys/priv.h> +#endif +#ifdef HAVE_SYS_ID_H +#include <sys/id.h> +#endif + +#ifdef HAVE_CRYPT_H +#include <crypt.h> +#endif + +#ifdef HAVE_SHADOW_H +#include <shadow.h> +#endif + +#ifdef HAVE_SYS_SECURITY_H +#include <sys/security.h> +#include <prot.h> +#define PASSWORD_LENGTH 16 +#endif /* HAVE_SYS_SECURITY_H */ + +#ifdef HAVE_GETPWANAM +#include <sys/label.h> +#include <sys/audit.h> +#include <pwdadj.h> +#endif + +#ifdef HAVE_COMPAT_H +#include <compat.h> +#endif + +#ifndef NGROUPS_MAX +#define NGROUPS_MAX 32 /* Guess... */ +#endif + +/* what is the longest significant password available on your system? + Knowing this speeds up password searches a lot */ +#ifndef PASSWORD_LENGTH +#define PASSWORD_LENGTH 8 +#endif + +#if defined(HAVE_PUTPRPWNAM) && defined(AUTH_CLEARTEXT_SEG_CHARS) +#define OSF1_ENH_SEC 1 +#endif + +#ifndef ALLOW_CHANGE_PASSWORD +#if (defined(HAVE_TERMIOS_H) && defined(HAVE_DUP2) && defined(HAVE_SETSID)) +#define ALLOW_CHANGE_PASSWORD 1 +#endif +#endif + +#if defined(HAVE_CRYPT16) && defined(HAVE_GETAUTHUID) +#define ULTRIX_AUTH 1 +#endif + +#ifdef NSS_WRAPPER +#ifndef NSS_WRAPPER_DISABLE +#ifndef NSS_WRAPPER_NOT_REPLACE +#define NSS_WRAPPER_REPLACE +#endif /* NSS_WRAPPER_NOT_REPLACE */ +#include "../nss_wrapper/nss_wrapper.h" +#endif /* NSS_WRAPPER_DISABLE */ +#endif /* NSS_WRAPPER */ + +#ifdef UID_WRAPPER +# ifndef UID_WRAPPER_DISABLE +# ifndef UID_WRAPPER_NOT_REPLACE +# define UID_WRAPPER_REPLACE +# endif /* UID_WRAPPER_NOT_REPLACE */ +# include "../uid_wrapper/uid_wrapper.h" +# endif /* UID_WRAPPER_DISABLE */ +#else /* UID_WRAPPER */ +# define uwrap_enabled() 0 +#endif /* UID_WRAPPER */ + +#endif diff --git a/ctdb/lib/replace/system/readline.h b/ctdb/lib/replace/system/readline.h new file mode 100644 index 0000000000..e6b8fb9129 --- /dev/null +++ b/ctdb/lib/replace/system/readline.h @@ -0,0 +1,58 @@ +#ifndef _system_readline_h +#define _system_readline_h +/* + Unix SMB/CIFS implementation. + + Readline wrappers + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_LIBREADLINE +# ifdef HAVE_READLINE_READLINE_H +# include <readline/readline.h> +# ifdef HAVE_READLINE_HISTORY_H +# include <readline/history.h> +# endif +# else +# ifdef HAVE_READLINE_H +# include <readline.h> +# ifdef HAVE_HISTORY_H +# include <history.h> +# endif +# else +# undef HAVE_LIBREADLINE +# endif +# endif +#endif + +#ifdef HAVE_NEW_LIBREADLINE +#ifdef HAVE_CPPFUNCTION +# define RL_COMPLETION_CAST (CPPFunction *) +#elif HAVE_RL_COMPLETION_T +# define RL_COMPLETION_CAST (rl_completion_t *) +#else +# define RL_COMPLETION_CAST +#endif +#else +/* This type is missing from libreadline<4.0 (approximately) */ +# define RL_COMPLETION_CAST +#endif /* HAVE_NEW_LIBREADLINE */ + +#endif diff --git a/ctdb/lib/replace/system/select.h b/ctdb/lib/replace/system/select.h new file mode 100644 index 0000000000..11c5390d90 --- /dev/null +++ b/ctdb/lib/replace/system/select.h @@ -0,0 +1,77 @@ +#ifndef _system_select_h +#define _system_select_h +/* + Unix SMB/CIFS implementation. + + select system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifdef HAVE_SYS_EPOLL_H +#include <sys/epoll.h> +#endif + +#ifndef SELECT_CAST +#define SELECT_CAST +#endif + +#ifdef HAVE_POLL + +#include <poll.h> + +#else + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd +{ + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ +}; + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ +#define POLLRDNORM 0x040 /* Normal data may be read. */ +#define POLLRDBAND 0x080 /* Priority data may be read. */ +#define POLLWRNORM 0x100 /* Writing now will not block. */ +#define POLLWRBAND 0x200 /* Priority data may be written. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ + +/* define is in "replace.h" */ +int rep_poll(struct pollfd *fds, nfds_t nfds, int timeout); + +#endif + +#endif diff --git a/ctdb/lib/replace/system/shmem.h b/ctdb/lib/replace/system/shmem.h new file mode 100644 index 0000000000..64fe39b6cb --- /dev/null +++ b/ctdb/lib/replace/system/shmem.h @@ -0,0 +1,59 @@ +#ifndef _system_shmem_h +#define _system_shmem_h +/* + Unix SMB/CIFS implementation. + + shared memory system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#if defined(HAVE_SYS_IPC_H) +#include <sys/ipc.h> +#endif /* HAVE_SYS_IPC_H */ + +#if defined(HAVE_SYS_SHM_H) +#include <sys/shm.h> +#endif /* HAVE_SYS_SHM_H */ + +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif + +/* NetBSD doesn't have these */ +#ifndef SHM_R +#define SHM_R 0400 +#endif + +#ifndef SHM_W +#define SHM_W 0200 +#endif + + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +#endif diff --git a/ctdb/lib/replace/system/syslog.h b/ctdb/lib/replace/system/syslog.h new file mode 100644 index 0000000000..104be1df84 --- /dev/null +++ b/ctdb/lib/replace/system/syslog.h @@ -0,0 +1,70 @@ +#ifndef _system_syslog_h +#define _system_syslog_h +/* + Unix SMB/CIFS implementation. + + syslog system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_SYSLOG_H +#include <syslog.h> +#else +#ifdef HAVE_SYS_SYSLOG_H +#include <sys/syslog.h> +#endif +#endif + +/* For sys_adminlog(). */ +#ifndef LOG_EMERG +#define LOG_EMERG 0 /* system is unusable */ +#endif + +#ifndef LOG_ALERT +#define LOG_ALERT 1 /* action must be taken immediately */ +#endif + +#ifndef LOG_CRIT +#define LOG_CRIT 2 /* critical conditions */ +#endif + +#ifndef LOG_ERR +#define LOG_ERR 3 /* error conditions */ +#endif + +#ifndef LOG_WARNING +#define LOG_WARNING 4 /* warning conditions */ +#endif + +#ifndef LOG_NOTICE +#define LOG_NOTICE 5 /* normal but significant condition */ +#endif + +#ifndef LOG_INFO +#define LOG_INFO 6 /* informational */ +#endif + +#ifndef LOG_DEBUG +#define LOG_DEBUG 7 /* debug-level messages */ +#endif + +#endif diff --git a/ctdb/lib/replace/system/terminal.h b/ctdb/lib/replace/system/terminal.h new file mode 100644 index 0000000000..9ad601ace0 --- /dev/null +++ b/ctdb/lib/replace/system/terminal.h @@ -0,0 +1,46 @@ +#ifndef _system_terminal_h +#define _system_terminal_h +/* + Unix SMB/CIFS implementation. + + terminal system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef SUNOS4 +/* on SUNOS4 termios.h conflicts with sys/ioctl.h */ +#undef HAVE_TERMIOS_H +#endif + + +#if defined(HAVE_TERMIOS_H) +/* POSIX terminal handling. */ +#include <termios.h> +#elif defined(HAVE_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <termio.h> +#elif defined(HAVE_SYS_TERMIO_H) +/* Older SYSV terminal handling - don't use if we can avoid it. */ +#include <sys/termio.h> +#endif + +#endif diff --git a/ctdb/lib/replace/system/time.h b/ctdb/lib/replace/system/time.h new file mode 100644 index 0000000000..b6d2609289 --- /dev/null +++ b/ctdb/lib/replace/system/time.h @@ -0,0 +1,91 @@ +#ifndef _system_time_h +#define _system_time_h +/* + Unix SMB/CIFS implementation. + + time system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef TIME_WITH_SYS_TIME +#include <sys/time.h> +#include <time.h> +#else +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#else +#include <time.h> +#endif +#endif + +#ifdef HAVE_UTIME_H +#include <utime.h> +#else +struct utimbuf { + time_t actime; /* access time */ + time_t modtime; /* modification time */ +}; +#endif + +#ifndef HAVE_STRUCT_TIMESPEC +struct timespec { + time_t tv_sec; /* Seconds. */ + long tv_nsec; /* Nanoseconds. */ +}; +#endif + +#ifndef HAVE_MKTIME +/* define is in "replace.h" */ +time_t rep_mktime(struct tm *t); +#endif + +#ifndef HAVE_TIMEGM +/* define is in "replace.h" */ +time_t rep_timegm(struct tm *tm); +#endif + +#ifndef HAVE_UTIME +/* define is in "replace.h" */ +int rep_utime(const char *filename, const struct utimbuf *buf); +#endif + +#ifndef HAVE_UTIMES +/* define is in "replace.h" */ +int rep_utimes(const char *filename, const struct timeval tv[2]); +#endif + +#ifndef HAVE_CLOCK_GETTIME +/* CLOCK_REALTIME is required by POSIX */ +#define CLOCK_REALTIME 0 +typedef int clockid_t; +int rep_clock_gettime(clockid_t clk_id, struct timespec *tp); +#endif +/* make sure we have a best effort CUSTOM_CLOCK_MONOTONIC we can rely on */ +#if defined(CLOCK_MONOTONIC) +#define CUSTOM_CLOCK_MONOTONIC CLOCK_MONOTONIC +#elif defined(CLOCK_HIGHRES) +#define CUSTOM_CLOCK_MONOTONIC CLOCK_HIGHRES +#else +#define CUSTOM_CLOCK_MONOTONIC CLOCK_REALTIME +#endif + +#endif diff --git a/ctdb/lib/replace/system/wait.h b/ctdb/lib/replace/system/wait.h new file mode 100644 index 0000000000..146c61a094 --- /dev/null +++ b/ctdb/lib/replace/system/wait.h @@ -0,0 +1,55 @@ +#ifndef _system_wait_h +#define _system_wait_h +/* + Unix SMB/CIFS implementation. + + waitpid system include wrappers + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. + +*/ + +#ifdef HAVE_SYS_WAIT_H +#include <sys/wait.h> +#endif + +#include <signal.h> + +#ifndef SIGCLD +#define SIGCLD SIGCHLD +#endif + +#ifdef HAVE_SETJMP_H +#include <setjmp.h> +#endif + +#ifdef HAVE_SYS_UCONTEXT_H +#include <sys/ucontext.h> +#endif + +#if !defined(HAVE_SIG_ATOMIC_T_TYPE) +typedef int sig_atomic_t; +#endif + +#if !defined(HAVE_WAITPID) && defined(HAVE_WAIT4) +int rep_waitpid(pid_t pid,int *status,int options) +#endif + +#endif diff --git a/ctdb/lib/replace/system/wscript_configure b/ctdb/lib/replace/system/wscript_configure new file mode 100644 index 0000000000..2035474b32 --- /dev/null +++ b/ctdb/lib/replace/system/wscript_configure @@ -0,0 +1,26 @@ +#!/usr/bin/env python + +conf.CHECK_HEADERS('sys/capability.h') +conf.CHECK_FUNCS('getpwnam_r getpwuid_r getpwent_r') + +# solaris varients of getXXent_r +conf.CHECK_C_PROTOTYPE('getpwent_r', + 'struct passwd *getpwent_r(struct passwd *src, char *buf, int buflen)', + define='SOLARIS_GETPWENT_R', headers='pwd.h') +conf.CHECK_C_PROTOTYPE('getgrent_r', + 'struct group *getgrent_r(struct group *src, char *buf, int buflen)', + define='SOLARIS_GETGRENT_R', headers='grp.h') + +# the irix varients +conf.CHECK_C_PROTOTYPE('getpwent_r', + 'struct passwd *getpwent_r(struct passwd *src, char *buf, size_t buflen)', + define='SOLARIS_GETPWENT_R', headers='pwd.h') +conf.CHECK_C_PROTOTYPE('getgrent_r', + 'struct group *getgrent_r(struct group *src, char *buf, size_t buflen)', + define='SOLARIS_GETGRENT_R', headers='grp.h') + +conf.CHECK_FUNCS('getgrouplist') +conf.CHECK_HEADERS('ctype.h locale.h langinfo.h') +conf.CHECK_HEADERS('fnmatch.h locale.h langinfo.h') +conf.CHECK_HEADERS('sys/ipc.h sys/mman.h sys/shm.h') +conf.CHECK_HEADERS('termios.h termio.h sys/termio.h') diff --git a/ctdb/lib/replace/test/getifaddrs.c b/ctdb/lib/replace/test/getifaddrs.c new file mode 100644 index 0000000000..d325d8bb1b --- /dev/null +++ b/ctdb/lib/replace/test/getifaddrs.c @@ -0,0 +1,101 @@ +/* + * Unix SMB/CIFS implementation. + * + * libreplace getifaddrs test + * + * Copyright (C) Michael Adam <obnox@samba.org> 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AUTOCONF_TEST +#include "replace.h" +#include "system/network.h" +#include "replace-test.h" +#endif + +#ifdef HAVE_INET_NTOP +#define rep_inet_ntop inet_ntop +#endif + +static const char *format_sockaddr(struct sockaddr *addr, + char *addrstring, + socklen_t addrlen) +{ + const char *result = NULL; + + if (addr->sa_family == AF_INET) { + result = rep_inet_ntop(AF_INET, + &((struct sockaddr_in *)addr)->sin_addr, + addrstring, + addrlen); +#ifdef HAVE_STRUCT_SOCKADDR_IN6 + } else if (addr->sa_family == AF_INET6) { + result = rep_inet_ntop(AF_INET6, + &((struct sockaddr_in6 *)addr)->sin6_addr, + addrstring, + addrlen); +#endif + } + return result; +} + +int getifaddrs_test(void) +{ + struct ifaddrs *ifs = NULL; + struct ifaddrs *ifs_head = NULL; + int ret; + + ret = getifaddrs(&ifs); + ifs_head = ifs; + if (ret != 0) { + fprintf(stderr, "getifaddrs() failed: %s\n", strerror(errno)); + return 1; + } + + while (ifs) { + printf("%-10s ", ifs->ifa_name); + if (ifs->ifa_addr != NULL) { + char addrstring[INET6_ADDRSTRLEN]; + const char *result; + + result = format_sockaddr(ifs->ifa_addr, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("IP=%s ", addrstring); + } + + if (ifs->ifa_netmask != NULL) { + result = format_sockaddr(ifs->ifa_netmask, + addrstring, + sizeof(addrstring)); + if (result != NULL) { + printf("NETMASK=%s", addrstring); + } + } else { + printf("AF=%d ", ifs->ifa_addr->sa_family); + } + } else { + printf("<no address>"); + } + + printf("\n"); + ifs = ifs->ifa_next; + } + + freeifaddrs(ifs_head); + + return 0; +} diff --git a/ctdb/lib/replace/test/incoherent_mmap.c b/ctdb/lib/replace/test/incoherent_mmap.c new file mode 100644 index 0000000000..ee288fd806 --- /dev/null +++ b/ctdb/lib/replace/test/incoherent_mmap.c @@ -0,0 +1,83 @@ +/* In OpenBSD, if you write to a file, another process doesn't see it + * in its mmap. Returns with exit status 0 if that is the case, 1 if + * it's coherent, and other if there's a problem. */ +#include <err.h> +#include <sys/mman.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#define DATA "coherent.mmap" + +int main(int argc, char *argv[]) +{ + int tochild[2], toparent[2]; + int fd; + volatile unsigned char *map; + unsigned char *page; + const char *fname = argv[1]; + char c = 0; + + if (pipe(tochild) != 0 || pipe(toparent) != 0) + err(2, "Creating pipe"); + + if (!fname) + fname = DATA; + + fd = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0600); + if (fd < 0) + err(2, "opening %s", fname); + unlink(fname); + + switch (fork()) { + case -1: + err(2, "Fork"); + case 0: + close(tochild[1]); + close(toparent[0]); + + /* Wait for parent to create file. */ + if (read(tochild[0], &c, 1) != 1) + err(2, "reading from parent"); + + /* Alter first byte. */ + pwrite(fd, &c, 1, 0); + + if (write(toparent[1], &c, 1) != 1) + err(2, "writing to parent"); + exit(0); + + default: + close(tochild[0]); + close(toparent[1]); + + /* Create a file and mmap it. */ + page = malloc(getpagesize()); + memset(page, 0x42, getpagesize()); + if (write(fd, page, getpagesize()) != getpagesize()) + err(2, "writing first page"); + map = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, + MAP_SHARED, fd, 0); + if (map == MAP_FAILED) + err(2, "mapping file"); + + if (*map != 0x42) + errx(2, "first byte isn't 0x42!"); + + /* Tell child to alter file. */ + if (write(tochild[1], &c, 1) != 1) + err(2, "writing to child"); + + if (read(toparent[0], &c, 1) != 1) + err(2, "reading from child"); + + if (*map) + errx(0, "mmap incoherent: first byte isn't 0."); + + exit(1); + } +} diff --git a/ctdb/lib/replace/test/main.c b/ctdb/lib/replace/test/main.c new file mode 100644 index 0000000000..94264d7367 --- /dev/null +++ b/ctdb/lib/replace/test/main.c @@ -0,0 +1,35 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "replace-testsuite.h" + +int main(void) +{ + bool ret = torture_local_replace(NULL); + if (ret) + return 0; + return -1; +} diff --git a/ctdb/lib/replace/test/os2_delete.c b/ctdb/lib/replace/test/os2_delete.c new file mode 100644 index 0000000000..a11ed3b370 --- /dev/null +++ b/ctdb/lib/replace/test/os2_delete.c @@ -0,0 +1,133 @@ +/* + test readdir/unlink pattern that OS/2 uses + tridge@samba.org July 2005 +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <unistd.h> +#include <sys/types.h> +#include <dirent.h> +#include <errno.h> +#include <string.h> +#include <fcntl.h> +#include "replace-test.h" + +#define NUM_FILES 700 +#define READDIR_SIZE 100 +#define DELETE_SIZE 4 + +#define TESTDIR "test.dir" + +static int test_readdir_os2_delete_ret; + +#define FAILED(d) (printf("failure: readdir [\nFailed for %s - %d = %s\n]\n", d, errno, strerror(errno)), test_readdir_os2_delete_ret = 1, 1) + +#ifndef MIN +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +#ifdef _WIN32 +#define mkdir(d,m) _mkdir(d) +#endif + +static void cleanup(void) +{ + /* I'm a lazy bastard */ + if (system("rm -rf " TESTDIR)) { + FAILED("system"); + } + mkdir(TESTDIR, 0700) == 0 || FAILED("mkdir"); +} + +static void create_files(void) +{ + int i; + for (i=0;i<NUM_FILES;i++) { + char fname[40]; + int fd; + snprintf(fname, sizeof(fname), TESTDIR "/test%u.txt", i); + fd = open(fname, O_CREAT|O_RDWR, 0600); + if (fd < 0) { + FAILED("open"); + } + if (close(fd) != 0) { + FAILED("close"); + } + } +} + +static int os2_delete(DIR *d) +{ + off_t offsets[READDIR_SIZE]; + int i, j; + struct dirent *de; + char names[READDIR_SIZE][30]; + + /* scan, remembering offsets */ + for (i=0, de=readdir(d); + de && i < READDIR_SIZE; + de=readdir(d), i++) { + offsets[i] = telldir(d); + strcpy(names[i], de->d_name); + } + + if (i == 0) { + return 0; + } + + /* delete the first few */ + for (j=0; j<MIN(i, DELETE_SIZE); j++) { + char fname[40]; + snprintf(fname, sizeof(fname), TESTDIR "/%s", names[j]); + unlink(fname) == 0 || FAILED("unlink"); + } + + /* seek to just after the deletion */ + seekdir(d, offsets[j-1]); + + /* return number deleted */ + return j; +} + +int test_readdir_os2_delete(void) +{ + int total_deleted = 0; + DIR *d; + struct dirent *de; + + test_readdir_os2_delete_ret = 0; + + cleanup(); + create_files(); + + d = opendir(TESTDIR "/test0.txt"); + if (d != NULL) FAILED("opendir() on file succeed"); + if (errno != ENOTDIR) FAILED("opendir() on file didn't give ENOTDIR"); + + d = opendir(TESTDIR); + + /* skip past . and .. */ + de = readdir(d); + strcmp(de->d_name, ".") == 0 || FAILED("match ."); + de = readdir(d); + strcmp(de->d_name, "..") == 0 || FAILED("match .."); + + while (1) { + int n = os2_delete(d); + if (n == 0) break; + total_deleted += n; + } + closedir(d); + + fprintf(stderr, "Deleted %d files of %d\n", total_deleted, NUM_FILES); + + rmdir(TESTDIR) == 0 || FAILED("rmdir"); + + if (system("rm -rf " TESTDIR) == -1) { + FAILED("system"); + } + + return test_readdir_os2_delete_ret; +} diff --git a/ctdb/lib/replace/test/shared_mmap.c b/ctdb/lib/replace/test/shared_mmap.c new file mode 100644 index 0000000000..50dad8d696 --- /dev/null +++ b/ctdb/lib/replace/test/shared_mmap.c @@ -0,0 +1,68 @@ +/* this tests whether we can use a shared writeable mmap on a file - + as needed for the mmap variant of FAST_SHARE_MODES */ + +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define DATA "conftest.mmap" + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +main() +{ + int *buf; + int i; + int fd = open(DATA,O_RDWR|O_CREAT|O_TRUNC,0666); + int count=7; + + if (fd == -1) exit(1); + + for (i=0;i<10000;i++) { + write(fd,&i,sizeof(i)); + } + + close(fd); + + if (fork() == 0) { + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + while (count-- && buf[9124] != 55732) sleep(1); + + if (count <= 0) exit(1); + + buf[1763] = 7268; + exit(0); + } + + fd = open(DATA,O_RDWR); + if (fd == -1) exit(1); + + buf = (int *)mmap(NULL, 10000*sizeof(int), + (PROT_READ | PROT_WRITE), + MAP_FILE | MAP_SHARED, + fd, 0); + + if (buf == (int *)-1) exit(1); + + buf[9124] = 55732; + + while (count-- && buf[1763] != 7268) sleep(1); + + unlink(DATA); + + if (count > 0) exit(0); + exit(1); +} diff --git a/ctdb/lib/replace/test/shared_mremap.c b/ctdb/lib/replace/test/shared_mremap.c new file mode 100644 index 0000000000..05032ad12e --- /dev/null +++ b/ctdb/lib/replace/test/shared_mremap.c @@ -0,0 +1,48 @@ +/* this tests whether we can use mremap */ + +#if defined(HAVE_UNISTD_H) +#include <unistd.h> +#endif +#include <sys/mman.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define DATA "conftest.mmap" + +#ifndef MAP_FILE +#define MAP_FILE 0 +#endif + +#ifndef MAP_FAILED +#define MAP_FAILED (int *)-1 +#endif + +main() +{ + int *buf; + int fd; + int err = 1; + + fd = open(DATA, O_RDWR|O_CREAT|O_TRUNC, 0666); + if (fd == -1) { + exit(1); + } + + buf = (int *)mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, + MAP_FILE | MAP_SHARED, fd, 0); + if (buf == MAP_FAILED) { + goto done; + } + + buf = mremap(buf, 0x1000, 0x2000, MREMAP_MAYMOVE); + if (buf == MAP_FAILED) { + goto done; + } + + err = 0; +done: + close(fd); + unlink(DATA); + exit(err); +} diff --git a/ctdb/lib/replace/test/snprintf.c b/ctdb/lib/replace/test/snprintf.c new file mode 100644 index 0000000000..d06630bcc9 --- /dev/null +++ b/ctdb/lib/replace/test/snprintf.c @@ -0,0 +1,29 @@ +void foo(const char *format, ...) +{ + va_list ap; + int len; + char buf[20]; + long long l = 1234567890; + l *= 100; + + va_start(ap, format); + len = vsnprintf(buf, 0, format, ap); + va_end(ap); + if (len != 5) exit(1); + + va_start(ap, format); + len = vsnprintf(0, 0, format, ap); + va_end(ap); + if (len != 5) exit(2); + + if (snprintf(buf, 3, "hello") != 5 || strcmp(buf, "he") != 0) exit(3); + + if (snprintf(buf, 20, "%lld", l) != 12 || strcmp(buf, "123456789000") != 0) exit(4); + if (snprintf(buf, 20, "%zu", 123456789) != 9 || strcmp(buf, "123456789") != 0) exit(5); + if (snprintf(buf, 20, "%2\$d %1\$d", 3, 4) != 3 || strcmp(buf, "4 3") != 0) exit(6); + if (snprintf(buf, 20, "%s", 0) < 3) exit(7); + + printf("1"); + exit(0); +} +main() { foo("hello"); } diff --git a/ctdb/lib/replace/test/strptime.c b/ctdb/lib/replace/test/strptime.c new file mode 100644 index 0000000000..5bf03f5b35 --- /dev/null +++ b/ctdb/lib/replace/test/strptime.c @@ -0,0 +1,173 @@ + +#ifdef LIBREPLACE_CONFIGURE_TEST_STRPTIME + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +#define true 1 +#define false 0 + +#ifndef __STRING +#define __STRING(x) #x +#endif + +/* make printf a no-op */ +#define printf if(0) printf + +#else /* LIBREPLACE_CONFIGURE_TEST_STRPTIME */ + +#include "replace.h" +#include "system/time.h" +#include "replace-test.h" + +#endif /* LIBREPLACE_CONFIGURE_TEST_STRPTIME */ + +int libreplace_test_strptime(void) +{ + const char *s = "20070414101546Z"; + char *ret; + struct tm t, t2; + + memset(&t, 0, sizeof(t)); + memset(&t2, 0, sizeof(t2)); + + printf("test: strptime\n"); + + ret = strptime(s, "%Y%m%d%H%M%S", &t); + if ( ret == NULL ) { + printf("failure: strptime [\n" + "returned NULL\n" + "]\n"); + return false; + } + + if ( *ret != 'Z' ) { + printf("failure: strptime [\n" + "ret doesn't point to 'Z'\n" + "]\n"); + return false; + } + + ret = strptime(s, "%Y%m%d%H%M%SZ", &t2); + if ( ret == NULL ) { + printf("failure: strptime [\n" + "returned NULL with Z\n" + "]\n"); + return false; + } + + if ( *ret != '\0' ) { + printf("failure: strptime [\n" + "ret doesn't point to '\\0'\n" + "]\n"); + return false; + } + +#define CMP_TM_ELEMENT(t1,t2,elem) \ + if (t1.elem != t2.elem) { \ + printf("failure: strptime [\n" \ + "result differs if the format string has a 'Z' at the end\n" \ + "element: %s %d != %d\n" \ + "]\n", \ + __STRING(elen), t1.elem, t2.elem); \ + return false; \ + } + + CMP_TM_ELEMENT(t,t2,tm_sec); + CMP_TM_ELEMENT(t,t2,tm_min); + CMP_TM_ELEMENT(t,t2,tm_hour); + CMP_TM_ELEMENT(t,t2,tm_mday); + CMP_TM_ELEMENT(t,t2,tm_mon); + CMP_TM_ELEMENT(t,t2,tm_year); + CMP_TM_ELEMENT(t,t2,tm_wday); + CMP_TM_ELEMENT(t,t2,tm_yday); + CMP_TM_ELEMENT(t,t2,tm_isdst); + + if (t.tm_sec != 46) { + printf("failure: strptime [\n" + "tm_sec: expected: 46, got: %d\n" + "]\n", + t.tm_sec); + return false; + } + + if (t.tm_min != 15) { + printf("failure: strptime [\n" + "tm_min: expected: 15, got: %d\n" + "]\n", + t.tm_min); + return false; + } + + if (t.tm_hour != 10) { + printf("failure: strptime [\n" + "tm_hour: expected: 10, got: %d\n" + "]\n", + t.tm_hour); + return false; + } + + if (t.tm_mday != 14) { + printf("failure: strptime [\n" + "tm_mday: expected: 14, got: %d\n" + "]\n", + t.tm_mday); + return false; + } + + if (t.tm_mon != 3) { + printf("failure: strptime [\n" + "tm_mon: expected: 3, got: %d\n" + "]\n", + t.tm_mon); + return false; + } + + if (t.tm_year != 107) { + printf("failure: strptime [\n" + "tm_year: expected: 107, got: %d\n" + "]\n", + t.tm_year); + return false; + } + + if (t.tm_wday != 6) { /* saturday */ + printf("failure: strptime [\n" + "tm_wday: expected: 6, got: %d\n" + "]\n", + t.tm_wday); + return false; + } + + if (t.tm_yday != 103) { + printf("failure: strptime [\n" + "tm_yday: expected: 103, got: %d\n" + "]\n", + t.tm_yday); + return false; + } + + /* we don't test this as it depends on the host configuration + if (t.tm_isdst != 0) { + printf("failure: strptime [\n" + "tm_isdst: expected: 0, got: %d\n" + "]\n", + t.tm_isdst); + return false; + }*/ + + printf("success: strptime\n"); + + return true; +} + +#ifdef LIBREPLACE_CONFIGURE_TEST_STRPTIME +int main (void) +{ + int ret; + ret = libreplace_test_strptime(); + if (ret == false) return 1; + return 0; +} +#endif diff --git a/ctdb/lib/replace/test/testsuite.c b/ctdb/lib/replace/test/testsuite.c new file mode 100644 index 0000000000..52629ec82e --- /dev/null +++ b/ctdb/lib/replace/test/testsuite.c @@ -0,0 +1,1101 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "replace-test.h" +#include "replace-testsuite.h" + +/* + we include all the system/ include files here so that libreplace tests + them in the build farm +*/ +#include "system/capability.h" +#include "system/dir.h" +#include "system/filesys.h" +#include "system/glob.h" +#include "system/iconv.h" +#include "system/locale.h" +#include "system/network.h" +#include "system/passwd.h" +#include "system/readline.h" +#include "system/select.h" +#include "system/shmem.h" +#include "system/syslog.h" +#include "system/terminal.h" +#include "system/time.h" +#include "system/wait.h" +#include "system/aio.h" + +#define TESTFILE "testfile.dat" + + +/* + test ftruncate() function + */ +static int test_ftruncate(void) +{ + struct stat st; + int fd; + const int size = 1234; + printf("test: ftruncate\n"); + unlink(TESTFILE); + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: ftruncate [\n" + "creating '%s' failed - %s\n]\n", TESTFILE, strerror(errno)); + return false; + } + if (ftruncate(fd, size) != 0) { + printf("failure: ftruncate [\n%s\n]\n", strerror(errno)); + return false; + } + if (fstat(fd, &st) != 0) { + printf("failure: ftruncate [\nfstat failed - %s\n]\n", strerror(errno)); + return false; + } + if (st.st_size != size) { + printf("failure: ftruncate [\ngave wrong size %d - expected %d\n]\n", + (int)st.st_size, size); + return false; + } + unlink(TESTFILE); + printf("success: ftruncate\n"); + return true; +} + +/* + test strlcpy() function. + see http://www.gratisoft.us/todd/papers/strlcpy.html + */ +static int test_strlcpy(void) +{ + char buf[4]; + const struct { + const char *src; + size_t result; + } tests[] = { + { "abc", 3 }, + { "abcdef", 6 }, + { "abcd", 4 }, + { "", 0 }, + { NULL, 0 } + }; + int i; + printf("test: strlcpy\n"); + for (i=0;tests[i].src;i++) { + if (strlcpy(buf, tests[i].src, sizeof(buf)) != tests[i].result) { + printf("failure: strlcpy [\ntest %d failed\n]\n", i); + return false; + } + } + printf("success: strlcpy\n"); + return true; +} + +static int test_strlcat(void) +{ + char tmp[10]; + printf("test: strlcat\n"); + strlcpy(tmp, "", sizeof(tmp)); + if (strlcat(tmp, "bla", 3) != 3) { + printf("failure: strlcat [\ninvalid return code\n]\n"); + return false; + } + if (strcmp(tmp, "bl") != 0) { + printf("failure: strlcat [\nexpected \"bl\", got \"%s\"\n]\n", + tmp); + return false; + } + + strlcpy(tmp, "da", sizeof(tmp)); + if (strlcat(tmp, "me", 4) != 4) { + printf("failure: strlcat [\nexpected \"dam\", got \"%s\"\n]\n", + tmp); + return false; + } + + printf("success: strlcat\n"); + return true; +} + +static int test_mktime(void) +{ + /* FIXME */ + return true; +} + +static int test_initgroups(void) +{ + /* FIXME */ + return true; +} + +static int test_memmove(void) +{ + /* FIXME */ + return true; +} + +static int test_strdup(void) +{ + char *x; + printf("test: strdup\n"); + x = strdup("bla"); + if (strcmp("bla", x) != 0) { + printf("failure: strdup [\nfailed: expected \"bla\", got \"%s\"\n]\n", + x); + return false; + } + free(x); + printf("success: strdup\n"); + return true; +} + +static int test_setlinebuf(void) +{ + printf("test: setlinebuf\n"); + setlinebuf(stdout); + printf("success: setlinebuf\n"); + return true; +} + +static int test_vsyslog(void) +{ + /* FIXME */ + return true; +} + +static int test_timegm(void) +{ + /* FIXME */ + return true; +} + +static int test_setenv(void) +{ +#define TEST_SETENV(key, value, overwrite, result) do { \ + int _ret; \ + char *_v; \ + _ret = setenv(key, value, overwrite); \ + if (_ret != 0) { \ + printf("failure: setenv [\n" \ + "setenv(%s, %s, %d) failed\n" \ + "]\n", \ + key, value, overwrite); \ + return false; \ + } \ + _v=getenv(key); \ + if (!_v) { \ + printf("failure: setenv [\n" \ + "getenv(%s) returned NULL\n" \ + "]\n", \ + key); \ + return false; \ + } \ + if (strcmp(result, _v) != 0) { \ + printf("failure: setenv [\n" \ + "getenv(%s): '%s' != '%s'\n" \ + "]\n", \ + key, result, _v); \ + return false; \ + } \ +} while(0) + +#define TEST_UNSETENV(key) do { \ + char *_v; \ + unsetenv(key); \ + _v=getenv(key); \ + if (_v) { \ + printf("failure: setenv [\n" \ + "getenv(%s): NULL != '%s'\n" \ + "]\n", \ + SETENVTEST_KEY, _v); \ + return false; \ + } \ +} while (0) + +#define SETENVTEST_KEY "SETENVTESTKEY" +#define SETENVTEST_VAL "SETENVTESTVAL" + + printf("test: setenv\n"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"1", 0, SETENVTEST_VAL"1"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"2", 0, SETENVTEST_VAL"1"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"3", 1, SETENVTEST_VAL"3"); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"4", 1, SETENVTEST_VAL"4"); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_SETENV(SETENVTEST_KEY, SETENVTEST_VAL"5", 0, SETENVTEST_VAL"5"); + TEST_UNSETENV(SETENVTEST_KEY); + TEST_UNSETENV(SETENVTEST_KEY); + printf("success: setenv\n"); + return true; +} + +static int test_strndup(void) +{ + char *x; + printf("test: strndup\n"); + x = strndup("bla", 0); + if (strcmp(x, "") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + return false; + } + free(x); + x = strndup("bla", 2); + if (strcmp(x, "bl") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + return false; + } + free(x); + x = strndup("bla", 10); + if (strcmp(x, "bla") != 0) { + printf("failure: strndup [\ninvalid\n]\n"); + return false; + } + free(x); + printf("success: strndup\n"); + return true; +} + +static int test_strnlen(void) +{ + printf("test: strnlen\n"); + if (strnlen("bla", 2) != 2) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + if (strnlen("some text\n", 0) != 0) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + if (strnlen("some text", 20) != 9) { + printf("failure: strnlen [\nunexpected length\n]\n"); + return false; + } + + printf("success: strnlen\n"); + return true; +} + +static int test_waitpid(void) +{ + /* FIXME */ + return true; +} + +static int test_seteuid(void) +{ + /* FIXME */ + return true; +} + +static int test_setegid(void) +{ + /* FIXME */ + return true; +} + +static int test_asprintf(void) +{ + char *x; + printf("test: asprintf\n"); + if (asprintf(&x, "%d", 9) != 1) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (strcmp(x, "9") != 0) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (asprintf(&x, "dat%s", "a") != 4) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + if (strcmp(x, "data") != 0) { + printf("failure: asprintf [\ngenerate asprintf\n]\n"); + return false; + } + printf("success: asprintf\n"); + return true; +} + +static int test_snprintf(void) +{ + char tmp[10]; + printf("test: snprintf\n"); + if (snprintf(tmp, 3, "foo%d", 9) != 4) { + printf("failure: snprintf [\nsnprintf return code failed\n]\n"); + return false; + } + + if (strcmp(tmp, "fo") != 0) { + printf("failure: snprintf [\nsnprintf failed\n]\n"); + return false; + } + + printf("success: snprintf\n"); + return true; +} + +static int test_vasprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_vsnprintf(void) +{ + /* FIXME */ + return true; +} + +static int test_opendir(void) +{ + /* FIXME */ + return true; +} + +static int test_readdir(void) +{ + printf("test: readdir\n"); + if (test_readdir_os2_delete() != 0) { + return false; + } + printf("success: readdir\n"); + return true; +} + +static int test_telldir(void) +{ + /* FIXME */ + return true; +} + +static int test_seekdir(void) +{ + /* FIXME */ + return true; +} + +static int test_dlopen(void) +{ + /* FIXME: test dlopen, dlsym, dlclose, dlerror */ + return true; +} + + +static int test_chroot(void) +{ + /* FIXME: chroot() */ + return true; +} + +static int test_bzero(void) +{ + /* FIXME: bzero */ + return true; +} + +static int test_strerror(void) +{ + /* FIXME */ + return true; +} + +static int test_errno(void) +{ + printf("test: errno\n"); + errno = 3; + if (errno != 3) { + printf("failure: errno [\nerrno failed\n]\n"); + return false; + } + + printf("success: errno\n"); + return true; +} + +static int test_mkdtemp(void) +{ + /* FIXME */ + return true; +} + +static int test_mkstemp(void) +{ + /* FIXME */ + return true; +} + +static int test_pread(void) +{ + /* FIXME */ + return true; +} + +static int test_pwrite(void) +{ + /* FIXME */ + return true; +} + +static int test_inet_ntoa(void) +{ + /* FIXME */ + return true; +} + +#define TEST_STRTO_X(type,fmt,func,str,base,res,diff,rrnoo) do {\ + type _v; \ + char _s[64]; \ + char *_p = NULL;\ + char *_ep = NULL; \ + strlcpy(_s, str, sizeof(_s));\ + if (diff >= 0) { \ + _ep = &_s[diff]; \ + } \ + errno = 0; \ + _v = func(_s, &_p, base); \ + if (errno != rrnoo) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \ + "\terrno: %d != %d\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v, rrnoo, errno); \ + return false; \ + } else if (_v != res) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " != " fmt "\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v); \ + return false; \ + } else if (_p != _ep) { \ + printf("failure: %s [\n" \ + "\t%s\n" \ + "\t%s(\"%s\",%d,%d): " fmt " (=/!)= " fmt "\n" \ + "\tptr: %p - %p = %d != %d\n" \ + "]\n", \ + __STRING(func), __location__, __STRING(func), \ + str, diff, base, res, _v, _ep, _p, (int)(diff - (_ep - _p)), diff); \ + return false; \ + } \ +} while (0) + +static int test_strtoll(void) +{ + printf("test: strtoll\n"); + +#define TEST_STRTOLL(str,base,res,diff,errnoo) TEST_STRTO_X(long long int, "%lld", strtoll,str,base,res,diff,errnoo) + + TEST_STRTOLL("15", 10, 15LL, 2, 0); + TEST_STRTOLL(" 15", 10, 15LL, 4, 0); + TEST_STRTOLL("15", 0, 15LL, 2, 0); + TEST_STRTOLL(" 15 ", 0, 15LL, 3, 0); + TEST_STRTOLL("+15", 10, 15LL, 3, 0); + TEST_STRTOLL(" +15", 10, 15LL, 5, 0); + TEST_STRTOLL("+15", 0, 15LL, 3, 0); + TEST_STRTOLL(" +15 ", 0, 15LL, 4, 0); + TEST_STRTOLL("-15", 10, -15LL, 3, 0); + TEST_STRTOLL(" -15", 10, -15LL, 5, 0); + TEST_STRTOLL("-15", 0, -15LL, 3, 0); + TEST_STRTOLL(" -15 ", 0, -15LL, 4, 0); + TEST_STRTOLL("015", 10, 15LL, 3, 0); + TEST_STRTOLL(" 015", 10, 15LL, 5, 0); + TEST_STRTOLL("015", 0, 13LL, 3, 0); + TEST_STRTOLL(" 015", 0, 13LL, 5, 0); + TEST_STRTOLL("0x15", 10, 0LL, 1, 0); + TEST_STRTOLL(" 0x15", 10, 0LL, 3, 0); + TEST_STRTOLL("0x15", 0, 21LL, 4, 0); + TEST_STRTOLL(" 0x15", 0, 21LL, 6, 0); + + TEST_STRTOLL("10", 16, 16LL, 2, 0); + TEST_STRTOLL(" 10 ", 16, 16LL, 4, 0); + TEST_STRTOLL("0x10", 16, 16LL, 4, 0); + TEST_STRTOLL("0x10", 0, 16LL, 4, 0); + TEST_STRTOLL(" 0x10 ", 0, 16LL, 5, 0); + TEST_STRTOLL("+10", 16, 16LL, 3, 0); + TEST_STRTOLL(" +10 ", 16, 16LL, 5, 0); + TEST_STRTOLL("+0x10", 16, 16LL, 5, 0); + TEST_STRTOLL("+0x10", 0, 16LL, 5, 0); + TEST_STRTOLL(" +0x10 ", 0, 16LL, 6, 0); + TEST_STRTOLL("-10", 16, -16LL, 3, 0); + TEST_STRTOLL(" -10 ", 16, -16LL, 5, 0); + TEST_STRTOLL("-0x10", 16, -16LL, 5, 0); + TEST_STRTOLL("-0x10", 0, -16LL, 5, 0); + TEST_STRTOLL(" -0x10 ", 0, -16LL, 6, 0); + TEST_STRTOLL("010", 16, 16LL, 3, 0); + TEST_STRTOLL(" 010 ", 16, 16LL, 5, 0); + TEST_STRTOLL("-010", 16, -16LL, 4, 0); + + TEST_STRTOLL("11", 8, 9LL, 2, 0); + TEST_STRTOLL("011", 8, 9LL, 3, 0); + TEST_STRTOLL("011", 0, 9LL, 3, 0); + TEST_STRTOLL("-11", 8, -9LL, 3, 0); + TEST_STRTOLL("-011", 8, -9LL, 4, 0); + TEST_STRTOLL("-011", 0, -9LL, 4, 0); + + TEST_STRTOLL("011", 8, 9LL, 3, 0); + TEST_STRTOLL("011", 0, 9LL, 3, 0); + TEST_STRTOLL("-11", 8, -9LL, 3, 0); + TEST_STRTOLL("-011", 8, -9LL, 4, 0); + TEST_STRTOLL("-011", 0, -9LL, 4, 0); + + TEST_STRTOLL("Text", 0, 0LL, 0, 0); + + TEST_STRTOLL("9223372036854775807", 10, 9223372036854775807LL, 19, 0); + TEST_STRTOLL("9223372036854775807", 0, 9223372036854775807LL, 19, 0); + TEST_STRTOLL("9223372036854775808", 0, 9223372036854775807LL, 19, ERANGE); + TEST_STRTOLL("9223372036854775808", 10, 9223372036854775807LL, 19, ERANGE); + TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LL, 18, 0); + TEST_STRTOLL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 18, 0); + TEST_STRTOLL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LL, 16, 0); + TEST_STRTOLL("0x8000000000000000", 0, 9223372036854775807LL, 18, ERANGE); + TEST_STRTOLL("0x8000000000000000", 16, 9223372036854775807LL, 18, ERANGE); + TEST_STRTOLL("80000000000000000", 16, 9223372036854775807LL, 17, ERANGE); + TEST_STRTOLL("0777777777777777777777", 0, 9223372036854775807LL, 22, 0); + TEST_STRTOLL("0777777777777777777777", 8, 9223372036854775807LL, 22, 0); + TEST_STRTOLL("777777777777777777777", 8, 9223372036854775807LL, 21, 0); + TEST_STRTOLL("01000000000000000000000", 0, 9223372036854775807LL, 23, ERANGE); + TEST_STRTOLL("01000000000000000000000", 8, 9223372036854775807LL, 23, ERANGE); + TEST_STRTOLL("1000000000000000000000", 8, 9223372036854775807LL, 22, ERANGE); + + TEST_STRTOLL("-9223372036854775808", 10, -9223372036854775807LL -1, 20, 0); + TEST_STRTOLL("-9223372036854775808", 0, -9223372036854775807LL -1, 20, 0); + TEST_STRTOLL("-9223372036854775809", 0, -9223372036854775807LL -1, 20, ERANGE); + TEST_STRTOLL("-9223372036854775809", 10, -9223372036854775807LL -1, 20, ERANGE); + TEST_STRTOLL("-0x8000000000000000", 0, -9223372036854775807LL -1, 19, 0); + TEST_STRTOLL("-0x8000000000000000", 16, -9223372036854775807LL -1, 19, 0); + TEST_STRTOLL("-8000000000000000", 16, -9223372036854775807LL -1, 17, 0); + TEST_STRTOLL("-0x8000000000000001", 0, -9223372036854775807LL -1, 19, ERANGE); + TEST_STRTOLL("-0x8000000000000001", 16, -9223372036854775807LL -1, 19, ERANGE); + TEST_STRTOLL("-80000000000000001", 16, -9223372036854775807LL -1, 18, ERANGE); + TEST_STRTOLL("-01000000000000000000000",0, -9223372036854775807LL -1, 24, 0); + TEST_STRTOLL("-01000000000000000000000",8, -9223372036854775807LL -1, 24, 0); + TEST_STRTOLL("-1000000000000000000000", 8, -9223372036854775807LL -1, 23, 0); + TEST_STRTOLL("-01000000000000000000001",0, -9223372036854775807LL -1, 24, ERANGE); + TEST_STRTOLL("-01000000000000000000001",8, -9223372036854775807LL -1, 24, ERANGE); + TEST_STRTOLL("-1000000000000000000001", 8, -9223372036854775807LL -1, 23, ERANGE); + + printf("success: strtoll\n"); + return true; +} + +static int test_strtoull(void) +{ + printf("test: strtoull\n"); + +#define TEST_STRTOULL(str,base,res,diff,errnoo) TEST_STRTO_X(long long unsigned int,"%llu",strtoull,str,base,res,diff,errnoo) + + TEST_STRTOULL("15", 10, 15LLU, 2, 0); + TEST_STRTOULL(" 15", 10, 15LLU, 4, 0); + TEST_STRTOULL("15", 0, 15LLU, 2, 0); + TEST_STRTOULL(" 15 ", 0, 15LLU, 3, 0); + TEST_STRTOULL("+15", 10, 15LLU, 3, 0); + TEST_STRTOULL(" +15", 10, 15LLU, 5, 0); + TEST_STRTOULL("+15", 0, 15LLU, 3, 0); + TEST_STRTOULL(" +15 ", 0, 15LLU, 4, 0); + TEST_STRTOULL("-15", 10, 18446744073709551601LLU, 3, 0); + TEST_STRTOULL(" -15", 10, 18446744073709551601LLU, 5, 0); + TEST_STRTOULL("-15", 0, 18446744073709551601LLU, 3, 0); + TEST_STRTOULL(" -15 ", 0, 18446744073709551601LLU, 4, 0); + TEST_STRTOULL("015", 10, 15LLU, 3, 0); + TEST_STRTOULL(" 015", 10, 15LLU, 5, 0); + TEST_STRTOULL("015", 0, 13LLU, 3, 0); + TEST_STRTOULL(" 015", 0, 13LLU, 5, 0); + TEST_STRTOULL("0x15", 10, 0LLU, 1, 0); + TEST_STRTOULL(" 0x15", 10, 0LLU, 3, 0); + TEST_STRTOULL("0x15", 0, 21LLU, 4, 0); + TEST_STRTOULL(" 0x15", 0, 21LLU, 6, 0); + + TEST_STRTOULL("10", 16, 16LLU, 2, 0); + TEST_STRTOULL(" 10 ", 16, 16LLU, 4, 0); + TEST_STRTOULL("0x10", 16, 16LLU, 4, 0); + TEST_STRTOULL("0x10", 0, 16LLU, 4, 0); + TEST_STRTOULL(" 0x10 ", 0, 16LLU, 5, 0); + TEST_STRTOULL("+10", 16, 16LLU, 3, 0); + TEST_STRTOULL(" +10 ", 16, 16LLU, 5, 0); + TEST_STRTOULL("+0x10", 16, 16LLU, 5, 0); + TEST_STRTOULL("+0x10", 0, 16LLU, 5, 0); + TEST_STRTOULL(" +0x10 ", 0, 16LLU, 6, 0); + TEST_STRTOULL("-10", 16, -16LLU, 3, 0); + TEST_STRTOULL(" -10 ", 16, -16LLU, 5, 0); + TEST_STRTOULL("-0x10", 16, -16LLU, 5, 0); + TEST_STRTOULL("-0x10", 0, -16LLU, 5, 0); + TEST_STRTOULL(" -0x10 ", 0, -16LLU, 6, 0); + TEST_STRTOULL("010", 16, 16LLU, 3, 0); + TEST_STRTOULL(" 010 ", 16, 16LLU, 5, 0); + TEST_STRTOULL("-010", 16, -16LLU, 4, 0); + + TEST_STRTOULL("11", 8, 9LLU, 2, 0); + TEST_STRTOULL("011", 8, 9LLU, 3, 0); + TEST_STRTOULL("011", 0, 9LLU, 3, 0); + TEST_STRTOULL("-11", 8, -9LLU, 3, 0); + TEST_STRTOULL("-011", 8, -9LLU, 4, 0); + TEST_STRTOULL("-011", 0, -9LLU, 4, 0); + + TEST_STRTOULL("011", 8, 9LLU, 3, 0); + TEST_STRTOULL("011", 0, 9LLU, 3, 0); + TEST_STRTOULL("-11", 8, -9LLU, 3, 0); + TEST_STRTOULL("-011", 8, -9LLU, 4, 0); + TEST_STRTOULL("-011", 0, -9LLU, 4, 0); + + TEST_STRTOULL("Text", 0, 0LLU, 0, 0); + + TEST_STRTOULL("9223372036854775807", 10, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("9223372036854775807", 0, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("9223372036854775808", 0, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("9223372036854775808", 10, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 0, 9223372036854775807LLU, 18, 0); + TEST_STRTOULL("0x7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 18, 0); + TEST_STRTOULL("7FFFFFFFFFFFFFFF", 16, 9223372036854775807LLU, 16, 0); + TEST_STRTOULL("0x8000000000000000", 0, 9223372036854775808LLU, 18, 0); + TEST_STRTOULL("0x8000000000000000", 16, 9223372036854775808LLU, 18, 0); + TEST_STRTOULL("8000000000000000", 16, 9223372036854775808LLU, 16, 0); + TEST_STRTOULL("0777777777777777777777", 0, 9223372036854775807LLU, 22, 0); + TEST_STRTOULL("0777777777777777777777", 8, 9223372036854775807LLU, 22, 0); + TEST_STRTOULL("777777777777777777777", 8, 9223372036854775807LLU, 21, 0); + TEST_STRTOULL("01000000000000000000000",0, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("01000000000000000000000",8, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("1000000000000000000000", 8, 9223372036854775808LLU, 22, 0); + + TEST_STRTOULL("-9223372036854775808", 10, 9223372036854775808LLU, 20, 0); + TEST_STRTOULL("-9223372036854775808", 0, 9223372036854775808LLU, 20, 0); + TEST_STRTOULL("-9223372036854775809", 0, 9223372036854775807LLU, 20, 0); + TEST_STRTOULL("-9223372036854775809", 10, 9223372036854775807LLU, 20, 0); + TEST_STRTOULL("-0x8000000000000000", 0, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("-0x8000000000000000", 16, 9223372036854775808LLU, 19, 0); + TEST_STRTOULL("-8000000000000000", 16, 9223372036854775808LLU, 17, 0); + TEST_STRTOULL("-0x8000000000000001", 0, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("-0x8000000000000001", 16, 9223372036854775807LLU, 19, 0); + TEST_STRTOULL("-8000000000000001", 16, 9223372036854775807LLU, 17, 0); + TEST_STRTOULL("-01000000000000000000000",0, 9223372036854775808LLU, 24, 0); + TEST_STRTOULL("-01000000000000000000000",8, 9223372036854775808LLU, 24, 0); + TEST_STRTOULL("-1000000000000000000000",8, 9223372036854775808LLU, 23, 0); + TEST_STRTOULL("-01000000000000000000001",0, 9223372036854775807LLU, 24, 0); + TEST_STRTOULL("-01000000000000000000001",8, 9223372036854775807LLU, 24, 0); + TEST_STRTOULL("-1000000000000000000001",8, 9223372036854775807LLU, 23, 0); + + TEST_STRTOULL("18446744073709551615", 0, 18446744073709551615LLU, 20, 0); + TEST_STRTOULL("18446744073709551615", 10, 18446744073709551615LLU, 20, 0); + TEST_STRTOULL("18446744073709551616", 0, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("18446744073709551616", 10, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 0, 18446744073709551615LLU, 18, 0); + TEST_STRTOULL("0xFFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 18, 0); + TEST_STRTOULL("FFFFFFFFFFFFFFFF", 16, 18446744073709551615LLU, 16, 0); + TEST_STRTOULL("0x10000000000000000", 0, 18446744073709551615LLU, 19, ERANGE); + TEST_STRTOULL("0x10000000000000000", 16, 18446744073709551615LLU, 19, ERANGE); + TEST_STRTOULL("10000000000000000", 16, 18446744073709551615LLU, 17, ERANGE); + TEST_STRTOULL("01777777777777777777777",0, 18446744073709551615LLU, 23, 0); + TEST_STRTOULL("01777777777777777777777",8, 18446744073709551615LLU, 23, 0); + TEST_STRTOULL("1777777777777777777777", 8, 18446744073709551615LLU, 22, 0); + TEST_STRTOULL("02000000000000000000000",0, 18446744073709551615LLU, 23, ERANGE); + TEST_STRTOULL("02000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE); + TEST_STRTOULL("2000000000000000000000", 8, 18446744073709551615LLU, 22, ERANGE); + + TEST_STRTOULL("-18446744073709551615", 0, 1LLU, 21, 0); + TEST_STRTOULL("-18446744073709551615", 10, 1LLU, 21, 0); + TEST_STRTOULL("-18446744073709551616", 0, 18446744073709551615LLU, 21, ERANGE); + TEST_STRTOULL("-18446744073709551616", 10, 18446744073709551615LLU, 21, ERANGE); + TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 0, 1LLU, 19, 0); + TEST_STRTOULL("-0xFFFFFFFFFFFFFFFF", 16, 1LLU, 19, 0); + TEST_STRTOULL("-FFFFFFFFFFFFFFFF", 16, 1LLU, 17, 0); + TEST_STRTOULL("-0x10000000000000000", 0, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("-0x10000000000000000", 16, 18446744073709551615LLU, 20, ERANGE); + TEST_STRTOULL("-10000000000000000", 16, 18446744073709551615LLU, 18, ERANGE); + TEST_STRTOULL("-01777777777777777777777",0, 1LLU, 24, 0); + TEST_STRTOULL("-01777777777777777777777",8, 1LLU, 24, 0); + TEST_STRTOULL("-1777777777777777777777",8, 1LLU, 23, 0); + TEST_STRTOULL("-02000000000000000000000",0, 18446744073709551615LLU, 24, ERANGE); + TEST_STRTOULL("-02000000000000000000000",8, 18446744073709551615LLU, 24, ERANGE); + TEST_STRTOULL("-2000000000000000000000",8, 18446744073709551615LLU, 23, ERANGE); + + printf("success: strtoull\n"); + return true; +} + +/* +FIXME: +Types: +bool +socklen_t +uint{8,16,32,64}_t +int{8,16,32,64}_t +intptr_t + +Constants: +PATH_NAME_MAX +UINT{16,32,64}_MAX +INT32_MAX +*/ + +static int test_va_copy(void) +{ + /* FIXME */ + return true; +} + +static int test_FUNCTION(void) +{ + printf("test: FUNCTION\n"); + if (strcmp(__FUNCTION__, "test_FUNCTION") != 0) { + printf("failure: FUNCTION [\nFUNCTION invalid\n]\n"); + return false; + } + printf("success: FUNCTION\n"); + return true; +} + +static int test_MIN(void) +{ + printf("test: MIN\n"); + if (MIN(20, 1) != 1) { + printf("failure: MIN [\nMIN invalid\n]\n"); + return false; + } + if (MIN(1, 20) != 1) { + printf("failure: MIN [\nMIN invalid\n]\n"); + return false; + } + printf("success: MIN\n"); + return true; +} + +static int test_MAX(void) +{ + printf("test: MAX\n"); + if (MAX(20, 1) != 20) { + printf("failure: MAX [\nMAX invalid\n]\n"); + return false; + } + if (MAX(1, 20) != 20) { + printf("failure: MAX [\nMAX invalid\n]\n"); + return false; + } + printf("success: MAX\n"); + return true; +} + +static int test_socketpair(void) +{ + int sock[2]; + char buf[20]; + + printf("test: socketpair\n"); + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, sock) == -1) { + printf("failure: socketpair [\n" + "socketpair() failed\n" + "]\n"); + return false; + } + + if (write(sock[1], "automatisch", 12) == -1) { + printf("failure: socketpair [\n" + "write() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (read(sock[0], buf, 12) == -1) { + printf("failure: socketpair [\n" + "read() failed: %s\n" + "]\n", strerror(errno)); + return false; + } + + if (strcmp(buf, "automatisch") != 0) { + printf("failure: socketpair [\n" + "expected: automatisch, got: %s\n" + "]\n", buf); + return false; + } + + printf("success: socketpair\n"); + + return true; +} + +extern int libreplace_test_strptime(void); + +static int test_strptime(void) +{ + return libreplace_test_strptime(); +} + +extern int getifaddrs_test(void); + +static int test_getifaddrs(void) +{ + + printf("test: getifaddrs\n"); + + if (getifaddrs_test() != 0) { + printf("failure: getifaddrs\n"); + return false; + } + + printf("success: getifaddrs\n"); + return true; +} + +static int test_utime(void) +{ + struct utimbuf u; + struct stat st1, st2, st3; + int fd; + + printf("test: utime\n"); + unlink(TESTFILE); + + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: utime [\n" + "creating '%s' failed - %s\n]\n", + TESTFILE, strerror(errno)); + return false; + } + + if (fstat(fd, &st1) != 0) { + printf("failure: utime [\n" + "fstat (1) failed - %s\n]\n", + strerror(errno)); + return false; + } + + u.actime = st1.st_atime + 300; + u.modtime = st1.st_mtime - 300; + if (utime(TESTFILE, &u) != 0) { + printf("failure: utime [\n" + "utime(&u) failed - %s\n]\n", + strerror(errno)); + return false; + } + + if (fstat(fd, &st2) != 0) { + printf("failure: utime [\n" + "fstat (2) failed - %s\n]\n", + strerror(errno)); + return false; + } + + if (utime(TESTFILE, NULL) != 0) { + printf("failure: utime [\n" + "utime(NULL) failed - %s\n]\n", + strerror(errno)); + return false; + } + + if (fstat(fd, &st3) != 0) { + printf("failure: utime [\n" + "fstat (3) failed - %s\n]\n", + strerror(errno)); + return false; + } + +#define CMP_VAL(a,c,b) do { \ + if (a c b) { \ + printf("failure: utime [\n" \ + "%s: %s(%d) %s %s(%d)\n]\n", \ + __location__, \ + #a, (int)a, #c, #b, (int)b); \ + return false; \ + } \ +} while(0) +#define EQUAL_VAL(a,b) CMP_VAL(a,!=,b) +#define GREATER_VAL(a,b) CMP_VAL(a,<=,b) +#define LESSER_VAL(a,b) CMP_VAL(a,>=,b) + + EQUAL_VAL(st2.st_atime, st1.st_atime + 300); + EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300); + LESSER_VAL(st3.st_atime, st2.st_atime); + GREATER_VAL(st3.st_mtime, st2.st_mtime); + +#undef CMP_VAL +#undef EQUAL_VAL +#undef GREATER_VAL +#undef LESSER_VAL + + unlink(TESTFILE); + printf("success: utime\n"); + return true; +} + +static int test_utimes(void) +{ + struct timeval tv[2]; + struct stat st1, st2; + int fd; + + printf("test: utimes\n"); + unlink(TESTFILE); + + fd = open(TESTFILE, O_RDWR|O_CREAT, 0600); + if (fd == -1) { + printf("failure: utimes [\n" + "creating '%s' failed - %s\n]\n", + TESTFILE, strerror(errno)); + return false; + } + + if (fstat(fd, &st1) != 0) { + printf("failure: utimes [\n" + "fstat (1) failed - %s\n]\n", + strerror(errno)); + return false; + } + + ZERO_STRUCT(tv); + tv[0].tv_sec = st1.st_atime + 300; + tv[1].tv_sec = st1.st_mtime - 300; + if (utimes(TESTFILE, tv) != 0) { + printf("failure: utimes [\n" + "utimes(tv) failed - %s\n]\n", + strerror(errno)); + return false; + } + + if (fstat(fd, &st2) != 0) { + printf("failure: utimes [\n" + "fstat (2) failed - %s\n]\n", + strerror(errno)); + return false; + } + +#define EQUAL_VAL(a,b) do { \ + if (a != b) { \ + printf("failure: utimes [\n" \ + "%s: %s(%d) != %s(%d)\n]\n", \ + __location__, \ + #a, (int)a, #b, (int)b); \ + return false; \ + } \ +} while(0) + + EQUAL_VAL(st2.st_atime, st1.st_atime + 300); + EQUAL_VAL(st2.st_mtime, st1.st_mtime - 300); + +#undef EQUAL_VAL + + unlink(TESTFILE); + printf("success: utimes\n"); + return true; +} + +static int test_memmem(void) +{ + char *s; + + printf("test: memmem\n"); + + s = (char *)memmem("foo", 3, "fo", 2); + if (strcmp(s, "foo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foo", 3, "", 0); + /* it is allowable for this to return NULL (as happens on + FreeBSD) */ + if (s && strcmp(s, "foo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foo", 4, "o", 1); + if (strcmp(s, "oo") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + s = (char *)memmem("foobarfodx", 11, "fod", 3); + if (strcmp(s, "fodx") != 0) { + printf(__location__ ": Failed memmem\n"); + return false; + } + + printf("success: memmem\n"); + + return true; +} + + +bool torture_local_replace(struct torture_context *ctx) +{ + bool ret = true; + ret &= test_ftruncate(); + ret &= test_strlcpy(); + ret &= test_strlcat(); + ret &= test_mktime(); + ret &= test_initgroups(); + ret &= test_memmove(); + ret &= test_strdup(); + ret &= test_setlinebuf(); + ret &= test_vsyslog(); + ret &= test_timegm(); + ret &= test_setenv(); + ret &= test_strndup(); + ret &= test_strnlen(); + ret &= test_waitpid(); + ret &= test_seteuid(); + ret &= test_setegid(); + ret &= test_asprintf(); + ret &= test_snprintf(); + ret &= test_vasprintf(); + ret &= test_vsnprintf(); + ret &= test_opendir(); + ret &= test_readdir(); + ret &= test_telldir(); + ret &= test_seekdir(); + ret &= test_dlopen(); + ret &= test_chroot(); + ret &= test_bzero(); + ret &= test_strerror(); + ret &= test_errno(); + ret &= test_mkdtemp(); + ret &= test_mkstemp(); + ret &= test_pread(); + ret &= test_pwrite(); + ret &= test_inet_ntoa(); + ret &= test_strtoll(); + ret &= test_strtoull(); + ret &= test_va_copy(); + ret &= test_FUNCTION(); + ret &= test_MIN(); + ret &= test_MAX(); + ret &= test_socketpair(); + ret &= test_strptime(); + ret &= test_getifaddrs(); + ret &= test_utime(); + ret &= test_utimes(); + ret &= test_memmem(); + + return ret; +} diff --git a/ctdb/lib/replace/timegm.c b/ctdb/lib/replace/timegm.c new file mode 100644 index 0000000000..395c684e11 --- /dev/null +++ b/ctdb/lib/replace/timegm.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + adapted for Samba4 by Andrew Tridgell +*/ + +#include "replace.h" +#include "system/time.h" + +static int is_leap(unsigned y) +{ + y += 1900; + return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); +} + +time_t rep_timegm(struct tm *tm) +{ + static const unsigned ndays[2][12] ={ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + time_t res = 0; + unsigned i; + + if (tm->tm_mon > 12 || + tm->tm_mon < 0 || + tm->tm_mday > 31 || + tm->tm_min > 60 || + tm->tm_sec > 60 || + tm->tm_hour > 24) { + /* invalid tm structure */ + return 0; + } + + for (i = 70; i < tm->tm_year; ++i) + res += is_leap(i) ? 366 : 365; + + for (i = 0; i < tm->tm_mon; ++i) + res += ndays[is_leap(tm->tm_year)][i]; + res += tm->tm_mday - 1; + res *= 24; + res += tm->tm_hour; + res *= 60; + res += tm->tm_min; + res *= 60; + res += tm->tm_sec; + return res; +} diff --git a/ctdb/lib/replace/timegm.m4 b/ctdb/lib/replace/timegm.m4 new file mode 100644 index 0000000000..9b76d0c727 --- /dev/null +++ b/ctdb/lib/replace/timegm.m4 @@ -0,0 +1 @@ +AC_CHECK_FUNCS(timegm,[],[LIBREPLACEOBJ="${LIBREPLACEOBJ} $libreplacedir/timegm.o"]) diff --git a/ctdb/lib/replace/win32.m4 b/ctdb/lib/replace/win32.m4 new file mode 100644 index 0000000000..eb364e2cb9 --- /dev/null +++ b/ctdb/lib/replace/win32.m4 @@ -0,0 +1,20 @@ +AC_CHECK_HEADERS(direct.h windows.h winsock2.h ws2tcpip.h) + +####################################### +# Check for mkdir mode +AC_CACHE_CHECK( [whether mkdir supports mode], libreplace_cv_mkdir_has_mode, + AC_TRY_COMPILE([ + #include <stdio.h> + #ifdef HAVE_DIRECT_H + #include <direct.h> + #endif],[ + mkdir("foo",0777); + return 0; + ], + libreplace_cv_mkdir_has_mode="yes", + libreplace_cv_mkdir_has_mode="no") ) + +if test "$libreplace_cv_mkdir_has_mode" = "yes" +then + AC_DEFINE(HAVE_MKDIR_MODE, 1, [Define if target mkdir supports mode option]) +fi diff --git a/ctdb/lib/replace/win32_replace.h b/ctdb/lib/replace/win32_replace.h new file mode 100644 index 0000000000..9901e72f6e --- /dev/null +++ b/ctdb/lib/replace/win32_replace.h @@ -0,0 +1,159 @@ +#ifndef _WIN32_REPLACE_H +#define _WIN32_REPLACE_H + +#ifdef HAVE_WINSOCK2_H +#include <winsock2.h> +#endif + +#ifdef HAVE_WS2TCPIP_H +#include <ws2tcpip.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif + +/* Map BSD Socket errorcodes to the WSA errorcodes (if possible) */ + +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#define ECONNREFUSED WSAECONNREFUSED +#define EINPROGRESS WSAEINPROGRESS +#define EMSGSIZE WSAEMSGSIZE +#define ENOBUFS WSAENOBUFS +#define ENOTSOCK WSAENOTSOCK +#define ENETUNREACH WSAENETUNREACH +#define ENOPROTOOPT WSAENOPROTOOPT +#define ENOTCONN WSAENOTCONN +#define ENOTSUP 134 + +/* We undefine the following constants due to conflicts with the w32api headers + * and the Windows Platform SDK/DDK. + */ + +#undef interface + +#undef ERROR_INVALID_PARAMETER +#undef ERROR_INSUFFICIENT_BUFFER +#undef ERROR_INVALID_DATATYPE + +#undef FILE_GENERIC_READ +#undef FILE_GENERIC_WRITE +#undef FILE_GENERIC_EXECUTE +#undef FILE_ATTRIBUTE_READONLY +#undef FILE_ATTRIBUTE_HIDDEN +#undef FILE_ATTRIBUTE_SYSTEM +#undef FILE_ATTRIBUTE_DIRECTORY +#undef FILE_ATTRIBUTE_ARCHIVE +#undef FILE_ATTRIBUTE_DEVICE +#undef FILE_ATTRIBUTE_NORMAL +#undef FILE_ATTRIBUTE_TEMPORARY +#undef FILE_ATTRIBUTE_REPARSE_POINT +#undef FILE_ATTRIBUTE_COMPRESSED +#undef FILE_ATTRIBUTE_OFFLINE +#undef FILE_ATTRIBUTE_ENCRYPTED +#undef FILE_FLAG_WRITE_THROUGH +#undef FILE_FLAG_NO_BUFFERING +#undef FILE_FLAG_RANDOM_ACCESS +#undef FILE_FLAG_SEQUENTIAL_SCAN +#undef FILE_FLAG_DELETE_ON_CLOSE +#undef FILE_FLAG_BACKUP_SEMANTICS +#undef FILE_FLAG_POSIX_SEMANTICS +#undef FILE_TYPE_DISK +#undef FILE_TYPE_UNKNOWN +#undef FILE_CASE_SENSITIVE_SEARCH +#undef FILE_CASE_PRESERVED_NAMES +#undef FILE_UNICODE_ON_DISK +#undef FILE_PERSISTENT_ACLS +#undef FILE_FILE_COMPRESSION +#undef FILE_VOLUME_QUOTAS +#undef FILE_VOLUME_IS_COMPRESSED +#undef FILE_NOTIFY_CHANGE_FILE_NAME +#undef FILE_NOTIFY_CHANGE_DIR_NAME +#undef FILE_NOTIFY_CHANGE_ATTRIBUTES +#undef FILE_NOTIFY_CHANGE_SIZE +#undef FILE_NOTIFY_CHANGE_LAST_WRITE +#undef FILE_NOTIFY_CHANGE_LAST_ACCESS +#undef FILE_NOTIFY_CHANGE_CREATION +#undef FILE_NOTIFY_CHANGE_EA +#undef FILE_NOTIFY_CHANGE_SECURITY +#undef FILE_NOTIFY_CHANGE_STREAM_NAME +#undef FILE_NOTIFY_CHANGE_STREAM_SIZE +#undef FILE_NOTIFY_CHANGE_STREAM_WRITE +#undef FILE_NOTIFY_CHANGE_NAME + +#undef PRINTER_ATTRIBUTE_QUEUED +#undef PRINTER_ATTRIBUTE_DIRECT +#undef PRINTER_ATTRIBUTE_DEFAULT +#undef PRINTER_ATTRIBUTE_SHARED +#undef PRINTER_ATTRIBUTE_NETWORK +#undef PRINTER_ATTRIBUTE_HIDDEN +#undef PRINTER_ATTRIBUTE_LOCAL +#undef PRINTER_ATTRIBUTE_ENABLE_DEVQ +#undef PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS +#undef PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST +#undef PRINTER_ATTRIBUTE_WORK_OFFLINE +#undef PRINTER_ATTRIBUTE_ENABLE_BIDI +#undef PRINTER_ATTRIBUTE_RAW_ONLY +#undef PRINTER_ATTRIBUTE_PUBLISHED +#undef PRINTER_ENUM_DEFAULT +#undef PRINTER_ENUM_LOCAL +#undef PRINTER_ENUM_CONNECTIONS +#undef PRINTER_ENUM_FAVORITE +#undef PRINTER_ENUM_NAME +#undef PRINTER_ENUM_REMOTE +#undef PRINTER_ENUM_SHARED +#undef PRINTER_ENUM_NETWORK +#undef PRINTER_ENUM_EXPAND +#undef PRINTER_ENUM_CONTAINER +#undef PRINTER_ENUM_ICON1 +#undef PRINTER_ENUM_ICON2 +#undef PRINTER_ENUM_ICON3 +#undef PRINTER_ENUM_ICON4 +#undef PRINTER_ENUM_ICON5 +#undef PRINTER_ENUM_ICON6 +#undef PRINTER_ENUM_ICON7 +#undef PRINTER_ENUM_ICON8 +#undef PRINTER_STATUS_PAUSED +#undef PRINTER_STATUS_ERROR +#undef PRINTER_STATUS_PENDING_DELETION +#undef PRINTER_STATUS_PAPER_JAM +#undef PRINTER_STATUS_PAPER_OUT +#undef PRINTER_STATUS_MANUAL_FEED +#undef PRINTER_STATUS_PAPER_PROBLEM +#undef PRINTER_STATUS_OFFLINE +#undef PRINTER_STATUS_IO_ACTIVE +#undef PRINTER_STATUS_BUSY +#undef PRINTER_STATUS_PRINTING +#undef PRINTER_STATUS_OUTPUT_BIN_FULL +#undef PRINTER_STATUS_NOT_AVAILABLE +#undef PRINTER_STATUS_WAITING +#undef PRINTER_STATUS_PROCESSING +#undef PRINTER_STATUS_INITIALIZING +#undef PRINTER_STATUS_WARMING_UP +#undef PRINTER_STATUS_TONER_LOW +#undef PRINTER_STATUS_NO_TONER +#undef PRINTER_STATUS_PAGE_PUNT +#undef PRINTER_STATUS_USER_INTERVENTION +#undef PRINTER_STATUS_OUT_OF_MEMORY +#undef PRINTER_STATUS_DOOR_OPEN +#undef PRINTER_STATUS_SERVER_UNKNOWN +#undef PRINTER_STATUS_POWER_SAVE + +#undef DWORD +#undef HKEY_CLASSES_ROOT +#undef HKEY_CURRENT_USER +#undef HKEY_LOCAL_MACHINE +#undef HKEY_USERS +#undef HKEY_PERFORMANCE_DATA +#undef HKEY_CURRENT_CONFIG +#undef HKEY_DYN_DATA +#undef REG_DWORD +#undef REG_QWORD + +#undef SERVICE_STATE_ALL + +#undef SE_GROUP_MANDATORY +#undef SE_GROUP_ENABLED_BY_DEFAULT +#undef SE_GROUP_ENABLED + +#endif /* _WIN32_REPLACE_H */ diff --git a/ctdb/lib/replace/wscript b/ctdb/lib/replace/wscript new file mode 100644 index 0000000000..2117f56e22 --- /dev/null +++ b/ctdb/lib/replace/wscript @@ -0,0 +1,632 @@ +#!/usr/bin/env python + +APPNAME = 'libreplace' +VERSION = '1.2.1' + +blddir = 'bin' + +import sys, os, Utils + +# find the buildtools directory +srcdir = '.' +while not os.path.exists(srcdir+'/buildtools') and len(srcdir.split('/')) < 5: + srcdir = '../' + srcdir +sys.path.insert(0, srcdir + '/buildtools/wafsamba') + +import wafsamba, samba_dist +import Options, os, preproc + +samba_dist.DIST_DIRS('lib/replace buildtools:buildtools') + +def set_options(opt): + opt.BUILTIN_DEFAULT('NONE') + opt.PRIVATE_EXTENSION_DEFAULT('') + opt.RECURSE('buildtools/wafsamba') + +@wafsamba.runonce +def configure(conf): + conf.RECURSE('buildtools/wafsamba') + + conf.env.standalone_replace = conf.IN_LAUNCH_DIR() + + conf.DEFINE('HAVE_LIBREPLACE', 1) + conf.DEFINE('LIBREPLACE_NETWORK_CHECKS', 1) + + # on Tru64 certain features are only available with _OSF_SOURCE set to 1 + # and _XOPEN_SOURCE set to 600 + if conf.env['SYSTEM_UNAME_SYSNAME'] == 'OSF1': + conf.DEFINE('_OSF_SOURCE', 1, add_to_cflags=True) + conf.DEFINE('_XOPEN_SOURCE', 600, add_to_cflags=True) + + # SCM_RIGHTS is only avail if _XOPEN_SOURCE iŃ• defined on IRIX + if conf.env['SYSTEM_UNAME_SYSNAME'] == 'IRIX': + conf.DEFINE('_XOPEN_SOURCE', 600, add_to_cflags=True) + conf.DEFINE('_BSD_TYPES', 1, add_to_cflags=True) + + # Try to find the right extra flags for C99 initialisers + for f in ["", "-AC99", "-qlanglvl=extc99", "-qlanglvl=stdc99", "-c99"]: + if conf.CHECK_CFLAGS([f], ''' +struct foo {int x;char y;}; +struct foo bar = { .y = 'X', .x = 1 }; +'''): + if f != "": + conf.ADD_CFLAGS(f) + break + + if conf.CHECK_CFLAGS(['-fstack-protector']) and conf.CHECK_LDFLAGS(['-fstack-protector']): + conf.ADD_CFLAGS('-fstack-protector') + conf.ADD_LDFLAGS('-fstack-protector') + + # Try to find the right extra flags for -Werror behaviour + for f in ["-Werror", # GCC + "-errwarn=%all", # Sun Studio + "-qhalt=w", # IBM xlc + "-w2", # Tru64 + ]: + if conf.CHECK_CFLAGS([f], ''' +'''): + if not 'WERROR_CFLAGS' in conf.env: + conf.env['WERROR_CFLAGS'] = [] + conf.env['WERROR_CFLAGS'].extend([f]) + break + + 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('libaio.h 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 sys/fs/vx/quota.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 malloc.h 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('libintl.h errno.h') + conf.CHECK_HEADERS('gcrypt.h getopt.h iconv.h') + conf.CHECK_HEADERS('sys/inotify.h memory.h nss.h sasl/sasl.h') + conf.CHECK_HEADERS('security/pam_appl.h zlib.h asm/unistd.h') + conf.CHECK_HEADERS('aio.h sys/unistd.h rpc/rpc.h rpc/nettype.h alloca.h float.h') + + conf.CHECK_HEADERS('rpcsvc/nis.h rpcsvc/ypclnt.h 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_CODE('', headers='rpc/rpc.h rpcsvc/yp_prot.h', define='HAVE_RPCSVC_YP_PROT_H') + + conf.CHECK_HEADERS('valgrind.h valgrind/valgrind.h valgrind/memcheck.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 malloc.h') + conf.CHECK_HEADERS('syscall.h sys/syscall.h inttypes.h') + + # Check for process set name support + conf.CHECK_CODE(''' + #include <sys/prctl.h> + int main(void) { + prctl(0); + return 0; + } + ''', + 'HAVE_PRCTL', + headers='sys/prctl.h', + msg='Checking for prctl syscall') + + conf.CHECK_CODE(''' + #include <unistd.h> + #ifdef HAVE_FCNTL_H + #include <fcntl.h> + #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') + conf.CHECK_TYPE('_Bool', define='HAVE__Bool') + conf.CHECK_TYPE('bool', define='HAVE_BOOL') + + 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') + 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_IN('''inet_ntoa inet_aton inet_ntop inet_pton connect gethostbyname + getaddrinfo getnameinfo freeaddrinfo gai_strerror socketpair''', + 'socket nsl', checklibc=True, + headers='sys/socket.h netinet/in.h arpa/inet.h netdb.h') + + # 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 <linux/in6.h> + #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') + + 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') + + # 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 <idra@samba.org> + # 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') + 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('prctl') + + # libbsd on some platforms provides strlcpy and strlcat + if not conf.CHECK_FUNCS('strlcpy strlcat'): + conf.CHECK_FUNCS_IN('strlcpy strlcat', 'bsd', headers='bsd/string.h', + checklibc=True) + 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', 'bsd', headers='sys/types.h bsd/unistd.h'): + conf.CHECK_FUNCS_IN('setproctitle', 'setproctitle', headers='setproctitle.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 convertion 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_nametoindex strerror_r') + conf.CHECK_FUNCS('getdirentries getdents 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_create') + + conf.SET_TARGET_TYPE('attr', 'EMPTY') + + xattr_headers='sys/attributes.h attr/xattr.h sys/xattr.h' + + conf.CHECK_FUNCS_IN(''' +fgetxattr flistea flistxattr +fremovexattr fsetxattr getxattr +listxattr removexattr setxattr +''', 'attr', checklibc=True, headers=xattr_headers) + + # We need to check for linux xattrs first, as we do not wish to link to -lattr + # (the XFS compat API) on Linux systems with the native xattr API + if not conf.CONFIG_SET('HAVE_GETXATTR'): + conf.CHECK_FUNCS_IN(''' +attr_get attr_getf attr_list attr_listf attropen attr_remove +attr_removef attr_set attr_setf extattr_delete_fd extattr_delete_file +extattr_get_fd extattr_get_file extattr_list_fd extattr_list_file +extattr_set_fd extattr_set_file fgetea +fremoveea fsetea getea listea +removeea setea +''', 'attr', checklibc=True, headers=xattr_headers) + + if (conf.CONFIG_SET('HAVE_ATTR_LISTF') or + conf.CONFIG_SET('HAVE_EXTATTR_LIST_FD') or + conf.CONFIG_SET('HAVE_FLISTEA') or + conf.CONFIG_SET('HAVE_FLISTXATTR')): + conf.DEFINE('HAVE_XATTR_SUPPORT', 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") + + 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') + + if conf.CHECK_FUNCS_IN('fdatasync', 'rt', checklibc=True): + # some systems are missing the declaration + conf.CHECK_DECLS('fdatasync') + + if conf.CHECK_FUNCS_IN('clock_gettime', 'rt', checklibc=True): + for c in ['CLOCK_MONOTONIC', 'CLOCK_PROCESS_CPUTIME_ID', 'CLOCK_REALTIME']: + conf.CHECK_CODE(''' + #if TIME_WITH_SYS_TIME + # include <sys/time.h> + # include <time.h> + #else + # if HAVE_SYS_TIME_H + # include <sys/time.h> + # else + # include <time.h> + # 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') + + + if not conf.CHECK_FUNCS_IN('gettext', 'intl', checklibc=True, headers='libintl.h'): + # Some hosts need lib iconv for linking with lib intl + # So we try with flags just in case it helps. + oldflags = conf.env['LDFLAGS_INTL'] + conf.env['LDFLAGS_INTL'] = "-liconv" + if not conf.CHECK_LIB('intl'): + conf.env['LDFLAGS_INTL'] = oldflags + else: + conf.CHECK_FUNCS_IN('gettext', 'intl', checklibc=True, headers='libintl.h') + + conf.CHECK_FUNCS_IN('dgettext gettext', 'intl', headers='libintl.h') + conf.CHECK_FUNCS_IN('pthread_create', 'pthread', checklibc=True, headers='pthread.h') + + conf.CHECK_FUNCS_IN('crypt', '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_DECLS('snprintf vsnprintf asprintf vasprintf') + + conf.CHECK_DECLS('errno', headers='errno.h', reverse=True) + conf.CHECK_DECLS('environ 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_CREATE') and conf.CONFIG_SET('HAVE_SYS_EPOLL_H'): + conf.DEFINE('HAVE_EPOLL', 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 "test/strptime.c"''', + define='HAVE_WORKING_STRPTIME', + execute=True, + addmain=False, + msg='Checking for working strptime') + + conf.CHECK_CODE('gettimeofday(NULL, NULL)', 'HAVE_GETTIMEOFDAY_TZ', execute=False) + + conf.CHECK_CODE('#include "test/snprintf.c"', + define="HAVE_C99_VSNPRINTF", + execute=True, + addmain=False, + msg="Checking for C99 vsnprintf") + + conf.CHECK_CODE('#include "test/shared_mmap.c"', + addmain=False, add_headers=False, execute=True, + define='HAVE_SHARED_MMAP', + msg="Checking for HAVE_SHARED_MMAP") + + conf.CHECK_CODE('#include "test/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 "test/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') + + conf.CHECK_STRUCTURE_MEMBER('struct stat', 'st_mtim.tv_nsec', define='HAVE_STAT_TV_NSEC', + 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_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 + + if conf.CHECK_CFLAGS('-fvisibility=hidden'): + conf.env.VISIBILITY_CFLAGS = '-fvisibility=hidden' + conf.CHECK_CODE('''void vis_foo1(void) {} + __attribute__((visibility("default"))) void vis_foo2(void) {}''', + cflags=conf.env.VISIBILITY_CFLAGS, + define='HAVE_VISIBILITY_ATTR') + + # 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']: + if conf.CHECK_CODE(''' + #define %s 1 + #define NO_CONFIG_H 1 + #define AUTOCONF_TEST 1 + #define SOCKET_WRAPPER_NOT_REPLACE + #include "replace.c" + #include "inet_ntop.c" + #include "snprintf.c" + #include "getifaddrs.c" + #define getifaddrs_test main + #include "test/getifaddrs.c" + ''' % method, + method, + lib='nsl socket', + addmain=False, + execute=True): + break + + conf.RECURSE('system') + conf.SAMBA_CONFIG_H() + + +REPLACEMENT_FUNCTIONS = { + 'replace.c': ['ftruncate', 'strlcpy', 'strlcat', 'mktime', 'initgroups', + 'memmove', 'strdup', 'setlinebuf', 'vsyslog', 'strnlen', + 'strndup', 'waitpid', 'seteuid', 'setegid', 'chroot', + 'mkstemp', 'mkdtemp', 'pread', 'pwrite', 'strcasestr', + 'strtok_r', 'strtoll', 'strtoull', 'setenv', 'unsetenv', + 'utime', 'utimes', 'dup2', 'chown', 'link', 'readlink', + 'symlink', 'lchown', 'realpath', 'memmem', 'vdprintf', + 'dprintf', 'get_current_dir_name', + 'strerror_r', 'clock_gettime'], + '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, functions in REPLACEMENT_FUNCTIONS.iteritems(): + for function in functions: + 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' + + bld.SAMBA_SUBSYSTEM('LIBREPLACE_HOSTCC', + REPLACE_HOSTCC_SOURCE, + use_hostcc=True, + use_global_deps=False, + cflags='-DSOCKET_WRAPPER_DISABLE=1 -DNSS_WRAPPER_DISABLE=1 -DUID_WRAPPER_DISABLE=1 -D_SAMBA_HOSTCC_', + group='compiler_libraries', + deps = extra_libs + ) + + REPLACE_SOURCE = REPLACE_HOSTCC_SOURCE + + if not bld.CONFIG_SET('HAVE_CRYPT'): REPLACE_SOURCE += ' crypt.c' + 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' + + 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, + deps='crypt dl nsl socket rt attr' + extra_libs) + + bld.SAMBA_SUBSYSTEM('replace-test', + source='''test/testsuite.c test/strptime.c + test/os2_delete.c test/getifaddrs.c''', + deps='replace') + + if bld.env.standalone_replace: + bld.SAMBA_BINARY('replace_testsuite', + source='test/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')) + +def dist(): + '''makes a tarball for distribution''' + samba_dist.dist() diff --git a/ctdb/lib/replace/xattr.c b/ctdb/lib/replace/xattr.c new file mode 100644 index 0000000000..a26ff674a1 --- /dev/null +++ b/ctdb/lib/replace/xattr.c @@ -0,0 +1,729 @@ +/* + Unix SMB/CIFS implementation. + replacement routines for xattr implementations + Copyright (C) Jeremy Allison 1998-2005 + Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 + Copyright (C) Herb Lewis 2003 + Copyright (C) Andrew Bartlett 2012 + + ** NOTE! The following LGPL license applies to the replace + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" +#include "system/filesys.h" +#include "system/dir.h" + +/******** Solaris EA helper function prototypes ********/ +#ifdef HAVE_ATTROPEN +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP +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); +#endif + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX and (Net|Free)BSD also. Expand as other systems have them. +****************************************************************************/ + +ssize_t rep_getxattr (const char *path, const char *name, void *value, size_t size) +{ +#if defined(HAVE_GETXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return getxattr(path, name, value, size); +#else + +/* So that we do not recursivly call this function */ +#undef getxattr + int options = 0; + return getxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_GETEA) + return getea(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FILE) + char *s; + ssize_t retval; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1; + /* + * 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. + */ + if((retval=extattr_get_file(path, attrnamespace, attrname, NULL, 0)) >= 0) { + if (size == 0) { + return retval; + } else if (retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_file(path, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + return -1; +#elif defined(HAVE_ATTR_GET) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + if (size == 0 && retval == -1 && errno == E2BIG) { + return valuelength; + } + + return retval ? retval : valuelength; +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t rep_fgetxattr (int filedes, const char *name, void *value, size_t size) +{ +#if defined(HAVE_FGETXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fgetxattr(filedes, name, value, size); +#else + +/* So that we do not recursivly call this function */ +#undef fgetxattr + int options = 0; + return fgetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FGETEA) + return fgetea(filedes, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FD) + char *s; + ssize_t retval; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr(name, '.')) == NULL) ? name : s + 1; + + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) { + if (size == 0) { + return retval; + } else if (retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + return -1; +#elif defined(HAVE_ATTR_GETF) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + if (size == 0 && retval == -1 && errno == E2BIG) { + return valuelength; + } + return retval ? retval : valuelength; +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +#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 < ARRAY_SIZE(extattr); 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; + } + /* Shift results back, so we can prepend prefixes */ + buf = (char *)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 + +#if defined(HAVE_ATTR_LIST) && (defined(HAVE_SYS_ATTRIBUTES_H) || defined(HAVE_ATTR_ATTRIBUTES_H)) +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 + +ssize_t rep_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return listxattr(path, list, size); +#else +/* So that we do not recursivly call this function */ +#undef listxattr + int options = 0; + return listxattr(path, list, size, options); +#endif +#elif defined(HAVE_LISTEA) + return listea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_FILE) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, 0); +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t rep_flistxattr (int filedes, char *list, size_t size) +{ +#if defined(HAVE_FLISTXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return flistxattr(filedes, list, size); +#else +/* So that we do not recursivly call this function */ +#undef flistxattr + int options = 0; + return flistxattr(filedes, list, size, options); +#endif +#elif defined(HAVE_FLISTEA) + return flistea(filedes, list, size); +#elif defined(HAVE_EXTATTR_LIST_FD) + extattr_arg arg; + arg.filedes = filedes; + return bsd_attr_list(2, arg, list, size); +#elif defined(HAVE_ATTR_LISTF) + return irix_attr_list(NULL, filedes, list, size, 0); +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_removexattr (const char *path, const char *name) +{ +#if defined(HAVE_REMOVEXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return removexattr(path, name); +#else +/* So that we do not recursivly call this function */ +#undef removexattr + int options = 0; + return removexattr(path, name, options); +#endif +#elif defined(HAVE_REMOVEEA) + return removeea(path, name); +#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(name, '.')) == NULL) ? name : s + 1; + + return extattr_delete_file(path, attrnamespace, attrname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_fremovexattr (int filedes, const char *name) +{ +#if defined(HAVE_FREMOVEXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fremovexattr(filedes, name); +#else +/* So that we do not recursivly call this function */ +#undef fremovexattr + int options = 0; + return fremovexattr(filedes, name, options); +#endif +#elif defined(HAVE_FREMOVEEA) + return fremoveea(filedes, name); +#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(name, '.')) == NULL) ? name : s + 1; + + return extattr_delete_fd(filedes, attrnamespace, attrname); +#elif defined(HAVE_ATTR_REMOVEF) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_removef(filedes, attrname, flags); +#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; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_setxattr (const char *path, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_SETXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return setxattr(path, name, value, size, flags); +#else +/* So that we do not recursivly call this function */ +#undef setxattr + int options = 0; + return setxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_SETEA) + return setea(path, name, value, size, flags); +#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(name, '.')) == NULL) ? name : s + 1; + 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; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_file(path, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SET) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + 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); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int rep_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags) +{ +#if defined(HAVE_FSETXATTR) +#ifndef XATTR_ADDITIONAL_OPTIONS + return fsetxattr(filedes, name, value, size, flags); +#else +/* So that we do not recursivly call this function */ +#undef fsetxattr + int options = 0; + return fsetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FSETEA) + return fsetea(filedes, name, value, size, flags); +#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(name, '.')) == NULL) ? name : s + 1; + 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; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SETF) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + 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); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_XATTR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +/************************************************************************** + 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; + 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) + 1; + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { + /* we don't want "." and ".." here: */ + continue; + } + + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen; + } else { + /* check size and copy entrieŃ• + nul into list. */ + if ((len + listlen) > size) { + errno = ERANGE; + len = -1; + break; + } else { + strlcpy(list + len, de->d_name, listlen); + len += listlen; + } + } + } + + if (closedir(dirp) == -1) { + 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) { + 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) { + 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 { + return -1; + } +} +#endif /*HAVE_ATTROPEN*/ + + |