From d084c2987bc4d0bf51b893c8d53098081382fec8 Mon Sep 17 00:00:00 2001 From: Frank Lahm Date: Mon, 17 Jan 2011 17:12:19 +0100 Subject: [PATCH] Integrate talloc from Samba, cleanup configure functions checks --- configure.in | 42 +- etc/afpd/file.c | 15 - etc/afpd/filedir.c | 14 - etc/afpd/gettok.c | 15 - etc/afpd/nfsquota.c | 13 - etc/afpd/quota.c | 13 - etc/afpd/uam.c | 15 - etc/afpd/unix.c | 17 - etc/afpd/volume.c | 13 - etc/uams/uams_gss.c | 16 +- etc/uams/uams_guest.c | 17 +- etc/uams/uams_krb4/uams_krb4.c | 15 - etc/uams/uams_pam.c | 15 - etc/uams/uams_passwd.c | 13 - etc/uams/uams_randnum.c | 15 - include/atalk/compat.h | 102 +- include/atalk/talloc.h | 202 +++ include/atalk/util.h | 21 +- libatalk/Makefile.am | 2 +- libatalk/compat/Makefile.am | 4 +- libatalk/compat/misc.c | 15 + libatalk/compat/snprintf.c | 1132 --------------- libatalk/compat/strcasecmp.c | 109 -- libatalk/compat/strdup.c | 23 - libatalk/{util => compat}/strlcpy.c | 0 libatalk/compat/strstr.c | 77 -- libatalk/talloc/Makefile.am | 7 + libatalk/talloc/talloc.c | 1990 +++++++++++++++++++++++++++ libatalk/unicode/charcnv.c | 4 +- libatalk/util/Makefile.am | 2 - libatalk/util/fault.c | 2 +- libatalk/util/strcasestr.c | 124 -- 32 files changed, 2280 insertions(+), 1784 deletions(-) create mode 100644 include/atalk/talloc.h create mode 100644 libatalk/compat/misc.c delete mode 100644 libatalk/compat/snprintf.c delete mode 100644 libatalk/compat/strcasecmp.c delete mode 100644 libatalk/compat/strdup.c rename libatalk/{util => compat}/strlcpy.c (100%) delete mode 100644 libatalk/compat/strstr.c create mode 100644 libatalk/talloc/Makefile.am create mode 100644 libatalk/talloc/talloc.c delete mode 100644 libatalk/util/strcasestr.c diff --git a/configure.in b/configure.in index aeff8134..293202d3 100644 --- a/configure.in +++ b/configure.in @@ -23,14 +23,23 @@ AC_PROG_GREP AC_PROG_PS AM_PROG_CC_C_O +dnl Request SUSv3 standard interfaces plus anything else the platform may have +CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ -D_GNU_SOURCE" + dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h limits.h stdint.h strings.h time.h sys/param.h sys/fcntl.h sys/file.h sys/ioctl.h sys/time.h sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h mntent.h syslog.h unistd.h termios.h sys/termios.h netdb.h sgtty.h ufs/quota.h mount.h statfs.h sys/types.h dlfcn.h errno.h sys/errno.h sys/uio.h langinfo.h locale.h sys/filio.h) +AC_CHECK_HEADERS(fcntl.h limits.h stdint.h strings.h time.h stdarg.h) +AC_CHECK_HEADERS(mntent.h syslog.h unistd.h termios.h ufs/quota.h) +AC_CHECK_HEADERS(netdb.h sgtty.h mount.h statfs.h dlfcn.h errno.h langinfo.h locale.h) +AC_CHECK_HEADERS(sys/param.h sys/fcntl.h sys/file.h sys/ioctl.h sys/time.h) +AC_CHECK_HEADERS(sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h) +AC_CHECK_HEADERS(sys/termios.h sys/types.h sys/errno.h sys/uio.h sys/filio.h) AC_CHECK_HEADER(sys/cdefs.h,, AC_MSG_RESULT([enabling generic cdefs.h from tree]) CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS" ) + AC_CHECK_HEADERS([sys/mount.h], , , [#ifdef HAVE_SYS_PARAM_H #include @@ -59,26 +68,18 @@ if test x"$libltdl_cv_need_uscore" = xyes; then AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro]) fi -dnl Checks for library functions. -AC_TYPE_GETGROUPS -AC_PROG_GCC_TRADITIONAL -AC_FUNC_MEMCMP -AC_HEADER_MAJOR -AC_FUNC_MMAP -AC_TYPE_SIGNAL -AC_FUNC_UTIME_NULL -AC_FUNC_WAIT3 -AC_CHECK_FUNCS(getcwd gethostname gettimeofday getusershell mkdir rmdir select socket strdup strcasestr strstr strtoul strchr memcpy) -AC_CHECK_FUNCS(backtrace_symbols setlocale nl_langinfo strlcpy strlcat setlinebuf dirfd pselect access pread pwrite) -AC_CHECK_FUNCS(waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64) -AC_CHECK_FUNC(renameat, AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)) +dnl Special hecks AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include ]) -AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) -AC_CHECK_FUNC(connect,,[AC_CHECK_LIB(socket,connect)]) -dnl search for necessary libs for libpthread stuff -AC_SEARCH_LIBS(pthread_sigmask, pthread,, - [AC_MSG_ERROR([cannot find pthread_sigmask in libc or libpthread])]) +dnl these tests have been comfirmed to be needed in 2011 +AC_CHECK_FUNC(renameat, AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)) +AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect) +AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen) + +dnl search for necessary libraries +AC_SEARCH_LIBS(gethostbyname, nsl) +AC_SEARCH_LIBS(connect, socket) +AC_SEARCH_LIBS(pthread_sigmask, pthread,,[AC_MSG_ERROR([missing pthread_sigmask])]) if test x"$ac_cv_search_pthread_sigmask" != x"none required" ; then PTHREAD_LIBS=$ac_cv_search_pthread_sigmask fi @@ -1253,8 +1254,6 @@ dnl --------------------- Netatalk Webmin NETATALK_WEBMIN dnl --------------------- last minute substitutions -dnl Request SUSv3 standard interfaces -CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__" AC_SUBST(LIBS) AC_SUBST(CFLAGS) AC_SUBST(OVERWRITE_CONFIG) @@ -1349,6 +1348,7 @@ AC_OUTPUT([Makefile libatalk/nbp/Makefile libatalk/netddp/Makefile libatalk/util/Makefile + libatalk/talloc/Makefile libatalk/tdb/Makefile libatalk/unicode/Makefile libatalk/unicode/charsets/Makefile diff --git a/etc/afpd/file.c b/etc/afpd/file.c index ebe61e12..e827134a 100644 --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@ -10,22 +10,7 @@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); - -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include diff --git a/etc/afpd/filedir.c b/etc/afpd/filedir.c index be7056a7..ebde9655 100644 --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@ -9,21 +9,7 @@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #ifdef HAVE_STRINGS_H #include #endif diff --git a/etc/afpd/gettok.c b/etc/afpd/gettok.c index d4e4d8f5..f8ef210a 100644 --- a/etc/afpd/gettok.c +++ b/etc/afpd/gettok.c @@ -10,22 +10,7 @@ #endif /* HAVE_CONFIG_H */ #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include diff --git a/etc/afpd/nfsquota.c b/etc/afpd/nfsquota.c index e3ad5ddc..60622733 100644 --- a/etc/afpd/nfsquota.c +++ b/etc/afpd/nfsquota.c @@ -20,20 +20,7 @@ #ifndef NO_QUOTA_SUPPORT #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #include #include #include /* for DEV_BSIZE */ diff --git a/etc/afpd/quota.c b/etc/afpd/quota.c index 9992948c..06008c20 100644 --- a/etc/afpd/quota.c +++ b/etc/afpd/quota.c @@ -15,20 +15,7 @@ #include #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #include #include #include diff --git a/etc/afpd/uam.c b/etc/afpd/uam.c index 5c105e31..8e247a24 100644 --- a/etc/afpd/uam.c +++ b/etc/afpd/uam.c @@ -11,22 +11,7 @@ #include #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ diff --git a/etc/afpd/unix.c b/etc/afpd/unix.c index 8f1fca20..b1ddfd91 100644 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@ -9,24 +9,7 @@ #include #include - -/* STDC check */ -#ifdef STDC_HEADERS #include -#else /* STDC_HEADERS */ - -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); - -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index ccd4b68e..89678605 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -17,20 +17,7 @@ #ifdef HAVE_STRINGS_H #include #endif -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #include #include #include diff --git a/etc/uams/uams_gss.c b/etc/uams/uams_gss.c index 044dd278..0560f5f7 100644 --- a/etc/uams/uams_gss.c +++ b/etc/uams/uams_gss.c @@ -17,23 +17,9 @@ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include + #include #include #include diff --git a/etc/uams/uams_guest.c b/etc/uams/uams_guest.c index 0b5019e0..7a2482d6 100644 --- a/etc/uams/uams_guest.c +++ b/etc/uams/uams_guest.c @@ -11,25 +11,10 @@ #include #include #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include -#include +#include #include #include #include diff --git a/etc/uams/uams_krb4/uams_krb4.c b/etc/uams/uams_krb4/uams_krb4.c index ff7c2c0a..1d2727a8 100644 --- a/etc/uams/uams_krb4/uams_krb4.c +++ b/etc/uams/uams_krb4/uams_krb4.c @@ -21,22 +21,7 @@ #include #include #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include diff --git a/etc/uams/uams_pam.c b/etc/uams/uams_pam.c index 46ce0d51..a374cc33 100644 --- a/etc/uams/uams_pam.c +++ b/etc/uams/uams_pam.c @@ -15,22 +15,7 @@ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #ifdef HAVE_SECURITY_PAM_APPL_H diff --git a/etc/uams/uams_passwd.c b/etc/uams/uams_passwd.c index d026a50d..507cb04f 100644 --- a/etc/uams/uams_passwd.c +++ b/etc/uams/uams_passwd.c @@ -21,20 +21,7 @@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ diff --git a/etc/uams/uams_randnum.c b/etc/uams/uams_randnum.c index 3d3a5bb9..c9a275ba 100644 --- a/etc/uams/uams_randnum.c +++ b/etc/uams/uams_randnum.c @@ -12,22 +12,7 @@ #include #include - -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #ifdef HAVE_UNISTD_H #include #endif /* HAVE_UNISTD_H */ diff --git a/include/atalk/compat.h b/include/atalk/compat.h index 42995534..f66c3a31 100644 --- a/include/atalk/compat.h +++ b/include/atalk/compat.h @@ -9,88 +9,22 @@ #include #include -#ifdef __svr4__ -/* - * SunOS 5 (solaris) has SA_RESTART, but no SA_INTERRUPT. - */ -#ifndef SA_INTERRUPT -#define SA_INTERRUPT 0 -#endif - -#include -#include -#include - -extern int flock (int, int); -extern int inet_aton (const char *, struct in_addr *); -#else /* __svr4__ */ - -#ifdef sun -/* - * SunOS 4 has SA_INTERRUPT, but no SA_RESTART. - */ -#ifndef SA_RESTART -#define SA_RESTART 0 -#endif -#endif /* sun */ - -#endif /* __svr4__ */ - -#ifdef linux -/* - * Linux has SA_RESTART, but no SA_INTERRUPT. Note that the documentation - * seems to be wrong on several counts. First, SA_ONESHOT is not the default, - * and second, SA_RESTART does what you'd expect (the same as svr4) and has - * nothing to do with SA_ONESHOT. - */ -#ifndef SA_INTERRUPT -#define SA_INTERRUPT 0 -#endif /* SA_INTERRUPT */ -#endif /* linux */ - -#ifdef ultrix -#include -#include -#include - -/* - * Here's the really confusing one... Under Ultrix, sigaction() works just - * like sigvec(), except that SV_INTERRUPT is always set. Hence, there is - * no SA_INTERRUPT flag. Unfortunately, there's also no SA_RESTART, so - * there's no way to suppress the interrupt. Sigh. - */ -#ifndef SA_INTERRUPT -#define SA_INTERRUPT 0 -#endif -#ifndef SA_RESTART -#define SA_RESTART 0 -#endif - -extern char *strdup (const char *); -extern int inet_aton (const char *, struct in_addr *); -#endif /* ultrix */ - -#ifdef BSD4_4 -#ifndef SA_INTERRUPT -#define SA_INTERRUPT 0 -#endif -#endif /* BSD4_4 */ +#include "config.h" #if defined(ultrix) || defined(_IBMR2) || defined(NEED_GETUSERSHELL) extern char *getusershell (void); #endif #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) -#include -#include -#endif - -#ifndef HAVE_SNPRINTF +# include +# include +# ifndef HAVE_SNPRINTF int snprintf (char *str,size_t count,const char *fmt,...); -#endif +# endif -#ifndef HAVE_VSNPRINTF +# ifndef HAVE_VSNPRINTF int vsnprintf(char *str, size_t count, const char *fmt, va_list args); +# endif #endif /* OpenBSD */ @@ -103,3 +37,25 @@ extern int pselect(int, fd_set * restrict, fd_set * restrict, fd_set * restrict, const struct timespec * restrict, const sigset_t * restrict); #endif + +#ifndef HAVE_FLOCK +extern int flock (int, int); +#endif + +#ifndef HAVE_INET_ATON +struct in_addr; +extern int inet_aton(const char *, struct in_addr *); +#endif + +#ifndef HAVE_STRNLEN +extern size_t strnlen(const char *s, size_t n); +#endif + +#ifndef HAVE_STRLCPY +extern size_t strlcpy (char *, const char *, size_t); +#endif + +#ifndef HAVE_STRLCAT +extern size_t strlcat (char *, const char *, size_t); +#endif + diff --git a/include/atalk/talloc.h b/include/atalk/talloc.h new file mode 100644 index 00000000..f549a17f --- /dev/null +++ b/include/atalk/talloc.h @@ -0,0 +1,202 @@ +#ifndef _TALLOC_H_ +#define _TALLOC_H_ +/* + Unix SMB/CIFS implementation. + Samba temporary memory allocation functions + + Copyright (C) Andrew Tridgell 2004-2005 + Copyright (C) Stefan Metzmacher 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 . +*/ + +#include +#include +#include + +#define TALLOC_VERSION_MAJOR 2 +#define TALLOC_VERSION_MINOR 0 + +int talloc_version_major(void); +int talloc_version_minor(void); + +/* this is only needed for compatibility with the old talloc */ +typedef void TALLOC_CTX; + +/* + this uses a little trick to allow __LINE__ to be stringified +*/ +#ifndef __location__ +#define __TALLOC_STRING_LINE1__(s) #s +#define __TALLOC_STRING_LINE2__(s) __TALLOC_STRING_LINE1__(s) +#define __TALLOC_STRING_LINE3__ __TALLOC_STRING_LINE2__(__LINE__) +#define __location__ __FILE__ ":" __TALLOC_STRING_LINE3__ +#endif + +#ifndef TALLOC_DEPRECATED +#define TALLOC_DEPRECATED 0 +#endif + +#ifndef PRINTF_ATTRIBUTE +#if (__GNUC__ >= 3) +/** 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 + +/* try to make talloc_set_destructor() and talloc_steal() type safe, + if we have a recent gcc */ +#if (__GNUC__ >= 3) +#define _TALLOC_TYPEOF(ptr) __typeof__(ptr) +#define talloc_set_destructor(ptr, function) \ + do { \ + int (*_talloc_destructor_fn)(_TALLOC_TYPEOF(ptr)) = (function); \ + _talloc_set_destructor((ptr), (int (*)(void *))_talloc_destructor_fn); \ + } while(0) +/* this extremely strange macro is to avoid some braindamaged warning + stupidity in gcc 4.1.x */ +#define talloc_steal(ctx, ptr) ({ _TALLOC_TYPEOF(ptr) __talloc_steal_ret = (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__); __talloc_steal_ret; }) +#else +#define talloc_set_destructor(ptr, function) \ + _talloc_set_destructor((ptr), (int (*)(void *))(function)) +#define _TALLOC_TYPEOF(ptr) void * +#define talloc_steal(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_steal_loc((ctx),(ptr), __location__) +#endif + +#define talloc_reference(ctx, ptr) (_TALLOC_TYPEOF(ptr))_talloc_reference_loc((ctx),(ptr), __location__) +#define talloc_move(ctx, ptr) (_TALLOC_TYPEOF(*(ptr)))_talloc_move((ctx),(void *)(ptr)) + +/* useful macros for creating type checked pointers */ +#define talloc(ctx, type) (type *)talloc_named_const(ctx, sizeof(type), #type) +#define talloc_size(ctx, size) talloc_named_const(ctx, size, __location__) +#define talloc_ptrtype(ctx, ptr) (_TALLOC_TYPEOF(ptr))talloc_size(ctx, sizeof(*(ptr))) + +#define talloc_new(ctx) talloc_named_const(ctx, 0, "talloc_new: " __location__) + +#define talloc_zero(ctx, type) (type *)_talloc_zero(ctx, sizeof(type), #type) +#define talloc_zero_size(ctx, size) _talloc_zero(ctx, size, __location__) + +#define talloc_zero_array(ctx, type, count) (type *)_talloc_zero_array(ctx, sizeof(type), count, #type) +#define talloc_array(ctx, type, count) (type *)_talloc_array(ctx, sizeof(type), count, #type) +#define talloc_array_size(ctx, size, count) _talloc_array(ctx, size, count, __location__) +#define talloc_array_ptrtype(ctx, ptr, count) (_TALLOC_TYPEOF(ptr))talloc_array_size(ctx, sizeof(*(ptr)), count) +#define talloc_array_length(ctx) (talloc_get_size(ctx)/sizeof(*ctx)) + +#define talloc_realloc(ctx, p, type, count) (type *)_talloc_realloc_array(ctx, p, sizeof(type), count, #type) +#define talloc_realloc_size(ctx, ptr, size) _talloc_realloc(ctx, ptr, size, __location__) + +#define talloc_memdup(t, p, size) _talloc_memdup(t, p, size, __location__) + +#define talloc_set_type(ptr, type) talloc_set_name_const(ptr, #type) +#define talloc_get_type(ptr, type) (type *)talloc_check_name(ptr, #type) +#define talloc_get_type_abort(ptr, type) (type *)_talloc_get_type_abort(ptr, #type, __location__) + +#define talloc_find_parent_bytype(ptr, type) (type *)talloc_find_parent_byname(ptr, #type) +#define talloc_free(ctx) _talloc_free(ctx, __location__) + + +#if TALLOC_DEPRECATED +#define talloc_zero_p(ctx, type) talloc_zero(ctx, type) +#define talloc_p(ctx, type) talloc(ctx, type) +#define talloc_array_p(ctx, type, count) talloc_array(ctx, type, count) +#define talloc_realloc_p(ctx, p, type, count) talloc_realloc(ctx, p, type, count) +#define talloc_destroy(ctx) talloc_free(ctx) +#define talloc_append_string(c, s, a) (s?talloc_strdup_append(s,a):talloc_strdup(c, a)) +#endif + +#define TALLOC_FREE(ctx) do { talloc_free(ctx); ctx=NULL; } while(0) + +/* The following definitions come from talloc.c */ +void *_talloc(const void *context, size_t size); +void *talloc_pool(const void *context, size_t size); +void _talloc_set_destructor(const void *ptr, int (*_destructor)(void *)); +int talloc_increase_ref_count(const void *ptr); +size_t talloc_reference_count(const void *ptr); +void *_talloc_reference_loc(const void *context, const void *ptr, const char *location); +int talloc_unlink(const void *context, void *ptr); +const char *talloc_set_name(const void *ptr, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +void talloc_set_name_const(const void *ptr, const char *name); +void *talloc_named(const void *context, size_t size, + const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); +void *talloc_named_const(const void *context, size_t size, const char *name); +const char *talloc_get_name(const void *ptr); +void *talloc_check_name(const void *ptr, const char *name); +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location); +void *talloc_parent(const void *ptr); +const char *talloc_parent_name(const void *ptr); +void *talloc_init(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +int _talloc_free(void *ptr, const char *location); +void talloc_free_children(void *ptr); +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name); +void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location); +void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr); +void *_talloc_move(const void *new_ctx, const void *pptr); +size_t talloc_total_size(const void *ptr); +size_t talloc_total_blocks(const void *ptr); +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data); +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f); +void talloc_report_full(const void *ptr, FILE *f); +void talloc_report(const void *ptr, FILE *f); +void talloc_enable_null_tracking(void); +void talloc_enable_null_tracking_no_autofree(void); +void talloc_disable_null_tracking(void); +void talloc_enable_leak_report(void); +void talloc_enable_leak_report_full(void); +void *_talloc_zero(const void *ctx, size_t size, const char *name); +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name); +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name); +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name); +void *talloc_realloc_fn(const void *context, void *ptr, size_t size); +void *talloc_autofree_context(void); +size_t talloc_get_size(const void *ctx); +void *talloc_find_parent_byname(const void *ctx, const char *name); +void talloc_show_parents(const void *context, FILE *file); +int talloc_is_parent(const void *context, const void *ptr); + +char *talloc_strdup(const void *t, const char *p); +char *talloc_strdup_append(char *s, const char *a); +char *talloc_strdup_append_buffer(char *s, const char *a); + +char *talloc_strndup(const void *t, const char *p, size_t n); +char *talloc_strndup_append(char *s, const char *a, size_t n); +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n); + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +char *talloc_asprintf(const void *t, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)); +void talloc_set_log_fn(void (*log_fn)(const char *message)); +void talloc_set_log_stderr(void); + +#endif diff --git a/include/atalk/util.h b/include/atalk/util.h index ba55bc9b..c94306d2 100644 --- a/include/atalk/util.h +++ b/include/atalk/util.h @@ -45,6 +45,14 @@ #define AFP_ASSERT(b) #endif /* NDEBUG */ +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + #define STRCMP(a,b,c) (strcmp(a,c) b 0) #ifdef WITH_SENDFILE @@ -69,19 +77,6 @@ extern void fault_setup (void (*fn)(void *)); extern void netatalk_panic(const char *why); #define server_unlock(x) (unlink(x)) -/* strlcpy and strlcat are used by pam modules */ -#ifndef UAM_MODULE_EXPORT -#define UAM_MODULE_EXPORT -#endif - -#ifndef HAVE_STRLCPY -UAM_MODULE_EXPORT size_t strlcpy (char *, const char *, size_t); -#endif - -#ifndef HAVE_STRLCAT -UAM_MODULE_EXPORT size_t strlcat (char *, const char *, size_t); -#endif - #ifndef HAVE_DLFCN_H extern void *mod_open (const char *); extern void *mod_symbol (void *, const char *); diff --git a/libatalk/Makefile.am b/libatalk/Makefile.am index a7023731..ab44b3d6 100644 --- a/libatalk/Makefile.am +++ b/libatalk/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am for libatalk/ -SUBDIRS = acl adouble bstring compat cnid dsi tdb util unicode vfs +SUBDIRS = acl adouble bstring compat cnid dsi talloc tdb util unicode vfs lib_LTLIBRARIES = libatalk.la diff --git a/libatalk/compat/Makefile.am b/libatalk/compat/Makefile.am index 515681d3..2338cf39 100644 --- a/libatalk/compat/Makefile.am +++ b/libatalk/compat/Makefile.am @@ -5,4 +5,6 @@ noinst_LTLIBRARIES = libcompat.la libcompat_la_SOURCES = \ getusershell.c \ rquota_xdr.c \ - pselect.c + pselect.c \ + strlcpy.c \ + misc.c diff --git a/libatalk/compat/misc.c b/libatalk/compat/misc.c new file mode 100644 index 00000000..2fe6a7f3 --- /dev/null +++ b/libatalk/compat/misc.c @@ -0,0 +1,15 @@ +#include + +#ifndef HAVE_STRNLEN +size_t strnlen(const char *s, size_t max) +{ + size_t len; + + for (len = 0; len < max; len++) { + if (s[len] == '\0') { + break; + } + } + return len; +} +#endif diff --git a/libatalk/compat/snprintf.c b/libatalk/compat/snprintf.c deleted file mode 100644 index eea77295..00000000 --- a/libatalk/compat/snprintf.c +++ /dev/null @@ -1,1132 +0,0 @@ -/************************************************************************** - * Copyright 1994-2000 Patrick Powell, San Diego, CA - * - * Modified for Netatalk 2002/02/12 Burkhard Schmidt - **************************************************************************/ - -/* - Overview: - - plp_snprintf( char *buffer, int len, const char *format,...) - plp_unsafe_snprintf( char *buffer, int len, const char *format,...) - its horribly unsafe companion that does NOT protect you from - the printing of evil control characters, but may be necessary - See the man page documentation below - - This version of snprintf was developed originally for printing - on a motley collection of specialized hardware that had NO IO - library. Due to contractual restrictions, a clean room implementation - of the printf() code had to be developed. - - The method chosen for printf was to be as paranoid as possible, - as these platforms had NO memory protection, and very small - address spaces. This made it possible to try to print - very long strings, i.e. - all of memory, very easily. To guard - against this, all printing was done via a buffer, generous enough - to hold strings, but small enough to protect against overruns, - etc. - - Strangely enough, this proved to be of immense importance when - SPRINTFing to a buffer on a stack... The rest, of course, is - well known, as buffer overruns in the stack are a common way to - do horrible things to operating systems, security, etc etc. - - This version of snprintf is VERY limited by modern standards. - - Revision History: - First Released Version - 1994. This version had NO comments. - First Released Version - 1994. This version had NO comments. - Second Major Released Version - Tue May 23 10:43:44 PDT 2000 - Configuration and other items changed. Read this doc. - Treat this as a new version. - - COPYRIGHT AND TERMS OF USE: - - You may use, copy, distribute, or otherwise incorporate this software - and documentation into any product or other item, provided that - the copyright in the documentation and source code as well as the - source code generated constant strings in the object, executable - or other code remain in place and are present in executable modules - or objects. - - You may modify this code as appropriate to your usage; however the - modified version must be identified by changing the various source - and object code identification strings as is appropriately noted - in the source code. - - The next include line is expected to work in conjunction with the - GNU CONFIGURE utility. You should define the following macros - appropriately: - - HAVE_STDARG_H - if the include file is available - HAVE_VARARG_H - if the include file is available - - HAVE_STRERROR - if the strerror() routine is available. - If it is not available, then examine the lines containing - the tests below. You may need to fiddle with HAVE_SYS_NERR - HAVE_SYS_ERRLIST - HAVE_DECL_SYS_ERRLIST - HAVE_SYS_NERR - HAVE_DECL_SYS_NERR - - HAVE_QUAD_T - if the quad_t type is defined - HAVE_LONG_LONG - if the long long type is defined - HAVE_LONG_DOUBLE - if the long double type is defined - - If you are using the GNU configure (autoconf) facility, add the - following line to the configure.in file, to force checking for the - quad_t and long long data types: - - - AC_CHECK_FUNCS(strerror); - AC_CACHE_CHECK(for errno, - ac_cv_errno, - [ - AC_TRY_LINK(,[extern int errno; return (errno);], - ac_cv_errno=yes, ac_cv_errno=no) - ]) - if test "$ac_cv_errno" = yes; then - AC_DEFINE(HAVE_ERRNO) - AC_CACHE_CHECK(for errno declaration, - ac_cv_decl_errno, - [ - AC_TRY_COMPILE([ - #include - #ifdef HAVE_STDLIB_H - #include - #endif - #ifdef HAVE_UNISTD_H - #include - #endif - #ifdef HAVE_ERRNO_H - #include - ],[return(sys_nerr);], - ac_cv_decl_errno=yes, ac_cv_decl_errno=no) - ]) - if test "$ac_cv_decl_errno" = yes; then - AC_DEFINE(HAVE_DECL_ERRNO) - fi; - fi - - AC_CACHE_CHECK(for sys_nerr, - ac_cv_sys_nerr, - [ - AC_TRY_LINK(,[extern int sys_nerr; return (sys_nerr);], - ac_cv_sys_nerr=yes, ac_cv_sys_nerr=no) - ]) - if test "$ac_cv_sys_nerr" = yes; then - AC_DEFINE(HAVE_SYS_NERR) - AC_CACHE_CHECK(for sys_nerr declaration, - ac_cv_decl_sys_nerr, - [ - AC_TRY_COMPILE([ - #include - #ifdef HAVE_STDLIB_H - #include - #endif - #ifdef HAVE_UNISTD_H - #include - #endif],[return(sys_nerr);], - ac_cv_decl_sys_nerr_def=yes, ac_cv_decl_sys_nerr_def=no) - ]) - if test "$ac_cv_decl_sys_nerr" = yes; then - AC_DEFINE(HAVE_DECL_SYS_NERR) - fi - fi - - - AC_CACHE_CHECK(for sys_errlist array, - ac_cv_sys_errlist, - [AC_TRY_LINK(,[extern char *sys_errlist[]; - sys_errlist[0];], - ac_cv_sys_errlist=yes, ac_cv_sys_errlist=no) - ]) - if test "$ac_cv_sys_errlist" = yes; then - AC_DEFINE(HAVE_SYS_ERRLIST) - AC_CACHE_CHECK(for sys_errlist declaration, - ac_cv_sys_errlist_def, - [AC_TRY_COMPILE([ - #include - #include - #ifdef HAVE_STDLIB_H - #include - #endif - #ifdef HAVE_UNISTD_H - #include - #endif],[char *s = sys_errlist[0]; return(*s);], - ac_cv_decl_sys_errlist=yes, ac_cv_decl_sys_errlist=no) - ]) - if test "$ac_cv_decl_sys_errlist" = yes; then - AC_DEFINE(HAVE_DECL_SYS_ERRLIST) - fi - fi - - - - AC_CACHE_CHECK(checking for long long, - ac_cv_long_long, - [ - AC_TRY_COMPILE([ - #include - #include - ], [printf("%d",sizeof(long long));], - ac_cv_long_long=yes, ac_cv_long_long=no) - ]) - if test $ac_cv_long_long = yes; then - AC_DEFINE(HAVE_LONG_LONG) - fi - - AC_CACHE_CHECK(checking for long double, - ac_cv_long_double, - [ - AC_TRY_COMPILE([ - #include - #include - ], [printf("%d",sizeof(long double));], - ac_cv_long_double=yes, ac_cv_long_double=no) - ]) - if test $ac_cv_long_double = yes; then - AC_DEFINE(HAVE_LONG_DOUBLE) - fi - - AC_CACHE_CHECK(checking for quad_t, - ac_cv_quad_t, - [ - AC_TRY_COMPILE([ - #include - #include - ], [printf("%d",sizeof(quad_t));], - ac_cv_quad_t=yes, ac_cv_quad_t=no) - ]) - if test $ac_cv_quad_t = yes; then - AC_DEFINE(HAVE_QUAD_T) - fi - - - -NAME - plp_snprintf, plp_vsnprintf - formatted output conversion - -SYNOPSIS - #include - #include - - int - plp_snprintf(const char *format, size_t size, va_list ap); - int - plp_unsafe_snprintf(const char *format, size_t size, va_list ap); - - AKA snprintf and unsafe_snprintf in the documentation below - - int - vsnprintf(char *str, size_t size, const char *format, va_list ap); - int - unsafe_vsnprintf(char *str, size_t size, const char *format, va_list ap); - - AKA vsnprintf and unsafe_vsnprintf in the documentation below - - (Multithreaded Safe) - -DESCRIPTION - The printf() family of functions produces output according to - a format as described below. Snprintf(), and vsnprintf() - write to the character string str. These functions write the - output under the control of a format string that specifies - how subsequent arguments (or arguments accessed via the - variable-length argument facilities of stdarg(3)) are converted - for output. These functions return the number of characters - printed (not including the trailing `\0' used to end output - to strings). Snprintf() and vsnprintf() will write at most - size-1 of the characters printed into the output string (the - size'th character then gets the terminating `\0'); if the - return value is greater than or equal to the size argument, - the string was too short and some of the printed characters - were discarded. The size or str may be given as zero to find - out how many characters are needed; in this case, the str - argument is ignored. - - By default, the snprintf function will not format control - characters (except new line and tab) in strings. This is a - safety feature that has proven to be extremely critical when - using snprintf for secure applications and when debugging. - If you MUST have control characters formatted or printed, - then use the unsafe_snprintf() and unsafe_vsnprintf() and on - your own head be the consequences. You have been warned. - - There is one exception to the comments above, and that is - the "%c" (character) format. It brutally assumes that the - user will have performed the necessary 'isprint()' or other - checks and uses the integer value as a character. - - The format string is composed of zero or more directives: - ordinary characters (not %), which are copied unchanged to - the output stream; and conversion specifications, each - of which results in fetching zero or more subsequent arguments. - Each conversion specification is introduced by the character - %. The arguments must correspond properly (after type promotion) - with the conversion specifier. After the %, the following - appear in sequence: - - o Zero or more of the following flags: - - - A zero `0' character specifying zero padding. For - all conversions except n, the converted value is padded - on the left with zeros rather than blanks. If a - precision is given with a numeric conversion (d, i, - o, u, i, x, and X), the `0' flag is ignored. - - - A negative field width flag `-' indicates the converted - value is to be left adjusted on the field boundary. Except - for n conversions, the converted value is padded on - the right with blanks, rather than on the left with - blanks or zeros. A `-' overrides a `0' if both are - given. - - - A space, specifying that a blank should be left before - a positive number produced by a signed conversion (d, e, E, f, - g, G, or i). - - - A `+' character specifying that a sign always be placed - before a number produced by a signed conversion. A `+' overrides - a space if both are used. - - o An optional decimal digit string specifying a minimum - field width. If the converted value has fewer - characters than the field width, it will be padded - with spaces on the left (or right, if the - left-adjustment flag has been given) to fill out - the field width. - - o An optional precision, in the form of a period `.' followed - by an optional digit string. If the digit string - is omitted, the precision is taken as zero. This - gives the minimum number of digits to appear for - d, i, o, u, x, and X conversions, the number of - digits to appear after the decimal-point for e, - E, and f conversions, the maximum number of - significant digits for g and G conversions, or - the maximum number of characters to be printed - from a string for s conversions. - - o The optional character h, specifying that a following d, - i, o, u, x, or X conversion corresponds to a short - int or unsigned short int argument, or that a - following n conversion corresponds to a pointer - to a short int argument. - - o The optional character l (ell) specifying that a following - d, i, o, u, x, or X conversion applies to a pointer - to a long int or unsigned long int argument, or - that a following n conversion corresponds to a - pointer to a long int argument. - - o The optional character q, specifying that a following d, - i, o, u, x, or X conversion corresponds to a quad_t - or u_quad_t argument, or that a following n - conversion corresponds to a quad_t argument. - This value is always printed in HEX notation. Tough. - quad_t's are an OS system implementation, and should - not be allowed. - - o The character L specifying that a following e, E, f, g, - or G conversion corresponds to a long double - argument. - - o A character that specifies the type of conversion to be applied. - - - A field width or precision, or both, may be indicated by an asterisk `*' - instead of a digit string. In this case, an int argument supplies the - field width or precision. A negative field width is treated as a left - adjustment flag followed by a positive field width; a negative precision - is treated as though it were missing. - - The conversion specifiers and their meanings are: - - diouxX The int (or appropriate variant) argument is converted to signed - decimal (d and i), unsigned octal (o), unsigned decimal - (u), or unsigned hexadecimal (x and X) notation. The - letters abcdef are used for x conversions; the letters - ABCDEF are used for X conversions. The precision, if - any, gives the minimum number of digits that must - appear; if the converted value requires fewer digits, - it is padded on the left with zeros. - - eE The double argument is rounded and converted in the style - [-]d.ddde+-dd where there is one digit before the decimal-point - character and the number of digits after it is equal - to the precision; if the precision is missing, it is - taken as 6; if the precision is zero, no decimal-point - character appears. An E conversion uses the letter - E (rather than e) to introduce the exponent. - The exponent always contains at least two digits; if - the value is zero, the exponent is 00. - - f The double argument is rounded and converted to decimal notation - in the style [-]ddd.ddd, where the number of digits after the - decimal-point character is equal to the precision specification. - If the precision is missing, it is taken as 6; if the precision - is explicitly zero, no decimal-point character appears. If a - decimal point appears, at least one digit appears before it. - - g The double argument is converted in style f or e (or - E for G conversions). The precision specifies the - number of significant digits. If the precision is - missing, 6 digits are given; if the precision is zero, - it is treated as 1. Style e is used if the exponent - from its conversion is less than -4 or greater than - or equal to the precision. Trailing zeros are removed - from the fractional part of the result; a decimal - point appears only if it is followed by at least one - digit. - - c The int argument is converted to an unsigned char, - and the resulting character is written. - - s The ``char *'' argument is expected to be a pointer to an array - of character type (pointer to a string). Characters - from the array are written up to (but not including) - a terminating NUL character; if a precision is - specified, no more than the number specified are - written. If a precision is given, no null character - need be present; if the precision is not specified, - or is greater than the size of the array, the array - must contain a terminating NUL character. - - % A `%' is written. No argument is converted. The complete - conversion specification is `%%'. - - In no case does a non-existent or small field width cause truncation of a - field; if the result of a conversion is wider than the field width, the - field is expanded to contain the conversion result. - -EXAMPLES - To print a date and time in the form `Sunday, July 3, 10:02', where - weekday and month are pointers to strings: - - #include - fprintf(stdout, "%s, %s %d, %.2d:%.2d\n", - weekday, month, day, hour, min); - - To print pi to five decimal places: - - #include - #include - fprintf(stdout, "pi = %.5f\n", 4 * atan(1.0)); - - To allocate a 128 byte string and print into it: - - #include - #include - #include - char *newfmt(const char *fmt, ...) - { - char *p; - va_list ap; - if ((p = malloc(128)) == NULL) - return (NULL); - va_start(ap, fmt); - (void) vsnprintf(p, 128, fmt, ap); - va_end(ap); - return (p); - } - -SEE ALSO - printf(1), scanf(3) - -STANDARDS - Turkey C Standardization and wimpy POSIX folks did not define - snprintf or vsnprintf(). - -BUGS - The conversion formats %D, %O, and %U are not standard and are provided - only for backward compatibility. The effect of padding the %p format - with zeros (either by the `0' flag or by specifying a precision), and the - benign effect (i.e., none) of the `#' flag on %n and %p conversions, as - well as other nonsensical combinations such as %Ld, are not standard; - such combinations should be avoided. - - The typedef names quad_t and u_quad_t are infelicitous. - -*/ - - -#include "config.h" - -#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) - -#include -#include -#include -#if defined(HAVE_STRING_H) -# include -#endif -#if defined(HAVE_STRINGS_H) -# include -#endif -#include - -/* - * For testing, define these values - */ -#if 0 -#define HAVE_STDARG_H 1 -#define TEST 1 -#define HAVE_QUAD_T 1 -#endif - -/**** ENDINCLUDE ****/ - -/************************************************* - * KEEP THIS STRING - MODIFY AT THE END WITH YOUR REVISIONS - * i.e. - the LOCAL REVISIONS part is for your use - *************************************************/ - - - static char *const _id = "plp_snprintf V98.12.21 Copyright Patrick Powell 1988-2000 " - "$Id: snprintf.c,v 1.2 2008-11-14 10:29:08 didg Exp $" - " LOCAL REVISIONS: Modified for Netatalk 2002/02/12 Burkhard Schmidt"; - -/* varargs declarations: */ - -# undef HAVE_STDARGS /* let's hope that works everywhere (mj) */ -# undef VA_LOCAL_DECL -# undef VA_START -# undef VA_SHIFT -# undef VA_END - -#if defined(HAVE_STDARG_H) -# include -# define HAVE_STDARGS /* let's hope that works everywhere (mj) */ -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap, f) -# define VA_SHIFT(v,t) ; /* no-op for ANSI */ -# define VA_END va_end(ap) -#else -# if defined(HAVE_VARARGS_H) -# include -# undef HAVE_STDARGS -# define VA_LOCAL_DECL va_list ap; -# define VA_START(f) va_start(ap) /* f is ignored! */ -# define VA_SHIFT(v,t) v = va_arg(ap,t) -# define VA_END va_end(ap) -# else -XX ** NO VARARGS ** XX -# endif -#endif - -union value { -#if defined(HAVE_QUAD_T) - quad_t qvalue; -#endif -#if defined(HAVE_LONG_LONG) - long long value; -#else - long value; -#endif - double dvalue; -}; - -#undef CVAL -#define CVAL(s) (*((unsigned char *)s)) - -extern int errno; - static char * plp_Errormsg ( int err, char *buffer ); - static void dopr( int visible_control, char **buffer, int *left, - const char *format, va_list args ); - static void fmtstr( int visible_control, char **buffer, int *left, - char *value, int ljust, int len, int zpad, int precision ); - static void fmtnum( char **buffer, int *left, - union value *value, int base, int dosign, - int ljust, int len, int zpad, int precision ); -#if defined(HAVE_QUAD_T) - static void fmtquad( char **buffer, int *left, - union value *value, int base, int dosign, - int ljust, int len, int zpad, int precision ); -#endif - static void fmtdouble( char **bufer, int *left, - int fmt, double value, - int ljust, int len, int zpad, int precision ); - static void dostr( char **buffer, int *left, char *str ); - static void dopr_outch( char **buffer, int *left, int c ); - -int plp_vsnprintf(char *str, size_t count, const char *fmt, va_list args) -{ - int left; - char *buffer; - if( count < 0 ) count = 0; - left = count; - if( count == 0 ) str = 0; - buffer = str; - dopr( 1, &buffer, &left, fmt, args ); - /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", - (int)str, (int)buffer, count, left ); */ - if( str && count > 0 ){ - if( left > 0 ){ - str[count-left] = 0; - } else { - str[count-1] = 0; - } - } - return(count - left); -} - -int plp_unsafe_vsnprintf(char *str, size_t count, const char *fmt, va_list args) -{ - int left; - char *buffer; - if( count < 0 ) count = 0; - left = count; - if( count == 0 ) str = 0; - buffer = str; - dopr( 0, &buffer, &left, fmt, args ); - /* fprintf(stderr,"str 0x%x, buffer 0x%x, count %d, left %d\n", - (int)str, (int)buffer, count, left ); */ - if( str && count > 0 ){ - if( left > 0 ){ - str[count-left] = 0; - } else { - str[count-1] = 0; - } - } - return(count - left); -} - -/* VARARGS3 */ -#ifdef HAVE_STDARGS -int plp_snprintf (char *str,size_t count,const char *fmt,...) -#else -int plp_snprintf (va_alist) va_dcl -#endif -{ -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - int n = 0; - VA_LOCAL_DECL - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - n = plp_vsnprintf ( str, count, fmt, ap); - VA_END; - return( n ); -} - - -/* VARARGS3 */ -#ifdef HAVE_STDARGS -int plp_unsafe_snprintf (char *str,size_t count,const char *fmt,...) -#else -int plp_unsafe_snprintf (va_alist) va_dcl -#endif -{ -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - int n = 0; - VA_LOCAL_DECL - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - n = plp_unsafe_vsnprintf ( str, count, fmt, ap); - VA_END; - return( n ); -} - static void dopr( int visible_control, char **buffer, int *left, const char *format, va_list args ) -{ - int ch; - union value value; - int longflag = 0; - int quadflag = 0; - char *strvalue; - int ljust; - int len; - int zpad; - int precision; - int set_precision; - double dval; - int err = errno; - int base = 0; - int signed_val = 0; - - while( (ch = *format++) ){ - switch( ch ){ - case '%': - longflag = quadflag = - ljust = len = zpad = base = signed_val = 0; - precision = -1; set_precision = 0; - nextch: - ch = *format++; - switch( ch ){ - case 0: - dostr( buffer, left, "**end of format**" ); - return; - case '-': ljust = 1; goto nextch; - case '.': set_precision = 1; precision = 0; goto nextch; - case '*': len = va_arg( args, int ); goto nextch; - case '0': /* set zero padding if len not set */ - if(len==0 && set_precision == 0 ) zpad = '0'; - case '1': case '2': case '3': - case '4': case '5': case '6': - case '7': case '8': case '9': - if( set_precision ){ - precision = precision*10 + ch - '0'; - } else { - len = len*10 + ch - '0'; - } - goto nextch; - case 'l': ++longflag; goto nextch; - case 'q': -#if !defined( HAVE_QUAD_T ) - dostr( buffer, left, "*no quad_t support *"); - return; -#endif - quadflag = 1; - goto nextch; - case 'u': case 'U': - if( base == 0 ){ base = 10; signed_val = 0; } - case 'o': case 'O': - if( base == 0 ){ base = 8; signed_val = 0; } - case 'd': case 'D': - if( base == 0 ){ base = 10; signed_val = 1; } - case 'x': - if( base == 0 ){ base = 16; signed_val = 0; } - case 'X': - if( base == 0 ){ base = -16; signed_val = 0; } -#if defined( HAVE_QUAD_T ) - if( quadflag ){ - value.qvalue = va_arg( args, quad_t ); - fmtquad( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); - break; - } else -#endif - if( longflag > 1 ){ -#if defined(HAVE_LONG_LONG) - if( signed_val ){ - value.value = va_arg( args, long long ); - } else { - value.value = va_arg( args, unsigned long long ); - } -#else - if( signed_val ){ - value.value = va_arg( args, long ); - } else { - value.value = va_arg( args, unsigned long ); - } -#endif - } else if( longflag ){ - if( signed_val ){ - value.value = va_arg( args, long ); - } else { - value.value = va_arg( args, unsigned long ); - } - } else { - if( signed_val ){ - value.value = va_arg( args, int ); - } else { - value.value = va_arg( args, unsigned int ); - } - } - fmtnum( buffer, left, &value,base,signed_val, ljust, len, zpad, precision ); break; - case 's': - strvalue = va_arg( args, char *); - fmtstr( visible_control, buffer, left, strvalue,ljust,len, zpad, precision ); - break; - case 'c': - ch = va_arg( args, int ); - { char b[2]; - b[0] = ch; - b[1] = 0; - fmtstr( 0, buffer, left, b,ljust,len, zpad, precision ); - } - break; - case 'f': case 'g': case 'e': - dval = va_arg( args, double ); - fmtdouble( buffer, left, ch, dval,ljust,len, zpad, precision ); break; - case 'm': - { char shortbuffer[32]; - fmtstr( visible_control, buffer, left, - plp_Errormsg(err, shortbuffer),ljust,len, zpad, precision ); - } - break; - case '%': dopr_outch( buffer, left, ch ); continue; - default: - dostr( buffer, left, "???????" ); - } - longflag = 0; - break; - default: - dopr_outch( buffer, left, ch ); - break; - } - } -} - -/* - * Format '%[-]len[.precision]s' - * - = left justify (ljust) - * len = minimum length - * precision = numbers of chars in string to use - */ - static void -fmtstr( int visible_control, char **buffer, int *left, - char *value, int ljust, int len, int zpad, int precision ) -{ - int padlen, strlenv, i, c; /* amount to pad */ - - if( value == 0 ){ - value = ""; - } - /* cheap strlen so you do not have library call */ - for( strlenv = i = 0; (c=CVAL(value+i)); ++i ){ - if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ - ++strlenv; - } - ++strlenv; - } - if( precision > 0 && strlenv > precision ){ - strlenv = precision; - } - padlen = len - strlenv; - if( padlen < 0 ) padlen = 0; - if( ljust ) padlen = -padlen; - while( padlen > 0 ) { - dopr_outch( buffer, left, ' ' ); - --padlen; - } - /* output characters */ - for( i = 0; i < strlenv && (c = CVAL(value+i)); ++i ){ - if( visible_control && iscntrl( c ) && c != '\t' && c != '\n' ){ - dopr_outch(buffer, left, '^'); - c = ('@' | (c & 0x1F)); - } - dopr_outch(buffer, left, c); - } - while( padlen < 0 ) { - dopr_outch( buffer, left, ' ' ); - ++padlen; - } -} - - static void -fmtnum( char **buffer, int *left, - union value *value, int base, int dosign, int ljust, - int len, int zpad, int precision ) -{ - int signvalue = 0; -#if defined(HAVE_LONG_LONG) - unsigned long long uvalue; -#else - unsigned long uvalue; -#endif - char convert[sizeof( union value) * 8 + 16]; - int place = 0; - int padlen = 0; /* amount to pad */ - int caps = 0; - - /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", - value, base, dosign, ljust, len, zpad );/ **/ - uvalue = value->value; - if( dosign ){ - if( value->value < 0 ) { - signvalue = '-'; - uvalue = -value->value; - } - } - if( base < 0 ){ - caps = 1; - base = -base; - } - do{ - convert[place++] = - (caps? "0123456789ABCDEF":"0123456789abcdef") - [uvalue % (unsigned)base ]; - uvalue = (uvalue / (unsigned)base ); - }while(uvalue); - convert[place] = 0; - padlen = len - place; - if( padlen < 0 ) padlen = 0; - if( ljust ) padlen = -padlen; - /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", - convert,place,signvalue,padlen); / **/ - if( zpad && padlen > 0 ){ - if( signvalue ){ - dopr_outch( buffer, left, signvalue ); - --padlen; - signvalue = 0; - } - while( padlen > 0 ){ - dopr_outch( buffer, left, zpad ); - --padlen; - } - } - while( padlen > 0 ) { - dopr_outch( buffer, left, ' ' ); - --padlen; - } - if( signvalue ) dopr_outch( buffer, left, signvalue ); - while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); - while( padlen < 0 ){ - dopr_outch( buffer, left, ' ' ); - ++padlen; - } -} - -#if defined(HAVE_QUAD_T) - - static void -fmtquad( char **buffer, int *left, - union value *value, int base, int dosign, int ljust, - int len, int zpad, int precision ) -{ - int signvalue = 0; - int place = 0; - int padlen = 0; /* amount to pad */ - int caps = 0; - int i, c; - union { - quad_t qvalue; - unsigned char qconvert[sizeof(quad_t)]; - } vvalue; - char convert[2*sizeof(quad_t)+1]; - - /* fprintf(stderr,"value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n", - value, base, dosign, ljust, len, zpad );/ **/ - vvalue.qvalue = value->qvalue; - - if( base < 0 ){ - caps = 1; - } - - for( i = 0; i < sizeof(quad_t); ++i ){ - c = vvalue.qconvert[i]; - convert[2*i] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[ (c >> 4) & 0xF]; - convert[2*i+1] = - (caps? "0123456789ABCDEF":"0123456789abcdef")[ c & 0xF]; - } - convert[2*i] = 0; - - place = strlen(convert); - padlen = len - place; - if( padlen < 0 ) padlen = 0; - if( ljust ) padlen = -padlen; - /* fprintf( stderr, "str '%s', place %d, sign %c, padlen %d\n", - convert,place,signvalue,padlen); / **/ - if( zpad && padlen > 0 ){ - if( signvalue ){ - dopr_outch( buffer, left, signvalue ); - --padlen; - signvalue = 0; - } - while( padlen > 0 ){ - dopr_outch( buffer, left, zpad ); - --padlen; - } - } - while( padlen > 0 ) { - dopr_outch( buffer, left, ' ' ); - --padlen; - } - if( signvalue ) dopr_outch( buffer, left, signvalue ); - while( place > 0 ) dopr_outch( buffer, left, convert[--place] ); - while( padlen < 0 ){ - dopr_outch( buffer, left, ' ' ); - ++padlen; - } -} - -#endif - - static void mystrcat(char *dest, char *src ) -{ - if( dest && src ){ - dest += strlen(dest); - strcpy(dest,src); - } -} - - static void -fmtdouble( char **buffer, int *left, - int fmt, double value, int ljust, int len, int zpad, int precision ) -{ - char convert[sizeof( union value) * 8 + 16]; - char formatstr[128]; - - /* fprintf(stderr,"len %d, precision %d\n", len, precision ); */ - if( len > (sizeof(convert) - 20) ){ - len = sizeof(convert) - 20; - } - if( precision >= 0 && precision > sizeof(convert) - 20 ){ - precision = sizeof(convert) - 20; - } - if( precision >= 0 && precision > len ) precision = len; - strcpy( formatstr, "%" ); - if( ljust ) mystrcat(formatstr, "-" ); - if( zpad ) mystrcat(formatstr, "0" ); - if( len ){ - sprintf( formatstr+strlen(formatstr), "%d", len ); - } - if( precision >= 0 ){ - sprintf( formatstr+strlen(formatstr), ".%d", precision ); - } - sprintf( formatstr+strlen(formatstr), "%c", fmt ); - /* this is easier than trying to do the portable dtostr */ - /* fprintf(stderr,"format string '%s'\n", formatstr); */ - sprintf( convert, formatstr, value ); - dostr( buffer, left, convert ); -} - - static void dostr( char **buffer, int *left, char *str ) -{ - if(str)while(*str) dopr_outch( buffer, left, *str++ ); -} - - static void dopr_outch( char **buffer, int *left, int c ) -{ - if( *left > 0 ){ - *(*buffer)++ = c; - } - *left -= 1; -} - - -/**************************************************************************** - * static char *plp_errormsg( int err ) - * returns a printable form of the - * errormessage corresponding to the valie of err. - * This is the poor man's version of sperror(), not available on all systems - * Patrick Powell Tue Apr 11 08:05:05 PDT 1995 - ****************************************************************************/ -/****************************************************************************/ - -#if !defined(HAVE_STRERROR) -# undef num_errors -# if defined(HAVE_SYS_ERRLIST) -# if !defined(HAVE_DECL_SYS_ERRLIST) - extern const char *const sys_errlist[]; -# endif -# if defined(HAVE_SYS_NERR) -# if !defined(HAVE_DECL_SYS_NERR) - extern int sys_nerr; -# endif -# define num_errors (sys_nerr) -# endif -# endif -# if !defined(num_errors) -# define num_errors (-1) /* always use "errno=%d" */ -# endif -#endif - - static char * plp_Errormsg ( int err, char *buffer /* int maxlen = 32 */) -{ - char *cp; - -#if defined(HAVE_STRERROR) - cp = (void *)strerror(err); -#else -# if defined(HAVE_SYS_ERRLIST) - if (err >= 0 && err < num_errors) { - cp = (void *)sys_errlist[err]; - } else -# endif - { - (void) sprintf (buffer, "errno=%d", err); - cp = buffer; - } -#endif - return (cp); -} - -#if defined(TEST) -#include -int main( void ) -{ - char buffer[128]; - char *t; - char *test1 = "01234"; - int n; - errno = 1; - buffer[0] = 0; - n = plp_snprintf( buffer, 0, (t="test")); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t="errno '%s'")); printf( "[%d] %s = '%s'\n", n, t, buffer, strerror(errno) ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%-12s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%-12.2s"), test1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%g"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.1g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.3g"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%0*d"), 6, 1 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); -#if defined(HAVE_LONG_LONG) - n = plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%llx"), (long long)1, (long long)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), 1, 2, 3, 4 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%qx"), (quad_t)1, (quad_t)2 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); -#endif - n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), (char *)(0x01234567), (char *)0x89ABCDEF, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "0%x, 0%x"), t, 0, 0, 0, 0); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.2345 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%12.2f"), 1.25 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%0.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%1.0f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%1.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - n = plp_snprintf( buffer, sizeof(buffer), (t = "%5.5f"), 1.0 ); printf( "[%d] %s = '%s'\n", n, t, buffer ); - return(0); -} -#endif - -#endif /* !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) */ - -#ifndef HAVE_VSNPRINTF -int vsnprintf(char *str, size_t count, const char *fmt, va_list args) -{ - int n; - - n = plp_vsnprintf(str, count, fmt, args); - - return(n); -} -#endif /* ! HAVE_VSNPRINTF */ - -#ifndef HAVE_SNPRINTF -#ifdef HAVE_STDARGS -int snprintf (char *str,size_t count,const char *fmt,...) -#else -int snprintf (va_alist) va_dcl -#endif -{ -#ifndef HAVE_STDARGS - char *str; - size_t count; - char *fmt; -#endif - int n = 0; - VA_LOCAL_DECL - - VA_START (fmt); - VA_SHIFT (str, char *); - VA_SHIFT (count, size_t ); - VA_SHIFT (fmt, char *); - n = plp_vsnprintf ( str, count, fmt, ap); - VA_END; - return( n ); -} -#endif /* ! HAVE_VNSPRINTF */ diff --git a/libatalk/compat/strcasecmp.c b/libatalk/compat/strcasecmp.c deleted file mode 100644 index bc8cb57b..00000000 --- a/libatalk/compat/strcasecmp.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * $Id: strcasecmp.c,v 1.4 2003-02-17 01:51:08 srittau Exp $ - * - * Copyright (c) 1987 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms are permitted - * provided that: (1) source distributions retain this entire copyright - * notice and comment, and (2) distributions including binaries display - * the following acknowledgement: ``This product includes software - * developed by the University of California, Berkeley and its contributors'' - * in the documentation or other materials provided with the distribution - * and in all advertising materials mentioning features or use of this - * software. Neither the name of the University 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -# if defined( ibm032 ) - -#include -#include - -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)strcasecmp.c 5.9 (Berkeley) 6/1/90"; -#endif /* LIBC_SCCS and not lint */ - -/* - * This array is designed for mapping upper and lower case letter - * together for a case independent comparison. The mappings are - * based upon ascii character sequences. - */ -static u_char charmap[] = { - '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007', - '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017', - '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027', - '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037', - '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047', - '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057', - '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067', - '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077', - '\100', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\133', '\134', '\135', '\136', '\137', - '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147', - '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157', - '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167', - '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177', - '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207', - '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217', - '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227', - '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237', - '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247', - '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257', - '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267', - '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277', - '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307', - '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317', - '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327', - '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337', - '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347', - '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357', - '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367', - '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377', -}; - -int -strcasecmp(s1, s2) - char *s1, *s2; -{ - register u_char *cm = charmap, - *us1 = (u_char *)s1, - *us2 = (u_char *)s2; - - while (cm[*us1] == cm[*us2++]) - if (*us1++ == '\0') - return (0); - return (cm[*us1] - cm[*--us2]); -} - -int -strncasecmp(s1, s2, n) - char *s1, *s2; - register size_t n; -{ - if (n != 0) { - register u_char *cm = charmap, - *us1 = (u_char *)s1, - *us2 = (u_char *)s2; - - do { - if (cm[*us1] != cm[*us2++]) - return (cm[*us1] - cm[*--us2]); - if (*us1++ == '\0') - break; - } while (--n != 0); - } - return (0); -} - -# endif /* ibm032 */ diff --git a/libatalk/compat/strdup.c b/libatalk/compat/strdup.c deleted file mode 100644 index 9537a857..00000000 --- a/libatalk/compat/strdup.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * $Id: strdup.c,v 1.4 2003-02-17 01:51:08 srittau Exp $ - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#include -#include -#include - -#ifdef ultrix -char *strdup(const char *string) -{ - char *new; - - if (new = (char *) malloc(strlen(string) + 1)) - strcpy(new, string); - - return new; -} -#endif /* ultrix */ diff --git a/libatalk/util/strlcpy.c b/libatalk/compat/strlcpy.c similarity index 100% rename from libatalk/util/strlcpy.c rename to libatalk/compat/strlcpy.c diff --git a/libatalk/compat/strstr.c b/libatalk/compat/strstr.c deleted file mode 100644 index ae555b49..00000000 --- a/libatalk/compat/strstr.c +++ /dev/null @@ -1,77 +0,0 @@ -/* - * $Id: strstr.c,v 1.4 2003-02-17 01:51:08 srittau Exp $ - * - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Chris Torek. - * - * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /* HAVE_CONFIG_H */ - -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)strstr.c 5.2 (Berkeley) 1/26/91"; -#endif /* LIBC_SCCS and not lint */ - -# if defined(ibm032) || (defined(sun) && defined(i386)) -#ifdef sun -#define const -#endif /* sun */ - -#include -#include - -/* - * Find the first occurrence of find in s. - */ -char * -strstr(s, find) - register const char *s, *find; -{ - register char c, sc; - register size_t len; - - if ((c = *find++) != 0) { - len = strlen(find); - do { - do { - if ((sc = *s++) == 0) - return (0); - } while (sc != c); - } while (strncmp(s, find, len) != 0); - s--; - } - return ((char *)s); -} -# endif /* ibm03 sun i386 */ diff --git a/libatalk/talloc/Makefile.am b/libatalk/talloc/Makefile.am new file mode 100644 index 00000000..0b011ed5 --- /dev/null +++ b/libatalk/talloc/Makefile.am @@ -0,0 +1,7 @@ +# Makefile.am for libatalk/talloc/ + +noinst_LTLIBRARIES = libtalloc.la + +AM_CFLAGS = + +libtalloc_la_SOURCES = talloc.c diff --git a/libatalk/talloc/talloc.c b/libatalk/talloc/talloc.c new file mode 100644 index 00000000..f56ec431 --- /dev/null +++ b/libatalk/talloc/talloc.c @@ -0,0 +1,1990 @@ +/* + Samba Unix SMB/CIFS implementation. + + Samba trivial allocation library - new interface + + NOTE: Please read talloc_guide.txt for full documentation + + Copyright (C) Andrew Tridgell 2004 + Copyright (C) Stefan Metzmacher 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 . +*/ + +/* + inspired by http://swapped.cc/halloc/ +*/ + +#include +#include + +#include +#include +#include + +#ifdef TALLOC_BUILD_VERSION_MAJOR +#if (TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR) +#error "TALLOC_VERSION_MAJOR != TALLOC_BUILD_VERSION_MAJOR" +#endif +#endif + +#ifdef TALLOC_BUILD_VERSION_MINOR +#if (TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR) +#error "TALLOC_VERSION_MINOR != TALLOC_BUILD_VERSION_MINOR" +#endif +#endif + +/* use this to force every realloc to change the pointer, to stress test + code that might not cope */ +#define ALWAYS_REALLOC 0 + + +#define MAX_TALLOC_SIZE 0x10000000 +#define TALLOC_MAGIC_BASE 0xe814ec70 +#define TALLOC_MAGIC ( \ + TALLOC_MAGIC_BASE + \ + (TALLOC_VERSION_MAJOR << 12) + \ + (TALLOC_VERSION_MINOR << 4) \ +) + +#define TALLOC_FLAG_FREE 0x01 +#define TALLOC_FLAG_LOOP 0x02 +#define TALLOC_FLAG_POOL 0x04 /* This is a talloc pool */ +#define TALLOC_FLAG_POOLMEM 0x08 /* This is allocated in a pool */ +#define TALLOC_MAGIC_REFERENCE ((const char *)1) + +/* by default we abort when given a bad pointer (such as when talloc_free() is called + on a pointer that came from malloc() */ +#ifndef TALLOC_ABORT +#define TALLOC_ABORT(reason) abort() +#endif + +#ifndef discard_const_p +#if defined(__intptr_t_defined) || defined(HAVE_INTPTR_T) +# define discard_const_p(type, ptr) ((type *)((intptr_t)(ptr))) +#else +# define discard_const_p(type, ptr) ((type *)(ptr)) +#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 + +/* this null_context is only used if talloc_enable_leak_report() or + talloc_enable_leak_report_full() is called, otherwise it remains + NULL +*/ +static void *null_context; +static void *autofree_context; + +struct talloc_reference_handle { + struct talloc_reference_handle *next, *prev; + void *ptr; + const char *location; +}; + +typedef int (*talloc_destructor_t)(void *); + +struct talloc_chunk { + struct talloc_chunk *next, *prev; + struct talloc_chunk *parent, *child; + struct talloc_reference_handle *refs; + talloc_destructor_t destructor; + const char *name; + size_t size; + unsigned flags; + + /* + * "pool" has dual use: + * + * For the talloc pool itself (i.e. TALLOC_FLAG_POOL is set), "pool" + * marks the end of the currently allocated area. + * + * For members of the pool (i.e. TALLOC_FLAG_POOLMEM is set), "pool" + * is a pointer to the struct talloc_chunk of the pool that it was + * allocated from. This way children can quickly find the pool to chew + * from. + */ + void *pool; +}; + +/* 16 byte alignment seems to keep everyone happy */ +#define TC_HDR_SIZE ((sizeof(struct talloc_chunk)+15)&~15) +#define TC_PTR_FROM_CHUNK(tc) ((void *)(TC_HDR_SIZE + (char*)tc)) + +int talloc_version_major(void) +{ + return TALLOC_VERSION_MAJOR; +} + +int talloc_version_minor(void) +{ + return TALLOC_VERSION_MINOR; +} + +static void (*talloc_log_fn)(const char *message); + +void talloc_set_log_fn(void (*log_fn)(const char *message)) +{ + talloc_log_fn = log_fn; +} + +static void talloc_log(const char *fmt, ...) PRINTF_ATTRIBUTE(1,2); +static void talloc_log(const char *fmt, ...) +{ + va_list ap; + char *message; + + if (!talloc_log_fn) { + return; + } + + va_start(ap, fmt); + message = talloc_vasprintf(NULL, fmt, ap); + va_end(ap); + + talloc_log_fn(message); + talloc_free(message); +} + +static void talloc_log_stderr(const char *message) +{ + fprintf(stderr, "%s", message); +} + +void talloc_set_log_stderr(void) +{ + talloc_set_log_fn(talloc_log_stderr); +} + +static void (*talloc_abort_fn)(const char *reason); + +void talloc_set_abort_fn(void (*abort_fn)(const char *reason)) +{ + talloc_abort_fn = abort_fn; +} + +static void talloc_abort(const char *reason) +{ + talloc_log("%s\n", reason); + + if (!talloc_abort_fn) { + TALLOC_ABORT(reason); + } + + talloc_abort_fn(reason); +} + +static void talloc_abort_magic(unsigned magic) +{ + unsigned striped = magic - TALLOC_MAGIC_BASE; + unsigned major = (striped & 0xFFFFF000) >> 12; + unsigned minor = (striped & 0x00000FF0) >> 4; + talloc_log("Bad talloc magic[0x%08X/%u/%u] expected[0x%08X/%u/%u]\n", + magic, major, minor, + TALLOC_MAGIC, TALLOC_VERSION_MAJOR, TALLOC_VERSION_MINOR); + talloc_abort("Bad talloc magic value - wrong talloc version used/mixed"); +} + +static void talloc_abort_double_free(void) +{ + talloc_abort("Bad talloc magic value - double free"); +} + +static void talloc_abort_unknown_value(void) +{ + talloc_abort("Bad talloc magic value - unknown value"); +} + +/* panic if we get a bad magic value */ +static inline struct talloc_chunk *talloc_chunk_from_ptr(const void *ptr) +{ + const char *pp = (const char *)ptr; + struct talloc_chunk *tc = discard_const_p(struct talloc_chunk, pp - TC_HDR_SIZE); + if (unlikely((tc->flags & (TALLOC_FLAG_FREE | ~0xF)) != TALLOC_MAGIC)) { + if ((tc->flags & (~0xFFF)) == TALLOC_MAGIC_BASE) { + talloc_abort_magic(tc->flags & (~0xF)); + return NULL; + } + + if (tc->flags & TALLOC_FLAG_FREE) { + talloc_log("talloc: double free error - first free may be at %s\n", tc->name); + talloc_abort_double_free(); + return NULL; + } else { + talloc_abort_unknown_value(); + return NULL; + } + } + return tc; +} + +/* hook into the front of the list */ +#define _TLIST_ADD(list, p) \ +do { \ + if (!(list)) { \ + (list) = (p); \ + (p)->next = (p)->prev = NULL; \ + } else { \ + (list)->prev = (p); \ + (p)->next = (list); \ + (p)->prev = NULL; \ + (list) = (p); \ + }\ +} while (0) + +/* remove an element from a list - element doesn't have to be in list. */ +#define _TLIST_REMOVE(list, p) \ +do { \ + if ((p) == (list)) { \ + (list) = (p)->next; \ + if (list) (list)->prev = NULL; \ + } else { \ + if ((p)->prev) (p)->prev->next = (p)->next; \ + if ((p)->next) (p)->next->prev = (p)->prev; \ + } \ + if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \ +} while (0) + + +/* + return the parent chunk of a pointer +*/ +static inline struct talloc_chunk *talloc_parent_chunk(const void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + while (tc->prev) tc=tc->prev; + + return tc->parent; +} + +void *talloc_parent(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? TC_PTR_FROM_CHUNK(tc) : NULL; +} + +/* + find parents name +*/ +const char *talloc_parent_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_parent_chunk(ptr); + return tc? tc->name : NULL; +} + +/* + A pool carries an in-pool object count count in the first 16 bytes. + bytes. This is done to support talloc_steal() to a parent outside of the + pool. The count includes the pool itself, so a talloc_free() on a pool will + only destroy the pool if the count has dropped to zero. A talloc_free() of a + pool member will reduce the count, and eventually also call free(3) on the + pool memory. + + The object count is not put into "struct talloc_chunk" because it is only + relevant for talloc pools and the alignment to 16 bytes would increase the + memory footprint of each talloc chunk by those 16 bytes. +*/ + +#define TALLOC_POOL_HDR_SIZE 16 + +static unsigned int *talloc_pool_objectcount(struct talloc_chunk *tc) +{ + return (unsigned int *)((char *)tc + sizeof(struct talloc_chunk)); +} + +/* + Allocate from a pool +*/ + +static struct talloc_chunk *talloc_alloc_pool(struct talloc_chunk *parent, + size_t size) +{ + struct talloc_chunk *pool_ctx = NULL; + size_t space_left; + struct talloc_chunk *result; + size_t chunk_size; + + if (parent == NULL) { + return NULL; + } + + if (parent->flags & TALLOC_FLAG_POOL) { + pool_ctx = parent; + } + else if (parent->flags & TALLOC_FLAG_POOLMEM) { + pool_ctx = (struct talloc_chunk *)parent->pool; + } + + if (pool_ctx == NULL) { + return NULL; + } + + space_left = ((char *)pool_ctx + TC_HDR_SIZE + pool_ctx->size) + - ((char *)pool_ctx->pool); + + /* + * Align size to 16 bytes + */ + chunk_size = ((size + 15) & ~15); + + if (space_left < chunk_size) { + return NULL; + } + + result = (struct talloc_chunk *)pool_ctx->pool; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_UNDEFINED) + VALGRIND_MAKE_MEM_UNDEFINED(result, size); +#endif + + pool_ctx->pool = (void *)((char *)result + chunk_size); + + result->flags = TALLOC_MAGIC | TALLOC_FLAG_POOLMEM; + result->pool = pool_ctx; + + *talloc_pool_objectcount(pool_ctx) += 1; + + return result; +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +static inline void *__talloc(const void *context, size_t size) +{ + struct talloc_chunk *tc = NULL; + + if (unlikely(context == NULL)) { + context = null_context; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + if (context != NULL) { + tc = talloc_alloc_pool(talloc_chunk_from_ptr(context), + TC_HDR_SIZE+size); + } + + if (tc == NULL) { + tc = (struct talloc_chunk *)malloc(TC_HDR_SIZE+size); + if (unlikely(tc == NULL)) return NULL; + tc->flags = TALLOC_MAGIC; + tc->pool = NULL; + } + + tc->size = size; + tc->destructor = NULL; + tc->child = NULL; + tc->name = NULL; + tc->refs = NULL; + + if (likely(context)) { + struct talloc_chunk *parent = talloc_chunk_from_ptr(context); + + if (parent->child) { + parent->child->parent = NULL; + tc->next = parent->child; + tc->next->prev = tc; + } else { + tc->next = NULL; + } + tc->parent = parent; + tc->prev = NULL; + parent->child = tc; + } else { + tc->next = tc->prev = tc->parent = NULL; + } + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + * Create a talloc pool + */ + +void *talloc_pool(const void *context, size_t size) +{ + void *result = __talloc(context, size + TALLOC_POOL_HDR_SIZE); + struct talloc_chunk *tc; + + if (unlikely(result == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(result); + + tc->flags |= TALLOC_FLAG_POOL; + tc->pool = (char *)result + TALLOC_POOL_HDR_SIZE; + + *talloc_pool_objectcount(tc) = 1; + +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS(tc->pool, size); +#endif + + return result; +} + +/* + setup a destructor to be called on free of a pointer + the destructor should return 0 on success, or -1 on failure. + if the destructor fails then the free is failed, and the memory can + be continued to be used +*/ +void _talloc_set_destructor(const void *ptr, int (*destructor)(void *)) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->destructor = destructor; +} + +/* + increase the reference count on a piece of memory. +*/ +int talloc_increase_ref_count(const void *ptr) +{ + if (unlikely(!talloc_reference(null_context, ptr))) { + return -1; + } + return 0; +} + +/* + helper for talloc_reference() + + this is referenced by a function pointer and should not be inline +*/ +static int talloc_reference_destructor(struct talloc_reference_handle *handle) +{ + struct talloc_chunk *ptr_tc = talloc_chunk_from_ptr(handle->ptr); + _TLIST_REMOVE(ptr_tc->refs, handle); + return 0; +} + +/* + more efficient way to add a name to a pointer - the name must point to a + true string constant +*/ +static inline void _talloc_set_name_const(const void *ptr, const char *name) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = name; +} + +/* + internal talloc_named_const() +*/ +static inline void *_talloc_named_const(const void *context, size_t size, const char *name) +{ + void *ptr; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) { + return NULL; + } + + _talloc_set_name_const(ptr, name); + + return ptr; +} + +/* + make a secondary reference to a pointer, hanging off the given context. + the pointer remains valid until both the original caller and this given + context are freed. + + the major use for this is when two different structures need to reference the + same underlying data, and you want to be able to free the two instances separately, + and in either order +*/ +void *_talloc_reference_loc(const void *context, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *handle; + if (unlikely(ptr == NULL)) return NULL; + + tc = talloc_chunk_from_ptr(ptr); + handle = (struct talloc_reference_handle *)_talloc_named_const(context, + sizeof(struct talloc_reference_handle), + TALLOC_MAGIC_REFERENCE); + if (unlikely(handle == NULL)) return NULL; + + /* note that we hang the destructor off the handle, not the + main context as that allows the caller to still setup their + own destructor on the context if they want to */ + talloc_set_destructor(handle, talloc_reference_destructor); + handle->ptr = discard_const_p(void, ptr); + handle->location = location; + _TLIST_ADD(tc->refs, handle); + return handle->ptr; +} + +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr); + +/* + internal talloc_free call +*/ +static inline int _talloc_free_internal(void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs)) { + int is_child; + /* check this is a reference from a child or grantchild + * back to it's parent or grantparent + * + * in that case we need to remove the reference and + * call another instance of talloc_free() on the current + * pointer. + */ + is_child = talloc_is_parent(tc->refs, ptr); + _talloc_free_internal(tc->refs, location); + if (is_child) { + return _talloc_free_internal(ptr, location); + } + return -1; + } + + if (unlikely(tc->flags & TALLOC_FLAG_LOOP)) { + /* we have a free loop - stop looping */ + return 0; + } + + if (unlikely(tc->destructor)) { + talloc_destructor_t d = tc->destructor; + if (d == (talloc_destructor_t)-1) { + return -1; + } + tc->destructor = (talloc_destructor_t)-1; + if (d(ptr) == -1) { + tc->destructor = d; + return -1; + } + tc->destructor = NULL; + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(_talloc_free_internal(child, location) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + _talloc_steal_internal(new_parent, child); + } + } + + tc->flags |= TALLOC_FLAG_FREE; + + /* we mark the freed memory with where we called the free + * from. This means on a double free error we can report where + * the first free came from + */ + tc->name = location; + + if (tc->flags & (TALLOC_FLAG_POOL|TALLOC_FLAG_POOLMEM)) { + struct talloc_chunk *pool; + unsigned int *pool_object_count; + + pool = (tc->flags & TALLOC_FLAG_POOL) + ? tc : (struct talloc_chunk *)tc->pool; + + pool_object_count = talloc_pool_objectcount(pool); + + if (*pool_object_count == 0) { + talloc_abort("Pool object count zero!"); + return 0; + } + + *pool_object_count -= 1; + + if (*pool_object_count == 0) { + free(pool); + } + } + else { + free(tc); + } + return 0; +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +static void *_talloc_steal_internal(const void *new_ctx, const void *ptr) +{ + struct talloc_chunk *tc, *new_tc; + + if (unlikely(!ptr)) { + return NULL; + } + + if (unlikely(new_ctx == NULL)) { + new_ctx = null_context; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(new_ctx == NULL)) { + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = tc->next = tc->prev = NULL; + return discard_const_p(void, ptr); + } + + new_tc = talloc_chunk_from_ptr(new_ctx); + + if (unlikely(tc == new_tc || tc->parent == new_tc)) { + return discard_const_p(void, ptr); + } + + if (tc->parent) { + _TLIST_REMOVE(tc->parent->child, tc); + if (tc->parent->child) { + tc->parent->child->parent = tc->parent; + } + } else { + if (tc->prev) tc->prev->next = tc->next; + if (tc->next) tc->next->prev = tc->prev; + } + + tc->parent = new_tc; + if (new_tc->child) new_tc->child->parent = NULL; + _TLIST_ADD(new_tc->child, tc); + + return discard_const_p(void, ptr); +} + +/* + move a lump of memory from one talloc context to another return the + ptr on success, or NULL if it could not be transferred. + passing NULL as ptr will always return NULL with no side effects. +*/ +void *_talloc_steal_loc(const void *new_ctx, const void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL) && talloc_parent(ptr) != new_ctx) { + struct talloc_reference_handle *h; + + talloc_log("WARNING: talloc_steal with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + } + + return _talloc_steal_internal(new_ctx, ptr); +} + +/* + this is like a talloc_steal(), but you must supply the old + parent. This resolves the ambiguity in a talloc_steal() which is + called on a context that has more than one parent (via references) + + The old parent can be either a reference or a parent +*/ +void *talloc_reparent(const void *old_parent, const void *new_parent, const void *ptr) +{ + struct talloc_chunk *tc; + struct talloc_reference_handle *h; + + if (unlikely(ptr == NULL)) { + return NULL; + } + + if (old_parent == talloc_parent(ptr)) { + return _talloc_steal_internal(new_parent, ptr); + } + + tc = talloc_chunk_from_ptr(ptr); + for (h=tc->refs;h;h=h->next) { + if (talloc_parent(h) == old_parent) { + if (_talloc_steal_internal(new_parent, h) != h) { + return NULL; + } + return discard_const_p(void, ptr); + } + } + + /* it wasn't a parent */ + return NULL; +} + +/* + remove a secondary reference to a pointer. This undo's what + talloc_reference() has done. The context and pointer arguments + must match those given to a talloc_reference() +*/ +static inline int talloc_unreference(const void *context, const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + + if (unlikely(context == NULL)) { + context = null_context; + } + + for (h=tc->refs;h;h=h->next) { + struct talloc_chunk *p = talloc_parent_chunk(h); + if (p == NULL) { + if (context == NULL) break; + } else if (TC_PTR_FROM_CHUNK(p) == context) { + break; + } + } + if (h == NULL) { + return -1; + } + + return _talloc_free_internal(h, __location__); +} + +/* + remove a specific parent context from a pointer. This is a more + controlled varient of talloc_free() +*/ +int talloc_unlink(const void *context, void *ptr) +{ + struct talloc_chunk *tc_p, *new_p; + void *new_parent; + + if (ptr == NULL) { + return -1; + } + + if (context == NULL) { + context = null_context; + } + + if (talloc_unreference(context, ptr) == 0) { + return 0; + } + + if (context == NULL) { + if (talloc_parent_chunk(ptr) != NULL) { + return -1; + } + } else { + if (talloc_chunk_from_ptr(context) != talloc_parent_chunk(ptr)) { + return -1; + } + } + + tc_p = talloc_chunk_from_ptr(ptr); + + if (tc_p->refs == NULL) { + return _talloc_free_internal(ptr, __location__); + } + + new_p = talloc_parent_chunk(tc_p->refs); + if (new_p) { + new_parent = TC_PTR_FROM_CHUNK(new_p); + } else { + new_parent = NULL; + } + + if (talloc_unreference(new_parent, ptr) != 0) { + return -1; + } + + _talloc_steal_internal(new_parent, ptr); + + return 0; +} + +/* + add a name to an existing pointer - va_list version +*/ +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(2,0); + +static inline const char *talloc_set_name_v(const void *ptr, const char *fmt, va_list ap) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + tc->name = talloc_vasprintf(ptr, fmt, ap); + if (likely(tc->name)) { + _talloc_set_name_const(tc->name, ".name"); + } + return tc->name; +} + +/* + add a name to an existing pointer +*/ +const char *talloc_set_name(const void *ptr, const char *fmt, ...) +{ + const char *name; + va_list ap; + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + return name; +} + + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named(const void *context, size_t size, const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + ptr = __talloc(context, size); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +/* + return the name of a talloc ptr, or "UNNAMED" +*/ +const char *talloc_get_name(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + if (unlikely(tc->name == TALLOC_MAGIC_REFERENCE)) { + return ".reference"; + } + if (likely(tc->name)) { + return tc->name; + } + return "UNNAMED"; +} + + +/* + check if a pointer has the given name. If it does, return the pointer, + otherwise return NULL +*/ +void *talloc_check_name(const void *ptr, const char *name) +{ + const char *pname; + if (unlikely(ptr == NULL)) return NULL; + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + return NULL; +} + +static void talloc_abort_type_missmatch(const char *location, + const char *name, + const char *expected) +{ + const char *reason; + + reason = talloc_asprintf(NULL, + "%s: Type mismatch: name[%s] expected[%s]", + location, + name?name:"NULL", + expected); + if (!reason) { + reason = "Type mismatch"; + } + + talloc_abort(reason); +} + +void *_talloc_get_type_abort(const void *ptr, const char *name, const char *location) +{ + const char *pname; + + if (unlikely(ptr == NULL)) { + talloc_abort_type_missmatch(location, NULL, name); + return NULL; + } + + pname = talloc_get_name(ptr); + if (likely(pname == name || strcmp(pname, name) == 0)) { + return discard_const_p(void, ptr); + } + + talloc_abort_type_missmatch(location, pname, name); + return NULL; +} + +/* + this is for compatibility with older versions of talloc +*/ +void *talloc_init(const char *fmt, ...) +{ + va_list ap; + void *ptr; + const char *name; + + /* + * samba3 expects talloc_report_depth_cb(NULL, ...) + * reports all talloc'ed memory, so we need to enable + * null_tracking + */ + talloc_enable_null_tracking(); + + ptr = __talloc(NULL, 0); + if (unlikely(ptr == NULL)) return NULL; + + va_start(ap, fmt); + name = talloc_set_name_v(ptr, fmt, ap); + va_end(ap); + + if (unlikely(name == NULL)) { + _talloc_free_internal(ptr, __location__); + return NULL; + } + + return ptr; +} + +/* + this is a replacement for the Samba3 talloc_destroy_pool functionality. It + should probably not be used in new code. It's in here to keep the talloc + code consistent across Samba 3 and 4. +*/ +void talloc_free_children(void *ptr) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return; + } + + tc = talloc_chunk_from_ptr(ptr); + + while (tc->child) { + /* we need to work out who will own an abandoned child + if it cannot be freed. In priority order, the first + choice is owner of any remaining reference to this + pointer, the second choice is our parent, and the + final choice is the null context. */ + void *child = TC_PTR_FROM_CHUNK(tc->child); + const void *new_parent = null_context; + if (unlikely(tc->child->refs)) { + struct talloc_chunk *p = talloc_parent_chunk(tc->child->refs); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + if (unlikely(talloc_free(child) == -1)) { + if (new_parent == null_context) { + struct talloc_chunk *p = talloc_parent_chunk(ptr); + if (p) new_parent = TC_PTR_FROM_CHUNK(p); + } + _talloc_steal_internal(new_parent, child); + } + } + + if ((tc->flags & TALLOC_FLAG_POOL) + && (*talloc_pool_objectcount(tc) == 1)) { + tc->pool = ((char *)tc + TC_HDR_SIZE + TALLOC_POOL_HDR_SIZE); +#if defined(DEVELOPER) && defined(VALGRIND_MAKE_MEM_NOACCESS) + VALGRIND_MAKE_MEM_NOACCESS( + tc->pool, tc->size - TALLOC_POOL_HDR_SIZE); +#endif + } +} + +/* + Allocate a bit of memory as a child of an existing pointer +*/ +void *_talloc(const void *context, size_t size) +{ + return __talloc(context, size); +} + +/* + externally callable talloc_set_name_const() +*/ +void talloc_set_name_const(const void *ptr, const char *name) +{ + _talloc_set_name_const(ptr, name); +} + +/* + create a named talloc pointer. Any talloc pointer can be named, and + talloc_named() operates just like talloc() except that it allows you + to name the pointer. +*/ +void *talloc_named_const(const void *context, size_t size, const char *name) +{ + return _talloc_named_const(context, size, name); +} + +/* + free a talloc pointer. This also frees all child pointers of this + pointer recursively + + return 0 if the memory is actually freed, otherwise -1. The memory + will not be freed if the ref_count is > 1 or the destructor (if + any) returns non-zero +*/ +int _talloc_free(void *ptr, const char *location) +{ + struct talloc_chunk *tc; + + if (unlikely(ptr == NULL)) { + return -1; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (unlikely(tc->refs != NULL)) { + struct talloc_reference_handle *h; + + talloc_log("ERROR: talloc_free with references at %s\n", + location); + + for (h=tc->refs; h; h=h->next) { + talloc_log("\treference at %s\n", + h->location); + } + return -1; + } + + return _talloc_free_internal(ptr, location); +} + + + +/* + A talloc version of realloc. The context argument is only used if + ptr is NULL +*/ +void *_talloc_realloc(const void *context, void *ptr, size_t size, const char *name) +{ + struct talloc_chunk *tc; + void *new_ptr; + bool malloced = false; + + /* size zero is equivalent to free() */ + if (unlikely(size == 0)) { + talloc_unlink(context, ptr); + return NULL; + } + + if (unlikely(size >= MAX_TALLOC_SIZE)) { + return NULL; + } + + /* realloc(NULL) is equivalent to malloc() */ + if (ptr == NULL) { + return _talloc_named_const(context, size, name); + } + + tc = talloc_chunk_from_ptr(ptr); + + /* don't allow realloc on referenced pointers */ + if (unlikely(tc->refs)) { + return NULL; + } + + /* don't let anybody try to realloc a talloc_pool */ + if (unlikely(tc->flags & TALLOC_FLAG_POOL)) { + return NULL; + } + + /* don't shrink if we have less than 1k to gain */ + if ((size < tc->size) && ((tc->size - size) < 1024)) { + tc->size = size; + return ptr; + } + + /* by resetting magic we catch users of the old memory */ + tc->flags |= TALLOC_FLAG_FREE; + +#if ALWAYS_REALLOC + new_ptr = malloc(size + TC_HDR_SIZE); + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size, size) + TC_HDR_SIZE); + free(tc); + } +#else + if (tc->flags & TALLOC_FLAG_POOLMEM) { + + new_ptr = talloc_alloc_pool(tc, size + TC_HDR_SIZE); + *talloc_pool_objectcount((struct talloc_chunk *) + (tc->pool)) -= 1; + + if (new_ptr == NULL) { + new_ptr = malloc(TC_HDR_SIZE+size); + malloced = true; + } + + if (new_ptr) { + memcpy(new_ptr, tc, MIN(tc->size,size) + TC_HDR_SIZE); + } + } + else { + new_ptr = realloc(tc, size + TC_HDR_SIZE); + } +#endif + if (unlikely(!new_ptr)) { + tc->flags &= ~TALLOC_FLAG_FREE; + return NULL; + } + + tc = (struct talloc_chunk *)new_ptr; + tc->flags &= ~TALLOC_FLAG_FREE; + if (malloced) { + tc->flags &= ~TALLOC_FLAG_POOLMEM; + } + if (tc->parent) { + tc->parent->child = tc; + } + if (tc->child) { + tc->child->parent = tc; + } + + if (tc->prev) { + tc->prev->next = tc; + } + if (tc->next) { + tc->next->prev = tc; + } + + tc->size = size; + _talloc_set_name_const(TC_PTR_FROM_CHUNK(tc), name); + + return TC_PTR_FROM_CHUNK(tc); +} + +/* + a wrapper around talloc_steal() for situations where you are moving a pointer + between two structures, and want the old pointer to be set to NULL +*/ +void *_talloc_move(const void *new_ctx, const void *_pptr) +{ + const void **pptr = discard_const_p(const void *,_pptr); + void *ret = talloc_steal(new_ctx, discard_const_p(void, *pptr)); + (*pptr) = NULL; + return ret; +} + +/* + return the total size of a talloc pool (subtree) +*/ +size_t talloc_total_size(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + if (likely(tc->name != TALLOC_MAGIC_REFERENCE)) { + total = tc->size; + } + for (c=tc->child;c;c=c->next) { + total += talloc_total_size(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the total number of blocks in a talloc pool (subtree) +*/ +size_t talloc_total_blocks(const void *ptr) +{ + size_t total = 0; + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return 0; + } + + tc->flags |= TALLOC_FLAG_LOOP; + + total++; + for (c=tc->child;c;c=c->next) { + total += talloc_total_blocks(TC_PTR_FROM_CHUNK(c)); + } + + tc->flags &= ~TALLOC_FLAG_LOOP; + + return total; +} + +/* + return the number of external references to a pointer +*/ +size_t talloc_reference_count(const void *ptr) +{ + struct talloc_chunk *tc = talloc_chunk_from_ptr(ptr); + struct talloc_reference_handle *h; + size_t ret = 0; + + for (h=tc->refs;h;h=h->next) { + ret++; + } + return ret; +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_cb(const void *ptr, int depth, int max_depth, + void (*callback)(const void *ptr, + int depth, int max_depth, + int is_ref, + void *private_data), + void *private_data) +{ + struct talloc_chunk *c, *tc; + + if (ptr == NULL) { + ptr = null_context; + } + if (ptr == NULL) return; + + tc = talloc_chunk_from_ptr(ptr); + + if (tc->flags & TALLOC_FLAG_LOOP) { + return; + } + + callback(ptr, depth, max_depth, 0, private_data); + + if (max_depth >= 0 && depth >= max_depth) { + return; + } + + tc->flags |= TALLOC_FLAG_LOOP; + for (c=tc->child;c;c=c->next) { + if (c->name == TALLOC_MAGIC_REFERENCE) { + struct talloc_reference_handle *h = (struct talloc_reference_handle *)TC_PTR_FROM_CHUNK(c); + callback(h->ptr, depth + 1, max_depth, 1, private_data); + } else { + talloc_report_depth_cb(TC_PTR_FROM_CHUNK(c), depth + 1, max_depth, callback, private_data); + } + } + tc->flags &= ~TALLOC_FLAG_LOOP; +} + +static void talloc_report_depth_FILE_helper(const void *ptr, int depth, int max_depth, int is_ref, void *_f) +{ + const char *name = talloc_get_name(ptr); + FILE *f = (FILE *)_f; + + if (is_ref) { + fprintf(f, "%*sreference to: %s\n", depth*4, "", name); + return; + } + + if (depth == 0) { + fprintf(f,"%stalloc report on '%s' (total %6lu bytes in %3lu blocks)\n", + (max_depth < 0 ? "full " :""), name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr)); + return; + } + + fprintf(f, "%*s%-30s contains %6lu bytes in %3lu blocks (ref %d) %p\n", + depth*4, "", + name, + (unsigned long)talloc_total_size(ptr), + (unsigned long)talloc_total_blocks(ptr), + (int)talloc_reference_count(ptr), ptr); + +#if 0 + fprintf(f, "content: "); + if (talloc_total_size(ptr)) { + int tot = talloc_total_size(ptr); + int i; + + for (i = 0; i < tot; i++) { + if ((((char *)ptr)[i] > 31) && (((char *)ptr)[i] < 126)) { + fprintf(f, "%c", ((char *)ptr)[i]); + } else { + fprintf(f, "~%02x", ((char *)ptr)[i]); + } + } + } + fprintf(f, "\n"); +#endif +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_depth_file(const void *ptr, int depth, int max_depth, FILE *f) +{ + if (f) { + talloc_report_depth_cb(ptr, depth, max_depth, talloc_report_depth_FILE_helper, f); + fflush(f); + } +} + +/* + report on memory usage by all children of a pointer, giving a full tree view +*/ +void talloc_report_full(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, -1, f); +} + +/* + report on memory usage by all children of a pointer +*/ +void talloc_report(const void *ptr, FILE *f) +{ + talloc_report_depth_file(ptr, 0, 1, f); +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report(null_context, stderr); + } +} + +/* + report on any memory hanging off the null context +*/ +static void talloc_report_null_full(void) +{ + if (talloc_total_size(null_context) != 0) { + talloc_report_full(null_context, stderr); + } +} + +/* + enable tracking of the NULL context +*/ +void talloc_enable_null_tracking(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + if (autofree_context != NULL) { + talloc_reparent(NULL, null_context, autofree_context); + } + } +} + +/* + enable tracking of the NULL context, not moving the autofree context + into the NULL context. This is needed for the talloc testsuite +*/ +void talloc_enable_null_tracking_no_autofree(void) +{ + if (null_context == NULL) { + null_context = _talloc_named_const(NULL, 0, "null_context"); + } +} + +/* + disable tracking of the NULL context +*/ +void talloc_disable_null_tracking(void) +{ + if (null_context != NULL) { + /* we have to move any children onto the real NULL + context */ + struct talloc_chunk *tc, *tc2; + tc = talloc_chunk_from_ptr(null_context); + for (tc2 = tc->child; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + for (tc2 = tc->next; tc2; tc2=tc2->next) { + if (tc2->parent == tc) tc2->parent = NULL; + if (tc2->prev == tc) tc2->prev = NULL; + } + tc->child = NULL; + tc->next = NULL; + } + talloc_free(null_context); + null_context = NULL; +} + +/* + enable leak reporting on exit +*/ +void talloc_enable_leak_report(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null); +} + +/* + enable full leak reporting on exit +*/ +void talloc_enable_leak_report_full(void) +{ + talloc_enable_null_tracking(); + atexit(talloc_report_null_full); +} + +/* + talloc and zero memory. +*/ +void *_talloc_zero(const void *ctx, size_t size, const char *name) +{ + void *p = _talloc_named_const(ctx, size, name); + + if (p) { + memset(p, '\0', size); + } + + return p; +} + +/* + memdup with a talloc. +*/ +void *_talloc_memdup(const void *t, const void *p, size_t size, const char *name) +{ + void *newp = _talloc_named_const(t, size, name); + + if (likely(newp)) { + memcpy(newp, p, size); + } + + return newp; +} + +static inline char *__talloc_strlendup(const void *t, const char *p, size_t len) +{ + char *ret; + + ret = (char *)__talloc(t, len + 1); + if (unlikely(!ret)) return NULL; + + memcpy(ret, p, len); + ret[len] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + strdup with a talloc +*/ +char *talloc_strdup(const void *t, const char *p) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strlen(p)); +} + +/* + strndup with a talloc +*/ +char *talloc_strndup(const void *t, const char *p, size_t n) +{ + if (unlikely(!p)) return NULL; + return __talloc_strlendup(t, p, strnlen(p, n)); +} + +static inline char *__talloc_strlendup_append(char *s, size_t slen, + const char *a, size_t alen) +{ + char *ret; + + ret = talloc_realloc(NULL, s, char, slen + alen + 1); + if (unlikely(!ret)) return NULL; + + /* append the string and the trailing \0 */ + memcpy(&ret[slen], a, alen); + ret[slen+alen] = 0; + + _talloc_set_name_const(ret, ret); + return ret; +} + +/* + * Appends at the end of the string. + */ +char *talloc_strdup_append(char *s, const char *a) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strlen(a)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strdup_append_buffer(char *s, const char *a) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strlen(a)); +} + +/* + * Appends at the end of the string. + */ +char *talloc_strndup_append(char *s, const char *a, size_t n) +{ + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + return __talloc_strlendup_append(s, strlen(s), a, strnlen(a, n)); +} + +/* + * Appends at the end of the talloc'ed buffer, + * not the end of the string. + */ +char *talloc_strndup_append_buffer(char *s, const char *a, size_t n) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_strdup(NULL, a); + } + + if (unlikely(!a)) { + return s; + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_strlendup_append(s, slen, a, strnlen(a, n)); +} + +char *talloc_vasprintf(const void *t, const char *fmt, va_list ap) +{ + int len; + char *ret; + va_list ap2; + char c; + + /* this call looks strange, but it makes it work on older solaris boxes */ + va_copy(ap2, ap); + len = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + if (unlikely(len < 0)) { + return NULL; + } + + ret = (char *)__talloc(t, len+1); + if (unlikely(!ret)) return NULL; + + va_copy(ap2, ap); + vsnprintf(ret, len+1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(ret, ret); + return ret; +} + + +/* + Perform string formatting, and return a pointer to newly allocated + memory holding the result, inside a memory pool. + */ +char *talloc_asprintf(const void *t, const char *fmt, ...) +{ + va_list ap; + char *ret; + + va_start(ap, fmt); + ret = talloc_vasprintf(t, fmt, ap); + va_end(ap); + return ret; +} + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) + PRINTF_ATTRIBUTE(3,0); + +static inline char *__talloc_vaslenprintf_append(char *s, size_t slen, + const char *fmt, va_list ap) +{ + ssize_t alen; + va_list ap2; + char c; + + va_copy(ap2, ap); + alen = vsnprintf(&c, 1, fmt, ap2); + va_end(ap2); + + if (alen <= 0) { + /* Either the vsnprintf failed or the format resulted in + * no characters being formatted. In the former case, we + * ought to return NULL, in the latter we ought to return + * the original string. Most current callers of this + * function expect it to never return NULL. + */ + return s; + } + + s = talloc_realloc(NULL, s, char, slen + alen + 1); + if (!s) return NULL; + + va_copy(ap2, ap); + vsnprintf(s + slen, alen + 1, fmt, ap2); + va_end(ap2); + + _talloc_set_name_const(s, s); + return s; +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Good for gradually + * accumulating output into a string buffer. Appends at the end + * of the string. + **/ +char *talloc_vasprintf_append(char *s, const char *fmt, va_list ap) +{ + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + return __talloc_vaslenprintf_append(s, strlen(s), fmt, ap); +} + +/** + * Realloc @p s to append the formatted result of @p fmt and @p ap, + * and return @p s, which may have moved. Always appends at the + * end of the talloc'ed buffer, not the end of the string. + **/ +char *talloc_vasprintf_append_buffer(char *s, const char *fmt, va_list ap) +{ + size_t slen; + + if (unlikely(!s)) { + return talloc_vasprintf(NULL, fmt, ap); + } + + slen = talloc_get_size(s); + if (likely(slen > 0)) { + slen--; + } + + return __talloc_vaslenprintf_append(s, slen, fmt, ap); +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a string buffer. + */ +char *talloc_asprintf_append(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append(s, fmt, ap); + va_end(ap); + return s; +} + +/* + Realloc @p s to append the formatted result of @p fmt and return @p + s, which may have moved. Good for gradually accumulating output + into a buffer. + */ +char *talloc_asprintf_append_buffer(char *s, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + s = talloc_vasprintf_append_buffer(s, fmt, ap); + va_end(ap); + return s; +} + +/* + alloc an array, checking for integer overflow in the array size +*/ +void *_talloc_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_named_const(ctx, el_size * count, name); +} + +/* + alloc an zero array, checking for integer overflow in the array size +*/ +void *_talloc_zero_array(const void *ctx, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_zero(ctx, el_size * count, name); +} + +/* + realloc an array, checking for integer overflow in the array size +*/ +void *_talloc_realloc_array(const void *ctx, void *ptr, size_t el_size, unsigned count, const char *name) +{ + if (count >= MAX_TALLOC_SIZE/el_size) { + return NULL; + } + return _talloc_realloc(ctx, ptr, el_size * count, name); +} + +/* + a function version of talloc_realloc(), so it can be passed as a function pointer + to libraries that want a realloc function (a realloc function encapsulates + all the basic capabilities of an allocation library, which is why this is useful) +*/ +void *talloc_realloc_fn(const void *context, void *ptr, size_t size) +{ + return _talloc_realloc(context, ptr, size, NULL); +} + + +static int talloc_autofree_destructor(void *ptr) +{ + autofree_context = NULL; + return 0; +} + +static void talloc_autofree(void) +{ + talloc_free(autofree_context); +} + +/* + return a context which will be auto-freed on exit + this is useful for reducing the noise in leak reports +*/ +void *talloc_autofree_context(void) +{ + if (autofree_context == NULL) { + autofree_context = _talloc_named_const(NULL, 0, "autofree_context"); + talloc_set_destructor(autofree_context, talloc_autofree_destructor); + atexit(talloc_autofree); + } + return autofree_context; +} + +size_t talloc_get_size(const void *context) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + context = null_context; + } + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + + return tc->size; +} + +/* + find a parent of this context that has the given name, if any +*/ +void *talloc_find_parent_byname(const void *context, const char *name) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return NULL; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (tc->name && strcmp(tc->name, name) == 0) { + return TC_PTR_FROM_CHUNK(tc); + } + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return NULL; +} + +/* + show the parentage of a context +*/ +void talloc_show_parents(const void *context, FILE *file) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + fprintf(file, "talloc no parents for NULL\n"); + return; + } + + tc = talloc_chunk_from_ptr(context); + fprintf(file, "talloc parents of '%s'\n", talloc_get_name(context)); + while (tc) { + fprintf(file, "\t'%s'\n", talloc_get_name(TC_PTR_FROM_CHUNK(tc))); + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + fflush(file); +} + +/* + return 1 if ptr is a parent of context +*/ +int talloc_is_parent(const void *context, const void *ptr) +{ + struct talloc_chunk *tc; + + if (context == NULL) { + return 0; + } + + tc = talloc_chunk_from_ptr(context); + while (tc) { + if (TC_PTR_FROM_CHUNK(tc) == ptr) return 1; + while (tc && tc->prev) tc = tc->prev; + if (tc) { + tc = tc->parent; + } + } + return 0; +} diff --git a/libatalk/unicode/charcnv.c b/libatalk/unicode/charcnv.c index 98e8ffcc..e4f6d2b3 100644 --- a/libatalk/unicode/charcnv.c +++ b/libatalk/unicode/charcnv.c @@ -139,13 +139,11 @@ static const char *charset_name(charset_t ch) if (!ret) ret = charset_names[ch]; -#if defined(HAVE_NL_LANGINFO) && defined(CODESET) +#if defined(CODESET) if (ret && strcasecmp(ret, "LOCALE") == 0) { const char *ln = NULL; -#ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); -#endif ln = nl_langinfo(CODESET); if (ln) { /* Check whether the charset name is supported diff --git a/libatalk/util/Makefile.am b/libatalk/util/Makefile.am index b844dc5a..0a5ebd68 100644 --- a/libatalk/util/Makefile.am +++ b/libatalk/util/Makefile.am @@ -18,8 +18,6 @@ libutil_la_SOURCES = \ server_ipc.c \ server_lock.c \ socket.c \ - strcasestr.c \ strdicasecmp.c \ - strlcpy.c \ volinfo.c \ unix.c diff --git a/libatalk/util/fault.c b/libatalk/util/fault.c index 60db65ac..48c4fe05 100644 --- a/libatalk/util/fault.c +++ b/libatalk/util/fault.c @@ -36,7 +36,7 @@ #include #ifndef SIGNAL_CAST -#define SIGNAL_CAST (RETSIGTYPE (*)(int)) +#define SIGNAL_CAST (void (*)(int)) #endif #ifndef SAFE_FREE /* Oh no this is also defined in tdb.h */ #define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0) diff --git a/libatalk/util/strcasestr.c b/libatalk/util/strcasestr.c deleted file mode 100644 index b26c89ff..00000000 --- a/libatalk/util/strcasestr.c +++ /dev/null @@ -1,124 +0,0 @@ -/* Return the offset of one string within another. - Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 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 Library General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* - * My personal strstr() implementation that beats most other algorithms. - * Until someone tells me otherwise, I assume that this is the - * fastest implementation of strstr() in C. - * I deliberately chose not to comment it. You should have at least - * as much fun trying to understand it, as I had to write it :-). - * - * Stephen R. van den Berg, berg@pool.informatik.rwth-aachen.de */ -/* added strcasestr support, davidm@lineo.com */ - -#if HAVE_CONFIG_H -# include -#endif - -#ifndef HAVE_STRCASESTR - -#if defined HAVE_STRING_H -# include -#endif - -typedef unsigned chartype; - -#include -#define VAL(x) tolower(x) -#define FUNC strcasestr -#undef strcasestr - -char * FUNC ( const char *phaystack, const char *pneedle) -{ - register const unsigned char *haystack, *needle; - register chartype b, c; - - haystack = (const unsigned char *) phaystack; - needle = (const unsigned char *) pneedle; - - b = *needle; - if (b != '\0') { - haystack--; /* possible ANSI violation */ - do { - c = *++haystack; - if (c == '\0') - goto ret0; - } - while (VAL(c) != VAL(b)); - - c = *++needle; - if (c == '\0') - goto foundneedle; - ++needle; - goto jin; - - for (;;) { - register chartype a; - register const unsigned char *rhaystack, *rneedle; - - do { - a = *++haystack; - if (a == '\0') - goto ret0; - if (VAL(a) == VAL(b)) - break; - a = *++haystack; - if (a == '\0') - goto ret0; - shloop:;} - while (VAL(a) != VAL(b)); - - jin:a = *++haystack; - if (a == '\0') - goto ret0; - - if (VAL(a) != VAL(c)) - goto shloop; - - rhaystack = haystack-- + 1; - rneedle = needle; - a = *rneedle; - - if (VAL(*rhaystack) == VAL(a)) - do { - if (a == '\0') - goto foundneedle; - ++rhaystack; - a = *++needle; - if (VAL(*rhaystack) != VAL(a)) - break; - if (a == '\0') - goto foundneedle; - ++rhaystack; - a = *++needle; - } - while (VAL(*rhaystack) == VAL(a)); - - needle = rneedle; /* took the register-poor approach */ - - if (a == '\0') - break; - } - } - foundneedle: - return (char *) haystack; - ret0: - return 0; -} -#endif -- 2.39.2