UUID-0.38/0000755000175000017500000000000015201361072010343 5ustar rikrikUUID-0.38/LICENSE0000644000175000017500000002152415201361067011360 0ustar rikrikThis software is Copyright (c) 2014-2026 by Rick Myers. This is free software, licensed under: The Artistic License 2.0 (GPL Compatible) The Artistic License 2.0 Copyright (c) 2000-2006, The Perl Foundation. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble This license establishes the terms under which a given free software Package may be copied, modified, distributed, and/or redistributed. The intent is that the Copyright Holder maintains some artistic control over the development of that Package while still keeping the Package available as open source and free software. You are always permitted to make arrangements wholly outside of this license directly with the Copyright Holder of a given Package. If the terms of this license do not permit the full use that you propose to make of the Package, you should contact the Copyright Holder and seek a different licensing arrangement. Definitions "Copyright Holder" means the individual(s) or organization(s) named in the copyright notice for the entire Package. "Contributor" means any party that has contributed code or other material to the Package, in accordance with the Copyright Holder's procedures. "You" and "your" means any person who would like to copy, distribute, or modify the Package. "Package" means the collection of files distributed by the Copyright Holder, and derivatives of that collection and/or of those files. A given Package may consist of either the Standard Version, or a Modified Version. "Distribute" means providing a copy of the Package or making it accessible to anyone else, or in the case of a company or organization, to others outside of your company or organization. "Distributor Fee" means any fee that you charge for Distributing this Package or providing support for this Package to another party. It does not mean licensing fees. "Standard Version" refers to the Package if it has not been modified, or has been modified only in ways explicitly requested by the Copyright Holder. "Modified Version" means the Package, if it has been changed, and such changes were not explicitly requested by the Copyright Holder. "Original License" means this Artistic License as Distributed with the Standard Version of the Package, in its current version or as it may be modified by The Perl Foundation in the future. "Source" form means the source code, documentation source, and configuration files for the Package. "Compiled" form means the compiled bytecode, object code, binary, or any other form resulting from mechanical transformation or translation of the Source form. Permission for Use and Modification Without Distribution (1) You are permitted to use the Standard Version and create and use Modified Versions for any purpose without restriction, provided that you do not Distribute the Modified Version. Permissions for Redistribution of the Standard Version (2) You may Distribute verbatim copies of the Source form of the Standard Version of this Package in any medium without restriction, either gratis or for a Distributor Fee, provided that you duplicate all of the original copyright notices and associated disclaimers. At your discretion, such verbatim copies may or may not include a Compiled form of the Package. (3) You may apply any bug fixes, portability changes, and other modifications made available from the Copyright Holder. The resulting Package will still be considered the Standard Version, and as such will be subject to the Original License. Distribution of Modified Versions of the Package as Source (4) You may Distribute your Modified Version as Source (either gratis or for a Distributor Fee, and with or without a Compiled form of the Modified Version) provided that you clearly document how it differs from the Standard Version, including, but not limited to, documenting any non-standard features, executables, or modules, and provided that you do at least ONE of the following: (a) make the Modified Version available to the Copyright Holder of the Standard Version, under the Original License, so that the Copyright Holder may include your modifications in the Standard Version. (b) ensure that installation of your Modified Version does not prevent the user installing or running the Standard Version. In addition, the Modified Version must bear a name that is different from the name of the Standard Version. (c) allow anyone who receives a copy of the Modified Version to make the Source form of the Modified Version available to others under (i) the Original License or (ii) a license that permits the licensee to freely copy, modify and redistribute the Modified Version using the same licensing terms that apply to the copy that the licensee received, and requires that the Source form of the Modified Version, and of any works derived from it, be made freely available in that license fees are prohibited but Distributor Fees are allowed. Distribution of Compiled Forms of the Standard Version or Modified Versions without the Source (5) You may Distribute Compiled forms of the Standard Version without the Source, provided that you include complete instructions on how to get the Source of the Standard Version. Such instructions must be valid at the time of your distribution. If these instructions, at any time while you are carrying out such distribution, become invalid, you must provide new instructions on demand or cease further distribution. If you provide valid instructions or cease distribution within thirty days after you become aware that the instructions are invalid, then you do not forfeit any of your rights under this license. (6) You may Distribute a Modified Version in Compiled form without the Source, provided that you comply with Section 4 with respect to the Source of the Modified Version. Aggregating or Linking the Package (7) You may aggregate the Package (either the Standard Version or Modified Version) with other packages and Distribute the resulting aggregation provided that you do not charge a licensing fee for the Package. Distributor Fees are permitted, and licensing fees for other components in the aggregation are permitted. The terms of this license apply to the use and Distribution of the Standard or Modified Versions as included in the aggregation. (8) You are permitted to link Modified and Standard Versions with other works, to embed the Package in a larger work of your own, or to build stand-alone binary or bytecode versions of applications that include the Package, and Distribute the result without restriction, provided the result does not expose a direct interface to the Package. Items That are Not Considered Part of a Modified Version (9) Works (including, but not limited to, modules and scripts) that merely extend or make use of the Package, do not, by themselves, cause the Package to be a Modified Version. In addition, such works are not considered parts of the Package itself, and are not subject to the terms of this license. General Provisions (10) Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license. (11) If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license. (12) This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder. (13) This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed. (14) Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. UUID-0.38/MANIFEST.SKIP0000644000175000017500000000007615176655431012264 0ustar rikrik.git .gitignore .gitmeta .gitmeta.db .gitmeta.git .no-my-meta UUID-0.38/Makefile.PL0000644000175000017500000006710415177010206012327 0ustar rikrikuse strict; use warnings; use Config; use Devel::CheckLib; use ExtUtils::MakeMaker; # buffering will ruin your day! select STDERR; $|=1; select STDOUT; $|=1; # prereqs my $CONF_version = 0; # Config my $DL_version = 0; # DynaLoader my $EX_version = 0; # Exporter my $FS_version = 0; # File::Spec my $HRT_version = 0; # Time::HiRes my $DC_version = '1.14'; # Devel::CheckLib my $EUMM_version = '7.06'; # ExtUtils::MakeMaker my $FT_version = '0.10'; # File::Temp my $V_version = '0.77'; # version my $UUID_version = get_uuidpm_version(); my $no_mymeta = -e '.no-my-meta'; my ($libs, $defines) = check_flags(); my $has_threads = check_threads(); WriteMakefile1( 'NAME' => 'UUID', 'AUTHOR' => 'Rick Myers ', 'VERSION_FROM' => 'lib/UUID.pm', 'ABSTRACT_FROM' => 'lib/UUID.pm', 'LICENSE' => 'artistic_2', # It's currently unknown how far back the code will run (at least # 5.8.9), but needs perl-5.8.1 or better to test due to Unicode # regexps used in Term::Table, which is included via Test::More. # Devel::CheckLib also uses Test::More so not much point avoiding the # inevitable. # # Otherwise, this code needs at least perl-5.5.63 to get the required # data types. # #'MIN_PERL_VERSION' => '5.005063', # for U64 'MIN_PERL_VERSION' => '5.008001', # for Term::Table, which uses Unicode regexps 'LIBS' => $libs, 'NO_MYMETA' => $no_mymeta, 'INC' => '-I.', 'CCFLAGS' => $Config{ccflags}, 'DEFINE' => $defines, 'OBJECT' => '$(O_FILES)', 'LDFROM' => join( ' ', qw{ lib/UUID.o ulib/atomic.o ulib/chacha.o ulib/clock.o ulib/compare.o ulib/gen.o ulib/gettime.o ulib/hash.o ulib/node.o ulib/pack.o ulib/parse.o ulib/splitmix.o ulib/sysrand.o ulib/util.o ulib/xoshiro.o }), 'C' => [qw{ lib/UUID.c ulib/atomic.c ulib/chacha.c ulib/clock.c ulib/compare.c ulib/gen.c ulib/gettime.c ulib/hash.c ulib/node.c ulib/pack.c ulib/parse.c ulib/splitmix.c ulib/sysrand.c ulib/util.c ulib/xoshiro.c }], 'H' => [qw{ ulib/EUMM.h ulib/FUTX.h ulib/PORT.h ulib/TYPE.h ulib/UMTX.h ulib/UUID.h ulib/atomic.h ulib/chacha.h ulib/clock.h ulib/compare.h ulib/gen.h ulib/gettime.h ulib/hash.h ulib/node.h ulib/pack.h ulib/parse.h ulib/splitmix.h ulib/sysrand.h ulib/util.h ulib/xoshiro.h ulib/arch/arm/atomic.h ulib/arch/x86/atomic.h }], 'PREREQ_PM' => { 'Carp' => 0, 'DynaLoader' => $DL_version, 'Exporter' => $EX_version, 'Time::HiRes' => $HRT_version, 'blib' => 0, 'strict' => 0, 'vars' => 0, 'warnings' => 0, }, 'CONFIGURE_REQUIRES' => { 'Config' => $CONF_version, 'Devel::CheckLib' => $DC_version, 'ExtUtils::MakeMaker' => $EUMM_version, 'File::Spec' => $FS_version, 'File::Temp' => $FT_version, 'strict' => 0, 'warnings' => 0, }, 'BUILD_REQUIRES' => { 'Config' => $CONF_version, 'Devel::CheckLib' => $DC_version, 'ExtUtils::MakeMaker' => $EUMM_version, 'File::Spec' => $FS_version, 'File::Temp' => $FT_version, 'blib' => 0, 'strict' => 0, 'warnings' => 0, }, 'TEST_REQUIRES' => { 'Benchmark' => 0, 'Config' => $CONF_version, 'CPAN::Meta' => 0, 'DynaLoader' => $DL_version, 'Exporter' => $EX_version, 'Fcntl' => 0, 'ExtUtils::Manifest' => 0, 'File::Spec' => $FS_version, 'File::Temp' => $FT_version, 'Time::HiRes' => $HRT_version, 'Try::Tiny' => 0, 'blib' => 0, 'strict' => 0, 'vars' => 0, 'version' => $V_version, 'warnings' => 0, ( $has_threads ? ( 'threads' => 0, 'threads::shared' => 0, 'Thread::Semaphore' => 0, ) : () ), }, 'META_MERGE' => { 'dynamic_config' => 0, 'provides' => { 'UUID' => { 'file' => 'lib/UUID.pm', 'version' => $UUID_version, }, }, }, 'realclean' => { 'FILES' => join( ' ', sort qw{ LICENSE_new META_new.json META_new.yml README_new README_new.bak lib/UUID.c lib/UUID.def lib/UUID_def.old lib/UUID.o lib/UUID.obj lib/UUID.pdb lib/UUID.xsc assertconf*.h assertconf*.txt assertlib*.c assertlib*.exe assertlib*.obj perl.core perl.exe.stackdump ulib/*.obj ulib/*.pdb ulib/EUMM.h ulib/EUMM.h.tmp uu_to_blib }), }, ); unlink($_) for ; exit 0; sub WriteMakefile1 { #Written by Alexandr Ciornii, version 0.21. Added by eumm-upgrade. my %params=@_; my $eumm_version=$ExtUtils::MakeMaker::VERSION; $eumm_version=eval $eumm_version; die "EXTRA_META is deprecated" if exists $params{EXTRA_META}; die "LICENSE not specified" if not exists $params{LICENSE}; if ($params{BUILD_REQUIRES} and $eumm_version < 6.5503) { #EUMM 6.5502 has problems with BUILD_REQUIRES $params{PREREQ_PM}={ %{$params{PREREQ_PM} || {}} , %{$params{BUILD_REQUIRES}} }; delete $params{BUILD_REQUIRES}; } delete $params{TEST_REQUIRES} if $eumm_version < 6.64; delete $params{CONFIGURE_REQUIRES} if $eumm_version < 6.52; delete $params{MIN_PERL_VERSION} if $eumm_version < 6.48; delete $params{META_MERGE} if $eumm_version < 6.46; delete $params{META_ADD} if $eumm_version < 6.46; delete $params{LICENSE} if $eumm_version < 6.31; delete $params{NO_MYMETA} if $eumm_version < 6.58; delete $params{AUTHOR} if $] < 5.005; delete $params{ABSTRACT_FROM} if $] < 5.005; delete $params{BINARY_LOCATION} if $] < 5.005; WriteMakefile(%params); } sub get_uuidpm_version { my $fn = 'lib/UUID.pm'; open my $fh, '<', $fn or die "open: $fn: $!"; while (<$fh>) { # $VERSION = '0.30_02'; return $1 if /^\$VERSION = '([\d\.\_]+)';/; } return undef; } sub check_flags { my $defs = []; my $libs = []; my $long = 0; for my $check ( 1, 0 ) { # this is to turn off the copious amount of spewage seen compiling # xs code on freebsd. # WISHLIST: would be nice if we could inspect the compiler output # from building the test file. would like to see if there was a # "unsupported command line option" warning. looks like it would # be a good bit of work though. try_compound($check, \$long, $defs, '-Wno-compound-token-split-by-macro'); # -ladvapi is needed for win32 random numbers. #try_advapi($check, \$long, $libs, '-ladvapi'); # -lbcrypt is needed for win32 random numbers. try_bcrypt($check, \$long, $libs, '-lbcrypt'); # -liphlpapi is needed for win32 real node discovery. try_iphlpapi($check, \$long, $libs, '-liphlpapi'); # -lkernel32 needed for win32 CriticalSection / SRWLocks. try_kernel32($check, \$long, $libs, '-lkernel32'); # -lsynchronization needed to WaitOnAddress(). #try_synchronization($check, \$long, $libs, '-lsynchronization'); # -lpthread is needed for sem ops. older perls dont link it unless -Dthreads. try_pthread($check, \$long, $libs, '-lpthread'); #... more ? } return join(' ', @$libs), join(' ', @$defs); } sub check_threads { # return true/false $Config{useithreads} ? 1 : 0; } sub try_compound { my ($check, $long, $flags, $try) = @_; my $msg = join ' ', 'Checking compound token switch'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ( check_lib( lib => 'c', # always do at least this ccflags => $try, debug => 0, )) { push @$flags, $try; print "found\n"; } else { print "none\n"; } } sub try_advapi { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib advapi'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. #my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; #my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; #my $is_native = $is_win32 && $is_nmake ? 1 : 0; #if ( $is_native && check_lib( if ( check_lib( lib => 'c', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } sub try_bcrypt { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib bcrypt'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. #my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; #my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; #my $is_native = $is_win32 && $is_nmake ? 1 : 0; #if ( $is_native && check_lib( if ( check_lib( lib => 'bcrypt', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } sub try_iphlpapi { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib iphlpapi'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; my $is_native = $is_win32 && $is_nmake ? 1 : 0; if ( $is_native && check_lib( lib => 'iphlpapi', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } sub try_kernel32 { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib kernel32'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. #my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; #my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; #my $is_native = $is_win32 && $is_nmake ? 1 : 0; if ( check_lib( lib => 'kernel32', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } sub try_synchronization { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib synchronization'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. #my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; #my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; #my $is_native = $is_win32 && $is_nmake ? 1 : 0; if ( check_lib( lib => 'synchronization', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } sub try_pthread { my ($check, $long, $libs, $try) = @_; my $msg = join ' ', 'Checking for lib pthread'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; # dont link unless its a native build. #my $is_win32 = $^O eq 'MSWin32' ? 1 : 0; #my $is_nmake = $Config{make} eq 'nmake' ? 1 : 0; #my $is_native = $is_win32 && $is_nmake ? 1 : 0; if ( check_lib( lib => 'pthread', debug => 0, )) { push @$libs, $try; print "found\n"; } else { print "none\n"; } } package MY; use Config; # # add 'compare' target. # sub top_targets { my $t = shift->SUPER::top_targets(@_); # add 'compare' targets. $t .= "\npersist : dynamic pure_all\n"; $t .= "\t\$(NOECHO) \$(ABSPERLRUN) ubin\$(DFSEP)cmp_persist.pl 2\n"; $t .= "\n"; $t .= "\nspeeds : dynamic pure_all\n"; $t .= "\t\$(NOECHO) \$(ABSPERLRUN) ubin\$(DFSEP)cmp_speeds.pl 2\n"; $t .= "\n"; $t .= "\nstyles : dynamic pure_all\n"; $t .= "\t\$(NOECHO) \$(ABSPERLRUN) ubin\$(DFSEP)cmp_styles.pl 2\n"; $t .= "\n"; $t .= "\ncompare : speeds styles persist\n"; $t .= "\t\$(NOECHO) \$(NOOP)"; # remove blibdirs from config prereq. $t =~ s{^(config\s*::.*)\s+blibdirs} {$1}m; # change pure_all prereqs $t =~ s{^(pure_all\s*::\s*).*$} {$1 config blibdirs dynamic bootstrap uu_to_blib}m; $t; } # # add distlicense and distreadme prereqs. ## silence manicopy step during config. # sub distdir { my $t = shift->SUPER::distdir(@_); $t =~ s{^(distdir :).*$}{$1 create_distdir license metafile readme distlicense distmeta distreadme}m; #$t =~ s{PERLRUN}{NOECHO) \$(PERLRUN}; $t; } # # remove metafile comments in manifest. # make metafiles authoritative to cpan. # sub distmeta { my $t = <<'EOS'; distmeta : create_distdir license metafile readme $(NOECHO) $(ECHO) Adding META.json to MANIFEST $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd \ -e "die 'No META.json' unless -f 'META.json';" \ -e "die 'No MANIFEST' unless -f 'MANIFEST';" \ -e "eval { maniadd({ 'META.json' => '' }) }" \ -e " or die \"Could not add META.json to MANIFEST: $$ @\"" -- $(NOECHO) $(ECHO) Adding META.yml to MANIFEST $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd \ -e "die 'No META.yml' unless -f 'META.yml';" \ -e "die 'No MANIFEST' unless -f 'MANIFEST';" \ -e "eval { maniadd({ 'META.yml' => '' }) }" \ -e " or die \"Could not add META.yml to MANIFEST: $$ @\"" -- EOS $t; } # # re-order meta generation # sub metafile { my $t = shift->SUPER::metafile_target(@_); $t =~ s{^(metafile :.*)$} {$1 meta_json meta_yml}m; $t =~ s{^(\s+.+Generating META.yml.*)$} {\nmeta_yml :\n$1}m; $t =~ s{^(\s+.+Generating META.json.*)$} {\nmeta_json :\n$1}m; $t; } # # add UUID_DISTTEST flag to 'make disttest' # sub dist_test { my $t = shift->SUPER::dist_test(@_); $t =~ s{ test }{ test UUID_DISTTEST=1 }; $t; } # # make TEST_VERBOSE=1 when AUTOMATED_TESTING=1. # add t/*/*.t to tests. # add TEST_LIB variable, set to t/lib. # insert TEST_LIB before other libs. # add USE_ITHREADS to test environment. # sub test { my $t = shift->SUPER::test(@_); # # make TEST_VERBOSE=1 when AUTOMATED_TESTING=1. if ( $ENV{AUTOMATED_TESTING} or $ENV{NONINTERACTIVE_TESTING} or $ENV{PERL_CPAN_REPORTER_CONFIG} ) { $t =~ s{TEST_VERBOSE\s*=\s*0}{TEST_VERBOSE = 1}msg; } # # add t/*/*.t to tests. $t =~ s{^(TEST_FILES\s*=\s*).+$} {${1}t\$(DFSEP)*.t t\$(DFSEP)*\$(DFSEP)*.t}m; # # add TEST_LIB variable, set to t/0LIB. $t =~ s{^} {TEST_LIB = t\$(DFSEP)0LIB\n}s; # # insert TEST_LIB before other libs. $t =~ s{(\S+)(INST_LIB)(\S+)} {${1}TEST_LIB$3 $1$2$3}g; # add USE_ITHREADS to test env. my $use_ithreads = $Config{useithreads} ? 'USE_ITHREADS=1' : 'USE_ITHREADS=0'; my $is_nmake = $Config{make} eq 'nmake'; my $is_gmake = $Config{make} eq 'gmake'; my $is_dmake = $Config{make} eq 'dmake'; if ($is_nmake) { $t =~ s{^(test_dynamic\s*:.+)$} {$1\n\t\@set $use_ithreads}m; } elsif ($is_gmake or $is_dmake) { $t =~ s{^(\s+)(\$\(FULLPERLRUN)} {${1}set $use_ithreads && $2}mg; } else { $t =~ s{^} {TEST_ENV = $use_ithreads\n}s; $t =~ s{^(.*PERL_DL_NONLAZY=\S+\s+)} {$1\$(TEST_ENV) }mg; } $t; } # # silence "cp_nonempty" bootstrap. # silence chmod bootstrap. # remove implicit rules and make our own! # (some seem to use the implicits first?) # move initial .bs file into lib # sub xs_c { '' } sub xs_o { '' } sub dynamic_bs { my $t = shift->SUPER::dynamic_bs(@_); # add bootstrap target after first newline $t =~ s{$} {\n\nbootstrap : \$(lib_UUID).bs\n\t\$(NOECHO) \$(NOOP)}m; # delay Mkbootstrap() until after c files $t =~ s{^(\S+BASEEXT\S+\s*:\s+.+$)} {$1 \$(O_FILES)}m; # silence chmod $t =~ s{CHMOD} {NOECHO) \$(CHMOD}sg; # move initial to lib (5 changes) $t =~ s{ \$\(BASEEXT\)\.bs } { \$(lib_UUID).bs }g; # 2 changes $t =~ s{"\$\(BASEEXT\)\.bs"} {"\$(lib_UUID).bs"}g; # 2 changes $t =~ s{^\$\(BASEEXT\)\.bs} {\$(lib_UUID).bs}m; # 1 change # change BOOTSTRAP var $t =~ s{^BOOTSTRAP\s*=\s*\S+} {BOOTSTRAP = \$(lib_UUID).bs}; $t; } sub perldepend { my $t = shift->SUPER::perldepend(@_); # add target to run xsubpp $t .= "\n"; $t .= '$(lib_UUID).c : $(XSUBPPDEPS) $(lib_UUID).xs $(ulib_EUMM).h'. "\n"; $t .= "\t". '$(XSUBPPRUN) $(XSPROTOARG) $(XSUBPPARGS) $(XSUBPP_EXTRA_ARGS) $(lib_UUID).xs > $(lib_UUID).xsc'. "\n"; $t .= "\t". '$(MV) $(lib_UUID).xsc $(lib_UUID).c'; $t; } sub blibdirs { my $t = shift->SUPER::blibdirs_target(); # add EUMM.h as prereq to blibdirs. $t =~ s{^(blibdirs\s*:\s*)(\S.*)$} {$1\$(ulib_EUMM).h $2}m; $t; } # # remove targets in dynamic_lib section. we do them manually later. # sub dynamic_lib { my $t = shift->SUPER::dynamic_lib(@_); $t =~ s{\n\n.+$} {\n}ms; $t; } # # remove most prereqs from dynamic. # sub dynamic { my $t = shift->SUPER::dynamic(@_); # remove most prereqs from dynamic. $t =~ s{^(dynamic\s*::)\s+\S+\s+\S+\s+\S+\s+(\S+)\s*$} {$1 $2}m; $t; } # # adjust dlsyms (only on win32) # sub dlsyms { my $t = shift->SUPER::dlsyms(@_); $t =~ s{^UUID.def} {\$(lib_UUID).def}m; $t =~ s{,} {, 'FILE' => 'lib/\$(BASEEXT)',}; $t; } # # our variables. # also add ulib/EUMM.h as prereq for pm_to_blib. # change EXPORT_LIST. # sub constants { my $t = shift->SUPER::constants(@_); my $v = <<'EOPC'; lib_UUID = lib$(DFSEP)UUID ubin_configure = ubin$(DFSEP)configure.pl ulib_EUMM = ulib$(DFSEP)EUMM ulib_FUTX = ulib$(FDSEP)FUTX ulib_TYPE = ulib$(DFSEP)TYPE ulib_UMTX = ulib$(DFSEP)UMTX ulib_UUID = ulib$(DFSEP)UUID ulib_atomic = ulib$(DFSEP)atomic ulib_chacha = ulib$(DFSEP)chacha ulib_clock = ulib$(DFSEP)clock ulib_compare = ulib$(DFSEP)compare ulib_gen = ulib$(DFSEP)gen ulib_gettime = ulib$(DFSEP)gettime ulib_hash = ulib$(DFSEP)hash ulib_node = ulib$(DFSEP)node ulib_pack = ulib$(DFSEP)pack ulib_parse = ulib$(DFSEP)parse ulib_splitmix = ulib$(DFSEP)splitmix ulib_sysrand = ulib$(DFSEP)sysrand ulib_util = ulib$(DFSEP)util ulib_xoshiro = ulib$(DFSEP)xoshiro EOPC # also add ulib/EUMM.h as prereq for pm_to_blib. # terrible hack due to MY::pm_to_blib() never called. $t =~ s{^(TO_INST_PM.+)$} {$v\n$1}m; #$t =~ s{^(TO_INST_PM.+)$} {$v\n$1 \$(ulib_EUMM).h}m; # change EXPORT_LIST. if empty, leave it alone. # otherwise change to lib/UUID. $t =~ s{^(EXPORT_LIST\s*= *)\S+([\r\n]+)} {$1\$(lib_UUID).def$2}m; $t; } # # add distlicense and distreadme targets. # add autoconf generated targets. # add explicit object rules. # sub postamble { my $pa = <<'EOP'; # Software::License requires perl-5.12.0 license: create_distdir $(NOECHO) $(ECHO) Generating LICENSE $(NOECHO) $(RM_F) LICENSE_new $(NOECHO) $(ABSPERLRUN) -M5.12.0 -MSoftware::License::Artistic_2_0 \ -e 'print Software::License::Artistic_2_0->new({holder => "Rick Myers", year => sprintf("2014-%04d", 1900+(localtime(time))[5])})->fulltext' \ > LICENSE_new $(NOECHO) $(MV) LICENSE_new $(DISTVNAME)$(DFSEP)LICENSE distlicense: create_distdir license $(NOECHO) $(ECHO) Adding LICENSE to MANIFEST $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd \ -e "die 'No LICENSE' unless -f 'LICENSE';" \ -e "die 'No MANIFEST' unless -f 'MANIFEST';" \ -e "eval { maniadd({ 'LICENSE' => '' }) }" \ -e " or die \"Could not add LICENSE to MANIFEST: $$ @\"" -- $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -e "print sort <>" MANIFEST > MANIFEST_new $(NOECHO) $(MV) $(DISTVNAME)$(DFSEP)MANIFEST_new $(DISTVNAME)$(DFSEP)MANIFEST readme: create_distdir $(NOECHO) $(ECHO) Generating README $(NOECHO) $(RM_F) README_new $(NOECHO) pod2text $(lib_UUID).pm README_new $(NOECHO) $(ABSPERLRUN) -i -pe's{\*(\S+)\*}{\1}g' README_new $(NOECHO) $(MV) README_new $(DISTVNAME)$(DFSEP)README distreadme: create_distdir readme $(NOECHO) $(ECHO) Adding README to MANIFEST $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -MExtUtils::Manifest=maniadd \ -e "die 'No README' unless -f 'README';" \ -e "die 'No MANIFEST' unless -f 'MANIFEST';" \ -e "eval { maniadd({ 'README' => '' }) }" \ -e " or die \"Could not add README to MANIFEST: $$ @\"" -- $(NOECHO) cd $(DISTVNAME) && $(ABSPERLRUN) -e "print sort <>" MANIFEST > MANIFEST_new $(NOECHO) $(MV) $(DISTVNAME)$(DFSEP)MANIFEST_new $(DISTVNAME)$(DFSEP)MANIFEST config :: $(ubin_configure) $(ulib_EUMM).h $(NOECHO) $(NOOP) uu_to_blib : $(lib_UUID).pm $(lib_UUID).bs $(CP) $(lib_UUID).pm $(INST_LIB)$(DFSEP)UUID.pm $(NOECHO) $(CHMOD) $(PERM_RW) $(INST_LIB)$(DFSEP)UUID.pm $(NOECHO) $(TOUCH) uu_to_blib deps = $(XSUBPPDEPS) $(ulib_EUMM).h cccmd = $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) $(ulib_EUMM).h : $(FIRST_MAKEFILE) $(ubin_configure) $(NOECHO) $(ECHO) Generating EUMM.h $(NOECHO) $(RM_F) $(ulib_EUMM).h $(ulib_EUMM).h.tmp $(NOECHO) $(PERL) $(ubin_configure) $(ulib_EUMM).h.tmp $(NOECHO) $(MV) $(ulib_EUMM).h.tmp $(ulib_EUMM).h atomic_deps = \ ulib/arch/arm/atomic.c \ ulib/arch/x86/atomic.c $(lib_UUID).obj : $(deps) $(lib_UUID).c $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_atomic).obj : $(deps) $(ulib_atomic).c $(ulib_atomic).h $(atomic_deps) $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_chacha).obj : $(deps) $(ulib_chacha).c $(ulib_chacha).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_clock).obj : $(deps) $(ulib_clock).c $(ulib_clock).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_compare).obj : $(deps) $(ulib_compare).c $(ulib_compare).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_gen).obj : $(deps) $(ulib_gen).c $(ulib_gen).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_gettime).obj : $(deps) $(ulib_gettime).c $(ulib_gettime).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_hash).obj : $(deps) $(ulib_hash).c $(ulib_hash).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_node).obj : $(deps) $(ulib_node).c $(ulib_node).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_pack).obj : $(deps) $(ulib_pack).c $(ulib_pack).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_parse).obj : $(deps) $(ulib_parse).c $(ulib_parse).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_splitmix).obj : $(deps) $(ulib_splitmix).c $(ulib_splitmix).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_sysrand).obj : $(deps) $(ulib_sysrand).c $(ulib_sysrand).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_util).obj : $(deps) $(ulib_util).c $(ulib_util).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(ulib_xoshiro).obj : $(deps) $(ulib_xoshiro).c $(ulib_xoshiro).h $(CCCMD) $(CCCDLFLAGS) "-I$(PERL_INC)" $(PASTHRU_DEFINE) $(DEFINE) -Fd$(*).pdb -Fo$(*).obj $*.c $(lib_UUID).o : $(deps) $(lib_UUID).c $(cccmd) $(lib_UUID).c -o $(lib_UUID).o $(ulib_atomic).o : $(deps) $(ulib_atomic).c $(ulib_atomic).h $(atomic_deps) $(cccmd) $(ulib_atomic).c -o $(ulib_atomic).o $(ulib_chacha).o : $(deps) $(ulib_chacha).c $(ulib_chacha).h $(cccmd) $(ulib_chacha).c -o $(ulib_chacha).o $(ulib_clock).o : $(deps) $(ulib_clock).c $(ulib_clock).h $(cccmd) $(ulib_clock).c -o $(ulib_clock).o $(ulib_compare).o : $(deps) $(ulib_compare).c $(ulib_compare).h $(cccmd) $(ulib_compare).c -o $(ulib_compare).o $(ulib_gen).o : $(deps) $(ulib_gen).c $(ulib_gen).h $(cccmd) $(ulib_gen).c -o $(ulib_gen).o $(ulib_gettime).o : $(deps) $(ulib_gettime).c $(ulib_gettime).h $(cccmd) $(ulib_gettime).c -o $(ulib_gettime).o $(ulib_hash).o : $(deps) $(ulib_hash).c $(ulib_hash).h $(cccmd) $(ulib_hash).c -o $(ulib_hash).o $(ulib_node).o : $(deps) $(ulib_node).c $(ulib_node).h $(cccmd) $(ulib_node).c -o $(ulib_node).o $(ulib_pack).o : $(deps) $(ulib_pack).c $(ulib_pack).h $(cccmd) $(ulib_pack).c -o $(ulib_pack).o $(ulib_parse).o : $(deps) $(ulib_parse).c $(ulib_parse).h $(cccmd) $(ulib_parse).c -o $(ulib_parse).o $(ulib_splitmix).o : $(deps) $(ulib_splitmix).c $(ulib_splitmix).h $(cccmd) $(ulib_splitmix).c -o $(ulib_splitmix).o $(ulib_sysrand).o : $(deps) $(ulib_sysrand).c $(ulib_sysrand).h $(cccmd) $(ulib_sysrand).c -o $(ulib_sysrand).o $(ulib_util).o : $(deps) $(ulib_util).c $(ulib_util).h $(cccmd) $(ulib_util).c -o $(ulib_util).o $(ulib_xoshiro).o : $(deps) $(ulib_xoshiro).c $(ulib_xoshiro).h $(cccmd) $(ulib_xoshiro).c -o $(ulib_xoshiro).o EOP if ($Config{make} eq 'nmake') { $pa .= <<'EOP'; $(INST_DYNAMIC) : \ lib/UUID.obj \ ulib/atomic.obj \ ulib/chacha.obj \ ulib/clock.obj \ ulib/compare.obj \ ulib/gen.obj \ ulib/gettime.obj \ ulib/hash.obj \ ulib/node.obj \ ulib/pack.obj \ ulib/parse.obj \ ulib/splitmix.obj \ ulib/sysrand.obj \ ulib/util.obj \ ulib/xoshiro.obj \ $(INST_ARCHAUTODIR)$(DFSEP).exists $(EXPORT_LIST) \ $(PERL_ARCHIVEDEP) $(INST_DYNAMIC_DEP) $(LD) -out:$@ $(LDDLFLAGS) \ lib/UUID.obj \ ulib/atomic.obj \ ulib/chacha.obj \ ulib/clock.obj \ ulib/compare.obj \ ulib/gen.obj \ ulib/gettime.obj \ ulib/hash.obj \ ulib/node.obj \ ulib/pack.obj \ ulib/parse.obj \ ulib/splitmix.obj \ ulib/sysrand.obj \ ulib/util.obj \ ulib/xoshiro.obj \ $(OTHERLDFLAGS) $(MYEXTLIB) "$(PERL_ARCHIVE)" $(LDLOADLIBS) \ -def:$(EXPORT_LIST) if exist $@.manifest mt -nologo -manifest $@.manifest -outputresource:$@;2 if exist $@.manifest del $@.manifest $(CHMOD) $(PERM_RWX) $@ EOP } else { $pa .= <<'EOP'; $(INST_DYNAMIC) : $(OBJECT) $(MYEXTLIB) $(INST_ARCHAUTODIR)$(DFSEP).exists \ $(EXPORT_LIST) $(PERL_ARCHIVEDEP) $(PERL_ARCHIVE_AFTER) $(INST_DYNAMIC_DEP) $(RM_F) $@ $(LD) $(LDDLFLAGS) $(LDFROM) $(OTHERLDFLAGS) -o $@ $(MYEXTLIB) $(PERL_ARCHIVE) $(LDLOADLIBS) $(PERL_ARCHIVE_AFTER) $(EXPORT_LIST) $(INST_DYNAMIC_FIX) $(NOECHO) $(CHMOD) $(PERM_RWX) $@ EOP } return $pa; } UUID-0.38/ubin/0000755000175000017500000000000015201361067011304 5ustar rikrikUUID-0.38/ubin/cmp_persist.pl0000644000175000017500000000450415175756704014214 0ustar rikrik # seconds per test my $seconds = $ARGV[0] || 2; #------------------------------------------------------------------------------ use blib; use strict; use warnings; use File::Temp (); use Benchmark qw(:hireswallclock cmpthese countit); use UUID qw( generate_v1 generate_v3 generate_v4 generate_v5 generate_v6 generate_v7 uuid1 uuid3 uuid4 uuid5 uuid6 uuid7 unparse ); use vars qw($tmpdir $fname); BEGIN { $tmpdir = File::Temp->newdir(CLEANUP => 0); $fname = File::Temp::tempnam($tmpdir, 'UUID.test.'); } END { unlink $fname if defined $fname; rmdir $tmpdir if defined $tmpdir; } # call END block on ^C $SIG{INT} = sub { exit 0 }; print "\ncomparing persist...\n\n"; UUID::_persist(undef); my $t0 = countit($seconds, 'my $s = uuid1()'); UUID::_persist($fname); my $t1 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.0000001); my $t2 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.000001); my $t3 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.00001); my $t4 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.0001); my $t5 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.001); my $t6 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.01); my $t7 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(0.1); my $t8 = countit($seconds, 'my $s = uuid1()'); UUID::_defer(1.0); my $t9 = countit($seconds, 'my $s = uuid1()'); my $r = cmpthese({ 'case0' => $t0, 'case1' => $t1, 'case2' => $t2, 'case3' => $t3, 'case4' => $t4, 'case5' => $t5, 'case6' => $t6, 'case7' => $t7, 'case8' => $t8, 'case9' => $t9, }, 'none'); printf("%9s %11s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", @$_) for @$r; print <<'EOT'; case0 -> no persist; eval 'my $s = uuid1()' case1 -> persistent; eval 'my $s = uuid1()' # undeferred case2 -> persistent; eval 'my $s = uuid1()' # deferred 100ns case3 -> persistent; eval 'my $s = uuid1()' # deferred 1us case4 -> persistent; eval 'my $s = uuid1()' # deferred 10us case5 -> persistent; eval 'my $s = uuid1()' # deferred 100us case6 -> persistent; eval 'my $s = uuid1()' # deferred 1ms case7 -> persistent; eval 'my $s = uuid1()' # deferred 10ms case8 -> persistent; eval 'my $s = uuid1()' # deferred 100ms case9 -> persistent; eval 'my $s = uuid1()' # deferred 1s EOT exit 0; UUID-0.38/ubin/cmp_styles.pl0000644000175000017500000000250215171603645014031 0ustar rikrik # seconds per test my $seconds = $ARGV[0] || 2; #------------------------------------------------------------------------------ use blib; use strict; use warnings; use Benchmark qw(:hireswallclock cmpthese countit); use UUID qw( generate_v1 generate_v3 generate_v4 generate_v5 generate_v6 generate_v7 uuid1 uuid3 uuid4 uuid5 uuid6 uuid7 unparse ); print "\ncomparing calling styles...\n\n"; my $r = cmpthese({ 'case1' => countit(2*$seconds, 'my $s = uuid1()'), 'case2' => countit(2*$seconds, 'my $s = UUID::uuid1()'), 'case3' => countit(2*$seconds, 'generate_v1(my $b); unparse($b, my $s)'), 'case4' => countit(2*$seconds, 'UUID::generate_v1(my $b); UUID::unparse($b, my $s)'), 'case5' => countit(2*$seconds, 'my($b,$s); generate_v1($b); unparse($b,$s)'), 'case6' => countit(2*$seconds, 'my($b,$s); UUID::generate_v1($b); UUID::unparse($b,$s)'), }, 'none'); printf("%9s %11s %6s %6s %6s %6s %6s %6s\n", @$_) for @$r; print <<'EOT'; case1 -> eval 'my $s = uuid1()' case2 -> eval 'my $s = UUID::uuid1()' case3 -> eval 'generate_v1(my $b); unparse($b, my $s)' case4 -> eval 'UUID::generate_v1(my $b); UUID::unparse($b, my $s)' case5 -> eval 'my($b,$s); generate_v1($b); unparse($b,$s)' case6 -> eval 'my($b,$s); UUID::generate_v1($b); UUID::unparse($b,$s)' EOT exit 0; UUID-0.38/ubin/configure.pl0000644000175000017500000005511615177010206013630 0ustar rikrik# # check a bunch of stuff. # write #define/#undef to file given in ARGV[0]. # now also writes #include's too. # use strict; use warnings; use Config; use File::Spec (); use File::Temp (); use Devel::CheckLib; select STDERR; $|=1; select STDOUT; $|=1; my ($out, $flagfile) = @ARGV; my $conf = []; my $flags = []; my $WIN32 = 0; # native # set this once a working random found my $RANDFOUND = 0; # try to make all temp files here my $TMPDIR = File::Temp->newdir('UUID-conf-XXXXXXXX', TMPDIR => 1, CLEANUP => 0); generate_conf($conf, $flags); write_conf ($conf, $out); #unlink($_) for ; my $tmpglob = File::Spec->catfile( $TMPDIR, 'assert*' ); unlink($_) for <"$tmpglob">; rmdir $TMPDIR; exit 0; sub generate_conf { my ($defines, $flags) = @_; my $longest = 0; # if lencheck is 1, \$longest is longest so far. sub is expected to # update it if it has one longer and skip actual test. # # if lencheck is 0, \$longest contains global longest. sub is expected # to use that when printing and to run the test. for my $check ( 1, 0 ) { # win32 native if on windows but not under some # sort of unix environ. i.e. native. # sets $WIN32. do this first. my $platform = try_platform($check, \$longest, $defines); # NOTE: winsock2.h must precede Windows.h, # at least for Cygwin. try_headers($check, \$longest, $defines, $platform, q( # # format: # SYMBOL FILE [PLATFORM [PLATFORM [...]]] # # if FILE is found SYMBOL will be defined and # the header included in EUMM.h. # # if one or more PLATFORMs are listed, one must # match that returned from try_platform() or the # check is skipped. # # if no platforms are listed, the header is tried # on every platform. # # invalid platforms are ignored but, if it is the # only platform for a symbol, the file will not # be checked. # # valid platforms: alien, cygwin, native, unix. # (alien = Strawberry) # # comments and blank lines allowed. # HAVE_WINSOCK2_H winsock2.h native skip HAVE_WINDOWS_H Windows.h alien cygwin native skip HAVE_IPHLPAPI_H iphlpapi.h native skip HAVE_BCRYPT_H bcrypt.h alien native skip #------------------------------------------------------------------------- HAVE_CTYPE_H ctype.h alien native unix skip HAVE_DISPATCH_DISPATCH_H dispatch/dispatch.h unix skip HAVE_ERR_H err.h unix skip HAVE_ERRNO_H errno.h alien native unix skip #------------------------------------------------------------------------- HAVE_FCNTL_H fcntl.h alien native unix skip HAVE_INTTYPES_H inttypes.h alien native unix skip HAVE_IO_H io.h alien native skip HAVE_MEMORYAPI_H memoryapi.h alien native skip #------------------------------------------------------------------------- HAVE_NETINET_IN_H netinet/in.h unix skip HAVE_NET_IF_DL_H net/if_dl.h unix skip HAVE_NET_IF_H net/if.h unix skip HAVE_PROCESS_H process.h alien native skip #------------------------------------------------------------------------- #HAVE_PTHREAD_H pthread.h alien unix skip HAVE_SEMAPHORE_H semaphore.h cygwin unix skip HAVE_STDINT_H stdint.h alien native unix skip HAVE_STDIO_H stdio.h alien native unix skip #------------------------------------------------------------------------- HAVE_STDLIB_H stdlib.h alien native unix skip HAVE_STRING_H string.h alien native unix skip HAVE_SYS_FILE_H sys/file.h alien unix skip HAVE_SYS_FUTEX_H sys/futex.h unix skip #------------------------------------------------------------------------- HAVE_SYS_IOCTL_H sys/ioctl.h unix skip HAVE_SYS_MMAN_H sys/mman.h cygwin unix skip HAVE_SYS_RANDOM_H sys/random.h cygwin unix skip HAVE_SYS_RESOURCE_H sys/resource.h unix skip #------------------------------------------------------------------------- HAVE_SYS_SOCKET_H sys/socket.h unix skip HAVE_SYS_SOCKIO_H sys/sockio.h unix skip HAVE_SYS_STAT_H sys/stat.h alien native unix skip HAVE_SYS_TIME_H sys/time.h alien unix skip #------------------------------------------------------------------------- HAVE_SYS_TYPES_H sys/types.h alien native unix skip HAVE_SYS_WAIT_H sys/wait.h unix skip HAVE_TIME_H time.h alien native unix skip HAVE_UNISTD_H unistd.h alien unix skip #------------------------------------------------------------------------- HAVE_WINCRYPT_H wincrypt.h alien native skip )); try_arc4random ($check, \$longest, $defines, $platform); try_BCryptGenRandom ($check, \$longest, $defines, $platform); try_CryptGenRandom ($check, \$longest, $defines, $platform); try_getentropy ($check, \$longest, $defines, $platform); try_getrandom ($check, \$longest, $defines, $platform); #try_gettimeofday ($check, \$longest, $defines, $platform); try_lstat ($check, \$longest, $defines, $platform); try_sa_len ($check, \$longest, $defines, $platform); try_srwlock ($check, \$longest, $defines, $platform); try_symlink ($check, \$longest, $defines, $platform); #try_threads ($check, \$longest, $defines, $platform); } } sub try_headers { my ($check, $long, $defines, $platform, $block) = @_; my @lines = split /\n/, $block; for my $line ( @lines ) { chomp $line; $line =~ s/\s*\#.*$//; # strip comments and tail space $line =~ s/^\s+//; # strip lead space next if $line =~ /^\s*$/; # skip empty lines my ($symbol, $file, @more) = split /\s+/, $line; # platform match ? my $skip = 0; if (scalar @more) { $skip = 1; for (@more) { $skip=0 if $_ eq $platform } } check_header($check, $skip, $long, $defines, $symbol, $file); } } sub check_header { my ($check, $skip, $long, $defines, $symbol, $file) = @_; if ($skip) { return if $check; push @$defines, "#undef $symbol"; return; } my $msg = join ' ', 'Checking for', $file; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($skip) { print "skip\n"; push @$defines, "#undef $symbol"; return; } my ($conf, $fh) = gen_confh_fh($defines); print $fh join("\n", map {s/^\s+//; $_} split(/\n/, qq{ #include <${file}> })); close $fh; my $win32permit = 1; $win32permit = 0 if !$WIN32 && $symbol =~ /WINSOCK/; $win32permit = 0 if !$WIN32 && $symbol =~ /IPHLPAPI/; if ( $win32permit && check_lib( header => $conf, #lib => 'c', # because not linking here.. duh! ccflags => '-I.', debug => 0, )) { push @$defines, "#define $symbol 1"; push @$defines, "#include <${file}>"; print "found\n"; } else { push @$defines, "#undef $symbol"; print "none\n"; } unlink $conf; } sub gen_confh { my ($defs) = @_; my ($fh, $fname) = File::Temp::tempfile( 'assertconfXXXXXXXX', SUFFIX => '.h', DIR => $TMPDIR, UNLINK => 0 ); print $fh "$_\n" for @$defs; close $fh; return $fname; } sub gen_confh_fh { my ($defs) = @_; my ($fh, $fname) = File::Temp::tempfile( 'assertconfXXXXXXXX', SUFFIX => '.h', DIR => $TMPDIR, UNLINK => 0 ); print $fh "$_\n" for @$defs; return $fname, $fh; } sub try_arc4random { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for arc4random()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($RANDFOUND or $platform eq 'native') { push @$defs, '#undef HAVE_ARC4RANDOM'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'c', # always do at least this ccflags => '-I.', debug => 0, function => q{ unsigned char p[4]; int c = 4; arc4random_buf(&p, c); return 0; }, )) { push @$defs, '#define HAVE_ARC4RANDOM 1'; print "found\n"; $RANDFOUND = 1; } else { push @$defs, '#undef HAVE_ARC4RANDOM'; print "none\n"; } unlink $conf; } sub try_BCryptGenRandom { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for BCryptGenRandom()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($RANDFOUND or $platform eq 'unix') { push @$defs, '#undef HAVE_BCRYPTGENRANDOM'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'bcrypt', ccflags => '-I.', debug => 0, function => q{ unsigned char p[4]; int r, c = 4; r = BCryptGenRandom(NULL, p, c, BCRYPT_USE_SYSTEM_PREFERRED_RNG); return 0; (void)r; }, )) { push @$defs, '#define HAVE_BCRYPTGENRANDOM 1'; print "found\n"; $RANDFOUND = 1; } else { push @$defs, '#undef HAVE_BCRYPTGENRANDOM'; print "none\n"; } unlink $conf; } sub try_CryptGenRandom { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for CryptGenRandom()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($RANDFOUND or $platform eq 'unix') { push @$defs, '#undef HAVE_CRYPTGENRANDOM'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'crypto', ccflags => '-I.', debug => 0, function => q{ unsigned char p[4]; int r, c = 4; r = CryptGenRandom((HCRYPTPROV)NULL, c, p); return 0; (void)r; }, )) { push @$defs, '#define HAVE_CRYPTGENRANDOM 1'; print "found\n"; $RANDFOUND = 1; } else { push @$defs, '#undef HAVE_CRYPTGENRANDOM'; print "none\n"; } unlink $conf; } sub try_getentropy { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for getentropy()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($RANDFOUND or $platform eq 'native') { push @$defs, '#undef HAVE_GETENTROPY'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'c', # always do at least this ccflags => '-I.', debug => 0, function => q{ unsigned char p[4]; int r, c = 4; r = getentropy(&p, c); return 0; (void)r; }, )) { push @$defs, '#define HAVE_GETENTROPY 1'; print "found\n"; $RANDFOUND = 1; } else { push @$defs, '#undef HAVE_GETENTROPY'; print "none\n"; } unlink $conf; } sub try_getrandom { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for getrandom()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($RANDFOUND or $platform eq 'native') { push @$defs, '#undef HAVE_GETRANDOM'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'c', # always do at least this ccflags => '-I.', debug => 0, function => ' unsigned char p[4]; int r, c = 4; r = getrandom(c, &p, 0); return 0; (void)r; ', )) { push @$defs, '#define HAVE_GETRANDOM 1'; print "found\n"; $RANDFOUND = 1; } else { push @$defs, '#undef HAVE_GETRANDOM'; print "none\n"; } unlink $conf; } sub try_gettimeofday { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for gettimeofday()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'c', # always do at least this ccflags => '-I.', debug => 0, function => ' struct timeval tv; int r = gettimeofday(&tv, 0); return 0; (void)r; ', )) { push @$defs, '#define HAVE_GETTIMEOFDAY 1'; print "found\n"; } else { push @$defs, '#undef HAVE_GETTIMEOFDAY'; print "none\n"; } unlink $conf; } sub try_lstat { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for lstat()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; my $conf = gen_confh($defs); my $Werror = $WIN32 ? '-WX' : '-Werror'; my $lib = $WIN32 ? 'ucrt' : 'c'; if ( check_lib( header => $conf, lib => $lib, # always do at least this ccflags => "-I. $Werror", debug => 0, function => q{ struct stat buf; int rc, islink; rc = lstat("foo", &buf); islink = ((buf.st_mode & S_IFMT) == S_IFLNK); return 0; (void)rc; (void)islink; }, )) { push @$defs, '#define HAVE_LSTAT 1'; print "found\n"; } else { push @$defs, '#undef HAVE_LSTAT'; print "none\n"; } unlink $conf; } sub try_symlink { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for symlink()'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; my $conf = gen_confh($defs); my $link = File::Spec->catfile( $TMPDIR, 'assertlibSYMLINK.h' ); my $has_symlink = eval { symlink $conf, $link; return 1 if -l $link; return 0; }; my $Werror = $WIN32 ? '-WX' : '-Werror'; my $lib = $WIN32 ? 'ucrt' : 'c'; if ( check_lib( header => $conf, lib => $lib, # always do at least this ccflags => "-I. $Werror", debug => 0, function => qq{ struct stat buf; int rc; rc = lstat("$link", &buf); if ((buf.st_mode & S_IFMT) == S_IFLNK) return 0; return 1; (void)rc; }, )) { push @$defs, '#define HAVE_SYMLINK 1'; print "found\n"; } else { push @$defs, '#undef HAVE_SYMLINK'; print "none\n"; } unlink $conf, $link; } sub try_sa_len { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for sa_len member'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($platform ne 'unix') { push @$defs, '#undef HAVE_SA_LEN'; print "skip\n"; return; } my $conf = gen_confh($defs); if ( check_lib( header => $conf, lib => 'c', # always do at least this ccflags => '-I.', debug => 0, function => q{ struct ifreq ifr; unsigned char *r; r = (unsigned char*)&ifr.ifr_addr.sa_len; return 0; (void)r; }, )) { push @$defs, '#define HAVE_SA_LEN 1'; print "found\n"; } else { push @$defs, '#undef HAVE_SA_LEN'; print "none\n"; } unlink $conf; } sub try_srwlock { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for SRWLocks'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' '; if ($platform ne 'alien' && $platform ne 'native') { push @$defs, '#undef HAVE_SRWLOCK'; print "skip\n"; return; } my ($conf, $fh) = gen_confh_fh($defs); print $fh join("\n", map {s/^\s+//; $_} split(/\n/, qq{ typedef SRWLOCK uu_lock_t; typedef struct { uu_lock_t LOCK; } smem_t; static smem_t smem; #define UMTX_init InitializeSRWLock(&smem.LOCK) #define UMTX_lock AcquireSRWLockExclusive(&smem.LOCK) #define UMTX_unlock ReleaseSRWLockExclusive(&smem.LOCK) })); close $fh; if ( check_lib( header => $conf, lib => 'kernel32', # always do at least this ccflags => '-I.', debug => 0, function => q{ UMTX_init; UMTX_lock; UMTX_unlock; return 0; }, )) { push @$defs, '#define HAVE_SRWLOCK 1'; print "found\n"; } else { push @$defs, '#undef HAVE_SRWLOCK'; print "none\n"; } unlink $conf; } sub try_platform { my ($check, $long, $defs) = @_; my $msg = 'Checking platform'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long } my $more = $$long - $len; print $msg, ' ..', '.'x$more, ' ' unless $check; my $rv; my $iscygwin = $^O eq 'cygwin'; my $iswin32 = $^O eq 'MSWin32'; my $isnmake = $Config{make} eq 'nmake'; { if ( $iswin32 and $isnmake ) { $WIN32 = 1; $rv = 'native'; last if $check; push @$defs, '#define USE_WIN32_NATIVE 1'; push @$defs, '#undef USE_WIN32_ALIEN'; push @$defs, '#undef USE_WIN32_CYGWIN'; } elsif ( $iscygwin ) { $WIN32 = 0; $rv = 'cygwin'; last if $check; push @$defs, '#undef USE_WIN32_NATIVE'; push @$defs, '#undef USE_WIN32_ALIEN'; push @$defs, '#define USE_WIN32_CYGWIN 1'; } elsif ( $iswin32 ) { $rv = 'alien'; # strawberry last if $check; push @$defs, '#undef USE_WIN32_NATIVE'; push @$defs, '#define USE_WIN32_ALIEN 1'; push @$defs, '#undef USE_WIN32_CYGWIN'; } else { $WIN32 = 0; $rv = 'unix'; last if $check; push @$defs, '#undef USE_WIN32_NATIVE'; push @$defs, '#undef USE_WIN32_ALIEN'; push @$defs, '#undef USE_WIN32_CYGWIN'; } } print $rv, "\n" unless $check; return $rv; } sub try_threads { my ($check, $long, $defs, $platform) = @_; my $msg = 'Checking for thread storage'; my $len = length $msg; if ($check) { $$long = $len if $len > $$long; return; } my $more = $$long - $len; # can we skip this if not -Duseithreads ? my ($conf1, $fh1) = gen_confh_fh($defs); print $fh1 q{ int dec(void) { static __thread int foo = 3; return --foo; } }; close $fh1; my ($conf2, $fh2) = gen_confh_fh($defs); print $fh2 q{ int dec(void) { static __declspec(thread) int foo = 3; return --foo; } }; close $fh2; my $Werror = $WIN32 ? '-WX' : '-Werror'; my $lib = $WIN32 ? 'ucrt' : 'c'; if ( check_lib( header => $conf1, lib => $lib, # always do at least this ccflags => "-I. $Werror", debug => 0, function => q{ int rv; rv = dec(); rv = dec(); rv = dec(); return rv; }, )) { push @$defs, '#define TLS __thread'; print $msg, ' ..', '.'x$more, ' __thread'; } elsif ( check_lib( header => $conf2, lib => $lib, # always do at least this ccflags => "-I. $Werror", debug => 0, function => q{ int rv; rv = dec(); rv = dec(); rv = dec(); return rv; }, )) { push @$defs, '#define TLS __declspec(thread)'; print $msg, ' ..', '.'x$more, ' __declspec(thread)'; } else { push @$defs, '#undef TLS'; print $msg, ' ..', '.'x$more, ' none'; } unlink $conf1, $conf2; } sub write_conf { my ($defines, $outfile) = @_; open my $fh, '>', $outfile or die 'open: ', $outfile, ": $!"; print $fh "#ifndef ULIB__EUMM_H\n"; print $fh "#define ULIB__EUMM_H\n"; print $fh "$_\n" for @$defines; print $fh "#endif\n"; } UUID-0.38/ubin/cmp_speeds.pl0000644000175000017500000000354015171603645013774 0ustar rikrik # seconds per test my $seconds = $ARGV[0] || 2; #------------------------------------------------------------------------------ use blib; use strict; use warnings; use Benchmark qw(:hireswallclock cmpthese countit); use UUID qw( generate_v1 generate_v3 generate_v4 generate_v5 generate_v6 generate_v7 uuid1 uuid3 uuid4 uuid5 uuid6 uuid7 unparse ); print "\ncomparing version speeds...\n\n"; my $r = cmpthese({ 'v1bin' => countit($seconds, 'generate_v1(my $b)'), 'v1str' => countit($seconds, 'my $s = uuid1()'), 'v3bin' => countit($seconds, 'generate_v3(my $b, dns => q(www.example.com))'), 'v3str' => countit($seconds, 'my $s = uuid3(dns => q(www.example.com))'), 'v4bin' => countit($seconds, 'generate_v4(my $b)'), 'v4str' => countit($seconds, 'my $s = uuid4()'), 'v5bin' => countit($seconds, 'generate_v5(my $b, dns => q(www.example.com))'), 'v5str' => countit($seconds, 'my $s = uuid5(dns => q(www.example.com))'), 'v6bin' => countit($seconds, 'generate_v6(my $b)'), 'v6str' => countit($seconds, 'my $s = uuid6()'), 'v7bin' => countit($seconds, 'generate_v7(my $b)'), 'v7str' => countit($seconds, 'my $s = uuid7()'), }, 'none'); printf("%9s %11s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s %7s\n", @$_) for @$r; print <<'EOT'; v1bin -> eval 'generate_v1(my $b)' v3bin -> eval 'generate_v3(my $b, dns => q(www.example.com))' v4bin -> eval 'generate_v4(my $b)' v5bin -> eval 'generate_v5(my $b, dns => q(www.example.com))' v6bin -> eval 'generate_v6(my $b)' v7bin -> eval 'generate_v7(my $b)' v1str -> eval 'my $s = uuid1()' v3str -> eval 'my $s = uuid3(dns => q(www.example.com))' v4str -> eval 'my $s = uuid4()' v5str -> eval 'my $s = uuid5(dns => q(www.example.com))' v6str -> eval 'my $s = uuid6()' v7str -> eval 'my $s = uuid7()' EOT exit 0; UUID-0.38/ulib/0000755000175000017500000000000015201361067011302 5ustar rikrikUUID-0.38/ulib/splitmix.c0000644000175000017500000000175115176525526013340 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/splitmix.h" #include "ulib/gettime.h" #include "ulib/sysrand.h" #ifdef __cplusplus } #endif /* based on splitmix64 * https://xorshift.di.unimi.it/splitmix64.c */ void uu_splitmix_srand(pUCXT) { unsigned int n; UV ptod[2]; U64 sysrand; /* gettimeofday(&tv, 0); */ (*uu_gettime_U2time)(aTHX_ ptod); SMEM->sm_x = (U64)ptod[0] * 1000000 + (U64)ptod[1]; /* stir 16 - 31 times, time-based */ n = 16 + ((ptod[0] ^ ptod[1]) & 0x0f); while (n-- > 0) (void)uu_splitmix_rand(aUCXT); uu_sysrand_bytes(&sysrand, 8); SMEM->sm_x ^= sysrand; /* stir 16 - 31 times, rand-based */ n = 16 + (sysrand & 0x0f); while (n-- > 0) (void)uu_splitmix_rand(aUCXT); } U64 uu_splitmix_rand(pUCXT) { U64 z = (SMEM->sm_x += 0x9e3779b97f4a7c15ULL); z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9ULL; z = (z ^ (z >> 27)) * 0x94d049bb133111ebULL; return z ^ (z >> 31); } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/chacha.h0000644000175000017500000000046315176525526012702 0ustar rikrik#ifndef ULIB__CHACHA_H #define ULIB__CHACHA_H #include "ulib/UUID.h" void uu_chacha_srand(pUCXT); void uu_chacha_rand16(pUCXT, U16 *out); void uu_chacha_rand32(pUCXT, U32 *out); void uu_chacha_rand64(pUCXT, U64 *out); void uu_chacha_rand128(pUCXT, void *out); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/pack.h0000644000175000017500000000115115176655431012403 0ustar rikrik#ifndef ULIB__PACK_H #define ULIB__PACK_H #include "ulib/UUID.h" /* pack uuid struct into uu string, big-endian */ void uu_pack_v0(const struct_uu_t *in, uu_t out); void uu_pack_v1(const struct_uu_t *in, uu_t out); void uu_pack_v3(const struct_uu_t *in, uu_t out); void uu_pack_v4(const struct_uu_t *in, uu_t out); void uu_pack_v5(const struct_uu_t *in, uu_t out); void uu_pack_v6(const struct_uu_t *in, uu_t out); void uu_pack_v7(const struct_uu_t *in, uu_t out); /* unpack uu string, big-endian, to uuid struct */ void uu_pack_unpack(const uu_t in, struct_uu_t *out); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/UUID.h0000644000175000017500000000664115176655431012244 0ustar rikrik#ifndef ULIB__UUID_H #define ULIB__UUID_H /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable general extensions on macOS. */ #ifndef _DARWIN_C_SOURCE # undef _DARWIN_C_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable X/Open compliant socket functions that do not require linking with -lxnet on HP-UX 11.11. */ #ifndef _HPUX_ALT_XOPEN_SOCKET_API # undef _HPUX_ALT_XOPEN_SOCKET_API #endif /* Identify the host operating system as Minix. This macro does not affect the system headers' behavior. A future release of Autoconf may stop defining this macro. */ #ifndef _MINIX # undef _MINIX #endif /* Enable general extensions on NetBSD. Enable NetBSD compatibility extensions on Minix. */ #ifndef _NETBSD_SOURCE # undef _NETBSD_SOURCE #endif /* Enable OpenBSD compatibility extensions on NetBSD. Oddly enough, this does nothing on OpenBSD. */ #ifndef _OPENBSD_SOURCE # undef _OPENBSD_SOURCE #endif /* Define to 1 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_SOURCE # undef _POSIX_SOURCE #endif /* Define to 2 if needed for POSIX-compatible behavior. */ #ifndef _POSIX_1_SOURCE # undef _POSIX_1_SOURCE #endif /* Enable POSIX-compatible threading on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions specified by ISO/IEC TS 18661-5:2014. */ #ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ # undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-1:2014. */ #ifndef __STDC_WANT_IEC_60559_BFP_EXT__ # undef __STDC_WANT_IEC_60559_BFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-2:2015. */ #ifndef __STDC_WANT_IEC_60559_DFP_EXT__ # undef __STDC_WANT_IEC_60559_DFP_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-4:2015. */ #ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__ # undef __STDC_WANT_IEC_60559_FUNCS_EXT__ #endif /* Enable extensions specified by ISO/IEC TS 18661-3:2015. */ #ifndef __STDC_WANT_IEC_60559_TYPES_EXT__ # undef __STDC_WANT_IEC_60559_TYPES_EXT__ #endif /* Enable extensions specified by ISO/IEC TR 24731-2:2010. */ #ifndef __STDC_WANT_LIB_EXT2__ # undef __STDC_WANT_LIB_EXT2__ #endif /* Enable extensions specified by ISO/IEC 24747:2009. */ #ifndef __STDC_WANT_MATH_SPEC_FUNCS__ # undef __STDC_WANT_MATH_SPEC_FUNCS__ #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable X/Open extensions. Define to 500 only if necessary to make mbstate_t available. */ #ifndef _XOPEN_SOURCE # undef _XOPEN_SOURCE #endif #define PERL_NO_GET_CONTEXT #include "ulib/EUMM.h" #include "EXTERN.h" #include "perl.h" #include "ulib/TYPE.h" #define SMEM UCXT.shared #include "ulib/PORT.h" #include "ulib/UMTX.h" #ifdef SvPVbyte # if PERL_VERSION_EQ(5,6,1) /* SvPVbyte does not work in perl-5.6.1, borrowed version for 5.7.3 */ # undef SvPVbyte # define SvPVbyte(sv, lp) \ ((SvFLAGS(sv) & (SVf_POK|SVf_UTF8)) == (SVf_POK) \ ? ((lp = SvCUR(sv)), SvPVX(sv)) : my_sv_2pvbyte(aTHX_ sv, &lp)) static char * my_sv_2pvbyte(pTHX_ register SV *sv, STRLEN *lp) { sv_utf8_downgrade(sv,0); return SvPV(sv,*lp); } # endif #else # define SvPVbyte SvPV #endif #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/sysrand.h0000644000175000017500000000024315176525526013152 0ustar rikrik#ifndef ULIB__SYSRAND_H #define ULIB__SYSRAND_H #include "ulib/UUID.h" void uu_sysrand_bytes(void *buf, int nbytes); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/sysrand.c0000644000175000017500000000363015176525526013150 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/sysrand.h" #ifdef __cplusplus } #endif #ifndef WIN32 #ifndef USE_WIN32_NATIVE static int get_random_fd(void) { int i, fd = -2; if (fd == -2) { fd = open("/dev/urandom", O_RDONLY); if (fd == -1) fd = open("/dev/random", O_RDONLY | O_NONBLOCK); if (fd >= 0) { i = fcntl(fd, F_GETFD); if (i >= 0) fcntl(fd, F_SETFD, i | FD_CLOEXEC); } } return fd; } #endif #endif /* * Generate a series of random bytes. Use /dev/urandom if possible, * and if not, use srandom/random. */ void uu_sysrand_bytes(void *buf, int nbytes) { int i, n = nbytes, fd; int lose_counter = 0; unsigned char *cp = buf; (void)n; (void)fd; (void)lose_counter; #ifdef HAVE_ARC4RANDOM arc4random_buf(buf, nbytes); return; #endif #ifdef HAVE_BCRYPTGENRANDOM if (BCryptGenRandom(NULL, buf, nbytes, BCRYPT_USE_SYSTEM_PREFERRED_RNG) == 0) return; #endif #ifdef HAVE_CRYPTGENRANDOM { int ok = 0; HCRYPTPROV hCryptProv; if (CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) { ok = CryptGenRandom(hCryptProv, nbytes, buf); CryptReleaseContext(hCryptProv, 0); if (ok) return; } } #endif #ifdef HAVE_GETENTROPY if (getentropy(buf, nbytes) == 0) return; #endif #ifdef HAVE_GETRANDOM if (getrandom(buf, nbytes, 0) == nbytes) return; #endif #ifndef WIN32 #ifndef USE_WIN32_NATIVE fd = get_random_fd(); if (fd >= 0) { while (n > 0) { i = read(fd, cp, n); if (i <= 0) { if (lose_counter++ > 16) break; continue; } n -= i; cp += i; lose_counter = 0; } } #endif #endif /* * We do this anyway, but this is the only source of * randomness if /dev/random/urandom is out to lunch. */ for (cp = buf, i = 0; i < nbytes; i++) *cp++ ^= (rand() >> 7) & 0xFF; return; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/compare.c0000644000175000017500000000675315176655431013123 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/compare.h" #include "ulib/pack.h" #include "ulib/util.h" #ifdef __cplusplus } #endif #define UUCMP(u1,u2) if (u1 != u2) return((u1) > (u2) ? 1 : -1); IV uu_compare_struct0(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v0.low, us2->v0.low); UUCMP(us1->v0.high, us2->v0.high); return 0; } IV uu_compare_struct1(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v1.time_low, us2->v1.time_low); UUCMP(us1->v1.time_mid, us2->v1.time_mid); UUCMP(us1->v1.time_high_and_version, us2->v1.time_high_and_version); UUCMP(us1->v1.clock_seq_and_variant, us2->v1.clock_seq_and_variant); return memcmp(us1->v1.node, us2->v1.node, 6); } IV uu_compare_struct3(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v3.md5_high32, us2->v3.md5_high32); UUCMP(us1->v3.md5_high16, us2->v3.md5_high16); UUCMP(us1->v3.md5_mid_and_version, us2->v3.md5_mid_and_version); UUCMP(us1->v3.md5_low_and_variant, us2->v3.md5_low_and_variant); UUCMP(us1->v3.md5_low, us2->v3.md5_low); return 0; } IV uu_compare_struct4(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v4.rand_a, us2->v4.rand_a); UUCMP(us1->v4.rand_b_and_version, us2->v4.rand_b_and_version); UUCMP(us1->v4.rand_c_and_variant, us2->v4.rand_c_and_variant); UUCMP(us1->v4.rand_d, us2->v4.rand_d); return 0; } IV uu_compare_struct5(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v5.sha1_high32, us2->v5.sha1_high32); UUCMP(us1->v5.sha1_high16, us2->v5.sha1_high16); UUCMP(us1->v5.sha1_mid_and_version, us2->v5.sha1_mid_and_version); UUCMP(us1->v5.sha1_low_and_variant, us2->v5.sha1_low_and_variant); UUCMP(us1->v5.sha1_low, us2->v5.sha1_low); return 0; } IV uu_compare_struct6(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v6.time_high, us2->v6.time_high); UUCMP(us1->v6.time_mid, us2->v6.time_mid ); UUCMP(us1->v6.time_low_and_version, us2->v6.time_low_and_version ); UUCMP(us1->v6.clock_seq_and_variant, us2->v6.clock_seq_and_variant); return memcmp(us1->v6.node, us2->v6.node, 6); return 0; } IV uu_compare_struct7(const struct_uu_t *us1, const struct_uu_t *us2) { UUCMP(us1->v7.time_high, us2->v7.time_high); UUCMP(us1->v7.time_low, us2->v7.time_low ); UUCMP(us1->v7.rand_a_and_version, us2->v7.rand_a_and_version); UUCMP(us1->v7.rand_b_and_variant, us2->v7.rand_b_and_variant); return 0; } IV uu_compare_binary(const uu_t uu1, const uu_t uu2) { IV typ1, typ2, var1, var2; struct_uu_t us1, us2; uu_pack_unpack(uu1, &us1); uu_pack_unpack(uu2, &us2); var1 = uu_variant(&us1); var2 = uu_variant(&us2); if (var1 != var2) return var1 > var2 ? 1 : -1; typ1 = uu_type(&us1); typ2 = uu_type(&us2); if (typ1 != typ2) return typ1 > typ2 ? 1 : -1; switch(typ1) { case 1: return uu_compare_struct1(&us1, &us2); case 3: return uu_compare_struct3(&us1, &us2); case 4: return uu_compare_struct4(&us1, &us2); case 5: return uu_compare_struct5(&us1, &us2); case 6: return uu_compare_struct6(&us1, &us2); case 7: return uu_compare_struct7(&us1, &us2); } /* handles null and unknown types */ return uu_compare_struct0(&us1, &us2); } IV uu_compare_isnull_binary(const uu_t in) { const U8 *cp = in; IV i; for (i=0; iv0.low) return 0; if (in->v0.high) return 0; return 1; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/compare.h0000644000175000017500000000137515176655431013123 0ustar rikrik#ifndef ULIB__COMPARE_H #define ULIB__COMPARE_H #include "ulib/UUID.h" IV uu_compare_struct0(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct1(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct3(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct4(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct5(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct6(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_struct7(const struct_uu_t *us1, const struct_uu_t *us2); IV uu_compare_binary(const uu_t uu1, const uu_t uu2); IV uu_compare_isnull_binary(const uu_t in); IV uu_compare_isnull_struct(const struct_uu_t *in); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/util.c0000644000175000017500000001300415176655431012435 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/util.h" #ifdef __cplusplus } #endif /****************************************************************************** * all for croak_caller before 5.13.4. */ #define PERL_ARGS_ASSERT_DOPOPTOSUB_AT assert(cxstk) #ifdef PERL_GLOBAL_STRUCT # define dVAR pVAR = (struct perl_vars*)PERL_GET_VARS() #else # define dVAR dNOOP #endif #ifndef dopoptosub #define dopoptosub(plop) dopoptosub_at(cxstack, (plop)) #endif #ifndef dopoptosub_at #if !defined(PERL_IMPLICIT_CONTEXT) # define dopoptosub_at my_dopoptosub_at #else # define dopoptosub_at(a,b) my_dopoptosub_at(aTHX_ a,b) #endif #endif STATIC I32 my_dopoptosub_at(pTHX_ const PERL_CONTEXT *cxstk, I32 startingblock) { dVAR; I32 i; PERL_ARGS_ASSERT_DOPOPTOSUB_AT; for (i = startingblock; i >= 0; i--) { register const PERL_CONTEXT * const cx = &cxstk[i]; switch (CxTYPE(cx)) { default: continue; case CXt_EVAL: case CXt_SUB: case CXt_FORMAT: DEBUG_l( Perl_deb(aTHX_ "(dopoptosub_at(): found sub at cx=%ld)\n", (long)i)); return i; } } return i; } const PERL_CONTEXT * my_caller_cx(pTHX_ I32 count, const PERL_CONTEXT **dbcxp) { register I32 cxix = dopoptosub(cxstack_ix); register const PERL_CONTEXT *cx; register const PERL_CONTEXT *ccstack = cxstack; const PERL_SI *top_si = PL_curstackinfo; for (;;) { /* we may be in a higher stacklevel, so dig down deeper */ while (cxix < 0 && top_si->si_type != PERLSI_MAIN) { top_si = top_si->si_prev; ccstack = top_si->si_cxstack; cxix = dopoptosub_at(ccstack, top_si->si_cxix); } if (cxix < 0) return NULL; /* caller() should not report the automatic calls to &DB::sub */ if (PL_DBsub && GvCV(PL_DBsub) && cxix >= 0 && ccstack[cxix].blk_sub.cv == GvCV(PL_DBsub)) count++; if (!count--) break; cxix = dopoptosub_at(ccstack, cxix - 1); } cx = &ccstack[cxix]; if (dbcxp) *dbcxp = cx; if (CxTYPE(cx) == CXt_SUB || CxTYPE(cx) == CXt_FORMAT) { const I32 dbcxix = dopoptosub_at(ccstack, cxix - 1); /* We expect that ccstack[dbcxix] is CXt_SUB, anyway, the field below is defined for any cx. */ /* caller() should not report the automatic calls to &DB::sub */ if (PL_DBsub && GvCV(PL_DBsub) && dbcxix >= 0 && ccstack[dbcxix].blk_sub.cv == GvCV(PL_DBsub)) cx = &ccstack[dbcxix]; } return cx; } void my_croak_caller(const char *pat, ...) { dTHX; va_list args; const PERL_CONTEXT *cx = my_caller_cx(aTHX_ 0, NULL); /* make error appear at call site */ assert(cx); PL_curcop = cx->blk_oldcop; va_start(args, pat); vcroak(pat, &args); NOT_REACHED; /* NOTREACHED */ va_end(args); } /******************************************************************************/ void uu_clear(struct_uu_t *io) { io->v1.time_low = 0; io->v1.time_mid = 0; io->v1.time_high_and_version = 0; io->v1.clock_seq_and_variant = 0; io->v1.node[0] = 0; io->v1.node[1] = 0; io->v1.node[2] = 0; io->v1.node[3] = 0; io->v1.node[4] = 0; io->v1.node[5] = 0; } void uu_copy_binary(pUCXT, const uu_t in, uu_t out) { /* XXX use Copy */ U8 *cp1 = (U8*)∈ U8 *cp2 = out; UV i; for (i=0; i < 16; i++) *cp1++ = *cp2++; } void uu_copy_struct(pUCXT, const struct_uu_t *in, struct_uu_t *out) { /* XXX use Copy */ out->v1.time_low = in->v1.time_low; out->v1.time_mid = in->v1.time_mid; out->v1.time_high_and_version = in->v1.time_high_and_version; out->v1.clock_seq_and_variant = in->v1.clock_seq_and_variant; out->v1.node[0] = in->v1.node[0]; out->v1.node[1] = in->v1.node[1]; out->v1.node[2] = in->v1.node[2]; out->v1.node[3] = in->v1.node[3]; out->v1.node[4] = in->v1.node[4]; out->v1.node[5] = in->v1.node[5]; } static NV uu_time_v1(const struct_uu_t *in) { U64 sum; NV rv; sum = ((U64)in->v1.time_high_and_version & 0x0fff) << 48 | ((U64)in->v1.time_mid) << 32 | (U64)in->v1.time_low; sum -= 122192928000000000ULL; rv = (NV)sum / 10000000.0; return rv; } static NV uu_time_v4(const struct_uu_t *in) { return 0.0; } static NV uu_time_v6(const struct_uu_t *in) { U64 sum; NV rv; sum = ((U64)in->v6.time_high) << 28 | ((U64)in->v6.time_mid) << 12 | ((U64)in->v6.time_low_and_version & 0x0fff); sum -= 122192928000000000ULL; rv = (NV)sum / 10000000.0; return rv; } static NV uu_time_v7(const struct_uu_t *in) { U64 sum; NV rv; sum = ((U64)in->v7.time_high) << 16 | (U64)in->v7.time_low; rv = (NV)sum / 1000.0; return rv; } NV uu_time(const struct_uu_t *in) { int version; version = in->v1.time_high_and_version >> 12; switch(version) { case 1: return uu_time_v1(in); case 4: return uu_time_v4(in); case 6: return uu_time_v6(in); case 7: return uu_time_v7(in); } return 0; } /* a.k.a. version */ UV uu_type(const struct_uu_t *in) { UV type; type = in->v1.time_high_and_version >> 12; if (type <= 8) return type; return 0; } UV uu_variant(const struct_uu_t *in) { U16 variant; variant = in->v1.clock_seq_and_variant; if ((variant & 0x8000) == 0) return 0; if ((variant & 0x4000) == 0) return 1; if ((variant & 0x2000) == 0) return 2; return 3; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/TYPE.h0000644000175000017500000001364215177010206012240 0ustar rikrik#ifndef ULIB__TYPE_H #define ULIB__TYPE_H #ifndef PERL_VERSION # undef SUBVERSION /* OS/390 */ # include # ifndef SUBVERSION # define SUBVERSION 0 # endif # if !defined(PATCHLEVEL))) # include # endif # define PERL_REVISION 5 # define PERL_VERSION PATCHLEVEL # define PERL_SUBVERSION SUBVERSION #endif #ifndef PERL_VERSION_DECIMAL # define PERL_VERSION_DECIMAL(r,v,s) (r*1000000 + v*1000 + s) #endif #ifndef PERL_DECIMAL_VERSION # define PERL_DECIMAL_VERSION \ PERL_VERSION_DECIMAL(PERL_REVISION,PERL_VERSION,PERL_SUBVERSION) #endif #ifndef PERL_VERSION_LT # define PERL_VERSION_LT(r,v,s) \ (PERL_DECIMAL_VERSION < PERL_VERSION_DECIMAL(r,v,s)) #endif #ifndef PERL_VERSION_EQ # define PERL_VERSION_EQ(r,v,s) \ (PERL_DECIMAL_VERSION == PERL_VERSION_DECIMAL(r,v,s)) #endif /* related from SO for gcc: * https://stackoverflow.com/questions/1188939/representing-128-bit-numbers-in-c ******************************************************************************* typedef unsigned int uint128_t __attribute__((mode(TI))); uint64_t x = 0xABCDEF01234568; uint64_t y = ~x; uint128_t result = ((uint128_t) x * y); printf("%016llX * %016llX -> ", x, y); uint64_t r1 = (result >> 64); uint64_t r2 = result; printf("%016llX %016llX\n", r1, r2); */ /* Quad_t/U64 first appear in 5.00563 (8175356b44). #ifdef Quad_t typedef I64TYPE I64; typedef U64TYPE U64; #endif * U64TYPE also first appears in 8175356b44. * HAS_QUAD also appears in 5.00563 (de1c261475), * but did not take over the typedefs until 6b8eaf9322, * (also 5.00563) where U64 type was restricted to core. * QUADKIND also first appears in 6b8eaf9322. * * U64 made available outside core in 5.27.7. */ #ifndef U64 # ifdef U64TYPE typedef U64TYPE U64; # else typedef uint64_t U64; # endif #endif typedef union { struct { /* keep this struct first for namespace init */ U32 time_low; U16 time_mid; U16 time_high_and_version; U16 clock_seq_and_variant; U8 node[6]; } v1; struct { U64 low; U64 high; } v0; struct { U32 md5_high32; U16 md5_high16; U16 md5_mid_and_version; U32 md5_low_and_variant; U32 md5_low; } v3; struct { U32 rand_a; U32 rand_b_and_version; U32 rand_c_and_variant; U32 rand_d; } v4; struct { U32 sha1_high32; U16 sha1_high16; U16 sha1_mid_and_version; U32 sha1_low_and_variant; U32 sha1_low; } v5; struct { U32 time_high; U16 time_mid; U16 time_low_and_version; U16 clock_seq_and_variant; U8 node[6]; } v6; struct { U32 time_high; U16 time_low; U16 rand_a_and_version; U64 rand_b_and_variant; } v7; U64 __align; } struct_uu_t; typedef unsigned char UCHAR; #define CC_STATESZ 16 /* words: 4 constant, 8 key, 2 counter, 2 nonce */ #define CC_KEYSZ 40 /* bytes of user supplied key+nonce */ #define CC_CORESZ 64 /* bytes output by core */ #define CC_BUFSZ 16*CC_CORESZ /* bytes we get at a time (1024) */ #define CC_ROUNDS 20 typedef struct { U32 state[CC_STATESZ]; UCHAR buf[CC_BUFSZ]; U16 have; U64 __align; } chacha_t; /* not including trailing null */ #define MAX_PERSIST_LEN 512 - sizeof(UV) - 1 typedef struct { STRLEN len; /* not including trailing null, so <= MAX_PERSIST_LEN */ UCHAR path[MAX_PERSIST_LEN]; } persist_t; #if defined(HAVE_SRWLOCK) typedef SRWLOCK uu_lock_t; #elif defined(USE_WIN32_ALIEN) || defined(USE_WIN32_NATIVE) typedef CRITICAL_SECTION uu_lock_t; #elif defined(__OpenBSD__) typedef uint32_t uu_lock_t; #elif defined(__APPLE__) && defined(HAVE_DISPATCH_DISPATCH_H) typedef dispatch_semaphore_t uu_lock_t; #else typedef sem_t uu_lock_t; #endif typedef struct { uu_lock_t LOCK; /* ?? bytes (on Linux) */ U8 __pad0[64 - sizeof(uu_lock_t)]; /* -- 64 bytes -- */ struct timeval clock_last; /* 16 bytes (8 on win32) */ U64 clock_prev_reg; /* 8 bytes */ U64 clock_defer_100ns; /* 8 bytes */ I16 clock_adj; /* 2 bytes */ U16 clock_seq; /* 2 bytes */ U8 __pad1[64 - 20 - sizeof(struct timeval)]; /* -- 64 bytes -- */ U64 gen_epoch; /* 8 bytes */ U8 gen_node[6]; /* 6 bytes */ /* need 64bit align */ U16 gen_has_real_node; /* 2 bytes */ U8 gen_real_node[6]; /* 6 bytes */ /* need 64bit align */ U16 gen_use_unique; /* 2 bytes */ U8 __pad2[64 - 24]; /* -- 64 bytes -- */ chacha_t cc; /* 1104 bytes */ /* aligned 64bit */ U64 xo_s[4]; /* 32 bytes */ U64 sm_x; /* 8 bytes */ U8 __pad3[1152 - 40 - sizeof(chacha_t)]; /* -- 18 * 64 bytes -- */ persist_t clock_persist; /* 512 bytes */ /* -- 8 * 64 bytes -- */ } shared_mem_t; /* this should be aligned at least 4 bytes, better yet 16 */ typedef U8 uu_t[16]; typedef struct { shared_mem_t *shared; /* 8 bytes */ IV shared_len; /* 8 bytes */ FILE *clock_state_f; /* 8 bytes */ I32 clock_state_fd; /* 4 bytes */ U8 __pad5[64 - 4 - sizeof(shared_mem_t*) - sizeof(IV) - sizeof(FILE*)]; /* -- 64 bytes -- */ persist_t clock_persist; /* 512 bytes */ /* -- 8 * 64 bytes -- */ } my_cxt_t; /*} __attribute__ ((aligned (64))) my_cxt_t; * * Align 64 bytes vs 8. * * It's a toss-up as to whether this helps -- faster some places, * slower others. */ /* no *UCXT_ variants, just use a comma */ #define pUCXT pTHX_ my_cxt_t *my_cxtp #define aUCXT aTHX_ my_cxtp #define UCXT (*my_cxtp) #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/gen.c0000644000175000017500000001163015176655431012234 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/chacha.h" #include "ulib/clock.h" #include "ulib/gen.h" #include "ulib/hash.h" #include "ulib/node.h" #ifdef __cplusplus } #endif /* randomize uu_node */ static void uu_gen_randomize(pUCXT) { uu_chacha_rand32(aUCXT, (U32*)&SMEM->gen_node[0]); uu_chacha_rand16(aUCXT, (U16*)&SMEM->gen_node[4]); SMEM->gen_node[0] |= 0x01; /* set mcast */ } /* call at boot */ void uu_gen_init(pUCXT) { SMEM->gen_epoch = (((U64) 0x01B21DD2) << 32) | 0x13814000; /* unused */ SMEM->gen_use_unique = 0; SMEM->gen_has_real_node = 0; SMEM->gen_node[0] = 0;; SMEM->gen_node[1] = 0;; SMEM->gen_node[2] = 0;; SMEM->gen_node[3] = 0;; SMEM->gen_node[4] = 0;; SMEM->gen_node[5] = 0;; SMEM->gen_real_node[0] = 0; SMEM->gen_real_node[1] = 0; SMEM->gen_real_node[2] = 0; SMEM->gen_real_node[3] = 0; SMEM->gen_real_node[4] = 0; SMEM->gen_real_node[5] = 0; /* get the real node or randomize it */ if (uu_node_getid(aUCXT, (U8*)&SMEM->gen_node) == 1) { SMEM->gen_has_real_node = 1; SMEM->gen_real_node[0] = SMEM->gen_node[0]; SMEM->gen_real_node[1] = SMEM->gen_node[1]; SMEM->gen_real_node[2] = SMEM->gen_node[2]; SMEM->gen_real_node[3] = SMEM->gen_node[3]; SMEM->gen_real_node[4] = SMEM->gen_node[4]; SMEM->gen_real_node[5] = SMEM->gen_node[5]; } else { SMEM->gen_has_real_node = 0; uu_gen_randomize(aUCXT); } } void uu_gen_setrand(pUCXT) { SMEM->gen_use_unique = 0; uu_gen_randomize(aUCXT); } void uu_gen_setuniq(pUCXT) { SMEM->gen_use_unique = 1; } /* returns 1 if has real node, or 0 */ int uu_gen_realnode(pUCXT, struct_uu_t *out) { uu_gen_v0(aUCXT, out, NULL); out->v1.node[0] = SMEM->gen_real_node[0]; out->v1.node[1] = SMEM->gen_real_node[1]; out->v1.node[2] = SMEM->gen_real_node[2]; out->v1.node[3] = SMEM->gen_real_node[3]; out->v1.node[4] = SMEM->gen_real_node[4]; out->v1.node[5] = SMEM->gen_real_node[5]; return SMEM->gen_has_real_node; } void uu_gen_v0(pUCXT, struct_uu_t *out, char *dptr) { out->v0.low = 0; out->v0.high = 0; } void uu_gen_v1(pUCXT, struct_uu_t *out, char *dptr) { U64 clock_reg; U16 clock_seq; uu_clock(aUCXT, &clock_reg, &clock_seq); clock_reg += (((U64)0x01b21dd2) << 32) + 0x13814000; out->v1.time_low = (U32)clock_reg; out->v1.time_mid = (U16)(clock_reg >> 32 & 0xffff); out->v1.time_high_and_version = (U16)((clock_reg >> 48 & 0x0fff) | 0x1000); out->v1.clock_seq_and_variant = (clock_seq & 0x3fff) | 0x8000; if (SMEM->gen_use_unique) uu_gen_randomize(aUCXT); out->v1.node[0] = SMEM->gen_node[0]; out->v1.node[1] = SMEM->gen_node[1]; out->v1.node[2] = SMEM->gen_node[2]; out->v1.node[3] = SMEM->gen_node[3]; out->v1.node[4] = SMEM->gen_node[4]; out->v1.node[5] = SMEM->gen_node[5]; } void uu_gen_v3(pUCXT, struct_uu_t *out, char *dptr) { /* out points to a v1 uuid to use as namespace. */ /* out also points to output buffer for v3 uuid. */ /* dptr points to string to use as name. */ uu_hash_md5(aUCXT, out, dptr); } void uu_gen_v4(pUCXT, struct_uu_t *out, char *dptr) { U64 *cp = (U64*)out; uu_chacha_rand64(aUCXT, cp++); uu_chacha_rand64(aUCXT, cp); out->v4.rand_b_and_version = (out->v4.rand_b_and_version & 0xffff0fff) | 0x00004000; out->v4.rand_c_and_variant = (out->v4.rand_c_and_variant & 0x3fffffff) | 0x80000000; } void uu_gen_v5(pUCXT, struct_uu_t *out, char *dptr) { /* out points to a v1 uuid to use as namespace. */ /* out also points to output buffer for v5 uuid. */ /* dptr points to string to use as name. */ uu_hash_sha1(aUCXT, out, dptr); } void uu_gen_v6(pUCXT, struct_uu_t *out, char *dptr) { U64 clock_reg; U16 clock_seq; uu_clock(aUCXT, &clock_reg, &clock_seq); clock_reg += (((U64)0x01b21dd2) << 32) + 0x13814000; out->v6.time_high = (U32)(clock_reg >> 28); out->v6.time_mid = (U16)(clock_reg >> 12); out->v6.time_low_and_version = (U16)(clock_reg & 0x0fff) | 0x6000; out->v6.clock_seq_and_variant = (clock_seq & 0x3fff) | 0x8000; /* use the same node as v1 */ if (SMEM->gen_use_unique) uu_gen_randomize(aUCXT); out->v6.node[0] = SMEM->gen_node[0]; out->v6.node[1] = SMEM->gen_node[1]; out->v6.node[2] = SMEM->gen_node[2]; out->v6.node[3] = SMEM->gen_node[3]; out->v6.node[4] = SMEM->gen_node[4]; out->v6.node[5] = SMEM->gen_node[5]; } void uu_gen_v7(pUCXT, struct_uu_t *out, char *dptr) { U64 clock_reg; U16 clock_seq; uu_clock(aUCXT, &clock_reg, &clock_seq); clock_reg /= 10000; uu_chacha_rand16(aUCXT, &out->v7.rand_a_and_version); uu_chacha_rand64(aUCXT, &out->v7.rand_b_and_variant); out->v7.time_high = (U32)(clock_reg >> 16); out->v7.time_low = (U16)(clock_reg & 0xffff); out->v7.rand_a_and_version = (out->v7.rand_a_and_version & 0x0fff) | 0x7000; out->v7.rand_b_and_variant = (out->v7.rand_b_and_variant & 0x3fffffffffffffffULL) | 0x8000000000000000ULL; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/parse.c0000644000175000017500000001520415176655431012576 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/parse.h" #ifdef __cplusplus } #endif IV uu_parse(const char *in, struct_uu_t *out) { int i; const char *cp; char buf[3]; if (strlen(in) != 36) return -1; for (i=0, cp = in; i <= 36; i++,cp++) { if ((i == 8) || (i == 13) || (i == 18) || (i == 23)) { if (*cp == '-') continue; return -1; } if (i == 36 && *cp == 0) continue; if (!isxdigit((int)*cp)) return -1; } out->v1.time_low = strtoul(in, NULL, 16); out->v1.time_mid = (U16)strtoul(in+9, NULL, 16); out->v1.time_high_and_version = (U16)strtoul(in+14, NULL, 16); out->v1.clock_seq_and_variant = (U16)strtoul(in+19, NULL, 16); cp = in+24; buf[2] = 0; for (i=0; i < 6; i++) { buf[0] = *cp++; buf[1] = *cp++; out->v1.node[i] = (U8)strtoul(buf, NULL, 16); } return 0; } const char *uu_parse_unparse_fmt_lower = "0123456789abcdef"; const char *uu_parse_unparse_fmt_upper = "0123456789ABCDEF"; /* convert U64 to hex chars. */ static void uu_u64_2hex(const U64 in, char *out, const int len, const char *fmt) { U64 n = in; int i = len; do { out[--i] = fmt[n % 16]; n >>= 4; } while (n > 0); while (i > 0) out[--i] = '0'; } void uu_parse_unparse_x0(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v1.time_low, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v1.time_mid, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.time_high_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.clock_seq_and_variant, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.node[0], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[1], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[2], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[3], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[4], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[5], dst, 2, fmt); dst += 2; *dst = 0; } void uu_parse_unparse_x1(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v1.time_low, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v1.time_mid, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.time_high_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.clock_seq_and_variant, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.node[0], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[1], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[2], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[3], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[4], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[5], dst, 2, fmt); dst += 2; *dst = 0; } void uu_parse_unparse_x3(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v1.time_low, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v1.time_mid, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.time_high_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.clock_seq_and_variant, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.node[0], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[1], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[2], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[3], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[4], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[5], dst, 2, fmt); dst += 2; *dst = 0; } void uu_parse_unparse_x4(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v4.rand_a, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v4.rand_b_and_version >> 16, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v4.rand_b_and_version & 0xffff, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v4.rand_c_and_variant >> 16, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v4.rand_c_and_variant & 0xffff, dst, 4, fmt); dst += 4; uu_u64_2hex(in->v4.rand_d, dst, 8, fmt); dst += 8; *dst = 0; } void uu_parse_unparse_x5(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v1.time_low, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v1.time_mid, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.time_high_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.clock_seq_and_variant, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v1.node[0], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[1], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[2], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[3], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[4], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v1.node[5], dst, 2, fmt); dst += 2; *dst = 0; } void uu_parse_unparse_x6(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v6.time_high, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v6.time_mid, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v6.time_low_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v6.clock_seq_and_variant, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v6.node[0], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v6.node[1], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v6.node[2], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v6.node[3], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v6.node[4], dst, 2, fmt); dst += 2; uu_u64_2hex(in->v6.node[5], dst, 2, fmt); dst += 2; *dst = 0; } void uu_parse_unparse_x7(const struct_uu_t *in, char *out, const char *fmt) { char *dst = out; uu_u64_2hex(in->v7.time_high, dst, 8, fmt); dst += 8; *dst++ = '-'; uu_u64_2hex(in->v7.time_low, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v7.rand_a_and_version, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v7.rand_b_and_variant >> 48, dst, 4, fmt); dst += 4; *dst++ = '-'; uu_u64_2hex(in->v7.rand_b_and_variant & 0xffffffffffffULL, dst, 12, fmt); dst += 12; *dst = 0; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/gen.h0000644000175000017500000000114115176525526012236 0ustar rikrik#ifndef ULIB__GEN_H #define ULIB__GEN_H #include "ulib/UUID.h" void uu_gen_init(pUCXT); void uu_gen_setrand(pUCXT); void uu_gen_setuniq(pUCXT); int uu_gen_realnode(pUCXT, struct_uu_t *out); void uu_gen_v0(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v1(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v3(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v4(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v5(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v6(pUCXT, struct_uu_t *out, char *dptr); void uu_gen_v7(pUCXT, struct_uu_t *out, char *dptr); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/parse.h0000644000175000017500000000603415176655431012604 0ustar rikrik#ifndef ULIB__PARSE_H #define ULIB__PARSE_H #include "ulib/UUID.h" IV uu_parse(const char *in, struct_uu_t *out); extern const char *uu_parse_unparse_fmt_lower; extern const char *uu_parse_unparse_fmt_upper; #ifdef UUID_UNPARSE_DEFAULT_UPPER #define UU_UNPARSE_FMT_DEFAULT uu_parse_unparse_fmt_upper #else #define UU_UNPARSE_FMT_DEFAULT uu_parse_unparse_fmt_lower #endif void uu_parse_unparse_x0(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower0(in, out) uu_parse_unparse_x0((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper0(in, out) uu_parse_unparse_x0((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v0(in, out) uu_parse_unparse_x0((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x1(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower1(in, out) uu_parse_unparse_x1((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper1(in, out) uu_parse_unparse_x1((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v1(in, out) uu_parse_unparse_x1((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x3(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower3(in, out) uu_parse_unparse_x3((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper3(in, out) uu_parse_unparse_x3((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v3(in, out) uu_parse_unparse_x3((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x4(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower4(in, out) uu_parse_unparse_x4((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper4(in, out) uu_parse_unparse_x4((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v4(in, out) uu_parse_unparse_x4((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x5(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower5(in, out) uu_parse_unparse_x5((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper5(in, out) uu_parse_unparse_x5((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v5(in, out) uu_parse_unparse_x5((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x6(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower6(in, out) uu_parse_unparse_x6((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper6(in, out) uu_parse_unparse_x6((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v6(in, out) uu_parse_unparse_x6((in), (out), UU_UNPARSE_FMT_DEFAULT) void uu_parse_unparse_x7(const struct_uu_t *in, char *out, const char *fmt); #define uu_parse_unparse_lower7(in, out) uu_parse_unparse_x7((in), (out), uu_parse_unparse_fmt_lower) #define uu_parse_unparse_upper7(in, out) uu_parse_unparse_x7((in), (out), uu_parse_unparse_fmt_upper) #define uu_parse_unparse_v7(in, out) uu_parse_unparse_x7((in), (out), UU_UNPARSE_FMT_DEFAULT) #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/UMTX.h0000644000175000017500000001054315177010206012251 0ustar rikrik#ifndef ULIB__UMTX_H #define ULIB__UMTX_H /* The entire need for locking in UUID springs from the fact that some are using it in forked or threaded environments, not to mention the "thread-safety" aspects. The first complaint was that UUIDv4 would repeat after creating new threads. This was solved by moving the RNG context into a thread-safe container and reseeding at clone time. The next complaint was that UUIDv4 would repeat after forking new processes. This was solved by saving the process id and comparing it to the live pid on every call. If they differed, reseed the RNG. The next complaint, which has not appeared yet but will in time as CPUs get faster, will be that UUIDv1 repeats due to timestamp overlap. This can already be seen in testing and has been partially mitigated by implementing a counter on top of the raw time value and spinning the clock_seq field as needed. However, in light of the first two complaints, this too shall fail. The real solution is to move both random number and time contexts into a shared memory space that can be seen by both threads and forks, which of course presents us with a serious need for a fast, reliable lock. There does not appear to be a portable solution, so we get this. */ #if defined(USE_WIN32_ALIEN) || defined(USE_WIN32_NATIVE) # ifdef HAVE_SRWLOCK # define UMTX_init InitializeSRWLock(&SMEM->LOCK) # define UMTX_lock AcquireSRWLockExclusive(&SMEM->LOCK) # define UMTX_unlock ReleaseSRWLockExclusive(&SMEM->LOCK) # else # define UMTX_init InitializeCriticalSection(&SMEM->LOCK) # define UMTX_lock EnterCriticalSection(&SMEM->LOCK) # define UMTX_unlock LeaveCriticalSection(&SMEM->LOCK) # endif #elif defined(__OpenBSD__) /* sem_init() broken when pshared != 0 */ #include "FUTX.h" #include "atomic.h" #define UMTX_init SMEM->LOCK = 0 #define UMTX_lock { \ long c; \ if ((c = cmpxchg(&SMEM->LOCK, 0, 1)) != 0) { \ if (c != 2) \ c = xchg(&SMEM->LOCK, 2); \ while (c != 0) { \ futex_wait(&SMEM->LOCK, 2, 0); \ c = xchg(&SMEM->LOCK, 2); \ } \ } \ } #define UMTX_unlock { \ if (xdec(&SMEM->LOCK) != 1) { \ SMEM->LOCK = 0; \ futex_wake(&SMEM->LOCK, 1); \ } \ } #elif defined(__APPLE__) && defined(HAVE_DISPATCH_DISPATCH_H) /* See this link for a nice discussion on options here. https://www.codestudy.net/blog/why-are-sem-init-sem-getvalue-sem-destroy-deprecated-on-mac-os-x-and-what-replaces-them/ * Note that one of the workarounds is with pthreads. Their call to * pthread_mutex_create() discards the pshared argument, which is really * where all our troubles began with pthreads in general. Notably that * once you start needing pshared=!0, various platforms display differing * states of brokenness. One platform (*cough* OpenBSD) going so far as to * say that removing process-shared mutex was POSIX-conformant. And while * that's probably true, our need is not diminished. */ /* For OSX and archlinux but arch seems to have a working sem_init/wait */ /* dispatch_semaphore_t is a pointer type */ #define UMTX_init SMEM->LOCK = dispatch_semaphore_create(0) #define UMTX_lock dispatch_semaphore_wait(SMEM->LOCK, DISPATCH_TIME_FOREVER) #define UMTX_unlock dispatch_semaphore_signal(SMEM->LOCK) #else #define UMTX_init \ if (sem_init(&SMEM->LOCK, 1, 1)) \ Perl_croak_nocontext("panic: sem_init (%d) [%s:%d]", errno, __FILE__, __LINE__) #define UMTX_lock do { \ if (sem_wait(&SMEM->LOCK) == 0) break; \ if (errno == EINVAL) \ Perl_croak_nocontext("panic: sem_wait (EINVAL) [%s:%d]", __FILE__, __LINE__); \ } while (1); #define UMTX_unlock { \ int r = sem_post(&SMEM->LOCK); \ if (r != 0) \ Perl_croak_nocontext("panic: sem_post (TRUE) [%s:%d]", __FILE__, __LINE__); \ } #endif /* This is try/catch from XSUB.h, copied here for reference. */ #ifdef NO_XSLOCKSxxx # define dXCPT dJMPENV; int rEtV = 0 # define XCPT_TRY_START JMPENV_PUSH(rEtV); if (rEtV == 0) # define XCPT_TRY_END JMPENV_POP; # define XCPT_CATCH if (rEtV != 0) # define XCPT_RETHROW JMPENV_JUMP(rEtV) #endif #define UMTX_INIT UMTX_init #define UMTX_LOCK dJMPENV; int rEtV = 0; UMTX_lock; JMPENV_PUSH(rEtV); if (rEtV == 0) #define UMTX_UNLOCK JMPENV_POP; UMTX_unlock; if (rEtV != 0) { JMPENV_JUMP(rEtV); } #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/clock.h0000644000175000017500000000057515176525526012572 0ustar rikrik#ifndef ULIB__CLOCK_H #define ULIB__CLOCK_H #include "ulib/UUID.h" /* Assume that gettimeofday() has microsecond granularity. */ #define MAX_ADJUSTMENT 10 void uu_clock_init(pUCXT); void uu_clock_getpath(pUCXT, persist_t *sp); void uu_clock_setpath(pUCXT, persist_t *sp); IV uu_clock(pUCXT, U64 *ret_clock_reg, U16 *ret_clock_seq); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/gettime.c0000644000175000017500000000171715176525526013127 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/gettime.h" #ifdef __cplusplus } #endif void (*uu_gettime_U2time)(pTHX_ UV ret[2]); /* called at boot */ void uu_gettime_init(pUCXT) { SV **svp; require_pv("Time/HiRes.pm"); svp = hv_fetchs(PL_modglobal, "Time::U2time", 0); if (!svp) croak("Time::HiRes is required"); if (!SvIOK(*svp)) croak("Time::U2time isn't a function pointer"); uu_gettime_U2time = INT2PTR(void(*)(pTHX_ UV ret[2]), SvIV(*svp)); /* if (0) { UV xx[2]; (*uu_gettime_U2time)(aTHX_ xx); printf("The current seconds are: %" UVuf ".%06" UVuf "\n", xx[0], xx[1]); exit(0); } */ } U64 uu_gettime_100ns64(pUCXT) { struct timeval tv; U64 rv; UV ptod[2]; /* gettimeofday(&tv, 0); */ (*uu_gettime_U2time)(aTHX_ ptod); tv.tv_sec = (long)ptod[0]; tv.tv_usec = (long)ptod[1]; rv = tv.tv_sec * 10000000 + tv.tv_usec * 10; return rv; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/splitmix.h0000644000175000017500000000026415176525526013343 0ustar rikrik#ifndef ULIB__SPLITMIX_H #define ULIB__SPLITMIX_H #include "ulib/UUID.h" void uu_splitmix_srand(pUCXT); U64 uu_splitmix_rand(pUCXT); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/gettime.h0000644000175000017500000000034615176525526013131 0ustar rikrik#ifndef ULIB__GETTIME_H #define ULIB__GETTIME_H #include "ulib/UUID.h" void uu_gettime_init(pUCXT); U64 uu_gettime_100ns64(pUCXT); extern void (*uu_gettime_U2time)(pTHX_ UV ret[2]); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/hash.c0000644000175000017500000006205515176655431012415 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/hash.h" #include "ulib/pack.h" #include "ulib/parse.h" #ifdef __cplusplus } #endif #ifdef MD5_DEBUG #undef MD5_DEBUG #endif static const char *hexdigits = "0123456789abcdef"; /* borrowed from Digest::MD5 with gentle mangling */ /*----------------------------------------------------------------*/ /* * This library is free software; you can redistribute it and/or * modify it under the same terms as Perl itself. * * Copyright 1998-2000 Gisle Aas. * Copyright 1995-1996 Neil Winton. * Copyright 1991-1992 RSA Data Security, Inc. * * This code is derived from Neil Winton's MD5-1.7 Perl module, which in * turn is derived from the reference implementation in RFC 1321 which * comes with this message: * * Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All * rights reserved. * * License to copy and use this software is granted provided that it * is identified as the "RSA Data Security, Inc. MD5 Message-Digest * Algorithm" in all material mentioning or referencing this software * or this function. * * License is also granted to make and use derivative works provided * that such works are identified as "derived from the RSA Data * Security, Inc. MD5 Message-Digest Algorithm" in all material * mentioning or referencing the derived work. * * RSA Data Security, Inc. makes no representations concerning either * the merchantability of this software or the suitability of this * software for any particular purpose. It is provided "as is" * without express or implied warranty of any kind. * * These notices must be retained in any copies of any part of this * documentation and/or software. */ #ifndef PERL_UNUSED_VAR # define PERL_UNUSED_VAR(x) ((void)x) #endif #if PERL_VERSION < 8 # undef SvPVbyte # define SvPVbyte(sv, lp) (sv_utf8_downgrade((sv), 0), SvPV((sv), (lp))) #endif /* Perl does not guarantee that U32 is exactly 32 bits. Some system * has no integral type with exactly 32 bits. For instance, A Cray has * short, int and long all at 64 bits so we need to apply this macro * to reduce U32 values to 32 bits at appropriate places. If U32 * really does have 32 bits then this is a no-op. */ #if BYTEORDER > 0x4321 || defined(TRUNCATE_U32) #define TO32(x) ((x) & 0xFFFFffff) #define TRUNC32(x) ((x) &= 0xFFFFffff) #else #define TO32(x) (x) #define TRUNC32(x) /*nothing*/ #endif /* The MD5 algorithm is defined in terms of little endian 32-bit * values. The following macros (and functions) allow us to convert * between native integers and such values. */ static void u2s(U32 u, U8* s) { *s++ = (U8)(u & 0xFF); *s++ = (U8)((u >> 8) & 0xFF); *s++ = (U8)((u >> 16) & 0xFF); *s = (U8)((u >> 24) & 0xFF); } #define s2u(s,u) ((u) = (U32)(*s) | \ ((U32)(*(s+1)) << 8) | \ ((U32)(*(s+2)) << 16) | \ ((U32)(*(s+3)) << 24)) typedef struct { U32 A, B, C, D; /* current digest */ U32 bytes_low; /* counts bytes in message */ U32 bytes_high; /* turn it into a 64-bit counter */ U8 buffer[128]; /* collect complete 64 byte blocks */ } MD5_CTX; /* Padding is added at the end of the message in order to fill a * complete 64 byte block (- 8 bytes for the message length). The * padding is also the reason the buffer in MD5_CTX have to be * 128 bytes. */ static const unsigned char PADDING[64] = { 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; /* Constants for MD5Transform routine. */ #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 /* F, G, H and I are basic MD5 functions. */ #define F(x, y, z) ((((x) & ((y) ^ (z))) ^ (z))) #define G(x, y, z) F(z, x, y) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) /* ROTATE_LEFT rotates x left n bits. */ #define ROTATE_LEFT(x, n) (((x) << (n) | ((x) >> (32-(n))))) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. * Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, s, ac) \ (a) += F ((b), (c), (d)) + (NEXTx) + (U32)(ac); \ TRUNC32((a)); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ TRUNC32((a)); #define GG(a, b, c, d, x, s, ac) \ (a) += G ((b), (c), (d)) + X[x] + (U32)(ac); \ TRUNC32((a)); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ TRUNC32((a)); #define HH(a, b, c, d, x, s, ac) \ (a) += H ((b), (c), (d)) + X[x] + (U32)(ac); \ TRUNC32((a)); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ TRUNC32((a)); #define II(a, b, c, d, x, s, ac) \ (a) += I ((b), (c), (d)) + X[x] + (U32)(ac); \ TRUNC32((a)); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ TRUNC32((a)); static void MD5Init(MD5_CTX *ctx) { /* Start state */ ctx->A = 0x67452301; ctx->B = 0xefcdab89; ctx->C = 0x98badcfe; ctx->D = 0x10325476; /* message length */ ctx->bytes_low = ctx->bytes_high = 0; } static void MD5Transform(MD5_CTX* ctx, const U8* buf, STRLEN blocks) { #ifdef MD5_DEBUG static int tcount = 0; #endif U32 A = ctx->A; U32 B = ctx->B; U32 C = ctx->C; U32 D = ctx->D; do { U32 a = A; U32 b = B; U32 c = C; U32 d = D; U32 X[16]; /* little-endian values, used in round 2-4 */ U32 *uptr = X; U32 tmp; #define NEXTx (s2u(buf,tmp), buf += 4, *uptr++ = tmp) #ifdef MD5_DEBUG if (buf == ctx->buffer) fprintf(stderr,"%5d: Transform ctx->buffer", ++tcount); else fprintf(stderr,"%5d: Transform %p (%d)", ++tcount, buf, blocks); { int i; fprintf(stderr,"["); for (i = 0; i < 16; i++) { fprintf(stderr,"%x,", X[i]); /* FIXME */ } fprintf(stderr,"]\n"); } #endif /* Round 1 */ FF (a, b, c, d, S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, S13, 0x242070db); /* 3 */ FF (b, c, d, a, S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, S13, 0xa8304613); /* 7 */ FF (b, c, d, a, S14, 0xfd469501); /* 8 */ FF (a, b, c, d, S11, 0x698098d8); /* 9 */ FF (d, a, b, c, S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, S11, 0x6b901122); /* 13 */ FF (d, a, b, c, S12, 0xfd987193); /* 14 */ FF (c, d, a, b, S13, 0xa679438e); /* 15 */ FF (b, c, d, a, S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, 1, S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, 6, S22, 0xc040b340); /* 18 */ GG (c, d, a, b, 11, S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, 0, S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, 5, S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, 10, S22, 0x2441453); /* 22 */ GG (c, d, a, b, 15, S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, 4, S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, 9, S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, 14, S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, 3, S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, 8, S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, 13, S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, 2, S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, 7, S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, 12, S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, 5, S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, 8, S32, 0x8771f681); /* 34 */ HH (c, d, a, b, 11, S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, 14, S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, 1, S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, 4, S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, 7, S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, 10, S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, 13, S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, 0, S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, 3, S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, 6, S34, 0x4881d05); /* 44 */ HH (a, b, c, d, 9, S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, 12, S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, 15, S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, 2, S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, 0, S41, 0xf4292244); /* 49 */ II (d, a, b, c, 7, S42, 0x432aff97); /* 50 */ II (c, d, a, b, 14, S43, 0xab9423a7); /* 51 */ II (b, c, d, a, 5, S44, 0xfc93a039); /* 52 */ II (a, b, c, d, 12, S41, 0x655b59c3); /* 53 */ II (d, a, b, c, 3, S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, 10, S43, 0xffeff47d); /* 55 */ II (b, c, d, a, 1, S44, 0x85845dd1); /* 56 */ II (a, b, c, d, 8, S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, 15, S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, 6, S43, 0xa3014314); /* 59 */ II (b, c, d, a, 13, S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, 4, S41, 0xf7537e82); /* 61 */ II (d, a, b, c, 11, S42, 0xbd3af235); /* 62 */ II (c, d, a, b, 2, S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, 9, S44, 0xeb86d391); /* 64 */ A += a; TRUNC32(A); B += b; TRUNC32(B); C += c; TRUNC32(C); D += d; TRUNC32(D); } while (--blocks); ctx->A = A; ctx->B = B; ctx->C = C; ctx->D = D; } #ifdef MD5_DEBUG static char* ctx_dump(MD5_CTX* ctx) { static char buf[1024]; sprintf(buf, "{A=%x,B=%x,C=%x,D=%x,%d,%d(%d)}", ctx->A, ctx->B, ctx->C, ctx->D, ctx->bytes_low, ctx->bytes_high, (ctx->bytes_low&0x3F)); return buf; } #endif static void MD5Update(MD5_CTX* ctx, const U8* buf, STRLEN len) { STRLEN blocks; STRLEN fill = ctx->bytes_low & 0x3F; #ifdef MD5_DEBUG static int ucount = 0; fprintf(stderr,"%5i: Update(%s, %p, %d)\n", ++ucount, ctx_dump(ctx), buf, len); #endif ctx->bytes_low += (U32)len; if (ctx->bytes_low < len) /* wrap around */ ctx->bytes_high++; if (fill) { STRLEN missing = 64 - fill; if (len < missing) { Copy(buf, ctx->buffer + fill, len, U8); return; } Copy(buf, ctx->buffer + fill, missing, U8); MD5Transform(ctx, ctx->buffer, 1); buf += missing; len -= missing; } blocks = len >> 6; if (blocks) MD5Transform(ctx, buf, blocks); if ( (len &= 0x3F)) { Copy(buf + (blocks << 6), ctx->buffer, len, U8); } } static void MD5Final(U8* digest, MD5_CTX *ctx) { STRLEN fill = ctx->bytes_low & 0x3F; STRLEN padlen = (fill < 56 ? 56 : 120) - fill; U32 bits_low, bits_high; #ifdef MD5_DEBUG fprintf(stderr," Final: %s\n", ctx_dump(ctx)); #endif Copy(PADDING, ctx->buffer + fill, padlen, U8); fill += padlen; bits_low = ctx->bytes_low << 3; bits_high = (ctx->bytes_high << 3) | (ctx->bytes_low >> 29); u2s(bits_low, ctx->buffer + fill); fill += 4; u2s(bits_high, ctx->buffer + fill); fill += 4; MD5Transform(ctx, ctx->buffer, fill >> 6); #ifdef MD5_DEBUG fprintf(stderr," Result: %s\n", ctx_dump(ctx)); #endif u2s(ctx->A, digest); u2s(ctx->B, digest+4); u2s(ctx->C, digest+8); u2s(ctx->D, digest+12); } /*----------------------------------------------------------------*/ /* declared above since also used in sha1 static const char *hexdigits = "0123456789abcdef"; */ static void hex_16(const unsigned char* from, char* to) { const unsigned char *end = from + 16; char *d = to; while (from < end) { *d++ = hexdigits[(*from >> 4)]; *d++ = hexdigits[(*from & 0x0F)]; from++; } *d = '\0'; } void uu_hash_md5(pUCXT, struct_uu_t *io, char *name) { /* io is assumed to be a v1 namespace uuid coming in. */ /* name is... a name. */ MD5_CTX context; char tmp[37]; char vardig; unsigned char digeststr[21]; uu_t packed; uu_pack_v1(io, (U8*)&packed); MD5Init(&context); MD5Update(&context, (U8*)&packed, sizeof(packed)); if (name) MD5Update(&context, (U8*)name, strlen(name)); MD5Final((U8*)digeststr, &context); digeststr[20] = '\0'; hex_16(digeststr, tmp); tmp[32] = '\0'; /* hyphenate */ Move(&tmp[20], &tmp[21], 12, char); tmp[20] = '-'; Move(&tmp[16], &tmp[17], 17, char); tmp[16] = '-'; Move(&tmp[12], &tmp[13], 22, char); tmp[12] = '-'; Move(&tmp[ 8], &tmp[ 9], 27, char); tmp[ 8] = '-'; tmp[36] = '\0'; /* version */ tmp[14] = '3'; /* variant */ vardig = tmp[19] - 48; if (vardig > 9) vardig -= 7; if (vardig > 15) vardig -= 32; vardig = (vardig & 0x3) | 0x8; if (vardig > 9) vardig += 87; else vardig += 48; tmp[19] = vardig; uu_parse(tmp, io); } /******************************************************************/ /******************************************************************/ /******************************************************************/ /* borrowed from Digest::SHA1 */ /*----------------------------------------------------------------*/ /* NIST Secure Hash Algorithm */ /* heavily modified by Uwe Hollerbach */ /* from Peter C. Gutmann's implementation as found in */ /* Applied Cryptography by Bruce Schneier */ /* Further modifications to include the "UNRAVEL" stuff, below */ /* This code is in the public domain */ /* Useful defines & typedefs */ #if defined(U64TYPE) && (defined(USE_64_BIT_INT) || ((BYTEORDER != 0x1234) && (BYTEORDER != 0x4321))) typedef U64TYPE ULONGx; # if BYTEORDER == 0x1234 # undef BYTEORDER # define BYTEORDER 0x12345678 # elif BYTEORDER == 0x4321 # undef BYTEORDER # define BYTEORDER 0x87654321 # endif #else typedef unsigned long ULONGx; /* 32-or-more-bit quantity */ #endif #define SHA_BLOCKSIZE 64 #define SHA_DIGESTSIZE 20 typedef struct { ULONGx digest[5]; /* message digest */ ULONGx count_lo, count_hi; /* 64-bit bit count */ U8 data[SHA_BLOCKSIZE]; /* SHA data buffer */ int local; /* unprocessed amount in data */ } SHA_INFO; /* UNRAVEL should be fastest & biggest */ /* UNROLL_LOOPS should be just as big, but slightly slower */ /* both undefined should be smallest and slowest */ #define SHA_VERSION 1 #define UNRAVEL /* #define UNROLL_LOOPS */ /* SHA f()-functions */ #define f1(x,y,z) ((x & y) | (~x & z)) #define f2(x,y,z) (x ^ y ^ z) #define f3(x,y,z) ((x & y) | (x & z) | (y & z)) #define f4(x,y,z) (x ^ y ^ z) /* SHA constants */ #define CONST1 0x5a827999L #define CONST2 0x6ed9eba1L #define CONST3 0x8f1bbcdcL #define CONST4 0xca62c1d6L /* truncate to 32 bits -- should be a null op on 32-bit machines */ #define T32(x) ((x) & 0xffffffffL) /* 32-bit rotate */ #define R32(x,n) T32(((x << n) | (x >> (32 - n)))) /* the generic case, for when the overall rotation is not unraveled */ #define FG(n) \ T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); \ E = D; D = C; C = R32(B,30); B = A; A = T /* specific cases, for when the overall rotation is unraveled */ #define FA(n) \ T = T32(R32(A,5) + f##n(B,C,D) + E + *WP++ + CONST##n); B = R32(B,30) #define FB(n) \ E = T32(R32(T,5) + f##n(A,B,C) + D + *WP++ + CONST##n); A = R32(A,30) #define FC(n) \ D = T32(R32(E,5) + f##n(T,A,B) + C + *WP++ + CONST##n); T = R32(T,30) #define FD(n) \ C = T32(R32(D,5) + f##n(E,T,A) + B + *WP++ + CONST##n); E = R32(E,30) #define FE(n) \ B = T32(R32(C,5) + f##n(D,E,T) + A + *WP++ + CONST##n); D = R32(D,30) #define FT(n) \ A = T32(R32(B,5) + f##n(C,D,E) + T + *WP++ + CONST##n); C = R32(C,30) static void sha_transform(SHA_INFO *sha_info) { int i; U8 *dp; ULONGx T, A, B, C, D, E, W[80], *WP; dp = sha_info->data; /* the following makes sure that at least one code block below is traversed or an error is reported, without the necessity for nested preprocessor if/else/endif blocks, which are a great pain in the nether regions of the anatomy... */ #undef SWAP_DONE #if BYTEORDER == 0x1234 #define SWAP_DONE /* assert(sizeof(ULONGx) == 4); */ for (i = 0; i < 16; ++i) { T = *((ULONGx *) dp); dp += 4; W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); } #endif #if BYTEORDER == 0x4321 #define SWAP_DONE /* assert(sizeof(ULONGx) == 4); */ for (i = 0; i < 16; ++i) { T = *((ULONGx *) dp); dp += 4; W[i] = T32(T); } #endif #if BYTEORDER == 0x12345678 #define SWAP_DONE /* assert(sizeof(ULONGx) == 8); */ for (i = 0; i < 16; i += 2) { T = *((ULONGx *) dp); dp += 8; W[i] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); T >>= 32; W[i+1] = ((T << 24) & 0xff000000) | ((T << 8) & 0x00ff0000) | ((T >> 8) & 0x0000ff00) | ((T >> 24) & 0x000000ff); } #endif #if BYTEORDER == 0x87654321 #define SWAP_DONE /* assert(sizeof(ULONGx) == 8); */ for (i = 0; i < 16; i += 2) { T = *((ULONGx *) dp); dp += 8; W[i] = T32(T >> 32); W[i+1] = T32(T); } #endif #ifndef SWAP_DONE #error Unknown byte order -- you need to add code here #endif /* SWAP_DONE */ for (i = 16; i < 80; ++i) { W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]; #if (SHA_VERSION == 1) W[i] = R32(W[i], 1); #endif /* SHA_VERSION */ } A = sha_info->digest[0]; B = sha_info->digest[1]; C = sha_info->digest[2]; D = sha_info->digest[3]; E = sha_info->digest[4]; WP = W; #ifdef UNRAVEL FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(1); FD(1); FE(1); FT(1); FA(1); FB(1); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(2); FT(2); FA(2); FB(2); FC(2); FD(2); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(3); FB(3); FC(3); FD(3); FE(3); FT(3); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); FC(4); FD(4); FE(4); FT(4); FA(4); FB(4); sha_info->digest[0] = T32(sha_info->digest[0] + E); sha_info->digest[1] = T32(sha_info->digest[1] + T); sha_info->digest[2] = T32(sha_info->digest[2] + A); sha_info->digest[3] = T32(sha_info->digest[3] + B); sha_info->digest[4] = T32(sha_info->digest[4] + C); #else /* !UNRAVEL */ #ifdef UNROLL_LOOPS FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(1); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(2); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(3); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); FG(4); #else /* !UNROLL_LOOPS */ for (i = 0; i < 20; ++i) { FG(1); } for (i = 20; i < 40; ++i) { FG(2); } for (i = 40; i < 60; ++i) { FG(3); } for (i = 60; i < 80; ++i) { FG(4); } #endif /* !UNROLL_LOOPS */ sha_info->digest[0] = T32(sha_info->digest[0] + A); sha_info->digest[1] = T32(sha_info->digest[1] + B); sha_info->digest[2] = T32(sha_info->digest[2] + C); sha_info->digest[3] = T32(sha_info->digest[3] + D); sha_info->digest[4] = T32(sha_info->digest[4] + E); #endif /* !UNRAVEL */ } /* initialize the SHA digest */ static void sha_init(SHA_INFO *sha_info) { sha_info->digest[0] = 0x67452301L; sha_info->digest[1] = 0xefcdab89L; sha_info->digest[2] = 0x98badcfeL; sha_info->digest[3] = 0x10325476L; sha_info->digest[4] = 0xc3d2e1f0L; sha_info->count_lo = 0L; sha_info->count_hi = 0L; sha_info->local = 0; } /* update the SHA digest */ static void sha_update(SHA_INFO *sha_info, U8 *buffer, int count) { int i; ULONGx clo; clo = T32(sha_info->count_lo + ((ULONGx) count << 3)); if (clo < sha_info->count_lo) { ++sha_info->count_hi; } sha_info->count_lo = clo; sha_info->count_hi += (ULONGx) count >> 29; if (sha_info->local) { i = SHA_BLOCKSIZE - sha_info->local; if (i > count) { i = count; } memcpy(((U8 *) sha_info->data) + sha_info->local, buffer, i); count -= i; buffer += i; sha_info->local += i; if (sha_info->local == SHA_BLOCKSIZE) { sha_transform(sha_info); } else { return; } } while (count >= SHA_BLOCKSIZE) { memcpy(sha_info->data, buffer, SHA_BLOCKSIZE); buffer += SHA_BLOCKSIZE; count -= SHA_BLOCKSIZE; sha_transform(sha_info); } memcpy(sha_info->data, buffer, count); sha_info->local = count; } static void sha_transform_and_copy(unsigned char digest[20], SHA_INFO *sha_info) { sha_transform(sha_info); digest[ 0] = (unsigned char) ((sha_info->digest[0] >> 24) & 0xff); digest[ 1] = (unsigned char) ((sha_info->digest[0] >> 16) & 0xff); digest[ 2] = (unsigned char) ((sha_info->digest[0] >> 8) & 0xff); digest[ 3] = (unsigned char) ((sha_info->digest[0] ) & 0xff); digest[ 4] = (unsigned char) ((sha_info->digest[1] >> 24) & 0xff); digest[ 5] = (unsigned char) ((sha_info->digest[1] >> 16) & 0xff); digest[ 6] = (unsigned char) ((sha_info->digest[1] >> 8) & 0xff); digest[ 7] = (unsigned char) ((sha_info->digest[1] ) & 0xff); digest[ 8] = (unsigned char) ((sha_info->digest[2] >> 24) & 0xff); digest[ 9] = (unsigned char) ((sha_info->digest[2] >> 16) & 0xff); digest[10] = (unsigned char) ((sha_info->digest[2] >> 8) & 0xff); digest[11] = (unsigned char) ((sha_info->digest[2] ) & 0xff); digest[12] = (unsigned char) ((sha_info->digest[3] >> 24) & 0xff); digest[13] = (unsigned char) ((sha_info->digest[3] >> 16) & 0xff); digest[14] = (unsigned char) ((sha_info->digest[3] >> 8) & 0xff); digest[15] = (unsigned char) ((sha_info->digest[3] ) & 0xff); digest[16] = (unsigned char) ((sha_info->digest[4] >> 24) & 0xff); digest[17] = (unsigned char) ((sha_info->digest[4] >> 16) & 0xff); digest[18] = (unsigned char) ((sha_info->digest[4] >> 8) & 0xff); digest[19] = (unsigned char) ((sha_info->digest[4] ) & 0xff); } /* finish computing the SHA digest */ static void sha_final(unsigned char digest[20], SHA_INFO *sha_info) { int count; ULONGx lo_bit_count, hi_bit_count; lo_bit_count = sha_info->count_lo; hi_bit_count = sha_info->count_hi; count = (int) ((lo_bit_count >> 3) & 0x3f); ((U8 *) sha_info->data)[count++] = 0x80; if (count > SHA_BLOCKSIZE - 8) { memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count); sha_transform(sha_info); memset((U8 *) sha_info->data, 0, SHA_BLOCKSIZE - 8); } else { memset(((U8 *) sha_info->data) + count, 0, SHA_BLOCKSIZE - 8 - count); } sha_info->data[56] = (U8)((hi_bit_count >> 24) & 0xff); sha_info->data[57] = (U8)((hi_bit_count >> 16) & 0xff); sha_info->data[58] = (U8)((hi_bit_count >> 8) & 0xff); sha_info->data[59] = (U8)((hi_bit_count >> 0) & 0xff); sha_info->data[60] = (U8)((lo_bit_count >> 24) & 0xff); sha_info->data[61] = (U8)((lo_bit_count >> 16) & 0xff); sha_info->data[62] = (U8)((lo_bit_count >> 8) & 0xff); sha_info->data[63] = (U8)((lo_bit_count >> 0) & 0xff); sha_transform_and_copy(digest, sha_info); } /*----------------------------------------------------------------*/ /* declared above since also used in md5 static const char *hexdigits = "0123456789abcdef"; */ static void hex_20(const unsigned char* from, char* to) { const unsigned char *end = from + 20; char *d = to; while (from < end) { *d++ = hexdigits[(*from >> 4)]; *d++ = hexdigits[(*from & 0x0F)]; from++; } *d = '\0'; } void uu_hash_sha1(pUCXT, struct_uu_t *io, char *name) { /* io is assumed to be a v1 namespace uuid coming in. */ /* do hton*() here. */ /* name is... a name. */ SHA_INFO context; char tmp[41]; char vardig; unsigned char digeststr[21]; uu_t packed; uu_pack_v1(io, (U8*)&packed); sha_init(&context); sha_update(&context, (U8*)&packed, sizeof(packed)); if (name) sha_update(&context, (U8*)name, (int)strlen(name)); sha_final((U8*)&digeststr, &context); digeststr[20] = '\0'; hex_20(digeststr, tmp); tmp[32] = '\0'; /* hyphenate */ Move(&tmp[20], &tmp[21], 12, char); tmp[20] = '-'; Move(&tmp[16], &tmp[17], 17, char); tmp[16] = '-'; Move(&tmp[12], &tmp[13], 22, char); tmp[12] = '-'; Move(&tmp[ 8], &tmp[ 9], 27, char); tmp[ 8] = '-'; tmp[36] = '\0'; /* version */ tmp[14] = '5'; /* variant */ vardig = tmp[19] - 48; if (vardig > 9) vardig -= 7; if (vardig > 15) vardig -= 32; vardig = (vardig & 0x3) | 0x8; if (vardig > 9) vardig += 87; else vardig += 48; tmp[19] = vardig; uu_parse(tmp, io); } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/atomic.c0000644000175000017500000000054615177010206012725 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/atomic.h" #ifdef __cplusplus } #endif #if defined(__OpenBSD__) # if defined(__arm__) # include "ulib/arch/arm/atomic.c" # elif defined(__amd64__) || defined(__x86_64__) # include "ulib/arch/x86/atomic.c" # else # error "unsupported architecture" # endif #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/xoshiro.h0000644000175000017500000000026015176525526013161 0ustar rikrik#ifndef ULIB__XOSHIRO_H #define ULIB__XOSHIRO_H #include "ulib/UUID.h" void uu_xoshiro_srand(pUCXT); U64 uu_xoshiro_rand(pUCXT); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/clock.c0000644000175000017500000001371615176655431012565 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/clock.h" #include "ulib/chacha.h" #include "ulib/gettime.h" #ifdef __cplusplus } #endif #ifdef USE_WIN32_NATIVE #define ftruncate(a,b) _chsize(a,b) #endif #undef open #define state_fd UCXT.clock_state_fd #define state_f UCXT.clock_state_f #define thread_persist UCXT.clock_persist #define adjustment SMEM->clock_adj #define last SMEM->clock_last #define clock_seq SMEM->clock_seq #define prev_reg SMEM->clock_prev_reg #define defer_100ns SMEM->clock_defer_100ns #define global_persist SMEM->clock_persist /* state_fd: * -4 cannot create * -3 untried * -2 symlink * -1 can create * >=0 open fd */ #define STATEFD_NOCREATE -4 #define STATEFD_UNTRIED -3 #define STATEFD_SYMLINK -2 #define STATEFD_CREATEOK -1 /* compare paths, return 0 if same or longer length if not */ static IV persistNE(persist_t *a, persist_t *b) { STRLEN longer = a->len >= b->len ? a->len : b->len; UV i; if (a->len != b->len) return longer; for (i=0 ; ipath[i] != b->path[i]) return longer; return 0; } /* called at boot */ void uu_clock_init(pUCXT) { UV ptod[2]; /* gettimeofday(&tv, 0); */ (*uu_gettime_U2time)(aTHX_ ptod); last.tv_sec = (long)ptod[0]; last.tv_usec = (long)ptod[1]; uu_chacha_rand16(aUCXT, &clock_seq); clock_seq &= 0x3fff; state_fd = STATEFD_UNTRIED; state_f = NULL; adjustment = 0; prev_reg = 0; defer_100ns = 0; Zero(&global_persist, 1, persist_t); Zero(&thread_persist, 1, persist_t); } void uu_clock_getpath(pUCXT, persist_t *persist) { Copy(&global_persist, &thread_persist, 1, persist_t); Copy(&thread_persist, persist, 1, persist_t); } void uu_clock_setpath(pUCXT, persist_t *persist) { Copy(persist, &thread_persist, 1, persist_t); Copy(persist, &global_persist, 1, persist_t); if (state_fd >= 0) fclose(state_f); state_fd = STATEFD_UNTRIED; /* doing this would break inter-process deferrals */ /* prev_reg = 0; */ } /* returns 100ns intervals since unix epoch. * since gettimeofday() is in 1usec intervals, * last digit is simulated via adjustment. */ IV uu_clock(pUCXT, U64 *ret_clock_reg, U16 *ret_clock_seq) { struct timeval tv; mode_t save_umask; U64 clock_reg; STRLEN longer; UV ptod[2]; #ifdef HAVE_LSTAT struct stat statbuf; #endif if ((longer = persistNE(&global_persist, &thread_persist))) { Copy(&global_persist, &thread_persist, longer, UCHAR); if (state_fd >= 0) fclose(state_f); state_fd = STATEFD_UNTRIED; } if (state_fd == STATEFD_UNTRIED) { #ifdef HAVE_LSTAT if (lstat((char*)thread_persist.path, &statbuf) < 0) { /* this covers EINTR too.. ugh */ if (errno == ENOENT) state_fd = STATEFD_CREATEOK; else state_fd = STATEFD_NOCREATE; } else if ((statbuf.st_mode & S_IFMT) == S_IFLNK) state_fd = STATEFD_SYMLINK; else { #endif state_fd = open((char*)thread_persist.path, O_RDWR); if (state_fd < 0 && errno == ENOENT) state_fd = STATEFD_CREATEOK; else if (state_fd >= 0) { #ifdef HAVE_LSTAT state_f = NULL; if ((lstat((char*)thread_persist.path, &statbuf) == 0) && ((statbuf.st_mode & S_IFMT) != S_IFLNK)) #endif state_f = fdopen(state_fd, "r+"); if (!state_f) { close(state_fd); state_fd = STATEFD_SYMLINK; } } #ifdef HAVE_LSTAT } #endif } if (state_fd >= 0) { unsigned int cl; unsigned long tv1, tv2; int a; rewind(state_f); if (fscanf(state_f, "clock: %04x tv: %lu %lu adj: %d\n", &cl, &tv1, &tv2, &a) == 4) { clock_seq = cl & 0x3fff; last.tv_sec = tv1; last.tv_usec = tv2; adjustment = a; } } /* gettimeofday(&tv, 0); */ (*uu_gettime_U2time)(aTHX_ ptod); tv.tv_sec = (long)ptod[0]; tv.tv_usec = (long)ptod[1]; if ((tv.tv_sec == last.tv_sec) && (tv.tv_usec == last.tv_usec)) { /* same time as last */ if (++adjustment >= MAX_ADJUSTMENT) { clock_seq = (clock_seq+1) & 0x3fff; adjustment = 0; } } else { /* time changed */ if (((tv.tv_sec == last.tv_sec) && (tv.tv_usec < last.tv_usec)) || (tv.tv_sec < last.tv_sec)) clock_seq = (clock_seq+1) & 0x3fff; /* time moved backward */ adjustment = 0; last = tv; } clock_reg = tv.tv_usec*10 + adjustment; clock_reg += ((U64)tv.tv_sec)*10000000; /* *clock_reg += (((U64)0x01b21dd2) << 32) + 0x13814000; */ if ((clock_reg - prev_reg) >= defer_100ns) { if (state_fd == STATEFD_CREATEOK) { #ifdef HAVE_LSTAT if ((lstat((char*)thread_persist.path, &statbuf) == 0) && ((statbuf.st_mode & S_IFMT) == S_IFLNK)) state_fd = STATEFD_SYMLINK; else { #endif save_umask = umask(0); state_fd = open((char*)thread_persist.path, O_RDWR|O_CREAT, 0660); if (state_fd < 0) state_fd = STATEFD_NOCREATE; (void) umask(save_umask); if (state_fd >= 0) { #ifdef HAVE_LSTAT state_f = NULL; if ((lstat((char*)thread_persist.path, &statbuf) == 0) && ((statbuf.st_mode & S_IFMT) != S_IFLNK)) #endif state_f = fdopen(state_fd, "r+"); if (!state_f) { close(state_fd); state_fd = STATEFD_SYMLINK; } } #ifdef HAVE_LSTAT } #endif } if (state_fd > 0) { rewind(state_f); long len = fprintf(state_f, "clock: %04x tv: %016lu %08lu adj: %08d\n", clock_seq, (unsigned long)last.tv_sec, (unsigned long)last.tv_usec, adjustment); fflush(state_f); if (ftruncate(state_fd, len) < 0) { fprintf(state_f, " \n"); fflush(state_f); } rewind(state_f); } } prev_reg = clock_reg; /* *clock_high = clock_reg >> 32; */ /* *clock_low = (U32)clock_reg; */ *ret_clock_reg = clock_reg; *ret_clock_seq = clock_seq; return 0; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/FUTX.h0000644000175000017500000000234415176655431012260 0ustar rikrik#ifndef ULIB__FUTX_H #define ULIB__FUTX_H #include "ulib/UUID.h" /* OpenBSD added futex() to libc since syscall mostly blocked from luserland. */ #if defined(__OpenBSD__) #define futex_wait(uaddr, val, timeout) futex(uaddr, FUTEX_WAIT, val, timeout, 0); #define futex_wake(uaddr, val) futex(uaddr, FUTEX_WAKE, val, 0, 0); #endif /* FreeBSD does not have futex() function or syscall. */ /* * Not needed with AcquireSRWLockExclusive(). * #if defined(_WIN32) #include bool futex_wait(LONG *uaddr, LONG val, DWORD timeout); void futex_wake(LONG *uaddr, LONG val); #endif */ /* * Not needed with AcquireSRWLockExclusive(). * #if defined(__CYGWIN__) #include #define futex_wait(uaddr, val, timeout) ({ typeof(*(uaddr)) _val = (val); WaitOnAddress(uaddr, &_val, sizeof(_val), timeout); }) #define futex_wake(uaddr, val) WakeByAddressSingle(uaddr) #endif */ /* * Not needed with switch to sem_wait(). * #if defined(__linux__) #include #include #include #define futex_wait(uaddr, val, timeout) syscall(SYS_futex, uaddr, FUTEX_WAIT, val, timeout, 0, 0); #define futex_wake(uaddr, val) syscall(SYS_futex, uaddr, FUTEX_WAKE, val, 0, 0, 0); #endif */ #endif UUID-0.38/ulib/atomic.h0000644000175000017500000000033315176655431012742 0ustar rikrik#ifndef ULIB__ATOMIC_H #define ULIB__ATOMIC_H #include "ulib/UUID.h" #if defined(__arm__) # include "ulib/arch/arm/atomic.h" #else # include "ulib/arch/x86/atomic.h" #endif #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/hash.h0000644000175000017500000000033615176655431012414 0ustar rikrik#ifndef ULIB__HASH_H #define ULIB__HASH_H #include "ulib/UUID.h" void uu_hash_md5(pUCXT, struct_uu_t *out, char *name); void uu_hash_sha1(pUCXT, struct_uu_t *out, char *name); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/node.h0000644000175000017500000000022615176525526012415 0ustar rikrik#ifndef ULIB__NODE_H #define ULIB__NODE_H #include "ulib/UUID.h" int uu_node_getid(pUCXT, U8 *node_id); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/arch/0000755000175000017500000000000015201361067012217 5ustar rikrikUUID-0.38/ulib/arch/x86/0000755000175000017500000000000015201361067012644 5ustar rikrikUUID-0.38/ulib/arch/x86/atomic.c0000644000175000017500000000157515176655431014310 0ustar rikrik#if defined(_WIN32) LONG cmpxchg(LONG *ptr, LONG old, LONG new) { volatile LONG *_ptr = (volatile LONG *)(ptr); return _InterlockedCompareExchange(_ptr, new, old); } LONG xchg(LONG *ptr, LONG new) { volatile LONG *_ptr = (volatile LONG *)(ptr); return _InterlockedExchange(_ptr, new); } /* _InterlockedDecrement() returns *ptr AFTER the decrement. * * we need value BEFORE decrement. * * LONG xdec(LONG *ptr) { return _InterlockedDecrement(ptr); } */ LONG xdec(LONG *ptr) { LONG r, old; do { old = *ptr; r = cmpxchg(ptr, old, old-1); } while (r != old); return r; } /*****************************************************************************/ #else /* ! _WIN32 */ /*****************************************************************************/ #endif /* _WIN32 */ /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/arch/x86/atomic.h0000644000175000017500000001252415176655431014311 0ustar rikrik#if defined(_WIN32) LONG cmpxchg(LONG *ptr, LONG old, LONG new); LONG xchg(LONG *ptr, LONG new); LONG xdec(LONG *ptr); /*****************************************************************************/ #else /* ! _WIN32 */ /*****************************************************************************/ extern void __compiletime_error(char *s); #define UU_cmpxchg_wrong_size(void) __compiletime_error("Bad argument size for cmpxchg") #define UU_xadd_wrong_size(void) __compiletime_error("Bad argument size for xadd") #define UU_xchg_wrong_size(void) __compiletime_error("Bad argument size for xchg") #define __X86_CASE_B 1 #define __X86_CASE_W 2 #define __X86_CASE_L 4 #define __X86_CASE_Q 8 /* * An exchange-type operation, which takes a value and a pointer, and * returns the old value. */ #define UU_xchg_op(ptr, arg, op) \ ({ \ __typeof__ (*(ptr)) _ret = (arg); \ switch (sizeof(*(ptr))) { \ case __X86_CASE_B: \ asm volatile ("lock; " #op "b %b0, %1\n" \ : "+q" (_ret), "+m" (*(ptr)) \ : : "memory", "cc"); \ break; \ case __X86_CASE_W: \ asm volatile ("lock; " #op "w %w0, %1\n" \ : "+r" (_ret), "+m" (*(ptr)) \ : : "memory", "cc"); \ break; \ case __X86_CASE_L: \ asm volatile ("lock; " #op "l %0, %1\n" \ : "+r" (_ret), "+m" (*(ptr)) \ : : "memory", "cc"); \ break; \ case __X86_CASE_Q: \ asm volatile ("lock; " #op "q %q0, %1\n" \ : "+r" (_ret), "+m" (*(ptr)) \ : : "memory", "cc"); \ break; \ default: \ UU_ ## op ## _wrong_size(); \ } \ _ret; \ }) /* * xadd() adds "inc" to "*ptr" and atomically returns the previous * value of "*ptr". */ #define xadd(ptr, inc) UU_xchg_op((ptr), (inc), xadd) #define xchg(ptr, val) UU_xchg_op((ptr), (val), xchg) #define xinc(ptr) xadd((ptr), 1) #define xdec(ptr) xadd((ptr), -1) typedef unsigned char u8; typedef unsigned int u16; typedef unsigned long int u32; typedef unsigned long long int u64; /* * Atomic compare and exchange. Compare OLD with MEM, if identical, * store NEW in MEM. Return the initial value in MEM. Success is * indicated by comparing RETURN with OLD. */ #define cmpxchg(ptr, old, new) \ ({ \ __typeof__ (*(ptr)) _ret; \ __typeof__ (*(ptr)) _old = (old); \ __typeof__ (*(ptr)) _new = (new); \ switch (sizeof(*(ptr))) { \ case __X86_CASE_B: \ { \ volatile u8 *_ptr = (volatile u8 *)(ptr); \ asm volatile("lock; cmpxchgb %2,%1" \ : "=a" (_ret), "+m" (*_ptr) \ : "q" (_new), "0" (_old) \ : "memory"); \ break; \ } \ case __X86_CASE_W: \ { \ volatile u16 *_ptr = (volatile u16 *)(ptr); \ asm volatile("lock; cmpxchgw %2,%1" \ : "=a" (_ret), "+m" (*_ptr) \ : "r" (_new), "0" (_old) \ : "memory"); \ break; \ } \ case __X86_CASE_L: \ { \ volatile u32 *_ptr = (volatile u32 *)(ptr); \ asm volatile("lock; cmpxchgl %2,%1" \ : "=a" (_ret), "+m" (*_ptr) \ : "r" (_new), "0" (_old) \ : "memory"); \ break; \ } \ case __X86_CASE_Q: \ { \ volatile u64 *_ptr = (volatile u64 *)(ptr); \ asm volatile("lock; cmpxchgq %2,%1" \ : "=a" (_ret), "+m" (*_ptr) \ : "r" (_new), "0" (_old) \ : "memory"); \ break; \ } \ default: \ UU_cmpxchg_wrong_size(); \ } \ _ret; \ }) #endif /* _WIN32 */ /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/arch/arm/0000755000175000017500000000000015201361067012776 5ustar rikrikUUID-0.38/ulib/arch/arm/atomic.c0000644000175000017500000000000015176655431014420 0ustar rikrikUUID-0.38/ulib/arch/arm/atomic.h0000644000175000017500000001760515176655431014450 0ustar rikrik//#include //#include //#include #if defined(CONFIG_CPU_SA1100) || defined(CONFIG_CPU_SA110) /* * On the StrongARM, "swp" is terminally broken since it bypasses the * cache totally. This means that the cache becomes inconsistent, and, * since we use normal loads/stores as well, this is really bad. * Typically, this causes oopsen in filp_close, but could have other, * more disastrous effects. There are two work-arounds: * 1. Disable interrupts and emulate the atomic swap * 2. Clean the cache, perform atomic swap, flush the cache * * We choose (1) since its the "easiest" to achieve here and is not * dependent on the processor type. * * NOTE that this solution won't work on an SMP system, so explcitly * forbid it here. */ #error "StrongARM unimplemented" #define swp_is_buggy #endif #define barrier() asm volatile ("" ::: "memory") #define smp_mb() barrier() #define prefetchw(x) __builtin_prefetch(x,1) extern void __bad_xchg(volatile void *, int); static inline unsigned long __xchg( unsigned long x, volatile void *ptr, int size ) { unsigned long ret; #ifdef swp_is_buggy unsigned long flags; #endif #if __ARM_ARCH >= 6 unsigned int tmp; #endif smp_mb(); prefetchw((const void *)ptr); switch (size) { #if __ARM_ARCH >= 6 case 1: asm volatile("@ __xchg1\n" "1: ldrexb %0, [%3]\n" " strexb %1, %2, [%3]\n" " teq %1, #0\n" " bne 1b" : "=&r" (ret), "=&r" (tmp) : "r" (x), "r" (ptr) : "memory", "cc"); break; case 4: asm volatile("@ __xchg4\n" "1: ldrex %0, [%3]\n" " strex %1, %2, [%3]\n" " teq %1, #0\n" " bne 1b" : "=&r" (ret), "=&r" (tmp) : "r" (x), "r" (ptr) : "memory", "cc"); break; #elif defined(swp_is_buggy) #ifdef CONFIG_SMP #error SMP is not supported on this platform #endif case 1: raw_local_irq_save(flags); ret = *(volatile unsigned char *)ptr; *(volatile unsigned char *)ptr = x; raw_local_irq_restore(flags); break; case 4: raw_local_irq_save(flags); ret = *(volatile unsigned long *)ptr; *(volatile unsigned long *)ptr = x; raw_local_irq_restore(flags); break; #else case 1: asm volatile("@ __xchg1\n" " swpb %0, %1, [%2]" : "=&r" (ret) : "r" (x), "r" (ptr) : "memory", "cc"); break; case 4: asm volatile("@ __xchg4\n" " swp %0, %1, [%2]" : "=&r" (ret) : "r" (x), "r" (ptr) : "memory", "cc"); break; #endif default: __bad_xchg(ptr, size), ret = 0; break; } smp_mb(); return ret; } #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) //#include #if __ARM_ARCH < 6 /* min ARCH < ARMv6 */ #ifdef CONFIG_SMP #error "SMP is not supported on this platform" #endif /* * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make * them available. #define cmpxchg_local(ptr, o, n) \ ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ (unsigned long)(n), sizeof(*(ptr)))) #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) */ #ifndef CONFIG_SMP //#include #endif #else /* min ARCH >= ARMv6 */ extern void __bad_cmpxchg(volatile void *ptr, int size); /* * cmpxchg only support 32-bits operands on ARMv6. */ static inline unsigned long __cmpxchg( volatile void *ptr, unsigned long old, unsigned long new, int size ) { unsigned long oldval, res; prefetchw((const void *)ptr); switch (size) { #ifndef CONFIG_CPU_V6 /* min ARCH >= ARMv6K */ case 1: do { asm volatile("@ __cmpxchg1\n" " ldrexb %1, [%2]\n" " mov %0, #0\n" " teq %1, %3\n" #ifdef __thumb__ " IT eq\n" #endif " strexbeq %0, %4, [%2]\n" : "=&r" (res), "=&r" (oldval) : "r" (ptr), "Ir" (old), "r" (new) : "memory", "cc"); } while (res); break; case 2: do { asm volatile("@ __cmpxchg1\n" " ldrexh %1, [%2]\n" " mov %0, #0\n" " teq %1, %3\n" #ifdef __thumb__ " IT eq\n" #endif " strexheq %0, %4, [%2]\n" : "=&r" (res), "=&r" (oldval) : "r" (ptr), "Ir" (old), "r" (new) : "memory", "cc"); } while (res); break; #endif case 4: do { asm volatile("@ __cmpxchg4\n" " ldrex %1, [%2]\n" " mov %0, #0\n" " teq %1, %3\n" #ifdef __thumb__ " IT eq\n" #endif " strexeq %0, %4, [%2]\n" : "=&r" (res), "=&r" (oldval) : "r" (ptr), "Ir" (old), "r" (new) : "memory", "cc"); } while (res); break; default: __bad_cmpxchg(ptr, size); oldval = 0; } return oldval; } static inline unsigned long __cmpxchg_mb( volatile void *ptr, unsigned long old, unsigned long new, int size ) { unsigned long ret; smp_mb(); ret = __cmpxchg(ptr, old, new, size); smp_mb(); return ret; } #define cmpxchg(ptr,o,n) ( \ (__typeof__(*(ptr)))__cmpxchg_mb( \ (ptr), (unsigned long)(o), (unsigned long)(n), sizeof(*(ptr)) \ ) \ ) /* static inline unsigned long __cmpxchg_local( volatile void *ptr, unsigned long old, unsigned long new, int size ) { unsigned long ret; switch (size) { #ifdef CONFIG_CPU_V6 *//* min ARCH == ARMv6 *//* case 1: case 2: ret = __cmpxchg_local_generic(ptr, old, new, size); break; #endif default: ret = __cmpxchg(ptr, old, new, size); } return ret; } static inline unsigned long long __cmpxchg64( unsigned long long *ptr, unsigned long long old, unsigned long long new ) { unsigned long long oldval; unsigned long res; prefetchw(ptr); __asm__ __volatile__( "1: ldrexd %1, %H1, [%3]\n" " teq %1, %4\n" " teqeq %H1, %H4\n" " bne 2f\n" " strexd %0, %5, %H5, [%3]\n" " teq %0, #0\n" " bne 1b\n" "2:" : "=&r" (res), "=&r" (oldval), "+Qo" (*ptr) : "r" (ptr), "r" (old), "r" (new) : "cc" ); return oldval; } static inline unsigned long long __cmpxchg64_mb( unsigned long long *ptr, unsigned long long old, unsigned long long new ) { unsigned long long ret; smp_mb(); ret = __cmpxchg64(ptr, old, new); smp_mb(); return ret; } #define cmpxchg_local(ptr,o,n) \ ((__typeof__(*(ptr)))__cmpxchg_local((ptr), \ (unsigned long)(o), \ (unsigned long)(n), \ sizeof(*(ptr)))) #define cmpxchg64(ptr, o, n) \ ((__typeof__(*(ptr)))__cmpxchg64_mb((ptr), \ (unsigned long long)(o), \ (unsigned long long)(n))) #define cmpxchg64_relaxed(ptr, o, n) \ ((__typeof__(*(ptr)))__cmpxchg64((ptr), \ (unsigned long long)(o), \ (unsigned long long)(n))) #define cmpxchg64_local(ptr, o, n) cmpxchg64_relaxed((ptr), (o), (n)) */ #endif /* __ARM_ARCH >= 6 */ #define xdec(ptr) ({ \ __typeof__(ptr) _ptr = (ptr); \ __typeof__(*(ptr)) _ret, _old; \ do { \ _old = *_ptr; \ _ret = cmpxchg(_ptr, _old, _old-1); \ } while (_ret != _old); \ _ret; \ }) UUID-0.38/ulib/PORT.h0000644000175000017500000000451115176525526012255 0ustar rikrik#ifndef ULIB__PORT_H #define ULIB__PORT_H #ifdef cBOOL #undef cBOOL #endif #define cBOOL(cbool) ((bool) (cbool)) #ifdef EXPECT #undef EXPECT #ifdef HAS_BUILTIN_EXPECT # define EXPECT(expr,val) __builtin_expect(expr,val) #else # define EXPECT(expr,val) (expr) #endif #endif #ifdef LIKELY #undef LIKELY #define LIKELY(cond) EXPECT(cBOOL(cond),TRUE) #endif #ifdef UNLIKELY #undef UNLIKELY #define UNLIKELY(cond) EXPECT(cBOOL(cond),FALSE) #endif #ifdef PERL_MALLOC_WRAP # ifdef _MEM_WRAP_NEEDS_RUNTIME_CHECK # undef _MEM_WRAP_NEEDS_RUNTIME_CHECK # endif # define _MEM_WRAP_NEEDS_RUNTIME_CHECK(n,t) \ (sizeof(MEM_SIZE) < sizeof(n) || sizeof(t) > ((MEM_SIZE)1 << 8*(sizeof(MEM_SIZE) - sizeof(n)))) # ifdef _MEM_WRAP_WILL_WRAP # undef _MEM_WRAP_WILL_WRAP # endif # define _MEM_WRAP_WILL_WRAP(n,t) \ ((_MEM_WRAP_NEEDS_RUNTIME_CHECK(n,t) ? (MEM_SIZE)(n) : MEM_SIZE_MAX/sizeof(t)) > MEM_SIZE_MAX/sizeof(t)) # ifdef MEM_WRAP_CHECK # undef MEM_WRAP_CHECK # endif # define MEM_WRAP_CHECK(n,t) \ (void)(UNLIKELY(_MEM_WRAP_WILL_WRAP(n,t)) && (Perl_croak_nocontext("panic: memory wrap"),0)) #endif /* PERL_MALLOC_WRAP */ #ifndef MUTEX_LOCK # define MUTEX_LOCK(m) NOOP #endif #ifndef MUTEX_UNLOCK # define MUTEX_UNLOCK(m) NOOP #endif #ifndef MUTEX_INIT # define MUTEX_INIT(m) NOOP #endif #ifndef MUTEX_DESTROY # define MUTEX_DESTROY(m) NOOP #endif #ifndef SVf_THINKFIRST #define SVf_THINKFIRST (SVf_READONLY|SVf_PROTECT|SVf_ROK|SVf_FAKE \ |SVs_RMG|SVf_IsCOW) #endif #ifndef SvTHINKFIRST #define SvTHINKFIRST(sv) (SvFLAGS(sv) & SVf_THINKFIRST #endif #ifndef SV_CHECK_THINKFIRST_COW_DROP #define SV_CHECK_THINKFIRST_COW_DROP(sv) \ if (SvTHINKFIRST(sv)) \ sv_force_normal_flags(sv, SV_COW_DROP_PV) #endif #ifndef CVf_AUTOLOAD #define CvAUTOLOAD_off(cv) NOOP #endif #ifndef ibcmp #define ibcmp Perl_my_ibcmp I32 Perl_my_ibcmp(pTHX_ const char *s1, const char *s2, register I32 len) { register U8 *a = (U8 *)s1; register U8 *b = (U8 *)s2; while (len--) { if (*a != *b && *a != PL_fold[*b]) return 1; a++,b++; } return 0; } #endif #ifndef NOT_REACHED #define NOT_REACHED #endif #ifndef croak_caller #define croak_caller my_croak_caller #endif #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/chacha.c0000644000175000017500000001210015176525526012664 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/chacha.h" #include "ulib/splitmix.h" #include "ulib/xoshiro.h" #ifdef __cplusplus } #endif /* perl versions broken on some platforms */ #undef U8TO16_LE #define U8TO16_LE(p) ( \ ((U16)((p)[0]) ) | \ ((U16)((p)[1]) << 8) \ ) #undef U8TO32_LE #define U8TO32_LE(p) ( \ ((U32)((p)[0]) ) | \ ((U32)((p)[1]) << 8) | \ ((U32)((p)[2]) << 16) | \ ((U32)((p)[3]) << 24) \ ) #undef U8TO64_LE #define U8TO64_LE(p) ( \ ((U64)((p)[0]) ) | \ ((U64)((p)[1]) << 8) | \ ((U64)((p)[2]) << 16) | \ ((U64)((p)[3]) << 24) | \ ((U64)((p)[4]) << 32) | \ ((U64)((p)[5]) << 40) | \ ((U64)((p)[6]) << 48) | \ ((U64)((p)[7]) << 56) \ ) #undef U32TO8_LE #define U32TO8_LE(p, v) do { \ U32 _v = v; \ (p)[0] = (((_v) ) & 0xFFU); \ (p)[1] = (((_v) >> 8) & 0xFFU); \ (p)[2] = (((_v) >> 16) & 0xFFU); \ (p)[3] = (((_v) >> 24) & 0xFFU); \ } while (0) /* perls ROTL32 broken too */ #define rotl32(x,r) ((((U32)(x)) << (r)) | (((U32)(x)) >> (32 - (r)))) #define QROUND(a,b,c,d) \ a += b; d = rotl32(d ^ a, 16); \ c += d; b = rotl32(b ^ c, 12); \ a += b; d = rotl32(d ^ a, 8); \ c += d; b = rotl32(b ^ c, 7); static void chacha_init(pUCXT, const UCHAR *seed, IV init_buffer) { chacha_t *cc = &SMEM->cc; U32 *x = (U32*)&cc->state; x[ 0] = 0x61707865; x[ 1] = 0x3320646e; x[ 2] = 0x79622d32; x[ 3] = 0x6b206574; x[ 4] = U8TO32_LE(seed + 0); x[ 5] = U8TO32_LE(seed + 4); x[ 6] = U8TO32_LE(seed + 8); x[ 7] = U8TO32_LE(seed + 12); x[ 8] = U8TO32_LE(seed + 16); x[ 9] = U8TO32_LE(seed + 20); x[10] = U8TO32_LE(seed + 24); x[11] = U8TO32_LE(seed + 28); x[12] = 0; x[13] = 0; x[14] = U8TO32_LE(seed + 32); x[15] = U8TO32_LE(seed + 36); if (init_buffer) { memset(cc->buf, 0, CC_BUFSZ); cc->have = 0; } } static void chacha_core(pUCXT, UCHAR* buf) { chacha_t *cc = &SMEM->cc; U32 *s = cc->state; U32 i, x[16]; memcpy(x, s, 16*sizeof(U32)); for (i = 0; i= CC_CORESZ) { chacha_core(aUCXT, buf); buf += CC_CORESZ; r -= CC_CORESZ; } if (r > 0) { chacha_core(aUCXT, sbuf); memcpy(buf, sbuf, r); } return n; } static U32 chacha_refill(pUCXT) { chacha_t *cc = &SMEM->cc; U64 *cp; /* refill buffer */ cc->have = chacha_stream(aUCXT, (UCHAR*)&cc->buf, CC_BUFSZ); /* reseed with KEYSZ bytes from buffer, then zero */ /* chacha_init(cc.buf, 0); memset(cc.buf, 0, KEYSZ); cc.have = BUFSZ - KEYSZ; return cc.have; */ /* create new key */ /* UCHAR seed[40]; cp = (U64*)&seed; *cp++ = uu_xoshiro_rand(); *cp++ = uu_xoshiro_rand(); *cp++ = uu_xoshiro_rand(); *cp++ = uu_xoshiro_rand(); *cp++ = uu_xoshiro_rand(); chacha_init((UCHAR*)&seed, 0); return cc.have; */ /* salt the state */ /* cp = (U64*)&cc.state; while (cp < (U64*)&cc.buf) *cp++ ^= (U32)uu_xoshiro_rand(); return cc.have; */ /* salt the buffer */ cp = (U64*)&cc->buf; while (cp < (U64*)&cc->have) *cp++ ^= uu_xoshiro_rand(aUCXT); return cc->have; } void uu_chacha_srand(pUCXT) { U64 d, n, *cp; UCHAR data[40]; uu_splitmix_srand(aUCXT); uu_xoshiro_srand(aUCXT); cp = (U64*)&data; *cp++ = uu_xoshiro_rand(aUCXT); *cp++ = uu_xoshiro_rand(aUCXT); *cp++ = uu_xoshiro_rand(aUCXT); *cp++ = uu_xoshiro_rand(aUCXT); *cp++ = uu_xoshiro_rand(aUCXT); chacha_init(aUCXT, data, 1); /* stir 8 - 39 times */ uu_chacha_rand64(aUCXT, &d); n = 8 + (d >> 59); while (n-- > 0) uu_chacha_rand64(aUCXT, &d); } /* API */ void uu_chacha_rand16(pUCXT, U16 *out) { chacha_t *cc = &SMEM->cc; UCHAR *ptr; if (cc->have < 2) chacha_refill(aUCXT); ptr = cc->buf + CC_BUFSZ - cc->have; cc->have -= 2; *out = U8TO16_LE(ptr); } void uu_chacha_rand32(pUCXT, U32 *out) { chacha_t *cc = &SMEM->cc; UCHAR *ptr; if (cc->have < 4) chacha_refill(aUCXT); ptr = cc->buf + CC_BUFSZ - cc->have; cc->have -= 4; *out = U8TO32_LE(ptr); } void uu_chacha_rand64(pUCXT, U64 *out) { chacha_t *cc = &SMEM->cc; UCHAR *ptr; if (cc->have < 8) chacha_refill(aUCXT); ptr = cc->buf + CC_BUFSZ - cc->have; cc->have -= 8; *out = U8TO64_LE(ptr); } void uu_chacha_rand128(pUCXT, void *out) { chacha_t *cc = &SMEM->cc; U64 a, b; UCHAR *ptr; if (cc->have < 16) chacha_refill(aUCXT); ptr = cc->buf + CC_BUFSZ - cc->have; cc->have -= 16; a = U8TO64_LE(ptr); b = U8TO64_LE(ptr); *((U64*)out) = a; *(((U64*)out)+8) = b; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/xoshiro.c0000644000175000017500000000166115176525526013162 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/xoshiro.h" #include "ulib/splitmix.h" #ifdef __cplusplus } #endif /* based on xoshiro256++ * https://prng.di.unimi.it/xoshiro256plusplus.c */ #define xo_rotl(x,k) (((x) << (k)) | ((x) >> (64 - (k)))) void uu_xoshiro_srand(pUCXT) { U64 n, *xo_s = SMEM->xo_s; xo_s[0] = uu_splitmix_rand(aUCXT); xo_s[1] = uu_splitmix_rand(aUCXT); xo_s[2] = uu_splitmix_rand(aUCXT); xo_s[3] = uu_splitmix_rand(aUCXT); /* stir 16 - 31 times */ n = 16 + (uu_splitmix_rand(aUCXT) >> 60); while (n-- > 0) (void)uu_xoshiro_rand(aUCXT); } U64 uu_xoshiro_rand(pUCXT) { U64 *xo_s = SMEM->xo_s; const U64 result = xo_rotl(xo_s[0] + xo_s[3], 23) + xo_s[0]; const U64 t = xo_s[1] << 17; xo_s[2] ^= xo_s[0]; xo_s[3] ^= xo_s[1]; xo_s[1] ^= xo_s[2]; xo_s[0] ^= xo_s[3]; xo_s[2] ^= t; xo_s[3] = xo_rotl(xo_s[3], 45); return result; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/pack.c0000644000175000017500000001006115176655431012376 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/pack.h" #ifdef __cplusplus } #endif void uu_pack_v0(const struct_uu_t *in, uu_t out) { uu_pack_v1(in, out); } void uu_pack_v1(const struct_uu_t *in, uu_t out) { U32 tmp; tmp = in->v1.time_low; out[3] = (U8)tmp; tmp >>= 8; out[2] = (U8)tmp; tmp >>= 8; out[1] = (U8)tmp; tmp >>= 8; out[0] = (U8)tmp; tmp = in->v1.time_mid; out[5] = (U8)tmp; tmp >>= 8; out[4] = (U8)tmp; tmp = in->v1.time_high_and_version; out[7] = (U8)tmp; tmp >>= 8; out[6] = (U8)tmp; tmp = in->v1.clock_seq_and_variant; out[9] = (U8)tmp; tmp >>= 8; out[8] = (U8)tmp; memcpy(out+10, in->v1.node, 6); } void uu_pack_v3(const struct_uu_t *in, uu_t out) { U32 tmp; tmp = in->v1.time_low; out[3] = (U8)tmp; tmp >>= 8; out[2] = (U8)tmp; tmp >>= 8; out[1] = (U8)tmp; tmp >>= 8; out[0] = (U8)tmp; tmp = in->v1.time_mid; out[5] = (U8)tmp; tmp >>= 8; out[4] = (U8)tmp; tmp = in->v1.time_high_and_version; out[7] = (U8)tmp; tmp >>= 8; out[6] = (U8)tmp; tmp = in->v1.clock_seq_and_variant; out[9] = (U8)tmp; tmp >>= 8; out[8] = (U8)tmp; memcpy(out+10, in->v1.node, 6); } void uu_pack_v4(const struct_uu_t *in, uu_t out) { U32 tmp; tmp = in->v4.rand_a; out[ 3] = (U8)tmp; tmp >>= 8; out[ 2] = (U8)tmp; tmp >>= 8; out[ 1] = (U8)tmp; tmp >>= 8; out[ 0] = (U8)tmp; tmp = in->v4.rand_b_and_version; out[ 7] = (U8)tmp; tmp >>= 8; out[ 6] = (U8)tmp; tmp >>= 8; out[ 5] = (U8)tmp; tmp >>= 8; out[ 4] = (U8)tmp; tmp = in->v4.rand_c_and_variant; out[11] = (U8)tmp; tmp >>= 8; out[10] = (U8)tmp; tmp >>= 8; out[ 9] = (U8)tmp; tmp >>= 8; out[ 8] = (U8)tmp; tmp = in->v4.rand_d; out[15] = (U8)tmp; tmp >>= 8; out[14] = (U8)tmp; tmp >>= 8; out[13] = (U8)tmp; tmp >>= 8; out[12] = (U8)tmp; } void uu_pack_v5(const struct_uu_t *in, uu_t out) { U32 tmp; tmp = in->v1.time_low; out[3] = (U8)tmp; tmp >>= 8; out[2] = (U8)tmp; tmp >>= 8; out[1] = (U8)tmp; tmp >>= 8; out[0] = (U8)tmp; tmp = in->v1.time_mid; out[5] = (U8)tmp; tmp >>= 8; out[4] = (U8)tmp; tmp = in->v1.time_high_and_version; out[7] = (U8)tmp; tmp >>= 8; out[6] = (U8)tmp; tmp = in->v1.clock_seq_and_variant; out[9] = (U8)tmp; tmp >>= 8; out[8] = (U8)tmp; memcpy(out+10, in->v1.node, 6); } void uu_pack_v6(const struct_uu_t *in, uu_t out) { U32 tmp; tmp = in->v6.time_high; out[3] = (U8)tmp; tmp >>= 8; out[2] = (U8)tmp; tmp >>= 8; out[1] = (U8)tmp; tmp >>= 8; out[0] = (U8)tmp; tmp = in->v6.time_mid; out[5] = (U8)tmp; tmp >>= 8; out[4] = (U8)tmp; tmp = in->v6.time_low_and_version; out[7] = (U8)tmp; tmp >>= 8; out[6] = (U8)tmp; tmp = in->v6.clock_seq_and_variant; out[9] = (U8)tmp; tmp >>= 8; out[8] = (U8)tmp; memcpy(out+10, in->v6.node, 6); } void uu_pack_v7(const struct_uu_t *in, uu_t out) { U64 tmp; tmp = in->v7.time_high; out[3] = (U8)tmp; tmp >>= 8; out[2] = (U8)tmp; tmp >>= 8; out[1] = (U8)tmp; tmp >>= 8; out[0] = (U8)tmp; tmp = in->v7.time_low; out[5] = (U8)tmp; tmp >>= 8; out[4] = (U8)tmp; tmp = in->v7.rand_a_and_version; out[7] = (U8)tmp; tmp >>= 8; out[6] = (U8)tmp; tmp = in->v7.rand_b_and_variant; out[15] = (U8)tmp; tmp >>= 8; out[14] = (U8)tmp; tmp >>= 8; out[13] = (U8)tmp; tmp >>= 8; out[12] = (U8)tmp; tmp >>= 8; out[11] = (U8)tmp; tmp >>= 8; out[10] = (U8)tmp; tmp >>= 8; out[ 9] = (U8)tmp; tmp >>= 8; out[ 8] = (U8)tmp; } void uu_pack_unpack(const uu_t in, struct_uu_t *out) { const U8 *ptr = in; U32 tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; tmp = (tmp << 8) | *ptr++; tmp = (tmp << 8) | *ptr++; out->v1.time_low = tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; out->v1.time_mid = (U16)tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; out->v1.time_high_and_version = (U16)tmp; tmp = *ptr++; tmp = (tmp << 8) | *ptr++; out->v1.clock_seq_and_variant = (U16)tmp; out->v1.node[0] = *ptr++; out->v1.node[1] = *ptr++; out->v1.node[2] = *ptr++; out->v1.node[3] = *ptr++; out->v1.node[4] = *ptr++; out->v1.node[5] = *ptr; } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/util.h0000644000175000017500000000064115176655431012445 0ustar rikrik#ifndef ULIB__UTIL_H #define ULIB__UTIL_H #include "ulib/UUID.h" void my_croak_caller(const char *pat, ...); void uu_clear(struct_uu_t *io); void uu_copy_binary(pUCXT, const uu_t in, uu_t out); void uu_copy_struct(pUCXT, const struct_uu_t *in, struct_uu_t *out); NV uu_time(const struct_uu_t *in); UV uu_type(const struct_uu_t *in); UV uu_variant(const struct_uu_t *in); #endif /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/ulib/node.c0000644000175000017500000001047115176525526012413 0ustar rikrik#ifdef __cplusplus extern "C" { #endif #include "ulib/node.h" #ifdef __cplusplus } #endif /* * BSD 4.4 defines the size of an ifreq to be * max(sizeof(ifreq), sizeof(ifreq.ifr_name)+ifreq.ifr_addr.sa_len * However, under earlier systems, sa_len isn't present, so the size is * just sizeof(struct ifreq) */ #ifndef max # define max(a,b) ((a) > (b) ? (a) : (b)) #endif #ifdef HAVE_SA_LEN # define ifreq_size(i) \ max( \ sizeof(struct ifreq), \ sizeof((i).ifr_name) + (i).ifr_addr.sa_len \ ) #else # define ifreq_size(i) sizeof(struct ifreq) #endif /* HAVE_SA_LEN*/ static int try_unix_node(pUCXT, U8 *node_id){ #ifdef HAVE_NET_IF_H struct ifconf ifc; struct ifreq ifr, *ifrp; #ifdef HAVE_NET_IF_DL_H struct sockaddr_dl *sdlp; #endif unsigned char *a; int i, n, sd; char buf[1024]; if ((sd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP)) < 0) return -1; Zero(buf, sizeof(buf), char); ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(sd, SIOCGIFCONF, (char*)&ifc) < 0) { close(sd); return -1; } n = ifc.ifc_len; for (i = 0 ; i < n ; i += ifreq_size(*ifrp)) { ifrp = (struct ifreq*)((char*)ifc.ifc_buf + i); Copy(ifrp->ifr_name, ifr.ifr_name, IFNAMSIZ, char); #if defined(SIOCGIFHWADDR) && ( defined(ifr_hwaddr) || defined(ifr_addr) ) if (ioctl(sd, SIOCGIFHWADDR, &ifr) < 0) continue; # ifdef ifr_hwaddr a = (unsigned char*)&ifr.ifr_hwaddr.sa_data; # else # ifdef ifr_addr a = (unsigned char*)&ifr.ifr_addr.sa_data; # endif /* ifr_addr */ # endif /* ifr_hwaddr */ #else # ifdef SIOCGENADDR if (ioctl(sd, SIOCGENADDR, &ifr) < 0) continue; a = (unsigned char*)ifr.ifr_enaddr; # else # ifdef HAVE_NET_IF_DL_H sdlp = (struct sockaddr_dl*)&ifrp->ifr_addr; if ((sdlp->sdl_family != AF_LINK) || (sdlp->sdl_alen != 6)) continue; a = (unsigned char*)&sdlp->sdl_data[sdlp->sdl_nlen]; # else /* XXX any other way of finding hardware address? */ close(sd); return 0; # endif /* HAVE_NET_IF_DL_H */ # endif /* SIOCGENADDR */ #endif /*SIOCGIFHWADDR */ if (!a[0] && !a[1] && !a[2] && !a[3] && !a[4] && !a[5]) continue; if (node_id) { memcpy(node_id, a, 6); close(sd); return 1; } } close(sd); #endif /* HAVE_NET_IF_H */ return 0; } static int try_windows_node(pUCXT, U8 *node_id) { int rv = 0; #ifdef USE_WIN32_NATIVE #ifdef HAVE_IPHLPAPI_H IP_ADAPTER_ADDRESSES *pAddr = NULL; IP_ADAPTER_ADDRESSES *pCurr = NULL; DWORD dwRetVal = 0; ULONG outBufLen = 8 * 1024; unsigned int i; rv = -1; for (i = 0 ; i < 3 ; ++i) { Newc(0, pAddr, outBufLen, char, IP_ADAPTER_ADDRESSES); if (pAddr == NULL) break; dwRetVal = GetAdaptersAddresses(AF_INET, 0, NULL, pAddr, &outBufLen); if (dwRetVal == ERROR_SUCCESS) { rv = 0; break; } if (dwRetVal != ERROR_BUFFER_OVERFLOW) { break; } Safefree(pAddr); pAddr = NULL; } if (rv == 0) { pCurr = pAddr; while (pCurr) { if ( pCurr->OperStatus == IfOperStatusUp && pCurr->IfType != IF_TYPE_SOFTWARE_LOOPBACK && pCurr->PhysicalAddressLength == 6 ) { /* printf("# Physical address:\n"); for (i = 0; i < (int) pCurr->PhysicalAddressLength; i++) { if (i == (pCurr->PhysicalAddressLength - 1)) printf("# %.2X\n", (int) pCurr->PhysicalAddress[i]); else printf("# %.2X-", (int) pCurr->PhysicalAddress[i]); } */ node_id[0] = pCurr->PhysicalAddress[0]; node_id[1] = pCurr->PhysicalAddress[1]; node_id[2] = pCurr->PhysicalAddress[2]; node_id[3] = pCurr->PhysicalAddress[3]; node_id[4] = pCurr->PhysicalAddress[4]; node_id[5] = pCurr->PhysicalAddress[5]; rv = 1; break; } pCurr = pCurr->Next; } } if (pAddr) Safefree(pAddr); #endif /* HAVE_IPHLPAPI_H */ #endif /* USE_WIN32_NATIVE */ return rv; } int uu_node_getid(pUCXT, U8 *node_id) { /* returns: * -1 if cant find due to error. * 0 if cant find. * 1 if found. */ return try_unix_node(aUCXT, node_id) || try_windows_node(aUCXT, node_id); } /* ex:set ts=2 sw=2 itab=spaces: */ UUID-0.38/META.json0000644000175000017500000000446315201361070011771 0ustar rikrik{ "abstract" : "Universally Unique Identifier library for Perl", "author" : [ "Rick Myers " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 7.76, CPAN::Meta::Converter version 2.150010", "license" : [ "artistic_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "UUID", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "Config" : "0", "Devel::CheckLib" : "1.14", "ExtUtils::MakeMaker" : "7.06", "File::Spec" : "0", "File::Temp" : "0.10", "blib" : "0", "strict" : "0", "warnings" : "0" } }, "configure" : { "requires" : { "Config" : "0", "Devel::CheckLib" : "1.14", "ExtUtils::MakeMaker" : "7.06", "File::Spec" : "0", "File::Temp" : "0.10", "strict" : "0", "warnings" : "0" } }, "runtime" : { "requires" : { "Carp" : "0", "DynaLoader" : "0", "Exporter" : "0", "Time::HiRes" : "0", "blib" : "0", "perl" : "5.008001", "strict" : "0", "vars" : "0", "warnings" : "0" } }, "test" : { "requires" : { "Benchmark" : "0", "CPAN::Meta" : "0", "Config" : "0", "DynaLoader" : "0", "Exporter" : "0", "ExtUtils::Manifest" : "0", "Fcntl" : "0", "File::Spec" : "0", "File::Temp" : "0.10", "Thread::Semaphore" : "0", "Time::HiRes" : "0", "Try::Tiny" : "0", "blib" : "0", "strict" : "0", "threads" : "0", "threads::shared" : "0", "vars" : "0", "version" : "0.77", "warnings" : "0" } } }, "provides" : { "UUID" : { "file" : "lib/UUID.pm", "version" : "0.38" } }, "release_status" : "stable", "version" : "0.38", "x_serialization_backend" : "JSON::PP version 4.16" } UUID-0.38/Changes0000644000175000017500000002456415201360777011664 0ustar rikrikRevision history for Perl extension UUID. 0.38 Thu May 14 10:52:38 EDT 2026 - Use system randomness for seeding internal PRNG. Source is platform-specific and preferred in the following order, if available: - arc4random() - BCryptGenRandom() - CryptGenRandom() - getentropy() - getrandom() - /dev/urandom - Move internal context to anonymous mmap to synchronize timestamps between multiple processes or threads. This also means random numbers from all processes/threads now come from a common pool, eliminating chance of parallel duplication. - Improved internal context locking, switching away from pthreads due to cross-platform inconsistencies with respect to process-shared mutexes. Now OpenBSD uses futex, Win32 uses SRWLocks, and OSX uses GCD. Everywhere else uses sem_wait. These solutions were promoted to top-tier after realizing they would have to be done anyway as fallbacks for pthreads. - Add internal try/catch to ensure locks are not orphaned and avoid deadlock in fork/thread scenarios. - Fix off-by-one in time adjustment causing occasional duplication on very fast hosts. (Over 10M UUIDs/sec, so probably never seen in production.) See, for example: https://www.cpantesters.org/cpan/report/f26eddf4-dc5c-11f0-baa1-832b6e8775ea - Scroll to failed test t/3unique/v6.t - Notice the first 3 digit groups of each UUID. - For v6 UUIDs, the first 3 groups are basically system time in 100ns steps. - The first 12 UUIDs are increasing 1 count each. - The next 11 UUIDs are also increasing 1 count each, repeating the same times as the first 12. The sequence field (the 4th digit group) has increased though, so this is okay. - The 24th UUID repeats the 23rd. - The burst ends with the 28th UUID. - Sped up t/3unique non-forking tests to tickle off-by-one bug. - Make t/3unique fork/prefork tests run in parallel. - Make t/8threads tests try harder to produce dupes. - Add fork/prefork tests for uncovered UUID versions. - Drop Test::More in favor of lighter, faster, homegrown module. 0.37 Mon Feb 24 04:25:27 EST 2025 - Fix build under gcc-15 default ISO C23. - Thanks Petr Pisar. [rt.cpan.org #159112] 0.36 Sat Jun 22 21:24:39 EDT 2024 - Fix distro tests run from read-only location. - Thanks Petr Pisar. [rt.cpan.org #153854] 0.35 Wed May 29 14:40:34 EDT 2024 - Reworked persist file handling for speed. - Reworked seeding for front-loading prefork processes. - Thanks again to Christopher Rasch-Olsen Raa. 0.34 Mon Apr 29 21:03:51 EDT 2024 - Added version 3 and 5 UUIDs. - Added deferred persistence, default 0.001 seconds. - Now forces reseed after fork(). - Thanks to Christopher Rasch-Olsen Raa. [rt.cpan.org #152751] 0.33 Sat Mar 16 07:34:19 EDT 2024 - Removed most bundled e2fsprogs UUID code. - Added :mac=random/unique to hide real MAC. - Fixed finding mac address on native Win32 builds. - Added version 6 and 7 UUIDs. - Switched to ChaCha20 as RNG salted with Xoshiro256++. - Added uuid1(), uuid4() to return strings directly. - Added generate_v1() and generate_v4() for binaries. - Fixed duplicate Win32 random UUIDs when > 1K/sec. - Fixed Win32 v1 throttling when > 10K/sec. - Fixed duplicate v1 UUIDs everywhere when > 10M/sec. - Exposed persistent state function. - Added :persist to make state path configurable. - Fixed possible symlink attack on persistent file. - Added generate_v0() and uuid0() to generate null UUIDs. - Added benchmarks in tests. > make test TEST_VERBOSE=1 TEST_FILES=t/9benchmark/*.t - Added benchmark comparing version speeds, calling styles, and persistence. > make compare - Now believed to be thread safe. 0.32 Tue Dec 12 23:23:51 EST 2023 - Expose uuid_type(). - Expose uuid_variant(). - Expose uuid_time(). - Remove dependence on system libraries. - Update POD. 0.31 Mon Nov 6 23:43:58 EST 2023 - Make generated metafiles authoritative and test. - Thanks to twata. [rt.cpan.org #150311] - Re-enable warnings, per Kwalitee. - Rename License to LICENSE, per Kwalitee. - Add 'provides' info to metafiles, per Kwalitee. - Add test deps, per Kwalitee. - Switch to non-system types. - Fix make order. - Fix misguided config.h. - Fix missing prototypes. - Fix missing patch. - Split to two level diff utils. 0.30 Tue Oct 31 17:16:50 EDT 2023 - Bump ExtUtils::MakeMaker prereq to 6.64 (first version supporting TEST_REQUIRES). - Better support for older Win32. - Fix trivial build warnings. 0.29 Wed Oct 25 01:15:57 EDT 2023 - Bump prereq version for Devel::CheckLib to 1.14 to fix problems with Strawberry versions 5.18 to 5.28. Earlier Strawberry did not ship Devel::CheckLib. Newer versions shipped 1.14 or later. - Thanks to twata. [rt.cpan.org #143841] 0.28 Sat Dec 29 00:59:25 EST 2018 - Add OSSP variant of libuuid. CentOS7 (and presumably other RedHat derivatives) have packages for both OSSP and e2fs. Favor e2fs, if found, since our implementation of OSSP is probably slower. - Thanks to Greg Cox. [rt.cpan.org #128122] 0.27 Fri Sep 23 01:52:00 EDT 2016 - Update SYNOPSIS to remove ":all". Indiscriminate exports could cause problems with other modules, such as File::Copy::copy(). - Thanks to Slaven Rezic. [rt.cpan.org #118033] 0.26 Sat May 7 02:32:52 EDT 2016 - Fix broken @ARGV handling in Makefile.PL regarding debug flag. - Also changed DEBUG flag to UUID_DEBUG - Thanks to gregor herrmann. [rt.cpan.org #114213] 0.25 Mon Mar 14 10:15:55 EDT 2016 - Changed all prints in Makefile.PL to warns and made both unbuffered to match Devel::CheckLib - Remove uuid_unparse_lower/upper() calls which don't exist on SunOS - Ignore TEST_REQUIRES on EUMM < 6.64 - Try to find correct link lib (-lrpcrt4, -luuid, -lc, in order) - Make string argument a char** for uuid_to_string() - Add note on Linux UUID packages - Moved test.pl to t/test.t and updated to Test::More - Changed debug() to emit to stderr to match Devel::CheckLib - Removed Makefile.PL verbosity - Added switch to Makefile.PL to incite verbosity - Become verbose for smokers only on dev releases - Added build notice for missing header/libraries - Bail out of build if uuid_t size == 0 - Reorganized header/library search to find wayward OSX - Thanks to David Wheeler and William Faulk for pointers and lots of patience in testing. [rt.cpan.org #104394] 0.24 Mon Jan 19 01:05:14 EST 2015 - Add 'extern "C"' for g++ 0.23 Sun Dec 28 18:58:04 EST 2014 - Reverse order of rpc.h and rpcdce.h in UUID.xs (rpc.h first) 0.22 Sun Dec 28 08:42:23 EST 2014 - Ugh! Forgot to include rpcdce.h in UUID.xs 0.21 Sun Dec 28 08:35:23 EST 2014 - Instead of unistd.h, try rpcdce.h on Win - Minor cleanup in test.pl 0.20 Sat Dec 27 19:27:28 EST 2014 - Also include unistd.h when using Rpc.h (Win) - Fix pointer problem in -luuid search on Win - Fix minor header propagation problem in Makefile.PL 0.19 Fri Dec 26 17:09:12 EST 2014 - Fix pointer confusion in do_uuid() on BSD [rt.cpan.org #101137] 0.18 Fri Dec 26 08:20:06 EST 2014 - Allow for non-true/false return from uuid_from_string() on BSD - Remove unused dependency on Config.pm - Added yet more debug info for 'make test' time - Change -DPERL__UUID__UUID_BUF_SZ to -DPERL__UUID__STRUCT_SZ 0.17 Fri Dec 26 05:05:13 EST 2014 - Removed two nested comments on BSD /* sigh */ - Let e2fs machines use sv_cmp too (let's see if OSX Frankenbox works) - Changed warns in Makefile.PL to prints 0.16 Thu Dec 25 18:24:23 EST 2014 - Typo on Windows/BSD - Trying sv_cmp() instead of uuid_compare() on RPC-based machines 0.15 Thu Dec 25 05:55:13 EST 2014 - REALLY fix do_uuid() typo. Really. - Fix pointer problems on BSD - Removed uuid_copy() from BSD. How did that get there? =) - Added yet another test for OSX segfault! - Check and set -DPERL__UUID__UUID_BUF_SZ=?? in Makefile.PL (Should be the same everywhere, right? Right?) 0.14 Wed Dec 24 22:39:42 EST 2014 - Fix typo in Windows do_uuid() for compiler fail on strawberry - Now checking for all header files instead of taking first - Added more detail for failed interface search - Added check for uuid struct size 0.13 Wed Dec 24 07:45:49 EST 2014 - Split -luuid search into header file and interface type stages - Removed SvPV_nolen everywhere (buffer overflows) 0.12 Wed Dec 24 03:07:50 EST 2014 - Added support for non-e2fs systems (BSD, OSX, Win) 0.11_01 Tue Dec 23 20:23:29 EST 2014 - Modified test.pl to hopefully catch where MacOSX fails - Heavy mods to Makefile.PL to differentiate between interfaces - Makefile.PL *lots* more verbose - Lots of #ifdefs added in XS - First shot at code that works for BSD style interface 0.11 Mon Dec 22 19:03:09 EST 2014 - Looks like I've managed to cut the failure reports down a little TOO far, so now splitting the search for -luuid into two separate phases. The first, which I don't want to deal with right now, tests for usability of the -luuid flag by itself. The second, tests for usability of individual functions. We'll deal with platforms that actually find libuuid first, then MAYBE revisit others. 0.10 Mon Dec 22 11:55:30 EST 2014 - Added clear() and is_null() - Added copy() and compare() - Added unparse_lower() and unparse_upper() - Added generate_random() and generate_time() 0.09 Mon Dec 22 04:31:26 EST 2014 - Drag test.pl into this century using Test.pm - Add postamble to Makefile to generate README - Overhaul POD - Fix MacOS warning "unsigned char* <--> char*" 0.08 Sun Dec 21 06:06:21 EST 2014 - Added README with pod2text UUID.pm README - Switched libuuid search to Devel::CheckLib 0.07 Sat Dec 20 21:12:17 EST 2014 - Updated Makefile.PL - Added search for -luuid at Makefile.PL time - Updated license and POD to Artistic 2.0 0.06 Thu Dec 18 08:01:44 EST 2014 - Took over maintaining (Rick Myers - JRM) - Added uuid() 0.05 Fri Dec 14 20:00:00 GMT 2012 - Took over maintaining (Lukas Zapletal - LZAP) - Version bump (no changes) - Releasing in the original location 0.04 Wed Jul 22 20:17:26 PDT 2009 - Seems to be abandoned (again) - Bump version number and upload to PAUSE 0.03 Fri Jan 12 15:24:24 MST 2007 - Added Artistic license - Took over maintaining (Colin Faber - CFABER) 0.02 Unknown - unknown changes 0.01 Thu Feb 8 06:07:59 2001 - original version; created by h2xs 1.20 with options -A -n UUID UUID-0.38/lib/0000755000175000017500000000000015201361067011115 5ustar rikrikUUID-0.38/lib/UUID.pm0000644000175000017500000004574515201356241012236 0ustar rikrikpackage UUID; require 5.005063; # see MIN_PERL_VERSION in Makefile.PL use strict; use warnings; use Carp 'croak'; require Exporter; require DynaLoader; use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK $VERSION); @ISA = qw(DynaLoader); $VERSION = '0.38'; %EXPORT_TAGS = ( 'all' => [qw( &clear &compare © &generate &generate_random &generate_time &generate_v0 &generate_v1 &generate_v3 &generate_v4 &generate_v5 &generate_v6 &generate_v7 &is_null &parse &time &type &unparse &unparse_lower &unparse_upper &uuid &uuid0 &uuid1 &uuid3 &uuid4 &uuid5 &uuid6 &uuid7 &variant &version )], ); @EXPORT_OK = @{$EXPORT_TAGS{'all'}}; bootstrap UUID $VERSION; sub import { for (my $i=scalar(@_)-1 ; $i>0 ; --$i) { my $v = $_[$i]; chomp $v; # :persist=FOO if (length($v) > 8 and substr($v,0,8) eq ':persist') { my $arg = substr $v, 8; if (length($arg) < 2 or substr($arg, 0, 1) ne '=') { croak "Usage: :persist=FILE"; } my $file = substr $arg, 1; _persist($file); splice @_, $i, 1; next; } # :mac=random if (length($v) == 11 and $v eq ':mac=random') { _hide_mac(); splice @_, $i, 1; next; } # :mac=unique if (length($v) == 11 and $v eq ':mac=unique') { _hide_always(); splice @_, $i, 1; next; } # :defer[=N] if (length($v) >= 6 and substr($v,0,6) eq ':defer') { my $arg = substr $v, 6; my $len = length $arg; if ($len == 0) { $arg = '=0.001'; } elsif ($len == 1 or substr($arg, 0, 1) ne '=') { croak "Usage: :defer[=N]"; } my $val = substr $arg, 1; _defer($val); splice @_, $i, 1; next; } } goto &Exporter::import; } # Preloaded methods go here. 1; __END__ =head1 NAME UUID - Universally Unique Identifier library for Perl =head1 SYNOPSIS use UUID qw(uuid); # see EXPORTS my $str = uuid(); # generate version 4 UUID string $str = uuid1(); # new version 1 UUID string $str = uuid4(); # new version 4 UUID string $str = uuid6(); # new version 6 UUID string $str = uuid7(); # new version 7 UUID string UUID::generate_v1($bin); # new version 1 binary UUID UUID::generate_v4($bin); # new version 4 binary UUID UUID::generate_v6($bin); # new version 6 binary UUID UUID::generate_v7($bin); # new version 7 binary UUID UUID::parse($str, $bin); # map string to binary UUID UUID::unparse($bin, $str); # stringify $bin; prefer lowercase UUID::compare($bin1, $bin2); # compare binary UUIDs UUID::copy($dst, $src); # copy binary UUID from $src to $dst UUID::clear($bin); # set binary UUID to NULL UUID::is_null($bin); # compare binary UUID to NULL UUID::time($bin); # return UUID time UUID::type($bin); # return UUID type UUID::variant($bin); # return UUID variant UUID::version($bin); # return UUID version UUID::generate($bin); # alias for generate_v1() UUID::generate_time($bin); # alias for generate_v1() UUID::generate_random($bin); # alias for generate_v4() UUID::unparse_lower($bin, $str); # force lowercase stringify UUID::unparse_upper($bin, $str); # force uppercase stringify # NAMESPACE is 'dns', 'url', 'oid', or 'x500'; case-insensitive. $str = uuid3(dns => 'www.example.com'); $str = uuid5(url => 'https://www.example.com/foo.html'); UUID::generate_v3($bin, dns => 'www.example.com'); UUID::generate_v5($bin, url => 'https://www.example.com/foo.txt'); =head1 DESCRIPTION The UUID library is used to generate unique identifiers for objects that may be accessible beyond the local system. For instance, they could be used to generate unique HTTP cookies across multiple web servers without communication between the servers, and without fear of a name clash. The generated UUIDs can be reasonably expected to be unique within a system, and unique across all systems, and are compatible with those created by the Open Software Foundation (OSF) Distributed Computing Environment (DCE). All generated UUIDs are either version 1, 3, 4, 5, 6, or version 7. And all are variant 1, meaning compliant with the OSF DCE standard as described in RFC4122. Versions 6 and 7 are not yet standardized. They are presented here as proposed in RFC4122bis, version 14, and may change in the future. RFC4122bis is noted to replace RFC4122, if approved. =head1 FUNCTIONS Most of the UUID functions expose the historically underlying I C interface rather directly. That is, many return their values in their parameters and nothing else. Not very Perlish, but it's been like that for a long time so not likely to change any time soon. All take or return UUIDs in either binary or string format. The string format resembles the following: 21b081a3-de83-4480-a14f-e89a1dcf8f0f Or, in terms of printf(3) format: "%08x-%04x-%04x-%04x-%012x" The binary form is simply a packed 16 byte binary value. =head2 B I<$uuid> B<)> Sets binary I<$uuid> equal to the value of the NULL UUID. =head2 B I<$uuid1>B<,> I<$uuid2> B<)> Compares two binary UUIDs. Returns an integer less than, equal to, or greater than zero if I<$uuid1> is less than, equal to, or greater than I<$uuid2>. If one is defined and the other not, the defined value is deemed the larger. If either operand is not a binary UUID, falls back to a simple string comparison returning similar values. =head2 B I<$dst>B<,> I<$src> B<)> Copies the binary I<$src> UUID to I<$dst>. If I<$src> isn't a UUID, I<$dst> is set to the NULL UUID. =head2 B I<$uuid> B<)> Alias for B. Prior to version 0.33, this function provided either a binary version 4 UUID or fell back to version 1 in some cases. This is no longer the case. The fallback feature was removed with the addition of an onboard crypto-strength number generator. =head2 B I<$uuid> B<)> Alias for B. =head2 B I<$uuid> B<)> Alias for B. =head2 B I<$uuid> B<)> Generates a new version 1 binary UUID using the current time and the local ethernet MAC address, if available. If the MAC address is not available at startup, or a randomized address is requested (see B<:mac> in B), a random address is used. The multicast bit of this address is set to avoid conflict with addresses returned from network cards. =head2 B I<$uuid>, I => I B<)> Generate a new version 3 binary UUID using the given namespace and name hashed through the MD5 algorithm. Namespace is one of "dns", "url", "oid", or "x500", and case-insensitive. It is used to select the namespace UUID to hash with the name. Name should be an entity from the given namespace, but can really be any text. =head2 B I<$uuid> B<)> Generates a new version 4 binary UUID using mostly random data. There are 6 bits used for the UUID format, leaving 122 bits for randomness. =head2 B I<$uuid>, I => I B<)> Generate a new version 5 binary UUID using the given namespace and name hashed through the SHA1 algorithm. Namespace is one of "dns", "url", "oid", or "x500", and case-insensitive. It is used to select the namespace UUID to hash with the name. Name should be an entity from the given namespace, but can really be any text. =head2 B I<$uuid> B<)> Generates a new version 6 binary UUID using the current time and the local ethernet MAC address, if available. If the MAC address is not available at startup, or a randomized address is requested (see B<:mac> in B), a random address is used. The multicast bit of this address is set to avoid conflict with addresses returned from network cards. Version 6 is the same as version 1, with reversed time fields to make it more database friendly. =head2 B I<$uuid> B<)> Generates a new version 7 binary UUID using the current time and random data. There are 6 bits used for the UUID format and 48 bits for timestamp, leaving 74 bits for randomness. Version 7 is the same as version 6, in that it uses reversed timestamp fields, but also uses a Unix epoch time base instead of Gregorian. =head2 B I<$uuid> B<)> Compares the value of I<$uuid> to the NULL UUID. Returns 1 if NULL, and 0 otherwise. =head2 B I<$string>B<,> I<$uuid> B<)> Converts the string format UUID in I<$string> to binary and returns in I<$uuid>. The previous content of I<$uuid>, if any, is lost. Returns 0 on success and -1 on failure. Additionally on failure, the content of I<$uuid> is unchanged. =head2 B I<$uuid> B<)> Returns the time element of a binary UUID in seconds since the epoch, the same as I's B