diff --git a/configure b/configure index 17f3f2654f..3663e50d15 100755 --- a/configure +++ b/configure @@ -657,7 +657,7 @@ acx_pthread_config have_win32_dbghelp HAVE_IPV6 LIBOBJS -OSSP_UUID_LIBS +UUID_LIBS ZIC python_enable_shared python_additional_libs @@ -705,7 +705,8 @@ with_system_tzdata with_libxslt with_libxml XML2_CONFIG -with_ossp_uuid +UUID_EXTRA_OBJS +with_uuid with_selinux with_openssl krb_srvtab @@ -826,6 +827,7 @@ with_openssl with_selinux with_readline with_libedit_preferred +with_uuid with_ossp_uuid with_libxml with_libxslt @@ -1512,7 +1514,8 @@ Optional Packages: --without-readline do not use GNU Readline nor BSD Libedit for editing --with-libedit-preferred prefer BSD Libedit over GNU Readline - --with-ossp-uuid build contrib/uuid-ossp, requires OSSP UUID library + --with-uuid=LIB build contrib/uuid-ossp using LIB (bsd,e2fs,ossp) + --with-ossp-uuid obsolete spelling of --with-uuid=ossp --with-libxml build with XML support --with-libxslt use XSLT support when building contrib/xml2 --with-system-tzdata=DIR @@ -1737,6 +1740,73 @@ fi } # ac_fn_c_try_cpp +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + # ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES # ------------------------------------------------------- # Tests whether HEADER exists, giving a warning if it cannot be compiled using @@ -2195,73 +2265,6 @@ rm -f conftest.val } # ac_fn_c_compute_int -# ac_fn_c_check_func LINENO FUNC VAR -# ---------------------------------- -# Tests whether FUNC exists, setting the cache variable VAR accordingly -ac_fn_c_check_func () -{ - as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 -$as_echo_n "checking for $2... " >&6; } -if eval \${$3+:} false; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Define $2 to an innocuous variant, in case declares $2. - For example, HP-UX 11i declares gettimeofday. */ -#define $2 innocuous_$2 - -/* System header to define __stub macros and hopefully few prototypes, - which can conflict with char $2 (); below. - Prefer to if __STDC__ is defined, since - exists even on freestanding compilers. */ - -#ifdef __STDC__ -# include -#else -# include -#endif - -#undef $2 - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char $2 (); -/* The GNU C library defines this for functions which it implements - to always fail with ENOSYS. Some functions are actually named - something starting with __ and the normal name is an alias. */ -#if defined __stub_$2 || defined __stub___$2 -choke me -#endif - -int -main () -{ -return $2 (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - eval "$3=yes" -else - eval "$3=no" -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -fi -eval ac_res=\$$3 - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 -$as_echo "$ac_res" >&6; } - eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno - -} # ac_fn_c_check_func - # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES # --------------------------------------------- # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR @@ -5614,8 +5617,37 @@ fi # -# OSSP UUID library +# UUID library # +# There are at least three UUID libraries in common use: the FreeBSD/NetBSD +# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP +# UUID library. More than one of these might be present on a given platform, +# so we make the user say which one she wants. +# + + + +# Check whether --with-uuid was given. +if test "${with_uuid+set}" = set; then : + withval=$with_uuid; + case $withval in + yes) + as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 + ;; + no) + as_fn_error $? "argument required for --with-uuid option" "$LINENO" 5 + ;; + *) + + ;; + esac + +fi + + +if test x"$with_uuid" = x"" ; then + with_uuid=no +fi @@ -5640,6 +5672,31 @@ else fi +if test "$with_ossp_uuid" = yes ; then + with_uuid=ossp +fi + +if test "$with_uuid" = bsd ; then + +$as_echo "#define HAVE_UUID_BSD 1" >>confdefs.h + + UUID_EXTRA_OBJS="md5.o sha1.o" +elif test "$with_uuid" = e2fs ; then + +$as_echo "#define HAVE_UUID_E2FS 1" >>confdefs.h + + UUID_EXTRA_OBJS="md5.o sha1.o" +elif test "$with_uuid" = ossp ; then + +$as_echo "#define HAVE_UUID_OSSP 1" >>confdefs.h + + UUID_EXTRA_OBJS="" +elif test "$with_uuid" = no ; then + UUID_EXTRA_OBJS="" +else + as_fn_error $? "--with-uuid must specify one of bsd, e2fs, or ossp" "$LINENO" 5 +fi + @@ -8775,7 +8832,66 @@ fi fi # for contrib/uuid-ossp -if test "$with_ossp_uuid" = yes ; then +if test "$with_uuid" = bsd ; then + # On BSD, the UUID functions are in libc + ac_fn_c_check_func "$LINENO" "uuid_to_string" "ac_cv_func_uuid_to_string" +if test "x$ac_cv_func_uuid_to_string" = xyes; then : + UUID_LIBS="" +else + as_fn_error $? "BSD UUID functions are not present" "$LINENO" 5 +fi + +elif test "$with_uuid" = e2fs ; then + # On OS X, the UUID functions are in libc + ac_fn_c_check_func "$LINENO" "uuid_generate" "ac_cv_func_uuid_generate" +if test "x$ac_cv_func_uuid_generate" = xyes; then : + UUID_LIBS="" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_generate in -luuid" >&5 +$as_echo_n "checking for uuid_generate in -luuid... " >&6; } +if ${ac_cv_lib_uuid_uuid_generate+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-luuid $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char uuid_generate (); +int +main () +{ +return uuid_generate (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_uuid_uuid_generate=yes +else + ac_cv_lib_uuid_uuid_generate=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_generate" >&5 +$as_echo "$ac_cv_lib_uuid_uuid_generate" >&6; } +if test "x$ac_cv_lib_uuid_uuid_generate" = xyes; then : + UUID_LIBS="-luuid" +else + as_fn_error $? "library 'uuid' is required for E2FS UUID" "$LINENO" 5 +fi + +fi + +elif test "$with_uuid" = ossp ; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_export in -lossp-uuid" >&5 $as_echo_n "checking for uuid_export in -lossp-uuid... " >&6; } if ${ac_cv_lib_ossp_uuid_uuid_export+:} false; then : @@ -8813,7 +8929,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ossp_uuid_uuid_export" >&5 $as_echo "$ac_cv_lib_ossp_uuid_uuid_export" >&6; } if test "x$ac_cv_lib_ossp_uuid_uuid_export" = xyes; then : - OSSP_UUID_LIBS="-lossp-uuid" + UUID_LIBS="-lossp-uuid" else { $as_echo "$as_me:${as_lineno-$LINENO}: checking for uuid_export in -luuid" >&5 $as_echo_n "checking for uuid_export in -luuid... " >&6; } @@ -8852,9 +8968,9 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_uuid_uuid_export" >&5 $as_echo "$ac_cv_lib_uuid_uuid_export" >&6; } if test "x$ac_cv_lib_uuid_uuid_export" = xyes; then : - OSSP_UUID_LIBS="-luuid" + UUID_LIBS="-luuid" else - as_fn_error $? "library 'ossp-uuid' or 'uuid' is required for OSSP-UUID" "$LINENO" 5 + as_fn_error $? "library 'ossp-uuid' or 'uuid' is required for OSSP UUID" "$LINENO" 5 fi fi @@ -9398,7 +9514,86 @@ fi fi # for contrib/uuid-ossp -if test "$with_ossp_uuid" = yes ; then +if test "$with_uuid" = bsd ; then + for ac_header in uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_H 1 +_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uuid_to_string" >/dev/null 2>&1; then : + +else + as_fn_error $? "header file does not match BSD UUID library" "$LINENO" 5 +fi +rm -f conftest* + +else + as_fn_error $? "header file is required for BSD UUID" "$LINENO" 5 +fi + +done + +elif test "$with_uuid" = e2fs ; then + for ac_header in uuid/uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid/uuid.h" "ac_cv_header_uuid_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_UUID_H 1 +_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uuid_generate" >/dev/null 2>&1; then : + +else + as_fn_error $? "header file does not match E2FS UUID library" "$LINENO" 5 +fi +rm -f conftest* + +else + for ac_header in uuid.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default" +if test "x$ac_cv_header_uuid_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_UUID_H 1 +_ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uuid_generate" >/dev/null 2>&1; then : + +else + as_fn_error $? "header file does not match E2FS UUID library" "$LINENO" 5 +fi +rm -f conftest* + +else + as_fn_error $? "header file or is required for E2FS UUID" "$LINENO" 5 +fi + +done + +fi + +done + +elif test "$with_uuid" = ossp ; then for ac_header in ossp/uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "ossp/uuid.h" "ac_cv_header_ossp_uuid_h" "$ac_includes_default" @@ -9406,19 +9601,42 @@ if test "x$ac_cv_header_ossp_uuid_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_OSSP_UUID_H 1 _ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uuid_export" >/dev/null 2>&1; then : else + as_fn_error $? "header file does not match OSSP UUID library" "$LINENO" 5 +fi +rm -f conftest* - for ac_header in uuid.h +else + for ac_header in uuid.h do : ac_fn_c_check_header_mongrel "$LINENO" "uuid.h" "ac_cv_header_uuid_h" "$ac_includes_default" if test "x$ac_cv_header_uuid_h" = xyes; then : cat >>confdefs.h <<_ACEOF #define HAVE_UUID_H 1 _ACEOF + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "uuid_export" >/dev/null 2>&1; then : else - as_fn_error $? "header file or is required for OSSP-UUID" "$LINENO" 5 + as_fn_error $? "header file does not match OSSP UUID library" "$LINENO" 5 +fi +rm -f conftest* + +else + as_fn_error $? "header file or is required for OSSP UUID" "$LINENO" 5 fi done diff --git a/configure.in b/configure.in index b94db352e1..80df1d7651 100644 --- a/configure.in +++ b/configure.in @@ -694,10 +694,38 @@ PGAC_ARG_BOOL(with, libedit-preferred, no, # -# OSSP UUID library +# UUID library # -PGAC_ARG_BOOL(with, ossp-uuid, no, [build contrib/uuid-ossp, requires OSSP UUID library]) -AC_SUBST(with_ossp_uuid) +# There are at least three UUID libraries in common use: the FreeBSD/NetBSD +# library, the e2fsprogs libuuid (now part of util-linux-ng), and the OSSP +# UUID library. More than one of these might be present on a given platform, +# so we make the user say which one she wants. +# +PGAC_ARG_REQ(with, uuid, [LIB], [build contrib/uuid-ossp using LIB (bsd,e2fs,ossp)]) +if test x"$with_uuid" = x"" ; then + with_uuid=no +fi +PGAC_ARG_BOOL(with, ossp-uuid, no, [obsolete spelling of --with-uuid=ossp]) +if test "$with_ossp_uuid" = yes ; then + with_uuid=ossp +fi + +if test "$with_uuid" = bsd ; then + AC_DEFINE([HAVE_UUID_BSD], 1, [Define to 1 if you have BSD UUID support.]) + UUID_EXTRA_OBJS="md5.o sha1.o" +elif test "$with_uuid" = e2fs ; then + AC_DEFINE([HAVE_UUID_E2FS], 1, [Define to 1 if you have E2FS UUID support.]) + UUID_EXTRA_OBJS="md5.o sha1.o" +elif test "$with_uuid" = ossp ; then + AC_DEFINE([HAVE_UUID_OSSP], 1, [Define to 1 if you have OSSP UUID support.]) + UUID_EXTRA_OBJS="" +elif test "$with_uuid" = no ; then + UUID_EXTRA_OBJS="" +else + AC_MSG_ERROR([--with-uuid must specify one of bsd, e2fs, or ossp]) +fi +AC_SUBST(with_uuid) +AC_SUBST(UUID_EXTRA_OBJS) # @@ -948,14 +976,26 @@ if test "$with_selinux" = yes; then fi # for contrib/uuid-ossp -if test "$with_ossp_uuid" = yes ; then +if test "$with_uuid" = bsd ; then + # On BSD, the UUID functions are in libc + AC_CHECK_FUNC(uuid_to_string, + [UUID_LIBS=""], + [AC_MSG_ERROR([BSD UUID functions are not present])]) +elif test "$with_uuid" = e2fs ; then + # On OS X, the UUID functions are in libc + AC_CHECK_FUNC(uuid_generate, + [UUID_LIBS=""], + [AC_CHECK_LIB(uuid, uuid_generate, + [UUID_LIBS="-luuid"], + [AC_MSG_ERROR([library 'uuid' is required for E2FS UUID])])]) +elif test "$with_uuid" = ossp ; then AC_CHECK_LIB(ossp-uuid, uuid_export, - [OSSP_UUID_LIBS="-lossp-uuid"], + [UUID_LIBS="-lossp-uuid"], [AC_CHECK_LIB(uuid, uuid_export, - [OSSP_UUID_LIBS="-luuid"], - [AC_MSG_ERROR([library 'ossp-uuid' or 'uuid' is required for OSSP-UUID])])]) + [UUID_LIBS="-luuid"], + [AC_MSG_ERROR([library 'ossp-uuid' or 'uuid' is required for OSSP UUID])])]) fi -AC_SUBST(OSSP_UUID_LIBS) +AC_SUBST(UUID_LIBS) ## @@ -1075,10 +1115,27 @@ if test "$with_bonjour" = yes ; then fi # for contrib/uuid-ossp -if test "$with_ossp_uuid" = yes ; then - AC_CHECK_HEADERS(ossp/uuid.h, [], [ - AC_CHECK_HEADERS(uuid.h, [], - [AC_MSG_ERROR([header file or is required for OSSP-UUID])])]) +if test "$with_uuid" = bsd ; then + AC_CHECK_HEADERS(uuid.h, + [AC_EGREP_HEADER([uuid_to_string], uuid.h, [], + [AC_MSG_ERROR([header file does not match BSD UUID library])])], + [AC_MSG_ERROR([header file is required for BSD UUID])]) +elif test "$with_uuid" = e2fs ; then + AC_CHECK_HEADERS(uuid/uuid.h, + [AC_EGREP_HEADER([uuid_generate], uuid/uuid.h, [], + [AC_MSG_ERROR([header file does not match E2FS UUID library])])], + [AC_CHECK_HEADERS(uuid.h, + [AC_EGREP_HEADER([uuid_generate], uuid.h, [], + [AC_MSG_ERROR([header file does not match E2FS UUID library])])], + [AC_MSG_ERROR([header file or is required for E2FS UUID])])]) +elif test "$with_uuid" = ossp ; then + AC_CHECK_HEADERS(ossp/uuid.h, + [AC_EGREP_HEADER([uuid_export], ossp/uuid.h, [], + [AC_MSG_ERROR([header file does not match OSSP UUID library])])], + [AC_CHECK_HEADERS(uuid.h, + [AC_EGREP_HEADER([uuid_export], uuid.h, [], + [AC_MSG_ERROR([header file does not match OSSP UUID library])])], + [AC_MSG_ERROR([header file or is required for OSSP UUID])])]) fi if test "$PORTNAME" = "win32" ; then diff --git a/contrib/Makefile b/contrib/Makefile index 8dc40f7de0..b37d0dd2c3 100644 --- a/contrib/Makefile +++ b/contrib/Makefile @@ -64,7 +64,7 @@ else ALWAYS_SUBDIRS += sslinfo endif -ifeq ($(with_ossp_uuid),yes) +ifneq ($(with_uuid),no) SUBDIRS += uuid-ossp else ALWAYS_SUBDIRS += uuid-ossp diff --git a/contrib/uuid-ossp/.gitignore b/contrib/uuid-ossp/.gitignore new file mode 100644 index 0000000000..6c989c7872 --- /dev/null +++ b/contrib/uuid-ossp/.gitignore @@ -0,0 +1,6 @@ +/md5.c +/sha1.c +# Generated subdirectories +/log/ +/results/ +/tmp_check/ diff --git a/contrib/uuid-ossp/Makefile b/contrib/uuid-ossp/Makefile index 9b2d2e3ff9..335cc7ef50 100644 --- a/contrib/uuid-ossp/Makefile +++ b/contrib/uuid-ossp/Makefile @@ -1,12 +1,21 @@ # contrib/uuid-ossp/Makefile MODULE_big = uuid-ossp -OBJS = uuid-ossp.o +OBJS = uuid-ossp.o $(UUID_EXTRA_OBJS) EXTENSION = uuid-ossp DATA = uuid-ossp--1.0.sql uuid-ossp--unpackaged--1.0.sql -SHLIB_LINK += $(OSSP_UUID_LIBS) +REGRESS = uuid_ossp + +SHLIB_LINK += $(UUID_LIBS) + +# We copy some needed files verbatim from pgcrypto +pgcrypto_src = $(top_srcdir)/contrib/pgcrypto + +PG_CPPFLAGS = -I$(pgcrypto_src) + +EXTRA_CLEAN = md5.c sha1.c ifdef USE_PGXS PG_CONFIG = pg_config @@ -18,3 +27,6 @@ top_builddir = ../.. include $(top_builddir)/src/Makefile.global include $(top_srcdir)/contrib/contrib-global.mk endif + +md5.c sha1.c: % : $(pgcrypto_src)/% + rm -f $@ && $(LN_S) $< . diff --git a/contrib/uuid-ossp/expected/uuid_ossp.out b/contrib/uuid-ossp/expected/uuid_ossp.out new file mode 100644 index 0000000000..986843c897 --- /dev/null +++ b/contrib/uuid-ossp/expected/uuid_ossp.out @@ -0,0 +1,91 @@ +CREATE EXTENSION "uuid-ossp"; +SELECT uuid_nil(); + uuid_nil +-------------------------------------- + 00000000-0000-0000-0000-000000000000 +(1 row) + +SELECT uuid_ns_dns(); + uuid_ns_dns +-------------------------------------- + 6ba7b810-9dad-11d1-80b4-00c04fd430c8 +(1 row) + +SELECT uuid_ns_url(); + uuid_ns_url +-------------------------------------- + 6ba7b811-9dad-11d1-80b4-00c04fd430c8 +(1 row) + +SELECT uuid_ns_oid(); + uuid_ns_oid +-------------------------------------- + 6ba7b812-9dad-11d1-80b4-00c04fd430c8 +(1 row) + +SELECT uuid_ns_x500(); + uuid_ns_x500 +-------------------------------------- + 6ba7b814-9dad-11d1-80b4-00c04fd430c8 +(1 row) + +SELECT uuid_generate_v1() < uuid_generate_v1(); + ?column? +---------- + t +(1 row) + +SELECT uuid_generate_v1() < uuid_generate_v1mc(); + ?column? +---------- + t +(1 row) + +SELECT substr(uuid_generate_v1()::text, 25) = substr(uuid_generate_v1()::text, 25); + ?column? +---------- + t +(1 row) + +SELECT substr(uuid_generate_v1()::text, 25) <> substr(uuid_generate_v1mc()::text, 25); + ?column? +---------- + t +(1 row) + +SELECT substr(uuid_generate_v1mc()::text, 25) <> substr(uuid_generate_v1mc()::text, 25); + ?column? +---------- + t +(1 row) + +SELECT ('x' || substr(uuid_generate_v1mc()::text, 25, 2))::bit(8) & '00000011'; + ?column? +---------- + 00000011 +(1 row) + +SELECT uuid_generate_v3(uuid_ns_dns(), 'www.widgets.com'); + uuid_generate_v3 +-------------------------------------- + 3d813cbb-47fb-32ba-91df-831e1593ac29 +(1 row) + +SELECT uuid_generate_v5(uuid_ns_dns(), 'www.widgets.com'); + uuid_generate_v5 +-------------------------------------- + 21f7f8de-8051-5b89-8680-0195ef798b6a +(1 row) + +SELECT uuid_generate_v4()::text ~ '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'; + ?column? +---------- + t +(1 row) + +SELECT uuid_generate_v4() <> uuid_generate_v4(); + ?column? +---------- + t +(1 row) + diff --git a/contrib/uuid-ossp/sql/uuid_ossp.sql b/contrib/uuid-ossp/sql/uuid_ossp.sql new file mode 100644 index 0000000000..29fba21b3f --- /dev/null +++ b/contrib/uuid-ossp/sql/uuid_ossp.sql @@ -0,0 +1,22 @@ +CREATE EXTENSION "uuid-ossp"; + +SELECT uuid_nil(); +SELECT uuid_ns_dns(); +SELECT uuid_ns_url(); +SELECT uuid_ns_oid(); +SELECT uuid_ns_x500(); + +SELECT uuid_generate_v1() < uuid_generate_v1(); +SELECT uuid_generate_v1() < uuid_generate_v1mc(); + +SELECT substr(uuid_generate_v1()::text, 25) = substr(uuid_generate_v1()::text, 25); +SELECT substr(uuid_generate_v1()::text, 25) <> substr(uuid_generate_v1mc()::text, 25); +SELECT substr(uuid_generate_v1mc()::text, 25) <> substr(uuid_generate_v1mc()::text, 25); + +SELECT ('x' || substr(uuid_generate_v1mc()::text, 25, 2))::bit(8) & '00000011'; + +SELECT uuid_generate_v3(uuid_ns_dns(), 'www.widgets.com'); +SELECT uuid_generate_v5(uuid_ns_dns(), 'www.widgets.com'); + +SELECT uuid_generate_v4()::text ~ '^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$'; +SELECT uuid_generate_v4() <> uuid_generate_v4(); diff --git a/contrib/uuid-ossp/uuid-ossp.c b/contrib/uuid-ossp/uuid-ossp.c index 8f99084df3..f8c33d2b46 100644 --- a/contrib/uuid-ossp/uuid-ossp.c +++ b/contrib/uuid-ossp/uuid-ossp.c @@ -1,40 +1,113 @@ /*------------------------------------------------------------------------- * - * UUID generation functions using the OSSP UUID library + * UUID generation functions using the BSD, E2FS or OSSP UUID library * * Copyright (c) 2007-2014, PostgreSQL Global Development Group * + * Portions Copyright (c) 2009 Andrew Gierth + * * contrib/uuid-ossp/uuid-ossp.c * *------------------------------------------------------------------------- */ #include "postgres.h" + #include "fmgr.h" #include "utils/builtins.h" #include "utils/uuid.h" /* - * There's some confusion over the location of the uuid.h header file. - * On Debian, it's installed as ossp/uuid.h, while on Fedora, or if you - * install ossp-uuid from a tarball, it's installed as uuid.h. Don't know - * what other systems do. + * It's possible that there's more than one uuid.h header file present. + * We expect configure to set the HAVE_ symbol for only the one we want. + * + * BSD includes a uuid_hash() function that conflicts with the one in + * builtins.h; we #define it out of the way. */ -#ifdef HAVE_OSSP_UUID_H -#include -#else +#define uuid_hash bsd_uuid_hash + #ifdef HAVE_UUID_H #include -#else -#error OSSP uuid.h not found #endif +#ifdef HAVE_OSSP_UUID_H +#include +#endif +#ifdef HAVE_UUID_UUID_H +#include #endif -/* better both be 16 */ -#if (UUID_LEN != UUID_LEN_BIN) +#undef uuid_hash + +/* + * Some BSD variants offer md5 and sha1 implementations but Linux does not, + * so we use a copy of the ones from pgcrypto. Not needed with OSSP, though. + */ +#ifndef HAVE_UUID_OSSP +#include "md5.h" +#include "sha1.h" +#endif + + +/* Check our UUID length against OSSP's; better both be 16 */ +#if defined(HAVE_UUID_OSSP) && (UUID_LEN != UUID_LEN_BIN) #error UUID length mismatch #endif +/* Define some constants like OSSP's, to make the code more readable */ +#ifndef HAVE_UUID_OSSP +#define UUID_MAKE_MC 0 +#define UUID_MAKE_V1 1 +#define UUID_MAKE_V2 2 +#define UUID_MAKE_V3 3 +#define UUID_MAKE_V4 4 +#define UUID_MAKE_V5 5 +#endif + +/* + * A DCE 1.1 compatible source representation of UUIDs, derived from + * the BSD implementation. BSD already has this; OSSP doesn't need it. + */ +#ifdef HAVE_UUID_E2FS +typedef struct +{ + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[6]; +} dce_uuid_t; +#else +#define dce_uuid_t uuid_t +#endif + +/* If not OSSP, we need some endianness-manipulation macros */ +#ifndef HAVE_UUID_OSSP + +#define UUID_TO_NETWORK(uu) \ +do { \ + uu.time_low = htonl(uu.time_low); \ + uu.time_mid = htons(uu.time_mid); \ + uu.time_hi_and_version = htons(uu.time_hi_and_version); \ +} while (0) + +#define UUID_TO_LOCAL(uu) \ +do { \ + uu.time_low = ntohl(uu.time_low); \ + uu.time_mid = ntohs(uu.time_mid); \ + uu.time_hi_and_version = ntohs(uu.time_hi_and_version); \ +} while (0) + +#define UUID_V3_OR_V5(uu, v) \ +do { \ + uu.time_hi_and_version &= 0x0FFF; \ + uu.time_hi_and_version |= (v << 12); \ + uu.clock_seq_hi_and_reserved &= 0x3F; \ + uu.clock_seq_hi_and_reserved |= 0x80; \ +} while(0) + +#endif /* !HAVE_UUID_OSSP */ + PG_MODULE_MAGIC; @@ -51,6 +124,8 @@ PG_FUNCTION_INFO_V1(uuid_generate_v3); PG_FUNCTION_INFO_V1(uuid_generate_v4); PG_FUNCTION_INFO_V1(uuid_generate_v5); +#ifdef HAVE_UUID_OSSP + static void pguuid_complain(uuid_rc_t rc) { @@ -114,44 +189,9 @@ special_uuid_value(const char *name) return DirectFunctionCall1(uuid_in, CStringGetDatum(str)); } - -Datum -uuid_nil(PG_FUNCTION_ARGS) -{ - return special_uuid_value("nil"); -} - - -Datum -uuid_ns_dns(PG_FUNCTION_ARGS) -{ - return special_uuid_value("ns:DNS"); -} - - -Datum -uuid_ns_url(PG_FUNCTION_ARGS) -{ - return special_uuid_value("ns:URL"); -} - - -Datum -uuid_ns_oid(PG_FUNCTION_ARGS) -{ - return special_uuid_value("ns:OID"); -} - - -Datum -uuid_ns_x500(PG_FUNCTION_ARGS) -{ - return special_uuid_value("ns:X500"); -} - - +/* len is unused with OSSP, but we want to have the same number of args */ static Datum -uuid_generate_internal(int mode, const uuid_t *ns, const char *name) +uuid_generate_internal(int mode, const uuid_t *ns, const char *name, int len) { uuid_t *uuid; char *str; @@ -172,20 +212,6 @@ uuid_generate_internal(int mode, const uuid_t *ns, const char *name) } -Datum -uuid_generate_v1(PG_FUNCTION_ARGS) -{ - return uuid_generate_internal(UUID_MAKE_V1, NULL, NULL); -} - - -Datum -uuid_generate_v1mc(PG_FUNCTION_ARGS) -{ - return uuid_generate_internal(UUID_MAKE_V1 | UUID_MAKE_MC, NULL, NULL); -} - - static Datum uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name) { @@ -201,7 +227,8 @@ uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name) result = uuid_generate_internal(mode, ns_uuid, - text_to_cstring(name)); + text_to_cstring(name), + 0); rc = uuid_destroy(ns_uuid); if (rc != UUID_RC_OK) @@ -210,6 +237,248 @@ uuid_generate_v35_internal(int mode, pg_uuid_t *ns, text *name) return result; } +#else /* !HAVE_UUID_OSSP */ + +static Datum +uuid_generate_internal(int v, unsigned char *ns, char *ptr, int len) +{ + char strbuf[40]; + + switch (v) + { + case 0: /* constant-value uuids */ + strlcpy(strbuf, ptr, 37); + break; + + case 1: /* time/node-based uuids */ + { +#ifdef HAVE_UUID_E2FS + uuid_t uu; + + uuid_generate_time(uu); + uuid_unparse(uu, strbuf); + + /* + * PTR, if set, replaces the trailing characters of the uuid; + * this is to support v1mc, where a random multicast MAC is + * used instead of the physical one + */ + if (ptr && len <= 36) + strcpy(strbuf + (36 - len), ptr); +#else /* BSD */ + uuid_t uu; + uint32_t status = uuid_s_ok; + char *str = NULL; + + uuid_create(&uu, &status); + + if (status == uuid_s_ok) + { + uuid_to_string(&uu, &str, &status); + if (status == uuid_s_ok) + { + strlcpy(strbuf, str, 37); + + /* + * PTR, if set, replaces the trailing characters of + * the uuid; this is to support v1mc, where a random + * multicast MAC is used instead of the physical one + */ + if (ptr && len <= 36) + strcpy(strbuf + (36 - len), ptr); + } + if (str) + free(str); + } + + if (status != uuid_s_ok) + ereport(ERROR, + (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), + errmsg("uuid library failure: %d", + (int) status))); +#endif + break; + } + + case 3: /* namespace-based MD5 uuids */ + case 5: /* namespace-based SHA1 uuids */ + { + dce_uuid_t uu; +#ifdef HAVE_UUID_BSD + uint32_t status = uuid_s_ok; + char *str = NULL; +#endif + + if (v == 3) + { + MD5_CTX ctx; + + MD5Init(&ctx); + MD5Update(&ctx, ns, sizeof(uu)); + MD5Update(&ctx, (unsigned char *) ptr, len); + MD5Final((unsigned char *) &uu, &ctx); + } + else + { + SHA1_CTX ctx; + + SHA1Init(&ctx); + SHA1Update(&ctx, ns, sizeof(uu)); + SHA1Update(&ctx, (unsigned char *) ptr, len); + SHA1Final((unsigned char *) &uu, &ctx); + } + + /* the calculated hash is using local order */ + UUID_TO_NETWORK(uu); + UUID_V3_OR_V5(uu, v); + +#ifdef HAVE_UUID_E2FS + /* uuid_unparse expects local order */ + UUID_TO_LOCAL(uu); + uuid_unparse((unsigned char *) &uu, strbuf); +#else /* BSD */ + uuid_to_string(&uu, &str, &status); + + if (status == uuid_s_ok) + strlcpy(strbuf, str, 37); + + if (str) + free(str); + + if (status != uuid_s_ok) + ereport(ERROR, + (errcode(ERRCODE_EXTERNAL_ROUTINE_EXCEPTION), + errmsg("uuid library failure: %d", + (int) status))); +#endif + break; + } + + case 4: /* random uuid */ + default: + { +#ifdef HAVE_UUID_E2FS + uuid_t uu; + + uuid_generate_random(uu); + uuid_unparse(uu, strbuf); +#else /* BSD */ + snprintf(strbuf, sizeof(strbuf), + "%08lx-%04x-%04x-%04x-%04x%08lx", + (unsigned long) arc4random(), + (unsigned) (arc4random() & 0xffff), + (unsigned) ((arc4random() & 0xfff) | 0x4000), + (unsigned) ((arc4random() & 0x3fff) | 0x8000), + (unsigned) (arc4random() & 0xffff), + (unsigned long) arc4random()); +#endif + break; + } + } + + return DirectFunctionCall1(uuid_in, CStringGetDatum(strbuf)); +} + +#endif /* HAVE_UUID_OSSP */ + + +Datum +uuid_nil(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + return special_uuid_value("nil"); +#else + return uuid_generate_internal(0, NULL, + "00000000-0000-0000-0000-000000000000", 36); +#endif +} + + +Datum +uuid_ns_dns(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + return special_uuid_value("ns:DNS"); +#else + return uuid_generate_internal(0, NULL, + "6ba7b810-9dad-11d1-80b4-00c04fd430c8", 36); +#endif +} + + +Datum +uuid_ns_url(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + return special_uuid_value("ns:URL"); +#else + return uuid_generate_internal(0, NULL, + "6ba7b811-9dad-11d1-80b4-00c04fd430c8", 36); +#endif +} + + +Datum +uuid_ns_oid(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + return special_uuid_value("ns:OID"); +#else + return uuid_generate_internal(0, NULL, + "6ba7b812-9dad-11d1-80b4-00c04fd430c8", 36); +#endif +} + + +Datum +uuid_ns_x500(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + return special_uuid_value("ns:X500"); +#else + return uuid_generate_internal(0, NULL, + "6ba7b814-9dad-11d1-80b4-00c04fd430c8", 36); +#endif +} + + +Datum +uuid_generate_v1(PG_FUNCTION_ARGS) +{ + return uuid_generate_internal(UUID_MAKE_V1, NULL, NULL, 0); +} + + +Datum +uuid_generate_v1mc(PG_FUNCTION_ARGS) +{ +#ifdef HAVE_UUID_OSSP + char *buf = NULL; +#elif defined(HAVE_UUID_E2FS) + char strbuf[40]; + char *buf; + uuid_t uu; + + uuid_generate_random(uu); + + /* set IEEE802 multicast and local-admin bits */ + ((dce_uuid_t *) &uu)->node[0] |= 0x03; + + uuid_unparse(uu, strbuf); + buf = strbuf + 24; +#else /* BSD */ + char buf[16]; + + /* set IEEE802 multicast and local-admin bits */ + snprintf(buf, sizeof(buf), "-%04x%08lx", + (unsigned) ((arc4random() & 0xffff) | 0x0300), + (unsigned long) arc4random()); +#endif + + return uuid_generate_internal(UUID_MAKE_V1 | UUID_MAKE_MC, NULL, + buf, 13); +} + Datum uuid_generate_v3(PG_FUNCTION_ARGS) @@ -217,14 +486,19 @@ uuid_generate_v3(PG_FUNCTION_ARGS) pg_uuid_t *ns = PG_GETARG_UUID_P(0); text *name = PG_GETARG_TEXT_P(1); +#ifdef HAVE_UUID_OSSP return uuid_generate_v35_internal(UUID_MAKE_V3, ns, name); +#else + return uuid_generate_internal(UUID_MAKE_V3, (unsigned char *) ns, + VARDATA(name), VARSIZE(name) - VARHDRSZ); +#endif } Datum uuid_generate_v4(PG_FUNCTION_ARGS) { - return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL); + return uuid_generate_internal(UUID_MAKE_V4, NULL, NULL, 0); } @@ -234,5 +508,10 @@ uuid_generate_v5(PG_FUNCTION_ARGS) pg_uuid_t *ns = PG_GETARG_UUID_P(0); text *name = PG_GETARG_TEXT_P(1); +#ifdef HAVE_UUID_OSSP return uuid_generate_v35_internal(UUID_MAKE_V5, ns, name); +#else + return uuid_generate_internal(UUID_MAKE_V5, (unsigned char *) ns, + VARDATA(name), VARSIZE(name) - VARHDRSZ); +#endif } diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index b6b582e24c..7353c612b1 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -869,17 +869,46 @@ su - postgres + + + + + Build the + ]]> module + (which provides functions to generate UUIDs), using the specified + UUID library.UUID + LIBRARY must be one of: + + + + + + + + + + + + + + + + + + - Build components using the OSSP UUID - library. Specifically, build the - - ]]> module, - which provides functions to generate - UUIDs.UUID + Obsolete equivalent of --with-uuid=ossp. diff --git a/doc/src/sgml/uuid-ossp.sgml b/doc/src/sgml/uuid-ossp.sgml index c48106ba0f..dbbea09313 100644 --- a/doc/src/sgml/uuid-ossp.sgml +++ b/doc/src/sgml/uuid-ossp.sgml @@ -13,20 +13,6 @@ are also functions to produce certain special UUID constants. - - This module depends on the OSSP UUID library, which can be found at - . - - - - - The OSSP UUID library is not well maintained, and is becoming increasingly - difficult to port to newer platforms. If you only need randomly-generated - (version 4) UUIDs, consider using the gen_random_uuid() - function from the module instead. - - - <literal>uuid-ossp</literal> Functions @@ -172,6 +158,39 @@ SELECT uuid_generate_v3(uuid_ns_url(), 'http://www.postgresql.org'); + + Building <filename>uuid-ossp</> + + + Historically this module depended on the OSSP UUID library, which accounts + for the module's name. While the OSSP UUID library can still be found + at , it is not well + maintained, and is becoming increasingly difficult to port to newer + platforms. uuid-ossp can now be built without the OSSP + library on some platforms. On FreeBSD, NetBSD, and some other BSD-derived + platforms, suitable UUID creation functions are included in the + core libc library. On Linux, Mac OS X, and some other + platforms, suitable functions are provided in the libuuid + library, which originally came from the e2fsprogs project + (though on modern Linux it is considered part + of util-linux-ng). When invoking configure, + specify to use the BSD functions, + or to + use e2fsprogs' libuuid, or + to use the OSSP UUID library. + More than one of these libraries might be available on a particular + machine, so configure does not automatically choose one. + + + + + If you only need randomly-generated (version 4) UUIDs, + consider using the gen_random_uuid() function + from the module instead. + + + + Author diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 4b31c0a85e..14119a1511 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -163,11 +163,11 @@ with_perl = @with_perl@ with_python = @with_python@ with_tcl = @with_tcl@ with_openssl = @with_openssl@ -with_ossp_uuid = @with_ossp_uuid@ with_selinux = @with_selinux@ with_libxml = @with_libxml@ with_libxslt = @with_libxslt@ with_system_tzdata = @with_system_tzdata@ +with_uuid = @with_uuid@ with_zlib = @with_zlib@ enable_rpath = @enable_rpath@ enable_nls = @enable_nls@ @@ -240,7 +240,8 @@ DLLWRAP = @DLLWRAP@ LIBS = @LIBS@ LDAP_LIBS_FE = @LDAP_LIBS_FE@ LDAP_LIBS_BE = @LDAP_LIBS_BE@ -OSSP_UUID_LIBS = @OSSP_UUID_LIBS@ +UUID_LIBS = @UUID_LIBS@ +UUID_EXTRA_OBJS = @UUID_EXTRA_OBJS@ LD = @LD@ with_gnu_ld = @with_gnu_ld@ ld_R_works = @ld_R_works@ diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index db930f5bb0..5ff9e41212 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -602,9 +602,21 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H +/* Define to 1 if you have BSD UUID support. */ +#undef HAVE_UUID_BSD + +/* Define to 1 if you have E2FS UUID support. */ +#undef HAVE_UUID_E2FS + /* Define to 1 if you have the header file. */ #undef HAVE_UUID_H +/* Define to 1 if you have OSSP UUID support. */ +#undef HAVE_UUID_OSSP + +/* Define to 1 if you have the header file. */ +#undef HAVE_UUID_UUID_H + /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF