From 90ab599dd15982b8702dbcf9dd7b8063b1872805 Mon Sep 17 00:00:00 2001 From: "William A. Rowe Jr" Date: Tue, 7 Jun 2005 18:16:12 +0000 Subject: [PATCH] Sandbox of apr/trunk/ for fips integration. Here may lurk fips issues (MD5 etc) git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/fips-dev@188837 13f79535-47bb-0310-9956-ffa450edef68 --- srclib/apr/CHANGES | 1942 ++++++++++++++ srclib/apr/LICENSE | 297 +++ srclib/apr/Makefile.in | 124 + srclib/apr/NOTICE | 9 + srclib/apr/NWGNUmakefile | 405 +++ srclib/apr/README.dev | 30 + srclib/apr/STATUS | 467 ++++ srclib/apr/apr-config.in | 250 ++ srclib/apr/apr.dsp | 651 +++++ srclib/apr/apr.dsw | 71 + srclib/apr/apr.pc.in | 11 + srclib/apr/atomic/netware/apr_atomic.c | 70 + srclib/apr/atomic/os390/atomic.c | 96 + srclib/apr/atomic/unix/apr_atomic.c | 393 +++ srclib/apr/atomic/win32/apr_atomic.c | 123 + srclib/apr/build.conf | 26 + srclib/apr/build/MakeEtags | 39 + srclib/apr/build/NWGNUenvironment.inc | 304 +++ srclib/apr/build/NWGNUhead.inc | 96 + srclib/apr/build/NWGNUmakefile | 94 + srclib/apr/build/NWGNUtail.inc | 322 +++ srclib/apr/build/PrintPath | 129 + srclib/apr/build/aplibtool.c | 755 ++++++ srclib/apr/build/apr_app.dsp | 89 + srclib/apr/build/apr_common.m4 | 954 +++++++ srclib/apr/build/apr_hints.m4 | 464 ++++ srclib/apr/build/apr_network.m4 | 746 ++++++ srclib/apr/build/apr_rules.mk.in | 207 ++ srclib/apr/build/apr_threads.m4 | 244 ++ srclib/apr/build/buildcheck.sh | 66 + srclib/apr/build/config.guess | 1449 +++++++++++ srclib/apr/build/config.sub | 1552 +++++++++++ srclib/apr/build/cvtdsp.pl | 490 ++++ srclib/apr/build/find_apr.m4 | 166 ++ srclib/apr/build/fixwin32mak.pl | 76 + srclib/apr/build/gen-build.py | 172 ++ srclib/apr/build/get-version.sh | 37 + srclib/apr/build/install.sh | 112 + srclib/apr/build/jlibtool.c | 1857 ++++++++++++++ srclib/apr/build/libapr_app.dsp | 93 + srclib/apr/build/lineends.pl | 149 ++ srclib/apr/build/make_exports.awk | 150 ++ srclib/apr/build/make_nw_export.awk | 78 + srclib/apr/build/make_var_export.awk | 59 + srclib/apr/build/mkdir.sh | 37 + srclib/apr/build/nw_export.inc | 82 + srclib/apr/build/nw_ver.awk | 25 + srclib/apr/build/pkg/README | 20 + srclib/apr/build/pkg/buildpkg.sh | 72 + srclib/apr/build/pkg/pkginfo.in | 11 + srclib/apr/build/prebuildNW.bat | 48 + srclib/apr/build/rpm/apr.spec.in | 96 + srclib/apr/build/run-gcov.sh | 130 + srclib/apr/build/win32ver.awk | 121 + srclib/apr/buildconf | 102 + srclib/apr/config.layout | 231 ++ srclib/apr/configure.in | 2075 +++++++++++++++ srclib/apr/docs/APRDesign.html | 399 +++ srclib/apr/docs/canonical_filenames.html | 156 ++ srclib/apr/docs/doxygen.conf | 38 + srclib/apr/docs/incomplete_types | 84 + srclib/apr/docs/non_apr_programs | 47 + srclib/apr/docs/pool-design.html | 100 + srclib/apr/docs/win32_builds.html | 57 + srclib/apr/dso/aix/dso.c | 714 ++++++ srclib/apr/dso/beos/dso.c | 98 + srclib/apr/dso/netware/dso.c | 137 + srclib/apr/dso/os2/dso.c | 132 + srclib/apr/dso/os390/dso.c | 109 + srclib/apr/dso/unix/dso.c | 251 ++ srclib/apr/dso/win32/dso.c | 167 ++ srclib/apr/emacs-mode | 15 + srclib/apr/file_io/netware/filepath.c | 4 + srclib/apr/file_io/netware/filestat.c | 389 +++ srclib/apr/file_io/netware/filesys.c | 106 + srclib/apr/file_io/netware/flock.c | 39 + srclib/apr/file_io/netware/mktemp.c | 50 + srclib/apr/file_io/netware/pipe.c | 187 ++ srclib/apr/file_io/os2/copy.c | 1 + srclib/apr/file_io/os2/dir.c | 167 ++ srclib/apr/file_io/os2/dir_make_recurse.c | 86 + srclib/apr/file_io/os2/fileacc.c | 18 + srclib/apr/file_io/os2/filedup.c | 125 + srclib/apr/file_io/os2/filepath.c | 16 + srclib/apr/file_io/os2/filepath_util.c | 1 + srclib/apr/file_io/os2/filestat.c | 229 ++ srclib/apr/file_io/os2/filesys.c | 148 ++ srclib/apr/file_io/os2/flock.c | 37 + srclib/apr/file_io/os2/fullrw.c | 1 + srclib/apr/file_io/os2/maperrorcode.c | 95 + srclib/apr/file_io/os2/mktemp.c | 1 + srclib/apr/file_io/os2/open.c | 245 ++ srclib/apr/file_io/os2/pipe.c | 177 ++ srclib/apr/file_io/os2/readwrite.c | 360 +++ srclib/apr/file_io/os2/seek.c | 114 + srclib/apr/file_io/os2/tempdir.c | 1 + srclib/apr/file_io/unix/copy.c | 112 + srclib/apr/file_io/unix/dir.c | 318 +++ srclib/apr/file_io/unix/fileacc.c | 119 + srclib/apr/file_io/unix/filedup.c | 158 ++ srclib/apr/file_io/unix/filepath.c | 309 +++ srclib/apr/file_io/unix/filepath_util.c | 111 + srclib/apr/file_io/unix/filestat.c | 282 ++ srclib/apr/file_io/unix/flock.c | 120 + srclib/apr/file_io/unix/fullrw.c | 85 + srclib/apr/file_io/unix/mktemp.c | 210 ++ srclib/apr/file_io/unix/open.c | 280 ++ srclib/apr/file_io/unix/pipe.c | 236 ++ srclib/apr/file_io/unix/readwrite.c | 441 ++++ srclib/apr/file_io/unix/seek.c | 99 + srclib/apr/file_io/unix/tempdir.c | 130 + srclib/apr/file_io/win32/dir.c | 393 +++ srclib/apr/file_io/win32/filedup.c | 179 ++ srclib/apr/file_io/win32/filepath.c | 978 +++++++ srclib/apr/file_io/win32/filestat.c | 760 ++++++ srclib/apr/file_io/win32/filesys.c | 229 ++ srclib/apr/file_io/win32/flock.c | 68 + srclib/apr/file_io/win32/open.c | 634 +++++ srclib/apr/file_io/win32/pipe.c | 182 ++ srclib/apr/file_io/win32/readwrite.c | 505 ++++ srclib/apr/file_io/win32/seek.c | 163 ++ srclib/apr/helpers/apr_rename.pl | 106 + srclib/apr/images/ScanDocBig.jpg | Bin 0 -> 5319 bytes srclib/apr/images/ScanDocSmall.jpg | Bin 0 -> 2382 bytes srclib/apr/images/ball1.gif | Bin 0 -> 1012 bytes srclib/apr/images/ball1.png | Bin 0 -> 499 bytes srclib/apr/images/ball2.gif | Bin 0 -> 1014 bytes srclib/apr/images/ball2.png | Bin 0 -> 436 bytes srclib/apr/images/bug.gif | Bin 0 -> 1040 bytes srclib/apr/images/bug.png | Bin 0 -> 383 bytes srclib/apr/images/caution.gif | Bin 0 -> 923 bytes srclib/apr/images/caution.png | Bin 0 -> 217 bytes srclib/apr/images/master.gif | Bin 0 -> 3955 bytes srclib/apr/images/master.png | Bin 0 -> 3371 bytes srclib/apr/images/tip.gif | Bin 0 -> 1018 bytes srclib/apr/images/tip.png | Bin 0 -> 331 bytes srclib/apr/images/warning.gif | Bin 0 -> 923 bytes srclib/apr/images/warning.png | Bin 0 -> 217 bytes srclib/apr/include/apr.h.in | 397 +++ srclib/apr/include/apr.hnw | 364 +++ srclib/apr/include/apr.hw | 510 ++++ srclib/apr/include/apr_allocator.h | 160 ++ srclib/apr/include/apr_atomic.h | 129 + srclib/apr/include/apr_dso.h | 94 + srclib/apr/include/apr_env.h | 67 + srclib/apr/include/apr_errno.h | 1224 +++++++++ srclib/apr/include/apr_file_info.h | 419 +++ srclib/apr/include/apr_file_io.h | 806 ++++++ srclib/apr/include/apr_fnmatch.h | 108 + srclib/apr/include/apr_general.h | 241 ++ srclib/apr/include/apr_getopt.h | 158 ++ srclib/apr/include/apr_global_mutex.h | 153 ++ srclib/apr/include/apr_hash.h | 225 ++ srclib/apr/include/apr_inherit.h | 51 + srclib/apr/include/apr_lib.h | 230 ++ srclib/apr/include/apr_mmap.h | 171 ++ srclib/apr/include/apr_network_io.h | 821 ++++++ srclib/apr/include/apr_poll.h | 176 ++ srclib/apr/include/apr_pools.h | 652 +++++ srclib/apr/include/apr_portable.h | 506 ++++ srclib/apr/include/apr_proc_mutex.h | 166 ++ srclib/apr/include/apr_random.h | 74 + srclib/apr/include/apr_ring.h | 489 ++++ srclib/apr/include/apr_shm.h | 140 + srclib/apr/include/apr_signal.h | 109 + srclib/apr/include/apr_strings.h | 357 +++ srclib/apr/include/apr_support.h | 53 + srclib/apr/include/apr_tables.h | 422 +++ srclib/apr/include/apr_thread_cond.h | 134 + srclib/apr/include/apr_thread_mutex.h | 110 + srclib/apr/include/apr_thread_proc.h | 798 ++++++ srclib/apr/include/apr_thread_rwlock.h | 129 + srclib/apr/include/apr_time.h | 232 ++ srclib/apr/include/apr_user.h | 158 ++ srclib/apr/include/apr_version.h | 143 ++ srclib/apr/include/apr_want.h | 109 + srclib/apr/include/arch/aix/apr_arch_dso.h | 41 + srclib/apr/include/arch/apr_private_common.h | 42 + srclib/apr/include/arch/beos/apr_arch_dso.h | 41 + .../include/arch/beos/apr_arch_proc_mutex.h | 36 + .../include/arch/beos/apr_arch_thread_cond.h | 46 + .../include/arch/beos/apr_arch_thread_mutex.h | 42 + .../arch/beos/apr_arch_thread_rwlock.h | 45 + .../include/arch/beos/apr_arch_threadproc.h | 95 + .../apr/include/arch/netware/apr_arch_dso.h | 43 + .../include/arch/netware/apr_arch_file_io.h | 151 ++ .../arch/netware/apr_arch_global_mutex.h | 29 + .../arch/netware/apr_arch_internal_time.h | 26 + .../include/arch/netware/apr_arch_networkio.h | 31 + .../include/arch/netware/apr_arch_pre_nw.h | 67 + .../arch/netware/apr_arch_proc_mutex.h | 29 + .../arch/netware/apr_arch_thread_cond.h | 29 + .../arch/netware/apr_arch_thread_mutex.h | 29 + .../arch/netware/apr_arch_thread_rwlock.h | 29 + .../arch/netware/apr_arch_threadproc.h | 78 + srclib/apr/include/arch/netware/apr_private.h | 191 ++ srclib/apr/include/arch/os2/apr_arch_dso.h | 37 + .../apr/include/arch/os2/apr_arch_file_io.h | 81 + .../apr/include/arch/os2/apr_arch_networkio.h | 76 + .../apr/include/arch/os2/apr_arch_os2calls.h | 59 + .../include/arch/os2/apr_arch_proc_mutex.h | 31 + .../include/arch/os2/apr_arch_thread_cond.h | 28 + .../include/arch/os2/apr_arch_thread_mutex.h | 29 + .../include/arch/os2/apr_arch_thread_rwlock.h | 31 + .../include/arch/os2/apr_arch_threadproc.h | 67 + srclib/apr/include/arch/os390/apr_arch_dso.h | 39 + srclib/apr/include/arch/unix/apr_arch_dso.h | 63 + .../apr/include/arch/unix/apr_arch_file_io.h | 138 + .../include/arch/unix/apr_arch_global_mutex.h | 37 + .../apr/include/arch/unix/apr_arch_inherit.h | 52 + .../arch/unix/apr_arch_internal_time.h | 24 + srclib/apr/include/arch/unix/apr_arch_misc.h | 67 + .../include/arch/unix/apr_arch_networkio.h | 142 + .../include/arch/unix/apr_arch_poll_private.h | 100 + .../include/arch/unix/apr_arch_proc_mutex.h | 113 + srclib/apr/include/arch/unix/apr_arch_shm.h | 70 + .../include/arch/unix/apr_arch_thread_cond.h | 42 + .../include/arch/unix/apr_arch_thread_mutex.h | 39 + .../arch/unix/apr_arch_thread_rwlock.h | 49 + .../include/arch/unix/apr_arch_threadproc.h | 106 + .../apr/include/arch/win32/apr_arch_atime.h | 63 + srclib/apr/include/arch/win32/apr_arch_dso.h | 36 + .../apr/include/arch/win32/apr_arch_file_io.h | 278 ++ .../apr/include/arch/win32/apr_arch_inherit.h | 69 + srclib/apr/include/arch/win32/apr_arch_misc.h | 327 +++ .../include/arch/win32/apr_arch_networkio.h | 86 + .../include/arch/win32/apr_arch_proc_mutex.h | 29 + .../include/arch/win32/apr_arch_thread_cond.h | 32 + .../arch/win32/apr_arch_thread_mutex.h | 40 + .../arch/win32/apr_arch_thread_rwlock.h | 30 + .../include/arch/win32/apr_arch_threadproc.h | 72 + srclib/apr/include/arch/win32/apr_arch_utf8.h | 56 + .../arch/win32/apr_dbg_win32_handles.h | 217 ++ srclib/apr/include/arch/win32/apr_private.h | 171 ++ srclib/apr/libapr.dsp | 645 +++++ srclib/apr/libapr.rc | 54 + srclib/apr/libaprnw.mcp.zip | Bin 0 -> 171800 bytes srclib/apr/locks/beos/proc_mutex.c | 170 ++ srclib/apr/locks/beos/thread_cond.c | 185 ++ srclib/apr/locks/beos/thread_mutex.c | 147 ++ srclib/apr/locks/beos/thread_rwlock.c | 190 ++ srclib/apr/locks/netware/proc_mutex.c | 118 + srclib/apr/locks/netware/thread_cond.c | 100 + srclib/apr/locks/netware/thread_mutex.c | 92 + srclib/apr/locks/netware/thread_rwlock.c | 102 + srclib/apr/locks/os2/proc_mutex.c | 234 ++ srclib/apr/locks/os2/thread_cond.c | 60 + srclib/apr/locks/os2/thread_mutex.c | 102 + srclib/apr/locks/os2/thread_rwlock.c | 200 ++ srclib/apr/locks/unix/global_mutex.c | 178 ++ srclib/apr/locks/unix/proc_mutex.c | 864 +++++++ srclib/apr/locks/unix/thread_cond.c | 135 + srclib/apr/locks/unix/thread_mutex.c | 138 + srclib/apr/locks/unix/thread_rwlock.c | 181 ++ srclib/apr/locks/win32/proc_mutex.c | 216 ++ srclib/apr/locks/win32/thread_cond.c | 173 ++ srclib/apr/locks/win32/thread_mutex.c | 135 + srclib/apr/locks/win32/thread_rwlock.c | 163 ++ srclib/apr/memory/unix/apr_pools.c | 2278 +++++++++++++++++ srclib/apr/misc/netware/apr.xdc | Bin 0 -> 128 bytes srclib/apr/misc/netware/aprlib.def | 3 + srclib/apr/misc/netware/charset.c | 34 + srclib/apr/misc/netware/libprews.c | 188 ++ srclib/apr/misc/netware/rand.c | 70 + srclib/apr/misc/netware/start.c | 188 ++ srclib/apr/misc/unix/charset.c | 83 + srclib/apr/misc/unix/env.c | 97 + srclib/apr/misc/unix/errorcodes.c | 416 +++ srclib/apr/misc/unix/getopt.c | 309 +++ srclib/apr/misc/unix/otherchild.c | 221 ++ srclib/apr/misc/unix/rand.c | 238 ++ srclib/apr/misc/unix/randbyte_os2.inc | 122 + srclib/apr/misc/unix/start.c | 89 + srclib/apr/misc/unix/version.c | 35 + srclib/apr/misc/win32/apr_app.c | 80 + srclib/apr/misc/win32/charset.c | 43 + srclib/apr/misc/win32/env.c | 169 ++ srclib/apr/misc/win32/internal.c | 102 + srclib/apr/misc/win32/misc.c | 245 ++ srclib/apr/misc/win32/rand.c | 68 + srclib/apr/misc/win32/start.c | 223 ++ srclib/apr/misc/win32/utf8.c | 254 ++ srclib/apr/mmap/unix/common.c | 43 + srclib/apr/mmap/unix/mmap.c | 172 ++ srclib/apr/mmap/win32/mmap.c | 162 ++ srclib/apr/network_io/beos/sendrecv.c | 214 ++ srclib/apr/network_io/beos/socketcommon.c | 5 + srclib/apr/network_io/os2/inet_ntop.c | 1 + srclib/apr/network_io/os2/inet_pton.c | 1 + srclib/apr/network_io/os2/os2calls.c | 132 + srclib/apr/network_io/os2/sendrecv.c | 151 ++ srclib/apr/network_io/os2/sendrecv_udp.c | 104 + srclib/apr/network_io/os2/sockaddr.c | 1 + srclib/apr/network_io/os2/sockets.c | 309 +++ srclib/apr/network_io/os2/sockopt.c | 139 + srclib/apr/network_io/unix/inet_ntop.c | 245 ++ srclib/apr/network_io/unix/inet_pton.c | 240 ++ srclib/apr/network_io/unix/multicast.c | 332 +++ srclib/apr/network_io/unix/sendrecv.c | 960 +++++++ srclib/apr/network_io/unix/sockaddr.c | 968 +++++++ srclib/apr/network_io/unix/sockets.c | 415 +++ srclib/apr/network_io/unix/sockopt.c | 391 +++ srclib/apr/network_io/win32/sendrecv.c | 451 ++++ srclib/apr/network_io/win32/sockets.c | 497 ++++ srclib/apr/network_io/win32/sockopt.c | 261 ++ srclib/apr/passwd/apr_getpass.c | 233 ++ srclib/apr/poll/os2/poll.c | 105 + srclib/apr/poll/os2/pollset.c | 223 ++ srclib/apr/poll/unix/epoll.c | 266 ++ srclib/apr/poll/unix/kqueue.c | 284 ++ srclib/apr/poll/unix/poll.c | 264 ++ srclib/apr/poll/unix/port.c | 339 +++ srclib/apr/poll/unix/select.c | 404 +++ srclib/apr/random/unix/apr_random.c | 300 +++ srclib/apr/random/unix/sha2.c | 1000 ++++++++ srclib/apr/random/unix/sha2.h | 86 + srclib/apr/random/unix/sha2_glue.c | 33 + srclib/apr/renames_pending | 39 + srclib/apr/shmem/beos/shm.c | 166 ++ srclib/apr/shmem/os2/shm.c | 144 ++ srclib/apr/shmem/unix/shm.c | 597 +++++ srclib/apr/shmem/win32/shm.c | 306 +++ srclib/apr/strings/apr_cpystrn.c | 312 +++ srclib/apr/strings/apr_fnmatch.c | 293 +++ srclib/apr/strings/apr_snprintf.c | 1310 ++++++++++ srclib/apr/strings/apr_strings.c | 466 ++++ srclib/apr/strings/apr_strnatcmp.c | 149 ++ srclib/apr/strings/apr_strtok.c | 56 + srclib/apr/support/unix/waitio.c | 116 + srclib/apr/tables/apr_hash.c | 469 ++++ srclib/apr/tables/apr_tables.c | 1210 +++++++++ srclib/apr/test/MakeWin32Make.awk | 53 + srclib/apr/test/Makefile.in | 117 + srclib/apr/test/Makefile.win | 101 + srclib/apr/test/NWGNUmakefile | 264 ++ srclib/apr/test/README | 233 ++ srclib/apr/test/abts.c | 413 +++ srclib/apr/test/abts.h | 98 + srclib/apr/test/abts_tests.h | 72 + srclib/apr/test/aprtest.def | 3 + srclib/apr/test/aprtest.dsp | 199 ++ srclib/apr/test/aprtest.dsw | 122 + srclib/apr/test/aprtest.win | 18 + srclib/apr/test/data/file_datafile.txt | 1 + srclib/apr/test/data/mmap_datafile.txt | 1 + srclib/apr/test/globalmutexchild.c | 64 + srclib/apr/test/internal/Makefile.in | 37 + srclib/apr/test/internal/testregex.c | 91 + srclib/apr/test/internal/testucs.c | 176 ++ srclib/apr/test/mod_test.c | 32 + srclib/apr/test/nw_misc.c | 16 + srclib/apr/test/nwgnuaprtest | 299 +++ srclib/apr/test/nwgnuglobalmutexchild | 255 ++ srclib/apr/test/nwgnumod_test | 257 ++ srclib/apr/test/nwgnuproc_child | 255 ++ srclib/apr/test/nwgnureadchild | 255 ++ srclib/apr/test/nwgnusockchild | 255 ++ srclib/apr/test/nwgnutestatmc | 255 ++ srclib/apr/test/nwgnutryread | 255 ++ srclib/apr/test/occhild.c | 26 + srclib/apr/test/proc_child.c | 21 + srclib/apr/test/readchild.c | 46 + srclib/apr/test/sendfile.c | 757 ++++++ srclib/apr/test/sockchild.c | 80 + srclib/apr/test/testall.dsp | 257 ++ srclib/apr/test/testall.dsw | 122 + srclib/apr/test/testapp.c | 10 + srclib/apr/test/testapp.dsp | 90 + srclib/apr/test/testappnt.dsp | 101 + srclib/apr/test/testargs.c | 236 ++ srclib/apr/test/testatomic.c | 305 +++ srclib/apr/test/testdir.c | 243 ++ srclib/apr/test/testdso.c | 256 ++ srclib/apr/test/testdup.c | 194 ++ srclib/apr/test/testenv.c | 95 + srclib/apr/test/testfile.c | 739 ++++++ srclib/apr/test/testfilecopy.c | 138 + srclib/apr/test/testfileinfo.c | 263 ++ srclib/apr/test/testflock.c | 101 + srclib/apr/test/testflock.h | 27 + srclib/apr/test/testfmt.c | 135 + srclib/apr/test/testfnmatch.c | 76 + srclib/apr/test/testglobalmutex.c | 135 + srclib/apr/test/testglobalmutex.h | 27 + srclib/apr/test/testhash.c | 431 ++++ srclib/apr/test/testipsub.c | 173 ++ srclib/apr/test/testlfs.c | 285 +++ srclib/apr/test/testlock.c | 331 +++ srclib/apr/test/testlockperf.c | 282 ++ srclib/apr/test/testmmap.c | 153 ++ srclib/apr/test/testmutexscope.c | 218 ++ srclib/apr/test/testnames.c | 214 ++ srclib/apr/test/testoc.c | 117 + srclib/apr/test/testpath.c | 138 + srclib/apr/test/testpipe.c | 199 ++ srclib/apr/test/testpoll.c | 538 ++++ srclib/apr/test/testpools.c | 156 ++ srclib/apr/test/testproc.c | 169 ++ srclib/apr/test/testprocmutex.c | 175 ++ srclib/apr/test/testrand.c | 46 + srclib/apr/test/testrand2.c | 298 +++ srclib/apr/test/testshm.c | 272 ++ srclib/apr/test/testshm.h | 33 + srclib/apr/test/testshmconsumer.c | 94 + srclib/apr/test/testshmproducer.c | 89 + srclib/apr/test/testsleep.c | 54 + srclib/apr/test/testsock.c | 218 ++ srclib/apr/test/testsock.h | 34 + srclib/apr/test/testsockets.c | 208 ++ srclib/apr/test/testsockopt.c | 137 + srclib/apr/test/teststr.c | 370 +++ srclib/apr/test/teststrnatcmp.c | 78 + srclib/apr/test/testtable.c | 190 ++ srclib/apr/test/testtemp.c | 55 + srclib/apr/test/testthread.c | 133 + srclib/apr/test/testtime.c | 307 +++ srclib/apr/test/testud.c | 91 + srclib/apr/test/testuser.c | 116 + srclib/apr/test/testutil.c | 44 + srclib/apr/test/testutil.h | 92 + srclib/apr/test/testvsn.c | 49 + srclib/apr/test/tryread.c | 49 + srclib/apr/threadproc/beos/apr_proc_stub.c | 76 + srclib/apr/threadproc/beos/proc.c | 419 +++ srclib/apr/threadproc/beos/thread.c | 238 ++ srclib/apr/threadproc/beos/threadpriv.c | 180 ++ .../apr/threadproc/beos/threadproc_common.c | 21 + srclib/apr/threadproc/netware/proc.c | 452 ++++ srclib/apr/threadproc/netware/procsup.c | 102 + srclib/apr/threadproc/netware/signals.c | 82 + srclib/apr/threadproc/netware/thread.c | 256 ++ srclib/apr/threadproc/netware/threadpriv.c | 102 + srclib/apr/threadproc/os2/proc.c | 617 +++++ srclib/apr/threadproc/os2/signals.c | 1 + srclib/apr/threadproc/os2/thread.c | 261 ++ srclib/apr/threadproc/os2/threadpriv.c | 88 + srclib/apr/threadproc/unix/proc.c | 669 +++++ srclib/apr/threadproc/unix/procsup.c | 101 + srclib/apr/threadproc/unix/signals.c | 487 ++++ srclib/apr/threadproc/unix/thread.c | 320 +++ srclib/apr/threadproc/unix/threadpriv.c | 129 + srclib/apr/threadproc/win32/proc.c | 898 +++++++ srclib/apr/threadproc/win32/signals.c | 66 + srclib/apr/threadproc/win32/thread.c | 282 ++ srclib/apr/threadproc/win32/threadpriv.c | 101 + srclib/apr/time/unix/time.c | 332 +++ srclib/apr/time/unix/timestr.c | 153 ++ srclib/apr/time/win32/access.c | 204 ++ srclib/apr/time/win32/time.c | 326 +++ srclib/apr/time/win32/timestr.c | 216 ++ srclib/apr/user/netware/groupinfo.c | 41 + srclib/apr/user/netware/userinfo.c | 70 + srclib/apr/user/unix/groupinfo.c | 67 + srclib/apr/user/unix/userinfo.c | 126 + srclib/apr/user/win32/groupinfo.c | 100 + srclib/apr/user/win32/userinfo.c | 279 ++ 456 files changed, 95379 insertions(+) create mode 100644 srclib/apr/CHANGES create mode 100644 srclib/apr/LICENSE create mode 100644 srclib/apr/Makefile.in create mode 100644 srclib/apr/NOTICE create mode 100644 srclib/apr/NWGNUmakefile create mode 100644 srclib/apr/README.dev create mode 100644 srclib/apr/STATUS create mode 100644 srclib/apr/apr-config.in create mode 100644 srclib/apr/apr.dsp create mode 100644 srclib/apr/apr.dsw create mode 100644 srclib/apr/apr.pc.in create mode 100644 srclib/apr/atomic/netware/apr_atomic.c create mode 100644 srclib/apr/atomic/os390/atomic.c create mode 100644 srclib/apr/atomic/unix/apr_atomic.c create mode 100644 srclib/apr/atomic/win32/apr_atomic.c create mode 100644 srclib/apr/build.conf create mode 100755 srclib/apr/build/MakeEtags create mode 100644 srclib/apr/build/NWGNUenvironment.inc create mode 100644 srclib/apr/build/NWGNUhead.inc create mode 100644 srclib/apr/build/NWGNUmakefile create mode 100644 srclib/apr/build/NWGNUtail.inc create mode 100755 srclib/apr/build/PrintPath create mode 100644 srclib/apr/build/aplibtool.c create mode 100644 srclib/apr/build/apr_app.dsp create mode 100644 srclib/apr/build/apr_common.m4 create mode 100644 srclib/apr/build/apr_hints.m4 create mode 100644 srclib/apr/build/apr_network.m4 create mode 100644 srclib/apr/build/apr_rules.mk.in create mode 100644 srclib/apr/build/apr_threads.m4 create mode 100755 srclib/apr/build/buildcheck.sh create mode 100755 srclib/apr/build/config.guess create mode 100755 srclib/apr/build/config.sub create mode 100644 srclib/apr/build/cvtdsp.pl create mode 100644 srclib/apr/build/find_apr.m4 create mode 100644 srclib/apr/build/fixwin32mak.pl create mode 100755 srclib/apr/build/gen-build.py create mode 100755 srclib/apr/build/get-version.sh create mode 100755 srclib/apr/build/install.sh create mode 100644 srclib/apr/build/jlibtool.c create mode 100644 srclib/apr/build/libapr_app.dsp create mode 100644 srclib/apr/build/lineends.pl create mode 100644 srclib/apr/build/make_exports.awk create mode 100644 srclib/apr/build/make_nw_export.awk create mode 100644 srclib/apr/build/make_var_export.awk create mode 100755 srclib/apr/build/mkdir.sh create mode 100644 srclib/apr/build/nw_export.inc create mode 100644 srclib/apr/build/nw_ver.awk create mode 100644 srclib/apr/build/pkg/README create mode 100755 srclib/apr/build/pkg/buildpkg.sh create mode 100644 srclib/apr/build/pkg/pkginfo.in create mode 100755 srclib/apr/build/prebuildNW.bat create mode 100644 srclib/apr/build/rpm/apr.spec.in create mode 100755 srclib/apr/build/run-gcov.sh create mode 100644 srclib/apr/build/win32ver.awk create mode 100755 srclib/apr/buildconf create mode 100644 srclib/apr/config.layout create mode 100644 srclib/apr/configure.in create mode 100644 srclib/apr/docs/APRDesign.html create mode 100644 srclib/apr/docs/canonical_filenames.html create mode 100644 srclib/apr/docs/doxygen.conf create mode 100644 srclib/apr/docs/incomplete_types create mode 100644 srclib/apr/docs/non_apr_programs create mode 100644 srclib/apr/docs/pool-design.html create mode 100644 srclib/apr/docs/win32_builds.html create mode 100644 srclib/apr/dso/aix/dso.c create mode 100644 srclib/apr/dso/beos/dso.c create mode 100644 srclib/apr/dso/netware/dso.c create mode 100644 srclib/apr/dso/os2/dso.c create mode 100644 srclib/apr/dso/os390/dso.c create mode 100644 srclib/apr/dso/unix/dso.c create mode 100644 srclib/apr/dso/win32/dso.c create mode 100644 srclib/apr/emacs-mode create mode 100644 srclib/apr/file_io/netware/filepath.c create mode 100644 srclib/apr/file_io/netware/filestat.c create mode 100644 srclib/apr/file_io/netware/filesys.c create mode 100644 srclib/apr/file_io/netware/flock.c create mode 100644 srclib/apr/file_io/netware/mktemp.c create mode 100644 srclib/apr/file_io/netware/pipe.c create mode 100644 srclib/apr/file_io/os2/copy.c create mode 100644 srclib/apr/file_io/os2/dir.c create mode 100644 srclib/apr/file_io/os2/dir_make_recurse.c create mode 100644 srclib/apr/file_io/os2/fileacc.c create mode 100644 srclib/apr/file_io/os2/filedup.c create mode 100644 srclib/apr/file_io/os2/filepath.c create mode 100644 srclib/apr/file_io/os2/filepath_util.c create mode 100644 srclib/apr/file_io/os2/filestat.c create mode 100644 srclib/apr/file_io/os2/filesys.c create mode 100644 srclib/apr/file_io/os2/flock.c create mode 100644 srclib/apr/file_io/os2/fullrw.c create mode 100644 srclib/apr/file_io/os2/maperrorcode.c create mode 100644 srclib/apr/file_io/os2/mktemp.c create mode 100644 srclib/apr/file_io/os2/open.c create mode 100644 srclib/apr/file_io/os2/pipe.c create mode 100644 srclib/apr/file_io/os2/readwrite.c create mode 100644 srclib/apr/file_io/os2/seek.c create mode 100644 srclib/apr/file_io/os2/tempdir.c create mode 100644 srclib/apr/file_io/unix/copy.c create mode 100644 srclib/apr/file_io/unix/dir.c create mode 100644 srclib/apr/file_io/unix/fileacc.c create mode 100644 srclib/apr/file_io/unix/filedup.c create mode 100644 srclib/apr/file_io/unix/filepath.c create mode 100644 srclib/apr/file_io/unix/filepath_util.c create mode 100644 srclib/apr/file_io/unix/filestat.c create mode 100644 srclib/apr/file_io/unix/flock.c create mode 100644 srclib/apr/file_io/unix/fullrw.c create mode 100644 srclib/apr/file_io/unix/mktemp.c create mode 100644 srclib/apr/file_io/unix/open.c create mode 100644 srclib/apr/file_io/unix/pipe.c create mode 100644 srclib/apr/file_io/unix/readwrite.c create mode 100644 srclib/apr/file_io/unix/seek.c create mode 100644 srclib/apr/file_io/unix/tempdir.c create mode 100644 srclib/apr/file_io/win32/dir.c create mode 100644 srclib/apr/file_io/win32/filedup.c create mode 100644 srclib/apr/file_io/win32/filepath.c create mode 100644 srclib/apr/file_io/win32/filestat.c create mode 100644 srclib/apr/file_io/win32/filesys.c create mode 100644 srclib/apr/file_io/win32/flock.c create mode 100644 srclib/apr/file_io/win32/open.c create mode 100644 srclib/apr/file_io/win32/pipe.c create mode 100644 srclib/apr/file_io/win32/readwrite.c create mode 100644 srclib/apr/file_io/win32/seek.c create mode 100755 srclib/apr/helpers/apr_rename.pl create mode 100644 srclib/apr/images/ScanDocBig.jpg create mode 100644 srclib/apr/images/ScanDocSmall.jpg create mode 100644 srclib/apr/images/ball1.gif create mode 100644 srclib/apr/images/ball1.png create mode 100644 srclib/apr/images/ball2.gif create mode 100644 srclib/apr/images/ball2.png create mode 100644 srclib/apr/images/bug.gif create mode 100644 srclib/apr/images/bug.png create mode 100644 srclib/apr/images/caution.gif create mode 100644 srclib/apr/images/caution.png create mode 100644 srclib/apr/images/master.gif create mode 100644 srclib/apr/images/master.png create mode 100644 srclib/apr/images/tip.gif create mode 100644 srclib/apr/images/tip.png create mode 100644 srclib/apr/images/warning.gif create mode 100644 srclib/apr/images/warning.png create mode 100644 srclib/apr/include/apr.h.in create mode 100644 srclib/apr/include/apr.hnw create mode 100644 srclib/apr/include/apr.hw create mode 100644 srclib/apr/include/apr_allocator.h create mode 100644 srclib/apr/include/apr_atomic.h create mode 100644 srclib/apr/include/apr_dso.h create mode 100644 srclib/apr/include/apr_env.h create mode 100644 srclib/apr/include/apr_errno.h create mode 100644 srclib/apr/include/apr_file_info.h create mode 100644 srclib/apr/include/apr_file_io.h create mode 100644 srclib/apr/include/apr_fnmatch.h create mode 100644 srclib/apr/include/apr_general.h create mode 100644 srclib/apr/include/apr_getopt.h create mode 100644 srclib/apr/include/apr_global_mutex.h create mode 100644 srclib/apr/include/apr_hash.h create mode 100644 srclib/apr/include/apr_inherit.h create mode 100644 srclib/apr/include/apr_lib.h create mode 100644 srclib/apr/include/apr_mmap.h create mode 100644 srclib/apr/include/apr_network_io.h create mode 100644 srclib/apr/include/apr_poll.h create mode 100644 srclib/apr/include/apr_pools.h create mode 100644 srclib/apr/include/apr_portable.h create mode 100644 srclib/apr/include/apr_proc_mutex.h create mode 100644 srclib/apr/include/apr_random.h create mode 100644 srclib/apr/include/apr_ring.h create mode 100644 srclib/apr/include/apr_shm.h create mode 100644 srclib/apr/include/apr_signal.h create mode 100644 srclib/apr/include/apr_strings.h create mode 100644 srclib/apr/include/apr_support.h create mode 100644 srclib/apr/include/apr_tables.h create mode 100644 srclib/apr/include/apr_thread_cond.h create mode 100644 srclib/apr/include/apr_thread_mutex.h create mode 100644 srclib/apr/include/apr_thread_proc.h create mode 100644 srclib/apr/include/apr_thread_rwlock.h create mode 100644 srclib/apr/include/apr_time.h create mode 100644 srclib/apr/include/apr_user.h create mode 100644 srclib/apr/include/apr_version.h create mode 100644 srclib/apr/include/apr_want.h create mode 100644 srclib/apr/include/arch/aix/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/apr_private_common.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_proc_mutex.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_thread_cond.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_thread_mutex.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_thread_rwlock.h create mode 100644 srclib/apr/include/arch/beos/apr_arch_threadproc.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_file_io.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_global_mutex.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_internal_time.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_networkio.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_pre_nw.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_proc_mutex.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_thread_cond.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_thread_mutex.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_thread_rwlock.h create mode 100644 srclib/apr/include/arch/netware/apr_arch_threadproc.h create mode 100644 srclib/apr/include/arch/netware/apr_private.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_file_io.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_networkio.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_os2calls.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_proc_mutex.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_thread_cond.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_thread_mutex.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_thread_rwlock.h create mode 100644 srclib/apr/include/arch/os2/apr_arch_threadproc.h create mode 100644 srclib/apr/include/arch/os390/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_file_io.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_global_mutex.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_inherit.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_internal_time.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_misc.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_networkio.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_poll_private.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_proc_mutex.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_shm.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_thread_cond.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_thread_mutex.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_thread_rwlock.h create mode 100644 srclib/apr/include/arch/unix/apr_arch_threadproc.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_atime.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_dso.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_file_io.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_inherit.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_misc.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_networkio.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_proc_mutex.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_thread_cond.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_thread_mutex.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_thread_rwlock.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_threadproc.h create mode 100644 srclib/apr/include/arch/win32/apr_arch_utf8.h create mode 100644 srclib/apr/include/arch/win32/apr_dbg_win32_handles.h create mode 100644 srclib/apr/include/arch/win32/apr_private.h create mode 100644 srclib/apr/libapr.dsp create mode 100644 srclib/apr/libapr.rc create mode 100644 srclib/apr/libaprnw.mcp.zip create mode 100644 srclib/apr/locks/beos/proc_mutex.c create mode 100644 srclib/apr/locks/beos/thread_cond.c create mode 100644 srclib/apr/locks/beos/thread_mutex.c create mode 100644 srclib/apr/locks/beos/thread_rwlock.c create mode 100644 srclib/apr/locks/netware/proc_mutex.c create mode 100644 srclib/apr/locks/netware/thread_cond.c create mode 100644 srclib/apr/locks/netware/thread_mutex.c create mode 100644 srclib/apr/locks/netware/thread_rwlock.c create mode 100644 srclib/apr/locks/os2/proc_mutex.c create mode 100644 srclib/apr/locks/os2/thread_cond.c create mode 100644 srclib/apr/locks/os2/thread_mutex.c create mode 100644 srclib/apr/locks/os2/thread_rwlock.c create mode 100644 srclib/apr/locks/unix/global_mutex.c create mode 100644 srclib/apr/locks/unix/proc_mutex.c create mode 100644 srclib/apr/locks/unix/thread_cond.c create mode 100644 srclib/apr/locks/unix/thread_mutex.c create mode 100644 srclib/apr/locks/unix/thread_rwlock.c create mode 100644 srclib/apr/locks/win32/proc_mutex.c create mode 100644 srclib/apr/locks/win32/thread_cond.c create mode 100644 srclib/apr/locks/win32/thread_mutex.c create mode 100644 srclib/apr/locks/win32/thread_rwlock.c create mode 100644 srclib/apr/memory/unix/apr_pools.c create mode 100644 srclib/apr/misc/netware/apr.xdc create mode 100644 srclib/apr/misc/netware/aprlib.def create mode 100644 srclib/apr/misc/netware/charset.c create mode 100644 srclib/apr/misc/netware/libprews.c create mode 100644 srclib/apr/misc/netware/rand.c create mode 100644 srclib/apr/misc/netware/start.c create mode 100644 srclib/apr/misc/unix/charset.c create mode 100644 srclib/apr/misc/unix/env.c create mode 100644 srclib/apr/misc/unix/errorcodes.c create mode 100644 srclib/apr/misc/unix/getopt.c create mode 100644 srclib/apr/misc/unix/otherchild.c create mode 100644 srclib/apr/misc/unix/rand.c create mode 100644 srclib/apr/misc/unix/randbyte_os2.inc create mode 100644 srclib/apr/misc/unix/start.c create mode 100644 srclib/apr/misc/unix/version.c create mode 100644 srclib/apr/misc/win32/apr_app.c create mode 100644 srclib/apr/misc/win32/charset.c create mode 100644 srclib/apr/misc/win32/env.c create mode 100644 srclib/apr/misc/win32/internal.c create mode 100644 srclib/apr/misc/win32/misc.c create mode 100644 srclib/apr/misc/win32/rand.c create mode 100644 srclib/apr/misc/win32/start.c create mode 100644 srclib/apr/misc/win32/utf8.c create mode 100644 srclib/apr/mmap/unix/common.c create mode 100644 srclib/apr/mmap/unix/mmap.c create mode 100644 srclib/apr/mmap/win32/mmap.c create mode 100644 srclib/apr/network_io/beos/sendrecv.c create mode 100644 srclib/apr/network_io/beos/socketcommon.c create mode 100644 srclib/apr/network_io/os2/inet_ntop.c create mode 100644 srclib/apr/network_io/os2/inet_pton.c create mode 100644 srclib/apr/network_io/os2/os2calls.c create mode 100644 srclib/apr/network_io/os2/sendrecv.c create mode 100644 srclib/apr/network_io/os2/sendrecv_udp.c create mode 100644 srclib/apr/network_io/os2/sockaddr.c create mode 100644 srclib/apr/network_io/os2/sockets.c create mode 100644 srclib/apr/network_io/os2/sockopt.c create mode 100644 srclib/apr/network_io/unix/inet_ntop.c create mode 100644 srclib/apr/network_io/unix/inet_pton.c create mode 100644 srclib/apr/network_io/unix/multicast.c create mode 100644 srclib/apr/network_io/unix/sendrecv.c create mode 100644 srclib/apr/network_io/unix/sockaddr.c create mode 100644 srclib/apr/network_io/unix/sockets.c create mode 100644 srclib/apr/network_io/unix/sockopt.c create mode 100644 srclib/apr/network_io/win32/sendrecv.c create mode 100644 srclib/apr/network_io/win32/sockets.c create mode 100644 srclib/apr/network_io/win32/sockopt.c create mode 100644 srclib/apr/passwd/apr_getpass.c create mode 100644 srclib/apr/poll/os2/poll.c create mode 100644 srclib/apr/poll/os2/pollset.c create mode 100644 srclib/apr/poll/unix/epoll.c create mode 100644 srclib/apr/poll/unix/kqueue.c create mode 100644 srclib/apr/poll/unix/poll.c create mode 100644 srclib/apr/poll/unix/port.c create mode 100644 srclib/apr/poll/unix/select.c create mode 100644 srclib/apr/random/unix/apr_random.c create mode 100644 srclib/apr/random/unix/sha2.c create mode 100644 srclib/apr/random/unix/sha2.h create mode 100644 srclib/apr/random/unix/sha2_glue.c create mode 100644 srclib/apr/renames_pending create mode 100644 srclib/apr/shmem/beos/shm.c create mode 100644 srclib/apr/shmem/os2/shm.c create mode 100644 srclib/apr/shmem/unix/shm.c create mode 100644 srclib/apr/shmem/win32/shm.c create mode 100644 srclib/apr/strings/apr_cpystrn.c create mode 100644 srclib/apr/strings/apr_fnmatch.c create mode 100644 srclib/apr/strings/apr_snprintf.c create mode 100644 srclib/apr/strings/apr_strings.c create mode 100644 srclib/apr/strings/apr_strnatcmp.c create mode 100644 srclib/apr/strings/apr_strtok.c create mode 100644 srclib/apr/support/unix/waitio.c create mode 100644 srclib/apr/tables/apr_hash.c create mode 100644 srclib/apr/tables/apr_tables.c create mode 100644 srclib/apr/test/MakeWin32Make.awk create mode 100644 srclib/apr/test/Makefile.in create mode 100644 srclib/apr/test/Makefile.win create mode 100644 srclib/apr/test/NWGNUmakefile create mode 100644 srclib/apr/test/README create mode 100644 srclib/apr/test/abts.c create mode 100644 srclib/apr/test/abts.h create mode 100644 srclib/apr/test/abts_tests.h create mode 100644 srclib/apr/test/aprtest.def create mode 100644 srclib/apr/test/aprtest.dsp create mode 100644 srclib/apr/test/aprtest.dsw create mode 100644 srclib/apr/test/aprtest.win create mode 100644 srclib/apr/test/data/file_datafile.txt create mode 100644 srclib/apr/test/data/mmap_datafile.txt create mode 100644 srclib/apr/test/globalmutexchild.c create mode 100644 srclib/apr/test/internal/Makefile.in create mode 100644 srclib/apr/test/internal/testregex.c create mode 100644 srclib/apr/test/internal/testucs.c create mode 100644 srclib/apr/test/mod_test.c create mode 100644 srclib/apr/test/nw_misc.c create mode 100644 srclib/apr/test/nwgnuaprtest create mode 100644 srclib/apr/test/nwgnuglobalmutexchild create mode 100644 srclib/apr/test/nwgnumod_test create mode 100644 srclib/apr/test/nwgnuproc_child create mode 100644 srclib/apr/test/nwgnureadchild create mode 100644 srclib/apr/test/nwgnusockchild create mode 100644 srclib/apr/test/nwgnutestatmc create mode 100644 srclib/apr/test/nwgnutryread create mode 100644 srclib/apr/test/occhild.c create mode 100644 srclib/apr/test/proc_child.c create mode 100644 srclib/apr/test/readchild.c create mode 100644 srclib/apr/test/sendfile.c create mode 100644 srclib/apr/test/sockchild.c create mode 100644 srclib/apr/test/testall.dsp create mode 100644 srclib/apr/test/testall.dsw create mode 100644 srclib/apr/test/testapp.c create mode 100644 srclib/apr/test/testapp.dsp create mode 100644 srclib/apr/test/testappnt.dsp create mode 100644 srclib/apr/test/testargs.c create mode 100644 srclib/apr/test/testatomic.c create mode 100644 srclib/apr/test/testdir.c create mode 100644 srclib/apr/test/testdso.c create mode 100644 srclib/apr/test/testdup.c create mode 100644 srclib/apr/test/testenv.c create mode 100644 srclib/apr/test/testfile.c create mode 100644 srclib/apr/test/testfilecopy.c create mode 100644 srclib/apr/test/testfileinfo.c create mode 100644 srclib/apr/test/testflock.c create mode 100644 srclib/apr/test/testflock.h create mode 100644 srclib/apr/test/testfmt.c create mode 100644 srclib/apr/test/testfnmatch.c create mode 100644 srclib/apr/test/testglobalmutex.c create mode 100644 srclib/apr/test/testglobalmutex.h create mode 100644 srclib/apr/test/testhash.c create mode 100644 srclib/apr/test/testipsub.c create mode 100644 srclib/apr/test/testlfs.c create mode 100644 srclib/apr/test/testlock.c create mode 100644 srclib/apr/test/testlockperf.c create mode 100644 srclib/apr/test/testmmap.c create mode 100644 srclib/apr/test/testmutexscope.c create mode 100644 srclib/apr/test/testnames.c create mode 100644 srclib/apr/test/testoc.c create mode 100644 srclib/apr/test/testpath.c create mode 100644 srclib/apr/test/testpipe.c create mode 100644 srclib/apr/test/testpoll.c create mode 100644 srclib/apr/test/testpools.c create mode 100644 srclib/apr/test/testproc.c create mode 100644 srclib/apr/test/testprocmutex.c create mode 100644 srclib/apr/test/testrand.c create mode 100644 srclib/apr/test/testrand2.c create mode 100644 srclib/apr/test/testshm.c create mode 100644 srclib/apr/test/testshm.h create mode 100644 srclib/apr/test/testshmconsumer.c create mode 100644 srclib/apr/test/testshmproducer.c create mode 100644 srclib/apr/test/testsleep.c create mode 100644 srclib/apr/test/testsock.c create mode 100644 srclib/apr/test/testsock.h create mode 100644 srclib/apr/test/testsockets.c create mode 100644 srclib/apr/test/testsockopt.c create mode 100644 srclib/apr/test/teststr.c create mode 100644 srclib/apr/test/teststrnatcmp.c create mode 100644 srclib/apr/test/testtable.c create mode 100644 srclib/apr/test/testtemp.c create mode 100644 srclib/apr/test/testthread.c create mode 100644 srclib/apr/test/testtime.c create mode 100644 srclib/apr/test/testud.c create mode 100644 srclib/apr/test/testuser.c create mode 100644 srclib/apr/test/testutil.c create mode 100644 srclib/apr/test/testutil.h create mode 100644 srclib/apr/test/testvsn.c create mode 100644 srclib/apr/test/tryread.c create mode 100644 srclib/apr/threadproc/beos/apr_proc_stub.c create mode 100644 srclib/apr/threadproc/beos/proc.c create mode 100644 srclib/apr/threadproc/beos/thread.c create mode 100644 srclib/apr/threadproc/beos/threadpriv.c create mode 100644 srclib/apr/threadproc/beos/threadproc_common.c create mode 100644 srclib/apr/threadproc/netware/proc.c create mode 100644 srclib/apr/threadproc/netware/procsup.c create mode 100644 srclib/apr/threadproc/netware/signals.c create mode 100644 srclib/apr/threadproc/netware/thread.c create mode 100644 srclib/apr/threadproc/netware/threadpriv.c create mode 100644 srclib/apr/threadproc/os2/proc.c create mode 100644 srclib/apr/threadproc/os2/signals.c create mode 100644 srclib/apr/threadproc/os2/thread.c create mode 100644 srclib/apr/threadproc/os2/threadpriv.c create mode 100644 srclib/apr/threadproc/unix/proc.c create mode 100644 srclib/apr/threadproc/unix/procsup.c create mode 100644 srclib/apr/threadproc/unix/signals.c create mode 100644 srclib/apr/threadproc/unix/thread.c create mode 100644 srclib/apr/threadproc/unix/threadpriv.c create mode 100644 srclib/apr/threadproc/win32/proc.c create mode 100644 srclib/apr/threadproc/win32/signals.c create mode 100644 srclib/apr/threadproc/win32/thread.c create mode 100644 srclib/apr/threadproc/win32/threadpriv.c create mode 100644 srclib/apr/time/unix/time.c create mode 100644 srclib/apr/time/unix/timestr.c create mode 100644 srclib/apr/time/win32/access.c create mode 100644 srclib/apr/time/win32/time.c create mode 100644 srclib/apr/time/win32/timestr.c create mode 100644 srclib/apr/user/netware/groupinfo.c create mode 100644 srclib/apr/user/netware/userinfo.c create mode 100644 srclib/apr/user/unix/groupinfo.c create mode 100644 srclib/apr/user/unix/userinfo.c create mode 100644 srclib/apr/user/win32/groupinfo.c create mode 100644 srclib/apr/user/win32/userinfo.c diff --git a/srclib/apr/CHANGES b/srclib/apr/CHANGES new file mode 100644 index 0000000000..00b384be1a --- /dev/null +++ b/srclib/apr/CHANGES @@ -0,0 +1,1942 @@ +Changes for APR 1.2.0 + + *) Fix apr_table_overlap()'s handling of tables allocated from + different pools. [Joe Schaefer ] + + *) Add support for uuid_generate on OS X 10.4. [Paul Querna] + + *) Include the C preprocessor flags in --cflags for pkg-config. + [Paul Querna] + + *) Fix issue with poll() followed by net I/O yielding EAGAIN on + Mac OS 10.4 (Darwin 8). [Wilfredo Sanchez] + +Changes for APR 1.1.1 + + *) Disable sendfile support for S/390 only in kernel versions < 2.4.0. + [Joe Orton] + + *) Fix posix rwlock detection on Darwin. [Aaron Bannert] + + *) Build fix for Multicast support on HP-UX 11.00 and Tru64 [Joe Orton] + + *) Fix libapr.rc for Win32 builds [William Rowe] + + *) Rewrite apr_file_writev_full using apr_file_write_full. [Paul Querna] + + *) Use APR_RING_CONCAT for moving dead list in KQueue, sys_epoll, and + Event Ports. [Paul Querna] + + *) find_apr.m4: Try installed APR before bundled copy if --with-apr not + passed to configure. [Justin Erenkrantz] + +Changes for APR 1.1.0 + + *) Added apr_procattr_user_set and apr_procattr_group_set + setting the user and group for new processes. [Mladen Turk] + + *) Add APR Multicast functions; including support for + Source-Specific Multicast from Colm MacCarthaigh. [Paul Querna] + + *) Add a build script to create a solaris package. [Graham Leggett] + + *) Add support for APR_TCP_DEFER_ACCEPT. [Paul Querna] + + *) Rename the apr_file_permissions macros (APR_UREAD, APR_UWRITE etc.) + to have prefix APR_FPROT_ (old names kept for compatibility). + [Stas Bekman] + + *) Emit the run-time link path option in apr-config after installation + if the user is linking with libtool. [Justin Erenkrantz] + + *) Add apr_file_writev_full to ensure an entire iovec is writen to a file. + [Paul Querna] + + *) Remove the runtime test for Sendfile versions on FreeBSD. PR 25718. + [Mike Silbersack , Paul Querna] + + *) Rename the apr_file_open macros (APR_READ, APR_WRITE, etc.) to + have prefix APR_FOPEN_ (old names kept for compatibility). + [Stas Bekman] + + *) Added apr_os_uuid_get() support for Linux via libuuid and for modern + BSDs which have uuid_create as part of their libc. [Paul Querna] + + *) Added Solaris 10 'Event Ports' as a backend for APR Pollset. This + backend also supports the APR_POLLSET_THREADSAFE flag. [Paul Querna] + + *) Added the APR_POLLSET_THREADSAFE flag. This allows multiple threads + to call the Pollset Add or Remove functions in a thread safe manner. + Currently only EPoll and KQueue support this flag. [Paul Querna] + + *) Split poll/unix/poll.c into separate files for each Poll or Pollset + implementation. [Paul Querna] + + *) Rewrite apr_file_printf to handle arbitrary length strings. + PR 28029. [Chris Knight , + Garrett Rooney ] + +Changes for APR 1.0.2 + + *) [NetWare] Fixed some type mismatches in threadproc/netware/proc.c and + locks/netware/thread_mutex.c that prevented APR from building with the + latest release of the LibC SDK. [Brad Nicholes] + +Changes for APR 1.0.1 + + *) apr_password_get(): Fix the check for buffer overflow. [Jeff Trawick] + + *) Fix HUP return codes in pollset when using KQueue. + [Paul Querna] + + *) Prevent unbounded memory use during repeated operations on a hash table. + [Julian Foad + + *) Moved repository to SVN + [Hackathon] + + *) jlibtool: Ignore '-export-symbols-regexp' option. + [Justin Erenkrantz] + + *) fix apr_file_dup and apr_file_dup2 win32 implementations + to create a mutex [Steve Hay ] + + *) Makes the threads to behave like on posix. If the thread is created + without APR_DETACH expect that the thread_join will be called, so don't + close the handle in advance, if the thread has already finished. + [Mladen Turk] + + *) The apr/test/Makefile.win is missing a target to build a + readchild.exe that test is depending on but is never built. + [Mladen Turk] + + *) Improve apr_file_gets() performance on buffered files. [Justin Erenkrantz] + + *) Win32: Fix bug in apr_socket_sendfile that interferred with + Win32 LSPs. PR 23982 [Jan Bilek, Bill Stoddard] + + *) Win32: Fix bug tracking the file pointer on a file opened for + overlapped/APR_XTHREAD io. [Bill Stoddard] + +Changes with APR 1.0 + + *) Only install apr-$MAJOR-config and add appropriate detection code to + find_apr.m4 (APR_FIND_APR). [Max Bowsher ] + + *) Remove APR_STATUS_IS_SUCCESS() macro. [Justin Erenkrantz] + + *) apr_proc_create() on Unix: Remove unnecessary check for read + access to the working directory of the child process. + PR 30137. [Jeremy Chadwick ] + + *) Add jlibtool - enabled with '--enable-experimental-libtool' option. + [Justin Erenkrantz] + + *) Add support for KQueue and sys_epoll to apr_pollset. [Paul Querna] + + *) Support threading on FreeBSD 5.x where kern.osreldate >= 502102. + [Craig Rodrigues ] + + *) Add an RPM spec file derived from Fedora Core. + [Graham Leggett, Joe Orton] + + *) Fix apr_threadattr_detach_set() on Mac OS X. PR 28472. + [INOUE Seiichiro ] + + *) Change default inter-process locking mechanisms: POSIX semaphores + and pthread cross-process mutexes are not used by default; on + Solaris, fcntl locks are used by default. [Joe Orton] + + *) Add apr_threadattr_guardsize_set() for overriding the default stack + guard area size for created created by apr_thread_create(). + [Joe Orton] + + *) Add apr_shm_remove() function for removing a named shared + memory segment. [Amit Athavale ] + + *) Add apr_strtoff() function for converting numeric strings into + apr_off_t values. [André Malo , Joe Orton] + + *) Fix stack overflow with IPv6 apr_socket_accept() on Win32. + PR 28471. [inoue ] + + *) Add new functions apr_signal_block, apr_signal_unblock to block/unblock + the delivery of a particular signal. [Madhusudan Mathihalli] + + *) Add support for developers to use their own hashing function with + apr_hash_make_custom. [Ami Ganguli ] + + *) Support "large files" by default on 32-bit Unix platforms which + implement the LFS standard. [Joe Orton] + + *) Add apr_threadattr_stacksize_set() for overriding the default + stack size for threads created by apr_thread_create(). + [Jeff Trawick] + + *) The whole codebase was relicensed and is now available under + the Apache License, Version 2.0 (http://www.apache.org/licenses). + [Apache Software Foundation] + + *) Switch to a single, top-level make. [Greg Stein] + + *) new error status APR_STATUS_IS_ENOTENOUGHENTROPY, Doxygen fixes + [Sander Temme apr_socket_accept + apr_allocator_get_mutex -> apr_allocator_mutex_get + apr_allocator_get_owner -> apr_allocator_owner_get + apr_allocator_set_max_free -> apr_allocator_max_free_set + apr_allocator_set_mutex -> apr_allocator_mutex_set + apr_allocator_set_owner -> apr_allocator_owner_set + apr_atomic_add -> apr_atomic_add32 + apr_atomic_cas -> apr_atomic_cas32 + apr_atomic_dec -> apr_atomic_dec32 + apr_atomic_inc -> apr_atomic_inc32 + apr_atomic_read -> apr_atomic_read32 + apr_atomic_set -> apr_atomic_set32 + apr_bind -> apr_socket_bind + apr_compare_groups -> apr_gid_compare + apr_compare_users -> apr_uid_compare + apr_connect -> apr_socket_connect + apr_current_userid -> apr_uid_current + apr_explode_localtime -> apr_time_exp_lt + apr_explode_time -> apr_time_exp_tz + apr_filename_of_pathname -> apr_filepath_name_get + apr_file_set_inherit -> apr_file_inherit_set + apr_file_unset_inherit -> apr_file_inherit_unset + apr_getsocketopt -> apr_socket_opt_get + apr_get_groupid -> apr_gid_get + apr_get_groupname -> apr_gid_name_get + apr_get_home_directory -> apr_uid_homepath_get + apr_get_userid -> apr_uid_get + apr_get_username -> apr_uid_name_get + apr_group_name_get -> apr_gid_name_get + apr_implode_gmt -> apr_time_exp_gmt_get + apr_is_fnmatch -> apr_fnmatch_test + apr_listen -> apr_socket_listen + apr_lstat -> apr_stat + apr_pool_get_abort -> apr_pool_abort_get + apr_pool_get_parent -> apr_pool_parent_get + apr_pool_set_abort -> apr_pool_abort_set + apr_pool_sub_make -> apr_pool_create_ex + apr_proc_other_child_read -> apr_proc_other_child_alert + apr_recv -> apr_socket_recv + apr_recvfrom -> apr_socket_recvfrom + apr_send -> apr_socket_send + apr_sendfile -> apr_socket_sendfile + apr_sendto -> apr_socket_sendto + apr_sendv -> apr_socket_sendv + apr_setsocketopt -> apr_socket_opt_set + apr_shutdown -> apr_socket_shutdown + apr_signal_get_description -> apr_signal_description_get + apr_sockaddr_ip_set -> apr_sockaddr_info_get + apr_sockaddr_port_get -> (access directly) + apr_sockaddr_port_set -> apr_sockaddr_info_get + apr_socket_create_ex -> apr_socket_create + apr_socket_set_inherit -> apr_socket_inherit_set + apr_socket_unset_inherit -> apr_socket_inherit_unset + FNM_NOMATCH -> APR_FNM_NOMATCH + FNM_NOESCAPE -> APR_FNM_NOESCAPE + FNM_PATHNAME -> APR_FNM_PATHNAME + FNM_PERIOD -> APR_FNM_PERIOD + FNM_CASE_BLIND -> APR_FNM_CASE_BLIND + MAX_SECONDS_TO_LINGER -> APR_MAX_SECONDS_TO_LINGER + + The following interfaces have function argument changes: + + apr_mmap_dup + apr_socket_create + + The following header files have been removed: + + apr_compat.h + +Changes with APR 0.9.5 + + *) Fix apr_snprintf() to respect precision for small floating point + numbers. PR 29621. [Artur Zaprzala ] + + *) Add command type APR_SHELLCMD_ENV for creating a process + which is started by the shell and which inherits the parent's + environment variables. [Jeff Trawick] + + *) Don't try to enable run-time linking on AIX < 4.2, as this + results in invalid linker options being used. PR 29170. + [Jeff Trawick] + + *) Don't assume getnameinfo() can handle IPv4-mapped IPv6 addresses + on any platforms. + [Jeff Trawick, Joe Orton, Colm MacCárthaigh ] + + *) Support setuid, setgid and sticky file permissions bits on Unix. + [André Malo] + + *) Fix sign error in apr_file_seek(APR_END). + [Greg Hudson ] + + *) Provide workaround for socklen_t declaration problem with 64-bit + build on HP-UX. Stop setting a PA-RISC-specific compile option + on ia64. Look for -mt thread option, which is used with HP-UX + vendor compiler on ia64. [Jeff Trawick, based on idea from + Madhusudan Mathihalli] + + *) Return an error instead of silently failing when apr_poll() is + used with file descriptors >= FD_SETSIZE. (Unix systems with + no native poll()) [Jeff Trawick, Brad Nicholes] + + *) Fix handling of negative numbers in apr_strtoi64() on platforms + without strtoll. [Joe Orton] + + *) Fix printing apr_int64_t values smaller than LONG_MIN on 32-bit + platforms in apr_vformatter. [Joe Orton] + + *) Fix apr_socket_opt_set with APR_IPV6_V6ONLY flag. Fixes httpd + Listen IPv6 socket behavior on FreeBSD 5.x, OpenBSD, NetBSD. + [Justin Erenkrantz] + + *) Fix apr_time_exp_get() for dates in 2038. + [Philip Martin ] + + *) Add APR_LARGEFILE flag to allow opening files with the + O_LARGEFILE flag; not recommended for general use, see + include/apr_file_io.h. [Joe Orton] + + *) Various build fixes: thread_rwlock.c on some Solaris platforms + (PR 22990); filestat.c on ReliantUnix (PR 22990); config.status + on IRIX (PR 19251). [Various] + + *) Use NI_NAMEREQD instead of NI_NUMERICHOST in + APR_CHECK_GETNAMEINFO_IPV4_MAPPED. PR 24469. [Justin Erenkrantz] + + *) Ensure that apr_sockaddr_info_get() does not return anything + other than AF_INET and AF_INET6 addresses. [Joe Orton] + + *) Clarify that apr_dir_read() does not guarantee order of returned + entries as previously claimed. [Joe Orton] + + *) The whole codebase was relicensed and is now available under + the Apache License, Version 2.0 (http://www.apache.org/licenses). + [Apache Software Foundation] + + *) Define apr_off_t as long rather than as off_t on platforms with a + 32-bit off_t to prevent incompatibility with packages such as + Perl which redefine the size of off_t via _FILE_OFFSET_BITS on + some platforms. [Ben Reser ] + + *) apr_socket_connect(): allow app to make subsequent call on + non-blocking socket. [Jeff Trawick] + + *) Add apr_os_pipe_put_ex(), which allows the caller to tell APR + to establish a cleanup on the pipe. [Jeff Trawick, Brad Nicholes] + + *) Fix make_exports.awk to work with apr-iconv. [Justin Erenkrantz] + +Changes with APR 0.9.4 + + *) win32: fix apr_file_dup() and apr_file_dup2() to dup the + ungetchar member [Stas Bekman] + + *) Preserve leading '../' segments as when merging to an empty and + unrooted path - fixes a bug observed in SVN with Win32/Netware/OS2. + [Mike Pilato , William Rowe] + + *) Work around a bug in Darwin when calling getnameinfo() on IPv4-mapped + IPv6-addresses. [Colm MacCárthaigh , Jeff Trawick, + Justin Erenkrantz] + + *) Add apr_temp_dir_get() for getting the most suitable temp directory + [Mike Pilato , Thom May] + + *) Modify apr_sockaddr_info_get to call the resolver when we + do not have a hostname. Also, fix bugs in the getaddrinfo() + implementation. + [Colm MacCárthaigh , Justin Erenkrantz] + + *) Change the behavior of unix process 'trylock's to return + APR_ENOTIMPL instead of segfaulting, consistent with the + other lock implementations. [William Rowe] + + *) Fix a subtle race where the ownership of a unix nested + thread lock could be corrupted when the prior owner released + the lock with another thread waiting on the same lock. + [William Rowe] + + *) apr_socket_data_set(): allow the same key to be used for + multiple sockets in the same pool. [Jeff Trawick] + + *) Add new table function apr_table_compress() and replace + red-black trees with mergesort in apr_table_overlap() + [Joe Schaefer , Brian Pane] + + *) Win32: Adopt Brian Havard's OS/2 rwlock implementation for + Windows [Marc Adkins, Bill Stoddard] + + *) Add apr_proc_mutex_lockfile() for retrieving the name of the + file associated with a mutex. [Jeff Trawick] + + *) Don't require the lock file name to be passed into + apr_proc_mutex_child_init() or apr_global_mutex_child_init(). + This allows child init to work when the lock file was a temp + file created by APR. (The problem only occurred with flock- + based mutexes.) [Jeff Trawick] + + *) When using a temporary file for flock- and fcntl-based mutexes, + don't let the file be deleted on close. For flock-based mutexes, + this corrects a fatal problem, since the file would disappear + when a program was spawned and cleanup-for-exec was performed, + and a subsequent attempt to perform child process mutex + initialization would fail. For fcntl-based mutexes, this was a + very minor issue that resulted in a failing unlink() when the + file was closed, since fcntl lock initialization always removes + the file immediately. [Jeff Trawick] + + *) When writing to pipes with a timeout set, handle the situation + where the kernel says the pipe is writable but an attempt to + write <= PIPE_BUF bytes gets EAGAIN. APR will now write whatever + data will fit. APR applications that relied on the atomic nature + of relatively small pipe write requests may be affected. + PR 20295 [Mark Street , Jeff Trawick] + + *) Define _THREAD_SAFE for all compilations on AIX. Previously + those of us who used the vendor compiler had it defined + implicitly and others did not. The difference became obvious + with the recent thread safety fixes to apr_password_validate(). + PR 20420 [Jeff Trawick] + + *) For apr_proc_detach(APR_PROC_DETACH_FOREGROUND), don't treat + a setsid() failure as fatal, as the usual cause is that the + caller is already a process group leader. PR 18519 + [Jeff Trawick] + + *) Fix some problems with non-blocking socket handling on unix + that resulted in infinite timeouts being used for non-blocking + sockets with apr_socket_connect() and some read/write calls. + [Jeff Trawick] + + *) Fix a bug in socket timeout handling on unix that left the + socket non-blocking after disabling the timeout. + [Jacob Craig Lewallen ] + + *) Added flag APR_FILE_ATTR_HIDDEN for manipulating the "hidden" + file attribute on Windows and OS/2. [Branko Cibej] + + *) SECURITY [CAN-2003-0245]: Fixed a bug that could be triggered + remotely through mod_dav and possibly other mechanisms, causing + an Apache child process to crash. The crash was first reported + by David Endler and was researched and + fixed by Joe Orton . Details will be released + on 30 May 2003. + + *) apr_proc_wait(): Handle interrupted waitpid(2) calls by calling + it repeatedly until it succeeds or fails with errno other than + EINTR. This hides this UNIX-specific behavior from APR clients. + + *) Removed the solaris-specific atomic code, due to licence + concerns (it was MPL 1.0, and the author could not be contacted) + [Ian Holsman] + + *) apr_file_gets(): Return APR_SUCCESS if any characters are + returned. Any I/O errors or EOF will be reported on the + next call. Callers that are coded to expect returned + data + APR_EOF when there is no final newline are affected + by this change. [Jeff Trawick] + + *) apr_proc_create() on Unix: Make the APR_SHELLCMD mode work + when there is more than one program argument passed in. + [Jeff Trawick] + + *) Add --cc and --cpp flags to apr-config. [Jeff Trawick] + + *) Don't segfault trying to close a file in error paths of flock + and fcntl mutex creation. PR 19036 [Jeff Trawick] + + *) Add %pT support to apr_snprintf() for printing an apr_os_thread_t. + [Jeff Trawick] + + *) Add APR_TCP_NODELAY_INHERITED & APR_O_NONBLOCK_INHERITED to apr.hw + [Allan Edwards] + + *) Add APR_UINT64_T_HEX_FMT. [Jeff Trawick] + + *) Add parameter to APR_SUBDIR_CONFIG to drop options passed to configure + before the subdir's configure is invoked. + [Jeff Trawick, Justin Erenkrantz] + + *) Implement APR_SO_RCVBUF socket option on Unix. + [Adam Sussman ] + + *) Don't add the math library (-lm) if the modf() function + is already available via libc. [Roy Fielding] + + *) Solaris cc: Don't use the -mt option for threaded builds. That + is for non-Posix threading, and the use of it prevented us from + linking with -lpthread, which in turn caused weird problems for + APR applications. [Kristofer Spinka ] + + *) OS/2: apr_stat() fixes - When a character device is stat'ed, + fill in finfo.name if it was asked for. Return APR_INCOMPLETE + when appropriate. Addresses httpd incident [CAN-2003-0134]. + [Brian Havard] + +Changes with APR 0.9.3 + + *) Don't enable posixsem, at build time, on systems where sem_t * + won't "fit" into an int (sizeof-wise). Also, better error handling + when we fail to create a posixsem. PR 17186 [Scott Herod + , Jim Jagielski] + + *) Default hpux 10.x to disable threading, since if it exists at all + the pthread implementation should not be trusted, while hpux 10 + had its own threads implementation that is no longer supported. + PR 9457 [William Rowe] + + *) Fix error in apr-config when symlinks are involved. + [Garrett Rooney ] + +Changes with APR 0.9.2 + + *) Numerous bug fixes for file and socket inheritence by child + processes on Unix, correcting bugs that affected the correct + behavior of apr_[file|socket]_inherit_[un]set() API. + [Bjoern A. Zeeb , William Rowe, Joe Orton] + + *) Define APR_UINT64_T_FMT and APR_UINT64_T_FMT_LEN. + Define APR_INT64_T_FMT_LEN on Windows and Netware. [Branko Cibej] + + *) Correct apr_file_gets() on OS2 and Win32 so that '\r's are no longer + eaten, and apr_file_gets() -> apr_file_puts() moves the contents + uncorrupted. [William Rowe] + + *) Alter Win32's handling of the apr_proc_t hproc member, so that we + close that system handle wherever an apr function would invoke the + final waitpid() against a zombie process on Unix. [William Rowe] + + *) APR_MAX_SECONDS_TO_LINGER and APR_FNM_* #defines replace their + old undecorated names (missing APR_ prefix). The old names will + disappear with APR 1.0.0. + [Craig Rodrigues , William Rowe] + + + *) When generating a semaphore name for posixsem locking, try to + be a little more robust (and unique). [Jim Jagielski] + + *) Add functions apr_env_get, apr_env_set and apr_env_delete for + manipulating the environment. [Branko Cibej] + + *) Fix APR_LAYOUT to work with layout files with no preceding blank lines + and emit errors when layout is not found. PR 15679. + [Justin Erenkrantz] + + *) Add functions apr_filepath_list_split and apr_filepath_list_merge + for managing search paths. [Branko Cibej] + + *) Introduce Release mode debugging symbols for Win32 builds of apr. + All library builds gain /Zi for debug symbols (which are discarded + at link time if some flavor of the /debug flag isn't passed to link) + and .dll builds gain .pdb symbols. [Allen Edwards, William Rowe] + + *) Add two new proc attributes to improve diagnostics for + apr_proc_create() failures on platforms where fork()+exec() is used. + See the doc for apr_procattr_child_errfn_set() and + apr_procattr_error_check_set(). [Jeff Trawick] + + *) Rename rules.mk to apr_rules.mk and make apr_rules.mk be installed. + [Thom May] + + *) Fix a bug in apr_proc_create() that could cause a new child process + to run the parent's code if setrlimit() fails. [Jeff Trawick] + + *) Disable apr_socket_sendfile() on 64-bit AIX to avoid an apparent + system problem. PR 11408. [Jeff Trawick] + + *) Add --includedir flag to apr-config. [Justin Erenkrantz] + + *) Only include sys/syslimits.h if we don't have limits.h + [Craig Rodrigues , Garrett Rooney + , Thom May] + + *) Allow apr-config to work in symlinked install directories when + 'realpath' is available. [Justin Erenkrantz] + + *) Namespace protect the header files in include/arch + [Thom May] + + *) Add function apr_filepath_encoding and associated constants. + [Branko Cibej] + + *) Allow apr_hash to have greater than int number of elements. + [Justin Erenkrantz] + + *) Allow generation of dependencies by non-GCC compilers. + [Justin Erenkrantz] + + *) Prevent obscenely large values of precision in apr_vformatter + from clobbering a buffer. [Sander Striker, Jim Jagielski] + + *) limit the renames performed in apr_rename.pl to the most recent renames. + [Thom May] + + *) Changed apr_mmap_dup() and friends so that there's no longer any + is_owner concept on the mmaped region, but rather something more + along the lines of a reference count. This allows the old apr_mmap_t + to still be used safely when the new apr_mmap_t is in a disjoint pool. + [Cliff Woolley, Sander Striker] + + *) Fix a bug in apr_hash_merge() which caused the last entry in the + overlay hash to be lost. PR 10522 [Jeff Trawick] + + *) Add DougM's apr_rename.pl script into helpers, and update for the new + batch of updates [Thom May] + + *) Renames done (deprecated functions wrapped): + apr_filename_of_pathname -> apr_filepath_name_get + apr_get_groupid -> apr_gid_get + apr_get_groupname -> apr_gid_name_get + apr_compare_groups -> apr_gid_compare + apr_parse_addr_port -> apr_port_addr_parse + apr_shutdown -> apr_socket_shutdown + apr_bind -> apr_socket_bind + apr_listen -> apr_socket_listen + apr_accept -> apr_socket_accept + apr_connect -> apr_socket_connect + apr_send -> apr_socket_send + apr_sendv -> apr_socket_sendv + apr_sendto -> apr_socket_sendto + apr_implode_gmt -> apr_time_exp_gmt_get + apr_get_home_directory -> apr_uid_homepath_get + apr_get_userid -> apr_uid_get + apr_current_userid -> apr_uid_current + apr_compare_users -> apr_uid_compare + apr_get_username -> apr_uid_name_get + apr_recvfrom -> apr_socket_recvfrom + apr_sendfile -> apr_socket_sendfile + apr_recv -> apr_socket_recv + [Thom May] + + *) Add APR_IPV6_V6ONLY socket option. [Jeff Trawick] + + *) Update timeout algorithm in free_proc_chain. If a subprocess + did not exit immediately, the thread would sleep for 3 seconds + before checking the subprocess exit status again. In a very + common case when the subprocess was an HTTP server CGI script, + the CGI script actually exited a fraction of a second into the 3 + second sleep, which effectively limited the server to serving one + CGI request every 3 seconds across a persistent connection. + [Bill Stoddard, Kai.Risku@arrak.fi] + + *) Update doxygen tags. [Justin Erenkrantz] + + *) NetWare: implemented a file IO path context scheme to directly + reference directory paths and files in the file system rather + than having to traverse the file system on every stat() or + open() call. (Performance enhancement) [Brad Nicholes] + + *) ReliantUnix: recognize that dlsym() is in libdl and dlopen() is in + libc. The check is generic so maybe this fixes some other system. + PR 14189 [Jeff Trawick] + + *) Win32: Fix APR_APPEND file i/o. [Bill Stoddard] + + *) Fix a problem retrieving the remote socket address for sockets + created via apr_os_sock_put() or apr_os_sock_make(). [Jeff Trawick] + + *) Add recognition of and socket API support for the SCTP protocol. + [Randall Stewart ] + + *) Win32: apr_shutdown was not honoring apr_shutdown_how_e and + always shutting down the socket for read. This could result + in Apache HTTPD 2.0 clients getting early connection closures + because lingering_close() was broken. [Bill Stoddard, Allan Edwards] + + *) Add apr_atomic_casptr() to support atomic compare-and-swap + of pointers [Brian Pane] + + *) Add apr_socket_create_ex() to allow protocol to be specified for the + socket. With APR 1.0, this function will be removed and apr_socket_create() + will have the additional parameter. + [Randall Stewart ] + + *) Fix the detection of INT64_C() when defined in . + [Joe Orton ] + + *) Don't use whitespace before preprocessor directives in the configure + logic. Such whitespace breaks with some older preprocessors; a + particularly nasty break occurs on Tru64 4.0f where APR_CHECK_DEFINE + will always succeed. [Joe Orton ] + + *) Add APR_IPV4_ADDR_OK flag to apr_sockaddr_info_get() to allow + apps to avoid lookup of IPv6 address if IPv4 address is sufficient. + (New APR_IPV6_ADDR_OK flag is similar.) [Jeff Trawick] + + *) Disable IPv6 support on Darwin. The current IPv6 support has a + problem in getnameinfo() which breaks certain applications. + [Sander Temme , Jeff Trawick] + + *) Support for SCO OpenServer Release 5 [Kean Johnston ] + + *) Faster (inline and mutex-free) implementations of all apr_atomic + operations for Linux/x86 (requires a 486 or later; to enable, + configure APR with --enable-nonportable-atomics=yes ) [Brian Pane] + + *) Add --bindir option to apr-config. [Justin Erenkrantz] + + *) Begin to rehash the test suite. There is now a new test program called + testall. This program currently runs testtime and teststr with the + CuTest framework. The stand-alone programs for testtime and teststr + can be built, but only if a special flag is specified when building. + [Ryan Bloom] + + *) Fix a broken check for a failure to read from the random device file. + PR 12615 [tenthumbs@cybernex.net] + + *) Print informative link errors on Darwin. [Justin Erenkrantz] + +Changes with APR 0.9.1 + + *) Fixed usage of alloca in apr_poll() on Tru64 + [Dave Hill ] + + *) Running "make check" in the toplevel directory or the test/ directory + will build and run all test programs. [Aaron Bannert] + + *) Add apr_array_pop(). [Justin Erenkrantz] + + *) Fixed the native SPARC v8plus version of apr_atomic_dec + to match the semantics of the default C version [Brian Pane] + +Changes with APR 0.9.0 + + *) If the length argument to apr_snprintf is 0, then we should return the + length that the string would be if we actually were going to fill it out. + However, if the length argument is 0, we can also accept a NULL string. + Also, added a test case for this. [Ryan Bloom] + + *) Printing a string with apr_snprintf can seg fault, if a precision is + specified for the string, and the string being printed doesn't have a + trailing '\0'. Fix that seg fault by not calling strlen if a precision + is specified when printing a string. Also add a test to the test suite + for this case. + [R Samuel Klatchko ] + + *) handle leak related to threads on Windows2000/XP + [INOUE Seiichiro ] + + *) Includes moved to INCLUDEDIR/apr-{major} (e.g. /usr/include/apr-0) + [Greg Stein] + + *) libtool versioning is used to give the library sonames a real + value. The libraries will be libapr-{major}.so.0.{minor}.{patch} + [Greg Stein] + + *) Fix apr_tokenize_to_argv() to remove the escape character + (backslash) from the argument tokens. PR 11793 [Paul J. Reder] + + *) Add APR_PARSE_ARGUMENTS and APR_LAYOUT macros for better layout + support. [Thom May] + + *) Add parallel-apr layout which utilizes the major version number in + directories and library names. [Justin Erenkrantz] + + *) Add a version number to the library name (e.g. libapr-1.so) so + that apps can do things like: -lapr-1 or -lapr-2, depending on + which version they want to use and link against. [Greg Stein] + + *) Add --version to apr-config so that apps can retrieve the version + information of the (installed) APR. [Greg Stein] + + *) Remove the APRVARS system; apps should use apr-config. [Greg Stein] + + *) EBCDIC: fix compile failure in strings/apr_strings.c in + httpd-2.0.40 with the following error message: + CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported + + *) In apr_signal_thread() remove synchronous signals from the mask + passed to sigwait(). It is never valid for them to be there. + Some platforms silently ignore them, some return EINVAL, some + don't process it as desired. [Jeff Trawick] + + *) Change config.nice generation to always expand variables. + [Justin Erenkrantz] + + *) Renamed apr_strtoll()/apr_atoll() to follow int64 convention, + so these new helpers are apr_strtoi64/apr_atoi64(), since + 'll' (long long) is a nonportable and aspecific construct. + Used ac/m4 tests to choose the appropriate fn behind strtoi64. + [William Rowe] + + *) don't perform a strlen on that name value without checking for NULL + first (in getopt) + [David Waite , Ian Holsman] + + *) Added apr_strtoll() and apr_atoll() to strings lib. + [Shantonu Sen , Wilfredo Sanchez] + + *) Added a lightweight internal index to apr_table_t to speed up + table lookup operations [Brian Pane] + + *) initalize handle members to invalid before calling createprocess + on win32 [Rob Saccoccio ] + + *) Removed apr/i18n to apr-util/xlate for inclusion of apr-iconv + as required by missing libiconv. [William Rowe] + + *) Removed apr/md5 and apr/uuid into apr-util/crypto. [William Rowe] + + *) Add APR_BUFFERED support to apr_os_file_put(). [Justin Erenkrantz] + + *) Fix misinterpretation of timeout for select() on Win32/Netware. + Identified by [TANAKA Koichi ] + + *) Re-write apr_poll() on Unix. This improves the performance by + giving the user back control over the memory in the pollset. + [Ryan Bloom] + + *) Added APR_LIMIT_NOFILE option to apr_procattr_limit_set() to + control the file descriptor limit on platforms that support + RLIMIT_NOFILE. [Brian Pane] + + *) FreeBSD: change apr_sendfile to accomodate a 4.6 kernel patch. + [Greg Ames] + + *) Faster code for the apr_table get/set functions [Brian Pane] + + *) Fix the userid functions on Irix to handle the way that Irix + reports a failure from getpwnam_r(). PR 10095. + [Robert I. Cowles , Jeff Trawick] + + *) apr_table_do() and apr_table_vdo() now return an int rather than + void to indicate whether or not any of its iterations returned 0. + [Cliff Woolley] + + *) Fix the definition of union semun so that it is valid on systems + where sizeof(long) != sizeof(int). This resolves a hang on + HP-UX/Itanium. + [Madhusudan Mathihalli ] + + *) Correct shared library support on Darwin to not fatally error out + when a shared library does not exist. [Justin Erenkrantz] + + *) Added optimized atomic CAS support for Linux/x86 (available only + when APR is configured with --enable-nonportable-atomics=yes) + [Brian Pane] + + *) Fix a compile error in the EGD support in rand.c on older Solaris + versions. PR 9976 [Jim Morris ] + + *) Fixed apr_file_seek() to unset the eof_hit flag. [Stas Bekman] + + *) Removed --disable-atomics flag and added --enable-nonportable-atomics, + thereby defaulting to portable binaries on those systems that could + be optimized at the expense of portability. PR: 9507 [Aaron Bannert] + + *) Added 2 additional lock functions: apr_proc_mutex_name and + apr_proc_mutex_defname which returns the type name of the mutex + (eg: "sysvsem") as well as the default mutex type (APR_LOCK_DEFAULT). + Mostly useful under Unix were the locktypes are selectable. + [Jim Jagielski] + + *) Fixed apr_generate_random_bytes() for Win32 on Win NT or 9x by + dropping the 0x40 bit (CRYPT_SILENT) for earlier OS'es. + PR 9286 [William Rowe] + + *) Added --with-devrandom=[DEV] configure flag which allows a particular + "/dev/random"-compatible device to be specified, overriding the + default search path (/dev/random then /dev/arandom then /dev/urandom). + Also, if --with-egd= is specified, it now implies + --without-devrandom. [Cliff Woolley] + + *) Darwin/Mac OS X: Don't leave zombie processes when the app calls + apr_signal(SIGCHLD, SIG_IGN). This fixes a problem with Apache's + mod_cgid. PR 9168. [Jeff Trawick] + + *) Win32: Fix bug where apr_sendfile() was incorrectly returning + APR_SUCCESS on a TransmitFile call that was interrupted by + the client closing its end of the connection. Always call + GetOverlappedResults() to get results of async TransmitFile() + completion notification. [Bill Stoddard] + + *) Renamed APR_XtOffset -> APR_OFFSET and APR_XtOffsetOf -> APR_OFFSETOF. + [Cliff Woolley] + + *) Cygwin: the unix version of apr_file_open() must respect the + APR_BINARY flag if the underlying platform requires it (in + which case we assume O_BINARY is defined). PR 9185. + [Cliff Woolley] + + *) Linux, AIX: Use crypt_r() instead of crypt() because the native + crypt() is not thread-safe. The misuse of crypt() led to + intermittent failures with Apache basic authentication when crypt + passwords were being used. [Jeff Trawick] + + *) AIX: Global mutexes don't need an intraprocess mutex when SysV + sems are used for the crossprocess mutex. + Darwin: The same optimization was applied for Posix sems. + [Jeff Trawick] + + *) Fix a problem with global mutexes on OS/390 when something other + than the default mechanism (SysV sem) was used. The mutexes didn't + necessarily block out other threads in the same process. + [Jeff Trawick] + + *) Fixed apr_strfsize formatting of values over 1 gig + [Matsuzaki Yoshinobu ] + + *) Renamed --disable-atomics as --disable-optimized-atomics, + since it doesn't really disable the atomics. [Aaron Bannert] + + *) Converted apr_pcalloc to a macro [Brian Pane] + + *) Fixed APR_STATUS_IS_ETIMEDOUT macro. + [Dagfinn Aarvaag ] + + *) Add --disable-atomics switch to override our handcoded assembly + optimizations. Note that this has no effect if your operating + system has a userspace atomic interface. [Justin Erenkrantz] + + *) Remove Linux atomic support since it does not have a usable + userspace atomic interface. [Justin Erenkrantz] + + *) Don't require that the DNS can map 127.0.0.1 when checking for + the presence/usability of getnameinfo(). PR 7642. [Jeff Trawick] + + *) Remove APR_WANT_SIGNAL from apr_want.h because code must include + apr_signal.h in order to get consistent definitions. [Roy Fielding] + + *) Don't try to use /dev/zero and mmap on platforms that don't + support that (such as HP-UX). PR 8537. [Justin Erenkrantz] + + *) Reduce the number of apr_sendfile calls on AIX and OS/390 by + remembering when the kernel tells us the next one will block. + [Jeff Trawick] + + *) Reduce the number of apr_sendfile calls on FreeBSD by remembering + when the kernel tells us the next one will block. [Greg Ames] + + *) To support modules like PHP, which implement their own + loaded extensions, Darwin needs to place their public + symbols in the global table. [Marko Karppinen , + Jim Jagielski] + + *) Rename apr_get_groupname to apr_group_name_get. + [Thom May ] + + *) Allow VPATH builds to properly build dependencies and switch to + a .deps dependency model to mimic httpd-2.0. [Justin Erenkrantz] + + *) Tru64: Stop leaving zombies in APR apps like mod_cgid which + tell APR to ignore SIGCHLD. + [Dave Hill ] + + *) Ensure that the ATOMIC_HASH can not be negative. + [Joe Orton ] + + *) Fix a problem with eof reporting with Unix file I/O on + unbuffered files. [Stas Bekman ] + + *) Rename apr_explode_time to apr_time_exp_tz. + [Thom May ] + + *) Rename apr_explode_localtime to apr_time_exp_lt. + [Thom May ] + + *) Set precompiler for Solaris atomics when using GNU binutils. + PR 7876. [solomon@conceptshopping.com (Marvin Solomon)] + + *) AIX: Fix breakage with 64-bit builds on versions of AIX prior + to 5L. PR 7957 [Jeff Trawick] + + *) On socket write functions (apr_sendfile, apr_send, apr_sendv), + added a select to wait for writability on the socket if the + previous write was incomplete. [Jeff Trawick, Brian Pane] + + *) Deprecated the apr_lock.h API. Please see the following files + for the improved thread and process locking and signaling: + apr_proc_mutex.h, apr_thread_mutex.h, apr_thread_rwlock.h, + apr_thread_cond.h, and apr_global_mutex.h. [Aaron Bannert] + + *) Fix some daylight savings time breakage on (at least) AIX, + Solaris, and HP-UX. [Jeff Trawick] + + *) Added support for Posix semaphores (sem_open, et.al.) for mutex + locking. We use named semaphores in this implementation. The + default priority is between pthread and sysvsem. + [Jim Jagielski] + + *) Get flock-based mutexes to work in apps like Apache. Use the + same permissions on flock- and fcntl-based mutexes as Apache + 1.3. [Jeff Trawick] + + *) Fix apr-config so that it will not attempt to cd to a non-existent + directory. [Justin Erenkrantz] + + *) Change the ordering of the apr_lock implementation method to + better match what's done in Apache 1.3. The ordering is + now (highest to lowest): pthread -> sysvsem -> fcntl -> flock. + [Jim Jagielski] + + *) Improve detection of the INT64_C macro to prevent problems + with HP-UX's ANSI C compiler. PR 8932. [Justin Erenkrantz] + + *) Make sure gethostbyname() can handle 255.255.255.255 if we + are to trust it to handle numeric address strings in + apr_sockaddr_info_get(). This fixes a problem on HP-UX + which led to an assertion failure at Apache startup when + using vhosts. [Jeff Trawick] + + *) Don't mask SIGUSR2 [Jin Hong ] + + *) Load libraries if they not MH_BUNDLE, but if they are not, it + just attempts to link them as shared libs. + [Pier Fumagalli ] + + *) apr_atomic_dec now returns a zero value if the value of + the atomic is zero, non-zero otherwise [Ian Holsman] + + *) When opening a file, only create an internal thread mutex + if APR_XTHREAD is set. [Brian Pane] + + *) Move the kill_conditions enum in apr_thread_proc.h into the + APR namespace. kill_after_timeout et al have been renamed + appropriately (e.g., APR_KILL_AFTER_TIMEOUT). [Jeff Trawick] + + *) Fix a segfault in apr_thread_rwlock_destroy() on Win32. + [INOUE Seiichiro ] + + *) configure now checks to see if we can change DNS timeout values + [Ian Holsman] + + *) Fix a bug in apr_file_seek() on Unix when using buffered + files. PR 10003 [Jeff Trawick] + + *) Small table performance optimization: eliminate the + zero-fill of newly allocated elements when expanding + a table's size. [Brian Pane] + + *) Allow APR to install its generated libtool(s) via the + --with-installbuilddir option (defaults to ${datadir}/build). + [Justin Erenkrantz] + + *) renames: apr_ansi_time_to_apr_time becomes apr_time_ansi_put + ap_exploded_time_t becomes apr_time_exp_t + [Thom May ] + + *) Add the APR_FILE_NOCLEANUP flag to apr_file_open(). + Adding the flag will prevent the file from being closed + when the pool passed in on apr_file_open() is destroyed. + This feature is useful when using apr_os_file_get|put() + to manage the apr_os_file_t in apr_file_t (ie, file handle + caching in the HTTP server) [Bill Stoddard] + + *) Win32: Fix APR_XTHREAD problems in apr_file_read() + and apr_file_write(). Multiple threads were using the + same overlapped structure and io event handle created + in the open call, which could cause unpredictable + file i/o results. [Bill Stoddard] + + *) Win32: apr_proc_mutex_trylock and apr_proc_mutex_lock were + incorrectly returning APR_BUSY if the lock was previously + held by a thread that exited before releasing the lock + (ie, if the process holding the lock segfaults). The MSDN + doc says when WaitForSingleObject returns WAIT_ABANDONED, + the calling thread takes ownership of the mutex, so these + two routines should return APR_SUCCESS in this case, not + APR_BUSY. [Bill Stoddard] + + *) Added a new m4 function APR_EXPAND_VAR that will iteratively + interpolate the contents of a variable, such as $sysconfdir, + for use in a borne script. [Aaron Bannert] + + *) apr-atomic support for old-sparc's and gas on solaris + [Dale Ghent , jean-frederic clere, Ian Holsman] + + *) Change apr_proc_detach to take a parameter that can enable/disable + automatic forking (aka, to "daemonize"). + [Jos Backus , Aaron Bannert] + + *) Implement apr_global_lock_foo() on Win32 + [Bill Stoddard] + + *) Fix select() argument call when waiting for IO. PR 9674. + [David MacKenzie ] + + *) Add a new lock API (apr_global_mutex_t) to provide guaranteed + cross-process AND cross-thread mutual exclusion. [Aaron Bannert] + + *) Note: We are in the process of deprecating the apr_lock.h API. + The new and improved lock/synchronization APIs now reside + in apr_thread_mutex.h, apr_proc_mutex.h, apr_thread_rwlock.h, + and apr_thread_cond.h. [Aaron Bannert] + + *) Enable autoconf 2.52{f,g} build support. + [Blair Zajac ] + + *) Added new functions for atomic operations. These are experimental + at the moment, so use in apps is discouraged [Ian Holsman] + + *) Correct serious problems with the Win32 apr_file_dup2 + and apr_file_open_stdxxx() fns. [William Rowe] + + *) Begin implementation of the WinCE port. + [Mladen Turk ] + + *) Disable SHMEM_MMAP_ZERO on HPUX 11.x where it is not supported. + Use SHMEM_SHMGET_ANON instead. [Aaron Bannert] + + *) Fix a few attempts to add to a void * ptr in the Unix shared + memory support code. PR #9710 Per Ekman [pek@pdc.kth.se] + + *) In the Linux apr_sendfile(), fix the types of some parameters + to apr_send() and apr_recv(). Breakage was seen in 64-bit mode + on s/390. PR #9712 [Neale.Ferguson@SoftwareAG-usa.coom] + + *) added APR_PROGRAM_ENV and APR_PROGRAM_PATH options for starting + processes via apr_proc_create() [Greg Stein] + + *) Deprecated apr_pool_free_blocks_num_bytes() [Sander Striker] + + *) Add --enable-pool-debug to make it easier for people to + enable pool debug mode. Removed the APR_POOL_DEBUG_VERBOSE + define that was previously being used. [Sander Striker] + + *) Changed the apr_file_dup2() function prototype. It can only + take and reuse an apr_file_t*, and will no longer create one + if *new_file == NULL (use apr_file_dup() for that). [Aaron Bannert] + + *) Implemented name-based shared memory on Unix. [Aaron Bannert] + + *) Fix spelling mistakes in APRDesign. + [Blair Zajac ] + + *) Ensure that apr_file_mktemp creates the temp file if it isn't there. + [John Sterling ] + + *) Make sure to pre-mark anon SysV shared memory segments as + removed. [Jim Jagielski] + + *) Add --with-efence to allow usage of Electric Fence. + [Justin Erenkrantz] + + *) Updated the pools debug code. Check if a pool is still + valid on the most common apr_pool_xxx functions. + Fix the way APR_POOL_DEBUG_VERBOSE was using stderr. + Make the output somewhat nicer in this debug mode. [Sander Striker] + + *) Add new define APR_POOL_DEBUG_VERBOSE which spits out info + about pool creation/destruction [Ian Holsman] + + *) Fix GMT offset adjustments for platforms that do not have native + GMT offset adjustments. [Jon Travis ] + + *) Add new apr_shm_t API and remove old apr_shmem_t API. The new + API handles both anonymous and name-based shared memory. Anonymous + shared memory segments are only usable on systems with process + inheritance, and so the new API with name-based segments is + usable on platforms like Win32. [Aaron Bannert and William Rowe + with much help from Justin Erenkrantz and Sander Striker] + + *) Add --with-egd to support EGD-compatible entropy gatherers for + those platforms without native support. [Justin Erenkrantz] + + *) apr_lock_create() and apr_proc_mutex_create() now have an + additional parameter for specifying the lock mechanism. + apr_lock_create_np() and apr_proc_mutex_create_np() have been + removed. [Jeff Trawick] + + *) Change the prototype of apr_thread_exit() so that the apr_status_t + is no longer a pointer. It was difficult and sometimes hazardous + to return a apr_status_t* at times, and this allows us to return + the APR_* error codes directly. [Aaron Bannert] + + *) Add apr_sockaddr_equal() for comparing APR sockaddrs. + [Jeff Trawick] + + *) Win32: apr_sendfile() should return APR_ENOTIMPL if + oslevel < WINNT. [Bill Stoddard] + + *) Put new pools code in place which allows applications to + switch off locking on pools operations in case a pool is + guaranteed to never being used in more than one thread + at the same time. We've seen a significant performance + improvement over the old code. [Sander Striker] + + *) Add apr-config - a shell script to allow third-party programs + easy access to APR configuration parameters. [Justin Erenkrantz] + + *) Add find_apr.m4 to allow third-party programs that use APR to + have a standard m4 macro for detection. [Greg Stein] + + *) SEGV in apr_table_overlap [Brian Pane] + + *) apr_array_copy speedup by removing the zero-fill [Brian Pane] + + *) Fix build breakage on systems with getaddrinfo() but not + gai_strerror() (e.g., RedHat 5.2). [Jeff Trawick] + + *) Fix a problem in Unix apr_file_dup() which caused 0 to be returned + by the first read. [Stas Bekman ] + + *) Fix a buglet that caused APR_FILE_BASED_SHM to be set inadvertently + on some platforms (e.g., Linux, AIX). [Jeff Trawick] + + *) Speed up apr_table operations by using a cache/checksum and a + red-black tree in the overlay. + [Brian Pane , Cliff Woolley] + + *) Speed up apr_pool_userdata_set[n] by letting hash_set figure out + the strings length. [Brian Pane ] + + *) New function apr_mmap_dup. This is called in the mmap_setaside. + [Brian Pane ] + + *) Speed up the apr_hash_t implementation's handling of APR_HASH_KEY_STRING. + [Brian Pane ] + + *) Tweak apr_gethostname() so that it detects truncation of the + name and returns an error. [Jeff Trawick] + + *) Fix bug in Darwin DSO code. [Sander Temme] + + *) Fix apr_setup_signal_thread() to grab the right error code from + a sigprocmask() failure. This only affects platforms that use + sigprocmask() in lieu of pthread_sigmask(). [Jeff Trawick] + + *) Fix the Unix HAVE_POLL flavor of apr_poll_socket_mask() so that + it doesn't segfault. Avoid some wasted storage in a poll-related + APR structure. [INOUE Seiichiro ] + + *) Fix apr_setup_signal_thread() so that threads don't block + synchronous signals (e.g., SIGSEGV). It is a programming error + to do so, and some platforms (e.g., Solaris, AIX) don't call any + registered signal handler when such signals are blocked. + [Jeff Trawick] + + *) Change the apr_table_elts macro so that it provides access via + a const pointer instead of a non-const pointer. + [Brian Pane ] + + *) Use strerror_r() where available, since strerror() isn't always + thread-safe. Example systems where strerror() isn't thread-safe: + Linux+glibc, AIX [Jeff Trawick] + + *) Fix some file cleanup problems in apr_proc_create() which could + result in the pipes for stdin/stdout/stderr being closed + immediately. [Jeff Trawick] + + *) New functions apr_hash_[merge|copy], change to overlay fn + so that it calls merge, which does a inline iteration instead + of calling the iterator function. [Brian Pane ] + + *) Introduce the apr_pool_userdata_setn() variant that doesn't + strdup the key. Allows both the _setn() and _set() variant to + accept NULL for the cleanup. [Brian Pane ] + + *) Re-vamp the apr_proc_wait and apr_proc_wait_all functions. We + now return the exit code from the program and a reason that the + program died, either normal exit or signalled. + [Jeff Trawick and Ryan Bloom] + + *) Implement portable accessors for proc mutex. These are equivalent + to apr_os_lock_get/set, but they work for apr_proc_mutex_t types + instead. [Aaron Bannert] + + *) Added a new parameter to apr_thread_mutex_init(). Now, by default, + thread mutexes are not nested (sometimes called "recursive"). To + enable nested mutexes, a flag must be passed to the init script. + Non-nested mutexes are much faster than nested ones. + [Aaron Bannert] + + *) read_with_timeout in apr/file_io/win32/readwrite.c incorrectly + returned APR_SUCCESS instead of APR_EOF when PeekNamedPipe failed + and the result from GetLastError() was ERROR_BROKEN_PIPE. Because + of this, the pipe wasn't closed as soon as it could be. + [Tim Costello ] + + *) Fix a problem in the Win32 pipe creation code called by + apr_proc_create(): It didn't register cleanups for either the + read or the write ends of the pipe, so file handles (and event + handles for pipes with asynchronous I/O mode set) are never + closed. [Tim Costello ] + + *) Add support for QNX 6. [J.T. Conklin ] + + *) We now create exports.c and export_vars.h, which in turn create + exports.c. From this we generate two more files with different + purposes: apr.exp - list of exported symbols; and exports.lo + (exports.o) - an object file that can be linked with an executable + to force resolution of all apr symbols. [Aaron Bannert] + + *) Add the apr_thread_cond_timedwait function to the condition + variable API. [Aaron Bannert] + + *) Fixed apr_file_mktemp on systems without mkstemp (Win32, etc). + [Mladen Turk, Cliff Woolley] + + *) Fix a segfault in apr_poll_clear on Unix. Also fix the logic + for the case where there are multiple events ORed together in + the events list. [Jamshid Mahdavi ] + + *) Files opened on Unix with the flag APR_DELONCLOSE are now + not unlinked until they are actually closed, rather than as + soon as they're opened. The old approach worked but made + handling temp files harder. [Cliff Woolley] + + *) Fix potential segfault when closing a file on Unix. If + apr_file_close() was called and it failed, it would not + deregister the file cleanup. Therefore the cleanup would + be run again later on a now-invalid descriptor. [Cliff Woolley] + + *) Introduce apr_pool_lock for debugging, in combination with + ALLOC_USE_MALLOC + DEBUG_WITH_MPROTECT. Only implemented + on Win32 today, very effective for debugging pool constness. + [William Rowe] + + *) Optimize apr_pstrcat by caching lengths of first 6 strings + [Brian Pane ] + + *) Add pool accessors to the apr_thread_mutex_t datatype. + [Aaron Bannert ] + + *) Add the apr_file_mktemp function. This creates and opens a + temporary file, for use by the program. This file is created + delete_on_close. The initial implementation only works on + Unix, but Windows is coming soon. [Ryan Bloom] + + *) Make the unix version of apr_proc_wait_all_procs a simple wrapper + around apr_proc_wait, and which extracts the exit code from the + status returned by waitpid. + [Kevin Pilch-Bisson ] + + *) Add process locking API to APR. [Aaron Bannert ] + + *) Add condition variables for Windows. [Ryan Bloom] + + *) Add condition variables to the APR set of locking functions. + This does Unix, and provides stubs for all other platforms. + [Aaron Bannert ] + + *) Don't search for IPv6 names in apr_sockaddr_info_get() if the + application doesn't specify the family (i.e., the application + passes in AF_UNSPEC) and APR isn't built with IPv6 support. + [Jeff Trawick] + + *) Fix the API for the apr_proc_create() call on Win32. Several + bad assumptions are gone, including a mismatch between unix and + win32, where win32 was defaulting to create detached. Also fixes + the apr_proc_t's pid member to a real pid (identity that works + across processes) instead of the handle (which is a new hproc + member value.) [William Rowe] + + *) Modify the external apr_filepath_get() fn to take a flags arg, + currently only for APR_FILEPATH_NATIVE. This returns c:\foo + format on Win32, and should do the same on OS2, or sys\vol:\foo + on Netware. Primarily for internals, but possibly useful to + others (and it mirrors some of the other apr_filepath_*() calls.) + [William Rowe] + + *) Add the new thread read/write lock API to APR. + [Aaron Bannert ] + + *) Add the new thread mutex lock API to APR. + [Aaron Bannert ] + + *) Cache GMT offset on platforms that don't store it in the tm struct. + This offset is normalized to be independent of daylight savings + time. [Brian Pane ] + + *) Initial support for cygwin. [Stipe Tolj ] + + *) Fix a problem with buffered files on Unix. [Brian Havard] + + *) Fix the bungling of getaddrinfo() error codes. [Jeff Trawick] + + *) Add an apr_thread_once function to APR. This allows a + program to ensure that a function is only called once. + [Ryan Bloom] + + *) APR Documentation is now in Doxygen format. + [Ian Holsman] + + *) Get apr_ungetc() to work with buffered files on Unix. + [Jeff Trawick] + + *) Fixed apr_filepath_root on Unix [William Rowe, Cliff Woolley]. + + *) Rename XtOffset to APR_XtOffset. This namespace protection + is important to keep from conflicting with other packages. + [Perl] + + *) Introduce a new --disable-ipv6 option to disable IPv6 support. + [Sterling Hughes , Jeff + Trawick] + + *) Fix the new shared memory code. We need to pass a pointer to + an apr_file_t to apr_file_open. Also, apr_os_file_get returns + a status value, not the OS file descriptor. [Ryan Bloom] + + *) Fix the new shared memory configure script. The APR_DECIDE + macros go in order, so the last set of dependancies that are + met are the ones used. That means that when using those macros, + options should be listed with the least desirable option first, + and the most desirable last. The new shared memory routines did + the opposite, so we chose the wrong shared memory option on Linux. + [Ryan Bloom] + + *) Move the necessary shared memory code from MM into APR and remove + our dependency upon MM. [Justin Erenkrantz] + + *) Get apr_lock_file and apr_unlock_file working on Windows 9x. + [Mladen Turk, Bill Stoddard] + + *) Make all APR pools be allocated out of the permanent pool. + This brings APR pools back to a tree structure. There are + no longer any way to create a pool that is not a decendant + of the permanent_pool. [Ryan Bloom] + + *) Wrap all functions in APR_DECLARE macro. + [Sterling Hughes ] + + *) Non-blocking connects shouldn't be calling connect a second + time. According to Single Unix, a non-blocking connect has + succeeded when the select pops successfully. It has failed + if the select failed. The second connect was causing 502's + in the httpd-proxy. [John Barbee barbee@veribox.net] + + *) Fix apr_dir_rewind() for Win32 to avoid returning a bogus error. + [Jeff Trawick, William Rowe] + + *) Detect required libraries first. This minimizes the libraries + needed in apr_hints.m4. [Justin Erenkrantz] + + *) Support the AIX, glibc2, and Solaris variants of gethostby{name|addr}_r. + Use gethostbyaddr_r function when available. + [Sterling Hughes ] + + *) Add new socket option, APR_INCOMPLETE_READ, that should be + set when you expect the first non-blocking read to fail with + EAGAIN. Setting APR_INCOMPLETE_READ prior to calling apr_read + will cause select() to be called first to wait for bytes + to read. [Brian Pane, Dean Gaudet] + + *) Better installation. This makes us install the APRVARS file, + as well as MM. [Ryan Bloom] + + *) Provide new number conversion functions apr_itoa, apr_ltoa, and + apr_off_t_toa, and inline code in inet_ntop4, to reduce CPU + consumption. [Brian Pane] + + *) Updated APR to pass the thread worker_function prototype + (apr_thread_start_t) two parameters, the apr private data + (apr_thread_t*) and the application private data (void*). + Applications' worker_thread() routines may use apr_thread_pool_get + to access the pool (implemented using APR_POOL_*_ACCESSOR() macros.) + [Aaron Bannert ] + + *) Add Solaris 8's sendfilev() support. This requires the following + patches from Sun: 111297 (Sparc), 111298 (x86). You'll need the + other patches listed in the patch description. [Justin Erenkrantz] + + *) Close file descriptor when we are done with fcntl or flock-based + cross-process lock. Otherwise, we leak descriptors. + [Justin Erenkrantz] + + *) Fix a possible data corruption problem with the use of getpwnam_r() on + all platforms where that function is used. + Use getpwnam_r() and getgrgid_r() instead of getpwnam() and getgrgid() + with threaded builds on glibc (2.1, at least) to avoid thread safety + issues. [Jeff Trawick] + + *) Added apr_lock_tryacquire. It will attempt to acquire the lock, but + will not block if it can not acquire the lock. Returns APR_EBUSY if + acquistion can not happen. [Justin Erenkrantz] + + *) Added an inherit flag to apr_socket_create and other socket creation + functions. This allows APR programs to specify that a socket should + be passed to any child processes that are created. The inherit flag + is only meaningful if programs use apr_process_create(). This + also adds a couple of macros that allow APR types to set and unset + the inherit flag. [Ryan Bloom] + + *) apr_connect()on Windows: Handle timeouts and returning the proper + status code when a connect is in progress. [Bill Stoddard] + + *) apr_connect() on Unix: Handle EINTR during connect(). Handle timeouts. + [Jeff Trawick] + + *) Handle the weird case where getpwnam() returns NULL but errno is zero. + [Jeff Trawick] + + *) Add apr_file_flags_get() which returns the flags that were originally + passed in to apr_file_open(). [Cliff Woolley] + + *) Added APR_HAS_XTHREAD_FILES macro that indicates whether or not the + platform handles files opened in APR_XTHREAD mode natively. Currently + only Win32 has such native support. [Cliff Woolley] + + *) Fix gmt offset handling on Solaris. Apache log messages now show + local time again. PR #7902 [Taketo Kabe ] + + *) apr_pstrcat() optimizations [Doug MacEachern, Jeff Trawick] + + *) Make the apr_pool_is_ancestor logic public. This is required for + some new logic that is going into HTTPD. I have left the join logic + in that function debug only. [Ryan Bloom] + + *) Clean up Win32 locks when the pool goes away. + [Justin Erenkrantz, Jeff Trawick] + + *) Implement apr_get_home_directory for Win32. [William Rowe] + + *) Complete the implementation of LARGEFILE support on Win32, although + the mmap semantics still need a touch of work. [William Rowe] + + *) Fix the APR_XTHREAD support, and apr_sendfile mechanics, so we can + handle cross-threaded file handles on Win32. [William Rowe] + + *) Implement APR_READWRITE locks on Unix with POSIX rwlocks. + Introduce new apr_lock_acquire_rw() function which takes in + APR_READER or APR_WRITER. [Justin Erenkrantz] + + *) Add apr_open_stdin. This mirrors apr_open_stderr, except it works + on stdin. [Aaron Bannert ] + + *) Add apr_strtok(), a thread-safe flavor of strtok() which has the + same interface as strtok_r(). [Jeff Trawick] + + *) Add other child support to Win32 [Bill Stoddard] + + *) Other-child registrations are automatically removed when the + associated pool is destroyed. This avoids garbage in the list + of registrations when a pool with a registration is freed. + [Jeff Trawick] + + *) Allow LTFLAGS to be overridden by the configure command-line + (default="--silent") and introduce LT_LDFLAGS. [Roy Fielding] + + *) Add memory code kindly donated to APR by + Elrond + Luke Kenneth Casson Leighton + Sander Striker + [David Reid] + + *) Fix a problem with the FreeBSD flavor of apr_sendfile() where we + could return APR_EAGAIN+bytes_sent. [Jeff Trawick] + + *) Fix a problem on unixware where clearing h_errno wouldn't work. + Use set_h_errno() instead. PR #7651 [Jeff Trawick] + + *) Add the test and build directories (when present) to the recursive + make process, being sure that they are run last. test is only done + recursively for make *clean targets. [Roy Fielding] + + *) Make the apr_mmap_create() function use the native_flags variable. + This allows us to actually create WRITEABLE MMAPs. + [Ed Korthof ] + + *) Completely revamp configure so that it preserves the standard make + variables CPPFLAGS, CFLAGS, CXXFLAGS, LDFLAGS and LIBS by moving + the configure additions to EXTRA_* variables. Also, allow the user + to specify NOTEST_* values for all of the above, which eliminates the + need for THREAD_CPPFLAGS, THREAD_CFLAGS, and OPTIM. Fix the setting + of INCLUDES and EXTRA_INCLUDES. Check flags as they are added to + avoid pointless duplications. Fix the order in which flags are given + on the compile and link lines. [Roy Fielding] + + *) Fix DSO code on HP/UX. We have to use == not =, and it makes more + sense to actually return errno, so that the return code means + something. [Ryan Bloom] + + *) Clean up conditionals in unix DSO code so that we decide based on + the dynamic loading implementation, which we noticed at configure + time, instead of by operating system. + [Wilfredo Sanchez] + + *) Add DSO support for dyld platforms (Darwin/Mac OS and OpenStep). + [Wilfredo Sanchez] + + *) Amend the time code to better deal with time zones. + [David Reid] + + *) Carefully select an appropriate native type for apr_int64_t and + define its format as APR_INT64_T_FMT and literal using APR_INT64_C(). + [Justin Erenkrantz, William Rowe] + + *) Make clean, distclean, and extraclean consistently according to the + Gnu makefile guidelines. [Justin Erenkrantz ] + + *) Initial implementation of of apr_filepath (get/set/parse_root and + merge) for Windows. [William Rowe] + + *) Cleaned up implementation of of apr_filepath (get/set/parse_root + and merge) for Unix. [Greg Stein, William Rowe] + + *) Fixup the --enable-libtool option. This allows the test directory + to compile again. The test directory still doesn't work when + APR is configured without libtool. [Ryan Bloom] + + *) If we don't have sigwait() in the system, see if sigsuspend() is + available, and use that instead. [Wilfredo Sanchez] + + *) Make libtool optional at configure time. This is done with + --disable-libtool. [Ryan Bloom] + + *) Recognize systems where the TCP_NODELAY setting is inherited from + the listening socket, and optimize apr_setsockopt(APR_TCP_NODELAY) + accordingly. [Jeff Trawick] + + *) Recognize the presence of getnameinfo() on Tru64. [David Reid] + + *) Allow APR to be installed. [Ryan Bloom] + + *) Generate config.nice for easy re-run of configure. [Roy Fielding] + + *) Define preprocessor flags in CPPFLAGS instead of CFLAGS and + bring some sanity to the compiler command-lines. [Roy Fielding] + + *) Use the dso/aix subdirectory for older versions of AIX and fix + a number of bugs in the dso code in that directory. + [Victor Orlikowski] + + *) Allow libtool 1.3b to be used. [Victor Orlikowski] + + *) Misc. Win32 fixes: Set the pool pointer in apr_sockaddr_t + structures created with the apr_socket_t to prevent segfault + in certain apps. Flush unwritten buffered data when the file + is closed. [Jeff Trawick] + + *) Win32: Get APR to compile with MSVC 5.0 (a.k.a. VC97). + PR #7489 [Jeff Trawick] + + *) First draft implementation of apr_filepath (get/set/parse_root + and merge) for Unix. [William Rowe] + + *) Add apr_ipsubnet_create() and apr_ipsubnet_test() for testing + whether or not an address is within a subnet. [Jeff Trawick] + + *) Add apr_sendto and apr_recvfrom for Unix. Start of adding UDP + support. [David Reid] + + *) Add a method to get the password from the system for a given + user. [John Barbee ] + + *) Change the include path order, so that we look for included files + in the APR paths first, and the system paths second. + [jean-frederic clere ] + + *) Add a with-sendfile option, so that people on platforms without a + sendfile implementation for APR can easily disable it from the + configure line. [Ryan Bloom] + + *) Change the check for netinet/tcp.h to work around an issue with + that header file on IRIX 6.5 which prevented it from being + detected. PR #6459 [Jeff Trawick] + + *) Introduce apr_get_userid to return a named user's apr_uid_t and + apr_gid_t across platforms [Cliff Woolley, William Rowe] + + *) In apr_shm_init(), check the retcode from mm_malloc(). Previously, + we segfaulted here if mm_malloc() failed to get a lock. An example + error scenario is when the lock file lives on a filesystem which + doesn't support locking. [Jeff Trawick] + + *) Name protected the autoconf macros defined by APR. Moved the + REENTRANCY_FLAGS settings into apr_hints.m4. Inlined the + APR_PREPARE_MM_DIR macro because it could only be used once. + Removed the unused macros MY_TRY_RUN, MY_TRY_RUN_NATIVE, and + AC_USE_FUNCTION. Added some macro comments. [Roy Fielding] + + *) Cope with BSDi installations where the default make has been + replaced with GNU make. [Joe Orton ] + + *) Changed apr/helpers to apr/build to be consistent with other Apache + source trees. Added make variables to rules.mk.in that point to the + builders directory and its scripts. Updated buildconf, configure.in, + and Makefile.in files to create and use the new scripts. Moved scandoc + to scandoc.pl and its default.pl template to scandoc_template.pl. + [Roy Fielding] + + *) Updated config.guess and config.sub to GNU libtool 1.3.5 features, + with the Apache additions for OS/390 and OS/2 emx. [Roy Fielding] + + *) Moved hints.m4, apr_common.m4, and helpers/apr-conf.m4 into the + new build directory as apr_hints.m4, apr_common.m4, apr_network.m4, + and apr_threads.m4. [Roy Fielding] + + *) Get apr_sendfile() working on HP-UX. This gets APR to build on + HP-UX without having to turn off APR_HAS_SENDFILE. [Jeff Trawick] + + *) Force FreeBSD to compile without threads by default. To enable + threads, use --enable-threads on the configure line. + [Ryan Bloom] + + *) Purge system password buffer before returning from apr_password_get. + No longer abuses bufsize argument on return. [William Rowe] + + *) Moved the prototypes for apr_snprintf and apr_vsnprintf to the + apr_strings.h header, from apr_lib.h. This location makes more + sense. [Ryan Bloom] + + *) Added the APR_TRY_COMPILE_NO_WARNING configure macro for testing a + compile with -Werror as well as the APR_CHECK_ICONV_INBUF macro to + test for annoying iconv prototype differences. + [Jeff Trawick, Roy Fielding] + + *) Fix a problem with configure on NetBSD. We must include sys/types.h + for some platforms. [jun-ichiro hagino ] + + *) Some fixes in the Win32 time support. + (IsLeapYear): New macro for quickly figgerin' out if a given year is a + leap year. (SystemTimeToAprExpTime): Perform the calculation of + tm_yday. Also, negate the sign of the tm_gmtoff field to be + consistent with Unix platforms and APR header file comments. + [Mike Pilato] + + *) Implement WinNT Unix'ish permissions. [William Rowe] + + *) Corrected an OS2'ism of apr_get_home_directory. OS2 now returns the + proper directory, including the user's name. + + *) Removed private os2errno.h and integrated the OS2 network error codes + into apr_errno.h for optimized error tests (APR_STATUS_IS_EFOO(rv)). + [William Rowe] + + *) Moved inclusion of header from multiple modules into apr.h + [William Rowe] + + *) Added apr_compare_users() and apr_compare_groups() for more complex + apr_uid_t and apr_gid_t structures. Enabled both .user and .group + results from WinNT/2000 stat/getfileinfo, but expect to find that + .group is 'None' in most cases. [William Rowe] + + *) Replace configure --with-optim option by using the environment + variable OPTIM instead. This is needed because configure options + do not support multiple flags separated by spaces. [Roy Fielding] + + *) Eliminate the APR_SIG* aliases for standard signal names, + since they serve no useful purpose. [Roy Fielding] + + *) Abstracted apr_get_username and apr_get_groupname for unix and win32. + Modified Win32 apr_uid_t and apr_gid_t to use PSIDs, and elimintated + the uid_t and gid_t definitions. [William Rowe] + + *) Radically refactored apr_stat/lstat/getfileinfo/dir_read for Win32 + to assure we are retrieving what we expect to retrieve, and reporting + the correct result (APR_SUCCESS or APR_INCOMPLETE). The potential + for a bit more optimization still remains. [William Rowe] + + *) While we have the future opportunity to cache the apr_stat'ed file + handle for a very fast open (dup handle) on Win32, patched to close + that file after a stat always. Needs a new semantic before we leave + handles dangling when the user intends to rm. [William Rowe] + + *) Correct Win32 apr_stat/lstat/getfileinfo/dir_read to all zero out + the finfo buffer on success (or incomplete success). [William Rowe] + + *) Fix Win32/Unix apr_lstat to throw the .valid bit APR_FINFO_LINK to + indicate we attempted to open the link. Only the .filetype APR_LNK + reflects if the file found was, in fact, a link. [William Rowe] + + *) Fixed apr_open and apr_rename to function on Win9x. + [Mike Pilato ] + + *) Add apr_open_stdout. This mirrors apr_open_stderr, except it works + on stdout. [Mike Pilato ] + + *) Fix bug in file_io/unix/dir.c. There is no such thing as a dirent, + it must be a struct dirent. + [Kevin Pilch-Bisson ] + + *) Fix the configure script so that we can build from a different + directory. [Kevin Pilch-Bisson ] + + *) Introduce the wanted flag argument to the apr_stat/lstat/getfileinfo + family of functions. This change allows the user to determine what + platform-specific file information is retrieved, to optimize both + portability and performance. [William Rowe] + + *) Fix make depend. [Ryan Bloom] + + *) All dso implementations now register a cleanup to unload the DSO + when it is loaded. If the pool is removed, we really do need to + remove the DSO. In the past, different platforms behaved differently + it this respect. [Ryan Bloom] + + *) Add linkage declarations to the DSO code. + [Gregory Nicholls ] + + *) Some adjustment of hints.m4 setting flags (used to check if null + first) and added some verbosity. [Jim Jagielski] + + *) Specify APR_DECLARE to some of the APR functions. This helps linking + on some operating systems. [Gregory Nicholls ] + + *) Libtool'ized APR and converted all the makefiles to share rules + from helpers/rules.mk. [Greg Stein] + + *) Remove a warning on FreeBSD. FreeBSD defines TCP_NO_PUSH, but we + don't actually use it. This causes os_cork to be defined but not + used. This patch keeps us from defining os_cork and os_uncork on + FreeBSD. [Ryan Bloom] + + *) Keep apr_terminate from seg faulting on terminate. This is + happening on systems that do not NULL out locks when they are + destroyed. To keep this from happening, we set the locks to + NULL after destroying them in apr_terminate, and we have to + check for NULL in free_blocks. + [Allan Edwards and Gregory Nicholls ] + + *) Remove the ability to allocate memory out of a NULL pool. + [Ryan Bloom] + + *) Add an APR_GET_POOL macro to get a pool from any APR type that has + a pool. This requires that ALL apr types put the pool as the first + field in their structure. [Ryan Bloom] + + *) Begin to remove the ability to allocate out of NULL pools. The first + problem to solve, is that we need an apr_lock in order to allocate + pools, so that we can lock things out when allocating. So, how do we + allocate locks without a pool to allocate from? The answer is to create + a global_apr_pool, which is a bootstrapping pool. There should NEVER + be a sub-pool off this pool, and it is static to an APR file. This is + only used to allow us to allocate the locks cleanly, without using the + NULL pool hack. [Ryan Bloom] + + *) Fix a logic error in the poll code when implemented using select. + [Nick Caruso ] + + *) FreeBSD does not support sendfile() in combination with threads + before version 4.2. We no longer even try to support it. + [Ryan Bloom] + + *) On FreeBSD, it is possible for the first call to sendfile to + get EAGAIN, but still send some data. This means that we cannot + call sendfile and then check for EAGAIN, and then wait and call + sendfile again. If we do that, then we are likely to send the + first chunk of data twice, once in the first call and once in the + second. If we are using a timed write, then we check to make sure + we can send data before trying to send it. [Ryan Bloom] + + *) Cleanup to help Apache support programs build cleanly. + [Cliff Woolley ] + + *) Cleanup some compiler warnings on Solaris + [Dale Ghent ] + + *) apr_getaddrinfo() can now return multiple addresses for a host + via the next field in apr_sockaddr_t. [Jeff Trawick] + + *) Tighten up the check for getaddrinfo(). If it can't figure out + the appropriate address family for 127.0.0.1, it fails. + Unfortunately, Tru64 fails this test so we won't do IPv6 on + Tru64. [Jeff Trawick] + + *) Rename apr_opendir to apr_dir_open. [Ryan Bloom] + + *) apr_snprintf()'s %pI format string now takes apr_sockaddr_t * + instead of sockaddr_in *. [Jeff Trawick] + + *) Fix a bug in apr_accept() for Win32 and Unix where the local + apr_sockaddr_t in the new connected socket was not initialized + properly. This could result in a bad string for apr_get_ipaddr(), + among other things. [Jeff Trawick] + + *) Add apr_getnameinfo(), a replacement for apr_get_hostname() which + supports IPv6 and will be friendlier for use with eventual + SOCK_DGRAM support. apr_get_hostname() is gone. [Jeff Trawick] + + +Changes with APR a9 + + *) Removed the iconv implementation from the i18n/unix/iconv branch. + This now resides in the apr-iconv repository, and will be ported + over time to use native apr types (e.g. apr_dso) for portability. + + *) Only support IPv6 if we have sockaddr_in and a working + getaddrinfo(). [Jeff Trawick] + + *) Add apr_parse_addr_port() for parsing the hostname:port portion + of URLs and similar strings. [Jeff Trawick] + + *) Add Win32 MMAP support [William Rowe] + + *) Allow the APR programmer to specify if the MMAP is read-only or + write-able. + [Ryan Bloom and Will Rowe] + + *) Check more carefully for getaddrinfo(). Accept those that + require to be included (e.g., Tru64). Reject those that + fail a very basic operational test (e.g., AIX). [Jeff Trawick] + + *) Add apr_make_os_sock() for constructing a fully-capable APR + socket. [Jeff Trawick] + + *) Make APR's shared memory routines always allocate enough memory + for the requested segment, the MM internal types, and the APR + internal types. + [Ryan Bloom] + + *) Add APR_SIZE_T_FMT. Get the other APR_xx_T_FMT variables + defined properly on AIX. [Jeff Trawick] + + *) network API changes: get rid of apr_get_socket_inaddr(), + apr_get_remote_name(), and apr_get_local_name() [Jeff Trawick] + + *) Add a step at configure time to create a file at the top-level, + apr.exports, which lists every function exported by APR. The + file is generated by a script in helpers, that reads each header + file. + [Ryan Bloom] + + *) Lock config changes: Detect SysV sem capability by the presence of + sempaphore functions, not by the presence of union semun. New + config variable apr_lock_method can override autodetection of the + apr_lock implementation method. For now, hints.m4 uses it to select + SysV semaphores for OS/390. New config variable + apr_process_lock_is_global specifies that the selected inter-process + lock method is sufficient for APR_LOCKALL (i.e., it blocks all + threads and processes). For now, hints.m4 turns on this flag for + OS/390. [Jeff Trawick] + + *) Get APR_OFF_T_FMT defined properly on Solaris Sparc. + [Jeff Trawick] + + +Changes with APR a8 + + *) Change the name of the sa_len field in apr_sockaddr_t to salen. + Some platforms have a macro named sa_len. + [Tony Finch] + + *) apr_set_port(), apr_get_port(), apr_set_ipaddr(), and apr_get_ipaddr() + now take apr_sockaddr_t as a parameter instead of apr_socket_t + + apr_interface_e. This will allow the same routines to be used with + datagram APIs to be added later. Note that code which calls + apr_set_ipaddr() should probably be changed to call apr_getaddrinfo() + for protocol independence. [Jeff Trawick] + + *) apr_create_tcp_socket() has been removed. Use apr_create_socket() + instead. [Jeff Trawick] + + *) Source was moved from the apache-2.0 repository. For all CHANGES + prior to this time, please see the apache-2.0 repository diff --git a/srclib/apr/LICENSE b/srclib/apr/LICENSE new file mode 100644 index 0000000000..6f0142f292 --- /dev/null +++ b/srclib/apr/LICENSE @@ -0,0 +1,297 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + +APACHE PORTABLE RUNTIME SUBCOMPONENTS: + +The Apache Portable Runtime includes a number of subcomponents with +separate copyright notices and license terms. Your use of the source +code for the these subcomponents is subject to the terms and +conditions of the following licenses. + +From strings/apr_fnmatch.c, include/apr_fnmatch.h, misc/unix/getopt.c, +file_io/unix/mktemp.c, strings/apr_strings.c: + +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + +From network_io/unix/inet_ntop.c, network_io/unix/inet_pton.c: + +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + +From dso/aix/dso.c: + + * Based on libdl (dlfcn.c/dlfcn.h) which is + * Copyright (c) 1992,1993,1995,1996,1997,1988 + * Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany. + * + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + +From strings/apr_strnatcmp.c, include/apr_strings.h: + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + diff --git a/srclib/apr/Makefile.in b/srclib/apr/Makefile.in new file mode 100644 index 0000000000..fe6ad501c9 --- /dev/null +++ b/srclib/apr/Makefile.in @@ -0,0 +1,124 @@ + +srcdir=@srcdir@ +VPATH=@srcdir@ +top_srcdir=@apr_srcdir@ +top_blddir=@apr_builddir@ + +# +# APR (Apache Portable Runtime) library Makefile. +# +CPP = @CPP@ + +# get substituted into some targets +APR_MAJOR_VERSION=@APR_MAJOR_VERSION@ + +# +# Macros for supporting directories +# +INCDIR=./include +OSDIR=$(top_srcdir)/include/arch/@OSDIR@ +DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@ +INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) -I$(top_srcdir)/include + +# +# Macros for target determination +# +CLEAN_SUBDIRS= test +INSTALL_SUBDIRS=@INSTALL_SUBDIRS@ + +TARGET_LIB = lib@APR_LIBNAME@.la +APR_PCFILE = apr-$(APR_MAJOR_VERSION).pc +APR_CONFIG = apr-$(APR_MAJOR_VERSION)-config +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ + +# +# Rules for building specific targets, starting with 'all' for +# building the entire package. +# +TARGETS = $(TARGET_LIB) export_vars.c apr.exp + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ +@INCLUDE_OUTPUTS@ + +CLEAN_TARGETS = apr-config.out apr.exp exports.c export_vars.c .make.dirs \ + build/apr_rules.out +DISTCLEAN_TARGETS = config.cache config.log config.status \ + include/apr.h include/arch/unix/apr_private.h \ + libtool $(APR_CONFIG) build/apr_rules.mk apr.pc \ + build/pkg/pkginfo +EXTRACLEAN_TARGETS = configure aclocal.m4 include/arch/unix/apr_private.h.in \ + build-outputs.mk build/ltcf-c.sh build/ltmain.sh build/libtool.m4 + +prefix=@prefix@ +exec_prefix=@exec_prefix@ +bindir=@bindir@ +libdir=@libdir@ +includedir=@includedir@ +installbuilddir=@installbuilddir@ + +# Create apr-config script suitable for the install tree +apr-config.out: $(APR_CONFIG) + sed 's,^\(location=\).*$$,\1installed,' < $(APR_CONFIG) > $@ + +# Create apr_rules.mk suitable for the install tree +build/apr_rules.out: build/apr_rules.mk + sed 's,^\(apr_build.*=\).*$$,\1$(installbuilddir),' < build/apr_rules.mk > $@ + +install: $(TARGET_LIB) apr-config.out build/apr_rules.out + $(APR_MKDIR) $(DESTDIR)$(libdir) $(DESTDIR)$(bindir) $(DESTDIR)$(installbuilddir) \ + $(DESTDIR)$(libdir)/pkgconfig $(DESTDIR)$(includedir) + $(INSTALL_DATA) $(top_blddir)/include/apr.h $(DESTDIR)$(includedir) + for f in $(top_srcdir)/include/apr_*.h; do \ + $(INSTALL_DATA) $${f} $(DESTDIR)$(includedir); \ + done + $(LIBTOOL) --mode=install $(INSTALL) -m 755 $(TARGET_LIB) $(DESTDIR)$(libdir) + $(INSTALL_DATA) apr.exp $(DESTDIR)$(libdir)/apr.exp + $(INSTALL_DATA) apr.pc $(DESTDIR)$(libdir)/pkgconfig/$(APR_PCFILE) + for f in libtool shlibtool; do \ + if test -f $${f}; then $(INSTALL) -m 755 $${f} $(DESTDIR)$(installbuilddir); fi; \ + done + $(INSTALL) -m 755 $(top_srcdir)/build/mkdir.sh $(DESTDIR)$(installbuilddir) + for f in make_exports.awk make_var_export.awk; do \ + $(INSTALL_DATA) $(top_srcdir)/build/$${f} $(DESTDIR)$(installbuilddir); \ + done + $(INSTALL_DATA) build/apr_rules.out $(DESTDIR)$(installbuilddir)/apr_rules.mk + $(INSTALL) -m 755 apr-config.out $(DESTDIR)$(bindir)/$(APR_CONFIG) + @if [ $(INSTALL_SUBDIRS) != "none" ]; then \ + for i in $(INSTALL_SUBDIRS); do \ + ( cd $$i ; $(MAKE) DESTDIR=$(DESTDIR) install ); \ + done \ + fi + +$(TARGET_LIB): $(OBJECTS) + $(LINK) @lib_target@ $(ALL_LIBS) + +exports.c: $(HEADERS) + $(APR_MKEXPORT) $(HEADERS) > $@ + +export_vars.c: $(HEADERS) + $(APR_MKVAREXPORT) $(HEADERS) > $@ + +apr.exp: exports.c export_vars.c + @echo "#! lib@APR_LIBNAME@.so" > $@ + @echo "* This file was AUTOGENERATED at build time." >> $@ + @echo "* Please do not edit by hand." >> $@ + $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) exports.c | grep "ap_hack_" | sed -e 's/^.*[)]\(.*\);$$/\1/' >> $@ + $(CPP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) export_vars.c | sed -e 's/^\#[^!]*//' | sed -e '/^$$/d' >> $@ + +dox: + doxygen $(top_srcdir)/docs/doxygen.conf + +gcov: + @build/run-gcov.sh + +test: check +check: $(TARGET_LIB) + (cd test && $(MAKE) check) + +etags: + etags `find . -name '*.[ch]'` + +# DO NOT REMOVE +docs: $(INCDIR)/*.h diff --git a/srclib/apr/NOTICE b/srclib/apr/NOTICE new file mode 100644 index 0000000000..129db55ae5 --- /dev/null +++ b/srclib/apr/NOTICE @@ -0,0 +1,9 @@ +This product includes software developed by +The Apache Software Foundation (http://www.apache.org/). + +Portions of this software were developed at the National Center +for Supercomputing Applications (NCSA) at the University of +Illinois at Urbana-Champaign. + +This software contains code derived from the RSA Data Security +Inc. MD5 Message-Digest Algorithm. diff --git a/srclib/apr/NWGNUmakefile b/srclib/apr/NWGNUmakefile new file mode 100644 index 0000000000..8bc6e2fdd3 --- /dev/null +++ b/srclib/apr/NWGNUmakefile @@ -0,0 +1,405 @@ +# +# Declare the sub-directories to be built here +# + +SUBDIRS = \ + build \ + $(APU_WORK) \ + $(EOLIST) + +# +# Get the 'head' of the build environment. This includes default targets and +# paths to tools +# + +include $(APR_WORK)\build\NWGNUhead.inc + +# +# build this level's files + +# +# Make sure all needed macro's are defined +# + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(APR)/include/arch/unix \ + $(APR)/memory/unix \ + $(APR)/random/unix \ + $(APRUTIL)/xml \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = aprlib + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = Apache Portability Runtime Library $(VERSION_STR) + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/aprlib.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(OBJDIR)/aprlib.lib \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/libprews.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(APRLIB) \ + $(APRUTLIB) \ + $(APULDAPLIB) \ + $(XMLLIB) \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + Libc \ + $(EOLIST) + +# Include the Winsock libraries if Winsock is being used +ifndef USE_STDSOCKETS +FILES_nlm_modules += ws2_32 \ + $(EOLIST) +endif + +#If the LDAP support is defined then add the auto-load modules +ifneq "$(LDAPSDK)" "" +FILES_nlm_modules += \ + lldapsdk \ + lldapssl \ + lldapx \ + $(EOLIST) +endif + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override $(NWOS)\copyright.txt. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @libc.imp \ + @netware.imp \ + $(EOLIST) + +# Include the Winsock imports if Winsock is being used +ifndef USE_STDSOCKETS +FILES_nlm_Ximports += \ + @ws2nlm.imp \ + WSAStartupRTags \ + WSACleanupRTag \ + $(EOLIST) +endif + +#If the LDAP support is defined then add the imports +ifneq "$(LDAPSDK)" "" +FILES_nlm_Ximports += \ + @$(LDAPSDK)/imports/lldapsdk.imp \ + @$(LDAPSDK)/imports/lldapssl.imp \ + $(EOLIST) +endif + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + @aprlib.imp \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(OBJDIR)/apr_atomic.o \ + $(OBJDIR)/apr_cpystrn.o \ + $(OBJDIR)/apr_fnmatch.o \ + $(OBJDIR)/apr_getpass.o \ + $(OBJDIR)/apr_hash.o \ + $(OBJDIR)/apr_pools.o \ + $(OBJDIR)/apr_random.o \ + $(OBJDIR)/apr_snprintf.o \ + $(OBJDIR)/apr_strings.o \ + $(OBJDIR)/apr_strnatcmp.o \ + $(OBJDIR)/apr_strtok.o \ + $(OBJDIR)/apr_tables.o \ + $(OBJDIR)/charset.o \ + $(OBJDIR)/copy.o \ + $(OBJDIR)/common.o \ + $(OBJDIR)/dir.o \ + $(OBJDIR)/dso.o \ + $(OBJDIR)/errorcodes.o \ + $(OBJDIR)/env.o \ + $(OBJDIR)/fileacc.o \ + $(OBJDIR)/filedup.o \ + $(OBJDIR)/filepath.o \ + $(OBJDIR)/filepath_util.o \ + $(OBJDIR)/filestat.o \ + $(OBJDIR)/filesys.o \ + $(OBJDIR)/flock.o \ + $(OBJDIR)/fullrw.o \ + $(OBJDIR)/getopt.o \ + $(OBJDIR)/groupinfo.o \ + $(OBJDIR)/inet_pton.o \ + $(OBJDIR)/inet_ntop.o \ + $(OBJDIR)/libprews.o \ + $(OBJDIR)/mktemp.o \ + $(OBJDIR)/mmap.o \ + $(OBJDIR)/multicast.o \ + $(OBJDIR)/open.o \ + $(OBJDIR)/pipe.o \ + $(OBJDIR)/otherchild.o \ + $(OBJDIR)/proc.o \ + $(OBJDIR)/procsup.o \ + $(OBJDIR)/proc_mutex.o \ + $(OBJDIR)/rand.o \ + $(OBJDIR)/readwrite.o \ + $(OBJDIR)/seek.o \ + $(OBJDIR)/select.o \ + $(OBJDIR)/sendrecv.o \ + $(OBJDIR)/sha2.o \ + $(OBJDIR)/sha2_glue.o \ + $(OBJDIR)/shm.o \ + $(OBJDIR)/signals.o \ + $(OBJDIR)/sockaddr.o \ + $(OBJDIR)/sockets.o \ + $(OBJDIR)/sockopt.o \ + $(OBJDIR)/start.o \ + $(OBJDIR)/tempdir.o \ + $(OBJDIR)/thread.o \ + $(OBJDIR)/thread_cond.o \ + $(OBJDIR)/thread_mutex.o \ + $(OBJDIR)/thread_rwlock.o \ + $(OBJDIR)/threadpriv.o \ + $(OBJDIR)/time.o \ + $(OBJDIR)/timestr.o \ + $(OBJDIR)/userinfo.o \ + $(OBJDIR)/version.o \ + $(OBJDIR)/waitio.o \ + $(EOLIST) + + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms $(INSTDIRS) FORCE + copy $(OBJDIR)\aprlib.nlm $(INSTALLBASE)\*.* +ifndef DEST + -copy $(subst /,\,$(APR))\STATUS $(INSTALLBASE)\*.apr + -copy $(subst /,\,$(APR))\LICENSE $(INSTALLBASE)\* + -copy $(subst /,\,$(APR))\CHANGES $(INSTALLBASE)\*.apr + -copy $(subst /,\,$(APRUTIL))\STATUS $(INSTALLBASE)\*.apu + -copy $(subst /,\,$(APRUTIL))\CHANGES $(INSTALLBASE)\*.apu + @echo rem copying the docs directories > xc.bat + @echo xcopy docs $(INSTALLBASE)\docs\*.* $(XCOPYSW) >> xc.bat + $(CMD) xc.bat + $(DEL) xc.bat +endif + +$(INSTDIRS) :: + $(CHKNOT) $@\NUL mkdir $@ + +ifndef DEST +installdev :: $(INSTDEVDIRS) FORCE + -copy $(subst /,\,$(APR))\include\*.h $(INSTALLBASE)\include\*.* + -copy $(subst /,\,$(APRUTIL))\include\*.h $(INSTALLBASE)\include\*.* + -copy $(subst /,\,$(APR))\*.imp $(INSTALLBASE)\lib\*.* + -copy $(subst /,\,$(APR))\misc\netware\*.xdc $(INSTALLBASE)\lib\*.* + +$(INSTDEVDIRS) :: + $(CHKNOT) $@\NUL mkdir $@ +endif + +# +# Any specialized rules here +# + +vpath %.c atomic/netware:strings:tables:passwd:lib:time/unix +vpath %.c file_io/unix:locks/netware:misc/netware:misc/unix:threadproc/netware +vpath %.c poll/unix:shmem\unix:support/unix:random/unix +vpath %.c dso/netware:memory/unix:mmap/unix:user/netware + +# Use the win32 network_io if Winsock is being used +ifdef USE_STDSOCKETS +vpath %.c network_io/unix +else +vpath %.c network_io/win32:network_io/unix +endif + +$(OBJDIR)/%.o: file_io/netware/%.c $(OBJDIR)\$(NLM_NAME)_cc.opt + @echo Compiling $< + $(CC) file_io\netware\$( for thread + discussing this. + +1: BrianH, Aaron, david, jerenkrantz + Status: Will Rowe was working on this. + + * Need some architecture/OS specific versions of the atomic operations. + progress: generic, solaris Sparc, FreeBSD5, linux, and OS/390 done + need: AIX, AS400, HPUX + + * The new lock API is a full replacement for the old API, but is + not yet complete on all platforms. Components that are incomplete + or missing include: + Netware: apr_proc_mutex_*() (Is proc_mutex unnecessary on Netware?) + * proc_mutex is not necessary on NetWare since the OS does + not support processes. The proc_mutex APIs actually + redirect to the thread_mutex APIs. (bnicholes) + OS/2: apr_thread_cond_*(), apr_proc_mutex_*() + + Less critical components that we may wish to add at some point: + Beos: apr_thread_rwlock_try*lock() + apr_proc_mutex_trylock() + Unix: apr_thread_rwlock_*() for platforms w/o rwlocks in pthread + Win32: apr_thread_cond_timedwait(), apr_proc_mutex_*() + (Is proc_mutex unnecessary on Win32?) + + * Need to contemplate apr_strftime... platforms vary. OtherBill + suggested this solution (but has no time to implement): + Document our list of 'supported' escapes. + Run some autoconf/m4 magic against the complete list we support. + Move the strftime re-implementation from time/win32 to time/unix. + Add some APR_HAVE_STRFTIME magic to use the system fn, or fail + over to time/unix/strftime.c. + Message-ID: <025e01c1a891$bf41f660$94c0b0d0@v505> + + * Using reentrant libraries with non-threaded APR + - Anecdotal evidence exists that suggests it is bad to + mix reentrant and non-reentrant libraries and therefore + we should always use the reentrant versions. + - Unfortunately, on some platforms (AIX 4.2.1) defining + the reentrant flag (-D_THREAD_SAFE) causes builds to fail, + and so one would expect --disable-threads to fix this. + Although this has been fixed for that particular version + of AIX, it may be useful to only enable the reentrant + versions when threads are enabled. + How will we deal with this issue once APR becomes a standalone + library? It is perfectly legitimate to have apps needing + both versions (threaded/reentrant and non-threaded/non-reentrant) + on the same machine. + + * Pools debugging + - Find a way to do check if a pool is used in multiple + threads, while the creation flags say it isn't. IOW, + when the pool was created with APR_POOL_FNEWALLOCATOR, + but without APR_POOL_FLOCK. + Currently, no matter what the creation flags say, we always + create a lock. Without it integrity_check() and + apr_pool_num_bytes() blow up (because they traverse pools + child lists that possibly belong to another thread, in + combination with the pool having no lock). However, + this might actually hide problems like creating a child pool + of a pool belonging to another thread. + Maybe a debug function apr_pool_set_owner(apr_thread_t *) in + combination with extra checks in integrity_check() will point + out these problems. apr_pool_set_owner() would need to be called + everytime the owner(the thread the pool is being used in) of + the pool changes. + + - Implement apr_pool_join and apr_pool_lock. Those functions + are noops at the moment. + + - Add stats to the pools code. We already have basic stats + in debug mode. Stats that tell us about wasted memory + in the production code require more thought. + Status: Sander Striker is looking into this (low priority) + + David says this is a 1.1 issue. + + * Get OTHER_CHILD support into Win32 + Status: Bill S. is looking into this + + * Win32 apr_proc_create fails to create 16 bit apps detached + (a win32 bug.) The question - test in advance (slow) or + recover gracefully from failure and try again? Only the test + method will work on Win9x, since it will appear to work, only + to encounter mangled pipes. Win2K (NT?) simply fails. + + * SysV semaphore support isn't usable by Apache when started as + root because we don't have a way to allow the semaphore to be + used by the configured User and Group. Current work-around: + change the initial permissions to 0666. Needed code: See + 1.3's http_main.c, SysV sem flavor of accept_mutex_init(). + Status: Jim will look into this + Update: Apache deals with this itself, though it might be nice + if APR could do something. + + * Build scripts do not recognise AIX 4.2.1 pthreads + Justin says: "Is this still true?" + + * FirstBill says we need a new procattr, APR_CREATE_SUSPENDED (or + something similar) to direct ap_create_process to create the + process suspended. We also need a call to wake up the suspended + process. This may not be able to be implemented everywhere though. + Status: OtherBill asks, why? What is the benefit, how is it + portably implemented? Unless this creates some tangible that + mirrors another platform, then I'm -1. + + * Replace tables with a proper opaque ADT that has pluggable + implementations (including something like the existing data type, + plus hash tables for speed, with options for more later). + Status: fanf is working on this. + + * add a version number to apr_initialize() as an extra failsafe against + (APR) library version skew. + MsgID: + Status: Greg -1, Jeff +1, Ryan +1, Tony -0(?), david +1 + + * add apr_crypt() and APR_HAS_CRYPT for apps to determine whether the + crypt() function is available, and a way to call it (whether it is + located in libc, libcrypt, or libufc) + Justin says: Should apr_crypt() be in apr-util? + + Status: Greg +1 (volunteers) + + * configure.in does post-processing on the AC_OUTPUT files (for + VPATH support). This means that config.status doesn't do the + right thing when you re-run it. We ought to revamp the makefiles + to do the right AC_SUBST stuff rather than depend upon rewriting. + + Sascha: As the rewriter is a crude hack, I would not worry too + much about it. It is designed to go away once we have + a proper build system in place. + + One of the perceived deficiencies of automake is that it + uses AC_SUBST too often, thereby slowing down the task of + generating Makefiles significantly, because it applies + dozens of substitutions to each Makefile. And why? Make's + built-in macro processing is much more powerful, and + combined with the include facility, generating Makefiles + becomes simpler and faster. + Justin says: "I think this got fixed with Roy's build changes." + + * use os_(un)cork in network_io/unix/sendrecv.c for FreeBSD's + sendfile implementation. + + david: The socket options stuff is now in and using it should + reduce the number of syscalls that are required for + os_cork and uncork, so the code should be reviewed to + make use of the new calls. If no-one beats me to it I'll + get around to it soonish... + + * toss the per-Makefile setup of INCLUDES; shift to rules.mk.in + rbb: This is a bad thing IMHO. If we do this, then we + can't use these makefiles for anything else. For example, + apr-util + + * add the rest of the pool accessor declare/impl macros. + Justin says: Both thread and file have the accessors now. Any others? + Status: Greg volunteers + + * I think apr_open_stderr() and friends *should* dup() the + descriptor. That would allow the new/returned file to be closed + (via pool cleanup or manually) without accidentally closing + stderr/out. + + * need to export (in code, not just build scripts) the shared + library extension (e.g. ".so") for the platform. clients need to + use this to construct filenames to pass to apr_dso_load() + -- note on Win32 we distinguish 'apache module' names from other + 'loadable module' names, so be careful with Apache's directive. + + * Possible gmtime_r replacement in explode_time + On Solaris (and possibly others), the gmtime_r libc function obtains + a mutex. We have seen 21/25 threads being blocked in this mutex on + a threaded httpd MPM when requesting static pages. It may be worth + it to hand optimize this since there is no real need for a mutex at + the system level (straight arithmetic from what I can tell). If you + have access to the Solaris source code: + osnet_volume/usr/src/lib/libc/port/gen/time_comm.c. + + * Add a way to query APR for what features it has at runtime (i.e. + threads). + Justin says: I'm not completely sold on this, but it has been mentioned + before and at least added to STATUS. + + * apr_xlate.h generates a bunch of compiler warnings. + Jeff asks: which platform? + Justin says: Solaris with Forte 6.1. + + * fcntl() oddness on Solaris. Under high loads, fcntl() decides to + return error code 46 (ENOLCK). + + httpd (prefork MPM) error log says (predictably): + + (46)No record locks available: couldn't grab the accept mutex + + All of the children report this and subsequently exits. httpd is now + hosed. AFAICT, this does not look to be an out-of-fds error. + + Solaris's man page says: + ENOLCK + The cmd argument is F_SETLK, F_SETLK64, F_SETLKW, or + F_SETLKW64 and satisfying the lock or unlock request + would result in the number of locked regions in the + system exceeding a system-imposed limit. + + Justin says: What is this system-imposed limit and how do we change it? + This gives me more rationale for switching the default + interprocess lock mechanism to pthread (if available). + + Explanation (from Kristofer Spinka ): + ============ + The system imposed default limit of outstanding lock requests is + 512. + You can verify this by, in a contemporary version of Solaris: + + # mdb -k + > tune_t_flckrec/D + tune_t_flckrec: + tune_t_flckrec: 512 + + This can be increased by adding the following to /etc/system: + + set tune_t_flckrec=1024 + + and rebooting. + + Of course "1024" can be any reasonable limit, although we do not know + what "reasonable" should be, so be conservative, only increase this as + necessary. + + * Generate a good bug report to send to the FreeBSD hackers that details + the problems we have seen with threads and system calls (specifically + sendfile data is corrupted). From our analysis so far, we don't think + that this is an APR issue, but rather a FreeBSD kernel issue. Our + current solution is to just disable threads across the board on + FreeBSD. + + MsgID: <20010828091959.D17570@ebuilt.com> + Status: Fixed in -CURRENT. MFC in about a week. Continuing + testing with threads on FreeBSD. + + FreeBSD PR kern/32684: + http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/32684 + + * There are some optimizations that can be done to the new + apr_proc_*() functions (on UNIX). One that may reduce pointer + indirection would be to make the apr_proc_mutex_unix_lock_methods_t + first-class members of the apr_proc_mutex_t structure. + + * Condition variables are tricky enough to use, and even trickier + to implement properly. We could really use a better test case + for those subtle quirks that sometimes creep into CV implementations. + + * Once we are fully satisfied with the new lock API, we can + begin to migrate the old API to be implemented on top of the + new one, or just decide to get rid of it altogether. + + * FreeBSD returns 45 (EOPNOTSUPP) when the lockfile is on a NFS + partition when you call fcntl(F_SETLKW). It may be good if we + can somehow detect this and error out when creating the lock + rather than waiting for the error to occur when acquiring lock. + + * Fix autoconf tests for strerror_r on BeOS and remove the hack in + misc/unix/errorcodes.c to get error reporting working. Committed as + the solution is elusive at present. + + * implement APR_PROGRAM_ENV and APR_PROGRAM_PATH on BeOS, OS/2, + Netware, and Win32. + + * stat() on a few platforms (notably Solaris and AIX) succeeds for + a non-directory even if a trailing '/' was specified in the + name. APR should perhaps simulate the normal -1/ENOTDIR + behavior in APR routines which retrieve information about the + file. Note: Win2K fails GetFileAttributesEx in this scenario. + See OtherBill's comments in this message to dev@httpd.apache.org: + Message-Id: <5.1.0.14.2.20020315080852.00bce168@localhost> + +Documentation that needs writing: + + * API documentation + Ian Says: APR Stuff in now in Doxygen format, which is the first step. + David says: are we planning on doing any more? I'm tempted to remove this + item. + + * apr-site needs to be revamped with Anakia/XHTML. + + * Identify and implement those protection bits that have general + usefulness, perhaps hidden, generic read-only [immutable], + effective current user permissions, etc. + + * Maybe make the following functions return void instead of + apr_status_t, as they cannot ever error: + + apr_md5_init() + apr_md5_update() + apr_md5_final() + apr_md5_encode() + apr_md5() /* plus make the obvious code tweak in this one */ + + (Volunteer: Karl Fogel .) + + However, don't do this until after apr and apr-util offer + library version numbers, and httpd uses those numbers to + indicate which version it needs. Until the libraries are + versioned, this api change is [somewhat] painful for httpd. + Status: Still in discussion, current leanings appear to be + Bill Stoddard -0.5 (?) + Sander Striker +1 + Greg Stein +1 + Karl Fogel +1 + + david: This was rejected for 1.0 following Ben L's comment that + should we ever start using any other form of md5 (e.g. + openssl) then errors would become a distinct possibility. + +API Changes Postponed for APR 2.0: + + * apr_socket_sendfile(): the offset parameter should not be + pass-by-reference, or it should be updated to do something + useful. + + * apr_password_get(): the bufsize parameter should not be + pass-by-reference. + + * apr_allocator.h: apr_memnode_t's use of uint32_t's doesn't match + well with allocation sizes being apr_size_t, possibly this can + be improved by using apr_size_t throughout. + + * apr_hash_count() should take a const apr_hash_t * argument. + +Stuff for post 1.0: + + * Almost every API in APR depends on pools, but pool semantics + aren't a good match for a lot of applications. We need to find + a way to support alternate allocators polymorphically without + a significant performance penalty. + + * apr_global_mutex_child_init and apr_proc_mutex_child_init aren't + portable. There are a variety of problems with the locking API when it + is used with apr_create_proc instead of apr_fork. First, _child_init + doesn't take a lockmech_e parameter so it causes a segfault after the + apr_proc_create, because the proc_mutex field hasn't been initialized. + When the lockmech_e parameter is added, it _still_ doesn't work, because + some lock mechanisms expect to inherit from the parent process. For + example, sys V semaphores don't have a file to open, so the child process + can't reaquire the lock. + + jerenkrantz says: This is not a showstopper and I believe the above + analysis is slightly confusing. The real problem here is that + apr_*_mutex_child_init assumes a shared memory space - that is, the + children processes have access to the parent apr_*_mutex_t pointer. The + children just call child_init on the original, inherited apr_*_mutex_t. + Unlike globalmutexchild in test, apr_*_mutex_create is *not* intended to + be called from the child and subsequently call child_init. Instead, + apr_create_proc is intended to exec separate processes with disjoint + memory addresses. Currently, APR does not provide a cross-platform + mechanism for joining an already existing lock. A simple + 'apr_*_mutex_join' which is intended to be called from separate + processes to an already-existing lock would solve this problem. + child_init is not intended to be used this way. Even with SysV + semaphores, using IPC_PRIVATE should still work due to the parent-child + relationship. A strawman has been posted to dev@apr: + Message-Id: <213031CF0406DE1AC426A411@[10.0.1.137]> + + This was listed as a showstopper for 1.0, but while the 2 patches above + exist neither was able to garner enough votes to be included in 1.0. + Will Rowe commented that a combination of the 2 would probably be the right + approach, a view that seems to have a lot of merit. Hopefully we can solve + this post 1.0. There were also enough people who felt that it wasn't a + real showstopper for it to be bumped. + + * Must namespace protect all include/apr_foo.h headers. Jon Travis + has especially observed these including apr within Apache-1.3. + Message-ID: <20020128100116.A4288@covalent.net> + Deprecating the symbols in 0.9, eliminating them with 1.0. + (Those problems have been fixed, but it is a good example of + what to look for.) + Some headers with issues: + apr.hnw (READDIR_IS_THREAD_SAFE, ENUM_BITFIELD, + _POSIX_THREAD_SAFE_FUNCTIONS (?)) + + * Flush out the test suite and make sure it passes on all platforms. + We currently have about 450 functions in APR and 147 tests. That + means we have a large number of functions that we can't verify are + actually portable. This TODO includes finishing the migration to the + unified test suite, and adding more tests to make the suite + comprehensive. + + * Eliminate the TODO's and XXX's by using the doxygen @bug feature + to allow us to better track the open issues, and provide historical + bug lists that help porters understand what was wrong in the old + versions of APR that they would be upgrading from. + + diff --git a/srclib/apr/apr-config.in b/srclib/apr/apr-config.in new file mode 100644 index 0000000000..718f0c62ac --- /dev/null +++ b/srclib/apr/apr-config.in @@ -0,0 +1,250 @@ +#!/bin/sh +# Copyright 2001-2005 The Apache Software Foundation or its licensors, as +# applicable. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# APR script designed to allow easy command line access to APR configuration +# parameters. + +APR_MAJOR_VERSION="@APR_MAJOR_VERSION@" +APR_DOTTED_VERSION="@APR_DOTTED_VERSION@" + +prefix="@prefix@" +exec_prefix="@exec_prefix@" +bindir="@bindir@" +libdir="@libdir@" +datadir="@datadir@" +installbuilddir="@installbuilddir@" +includedir="@includedir@" + +CC="@CC@" +CPP="@CPP@" +SHELL="@SHELL@" +CPPFLAGS="@EXTRA_CPPFLAGS@" +CFLAGS="@EXTRA_CFLAGS@" +LDFLAGS="@EXTRA_LDFLAGS@" +LIBS="@EXTRA_LIBS@" +EXTRA_INCLUDES="@EXTRA_INCLUDES@" +SHLIBPATH_VAR="@shlibpath_var@" +APR_SOURCE_DIR="@apr_srcdir@" +APR_BUILD_DIR="@apr_builddir@" +APR_SO_EXT="@so_ext@" +APR_LIB_TARGET="@export_lib_target@" +APR_LIBNAME="@APR_LIBNAME@" + +# NOTE: the following line is modified during 'make install': alter with care! +location=@APR_CONFIG_LOCATION@ + +show_usage() +{ + cat << EOF +Usage: apr-$APR_MAJOR_VERSION-config [OPTION] + +Known values for OPTION are: + --prefix[=DIR] change prefix to DIR + --bindir print location where binaries are installed + --includedir print location where headers are installed + --cc print C compiler name + --cpp print C preprocessor name and any required options + --cflags print C compiler flags + --cppflags print C preprocessor flags + --includes print include information + --ldflags print linker flags + --libs print additional libraries to link against + --srcdir print APR source directory + --installbuilddir print APR build helper directory + --link-ld print link switch(es) for linking to APR + --link-libtool print the libtool inputs for linking to APR + --shlib-path-var print the name of the shared library path env var + --apr-la-file print the path to the .la file, if available + --apr-so-ext print the extensions of shared objects on this platform + --apr-lib-target print the libtool target information + --apr-libtool print the path to APR's libtool + --version print the APR's version as a dotted triple + --help print this help + +When linking with libtool, an application should do something like: + APR_LIBS="\`apr-$APR_MAJOR_VERSION-config --link-libtool --libs\`" +or when linking directly: + APR_LIBS="\`apr-$APR_MAJOR_VERSION-config --link-ld --libs\`" + +An application should use the results of --cflags, --cppflags, --includes, +and --ldflags in their build process. +EOF +} + +if test $# -eq 0; then + show_usage + exit 1 +fi + +if test "$location" = "installed"; then + LA_FILE="$libdir/lib${APR_LIBNAME}.la" +else + LA_FILE="$APR_BUILD_DIR/lib${APR_LIBNAME}.la" +fi + +flags="" + +while test $# -gt 0; do + # Normalize the prefix. + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case "$1" in + # It is possible for the user to override our prefix. + --prefix=*) + prefix=$optarg + ;; + --prefix) + echo $prefix + exit 0 + ;; + --bindir) + echo $bindir + exit 0 + ;; + --includedir) + if test "$location" = "installed"; then + flags="$includedir" + elif test "$location" = "source"; then + flags="$APR_SOURCE_DIR/include" + else + # this is for VPATH builds + flags="$APR_BUILD_DIR/include $APR_SOURCE_DIR/include" + fi + echo $flags + exit 0 + ;; + --cc) + echo $CC + exit 0 + ;; + --cpp) + echo $CPP + exit 0 + ;; + --cflags) + flags="$flags $CFLAGS" + ;; + --cppflags) + flags="$flags $CPPFLAGS" + ;; + --libs) + flags="$flags $LIBS" + ;; + --ldflags) + flags="$flags $LDFLAGS" + ;; + --includes) + if test "$location" = "installed"; then + flags="$flags -I$includedir $EXTRA_INCLUDES" + elif test "$location" = "source"; then + flags="$flags -I$APR_SOURCE_DIR/include $EXTRA_INCLUDES" + else + # this is for VPATH builds + flags="$flags -I$APR_BUILD_DIR/include -I$APR_SOURCE_DIR/include $EXTRA_INCLUDES" + fi + ;; + --srcdir) + echo $APR_SOURCE_DIR + exit 0 + ;; + --installbuilddir) + if test "$location" = "installed"; then + echo "${installbuilddir}" + elif test "$location" = "source"; then + echo "$APR_SOURCE_DIR/build" + else + # this is for VPATH builds + echo "$APR_BUILD_DIR/build" + fi + exit 0 + ;; + --version) + echo $APR_DOTTED_VERSION + exit 0 + ;; + --link-ld) + if test "$location" = "installed"; then + ### avoid using -L if libdir is a "standard" location like /usr/lib + flags="$flags -L$libdir -l${APR_LIBNAME}" + else + ### this surely can't work since the library is in .libs? + flags="$flags -L$APR_BUILD_DIR -l${APR_LIBNAME}" + fi + ;; + --link-libtool) + # If the LA_FILE exists where we think it should be, use it. If we're + # installed and the LA_FILE does not exist, assume to use -L/-l + # (the LA_FILE may not have been installed). If we're building ourselves, + # we'll assume that at some point the .la file be created. + if test -f "$LA_FILE"; then + flags="$flags $LA_FILE" + elif test "$location" = "installed"; then + ### avoid using -L if libdir is a "standard" location like /usr/lib + # Since the user is specifying they are linking with libtool, we + # *know* that -R will be recognized by libtool. + flags="$flags -L$libdir -R$libdir -l${APR_LIBNAME}" + else + flags="$flags $LA_FILE" + fi + ;; + --shlib-path-var) + echo "$SHLIBPATH_VAR" + exit 0 + ;; + --apr-la-file) + if test -f "$LA_FILE"; then + flags="$flags $LA_FILE" + fi + ;; + --apr-so-ext) + echo "$APR_SO_EXT" + exit 0 + ;; + --apr-lib-target) + echo "$APR_LIB_TARGET" + exit 0 + ;; + --apr-libtool) + if test "$location" = "installed"; then + echo "${installbuilddir}/libtool" + else + echo "$APR_BUILD_DIR/libtool" + fi + exit 0 + ;; + --help) + show_usage + exit 0 + ;; + *) + show_usage + exit 1 + ;; + esac + + # Next please. + shift +done + +if test -n "$flags"; then + echo "$flags" +fi + +exit 0 diff --git a/srclib/apr/apr.dsp b/srclib/apr/apr.dsp new file mode 100644 index 0000000000..a67674148b --- /dev/null +++ b/srclib/apr/apr.dsp @@ -0,0 +1,651 @@ +# Microsoft Developer Studio Project File - Name="apr" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=apr - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "apr.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "apr.mak" CFG="apr - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "apr - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "apr - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "apr - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "LibR" +# PROP BASE Intermediate_Dir "LibR" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "LibR" +# PROP Intermediate_Dir "LibR" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I "./include/arch" /I "./include/arch/win32" /I "./include/arch/unix" /D "NDEBUG" /D "APR_DECLARE_STATIC" /D "WIN32" /D "_WINDOWS" /Fd"LibR\apr_src" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"LibR\apr-1.lib" + +!ELSEIF "$(CFG)" == "apr - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "LibD" +# PROP BASE Intermediate_Dir "LibD" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "LibD" +# PROP Intermediate_Dir "LibD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "./include" /I "./include/arch" /I "./include/arch/win32" /I "./include/arch/unix" /D "_DEBUG" /D "APR_DECLARE_STATIC" /D "WIN32" /D "_WINDOWS" /Fd"LibD\apr_src" /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"LibD\apr-1.lib" + +!ENDIF + +# Begin Target + +# Name "apr - Win32 Release" +# Name "apr - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter ".c" +# Begin Group "atomic" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\atomic\win32\apr_atomic.c +# End Source File +# End Group +# Begin Group "dso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\dso\win32\dso.c +# End Source File +# End Group +# Begin Group "file_io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\file_io\unix\copy.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\dir.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\fileacc.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filedup.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filepath.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\filepath_util.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filestat.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filesys.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\flock.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\fullrw.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\mktemp.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\open.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\pipe.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\readwrite.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\seek.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\tempdir.c +# End Source File +# End Group +# Begin Group "locks" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\locks\win32\proc_mutex.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_cond.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_mutex.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_rwlock.c +# End Source File +# End Group +# Begin Group "memory" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\memory\unix\apr_pools.c +# End Source File +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\misc\win32\apr_app.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\charset.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\env.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\errorcodes.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\getopt.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\internal.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\misc.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\otherchild.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\rand.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\start.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\utf8.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\version.c +# End Source File +# End Group +# Begin Group "mmap" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\mmap\unix\common.c +# End Source File +# Begin Source File + +SOURCE=.\mmap\win32\mmap.c +# End Source File +# End Group +# Begin Group "network_io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\network_io\unix\inet_ntop.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\inet_pton.c +# End Source File +# Begin Source File + +SOURCE=.\poll\unix\select.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\multicast.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sendrecv.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\sockaddr.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sockets.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sockopt.c +# End Source File +# End Group +# Begin Group "passwd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\passwd\apr_getpass.c +# End Source File +# End Group +# Begin Group "random" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\random\unix\apr_random.c +# End Source File +# Begin Source File + +SOURCE=.\random\unix\sha2.c +# End Source File +# Begin Source File + +SOURCE=.\random\unix\sha2_glue.c +# End Source File +# End Group +# Begin Group "shmem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\shmem\win32\shm.c +# End Source File +# End Group +# Begin Group "strings" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\strings\apr_cpystrn.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_fnmatch.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strings.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strnatcmp.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strtok.c +# End Source File +# End Group +# Begin Group "tables" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\tables\apr_hash.c +# End Source File +# Begin Source File + +SOURCE=.\tables\apr_tables.c +# End Source File +# End Group +# Begin Group "threadproc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\threadproc\win32\proc.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\signals.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\thread.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\threadpriv.c +# End Source File +# End Group +# Begin Group "time" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\time\win32\access.c +# End Source File +# Begin Source File + +SOURCE=.\time\win32\time.c +# End Source File +# Begin Source File + +SOURCE=.\time\win32\timestr.c +# End Source File +# End Group +# Begin Group "user" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\user\win32\groupinfo.c +# End Source File +# Begin Source File + +SOURCE=.\user\win32\userinfo.c +# End Source File +# End Group +# End Group +# Begin Group "Private Header Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_atime.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_dso.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_file_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_inherit.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_misc.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_networkio.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_thread_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_thread_rwlock.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_threadproc.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_utf8.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_private.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\apr_private_common.h +# End Source File +# End Group +# Begin Group "Public Header Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\apr.h.in +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\include\apr.hnw +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\include\apr.hw + +!IF "$(CFG)" == "apr - Win32 Release" + +# Begin Custom Build - Creating apr.h from apr.hw +InputPath=.\include\apr.hw + +".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + type .\include\apr.hw > .\include\apr.h + +# End Custom Build + +!ELSEIF "$(CFG)" == "apr - Win32 Debug" + +# Begin Custom Build - Creating apr.h from apr.hw +InputPath=.\include\apr.hw + +".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + type .\include\apr.hw > .\include\apr.h + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\include\apr_allocator.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_atomic.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_dso.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_env.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_errno.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_file_info.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_file_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_fnmatch.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_general.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_getopt.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_global_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_hash.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_inherit.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_lib.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_mmap.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_network_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_poll.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_pools.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_portable.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_proc_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_ring.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_shm.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_signal.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_strings.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_support.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_tables.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_cond.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_proc.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_rwlock.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_time.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_user.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_version.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_want.h +# End Source File +# End Group +# End Target +# End Project diff --git a/srclib/apr/apr.dsw b/srclib/apr/apr.dsw new file mode 100644 index 0000000000..dc0871bbc8 --- /dev/null +++ b/srclib/apr/apr.dsw @@ -0,0 +1,71 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "apr"=".\apr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "apr_app"=".\build\apr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency +}}} + +############################################################################### + +Project: "libapr"=".\libapr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libapr_app"=".\build\libapr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libapr + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/srclib/apr/apr.pc.in b/srclib/apr/apr.pc.in new file mode 100644 index 0000000000..318a81e26b --- /dev/null +++ b/srclib/apr/apr.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +APR_MAJOR_VERSION=@APR_MAJOR_VERSION@ +includedir=@includedir@ + +Name: APR +Description: The Apache Portable Runtime library +Version: @APR_DOTTED_VERSION@ +Libs: -L${libdir} -l@APR_LIBNAME@ @EXTRA_LIBS@ +Cflags: @EXTRA_CPPFLAGS@ @EXTRA_CFLAGS@ -I${includedir} diff --git a/srclib/apr/atomic/netware/apr_atomic.c b/srclib/apr/atomic/netware/apr_atomic.c new file mode 100644 index 0000000000..78d14a65c1 --- /dev/null +++ b/srclib/apr/atomic/netware/apr_atomic.c @@ -0,0 +1,70 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_atomic.h" + +#include + +APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *pool) +{ + return APR_SUCCESS; +} + +APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + return atomic_xchgadd((unsigned long *)mem,(unsigned long)val); +} + +APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + atomic_sub((unsigned long *)mem,(unsigned long)val); +} + +APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return atomic_xchgadd((unsigned long *)mem, 1); +} + +APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + *mem = val; +} + +APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} + +APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with,apr_uint32_t cmp) +{ + return atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with); +} + +APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + return atomic_xchg((unsigned long *)mem,(unsigned long)val); +} + +APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + return (atomic_xchgadd((unsigned long *)mem, 0xFFFFFFFF) - 1); +} + +APR_DECLARE(void *) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) +{ + return (void*)atomic_cmpxchg((unsigned long *)mem,(unsigned long)cmp,(unsigned long)with); +} diff --git a/srclib/apr/atomic/os390/atomic.c b/srclib/apr/atomic/os390/atomic.c new file mode 100644 index 0000000000..675a045772 --- /dev/null +++ b/srclib/apr/atomic/os390/atomic.c @@ -0,0 +1,96 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "apr.h" +#include "apr_atomic.h" + +#include + +apr_status_t apr_atomic_init(apr_pool_t *p) +{ + return APR_SUCCESS; +} + +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old, new_val; + + old = *mem; /* old is automatically updated on cs failure */ + do { + new_val = old + val; + } while (__cs(&old, (cs_t *)mem, new_val)); + return old; +} + +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old, new_val; + + old = *mem; /* old is automatically updated on cs failure */ + do { + new_val = old - val; + } while (__cs(&old, (cs_t *)mem, new_val)); +} + +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return apr_atomic_add32(mem, 1); +} + +int apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + apr_uint32_t old, new_val; + + old = *mem; /* old is automatically updated on cs failure */ + do { + new_val = old - 1; + } while (__cs(&old, (cs_t *)mem, new_val)); + + return new_val != 0; +} + +apr_uint32_t apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} + +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + *mem = val; +} + +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t swap, + apr_uint32_t cmp) +{ + apr_uint32_t old = cmp; + + __cs(&old, (cs_t *)mem, swap); + return old; /* old is automatically updated from mem on cs failure */ +} + +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old, new_val; + + old = *mem; /* old is automatically updated on cs failure */ + do { + new_val = val; + } while (__cs(&old, (cs_t *)mem, new_val)); + + return old; +} + diff --git a/srclib/apr/atomic/unix/apr_atomic.c b/srclib/apr/atomic/unix/apr_atomic.c new file mode 100644 index 0000000000..5484eba0ad --- /dev/null +++ b/srclib/apr/atomic/unix/apr_atomic.c @@ -0,0 +1,393 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_atomic.h" +#include "apr_thread_mutex.h" + +#include "apr_private.h" + +#include + +#if defined(__GNUC__) && defined(__STRICT_ANSI__) && !defined(USE_GENERIC_ATOMICS) +/* force use of generic atomics if building e.g. with -std=c89, which + * doesn't allow inline asm */ +#define USE_GENERIC_ATOMICS +#endif + +#if (defined(__i386__) || defined(__x86_64__)) \ + && defined(__GNUC__) && !defined(USE_GENERIC_ATOMICS) + +APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, + apr_uint32_t with, + apr_uint32_t cmp) +{ + apr_uint32_t prev; + + asm volatile ("lock; cmpxchgl %1, %2" + : "=a" (prev) + : "r" (with), "m" (*(mem)), "0"(cmp) + : "memory", "cc"); + return prev; +} +#define APR_OVERRIDE_ATOMIC_CAS32 + +static apr_uint32_t inline intel_atomic_add32(volatile apr_uint32_t *mem, + apr_uint32_t val) +{ + asm volatile ("lock; xaddl %0,%1" + : "=r"(val), "=m"(*mem) /* outputs */ + : "0"(val), "m"(*mem) /* inputs */ + : "memory", "cc"); + return val; +} + +APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, + apr_uint32_t val) +{ + return intel_atomic_add32(mem, val); +} +#define APR_OVERRIDE_ATOMIC_ADD32 + +APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + asm volatile ("lock; subl %1, %0" + : + : "m" (*(mem)), "r" (val) + : "memory", "cc"); +} +#define APR_OVERRIDE_ATOMIC_SUB32 + +APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + unsigned char prev; + + asm volatile ("lock; decl %1;\n\t" + "setnz %%al" + : "=a" (prev) + : "m" (*(mem)) + : "memory", "cc"); + return prev; +} +#define APR_OVERRIDE_ATOMIC_DEC32 + +APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return intel_atomic_add32(mem, 1); +} +#define APR_OVERRIDE_ATOMIC_INC32 + +APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + *mem = val; +} +#define APR_OVERRIDE_ATOMIC_SET32 + +APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t prev = val; + + asm volatile ("lock; xchgl %0, %1" + : "=r" (prev) + : "m" (*(mem)), "0"(prev) + : "memory"); + return prev; +} +#define APR_OVERRIDE_ATOMIC_XCHG32 + +/*#define apr_atomic_init(pool) APR_SUCCESS*/ + +#endif /* (__linux__ || __EMX__ || __FreeBSD__) && __i386__ */ + +#if (defined(__PPC__) || defined(__ppc__)) && defined(__GNUC__) \ + && !defined(USE_GENERIC_ATOMICS) + +APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, + apr_uint32_t swap, + apr_uint32_t cmp) +{ + apr_uint32_t prev; + + asm volatile ("0:\n\t" /* retry local label */ + "lwarx %0,0,%1\n\t" /* load prev and reserve */ + "cmpw %0,%3\n\t" /* does it match cmp? */ + "bne- 1f\n\t" /* ...no, bail out */ + "stwcx. %2,0,%1\n\t" /* ...yes, conditionally + store swap */ + "bne- 0b\n\t" /* start over if we lost + the reservation */ + "1:" /* exit local label */ + + : "=&r"(prev) /* output */ + : "b" (mem), "r" (swap), "r"(cmp) /* inputs */ + : "memory", "cc"); /* clobbered */ + return prev; +} +#define APR_OVERRIDE_ATOMIC_CAS32 + +APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, + apr_uint32_t delta) +{ + apr_uint32_t prev, temp; + + asm volatile ("0:\n\t" /* retry local label */ + "lwarx %0,0,%2\n\t" /* load prev and reserve */ + "add %1,%0,%3\n\t" /* temp = prev + delta */ + "stwcx. %1,0,%2\n\t" /* conditionally store */ + "bne- 0b" /* start over if we lost + the reservation */ + + /*XXX find a cleaner way to define the temp + * it's not an output + */ + : "=&r" (prev), "=&r" (temp) /* output, temp */ + : "b" (mem), "r" (delta) /* inputs */ + : "memory", "cc"); /* clobbered */ + return prev; +} +#define APR_OVERRIDE_ATOMIC_ADD32 + +#endif /* __PPC__ && __GNUC__ */ + +#if !defined(APR_OVERRIDE_ATOMIC_INIT) + +#if APR_HAS_THREADS +#define NUM_ATOMIC_HASH 7 +/* shift by 2 to get rid of alignment issues */ +#define ATOMIC_HASH(x) (unsigned int)(((unsigned long)(x)>>2)%(unsigned int)NUM_ATOMIC_HASH) +static apr_thread_mutex_t **hash_mutex; +#endif /* APR_HAS_THREADS */ + +apr_status_t apr_atomic_init(apr_pool_t *p) +{ +#if APR_HAS_THREADS + int i; + apr_status_t rv; + hash_mutex = apr_palloc(p, sizeof(apr_thread_mutex_t*) * NUM_ATOMIC_HASH); + + for (i = 0; i < NUM_ATOMIC_HASH; i++) { + rv = apr_thread_mutex_create(&(hash_mutex[i]), + APR_THREAD_MUTEX_DEFAULT, p); + if (rv != APR_SUCCESS) { + return rv; + } + } +#endif /* APR_HAS_THREADS */ + return APR_SUCCESS; +} +#endif /* !defined(APR_OVERRIDE_ATOMIC_INIT) */ + +/* abort() if 'x' does not evaluate to APR_SUCCESS. */ +#define CHECK(x) do { if ((x) != APR_SUCCESS) abort(); } while (0) + +#if !defined(APR_OVERRIDE_ATOMIC_ADD32) +#if defined(APR_OVERRIDE_ATOMIC_CAS32) +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old_value, new_value; + + do { + old_value = *mem; + new_value = old_value + val; + } while (apr_atomic_cas32(mem, new_value, old_value) != old_value); + return old_value; +} +#else +apr_uint32_t apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old_value; + +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + old_value = *mem; + *mem += val; + CHECK(apr_thread_mutex_unlock(lock)); +#else + old_value = *mem; + *mem += val; +#endif /* APR_HAS_THREADS */ + return old_value; +} +#endif /* defined(APR_OVERRIDE_ATOMIC_CAS32) */ +#endif /* !defined(APR_OVERRIDE_ATOMIC_ADD32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_SUB32) +#if defined(APR_OVERRIDE_ATOMIC_CAS32) +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t old_value, new_value; + + do { + old_value = *mem; + new_value = old_value - val; + } while (apr_atomic_cas32(mem, new_value, old_value) != old_value); +} +#else +void apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + *mem -= val; + CHECK(apr_thread_mutex_unlock(lock)); +#else + *mem -= val; +#endif /* APR_HAS_THREADS */ +} +#endif /* defined(APR_OVERRIDE_ATOMIC_CAS32) */ +#endif /* !defined(APR_OVERRIDE_ATOMIC_SUB32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_SET32) +void apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + *mem = val; + CHECK(apr_thread_mutex_unlock(lock)); +#else + *mem = val; +#endif /* APR_HAS_THREADS */ +} +#endif /* !defined(APR_OVERRIDE_ATOMIC_SET32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_INC32) +apr_uint32_t apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + return apr_atomic_add32(mem, 1); +} +#endif /* !defined(APR_OVERRIDE_ATOMIC_INC32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_DEC32) +#if defined(APR_OVERRIDE_ATOMIC_CAS32) +int apr_atomic_dec32(volatile apr_uint32_t *mem) +{ + apr_uint32_t old_value, new_value; + + do { + old_value = *mem; + new_value = old_value - 1; + } while (apr_atomic_cas32(mem, new_value, old_value) != old_value); + return old_value != 1; +} +#else +int apr_atomic_dec32(volatile apr_uint32_t *mem) +{ +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + apr_uint32_t new; + + CHECK(apr_thread_mutex_lock(lock)); + (*mem)--; + new = *mem; + CHECK(apr_thread_mutex_unlock(lock)); + return new; +#else + (*mem)--; + return *mem; +#endif /* APR_HAS_THREADS */ +} +#endif /* defined(APR_OVERRIDE_ATOMIC_CAS32) */ +#endif /* !defined(APR_OVERRIDE_ATOMIC_DEC32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_CAS32) +apr_uint32_t apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp) +{ + apr_uint32_t prev; +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + prev = *mem; + if (prev == cmp) { + *mem = with; + } + CHECK(apr_thread_mutex_unlock(lock)); +#else + prev = *mem; + if (prev == cmp) { + *mem = with; + } +#endif /* APR_HAS_THREADS */ + return prev; +} +#endif /* !defined(APR_OVERRIDE_ATOMIC_CAS32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_XCHG32) +#if defined(APR_OVERRIDE_ATOMIC_CAS32) +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t prev; + do { + prev = *mem; + } while (apr_atomic_cas32(mem, val, prev) != prev); + return prev; +} +#else +apr_uint32_t apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ + apr_uint32_t prev; +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + prev = *mem; + *mem = val; + CHECK(apr_thread_mutex_unlock(lock)); +#else + prev = *mem; + *mem = val; +#endif /* APR_HAS_THREADS */ + return prev; +} +#endif /* defined(APR_OVERRIDE_ATOMIC_CAS32) */ +#endif /* !defined(APR_OVERRIDE_ATOMIC_XCHG32) */ + +#if !defined(APR_OVERRIDE_ATOMIC_CASPTR) +void *apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) +{ + void *prev; +#if APR_HAS_THREADS + apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)]; + + CHECK(apr_thread_mutex_lock(lock)); + prev = *(void **)mem; + if (prev == cmp) { + *mem = with; + } + CHECK(apr_thread_mutex_unlock(lock)); +#else + prev = *(void **)mem; + if (prev == cmp) { + *mem = with; + } +#endif /* APR_HAS_THREADS */ + return prev; +} +#endif /* !defined(APR_OVERRIDE_ATOMIC_CASPTR) */ + +#if !defined(APR_OVERRIDE_ATOMIC_READ32) +APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} +#endif + diff --git a/srclib/apr/atomic/win32/apr_atomic.c b/srclib/apr/atomic/win32/apr_atomic.c new file mode 100644 index 0000000000..95db7503b9 --- /dev/null +++ b/srclib/apr/atomic/win32/apr_atomic.c @@ -0,0 +1,123 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_atomic.h" +#include "apr_thread_mutex.h" + +APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p) +{ + return APR_SUCCESS; +} + +/* + * Remapping function pointer type to accept apr_uint32_t's type-safely + * as the arguments for as our apr_atomic_foo32 Functions + */ +typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_fn) + (apr_uint32_t volatile *); +typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_fn) + (apr_uint32_t volatile *, + apr_uint32_t); +typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_val_fn) + (apr_uint32_t volatile *, + apr_uint32_t, apr_uint32_t); +typedef WINBASEAPI void * (WINAPI * apr_atomic_win32_ptr_ptr_ptr_fn) + (volatile void **, + void *, const void *); + +APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) + return InterlockedExchangeAdd(mem, val); +#else + return ((apr_atomic_win32_ptr_val_fn)InterlockedExchangeAdd)(mem, val); +#endif +} + +/* Of course we want the 2's compliment of the unsigned value, val */ +#pragma warning(disable: 4146) + +APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) + InterlockedExchangeAdd(mem, -val); +#else + ((apr_atomic_win32_ptr_val_fn)InterlockedExchangeAdd)(mem, -val); +#endif +} + +APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem) +{ + /* we return old value, win32 returns new value :( */ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedIncrement(mem) - 1; +#else + return ((apr_atomic_win32_ptr_fn)InterlockedIncrement)(mem) - 1; +#endif +} + +APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedDecrement(mem); +#else + return ((apr_atomic_win32_ptr_fn)InterlockedDecrement)(mem); +#endif +} + +APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + InterlockedExchange(mem, val); +#else + ((apr_atomic_win32_ptr_val_fn)InterlockedExchange)(mem, val); +#endif +} + +APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem) +{ + return *mem; +} + +APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedCompareExchange(mem, with, cmp); +#else + return ((apr_atomic_win32_ptr_val_val_fn)InterlockedCompareExchange)(mem, with, cmp); +#endif +} + +APR_DECLARE(void *) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedCompareExchangePointer(mem, with, cmp); +#else + /* Too many VC6 users have stale win32 API files, stub this */ + return ((apr_atomic_win32_ptr_ptr_ptr_fn)InterlockedCompareExchange)(mem, with, cmp); +#endif +} + +APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val) +{ +#if (defined(_M_IA64) || defined(_M_AMD64)) && !defined(RC_INVOKED) + return InterlockedExchange(mem, val); +#else + return ((apr_atomic_win32_ptr_val_fn)InterlockedExchange)(mem, val); +#endif +} diff --git a/srclib/apr/build.conf b/srclib/apr/build.conf new file mode 100644 index 0000000000..0522a1bb78 --- /dev/null +++ b/srclib/apr/build.conf @@ -0,0 +1,26 @@ +# +# Configuration file for APR. Used by APR/build/gen-build.py +# + +[options] + +# paths to platform-independent .c files to build +paths = + passwd/*.c + strings/*.c + tables/*.c + +# directories that have platform-specific code in them. the resulting +# pattern will be: SUBDIR/PLATFORM/*.c +platform_dirs = + atomic dso file_io locks memory misc mmap network_io poll random + shmem support threadproc time user + +# all the public headers +headers = include/*.h + +# aplibtool is manually built by the configure process +# build/aplibtool.c + +# we have a recursive makefile for the test files (for now) +# test/*.c diff --git a/srclib/apr/build/MakeEtags b/srclib/apr/build/MakeEtags new file mode 100755 index 0000000000..c4e957c97f --- /dev/null +++ b/srclib/apr/build/MakeEtags @@ -0,0 +1,39 @@ +#!/bin/sh + +# This file illustrates how to generate a useful TAGS file via etags +# for emacs. This should be invoked from the top source directory i.e.: +# > build/MakeEtags +# and will create a TAGS file in the top source directory. + +# This script falls under the Apache License. +# See http://www.apache.org/docs/LICENSE + +# Once you have created ./TAGS in emacs you'll need to setup +# tag-table-alist with an entry to assure it finds the single ./TAGS +# file from the many source directories. Something along these lines: +# (setq tag-table-alist +# '(("/home/me/work/httpd-2.0/" +# . "/home/me/work/httpd-2.0/") +# )) + +# This requires a special version of etags, i.e. the +# one called "Exuberant ctags" available at: +# http://fly.hiwaay.net/~darren/ctags/ +# Once that is setup you'll need to point to the +# executable here: + +etags=~/local/bin/etags + +# Exuberant etags is necessary since it can ignore some defined symbols +# that obscure the function signatures. + +ignore=AP_DECLARE,AP_DECLARE_NONSTD,__declspec + +# Create an etags file at the root of the source +# tree, then create symbol links to it from each +# directory in the source tree. By passing etags +# absolute pathnames we get a tag file that is +# NOT portable when we move the directory tree. + +find . -name '*.[ch]' -print | $etags -I "$ignore" -L - + diff --git a/srclib/apr/build/NWGNUenvironment.inc b/srclib/apr/build/NWGNUenvironment.inc new file mode 100644 index 0000000000..fd54b487c9 --- /dev/null +++ b/srclib/apr/build/NWGNUenvironment.inc @@ -0,0 +1,304 @@ +# +# Setup needed Tools and Libraries +# + +ifeq "$(wildcard $(APR_WORK)\build\NWGNUcustom.inc)" "$(APR_WORK)\build\NWGNUcustom.inc" +include $(APR_WORK)\build\NWGNUcustom.inc +CUSTOM_INI = $(AP_WORK)\NWGNUcustom.ini +endif + +ifndef VERBOSE +.SILENT: +endif + +# +# Treat like an include +# +ifndef EnvironmentDefined + +# +# simple macros for parsing makefiles +# +EOLIST:= +EMPTY := +COMMA := , +SPACE := $(EMPTY) $(EMPTY) + +# +# Base environment +# + +# Try and handle case issues +ifndef NOVELLLIBC +ifdef NovellLibC +NOVELLLIBC = $(NovellLibC) +endif +endif + +ifndef NOVELLLIBC +NOVELLLIBC = C:/novell/ndk/libc +endif + +# This is a placeholder +# ifndef LDAPSDK +# LDAPSDK = C:/novell/ndk/cldapsdk +# endif + +ifndef METROWERKS +METROWERKS = C:\Program Files\Metrowerks\CodeWarrior +endif + +# If LM_LICENSE_FILE isn't defined, define a variable that can be used to +# restart make with it defined +ifndef LM_LICENSE_FILE +NO_LICENSE_FILE = NO_LICENSE_FILE +endif + +# +# Set the Release type that you want to build, possible values are: +# +# debug - full debug switches are set +# noopt - normal switches are set (default) +# optimized - optimization switches are set + +ifdef reltype +RELEASE=$(reltype) +endif + +ifdef RELTYPE +RELEASE=$(RELTYPE) +endif + +ifdef debug +RELEASE=debug +endif + +ifdef DEBUG +RELEASE=debug +endif + +ifdef optimized +RELEASE=optimized +endif + +ifdef OPTIMIZED +RELEASE=optimized +endif + +ifndef RELEASE +RELEASE = optimized +endif + +ifeq "$(RELEASE)" "debug" +OBJDIR = Debug +endif + +ifeq "$(RELEASE)" "noopt" +OBJDIR = Noopt +endif + +ifeq "$(RELEASE)" "optimized" +OBJDIR = Release +endif + +# +# Setup compiler information +# + +# MetroWerks NLM tools +CC = mwccnlm +CPP = mwccnlm +LINK = mwldnlm +LIB = mwldnlm -type library -w nocmdline + +ifdef IPV6 +ifndef USE_STDSOCKETS +USE_STDSOCKETS=1 +endif +endif + +NOVI = $(NOVELLLIBC)\imports + +INCDIRS = $(NOVELLLIBC)\include;$(NOVELLLIBC)\include\nks;$(NOVELLLIBC)\include\winsock; + +DEFINES = -DNETWARE +ifndef USE_STDSOCKETS +DEFINES += -DUSE_WINSOCK +endif +ifndef DEBUG +DEFINES += -DNDEBUG +endif + +# +# MetroWerks static Libraries + +CLIB3S = $(METROWERKS)\Novell Support\Metrowerks Support\Libraries\Runtime\mwcrtl.lib +MATH3S = +PLIB3S = $(METROWERKS)\Novell Support\Metrowerks Support\Libraries\MSL C++\MWCPP.lib + +# Base compile flags +# and prefix or precompiled header added here. + +# The default flags are as follows: +# +# -c compile only, no link +# -nosyspath treat #include <...> like #include "..." +# -Cpp_exceptions off disable C++ exceptions +# -RTTI off disable C++ run-time typing information +# -align 4 align on 4 byte bounderies +# -w nocmdline disable command-line driver/parser warnings +# -proc PII generate code base on Pentium II instruction set +# -inst mmx use MMX extensions (not used) + +CFLAGS = -c -nosyspath -Cpp_exceptions off -RTTI off -align 4 -w nocmdline -proc PII + +# -g generate debugging information +# -O0 level 0 optimizations + +ifeq "$(RELEASE)" "debug" +CFLAGS += -g -O0 +endif + +# -O4,p level 4 optimizations, optimize for speed +ifeq "$(RELEASE)" "optimized" +CFLAGS += -O4,p +endif + +# -prefix apr_arch_pre_nw.h #include pre_nw.h for all files + +CFLAGS += -prefix apr_arch_pre_nw.h + + +PATH:=$(PATH);$(METROWERKS)\bin;$(METROWERKS)\Other Metrowerks Tools\Command Line Tools + +# +# Declare major project deliverables output directories here +# + +ifdef DEST +INSTALL = $(DEST) +ifeq (\, $(findstring \,$(INSTALL))) +INSTDIRS = $(DEST) +endif +endif + +ifdef dest +INSTALL = $(dest) +ifeq (\, $(findstring \,$(INSTALL))) +INSTDIRS = $(dest) +endif +endif + +ifndef INSTALL +INSTALL = $(APR_WORK)\Dist +INSTDIRS = $(APR_WORK)\Dist +endif + +# Add support for building IPV6 alongside +ifneq "$(IPV6)" "" +DEFINES += -DNW_BUILD_IPV6 +INCDIRS := $(NOVELLLIBC)\include\winsock\IPV6;$(INCDIRS) + +ifneq "$(findstring IPV6,$(OBJDIR))" "IPV6" +OBJDIR := $(OBJDIR)_IPV6 +endif + +ifneq "$(findstring IPV6,$(INSTALL))" "IPV6" +INSTALL := $(INSTALL)_IPV6 +endif + +ifneq "$(findstring IPV6,$(INSTDIRS))" "IPV6" +INSTDIRS := $(INSTDIRS)_IPV6 +endif + +endif + +ifdef DEST +INSTALLBASE := $(INSTALL)\Apache2 + +INSTDEVDIRS := \ + $(INSTDIRS) \ + $(INSTALLBASE) \ + $(INSTALLBASE)\include \ + $(INSTALLBASE)\lib \ + +INSTDIRS += \ + $(INSTALLBASE) \ + +else +INSTALLBASE := $(INSTALL)\apr + +INSTDEVDIRS := \ + $(INSTDIRS) \ + $(INSTALLBASE) \ + $(INSTALLBASE)\include \ + $(INSTALLBASE)\lib \ + +INSTDIRS += \ + $(INSTALLBASE) \ + +endif + +# +# Declare Command and tool macros here +# + +# Os2LibPath is an extra check to see if we are on NT +ifdef Os2LibPath +OS = Windows_NT +endif + +ifeq "$(OS)" "Windows_NT" +CMD=cmd /C +CHK=cmd /C if exist +CHKNOT=cmd /C if not exist +DEL = del /F +DELTREE = cmd /C rd /s/q +WINNT=1 +XCOPYSW = /E +else +CMD=command /C +CHK=command /C if exist +CHKNOT=command /C if not exist +DEL = del +DELTREE = deltree /y +XCOPYSW = /E /Y +endif + + +# +# Setup base C compiler flags +# + +# +# Common directories +# + +APR = $(APR_WORK) +APRTEST = $(APR_WORK)/test +APRUTIL = $(APU_WORK) +APULDAP = $(APU_WORK)/ldap +XML = $(APRUTIL)/xml + +# +# Internal Libraries +# + +APRLIB = $(APR)/$(OBJDIR)/aprlib.lib +APRUTLIB = $(APRUTIL)/$(OBJDIR)/aprutil.lib +APULDAPLIB = $(APULDAP)/$(OBJDIR)/apuldap.lib +XMLLIB = $(XML)/$(OBJDIR)/xmllib.lib + +# +# Additional general defines +# + +EnvironmentDefined = 1 +endif # ifndef EnvironmentDefined + +# This is always set so that it will show up in lower directories + +ifdef Path +Path = $(PATH) +endif + diff --git a/srclib/apr/build/NWGNUhead.inc b/srclib/apr/build/NWGNUhead.inc new file mode 100644 index 0000000000..17f149cadd --- /dev/null +++ b/srclib/apr/build/NWGNUhead.inc @@ -0,0 +1,96 @@ +# +# Obtain the global build environment +# + +include $(APR_WORK)\build\NWGNUenvironment.inc + +# +# Define base targets and rules +# + +TARGETS = libs nlms install clobber_libs clobber_nlms clean installdev + +.PHONY : $(TARGETS) default all help $(NO_LICENSE_FILE) + +# Here is where we will use the NO_LICENSE_FILE variable to see if we need to +# restart the make with it defined + +ifdef NO_LICENSE_FILE + +default: NO_LICENSE_FILE + +all: NO_LICENSE_FILE + +install :: NO_LICENSE_FILE + +installdev :: NO_LICENSE_FILE + +NO_LICENSE_FILE : + $(MAKE) $(MAKECMDGOALS) -f NWGNUmakefile RELEASE=$(RELEASE) DEST="$(INSTALL)" LM_LICENSE_FILE="$(METROWERKS)\license.dat" + +else # LM_LICENSE_FILE must be defined so use the real targets + +default: $(SUBDIRS) libs nlms + +all: $(SUBDIRS) libs nlms install + +$(TARGETS) :: $(SUBDIRS) + +endif #NO_LICENSE_FILE check + +help : + @echo targets for RELEASE=$(RELEASE): + @echo (default) . . . . libs nlms + @echo all . . . . . . . does everything (libs nlms install) + @echo libs. . . . . . . builds all libs + @echo nlms. . . . . . . builds all nlms + @echo install . . . . . builds libs and nlms and copies install files to + @echo "$(INSTALL)" + @echo installdev. . . . copies headers and files needed for development to + @echo "$(INSTALL)" + @echo clean . . . . . . deletes $(OBJDIR) dirs, *.err, and *.map + @echo clobber_all . . . deletes all possible output from the make + @echo clobber_install . deletes all files in $(INSTALL) + @$(CMD) echo. + @echo Multiple targets can be used on a single nmake command line - + @echo (i.e. $(MAKE) clean all) + @$(CMD) echo. + @echo You can also specify RELEASE=debug, RELEASE=noopt, or RELEASE=optimized + @echo The default is RELEASE=optimized + +clobber_all :: clean clobber_install + +clobber_install :: + -$(DELTREE) $(INSTALL) 2>NUL + +# +# build recursive targets +# + +$(SUBDIRS) : FORCE +ifneq "$(MAKECMDGOALS)" "clean" + $(CMD) echo. + @echo Building $(CURDIR)/$@ +endif + $(MAKE) -C $@ $(MAKECMDGOALS) -f NWGNUmakefile RELEASE=$(RELEASE) DEST="$(INSTALL)" LM_LICENSE_FILE="$(LM_LICENSE_FILE)" + $(CMD) echo. + +FORCE: + +# +# Standard targets +# + +clean :: $(SUBDIRS) + @echo Cleaning up $(CURDIR) + -$(DELTREE) $(OBJDIR) 2> NUL + $(CHK) *.err $(DEL) *.err + $(CHK) *.map $(DEL) *.map + $(CHK) *.d $(DEL) *.d + $(CHK) *.tmp $(DEL) *.tmp + $(CHK) xc.bat $(DEL) xc.bat + -$(DELTREE) $(OBJDIR) 2> NUL + +$(OBJDIR) :: + $(CHKNOT) $(OBJDIR)\nul mkdir $(OBJDIR) + diff --git a/srclib/apr/build/NWGNUmakefile b/srclib/apr/build/NWGNUmakefile new file mode 100644 index 0000000000..6f9b32dd04 --- /dev/null +++ b/srclib/apr/build/NWGNUmakefile @@ -0,0 +1,94 @@ +# +# Declare the sub-directories to be built here +# + +SUBDIRS = \ + $(EOLIST) + +# +# Get the 'head' of the build environment. This includes default targets and +# paths to tools +# + +include $(APR_WORK)\build\NWGNUhead.inc + +# +# build this level's files + +FILES_prebuild_headers = \ + $(APR)/include/apr.h \ + $(APRUTIL)/include/apu.h \ + $(APRUTIL)/include/apu_want.h \ + $(APRUTIL)/include/apr_ldap.h \ + $(APRUTIL)/include/private/apu_config.h \ + $(APRUTIL)/include/private/apu_select_dbm.h \ + $(APRUTIL)/xml/expat/lib/expat.h \ + $(APRUTIL)/xml/expat/lib/config.h \ + $(EOLIST) + +nlms :: $(APR)/aprlib.imp + +$(APR)/aprlib.imp : make_nw_export.awk nw_export.i + @echo Generating $(subst /,\,$@) + awk -f make_nw_export.awk nw_export.i | sort >$(APR)/aprlib.imp + +nw_export.i : nw_export.inc $(FILES_prebuild_headers) $(NLM_NAME)_cc.opt + @echo Generating $(subst /,\,$@) + $(CC) $< @$(NLM_NAME)_cc.opt + +$(NLM_NAME)_cc.opt : NWGNUmakefile $(APR_WORK)\build\NWGNUenvironment.inc $(APR_WORK)\build\NWGNUhead.inc $(APR_WORK)\build\NWGNUtail.inc $(CUSTOM_INI) + $(CHK) $@ $(DEL) $@ + @echo -P >> $@ + @echo -EP >> $@ + @echo -nosyspath >> $@ + @echo -w nocmdline >> $@ + @echo $(DEFINES) -DGENEXPORTS >> $@ + @echo -I$(APR)\include >> $@ + @echo -I$(APR)\include\arch\netware >> $@ + @echo -I$(APR)\include\arch\unix >> $@ + @echo -I$(APRUTIL)\include >> $@ + @echo -ir $(NOVELLLIBC) >> $@ +ifneq "$(LDAPSDK)" "" + @echo -ir $(LDAPSDK) >> $@ +endif + +$(APR)/include/%.h: $(subst /,\,$(APR))\include\%.hnw + @echo Creating $(subst /,\,$@) + copy $< $(subst /,\,$(APR))\include\$(@F) + +$(APRUTIL)/include/%.h: $(subst /,\,$(APRUTIL))\include\%.hnw + @echo Creating $(subst /,\,$@) + copy $< $(subst /,\,$(APRUTIL))\include\$(@F) + +$(APRUTIL)/include/private/%.h: $(subst /,\,$(APRUTIL))\include\private\%.hw + @echo Creating $(subst /,\,$@) + copy $< $(subst /,\,$(APRUTIL))\include\private\$(@F) + +$(APRUTIL)/xml/expat/lib/%.h: $(subst /,\,$(APRUTIL))\xml\expat\lib\%.hnw + @echo Creating $(subst /,\,$@) + copy $< $(subst /,\,$(APRUTIL))\xml\expat\lib\$(@F) + +$(APRUTIL)/xml/expat/lib/%.h: $(subst /,\,$(APRUTIL))\xml\expat\lib\%.h.in + @echo Creating $(subst /,\,$@) + copy $< $(subst /,\,$(APRUTIL))\xml\expat\lib\$(@F) + +# +# You can use this target if all that is needed is to copy files to the +# installation area +# +install :: nlms FORCE + + +clean :: + $(CHK) nw_export.i $(DEL) nw_export.i + $(CHK) $(NLM_NAME)_cc.opt $(DEL) $(NLM_NAME)_cc.opt + $(CHK) NWGNUversion.inc $(DEL) NWGNUversion.inc + $(CHK) $(subst /,\,$(APR))\include\apr.h $(DEL) $(subst /,\,$(APR))\include\apr.h + $(CHK) $(subst /,\,$(APRUTIL))\include\apu.h $(DEL) $(subst /,\,$(APRUTIL))\include\apu.h + $(CHK) $(subst /,\,$(APRUTIL))\include\apr_ldap.h $(DEL) $(subst /,\,$(APRUTIL))\include\apr_ldap.h + $(CHK) $(subst /,\,$(APRUTIL))\include\private\apu_config.h $(DEL) $(subst /,\,$(APRUTIL))\include\private\apu_config.h + $(CHK) $(subst /,\,$(APRUTIL))\include\private\apu_select_dbm.h $(DEL) $(subst /,\,$(APRUTIL))\include\private\apu_select_dbm.h + $(CHK) $(subst /,\,$(APRUTIL))\xml\expat\lib\expat.h $(DEL) $(subst /,\,$(APRUTIL))\xml\expat\lib\expat.h + $(CHK) $(subst /,\,$(APRUTIL))\xml\expat\lib\config.h $(DEL) $(subst /,\,$(APRUTIL))\xml\expat\lib\config.h + $(CHK) $(subst /,\,$(APR))\aprlib.imp $(DEL) $(subst /,\,$(APR))\aprlib.imp + diff --git a/srclib/apr/build/NWGNUtail.inc b/srclib/apr/build/NWGNUtail.inc new file mode 100644 index 0000000000..a0ec6af9a0 --- /dev/null +++ b/srclib/apr/build/NWGNUtail.inc @@ -0,0 +1,322 @@ +# +# This contains final targets and should be included at the end of any +# NWGNUmakefile file +# + +# +# If we are going to create an nlm, make sure we have assigned variables to +# use during the link. +# +echo NLM_NAME=$(NLM_NAME) +ifndef NLM_NAME +NLM_NAME = $(TARGET_nlm) +endif + +ifndef NLM_DESCRIPTION +NLM_DESCRIPTION = $(NLM_NAME) +endif + +ifndef NLM_THREAD_NAME +NLM_THREAD_NAME = $(NLM_NAME) Thread +endif + +ifndef NLM_SCREEN_NAME +NLM_SCREEN_NAME = DEFAULT +endif + +ifndef NLM_COPYRIGHT +NLM_COPYRIGHT = Copyright (c) 2000-2005 The Apache Software Foundation. All rights reserved. +endif + +# +# Create dependency lists based on the files available +# + + +CCOPT_DEPENDS = \ + $(APR_WORK)\build\NWGNUhead.inc \ + $(APR_WORK)\build\NWGNUenvironment.inc \ + $(APR_WORK)\build\NWGNUtail.inc \ + NWGNUmakefile \ + $(CUSTOM_INI) \ + $(EOLIST) + +CPPOPT_DEPENDS = \ + $(APR_WORK)\build\NWGNUhead.inc \ + $(APR_WORK)\build\NWGNUenvironment.inc \ + $(APR_WORK)\build\NWGNUtail.inc \ + NWGNUmakefile \ + $(CUSTOM_INI) \ + $(EOLIST) + +$(NLM_NAME)_LINKOPT_DEPENDS = \ + $(TARGET_lib) \ + $(APR_WORK)\build\NWGNUenvironment.inc \ + NWGNUmakefile \ + $(APR_WORK)\build\NWGNUtail.inc \ + $(CUSTOM_INI) \ + $(VERSION_INC) \ + $(EOLIST) + +ifeq "$(words $(strip $(TARGET_lib)))" "1" +LIB_NAME = $(basename $(notdir $(TARGET_lib))) +$(LIB_NAME)_LIBLST_DEPENDS = \ + $(FILES_lib_objs) \ + $(APR_WORK)\build\NWGNUenvironment.inc \ + NWGNUmakefile \ + $(APR_WORK)\build\NWGNUtail.inc \ + $(CUSTOM_INI) \ + $(EOLIST) +endif + +ifeq "$(wildcard NWGNU$(LIB_NAME))" "NWGNU$(LIB_NAME)" +$(LIB_NAME)_LIBLST_DEPENDS += NWGNU$(LIB_NAME) +endif + +ifeq "$(wildcard NWGNU$(NLM_NAME))" "NWGNU$(NLM_NAME)" +$(NLM_NAME)_LINKOPT_DEPENDS += NWGNU$(NLM_NAME) +CCOPT_DEPENDS += NWGNU$(NLM_NAME) +CPPOPT_DEPENDS += NWGNU$(NLM_NAME) +endif + +# +# Generic compiler rules +# + +$(APR_WORK)\build\NWGNUversion.inc : $(APR_WORK)\include\apr_version.h $(APR_WORK)\build\nw_ver.awk + @echo Generating $(subst /,\,$@) + awk -f $(APR_WORK)\build\nw_ver.awk $(APR_WORK)\include\apr_version.h > $(APR_WORK)\build\NWGNUversion.inc + +-include $(APR_WORK)\build\NWGNUversion.inc + +ifneq "$(strip $(VERSION_STR))" "" +VERSION_INC = $(APR_WORK)\build\NWGNUversion.inc +else +VERSION = 1,0,0 +VERSION_STR = 1.0.0 +endif + +ifeq "$(words $(strip $(TARGET_nlm)))" "1" +INCLUDE_BLDCMDS=1 +endif + +ifeq "$(words $(strip $(TARGET_lib)))" "1" +INCLUDE_BLDCMDS=1 +endif + +ifeq "$(INCLUDE_BLDCMDS)" "1" + +$(OBJDIR)/%.o: %.c $(OBJDIR)\$(NLM_NAME)_cc.opt + @echo Compiling $< + $(CC) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\$(NLM_NAME)_cc.opt + +$(OBJDIR)\$(NLM_NAME)_cc.opt: $(CCOPT_DEPENDS) + @echo CCOPT_DEPENDS=$(CCOPT_DEPENDS) + $(CHK) $@ $(DEL) $@ + @echo Generating $@ +ifneq "$(strip $(CFLAGS))" "" + @echo $(CFLAGS) >> $@ +endif +ifneq "$(strip $(XCFLAGS))" "" + @echo $(XCFLAGS) >> $@ +endif +ifneq "$(strip $(XINCDIRS))" "" + @echo $(foreach xincdir,$(strip $(subst ;,$(SPACE),$(XINCDIRS))),-I$(xincdir)) >> $@ +endif +ifneq "$(strip $(INCDIRS))" "" + @echo $(foreach incdir,$(strip $(subst ;,$(SPACE),$(INCDIRS))),-I$(incdir)) >> $@ +endif +ifneq "$(strip $(DEFINES))" "" + @echo $(DEFINES) >> $@ +endif +ifneq "$(strip $(XDEFINES))" "" + @echo $(XDEFINES) >> $@ +endif + +$(OBJDIR)/%.o: %.cpp $(OBJDIR)\cpp.opt + @echo Compiling $< + $(CPP) $< -o=$(OBJDIR)\$(@F) @$(OBJDIR)\cpp.opt + +$(OBJDIR)\cpp.opt: $(CPPOPT_DEPENDS) + $(CHK) $@ $(DEL) $@ + @echo Generating $@ +ifneq "$(strip $(CFLAGS))" "" + @echo $(CFLAGS) >> $@ +endif +ifneq "$(strip $(XCFLAGS))" "" + @echo $(XCFLAGS) >> $@ +endif +ifneq "$(strip $(XINCDIRS))" "" + @echo $(foreach xincdir,$(strip $(subst ;,$(SPACE),$(XINCDIRS))),-I$(xincdir)) >> $@ +endif +ifneq "$(strip $(INCDIRS))" "" + @echo $(foreach incdir,$(strip $(subst ;,$(SPACE),$(INCDIRS))),-I$(incdir)) >> $@ +endif +ifneq "$(strip $(DEFINES))" "" + @echo $(DEFINES) >> $@ +endif +ifneq "$(strip $(XDEFINES))" "" + @echo $(XDEFINES) >> $@ +endif + +endif # one target nlm + +# +# Rules to build libraries +# + +# If we only have one target library then build it + +ifeq "$(words $(strip $(TARGET_lib)))" "1" + +$(TARGET_lib) : $(OBJDIR)\$(LIB_NAME)_lib.lst + @echo Generating $@ + $(CHK) $(OBJDIR)\$(@F) $(DEL) $(OBJDIR)\$(@F) + $(LIB) -o $(OBJDIR)\$(@F) @$? + +$(OBJDIR)\$(LIB_NAME)_lib.lst: $($(LIB_NAME)_LIBLST_DEPENDS) + $(CHK) $@ $(DEL) $@ + @echo Generating $@ +ifneq "$(strip $(FILES_lib_objs))" "" + @echo $(foreach objfile,$(FILES_lib_objs),$(subst /,\,$(objfile)) ) >> $@ +endif + +else # We must have more than one target library so load the individual makefiles + +$(OBJDIR)/%.lib: NWGNU% $(APR_WORK)\build\NWGNUhead.inc $(APR_WORK)\build\NWGNUtail.inc $(APR_WORK)\build\NWGNUenvironment.inc FORCE + @echo Calling $< + $(MAKE) -f $< $(MAKECMDGOALS) RELEASE=$(RELEASE) + +endif + +# +# Rules to build nlms. +# + +vpath libcpre.o $(NOVELLLIBC)\imports + +# If we only have one target NLM then build it +ifeq "$(words $(strip $(TARGET_nlm)))" "1" + +$(TARGET_nlm) : $(FILES_nlm_objs) $(FILES_nlm_libs) $(OBJDIR)\$(NLM_NAME)_link.opt + @echo Linking $@ + $(LINK) @$(OBJDIR)\$(NLM_NAME)_link.opt + +# This will force the link option file to be rebuilt if we change the +# corresponding makefile + +$(OBJDIR)\$(NLM_NAME)_link.opt : $($(NLM_NAME)_LINKOPT_DEPENDS) + $(CHK) $(OBJDIR)\$(@F) $(DEL) $(OBJDIR)\$(@F) + $(CHK) $(OBJDIR)\$(NLM_NAME)_link.def $(DEL) $(OBJDIR)\$(NLM_NAME)_link.def + @echo Generating $@ + @echo -warnings off >> $@ + @echo -zerobss >> $@ + @echo -desc "$(NLM_DESCRIPTION)" >> $@ + @echo -o $(TARGET_nlm) >> $@ +ifneq "$(FILE_nlm_copyright)" "" + @-type $(FILE_nlm_copyright) >> $@ +else + @echo -copy "$(NLM_COPYRIGHT)" >> $@ +endif +ifeq "$(RELEASE)" "debug" + @echo -g >> $@ + @echo -sym internal >> $@ + @echo -sym codeview4 >> $@ + @echo -osym $(OBJDIR)\$(NLM_NAME).sym >> $@ +else + @echo -sym internal >> $@ +endif + @echo -screenname "$(NLM_SCREEN_NAME)" >> $@ +ifneq "$(NLM_VERSION)" "" + @echo -nlmversion=$(NLM_VERSION) >> $@ +else + @echo -nlmversion=$(VERSION) >> $@ +endif + @echo -l $(APR)/$(OBJDIR) >> $@ + @echo -l $(APRUTIL)/$(OBJDIR) >> $@ + @echo -l $(APULDAP)/$(OBJDIR) >> $@ + @echo -l $(XML)/$(OBJDIR) >> $@ + @echo -l "$(METROWERKS)/Novell Support/Metrowerks Support/Libraries/Runtime" >> $@ + @echo -l "$(METROWERKS)/Novell Support/Metrowerks Support/Libraries/MSL C++" >> $@ +ifneq "$(IPV6)" "" + @echo -l $(NOVELLLIBC)\include\winsock\IPV6 >> $@ +endif + @echo -l $(NOVELLLIBC)/imports >> $@ +ifneq "$(LDAPSDK)" "" + @echo -l $(LDAPSDK)/lib/nlm >> $@ +endif + @echo -nodefaults >> $@ + @echo -map $(OBJDIR)\$(NLM_NAME).map>> $@ + @echo -threadname "$(NLM_THREAD_NAME)" >> $@ +ifneq "$(NLM_STACK_SIZE)" "" + @echo -stacksize $(subst K,000,$(subst k,K,$(strip $(NLM_STACK_SIZE)))) >> $@ +else + @echo -stacksize 64000 >> $@ +endif +ifneq "$(NLM_ENTRY_SYM)" "" + @echo -entry $(NLM_ENTRY_SYM) >> $@ +endif +ifneq "$(NLM_EXIT_SYM)" "" + @echo -exit $(NLM_EXIT_SYM) >> $@ +endif +ifneq "$(NLM_CHECK_SYM)" "" + @echo -check $(NLM_CHECK_SYM) >> $@ +endif +ifneq "$(NLM_FLAGS)" "" + @echo -flags $(NLM_FLAGS) >> $@ +endif +ifneq "$(strip $(XLFLAGS))" "" + @echo $(XLFLAGS) >> $@ +endif +ifneq "$(strip $(FILES_nlm_objs))" "" + @echo $(foreach objfile,$(strip $(FILES_nlm_objs)),$(subst /,\,$(objfile))) >> $@ +endif +ifneq "$(FILES_nlm_libs)" "" + @echo $(foreach libfile, $(notdir $(strip $(FILES_nlm_libs))),-l$(subst /,\,$(libfile))) >> $@ +endif + @echo -commandfile $(OBJDIR)\$(NLM_NAME)_link.def >> $@ +ifneq "$(FILE_nlm_msg)" "" + @echo Messages $(FILE_nlm_msg) >> $(OBJDIR)\$(NLM_NAME)_link.def +endif +ifneq "$(FILE_nlm_hlp)" "" + @echo Help $(FILE_nlm_hlp) >> $(OBJDIR)\$(NLM_NAME)_link.def +endif +ifneq "$(FILES_nlm_modules)" "" + @echo module $(foreach module,$(subst $(SPACE),$(COMMA),$(strip $(FILES_nlm_modules))),$(subst /,\,$(module))) >> $(OBJDIR)\$(NLM_NAME)_link.def +endif +ifneq "$(FILES_nlm_Ximports)" "" + @echo Import $(foreach import,$(subst $(SPACE),$(COMMA),$(strip $(FILES_nlm_Ximports))),$(subst /,\,$(import))) >> $(OBJDIR)\$(NLM_NAME)_link.def +endif +ifneq "$(FILES_nlm_exports)" "" + @echo Export $(foreach export,$(subst $(SPACE),$(COMMA),$(strip $(FILES_nlm_exports))),$(subst /,\,$(export))) >> $(OBJDIR)\$(NLM_NAME)_link.def +endif + +# if APACHE_UNIPROC is defined, don't include XDCData +ifndef APACHE_UNIPROC +ifneq "$(string $(XDCDATA))" "" + @echo XDCData $(XDCDATA) >> $(OBJDIR)\$(NLM_NAME)_link.def +else + @echo XDCData $(APR)\misc\netware\apr.xdc >> $(OBJDIR)\$(NLM_NAME)_link.def +endif +endif + +else # more than one target so look for individual makefiles. + +# Only include these if NO_LICENSE_FILE isn't set to prevent excessive +# recursion + +ifndef NO_LICENSE_FILE + +$(OBJDIR)/%.nlm: NWGNU% $(APR_WORK)\build\NWGNUhead.inc $(APR_WORK)\build\NWGNUtail.inc $(APR_WORK)\build\NWGNUenvironment.inc $(CUSTOM_INI) $(VERSION_INC) FORCE + @echo Calling $< + $(MAKE) -f $< $(MAKECMDGOALS) RELEASE=$(RELEASE) + $(CMD) echo. + +else + +$(TARGET_nlm): + +endif # NO_LICENSE_FILE + +endif # multiple targets + diff --git a/srclib/apr/build/PrintPath b/srclib/apr/build/PrintPath new file mode 100755 index 0000000000..0e512250f9 --- /dev/null +++ b/srclib/apr/build/PrintPath @@ -0,0 +1,129 @@ +#!/bin/sh +# +# Copyright 1999-2004 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# +# Look for program[s] somewhere in $PATH. +# +# Options: +# -s +# Do not print out full pathname. (silent) +# -pPATHNAME +# Look in PATHNAME instead of $PATH +# +# Usage: +# PrintPath [-s] [-pPATHNAME] program [program ...] +# +# Initially written by Jim Jagielski for the Apache configuration mechanism +# (with kudos to Kernighan/Pike) + +## +# Some "constants" +## +pathname=$PATH +echo="yes" + +## +# Find out what OS we are running for later on +## +os=`(uname) 2>/dev/null` + +## +# Parse command line +## +for args in $* +do + case $args in + -s ) echo="no" ;; + -p* ) pathname="`echo $args | sed 's/^..//'`" ;; + * ) programs="$programs $args" ;; + esac +done + +## +# Now we make the adjustments required for OS/2 and everyone +# else :) +# +# First of all, all OS/2 programs have the '.exe' extension. +# Next, we adjust PATH (or what was given to us as PATH) to +# be whitespace separated directories. +# Finally, we try to determine the best flag to use for +# test/[] to look for an executable file. OS/2 just has '-r' +# but with other OSs, we do some funny stuff to check to see +# if test/[] knows about -x, which is the prefered flag. +## + +if [ "x$os" = "xOS/2" ] +then + ext=".exe" + pathname=`echo -E $pathname | + sed 's/^;/.;/ + s/;;/;.;/g + s/;$/;./ + s/;/ /g + s/\\\\/\\//g' ` + test_exec_flag="-r" +else + ext="" # No default extensions + pathname=`echo $pathname | + sed 's/^:/.:/ + s/::/:.:/g + s/:$/:./ + s/:/ /g' ` + # Here is how we test to see if test/[] can handle -x + testfile="pp.t.$$" + + cat > $testfile </dev/null`; then + test_exec_flag="-x" + else + test_exec_flag="-r" + fi + rm -f $testfile +fi + +for program in $programs +do + for path in $pathname + do + if [ $test_exec_flag $path/${program}${ext} ] && \ + [ ! -d $path/${program}${ext} ]; then + if [ "x$echo" = "xyes" ]; then + echo $path/${program}${ext} + fi + exit 0 + fi + +# Next try without extension (if one was used above) + if [ "x$ext" != "x" ]; then + if [ $test_exec_flag $path/${program} ] && \ + [ ! -d $path/${program} ]; then + if [ "x$echo" = "xyes" ]; then + echo $path/${program} + fi + exit 0 + fi + fi + done +done +exit 1 + diff --git a/srclib/apr/build/aplibtool.c b/srclib/apr/build/aplibtool.c new file mode 100644 index 0000000000..22a316ace1 --- /dev/null +++ b/srclib/apr/build/aplibtool.c @@ -0,0 +1,755 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +typedef char bool; +#define false 0 +#define true (!false) + +bool silent = false; +bool shared = false; +bool export_all = false; +enum mode_t { mCompile, mLink, mInstall }; +enum output_type_t { otGeneral, otObject, otProgram, otStaticLibrary, otDynamicLibrary }; + +#ifdef __EMX__ +# define SHELL_CMD "sh" +# define CC "gcc" +# define GEN_EXPORTS "emxexp" +# define DEF2IMPLIB_CMD "emximp" +# define SHARE_SW "-Zdll -Zmtd" +# define USE_OMF true +# define TRUNCATE_DLL_NAME +# define DYNAMIC_LIB_EXT "dll" +# define EXE_EXT ".exe" + +# if USE_OMF + /* OMF is the native format under OS/2 */ +# define STATIC_LIB_EXT "lib" +# define OBJECT_EXT "obj" +# define LIBRARIAN "emxomfar" +# else + /* but the alternative, a.out, can fork() which is sometimes necessary */ +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# endif +#endif + + +typedef struct { + char *arglist[1024]; + int num_args; + enum mode_t mode; + enum output_type_t output_type; + char *output_name; + char *stub_name; + char *tmp_dirs[1024]; + int num_tmp_dirs; + char *obj_files[1024]; + int num_obj_files; +} cmd_data_t; + +void parse_args(int argc, char *argv[], cmd_data_t *cmd_data); +bool parse_long_opt(char *arg, cmd_data_t *cmd_data); +int parse_short_opt(char *arg, cmd_data_t *cmd_data); +bool parse_input_file_name(char *arg, cmd_data_t *cmd_data); +bool parse_output_file_name(char *arg, cmd_data_t *cmd_data); +void post_parse_fixup(cmd_data_t *cmd_data); +bool explode_static_lib(char *lib, cmd_data_t *cmd_data); +int execute_command(cmd_data_t *cmd_data); +char *shell_esc(const char *str); +void cleanup_tmp_dirs(cmd_data_t *cmd_data); +void generate_def_file(cmd_data_t *cmd_data); +char *nameof(char *fullpath); +char *truncate_dll_name(char *path); + + +int main(int argc, char *argv[]) +{ + int rc; + cmd_data_t cmd_data; + + memset(&cmd_data, 0, sizeof(cmd_data)); + cmd_data.mode = mCompile; + cmd_data.output_type = otGeneral; + + parse_args(argc, argv, &cmd_data); + rc = execute_command(&cmd_data); + + if (rc == 0 && cmd_data.stub_name) { + fopen(cmd_data.stub_name, "w"); + } + + cleanup_tmp_dirs(&cmd_data); + return rc; +} + + + +void parse_args(int argc, char *argv[], cmd_data_t *cmd_data) +{ + int a; + char *arg; + bool argused; + + for (a=1; a < argc; a++) { + arg = argv[a]; + argused = false; + + if (arg[0] == '-') { + if (arg[1] == '-') { + argused = parse_long_opt(arg + 2, cmd_data); + } else if (arg[1] == 'o' && a+1 < argc) { + cmd_data->arglist[cmd_data->num_args++] = arg; + arg = argv[++a]; + argused = parse_output_file_name(arg, cmd_data); + } else { + int num_used = parse_short_opt(arg + 1, cmd_data); + argused = num_used > 0; + + if (num_used > 1) { + a += num_used - 1; + } + } + } else { + argused = parse_input_file_name(arg, cmd_data); + } + + if (!argused) { + cmd_data->arglist[cmd_data->num_args++] = arg; + } + } + + post_parse_fixup(cmd_data); +} + + + +bool parse_long_opt(char *arg, cmd_data_t *cmd_data) +{ + char *equal_pos = strchr(arg, '='); + char var[50]; + char value[500]; + + if (equal_pos) { + strncpy(var, arg, equal_pos - arg); + var[equal_pos - arg] = 0; + strcpy(value, equal_pos + 1); + } else { + strcpy(var, arg); + } + + if (strcmp(var, "silent") == 0) { + silent = true; + } else if (strcmp(var, "mode") == 0) { + if (strcmp(value, "compile") == 0) { + cmd_data->mode = mCompile; + cmd_data->output_type = otObject; + } + + if (strcmp(value, "link") == 0) { + cmd_data->mode = mLink; + } + + if (strcmp(value, "install") == 0) { + cmd_data->mode = mInstall; + } + } else if (strcmp(var, "shared") == 0) { + shared = true; + } else if (strcmp(var, "export-all") == 0) { + export_all = true; + } else { + return false; + } + + return true; +} + + + +int parse_short_opt(char *arg, cmd_data_t *cmd_data) +{ + if (strcmp(arg, "export-dynamic") == 0) { + return 1; + } + + if (strcmp(arg, "module") == 0) { + return 1; + } + + if (strcmp(arg, "Zexe") == 0) { + return 1; + } + + if (strcmp(arg, "avoid-version") == 0) { + return 1; + } + + if (strcmp(arg, "prefer-pic") == 0) { + return 1; + } + + if (strcmp(arg, "prefer-non-pic") == 0) { + return 1; + } + + if (strcmp(arg, "version-info") == 0 ) { + return 2; + } + + if (strcmp(arg, "no-install") == 0) { + return 1; + } + + return 0; +} + + + +bool parse_input_file_name(char *arg, cmd_data_t *cmd_data) +{ + char *ext = strrchr(arg, '.'); + char *name = strrchr(arg, '/'); + int pathlen; + char *newarg; + + if (!ext) { + return false; + } + + ext++; + + if (name == NULL) { + name = strrchr(arg, '\\'); + + if (name == NULL) { + name = arg; + } else { + name++; + } + } else { + name++; + } + + pathlen = name - arg; + + if (strcmp(ext, "lo") == 0) { + newarg = (char *)malloc(strlen(arg) + 10); + strcpy(newarg, arg); + strcpy(newarg + (ext - arg), OBJECT_EXT); + cmd_data->arglist[cmd_data->num_args++] = newarg; + cmd_data->obj_files[cmd_data->num_obj_files++] = newarg; + return true; + } + + if (strcmp(ext, "la") == 0) { + newarg = (char *)malloc(strlen(arg) + 10); + strcpy(newarg, arg); + newarg[pathlen] = 0; + strcat(newarg, ".libs/"); + + if (strncmp(name, "lib", 3) == 0) { + name += 3; + } + + strcat(newarg, name); + ext = strrchr(newarg, '.') + 1; + + if (shared && cmd_data->mode == mInstall) { + strcpy(ext, DYNAMIC_LIB_EXT); + newarg = truncate_dll_name(newarg); + } else { + strcpy(ext, STATIC_LIB_EXT); + } + + cmd_data->arglist[cmd_data->num_args++] = newarg; + return true; + } + + if (strcmp(ext, "c") == 0) { + if (cmd_data->stub_name == NULL) { + cmd_data->stub_name = (char *)malloc(strlen(arg) + 4); + strcpy(cmd_data->stub_name, arg); + strcpy(strrchr(cmd_data->stub_name, '.') + 1, "lo"); + } + } + + if (strcmp(name, CC) == 0 || strcmp(name, CC EXE_EXT) == 0) { + if (cmd_data->output_type == otGeneral) { + cmd_data->output_type = otObject; + } + } + + return false; +} + + + +bool parse_output_file_name(char *arg, cmd_data_t *cmd_data) +{ + char *name = strrchr(arg, '/'); + char *ext = strrchr(arg, '.'); + char *newarg = NULL, *newext; + int pathlen; + + if (name == NULL) { + name = strrchr(arg, '\\'); + + if (name == NULL) { + name = arg; + } else { + name++; + } + } else { + name++; + } + + if (!ext) { + cmd_data->stub_name = arg; + cmd_data->output_type = otProgram; + newarg = (char *)malloc(strlen(arg) + 5); + strcpy(newarg, arg); + strcat(newarg, EXE_EXT); + cmd_data->arglist[cmd_data->num_args++] = newarg; + cmd_data->output_name = newarg; + return true; + } + + ext++; + pathlen = name - arg; + + if (strcmp(ext, "la") == 0) { + cmd_data->stub_name = arg; + cmd_data->output_type = shared ? otDynamicLibrary : otStaticLibrary; + newarg = (char *)malloc(strlen(arg) + 10); + mkdir(".libs", 0); + strcpy(newarg, ".libs/"); + + if (strncmp(arg, "lib", 3) == 0) { + arg += 3; + } + + strcat(newarg, arg); + newext = strrchr(newarg, '.') + 1; + strcpy(newext, shared ? DYNAMIC_LIB_EXT : STATIC_LIB_EXT); + +#ifdef TRUNCATE_DLL_NAME + if (shared) { + newarg = truncate_dll_name(newarg); + } +#endif + + cmd_data->arglist[cmd_data->num_args++] = newarg; + cmd_data->output_name = newarg; + return true; + } + + if (strcmp(ext, "lo") == 0) { + cmd_data->stub_name = arg; + cmd_data->output_type = otObject; + newarg = (char *)malloc(strlen(arg) + 2); + strcpy(newarg, arg); + ext = strrchr(newarg, '.') + 1; + strcpy(ext, OBJECT_EXT); + cmd_data->arglist[cmd_data->num_args++] = newarg; + cmd_data->output_name = newarg; + return true; + } + + return false; +} + + + +void post_parse_fixup(cmd_data_t *cmd_data) +{ + int a; + char *arg; + char *ext; + + if (cmd_data->output_type == otStaticLibrary && cmd_data->mode == mLink) { + /* We do a real hatchet job on the args when making a static library + * removing all compiler switches & any other cruft that ar won't like + * We also need to explode any libraries listed + */ + + for (a=0; a < cmd_data->num_args; a++) { + arg = cmd_data->arglist[a]; + + if (arg) { + ext = strrchr(arg, '.'); + + if (ext) { + ext++; + } + + if (arg[0] == '-') { + cmd_data->arglist[a] = NULL; + + if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) { + cmd_data->arglist[a+1] = NULL; + } + + if (strcmp(arg, "-R") == 0 && a+1 < cmd_data->num_args) { + cmd_data->arglist[a+1] = NULL; + } + + if (strcmp(arg, "-version-info") == 0 && a+1 < cmd_data->num_args) { + cmd_data->arglist[a+1] = NULL; + } + + if (strcmp(arg, "-Zstack") == 0 && a+1 < cmd_data->num_args) { + cmd_data->arglist[a+1] = NULL; + } + + if (strcmp(arg, "-o") == 0) { + a++; + } + } + + if (strcmp(arg, CC) == 0 || strcmp(arg, CC EXE_EXT) == 0) { + cmd_data->arglist[a] = LIBRARIAN " cr"; + } + + if (ext) { + if (strcmp(ext, "h") == 0 || strcmp(ext, "c") == 0) { + /* ignore source files, they don't belong in a library */ + cmd_data->arglist[a] = NULL; + } + + if (strcmp(ext, STATIC_LIB_EXT) == 0) { + cmd_data->arglist[a] = NULL; + explode_static_lib(arg, cmd_data); + } + } + } + } + } + + if (cmd_data->output_type == otDynamicLibrary) { + for (a=0; a < cmd_data->num_args; a++) { + arg = cmd_data->arglist[a]; + + if (arg) { + if (strcmp(arg, "-rpath") == 0 && a+1 < cmd_data->num_args) { + cmd_data->arglist[a] = NULL; + cmd_data->arglist[a+1] = NULL; + } + } + } + + if (export_all) { + generate_def_file(cmd_data); + } + } + +#if USE_OMF + if (cmd_data->output_type == otObject || + cmd_data->output_type == otProgram || + cmd_data->output_type == otDynamicLibrary) { + cmd_data->arglist[cmd_data->num_args++] = "-Zomf"; + } +#endif + + if (shared && (cmd_data->output_type == otObject || cmd_data->output_type == otDynamicLibrary)) { + cmd_data->arglist[cmd_data->num_args++] = SHARE_SW; + } +} + + + +int execute_command(cmd_data_t *cmd_data) +{ + int target = 0; + char *command; + int a, total_len = 0; + char *args[4]; + + for (a=0; a < cmd_data->num_args; a++) { + if (cmd_data->arglist[a]) { + total_len += strlen(cmd_data->arglist[a]) + 1; + } + } + + command = (char *)malloc( total_len ); + command[0] = 0; + + for (a=0; a < cmd_data->num_args; a++) { + if (cmd_data->arglist[a]) { + strcat(command, cmd_data->arglist[a]); + strcat(command, " "); + } + } + + command[strlen(command)-1] = 0; + + if (!silent) { + puts(command); + } + + cmd_data->num_args = target; + cmd_data->arglist[cmd_data->num_args] = NULL; + command = shell_esc(command); + + args[0] = SHELL_CMD; + args[1] = "-c"; + args[2] = command; + args[3] = NULL; + return spawnvp(P_WAIT, args[0], args); +} + + + +char *shell_esc(const char *str) +{ + char *cmd; + unsigned char *d; + const unsigned char *s; + + cmd = (char *)malloc(2 * strlen(str) + 1); + d = (unsigned char *)cmd; + s = (const unsigned char *)str; + + for (; *s; ++s) { + if (*s == '"' || *s == '\\') { + *d++ = '\\'; + } + *d++ = *s; + } + + *d = '\0'; + return cmd; +} + + + +bool explode_static_lib(char *lib, cmd_data_t *cmd_data) +{ + char tmpdir[1024]; + char savewd[1024]; + char cmd[1024]; + char *name; + DIR *dir; + struct dirent *entry; + + strcpy(tmpdir, lib); + strcat(tmpdir, ".exploded"); + + mkdir(tmpdir, 0); + cmd_data->tmp_dirs[cmd_data->num_tmp_dirs++] = strdup(tmpdir); + getcwd(savewd, sizeof(savewd)); + + if (chdir(tmpdir) != 0) + return false; + + strcpy(cmd, LIBRARIAN " x "); + name = strrchr(lib, '/'); + + if (name) { + name++; + } else { + name = lib; + } + + strcat(cmd, "../"); + strcat(cmd, name); + system(cmd); + chdir(savewd); + dir = opendir(tmpdir); + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_name[0] != '.') { + strcpy(cmd, tmpdir); + strcat(cmd, "/"); + strcat(cmd, entry->d_name); + cmd_data->arglist[cmd_data->num_args++] = strdup(cmd); + } + } + + closedir(dir); + return true; +} + + + +void cleanup_tmp_dir(char *dirname) +{ + DIR *dir; + struct dirent *entry; + char fullname[1024]; + + dir = opendir(dirname); + + if (dir == NULL) + return; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_name[0] != '.') { + strcpy(fullname, dirname); + strcat(fullname, "/"); + strcat(fullname, entry->d_name); + remove(fullname); + } + } + + rmdir(dirname); +} + + + +void cleanup_tmp_dirs(cmd_data_t *cmd_data) +{ + int d; + + for (d=0; d < cmd_data->num_tmp_dirs; d++) { + cleanup_tmp_dir(cmd_data->tmp_dirs[d]); + } +} + + + +void generate_def_file(cmd_data_t *cmd_data) +{ + char def_file[1024]; + char implib_file[1024]; + char *ext; + FILE *hDef; + char *export_args[1024]; + int num_export_args = 0; + char *cmd; + int cmd_size = 0; + int a; + + if (cmd_data->output_name) { + strcpy(def_file, cmd_data->output_name); + strcat(def_file, ".def"); + hDef = fopen(def_file, "w"); + + if (hDef != NULL) { + fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name)); + fprintf(hDef, "DATA NONSHARED\n"); + fprintf(hDef, "EXPORTS\n"); + fclose(hDef); + + for (a=0; a < cmd_data->num_obj_files; a++) { + cmd_size += strlen(cmd_data->obj_files[a]) + 1; + } + + cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3; + cmd = (char *)malloc(cmd_size); + strcpy(cmd, GEN_EXPORTS); + + for (a=0; a < cmd_data->num_obj_files; a++) { + strcat(cmd, " "); + strcat(cmd, cmd_data->obj_files[a] ); + } + + strcat(cmd, ">>"); + strcat(cmd, def_file); + puts(cmd); + export_args[num_export_args++] = SHELL_CMD; + export_args[num_export_args++] = "-c"; + export_args[num_export_args++] = cmd; + export_args[num_export_args++] = NULL; + spawnvp(P_WAIT, export_args[0], export_args); + cmd_data->arglist[cmd_data->num_args++] = strdup(def_file); + + /* Now make an import library for the dll */ + num_export_args = 0; + export_args[num_export_args++] = DEF2IMPLIB_CMD; + export_args[num_export_args++] = "-o"; + + strcpy(implib_file, ".libs/"); + strcat(implib_file, cmd_data->stub_name); + ext = strrchr(implib_file, '.'); + + if (ext) + *ext = 0; + + strcat(implib_file, "."); + strcat(implib_file, STATIC_LIB_EXT); + + export_args[num_export_args++] = implib_file; + export_args[num_export_args++] = def_file; + export_args[num_export_args++] = NULL; + spawnvp(P_WAIT, export_args[0], export_args); + } + } +} + + + +/* returns just a file's name without path or extension */ +char *nameof(char *fullpath) +{ + char buffer[1024]; + char *ext; + char *name = strrchr(fullpath, '/'); + + if (name == NULL) { + name = strrchr(fullpath, '\\'); + } + + if (name == NULL) { + name = fullpath; + } else { + name++; + } + + strcpy(buffer, name); + ext = strrchr(buffer, '.'); + + if (ext) { + *ext = 0; + return strdup(buffer); + } + + return name; +} + + + +char *truncate_dll_name(char *path) +{ + /* Cut DLL name down to 8 characters after removing any mod_ prefix */ + char *tmppath = strdup(path); + char *newname = strrchr(tmppath, '/') + 1; + char *ext = strrchr(tmppath, '.'); + int len; + + if (ext == NULL) + return tmppath; + + len = ext - newname; + + if (strncmp(newname, "mod_", 4) == 0) { + strcpy(newname, newname + 4); + len -= 4; + } + + if (len > 8) { + strcpy(newname + 8, strchr(newname, '.')); + } + + return tmppath; +} diff --git a/srclib/apr/build/apr_app.dsp b/srclib/apr/build/apr_app.dsp new file mode 100644 index 0000000000..a919872e2a --- /dev/null +++ b/srclib/apr/build/apr_app.dsp @@ -0,0 +1,89 @@ +# Microsoft Developer Studio Project File - Name="apr_app" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=apr_app - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "apr_app.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "apr_app.mak" CFG="apr_app - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "apr_app - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "apr_app - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "apr_app - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "LibR" +# PROP BASE Intermediate_Dir "LibR" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "LibR" +# PROP Intermediate_Dir "LibR" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../include" /I "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /D "APR_DECLARE_STATIC" /Fd"LibR\apr_app_src" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"LibR\apr_app-1.lib" + +!ELSEIF "$(CFG)" == "apr_app - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "LibD" +# PROP BASE Intermediate_Dir "LibD" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "LibD" +# PROP Intermediate_Dir "LibD" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../include" /I "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /D "APR_DECLARE_STATIC" /Fd"LibD\apr_app_src" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"LibD\apr_app-1.lib" + +!ENDIF + +# Begin Target + +# Name "apr_app - Win32 Release" +# Name "apr_app - Win32 Debug" +# Begin Source File + +SOURCE=..\misc\win32\apr_app.c +# End Source File +# End Target +# End Project diff --git a/srclib/apr/build/apr_common.m4 b/srclib/apr/build/apr_common.m4 new file mode 100644 index 0000000000..8298022abb --- /dev/null +++ b/srclib/apr/build/apr_common.m4 @@ -0,0 +1,954 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Copyright 2000-2005 The Apache Software Foundation +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl +dnl apr_common.m4: APR's general-purpose autoconf macros +dnl + +dnl +dnl APR_CONFIG_NICE(filename) +dnl +dnl Saves a snapshot of the configure command-line for later reuse +dnl +AC_DEFUN(APR_CONFIG_NICE,[ + rm -f $1 + cat >$1<> $1 + fi + if test -n "$CFLAGS"; then + echo "CFLAGS=\"$CFLAGS\"; export CFLAGS" >> $1 + fi + if test -n "$CPPFLAGS"; then + echo "CPPFLAGS=\"$CPPFLAGS\"; export CPPFLAGS" >> $1 + fi + if test -n "$LDFLAGS"; then + echo "LDFLAGS=\"$LDFLAGS\"; export LDFLAGS" >> $1 + fi + if test -n "$LTFLAGS"; then + echo "LTFLAGS=\"$LTFLAGS\"; export LTFLAGS" >> $1 + fi + if test -n "$LIBS"; then + echo "LIBS=\"$LIBS\"; export LIBS" >> $1 + fi + if test -n "$INCLUDES"; then + echo "INCLUDES=\"$INCLUDES\"; export INCLUDES" >> $1 + fi + if test -n "$NOTEST_CFLAGS"; then + echo "NOTEST_CFLAGS=\"$NOTEST_CFLAGS\"; export NOTEST_CFLAGS" >> $1 + fi + if test -n "$NOTEST_CPPFLAGS"; then + echo "NOTEST_CPPFLAGS=\"$NOTEST_CPPFLAGS\"; export NOTEST_CPPFLAGS" >> $1 + fi + if test -n "$NOTEST_LDFLAGS"; then + echo "NOTEST_LDFLAGS=\"$NOTEST_LDFLAGS\"; export NOTEST_LDFLAGS" >> $1 + fi + if test -n "$NOTEST_LIBS"; then + echo "NOTEST_LIBS=\"$NOTEST_LIBS\"; export NOTEST_LIBS" >> $1 + fi + + for arg in [$]0 "[$]@"; do + APR_EXPAND_VAR(arg, $arg) + echo "\"[$]arg\" \\" >> $1 + done + echo '"[$]@"' >> $1 + chmod +x $1 +])dnl + +dnl APR_MKDIR_P_CHECK(fallback-mkdir-p) +dnl checks whether mkdir -p works +AC_DEFUN(APR_MKDIR_P_CHECK,[ + AC_CACHE_CHECK(for working mkdir -p, ac_cv_mkdir_p,[ + test -d conftestdir && rm -rf conftestdir + mkdir -p conftestdir/somedir >/dev/null 2>&1 + if test -d conftestdir/somedir; then + ac_cv_mkdir_p=yes + else + ac_cv_mkdir_p=no + fi + rm -rf conftestdir + ]) + if test "$ac_cv_mkdir_p" = "yes"; then + mkdir_p="mkdir -p" + else + mkdir_p="$1" + fi +]) + +dnl +dnl APR_SUBDIR_CONFIG(dir [, sub-package-cmdline-args, args-to-drop]) +dnl +dnl dir: directory to find configure in +dnl sub-package-cmdline-args: arguments to add to the invocation (optional) +dnl args-to-drop: arguments to drop from the invocation (optional) +dnl +dnl Note: This macro relies on ac_configure_args being set properly. +dnl +dnl The args-to-drop argument is shoved into a case statement, so +dnl multiple arguments can be separated with a |. +dnl +dnl Note: Older versions of autoconf do not single-quote args, while 2.54+ +dnl places quotes around every argument. So, if you want to drop the +dnl argument called --enable-layout, you must pass the third argument as: +dnl [--enable-layout=*|\'--enable-layout=*] +dnl +dnl Trying to optimize this is left as an exercise to the reader who wants +dnl to put up with more autoconf craziness. I give up. +dnl +AC_DEFUN(APR_SUBDIR_CONFIG, [ + # save our work to this point; this allows the sub-package to use it + AC_CACHE_SAVE + + echo "configuring package in $1 now" + ac_popdir=`pwd` + apr_config_subdirs="$1" + test -d $1 || $mkdir_p $1 + ac_abs_srcdir=`(cd $srcdir/$1 && pwd)` + cd $1 + +changequote(, )dnl + # A "../" for each directory in /$config_subdirs. + ac_dots=`echo $apr_config_subdirs|sed -e 's%^\./%%' -e 's%[^/]$%&/%' -e 's%[^/]*/%../%g'` +changequote([, ])dnl + + # Make the cache file pathname absolute for the subdirs + # required to correctly handle subdirs that might actually + # be symlinks + case "$cache_file" in + /*) # already absolute + ac_sub_cache_file=$cache_file ;; + *) # Was relative path. + ac_sub_cache_file="$ac_popdir/$cache_file" ;; + esac + + ifelse($3, [], [apr_configure_args=$ac_configure_args],[ + apr_configure_args= + apr_sep= + for apr_configure_arg in $ac_configure_args + do + case "$apr_configure_arg" in + $3) + continue ;; + esac + apr_configure_args="$apr_configure_args$apr_sep'$apr_configure_arg'" + apr_sep=" " + done + ]) + + # autoconf doesn't add --silent to ac_configure_args; explicitly pass it + test "x$silent" = "xyes" && apr_configure_args="$apr_configure_args --silent" + + dnl The eval makes quoting arguments work - specifically $2 where the + dnl quoting mechanisms used is "" rather than []. + dnl + dnl We need to execute another shell because some autoconf/shell combinations + dnl will choke after doing repeated APR_SUBDIR_CONFIG()s. (Namely Solaris + dnl and autoconf-2.54+) + if eval $SHELL $ac_abs_srcdir/configure $apr_configure_args --cache-file=$ac_sub_cache_file --srcdir=$ac_abs_srcdir $2 + then : + echo "$1 configured properly" + else + echo "configure failed for $1" + exit 1 + fi + + cd $ac_popdir + + # grab any updates from the sub-package + AC_CACHE_LOAD +])dnl + +dnl +dnl APR_SAVE_THE_ENVIRONMENT(variable_name) +dnl +dnl Stores the variable (usually a Makefile macro) for later restoration +dnl +AC_DEFUN(APR_SAVE_THE_ENVIRONMENT,[ + apr_ste_save_$1="$$1" +])dnl + +dnl +dnl APR_RESTORE_THE_ENVIRONMENT(variable_name, prefix_) +dnl +dnl Uses the previously saved variable content to figure out what configure +dnl has added to the variable, moving the new bits to prefix_variable_name +dnl and restoring the original variable contents. This makes it possible +dnl for a user to override configure when it does something stupid. +dnl +AC_DEFUN(APR_RESTORE_THE_ENVIRONMENT,[ +if test "x$apr_ste_save_$1" = "x"; then + $2$1="$$1" + $1= +else + if test "x$apr_ste_save_$1" = "x$$1"; then + $2$1= + else + $2$1=`echo $$1 | sed -e "s%${apr_ste_save_$1}%%"` + $1="$apr_ste_save_$1" + fi +fi +if test "x$silent" != "xyes"; then + echo " restoring $1 to \"$$1\"" + echo " setting $2$1 to \"$$2$1\"" +fi +AC_SUBST($2$1) +])dnl + +dnl +dnl APR_SETIFNULL(variable, value) +dnl +dnl Set variable iff it's currently null +dnl +AC_DEFUN(APR_SETIFNULL,[ + if test -z "$$1"; then + test "x$silent" != "xyes" && echo " setting $1 to \"$2\"" + $1="$2" + fi +])dnl + +dnl +dnl APR_SETVAR(variable, value) +dnl +dnl Set variable no matter what +dnl +AC_DEFUN(APR_SETVAR,[ + test "x$silent" != "xyes" && echo " forcing $1 to \"$2\"" + $1="$2" +])dnl + +dnl +dnl APR_ADDTO(variable, value) +dnl +dnl Add value to variable +dnl +AC_DEFUN(APR_ADDTO,[ + if test "x$$1" = "x"; then + test "x$silent" != "xyes" && echo " setting $1 to \"$2\"" + $1="$2" + else + apr_addto_bugger="$2" + for i in $apr_addto_bugger; do + apr_addto_duplicate="0" + for j in $$1; do + if test "x$i" = "x$j"; then + apr_addto_duplicate="1" + break + fi + done + if test $apr_addto_duplicate = "0"; then + test "x$silent" != "xyes" && echo " adding \"$i\" to $1" + $1="$$1 $i" + fi + done + fi +])dnl + +dnl +dnl APR_REMOVEFROM(variable, value) +dnl +dnl Remove a value from a variable +dnl +AC_DEFUN(APR_REMOVEFROM,[ + if test "x$$1" = "x$2"; then + test "x$silent" != "xyes" && echo " nulling $1" + $1="" + else + apr_new_bugger="" + apr_removed=0 + for i in $$1; do + if test "x$i" != "x$2"; then + apr_new_bugger="$apr_new_bugger $i" + else + apr_removed=1 + fi + done + if test $apr_removed = "1"; then + test "x$silent" != "xyes" && echo " removed \"$2\" from $1" + $1=$apr_new_bugger + fi + fi +]) dnl + +dnl +dnl APR_CHECK_DEFINE_FILES( symbol, header_file [header_file ...] ) +dnl +AC_DEFUN(APR_CHECK_DEFINE_FILES,[ + AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[ + ac_cv_define_$1=no + for curhdr in $2 + do + AC_EGREP_CPP(YES_IS_DEFINED, [ +#include <$curhdr> +#ifdef $1 +YES_IS_DEFINED +#endif + ], ac_cv_define_$1=yes) + done + ]) + if test "$ac_cv_define_$1" = "yes"; then + AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined]) + fi +]) + + +dnl +dnl APR_CHECK_DEFINE(symbol, header_file) +dnl +AC_DEFUN(APR_CHECK_DEFINE,[ + AC_CACHE_CHECK([for $1 in $2],ac_cv_define_$1,[ + AC_EGREP_CPP(YES_IS_DEFINED, [ +#include <$2> +#ifdef $1 +YES_IS_DEFINED +#endif + ], ac_cv_define_$1=yes, ac_cv_define_$1=no) + ]) + if test "$ac_cv_define_$1" = "yes"; then + AC_DEFINE(HAVE_$1, 1, [Define if $1 is defined in $2]) + fi +]) + +dnl +dnl APR_CHECK_APR_DEFINE( symbol ) +dnl +AC_DEFUN(APR_CHECK_APR_DEFINE,[ +apr_old_cppflags=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $INCLUDES" +AC_EGREP_CPP(YES_IS_DEFINED, [ +#include +#if $1 +YES_IS_DEFINED +#endif +], ac_cv_define_$1=yes, ac_cv_define_$1=no) +CPPFLAGS=$apr_old_cppflags +]) + +dnl APR_CHECK_FILE(filename); set ac_cv_file_filename to +dnl "yes" if 'filename' is readable, else "no". +AC_DEFUN([APR_CHECK_FILE], [ +dnl Pick a safe variable name +define([apr_cvname], ac_cv_file_[]translit([$1], [./+-], [__p_])) +AC_CACHE_CHECK([for $1], [apr_cvname], +[if test -r $1; then + apr_cvname=yes + else + apr_cvname=no + fi]) +]) + +define(APR_IFALLYES,[dnl +ac_rc=yes +for ac_spec in $1; do + ac_type=`echo "$ac_spec" | sed -e 's/:.*$//'` + ac_item=`echo "$ac_spec" | sed -e 's/^.*://'` + case $ac_type in + header ) + ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'` + ac_var="ac_cv_header_$ac_item" + ;; + file ) + ac_item=`echo "$ac_item" | sed 'y%./+-%__p_%'` + ac_var="ac_cv_file_$ac_item" + ;; + func ) ac_var="ac_cv_func_$ac_item" ;; + struct ) ac_var="ac_cv_struct_$ac_item" ;; + define ) ac_var="ac_cv_define_$ac_item" ;; + custom ) ac_var="$ac_item" ;; + esac + eval "ac_val=\$$ac_var" + if test ".$ac_val" != .yes; then + ac_rc=no + break + fi +done +if test ".$ac_rc" = .yes; then + : + $2 +else + : + $3 +fi +]) + + +define(APR_BEGIN_DECISION,[dnl +ac_decision_item='$1' +ac_decision_msg='FAILED' +ac_decision='' +]) + + +AC_DEFUN([APR_DECIDE],[dnl +dnl Define the flag (or not) in apr_private.h via autoheader +AH_TEMPLATE($1, [Define if $2 will be used]) +ac_decision='$1' +ac_decision_msg='$2' +ac_decision_$1=yes +ac_decision_$1_msg='$2' +]) + + +define(APR_DECISION_OVERRIDE,[dnl + ac_decision='' + for ac_item in $1; do + eval "ac_decision_this=\$ac_decision_${ac_item}" + if test ".$ac_decision_this" = .yes; then + ac_decision=$ac_item + eval "ac_decision_msg=\$ac_decision_${ac_item}_msg" + fi + done +]) + + +define(APR_DECISION_FORCE,[dnl +ac_decision="$1" +eval "ac_decision_msg=\"\$ac_decision_${ac_decision}_msg\"" +]) + + +define(APR_END_DECISION,[dnl +if test ".$ac_decision" = .; then + echo "[$]0:Error: decision on $ac_decision_item failed" 1>&2 + exit 1 +else + if test ".$ac_decision_msg" = .; then + ac_decision_msg="$ac_decision" + fi + AC_DEFINE_UNQUOTED(${ac_decision_item}) + AC_MSG_RESULT([decision on $ac_decision_item... $ac_decision_msg]) +fi +]) + + +dnl +dnl APR_CHECK_SIZEOF_EXTENDED(INCLUDES, TYPE [, CROSS_SIZE]) +dnl +dnl A variant of AC_CHECK_SIZEOF which allows the checking of +dnl sizes of non-builtin types +dnl +AC_DEFUN(APR_CHECK_SIZEOF_EXTENDED, +[changequote(<<,>>)dnl +dnl The name to #define +define(<>, translit(sizeof_$2, [a-z *], [A-Z_P]))dnl +dnl The cache variable +define(<>, translit(ac_cv_sizeof_$2, [ *],[

]))dnl +changequote([, ])dnl +AC_MSG_CHECKING(size of $2) +AC_CACHE_VAL(AC_CV_NAME, +[AC_TRY_RUN([#include +$1 +main() +{ + FILE *f=fopen("conftestval","w"); + if (!f) exit(1); + fprintf(f, "%d\n", sizeof($2)); + exit(0); +}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$3],,, +AC_CV_NAME=$3))])dnl +AC_MSG_RESULT($AC_CV_NAME) +AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [The size of ]$2) +undefine([AC_TYPE_NAME])dnl +undefine([AC_CV_NAME])dnl +]) + + +dnl +dnl APR_TRY_COMPILE_NO_WARNING(INCLUDES, FUNCTION-BODY, +dnl [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +dnl Tries a compile test with warnings activated so that the result +dnl is false if the code doesn't compile cleanly. +dnl +AC_DEFUN(APR_TRY_COMPILE_NO_WARNING, +[if test "x$CFLAGS_WARN" = "x"; then + apr_tcnw_flags="" +else + apr_tcnw_flags=$CFLAGS_WARN +fi +if test "$ac_cv_prog_gcc" = "yes"; then + apr_tcnw_flags="$apr_tcnw_flags -Werror" +fi +changequote(', ') +cat > conftest.$ac_ext <&AC_FD_CC ; then + ifelse([$3], , :, [rm -rf conftest* + $3]) +else + echo "configure: failed or warning program:" >&AC_FD_CC + cat conftest.$ac_ext >&AC_FD_CC + ifelse([$4], , , [rm -rf conftest* + $4]) +fi +rm -f conftest* +])dnl + +dnl +dnl APR_CHECK_STRERROR_R_RC +dnl +dnl Decide which style of retcode is used by this system's +dnl strerror_r(). It either returns int (0 for success, -1 +dnl for failure), or it returns a pointer to the error +dnl string. +dnl +dnl +AC_DEFUN(APR_CHECK_STRERROR_R_RC,[ +AC_MSG_CHECKING(for type of return code from strerror_r) +AC_TRY_RUN([ +#include +#include +#include +main() +{ + char buf[1024]; + if (strerror_r(ERANGE, buf, sizeof buf) < 1) { + exit(0); + } + else { + exit(1); + } +}], [ + ac_cv_strerror_r_rc_int=yes ], [ + ac_cv_strerror_r_rc_int=no ], [ + ac_cv_strerror_r_rc_int=no ] ) +if test "x$ac_cv_strerror_r_rc_int" = xyes; then + AC_DEFINE(STRERROR_R_RC_INT, 1, [Define if strerror returns int]) + msg="int" +else + msg="pointer" +fi +AC_MSG_RESULT([$msg]) +] ) + +dnl +dnl APR_CHECK_DIRENT_INODE +dnl +dnl Decide if d_fileno or d_ino are available in the dirent +dnl structure on this platform. Single UNIX Spec says d_ino, +dnl BSD uses d_fileno. Undef to find the real beast. +dnl +AC_DEFUN(APR_CHECK_DIRENT_INODE, [ +AC_CACHE_CHECK([for inode member of struct dirent], apr_cv_dirent_inode, [ +apr_cv_dirent_inode=no +AC_TRY_COMPILE([ +#include +#include +],[ +#ifdef d_ino +#undef d_ino +#endif +struct dirent de; de.d_fileno; +], apr_cv_dirent_inode=d_fileno) +if test "$apr_cv_dirent_inode" = "no"; then +AC_TRY_COMPILE([ +#include +#include +],[ +#ifdef d_fileno +#undef d_fileno +#endif +struct dirent de; de.d_ino; +], apr_cv_dirent_inode=d_ino) +fi +]) +if test "$apr_cv_dirent_inode" != "no"; then + AC_DEFINE_UNQUOTED(DIRENT_INODE, $apr_cv_dirent_inode, + [Define if struct dirent has an inode member]) +fi +]) + +dnl +dnl APR_CHECK_DIRENT_TYPE +dnl +dnl Decide if d_type is available in the dirent structure +dnl on this platform. Not part of the Single UNIX Spec. +dnl Note that this is worthless without DT_xxx macros, so +dnl look for one while we are at it. +dnl +AC_DEFUN(APR_CHECK_DIRENT_TYPE,[ +AC_CACHE_CHECK([for file type member of struct dirent], apr_cv_dirent_type,[ +apr_cv_dirent_type=no +AC_TRY_COMPILE([ +#include +#include +],[ +struct dirent de; de.d_type = DT_REG; +], apr_cv_dirent_type=d_type) +]) +if test "$apr_cv_dirent_type" != "no"; then + AC_DEFINE_UNQUOTED(DIRENT_TYPE, $apr_cv_dirent_type, + [Define if struct dirent has a d_type member]) +fi +]) + +dnl the following is a newline, a space, a tab, and a backslash (the +dnl backslash is used by the shell to skip newlines, but m4 sees it; +dnl treat it like whitespace). +dnl WARNING: don't reindent these lines, or the space/tab will be lost! +define([apr_whitespace],[ + \]) + +dnl +dnl APR_COMMA_ARGS(ARG1 ...) +dnl convert the whitespace-separated arguments into comman-separated +dnl arguments. +dnl +dnl APR_FOREACH(CODE-BLOCK, ARG1, ARG2, ...) +dnl subsitute CODE-BLOCK for each ARG[i]. "eachval" will be set to ARG[i] +dnl within each iteration. +dnl +changequote({,}) +define({APR_COMMA_ARGS},{patsubst([$}{1],[[}apr_whitespace{]+],[,])}) +define({APR_FOREACH}, + {ifelse($}{2,,, + [define([eachval], + $}{2)$}{1[]APR_FOREACH([$}{1], + builtin([shift], + builtin([shift], $}{@)))])}) +changequote([,]) + +dnl APR_FLAG_HEADERS(HEADER-FILE ... [, FLAG-TO-SET ] [, "yes" ]) +dnl we set FLAG-TO-SET to 1 if we find HEADER-FILE, otherwise we set to 0 +dnl if FLAG-TO-SET is null, we automagically determine it's name +dnl by changing all "/" to "_" in the HEADER-FILE and dropping +dnl all "." and "-" chars. If the 3rd parameter is "yes" then instead of +dnl setting to 1 or 0, we set FLAG-TO-SET to yes or no. +dnl +AC_DEFUN(APR_FLAG_HEADERS,[ +AC_CHECK_HEADERS($1) +for aprt_i in $1 +do + ac_safe=`echo "$aprt_i" | sed 'y%./+-%__p_%'` + aprt_2=`echo "$aprt_i" | sed -e 's%/%_%g' -e 's/\.//g' -e 's/-//g'` + if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,yes,1)" + else + eval "ifelse($2,,$aprt_2,$2)=ifelse($3,yes,no,0)" + fi +done +]) + +dnl APR_FLAG_FUNCS(FUNC ... [, FLAG-TO-SET] [, "yes" ]) +dnl if FLAG-TO-SET is null, we automagically determine it's name +dnl prepending "have_" to the function name in FUNC, otherwise +dnl we use what's provided as FLAG-TO-SET. If the 3rd parameter +dnl is "yes" then instead of setting to 1 or 0, we set FLAG-TO-SET +dnl to yes or no. +dnl +AC_DEFUN(APR_FLAG_FUNCS,[ +AC_CHECK_FUNCS($1) +for aprt_j in $1 +do + aprt_3="have_$aprt_j" + if eval "test \"`echo '$ac_cv_func_'$aprt_j`\" = yes"; then + eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,yes,1)" + else + eval "ifelse($2,,$aprt_3,$2)=ifelse($3,yes,no,0)" + fi +done +]) + +dnl Iteratively interpolate the contents of the second argument +dnl until interpolation offers no new result. Then assign the +dnl final result to $1. +dnl +dnl Example: +dnl +dnl foo=1 +dnl bar='${foo}/2' +dnl baz='${bar}/3' +dnl APR_EXPAND_VAR(fraz, $baz) +dnl $fraz is now "1/2/3" +dnl +AC_DEFUN(APR_EXPAND_VAR,[ +ap_last= +ap_cur="$2" +while test "x${ap_cur}" != "x${ap_last}"; +do + ap_last="${ap_cur}" + ap_cur=`eval "echo ${ap_cur}"` +done +$1="${ap_cur}" +]) + +dnl +dnl Removes the value of $3 from the string in $2, strips of any leading +dnl slashes, and returns the value in $1. +dnl +dnl Example: +dnl orig_path="${prefix}/bar" +dnl APR_PATH_RELATIVE(final_path, $orig_path, $prefix) +dnl $final_path now contains "bar" +AC_DEFUN(APR_PATH_RELATIVE,[ +ap_stripped=`echo $2 | sed -e "s#^$3##"` +# check if the stripping was successful +if test "x$2" != "x${ap_stripped}"; then + # it was, so strip of any leading slashes + $1="`echo ${ap_stripped} | sed -e 's#^/*##'`" +else + # it wasn't so return the original + $1="$2" +fi +]) + +dnl APR_HELP_STRING(LHS, RHS) +dnl Autoconf 2.50 can not handle substr correctly. It does have +dnl AC_HELP_STRING, so let's try to call it if we can. +dnl Note: this define must be on one line so that it can be properly returned +dnl as the help string. When using this macro with a multi-line RHS, ensure +dnl that you surround the macro invocation with []s +AC_DEFUN(APR_HELP_STRING,[ifelse(regexp(AC_ACVERSION, 2\.1), -1, AC_HELP_STRING([$1],[$2]),[ ][$1] substr([ ],len($1))[$2])]) + +dnl +dnl APR_LAYOUT(configlayout, layoutname [, extravars]) +dnl +AC_DEFUN(APR_LAYOUT,[ + if test ! -f $srcdir/config.layout; then + echo "** Error: Layout file $srcdir/config.layout not found" + echo "** Error: Cannot use undefined layout '$LAYOUT'" + exit 1 + fi + pldconf=./config.pld + changequote({,}) + sed -e "1s/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*//;1t" \ + -e "1,/[ ]*<[lL]ayout[ ]*$2[ ]*>[ ]*/d" \ + -e '/[ ]*<\/Layout>[ ]*/,$d' \ + -e "s/^[ ]*//g" \ + -e "s/:[ ]*/=\'/g" \ + -e "s/[ ]*$/'/g" \ + $1 > $pldconf + layout_name=$2 + if test ! -s $pldconf; then + echo "** Error: unable to find layout $layout_name" + exit 1 + fi + . $pldconf + rm $pldconf + for var in prefix exec_prefix bindir sbindir libexecdir mandir \ + sysconfdir datadir includedir localstatedir runtimedir \ + logfiledir libdir installbuilddir libsuffix $3; do + eval "val=\"\$$var\"" + case $val in + *+) + val=`echo $val | sed -e 's;\+$;;'` + eval "$var=\"\$val\"" + autosuffix=yes + ;; + *) + autosuffix=no + ;; + esac + val=`echo $val | sed -e 's:\(.\)/*$:\1:'` + val=`echo $val | sed -e 's:[\$]\([a-z_]*\):${\1}:g'` + if test "$autosuffix" = "yes"; then + if echo $val | grep apache >/dev/null; then + addtarget=no + else + addtarget=yes + fi + if test "$addtarget" = "yes"; then + val="$val/apache2" + fi + fi + eval "$var='$val'" + done + changequote([,]) +])dnl + +dnl +dnl APR_ENABLE_LAYOUT(default layout name [, extra vars]) +dnl +AC_DEFUN(APR_ENABLE_LAYOUT,[ +AC_ARG_ENABLE(layout, +[ --enable-layout=LAYOUT],[ + LAYOUT=$enableval +]) + +if test -z "$LAYOUT"; then + LAYOUT="$1" +fi +APR_LAYOUT($srcdir/config.layout, $LAYOUT, $2) + +AC_MSG_CHECKING(for chosen layout) +AC_MSG_RESULT($layout_name) +]) + + +dnl +dnl APR_PARSE_ARGUMENTS +dnl a reimplementation of autoconf's argument parser, +dnl used here to allow us to co-exist layouts and argument based +dnl set ups. +AC_DEFUN(APR_PARSE_ARGUMENTS,[ +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[[^=]]*=\(.*\)'` + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix="$ac_optarg" ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix="$ac_optarg" ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + + esac +done + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [[\\/$]]* | ?:[[\\/]]* | NONE | '' ) ;; + *) AC_MSG_ERROR([expected an absolute path for --$ac_var: $ac_val]);; + esac +done + +])dnl + +dnl +dnl APR_CHECK_DEPEND +dnl +dnl Determine what program we can use to generate .deps-style dependencies +dnl +AC_DEFUN(APR_CHECK_DEPEND,[ +dnl Try to determine what depend program we can use +dnl All GCC-variants should have -MM. +dnl If not, then we can check on those, too. +if test "$GCC" = "yes"; then + MKDEP='$(CC) -MM' +else + rm -f conftest.c +dnl should be available everywhere! + cat > conftest.c < + int main() { return 0; } +EOF + MKDEP="true" + for i in "$CC -MM" "$CC -M" "$CPP -MM" "$CPP -M" "cpp -M"; do + AC_MSG_CHECKING([if $i can create proper make dependencies]) + if $i conftest.c 2>/dev/null | grep 'conftest.o: conftest.c' >/dev/null; then + MKDEP=$i + AC_MSG_RESULT(yes) + break; + fi + AC_MSG_RESULT(no) + done + rm -f conftest.c +fi + +AC_SUBST(MKDEP) +]) diff --git a/srclib/apr/build/apr_hints.m4 b/srclib/apr/build/apr_hints.m4 new file mode 100644 index 0000000000..48c035b7dd --- /dev/null +++ b/srclib/apr/build/apr_hints.m4 @@ -0,0 +1,464 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Copyright 2000-2005 The Apache Software Foundation +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl ----------------------------------------------------------------- +dnl apr_hints.m4: APR's autoconf macros for platform-specific hints +dnl +dnl We preload various configure settings depending +dnl on previously obtained platform knowledge. +dnl We allow all settings to be overridden from +dnl the command-line. +dnl +dnl We maintain the "format" that we've used +dnl under 1.3.x, so we don't exactly follow +dnl what is "recommended" by autoconf. + +dnl +dnl APR_PRELOAD +dnl +dnl Preload various ENV/makefile params such as CC, CFLAGS, etc +dnl based on outside knowledge +dnl +dnl Generally, we force the setting of CC, and add flags +dnl to CFLAGS, CPPFLAGS, LIBS and LDFLAGS. +dnl +AC_DEFUN(APR_PRELOAD, [ +if test "x$apr_preload_done" != "xyes" ; then + + apr_preload_done="yes" + + echo "Applying APR hints file rules for $host" + + case "$host" in + *mint) + APR_ADDTO(CPPFLAGS, [-DMINT]) + APR_ADDTO(LIBS, [-lportlib]) + ;; + *MPE/iX*) + APR_ADDTO(CPPFLAGS, [-DMPE -D_POSIX_SOURCE -D_SOCKET_SOURCE]) + APR_ADDTO(LIBS, [-lsvipc -lcurses]) + APR_ADDTO(LDFLAGS, [-Xlinker \"-WL,cap=ia,ba,ph;nmstack=1024000\"]) + ;; + *-apple-aux3*) + APR_ADDTO(CPPFLAGS, [-DAUX3 -D_POSIX_SOURCE]) + APR_ADDTO(LIBS, [-lposix -lbsd]) + APR_ADDTO(LDFLAGS, [-s]) + APR_SETVAR(SHELL, [/bin/ksh]) + ;; + *-ibm-aix*) + APR_ADDTO(CPPFLAGS, [-U__STR__ -D_THREAD_SAFE]) + dnl _USR_IRS gets us the hstrerror() proto in netdb.h + case $host in + *-ibm-aix4.3) + APR_ADDTO(CPPFLAGS, [-D_USE_IRS]) + ;; + *-ibm-aix5*) + APR_ADDTO(CPPFLAGS, [-D_USE_IRS]) + ;; + *-ibm-aix4.3.*) + APR_ADDTO(CPPFLAGS, [-D_USE_IRS]) + ;; + esac + dnl If using xlc, remember it, and give it the right options. + if $CC 2>&1 | grep 'xlc' > /dev/null; then + APR_SETIFNULL(AIX_XLC, [yes]) + APR_ADDTO(CFLAGS, [-qHALT=E]) + fi + APR_SETIFNULL(apr_sysvsem_is_global, [yes]) + APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE]) + case $host in + *-ibm-aix3* | *-ibm-aix4.1.*) + ;; + *) + APR_ADDTO(LDFLAGS, [-Wl,-brtl]) + ;; + esac + ;; + *-apollo-*) + APR_ADDTO(CPPFLAGS, [-DAPOLLO]) + ;; + *-dg-dgux*) + APR_ADDTO(CPPFLAGS, [-DDGUX]) + ;; + *-os2*) + APR_SETVAR(SHELL, [sh]) + APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes]) + APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes]) + ;; + *-hi-hiux) + APR_ADDTO(CPPFLAGS, [-DHIUX]) + ;; + *-hp-hpux11.*) + APR_ADDTO(CPPFLAGS, [-DHPUX11 -D_REENTRANT -D_XOPEN_SOURCE_EXTENDED]) + ;; + *-hp-hpux10.*) + case $host in + *-hp-hpux10.01) +dnl # We know this is a problem in 10.01. +dnl # Not a problem in 10.20. Otherwise, who knows? + APR_ADDTO(CPPFLAGS, [-DSELECT_NEEDS_CAST]) + ;; + esac + APR_ADDTO(CPPFLAGS, [-D_REENTRANT]) + ;; + *-hp-hpux*) + APR_ADDTO(CPPFLAGS, [-DHPUX -D_REENTRANT]) + ;; + *-linux-*) + case `uname -r` in + 2.* ) APR_ADDTO(CPPFLAGS, [-DLINUX=2]) + ;; + 1.* ) APR_ADDTO(CPPFLAGS, [-DLINUX=1]) + ;; + * ) + ;; + esac + APR_ADDTO(CPPFLAGS, [-D_REENTRANT -D_GNU_SOURCE]) + ;; + *-GNU*) + APR_ADDTO(CPPFLAGS, [-DHURD -D_GNU_SOURCE]) + ;; + *-lynx-lynxos) + APR_ADDTO(CPPFLAGS, [-D__NO_INCLUDE_WARN__ -DLYNXOS]) + APR_ADDTO(LIBS, [-lbsd]) + ;; + *486-*-bsdi*) + APR_ADDTO(CFLAGS, [-m486]) + ;; + *-*-bsdi*) + case $host in + *bsdi4.1) + APR_ADDTO(CFLAGS, [-D_REENTRANT]) + ;; + esac + ;; + *-openbsd*) + APR_ADDTO(CPPFLAGS, [-D_POSIX_THREADS]) + # binding to an ephemeral port fails on OpenBSD so override + # the test for O_NONBLOCK inheritance across accept(). + APR_SETIFNULL(ac_cv_o_nonblock_inherited, [yes]) + ;; + *-netbsd*) + APR_ADDTO(CPPFLAGS, [-DNETBSD]) + # fcntl() lies about O_NONBLOCK on an accept()ed socket (PR kern/26950) + APR_SETIFNULL(ac_cv_o_nonblock_inherited, [yes]) + ;; + *-freebsd*) + APR_SETIFNULL(apr_lock_method, [USE_FLOCK_SERIALIZE]) + if test -x /sbin/sysctl; then + os_version=`/sbin/sysctl -n kern.osreldate` + else + os_version=000000 + fi + # 502102 is when libc_r switched to libpthread (aka libkse). + if test $os_version -ge "502102"; then + apr_cv_pthreads_cflags="none" + apr_cv_pthreads_lib="-lpthread" + else + APR_ADDTO(CPPFLAGS, [-D_THREAD_SAFE -D_REENTRANT]) + APR_SETIFNULL(enable_threads, [no]) + fi + # prevent use of KQueue before FreeBSD 4.8 + if test $os_version -lt "480000"; then + APR_SETIFNULL(ac_cv_func_kqueue, no) + fi + ;; + *-next-nextstep*) + APR_SETIFNULL(CFLAGS, [-O]) + APR_ADDTO(CPPFLAGS, [-DNEXT]) + ;; + *-next-openstep*) + APR_SETIFNULL(CFLAGS, [-O]) + APR_ADDTO(CPPFLAGS, [-DNEXT]) + ;; + *-apple-rhapsody*) + APR_ADDTO(CPPFLAGS, [-DRHAPSODY]) + ;; + *-apple-darwin*) + APR_ADDTO(CPPFLAGS, [-DDARWIN -DSIGPROCMASK_SETS_THREAD_MASK -no-cpp-precomp]) + APR_SETIFNULL(apr_posixsem_is_global, [yes]) + APR_SETIFNULL(ac_cv_func_poll, [no]) # See issue 34332 + ;; + *-dec-osf*) + APR_ADDTO(CPPFLAGS, [-DOSF1]) + # process-shared mutexes don't seem to work in Tru64 5.0 + APR_SETIFNULL(apr_cv_process_shared_works, [no]) + ;; + *-nto-qnx*) + ;; + *-qnx) + APR_ADDTO(CPPFLAGS, [-DQNX]) + APR_ADDTO(LIBS, [-N128k -lunix]) + ;; + *-qnx32) + APR_ADDTO(CPPFLAGS, [-DQNX]) + APR_ADDTO(CFLAGS, [-mf -3]) + APR_ADDTO(LIBS, [-N128k -lunix]) + ;; + *-isc4*) + APR_ADDTO(CPPFLAGS, [-posix -DISC]) + APR_ADDTO(LDFLAGS, [-posix]) + APR_ADDTO(LIBS, [-linet]) + ;; + *-sco3.2v[[234]]*) + APR_ADDTO(CPPFLAGS, [-DSCO -D_REENTRANT]) + if test "$GCC" = "no"; then + APR_ADDTO(CFLAGS, [-Oacgiltz]) + fi + APR_ADDTO(LIBS, [-lPW -lmalloc]) + ;; + *-sco3.2v5*) + APR_ADDTO(CPPFLAGS, [-DSCO5 -D_REENTRANT]) + ;; + *-sco_sv*|*-SCO_SV*) + APR_ADDTO(CPPFLAGS, [-DSCO -D_REENTRANT]) + APR_ADDTO(LIBS, [-lPW -lmalloc]) + ;; + *-solaris2*) + PLATOSVERS=`echo $host | sed 's/^.*solaris2.//'` + APR_ADDTO(CPPFLAGS, [-DSOLARIS2=$PLATOSVERS -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT]) + APR_SETIFNULL(apr_lock_method, [USE_FCNTL_SERIALIZE]) + ;; + *-sunos4*) + APR_ADDTO(CPPFLAGS, [-DSUNOS4]) + ;; + *-unixware1) + APR_ADDTO(CPPFLAGS, [-DUW=100]) + ;; + *-unixware2) + APR_ADDTO(CPPFLAGS, [-DUW=200]) + APR_ADDTO(LIBS, [-lgen]) + ;; + *-unixware211) + APR_ADDTO(CPPFLAGS, [-DUW=211]) + APR_ADDTO(LIBS, [-lgen]) + ;; + *-unixware212) + APR_ADDTO(CPPFLAGS, [-DUW=212]) + APR_ADDTO(LIBS, [-lgen]) + ;; + *-unixware7) + APR_ADDTO(CPPFLAGS, [-DUW=700]) + APR_ADDTO(LIBS, [-lgen]) + ;; + maxion-*-sysv4*) + APR_ADDTO(CPPFLAGS, [-DSVR4]) + APR_ADDTO(LIBS, [-lc -lgen]) + ;; + *-*-powermax*) + APR_ADDTO(CPPFLAGS, [-DSVR4]) + APR_ADDTO(LIBS, [-lgen]) + ;; + TPF) + APR_ADDTO(CPPFLAGS, [-DTPF -D_POSIX_SOURCE]) + ;; + bs2000*-siemens-sysv*) + APR_SETIFNULL(CFLAGS, [-O]) + APR_ADDTO(CPPFLAGS, [-DSVR4 -D_XPG_IV -D_KMEMUSER]) + APR_ADDTO(LIBS, [-lsocket]) + APR_SETIFNULL(enable_threads, [no]) + ;; + *-siemens-sysv4*) + APR_ADDTO(CPPFLAGS, [-DSVR4 -D_XPG_IV -DHAS_DLFCN -DUSE_MMAP_FILES -DUSE_SYSVSEM_SERIALIZED_ACCEPT]) + APR_ADDTO(LIBS, [-lc]) + ;; + pyramid-pyramid-svr4) + APR_ADDTO(CPPFLAGS, [-DSVR4 -DNO_LONG_DOUBLE]) + APR_ADDTO(LIBS, [-lc]) + ;; + DS/90\ 7000-*-sysv4*) + APR_ADDTO(CPPFLAGS, [-DUXPDS]) + ;; + *-tandem-sysv4*) + APR_ADDTO(CPPFLAGS, [-DSVR4]) + ;; + *-ncr-sysv4) + APR_ADDTO(CPPFLAGS, [-DSVR4 -DMPRAS]) + APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb]) + ;; + *-sysv4*) + APR_ADDTO(CPPFLAGS, [-DSVR4]) + APR_ADDTO(LIBS, [-lc]) + ;; + 88k-encore-sysv4) + APR_ADDTO(CPPFLAGS, [-DSVR4 -DENCORE]) + APR_ADDTO(LIBS, [-lPW]) + ;; + *-uts*) + PLATOSVERS=`echo $host | sed 's/^.*,//'` + case $PLATOSVERS in + 2*) APR_ADDTO(CPPFLAGS, [-DUTS21]) + APR_ADDTO(CFLAGS, [-Xa -eft]) + APR_ADDTO(LIBS, [-lbsd -la]) + ;; + *) APR_ADDTO(CPPFLAGS, [-DSVR4]) + APR_ADDTO(CFLAGS, [-Xa]) + ;; + esac + ;; + *-ultrix) + APR_ADDTO(CPPFLAGS, [-DULTRIX]) + APR_SETVAR(SHELL, [/bin/sh5]) + ;; + *powerpc-tenon-machten*) + APR_ADDTO(LDFLAGS, [-Xlstack=0x14000 -Xldelcsect]) + ;; + *-machten*) + APR_ADDTO(LDFLAGS, [-stack 0x14000]) + ;; + *convex-v11*) + APR_ADDTO(CPPFLAGS, [-DCONVEXOS11]) + APR_SETIFNULL(CFLAGS, [-O1]) + APR_ADDTO(CFLAGS, [-ext]) + ;; + i860-intel-osf1) + APR_ADDTO(CPPFLAGS, [-DPARAGON]) + ;; + *-sequent-ptx2.*.*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=20]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-linet -lc -lseq]) + ;; + *-sequent-ptx4.0.*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=40]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-linet -lc]) + ;; + *-sequent-ptx4.[[123]].*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=41]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-lc]) + ;; + *-sequent-ptx4.4.*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=44]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-lc]) + ;; + *-sequent-ptx4.5.*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=45]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-lc]) + ;; + *-sequent-ptx5.0.*) + APR_ADDTO(CPPFLAGS, [-DSEQUENT=50]) + APR_ADDTO(CFLAGS, [-Wc,-pw]) + APR_ADDTO(LIBS, [-lc]) + ;; + *NEWS-OS*) + APR_ADDTO(CPPFLAGS, [-DNEWSOS]) + ;; + *-riscix) + APR_ADDTO(CPPFLAGS, [-DRISCIX]) + APR_SETIFNULL(CFLAGS, [-O]) + ;; + *-irix*) + APR_ADDTO(CPPFLAGS, [-D_POSIX_THREAD_SAFE_FUNCTIONS]) + ;; + *beos*) + APR_ADDTO(CPPFLAGS, [-DBEOS]) + PLATOSVERS=`uname -r` + APR_SETIFNULL(apr_process_lock_is_global, [yes]) + case $PLATOSVERS in + 5.0.4) + APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib]) + APR_ADDTO(LIBS, [-lbind -lsocket]) + APR_ADDTO(CPPFLAGS,[-DBONE7]) + ;; + 5.1) + APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib]) + APR_ADDTO(LIBS, [-lbind -lsocket]) + ;; + esac + APR_ADDTO(CPPFLAGS, [-DSIGPROCMASK_SETS_THREAD_MASK -DAP_AUTH_DBM_USE_APR]) + ;; + 4850-*.*) + APR_ADDTO(CPPFLAGS, [-DSVR4 -DMPRAS]) + APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb]) + ;; + drs6000*) + APR_ADDTO(CPPFLAGS, [-DSVR4]) + APR_ADDTO(LIBS, [-lc -L/usr/ucblib -lucb]) + ;; + m88k-*-CX/SX|CYBER) + APR_ADDTO(CPPFLAGS, [-D_CX_SX]) + APR_ADDTO(CFLAGS, [-Xa]) + ;; + *-tandem-oss) + APR_ADDTO(CPPFLAGS, [-D_TANDEM_SOURCE -D_XOPEN_SOURCE_EXTENDED=1]) + ;; + *-ibm-os390) + APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE]) + APR_SETIFNULL(apr_sysvsem_is_global, [yes]) + APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes]) + APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes]) + APR_ADDTO(CPPFLAGS, [-U_NO_PROTO -DPTHREAD_ATTR_SETDETACHSTATE_ARG2_ADDR -DPTHREAD_SETS_ERRNO -DPTHREAD_DETACH_ARG1_ADDR -DSIGPROCMASK_SETS_THREAD_MASK -DTCP_NODELAY=1]) + ;; + *-ibm-as400) + APR_SETIFNULL(apr_lock_method, [USE_SYSVSEM_SERIALIZE]) + APR_SETIFNULL(apr_process_lock_is_global, [yes]) + APR_SETIFNULL(apr_gethostbyname_is_thread_safe, [yes]) + APR_SETIFNULL(apr_gethostbyaddr_is_thread_safe, [yes]) + ;; + *cygwin*) + APR_ADDTO(CPPFLAGS, [-DCYGWIN]) + APR_ADDTO(LIBS, [-lcrypt]) + ;; + esac + +fi +]) + +dnl +dnl APR_CC_HINTS +dnl +dnl Allows us to provide a default choice of compiler which +dnl the user can override. +AC_DEFUN(APR_CC_HINTS, [ +case "$host" in + *-apple-aux3*) + APR_SETIFNULL(CC, [gcc]) + ;; + bs2000*-siemens-sysv*) + APR_SETIFNULL(CC, [c89 -XLLML -XLLMK -XL -Kno_integer_overflow]) + ;; + *convex-v11*) + APR_SETIFNULL(CC, [cc]) + ;; + *-ibm-os390) + APR_SETIFNULL(CC, [cc]) + ;; + *-ibm-as400) + APR_SETIFNULL(CC, [icc]) + ;; + *-isc4*) + APR_SETIFNULL(CC, [gcc]) + ;; + m88k-*-CX/SX|CYBER) + APR_SETIFNULL(CC, [cc]) + ;; + *-next-openstep*) + APR_SETIFNULL(CC, [cc]) + ;; + *-qnx32) + APR_SETIFNULL(CC, [cc -F]) + ;; + *-tandem-oss) + APR_SETIFNULL(CC, [c89]) + ;; + TPF) + APR_SETIFNULL(CC, [c89]) + ;; +esac +]) diff --git a/srclib/apr/build/apr_network.m4 b/srclib/apr/build/apr_network.m4 new file mode 100644 index 0000000000..848a5e97fa --- /dev/null +++ b/srclib/apr/build/apr_network.m4 @@ -0,0 +1,746 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Copyright 2000-2005 The Apache Software Foundation +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl ----------------------------------------------------------------- +dnl apr_network.m4: APR's autoconf macros for testing network support +dnl + +dnl +dnl check for working getaddrinfo() +dnl +dnl Note that if the system doesn't have gai_strerror(), we +dnl can't use getaddrinfo() because we can't get strings +dnl describing the error codes. +dnl +AC_DEFUN(APR_CHECK_WORKING_GETADDRINFO,[ + AC_CACHE_CHECK(for working getaddrinfo, ac_cv_working_getaddrinfo,[ + AC_TRY_RUN( [ +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +void main(void) { + struct addrinfo hints, *ai; + int error; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo("127.0.0.1", NULL, &hints, &ai); + if (error) { + exit(1); + } + if (ai->ai_addr->sa_family != AF_INET) { + exit(1); + } + exit(0); +} +],[ + ac_cv_working_getaddrinfo="yes" +],[ + ac_cv_working_getaddrinfo="no" +],[ + ac_cv_working_getaddrinfo="yes" +])]) +if test "$ac_cv_working_getaddrinfo" = "yes"; then + if test "$ac_cv_func_gai_strerror" != "yes"; then + ac_cv_working_getaddrinfo="no" + else + AC_DEFINE(HAVE_GETADDRINFO, 1, [Define if getaddrinfo exists and works well enough for APR]) + fi +fi +]) + +dnl Check whether the AI_ADDRCONFIG flag can be used with getaddrinfo +AC_DEFUN(APR_CHECK_GETADDRINFO_ADDRCONFIG, [ + AC_CACHE_CHECK(for working AI_ADDRCONFIG, apr_cv_gai_addrconfig, [ + AC_TRY_RUN([ +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + +int main(int argc, char **argv) { + struct addrinfo hints, *ai; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG; + return getaddrinfo("localhost", NULL, &hints, &ai) != 0; +}], [apr_cv_gai_addrconfig=yes], + [apr_cv_gai_addrconfig=no], + [apr_cv_gai_addrconfig=no])]) + +if test $apr_cv_gai_addrconfig = yes; then + AC_DEFINE(HAVE_GAI_ADDRCONFIG, 1, [Define if getaddrinfo accepts the AI_ADDRCONFIG flag]) +fi +]) + +dnl +dnl check for working getnameinfo() +dnl +AC_DEFUN(APR_CHECK_WORKING_GETNAMEINFO,[ + AC_CACHE_CHECK(for working getnameinfo, ac_cv_working_getnameinfo,[ + AC_TRY_RUN( [ +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif + +void main(void) { + struct sockaddr_in sa; + char hbuf[256]; + int error; + + sa.sin_family = AF_INET; + sa.sin_port = 0; + sa.sin_addr.s_addr = inet_addr("127.0.0.1"); +#ifdef SIN6_LEN + sa.sin_len = sizeof(sa); +#endif + + error = getnameinfo((const struct sockaddr *)&sa, sizeof(sa), + hbuf, 256, NULL, 0, + NI_NUMERICHOST); + if (error) { + exit(1); + } else { + exit(0); + } +} +],[ + ac_cv_working_getnameinfo="yes" +],[ + ac_cv_working_getnameinfo="no" +],[ + ac_cv_working_getnameinfo="yes" +])]) +if test "$ac_cv_working_getnameinfo" = "yes"; then + AC_DEFINE(HAVE_GETNAMEINFO, 1, [Define if getnameinfo exists]) +fi +]) + +dnl +dnl check for negative error codes for getaddrinfo() +dnl +AC_DEFUN(APR_CHECK_NEGATIVE_EAI,[ + AC_CACHE_CHECK(for negative error codes for getaddrinfo, ac_cv_negative_eai,[ + AC_TRY_RUN( [ +#ifdef HAVE_NETDB_H +#include +#endif + +void main(void) { + if (EAI_ADDRFAMILY < 0) { + exit(0); + } + exit(1); +} +],[ + ac_cv_negative_eai="yes" +],[ + ac_cv_negative_eai="no" +],[ + ac_cv_negative_eai="no" +])]) +if test "$ac_cv_negative_eai" = "yes"; then + AC_DEFINE(NEGATIVE_EAI, 1, [Define if EAI_ error codes from getaddrinfo are negative]) +fi +]) + +dnl +dnl Checks the definition of gethostbyname_r and gethostbyaddr_r +dnl which are different for glibc, solaris and assorted other operating +dnl systems +dnl +dnl Note that this test is executed too early to see if we have all of +dnl the headers. +AC_DEFUN(APR_CHECK_GETHOSTBYNAME_R_STYLE,[ + +dnl Try and compile a glibc2 gethostbyname_r piece of code, and set the +dnl style of the routines to glibc2 on success +AC_CACHE_CHECK([style of gethostbyname_r routine], ac_cv_gethostbyname_r_style, +APR_TRY_COMPILE_NO_WARNING([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +],[ +int tmp = gethostbyname_r((const char *) 0, (struct hostent *) 0, + (char *) 0, 0, (struct hostent **) 0, &tmp); +], ac_cv_gethostbyname_r_style=glibc2, ac_cv_gethostbyname_r_style=none)) + +if test "$ac_cv_gethostbyname_r_style" = "glibc2"; then + AC_DEFINE(GETHOSTBYNAME_R_GLIBC2, 1, [Define if gethostbyname_r has the glibc style]) +fi + +AC_CACHE_CHECK([3rd argument to the gethostbyname_r routines], ac_cv_gethostbyname_r_arg, +APR_TRY_COMPILE_NO_WARNING([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif +],[ +int tmp = gethostbyname_r((const char *) 0, (struct hostent *) 0, + (struct hostent_data *) 0);], +ac_cv_gethostbyname_r_arg=hostent_data, ac_cv_gethostbyname_r_arg=char)) + +if test "$ac_cv_gethostbyname_r_arg" = "hostent_data"; then + AC_DEFINE(GETHOSTBYNAME_R_HOSTENT_DATA, 1, [Define if gethostbyname_r has the hostent_data for the third argument]) +fi +]) + +dnl +dnl see if TCP_NODELAY setting is inherited from listening sockets +dnl +AC_DEFUN(APR_CHECK_TCP_NODELAY_INHERITED,[ + AC_CACHE_CHECK(if TCP_NODELAY setting is inherited from listening sockets, ac_cv_tcp_nodelay_inherited,[ + AC_TRY_RUN( [ +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_TCP_H +#include +#endif +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif +int main(void) { + int listen_s, connected_s, client_s; + int listen_port, rc; + struct sockaddr_in sa; + socklen_t sa_len; + socklen_t option_len; + int option; + + listen_s = socket(AF_INET, SOCK_STREAM, 0); + if (listen_s < 0) { + perror("socket"); + exit(1); + } + option = 1; + rc = setsockopt(listen_s, IPPROTO_TCP, TCP_NODELAY, &option, sizeof option); + if (rc < 0) { + perror("setsockopt TCP_NODELAY"); + exit(1); + } + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; +#ifdef BEOS + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#endif + /* leave port 0 to get ephemeral */ + rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa); + if (rc < 0) { + perror("bind for ephemeral port"); + exit(1); + } + /* find ephemeral port */ + sa_len = sizeof(sa); + rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len); + if (rc < 0) { + perror("getsockname"); + exit(1); + } + listen_port = sa.sin_port; + rc = listen(listen_s, 5); + if (rc < 0) { + perror("listen"); + exit(1); + } + client_s = socket(AF_INET, SOCK_STREAM, 0); + if (client_s < 0) { + perror("socket"); + exit(1); + } + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; + sa.sin_port = listen_port; +#ifdef BEOS + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#endif + /* leave sin_addr all zeros to use loopback */ + rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa); + if (rc < 0) { + perror("connect"); + exit(1); + } + sa_len = sizeof sa; + connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len); + if (connected_s < 0) { + perror("accept"); + exit(1); + } + option_len = sizeof option; + rc = getsockopt(connected_s, IPPROTO_TCP, TCP_NODELAY, &option, &option_len); + if (rc < 0) { + perror("getsockopt"); + exit(1); + } + if (!option) { + fprintf(stderr, "TCP_NODELAY is not set in the child.\n"); + exit(1); + } + return 0; +} +],[ + ac_cv_tcp_nodelay_inherited="yes" +],[ + ac_cv_tcp_nodelay_inherited="no" +],[ + ac_cv_tcp_nodelay_inherited="yes" +])]) +if test "$ac_cv_tcp_nodelay_inherited" = "yes"; then + tcp_nodelay_inherited=1 +else + tcp_nodelay_inherited=0 +fi +]) + +dnl +dnl see if O_NONBLOCK setting is inherited from listening sockets +dnl +AC_DEFUN(APR_CHECK_O_NONBLOCK_INHERITED,[ + AC_CACHE_CHECK(if O_NONBLOCK setting is inherited from listening sockets, ac_cv_o_nonblock_inherited,[ + AC_TRY_RUN( [ +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_TCP_H +#include +#endif +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif +#ifdef HAVE_FCNTL_H +#include +#endif +int main(void) { + int listen_s, connected_s, client_s; + int listen_port, rc; + struct sockaddr_in sa; + socklen_t sa_len; + + listen_s = socket(AF_INET, SOCK_STREAM, 0); + if (listen_s < 0) { + perror("socket"); + exit(1); + } + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; +#ifdef BEOS + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#endif + /* leave port 0 to get ephemeral */ + rc = bind(listen_s, (struct sockaddr *)&sa, sizeof sa); + if (rc < 0) { + perror("bind for ephemeral port"); + exit(1); + } + /* find ephemeral port */ + sa_len = sizeof(sa); + rc = getsockname(listen_s, (struct sockaddr *)&sa, &sa_len); + if (rc < 0) { + perror("getsockname"); + exit(1); + } + listen_port = sa.sin_port; + rc = listen(listen_s, 5); + if (rc < 0) { + perror("listen"); + exit(1); + } + rc = fcntl(listen_s, F_SETFL, O_NONBLOCK); + if (rc < 0) { + perror("fcntl(F_SETFL)"); + exit(1); + } + client_s = socket(AF_INET, SOCK_STREAM, 0); + if (client_s < 0) { + perror("socket"); + exit(1); + } + memset(&sa, 0, sizeof sa); + sa.sin_family = AF_INET; + sa.sin_port = listen_port; +#ifdef BEOS + sa.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +#endif + /* leave sin_addr all zeros to use loopback */ + rc = connect(client_s, (struct sockaddr *)&sa, sizeof sa); + if (rc < 0) { + perror("connect"); + exit(1); + } + sa_len = sizeof sa; + connected_s = accept(listen_s, (struct sockaddr *)&sa, &sa_len); + if (connected_s < 0) { + perror("accept"); + exit(1); + } + rc = fcntl(connected_s, F_GETFL, 0); + if (rc < 0) { + perror("fcntl(F_GETFL)"); + exit(1); + } + if (!(rc & O_NONBLOCK)) { + fprintf(stderr, "O_NONBLOCK is not set in the child.\n"); + exit(1); + } + return 0; +} +],[ + ac_cv_o_nonblock_inherited="yes" +],[ + ac_cv_o_nonblock_inherited="no" +],[ + ac_cv_o_nonblock_inherited="yes" +])]) +if test "$ac_cv_o_nonblock_inherited" = "yes"; then + o_nonblock_inherited=1 +else + o_nonblock_inherited=0 +fi +]) + +dnl +dnl check for socklen_t, fall back to unsigned int +dnl +AC_DEFUN(APR_CHECK_SOCKLEN_T,[ +AC_CACHE_CHECK(for socklen_t, ac_cv_socklen_t,[ +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +],[ +socklen_t foo = (socklen_t) 0; +],[ + ac_cv_socklen_t=yes +],[ + ac_cv_socklen_t=no +]) +]) + +if test "$ac_cv_socklen_t" = "yes"; then + AC_DEFINE(HAVE_SOCKLEN_T, 1, [Whether you have socklen_t]) +fi +]) + + +AC_DEFUN(APR_CHECK_INET_ADDR,[ +AC_CACHE_CHECK(for inet_addr, ac_cv_func_inet_addr,[ +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +],[ +inet_addr("127.0.0.1"); +],[ + ac_cv_func_inet_addr=yes +],[ + ac_cv_func_inet_addr=no +]) +]) + +if test "$ac_cv_func_inet_addr" = "yes"; then + have_inet_addr=1 +else + have_inet_addr=0 +fi +]) + + +AC_DEFUN(APR_CHECK_INET_NETWORK,[ +AC_CACHE_CHECK(for inet_network, ac_cv_func_inet_network,[ +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +],[ +inet_network("127.0.0.1"); +],[ + ac_cv_func_inet_network=yes +],[ + ac_cv_func_inet_network=no +]) +]) + +if test "$ac_cv_func_inet_network" = "yes"; then + have_inet_network=1 +else + have_inet_network=0 +fi +]) + +dnl Check for presence of struct sockaddr_storage. +AC_DEFUN(APR_CHECK_SOCKADDR_STORAGE,[ +AC_CACHE_CHECK(for sockaddr_storage, apr_cv_define_sockaddr_storage,[ +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +],[struct sockaddr_storage sa;], +[apr_cv_define_sockaddr_storage=yes], +[apr_cv_define_sockaddr_storage=no])]) + +if test "$apr_cv_define_sockaddr_storage" = "yes"; then + have_sa_storage=1 +else + have_sa_storage=0 +fi +AC_SUBST(have_sa_storage) +]) + +dnl Check for presence of struct sockaddr_in6. +AC_DEFUN(APR_CHECK_SOCKADDR_IN6,[ +AC_CACHE_CHECK(for sockaddr_in6, ac_cv_define_sockaddr_in6,[ +AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +],[ +struct sockaddr_in6 sa; +],[ + ac_cv_define_sockaddr_in6=yes +],[ + ac_cv_define_sockaddr_in6=no +]) +]) + +if test "$ac_cv_define_sockaddr_in6" = "yes"; then + have_sockaddr_in6=1 +else + have_sockaddr_in6=0 +fi +]) + +dnl +dnl APR_H_ERRNO_COMPILE_CHECK +dnl +AC_DEFUN(APR_H_ERRNO_COMPILE_CHECK,[ + if test x$1 != x; then + CPPFLAGS="-D$1 $CPPFLAGS" + fi + AC_TRY_COMPILE([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +],[ +int h_e = h_errno; +],[ + if test x$1 != x; then + ac_cv_h_errno_cppflags="$1" + else + ac_cv_h_errno_cppflags=yes + fi +],[ + ac_cv_h_errno_cppflags=no +])]) + + +dnl +dnl APR_CHECK_SCTP +dnl +dnl check for presence of SCTP protocol support +dnl +AC_DEFUN([APR_CHECK_SCTP], +[ + AC_CACHE_CHECK([whether SCTP is supported], [apr_cv_sctp], [ + AC_TRY_RUN([ +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_SCTP_H +#include +#endif +#ifdef HAVE_NETINET_SCTP_UIO_H +#include +#endif +#include +int main(void) { + int s, opt = 1; + if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_SCTP)) < 0) + exit(1); + if (setsockopt(s, IPPROTO_SCTP, SCTP_NODELAY, &opt, sizeof(int)) < 0) + exit(2); + exit(0); +}], [apr_cv_sctp=yes], [apr_cv_sctp=no], [apr_cv_sctp=no])]) + +if test "$apr_cv_sctp" = "yes"; then + have_sctp=1 +else + have_sctp=0 +fi +]) + +dnl APR_CHECK_MCAST: check for multicast interfaces +AC_DEFUN([APR_CHECK_MCAST], [ +AC_CACHE_CHECK([for struct ip_mreq], [apr_cv_struct_ipmreq], [ +AC_TRY_COMPILE([ +#include +#include +], [ + struct ip_mreq mip; + mip.imr_interface.s_addr = INADDR_ANY; +], [apr_cv_struct_ipmreq=yes], [apr_cv_struct_ipmreq=no], [apr_cv_struct_ipmreq=yes])]) + +if test $apr_cv_struct_ipmreq = yes; then + AC_DEFINE([HAVE_STRUCT_IPMREQ], 1, [Define if struct impreq was found]) +fi +]) + +dnl +dnl APR_CHECK_H_ERRNO_FLAG +dnl +dnl checks which flags are necessary for to define h_errno +dnl +AC_DEFUN(APR_CHECK_H_ERRNO_FLAG,[ + AC_MSG_CHECKING([for h_errno in netdb.h]) + AC_CACHE_VAL(ac_cv_h_errno_cppflags,[ + APR_H_ERRNO_COMPILE_CHECK + if test "$ac_cv_h_errno_cppflags" = "no"; then + ac_save="$CPPFLAGS" + for flag in _XOPEN_SOURCE_EXTENDED; do + APR_H_ERRNO_COMPILE_CHECK($flag) + if test "$ac_cv_h_errno_cppflags" != "no"; then + break + fi + done + CPPFLAGS="$ac_save" + fi + ]) + if test "$ac_cv_h_errno_cppflags" != "no"; then + if test "$ac_cv_h_errno_cppflags" != "yes"; then + CPPFLAGS="-D$ac_cv_h_errno_cppflags $CPPFLAGS" + AC_MSG_RESULT([yes, with -D$ac_cv_h_errno_cppflags]) + else + AC_MSG_RESULT([$ac_cv_h_errno_cppflags]) + fi + else + AC_MSG_RESULT([$ac_cv_h_errno_cppflags]) + fi +]) + + +AC_DEFUN(APR_EBCDIC,[ + AC_CACHE_CHECK([whether system uses EBCDIC],ac_cv_ebcdic,[ + AC_TRY_RUN( [ +int main(void) { + return (unsigned char)'A' != (unsigned char)0xC1; +} +],[ + ac_cv_ebcdic="yes" +],[ + ac_cv_ebcdic="no" +],[ + ac_cv_ebcdic="no" +])]) + if test "$ac_cv_ebcdic" = "yes"; then + apr_charset_ebcdic=1 + else + apr_charset_ebcdic=0 + fi + AC_SUBST(apr_charset_ebcdic) +]) + diff --git a/srclib/apr/build/apr_rules.mk.in b/srclib/apr/build/apr_rules.mk.in new file mode 100644 index 0000000000..233fecf87b --- /dev/null +++ b/srclib/apr/build/apr_rules.mk.in @@ -0,0 +1,207 @@ +# Copyright 2000-2005 The Apache Software Foundation or its licensors, as +# applicable. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +# +# rules.mk: standard rules for APR +# + +@SET_MAKE@ + +# +# Configuration variables +# +apr_builddir=@apr_builddir@ +apr_builders=@apr_builders@ + +# Some layouts require knowing what version we are at. +APR_MAJOR_VERSION=@APR_MAJOR_VERSION@ +APR_DOTTED_VERSION=@APR_DOTTED_VERSION@ + +CC=@CC@ +RM=@RM@ +AWK=@AWK@ +SHELL=@SHELL@ +LIBTOOL=@LIBTOOL@ + +# compilation and linking flags that are supposed to be set only by the user. +# configure adds to them for tests, but we restore them at the end. +# +CFLAGS=@CFLAGS@ +CPPFLAGS=@CPPFLAGS@ +LDFLAGS=@LDFLAGS@ +LIBS=@LIBS@ +DEFS=@DEFS@ + +# anything added to the standard flags by configure is moved to EXTRA_* +# at the end of the process. +# +EXTRA_CFLAGS=@EXTRA_CFLAGS@ +EXTRA_CPPFLAGS=@EXTRA_CPPFLAGS@ +EXTRA_LDFLAGS=@EXTRA_LDFLAGS@ +EXTRA_LIBS=@EXTRA_LIBS@ +EXTRA_INCLUDES=@EXTRA_INCLUDES@ + +# NOTEST_* are flags and libraries that can be added by the user without +# causing them to be used in configure tests (necessary for things like +# -Werror and other strict warnings that maintainers like to use). +# +NOTEST_CFLAGS=@NOTEST_CFLAGS@ +NOTEST_CPPFLAGS=@NOTEST_CPPFLAGS@ +NOTEST_LDFLAGS=@NOTEST_LDFLAGS@ +NOTEST_LIBS=@NOTEST_LIBS@ + +# Finally, combine all of the flags together in the proper order so that +# the user-defined flags can always override the configure ones, if needed. +# Note that includes are listed after the flags because -I options have +# left-to-right precedence and CPPFLAGS may include user-defined overrides. +# +ALL_CFLAGS = $(EXTRA_CFLAGS) $(NOTEST_CFLAGS) $(CFLAGS) +ALL_CPPFLAGS = $(DEFS) $(EXTRA_CPPFLAGS) $(NOTEST_CPPFLAGS) $(CPPFLAGS) +ALL_LDFLAGS = $(EXTRA_LDFLAGS) $(NOTEST_LDFLAGS) $(LDFLAGS) +ALL_LIBS = $(LIBS) $(NOTEST_LIBS) $(EXTRA_LIBS) +ALL_INCLUDES = $(INCLUDES) $(EXTRA_INCLUDES) + +LTFLAGS = @LTFLAGS@ +LT_LDFLAGS = @LT_LDFLAGS@ + +# The set of object files that will be linked into the target library. +# The build-outputs.mk specifies a different set for each platform. The +# configure script will select the appropriate set. +# +OBJECTS = @OBJECTS_PLATFORM@ + +# +# Basic macro setup +# +COMPILE = $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(ALL_INCLUDES) +LT_COMPILE = @lt_compile@ + +LINK = @link@ + +APR_MKDIR = $(apr_builders)/mkdir.sh +APR_MKEXPORT = $(AWK) -f $(apr_builders)/make_exports.awk +APR_MKVAREXPORT = $(AWK) -f $(apr_builders)/make_var_export.awk +MKDEP = @MKDEP@ + +# +# Standard build rules +# +all: all-recursive +depend: depend-recursive +clean: clean-recursive +distclean: distclean-recursive +extraclean: extraclean-recursive + +install: all-recursive + + +all-recursive depend-recursive: + @otarget=`echo $@ | sed s/-recursive//`; \ + list='$(SOURCE_DIRS)'; \ + for i in $$list; do \ + if test -f "$$i/Makefile"; then \ + target="$$otarget"; \ + echo "Making $$target in $$i"; \ + if test "$$i" = "."; then \ + made_local=yes; \ + target="local-$$target"; \ + fi; \ + (cd $$i && $(MAKE) $$target) || exit 1; \ + fi; \ + done; \ + if test "$$otarget" = "all" && test -z "$(TARGETS)"; then \ + made_local=yes; \ + fi; \ + if test "$$made_local" != "yes"; then \ + $(MAKE) "local-$$otarget" || exit 1; \ + fi + +clean-recursive distclean-recursive extraclean-recursive: + @otarget=`echo $@ | sed s/-recursive//`; \ + list='$(CLEAN_SUBDIRS)'; \ + for i in $$list; do \ + if test -f "$$i/Makefile"; then \ + target="$$otarget"; \ + echo "Making $$target in $$i"; \ + if test "$$i" = "."; then \ + made_local=yes; \ + target="local-$$target"; \ + fi; \ + (cd $$i && $(MAKE) $$target); \ + fi; \ + done; \ + if test "$$otarget" = "all" && test -z "$(TARGETS)"; then \ + made_local=yes; \ + fi; \ + if test "$$made_local" != "yes"; then \ + $(MAKE) "local-$$otarget"; \ + fi + +# autoconf 2.5x is creating a 'autom4te.cache' directory +# In case someone ran autoconf by hand, get rid of that directory +# as well. +local-clean: x-local-clean + @list='. $(SOURCE_DIRS)'; \ + for i in $$list; do \ + echo $(RM) -f $$i/*.o $$i/*.lo $$i/*.a $$i/*.la $$i/*.so $$i/*.obj; \ + $(RM) -f $$i/*.o $$i/*.lo $$i/*.a $$i/*.la $$i/*.so $$i/*.obj; \ + echo $(RM) -rf $$i/.libs; \ + $(RM) -rf $$i/.libs; \ + done + $(RM) -f $(CLEAN_TARGETS) $(PROGRAMS) + $(RM) -rf autom4te.cache + +local-distclean: local-clean x-local-distclean + $(RM) -f Makefile $(DISTCLEAN_TARGETS) + +local-extraclean: local-distclean x-local-extraclean + @if test -n "$(EXTRACLEAN_TARGETS)"; then \ + echo $(RM) -f $(EXTRACLEAN_TARGETS) ; \ + $(RM) -f $(EXTRACLEAN_TARGETS) ; \ + fi + +local-all: $(TARGETS) + +local-depend: x-local-depend + @if test -n "`ls $(srcdir)/*.c 2> /dev/null`"; then \ + $(RM) -f .deps; \ + list='$(srcdir)/*.c'; \ + for i in $$list; do \ + $(MKDEP) $(ALL_CPPFLAGS) $(ALL_INCLUDES) $$i | sed 's/\.o:/.lo:/' >> .deps; \ + done; \ + fi + +# to be filled in by the actual Makefile +x-local-depend x-local-clean x-local-distclean x-local-extraclean: + +# +# Implicit rules for creating outputs from input files +# +.SUFFIXES: +.SUFFIXES: .c .lo .o + +.c.o: + $(COMPILE) -c $< + +.c.lo: + $(LT_COMPILE) + +.PHONY: all all-recursive local-all install \ + depend depend-recursive local-depend x-local-depend \ + clean clean-recursive local-clean x-local-clean \ + distclean distclean-recursive local-distclean x-local-distclean \ + extraclean extraclean-recursive local-extraclean x-local-extraclean diff --git a/srclib/apr/build/apr_threads.m4 b/srclib/apr/build/apr_threads.m4 new file mode 100644 index 0000000000..6fd1e2348e --- /dev/null +++ b/srclib/apr/build/apr_threads.m4 @@ -0,0 +1,244 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Copyright 2000-2005 The Apache Software Foundation +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl ----------------------------------------------------------------- +dnl apr_threads.m4: APR's autoconf macros for testing thread support +dnl + +dnl +dnl APR_CHECK_PTHREADS_H([ ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +dnl gcc issues warnings when parsing AIX 4.3.3's pthread.h +dnl which causes autoconf to incorrectly conclude that +dnl pthreads is not available. +dnl Turn off warnings if we're using gcc. +dnl +AC_DEFUN(APR_CHECK_PTHREADS_H, [ + if test "$GCC" = "yes"; then + SAVE_FL="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS -w" + AC_CHECK_HEADERS(pthread.h, [ $1 ] , [ $2 ] ) + CPPFLAGS="$SAVE_FL" + else + AC_CHECK_HEADERS(pthread.h, [ $1 ] , [ $2 ] ) + fi +])dnl + + +dnl +dnl APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS +dnl +AC_DEFUN(APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS, [ +AC_CACHE_CHECK(whether pthread_getspecific takes two arguments, ac_cv_pthread_getspecific_two_args,[ +AC_TRY_COMPILE([ +#include +],[ +pthread_key_t key; +void *tmp; +pthread_getspecific(key,&tmp); +],[ + ac_cv_pthread_getspecific_two_args=yes +],[ + ac_cv_pthread_getspecific_two_args=no +]) +]) + +if test "$ac_cv_pthread_getspecific_two_args" = "yes"; then + AC_DEFINE(PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS, 1, [Define if pthread_getspecific() has two args]) +fi +])dnl + + +dnl +dnl APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG +dnl +AC_DEFUN(APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG, [ +AC_CACHE_CHECK(whether pthread_attr_getdetachstate takes one argument, ac_cv_pthread_attr_getdetachstate_one_arg,[ +AC_TRY_COMPILE([ +#include +],[ +pthread_attr_t *attr; +pthread_attr_getdetachstate(attr); +],[ + ac_cv_pthread_attr_getdetachstate_one_arg=yes +],[ + ac_cv_pthread_attr_getdetachstate_one_arg=no +]) +]) + +if test "$ac_cv_pthread_attr_getdetachstate_one_arg" = "yes"; then + AC_DEFINE(PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG, 1, [Define if pthread_attr_getdetachstate() has one arg]) +fi +])dnl + + +dnl +dnl APR_PTHREADS_TRY_RUN(actions-if-success) +dnl +dnl Try running a program which uses pthreads, executing the +dnl actions-if-success commands on success. +dnl +AC_DEFUN(APR_PTHREADS_TRY_RUN, [ +AC_TRY_RUN( [ +#include +#include + +void *thread_routine(void *data) { + return data; +} + +int main() { + pthread_t thd; + pthread_mutexattr_t mattr; + pthread_once_t once_init = PTHREAD_ONCE_INIT; + int data = 1; + pthread_mutexattr_init(&mattr); + return pthread_create(&thd, NULL, thread_routine, &data); +} ], [apr_p_t_r=yes], [apr_p_t_r=no], [apr_p_t_r=no]) + +if test $apr_p_t_r = yes; then + $1 +fi + +])dnl + + +dnl +dnl APR_PTHREADS_CHECK() +dnl +dnl Try to find a way to enable POSIX threads. Sets the +dnl pthreads_working variable to "yes" on success. +dnl +AC_DEFUN(APR_PTHREADS_CHECK,[ + +AC_CACHE_CHECK([for CFLAGS needed for pthreads], [apr_cv_pthreads_cflags], +[apr_ptc_cflags=$CFLAGS + for flag in none -kthread -pthread -pthreads -mt -mthreads -Kthread -threads; do + CFLAGS=$apr_ptc_cflags + test "x$flag" != "xnone" && CFLAGS="$CFLAGS $flag" + APR_PTHREADS_TRY_RUN([ + apr_cv_pthreads_cflags="$flag" + break + ]) + done + CFLAGS=$apr_ptc_cflags +]) + +if test -n "$apr_cv_pthreads_cflags"; then + pthreads_working=yes + if test "x$apr_cv_pthreads_cflags" != "xnone"; then + APR_ADDTO(CFLAGS,[$apr_cv_pthreads_cflags]) + fi +fi + +# The CFLAGS may or may not be sufficient to ensure that libapr +# depends on the pthreads library: some versions of libtool +# drop -pthread when passed on the link line; some versions of +# gcc ignore -pthread when linking a shared object. So always +# try and add the relevant library to LIBS too. + +AC_CACHE_CHECK([for LIBS needed for pthreads], [apr_cv_pthreads_lib], [ + apr_ptc_libs=$LIBS + for lib in -lpthread -lpthreads -lc_r; do + LIBS="$apr_ptc_libs $lib" + APR_PTHREADS_TRY_RUN([ + apr_cv_pthreads_lib=$lib + break + ]) + done + LIBS=$apr_ptc_libs +]) + +if test -n "$apr_cv_pthreads_lib"; then + pthreads_working=yes + APR_ADDTO(LIBS,[$apr_cv_pthreads_lib]) +fi + +if test "$pthreads_working" = "yes"; then + threads_result="POSIX Threads found" +else + threads_result="POSIX Threads not found" +fi +])dnl + +dnl +dnl APR_PTHREADS_CHECK_SAVE +dnl APR_PTHREADS_CHECK_RESTORE +dnl +dnl Save the global environment variables that might be modified during +dnl the checks for threading support so that they can restored if the +dnl result is not what the caller wanted. +dnl +AC_DEFUN(APR_PTHREADS_CHECK_SAVE, [ + apr_pthsv_CFLAGS="$CFLAGS" + apr_pthsv_LIBS="$LIBS" +])dnl + +AC_DEFUN(APR_PTHREADS_CHECK_RESTORE, [ + CFLAGS="$apr_pthsv_CFLAGS" + LIBS="$apr_pthsv_LIBS" +])dnl + +dnl +dnl APR_CHECK_SIGWAIT_ONE_ARG +dnl +AC_DEFUN(APR_CHECK_SIGWAIT_ONE_ARG,[ + AC_CACHE_CHECK(whether sigwait takes one argument,ac_cv_sigwait_one_arg,[ + AC_TRY_COMPILE([ +#if defined(__NETBSD__) || defined(DARWIN) + /* When using the unproven-pthreads package, we need to pull in this + * header to get a prototype for sigwait(). Else things will fail later + * on. XXX Should probably be fixed in the unproven-pthreads package. + * Darwin is declaring sigwait() in the wrong place as well. + */ +#include +#endif +#include +],[ + sigset_t set; + + sigwait(&set); +],[ + ac_cv_sigwait_one_arg=yes +],[ + ac_cv_sigwait_one_arg=no +])]) + if test "$ac_cv_sigwait_one_arg" = "yes"; then + AC_DEFINE(SIGWAIT_TAKES_ONE_ARG,1,[ ]) + fi +]) + +dnl Check for recursive mutex support (per SUSv3). +AC_DEFUN([APR_CHECK_PTHREAD_RECURSIVE_MUTEX], [ + AC_CACHE_CHECK([for recursive mutex support], [apr_cv_mutex_recursive], +[AC_TRY_RUN([#include +#include +#include + +int main() { + pthread_mutexattr_t attr; + pthread_mutex_t m; + + exit (pthread_mutexattr_init(&attr) + || pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) + || pthread_mutex_init(&m, &attr)); +}], [apr_cv_mutex_recursive=yes], [apr_cv_mutex_recursive=no], +[apr_cv_mutex_recursive=no])]) + +if test "$apr_cv_mutex_recursive" = "yes"; then + AC_DEFINE([HAVE_PTHREAD_MUTEX_RECURSIVE], 1, + [Define if recursive pthread mutexes are available]) +fi +]) diff --git a/srclib/apr/build/buildcheck.sh b/srclib/apr/build/buildcheck.sh new file mode 100755 index 0000000000..f24fa74c0b --- /dev/null +++ b/srclib/apr/build/buildcheck.sh @@ -0,0 +1,66 @@ +#! /bin/sh + +echo "buildconf: checking installation..." + +# any python +python=`build/PrintPath python` +if test -z "$python"; then +echo "buildconf: python not found." +echo " You need python installed" +echo " to build APR from CVS." +exit 1 +else +py_version=`python -c 'import sys; print sys.version' 2>&1|sed 's/ .*//;q'` +echo "buildconf: python version $py_version (ok)" +fi + +# autoconf 2.50 or newer +ac_version=`${AUTOCONF:-autoconf} --version 2>/dev/null|sed -e 's/^[^0-9]*//;s/[a-z]* *$//;q'` +if test -z "$ac_version"; then +echo "buildconf: autoconf not found." +echo " You need autoconf version 2.50 or newer installed" +echo " to build APR from CVS." +exit 1 +fi +IFS=.; set $ac_version; IFS=' ' +if test "$1" = "2" -a "$2" -lt "50" || test "$1" -lt "2"; then +echo "buildconf: autoconf version $ac_version found." +echo " You need autoconf version 2.50 or newer installed" +echo " to build APR from CVS." +exit 1 +else +echo "buildconf: autoconf version $ac_version (ok)" +fi + +# Sample libtool --version outputs: +# ltmain.sh (GNU libtool) 1.3.3 (1.385.2.181 1999/07/02 15:49:11) +# ltmain.sh (GNU libtool 1.1361 2004/01/02 23:10:52) 1.5a +# output is multiline from 1.5 onwards + +# Require libtool 1.4 or newer +libtool=`build/PrintPath glibtool libtool libtool15 libtool14` +lt_pversion=`$libtool --version 2>/dev/null|sed -e 's/([^)]*)//g;s/^[^0-9]*//;s/[- ].*//g;q'` +if test -z "$lt_pversion"; then +echo "buildconf: libtool not found." +echo " You need libtool version 1.4 or newer installed" +echo " to build APR from CVS." +exit 1 +fi +lt_version=`echo $lt_pversion|sed -e 's/\([a-z]*\)$/.\1/'` +IFS=.; set $lt_version; IFS=' ' +lt_status="good" +if test "$1" = "1"; then + if test "$2" -lt "4"; then + lt_status="bad" + fi +fi +if test $lt_status = "good"; then + echo "buildconf: libtool version $lt_pversion (ok)" + exit 0 +fi + +echo "buildconf: libtool version $lt_pversion found." +echo " You need libtool version 1.4 or newer installed" +echo " to build APR from CVS." + +exit 1 diff --git a/srclib/apr/build/config.guess b/srclib/apr/build/config.guess new file mode 100755 index 0000000000..a6d8a945f6 --- /dev/null +++ b/srclib/apr/build/config.guess @@ -0,0 +1,1449 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + +timestamp='2004-06-24' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amd64:OpenBSD:*:*) + echo x86_64-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + cats:OpenBSD:*:*) + echo arm-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + luna88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit 0 ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && exit 0 + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + # avoid double evaluation of $set_cc_for_build + test -n "$CC_FOR_BUILD" || eval $set_cc_for_build + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E -) | grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && $dummy && exit 0 + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:[34]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit 0 ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && echo "${CPU}-unknown-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit 0 ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + case `uname -p` in + *86) UNAME_PROCESSOR=i686 ;; + powerpc) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit 0 ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms && exit 0 ;; + I*) echo ia64-dec-vms && exit 0 ;; + V*) echo vax-dec-vms && exit 0 ;; + esac +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && $dummy && exit 0 + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/srclib/apr/build/config.sub b/srclib/apr/build/config.sub new file mode 100755 index 0000000000..ac6de9869c --- /dev/null +++ b/srclib/apr/build/config.sub @@ -0,0 +1,1552 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + +timestamp='2004-06-24' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | msp430 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/srclib/apr/build/cvtdsp.pl b/srclib/apr/build/cvtdsp.pl new file mode 100644 index 0000000000..524ba90b2d --- /dev/null +++ b/srclib/apr/build/cvtdsp.pl @@ -0,0 +1,490 @@ +use IO::File; +use File::Find; + +if ($ARGV[0] eq '-6') { + find(\&tovc6, '.'); +} +elsif ($ARGV[0] eq '-5') { + find(\&tovc5, '.'); +} +elsif ($ARGV[0] eq '-w3') { + find(\&tow3, '.'); +} +elsif ($ARGV[0] eq '-w4') { + find(\&tow4, '.'); +} +elsif ($ARGV[0] eq '-ia64') { + find(\&tovc64, '.'); +} +elsif ($ARGV[0] eq '-d') { + find(\&todebugpools, '.'); +} +elsif ($ARGV[0] eq '-b') { + find(\&tobrowse, '.'); +} +elsif ($ARGV[0] eq '-m') { + ## 0 - conapp, 1 - dll lib, 2 - static lib + $dsptype = 2; + $name = "apr"; + onemake(); +} +else { + print "Specify -5 or -6 for Visual Studio 5 or 6 (98) .dsp format\n"; + print "Specify -w3 or -w4 for .dsp build with warning level 3 or 4 (strict)\n\n"; + print "Specify -ia64 for build targeted at Itanium (req's psdk tools)\n\n"; + print "Specify -p for extreme pool debugging\n\n"; + die "Missing argument"; +} + +sub tovc5 { + + if (m|\.dsp$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $oname, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ s|Format Version 6\.00|Format Version 5\.00|) { + $verchg = -1; + } + if ($src =~ s|^(# ADD CPP .*)/ZI (.*)|$1/Zi $2|) { + $verchg = -1; + } + if ($src =~ s|^(# ADD BASE CPP .*)/ZI (.*)|$1/Zi $2|) { + $verchg = -1; + } + if ($src !~ m|^# PROP AllowPerConfigDependencies|) { + print $dstfl $src; } + else { + $verchg = -1; + } + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted VC6 project " . $oname . " to VC5 in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub tovc6 { + + if (m|\.dsp$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $_, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ s|Format Version 5\.00|Format Version 6\.00|) { + $verchg = -1; + } + if ($src =~ s|^(!MESSAGE .*)\\\n|$1|) { + $cont = <$srcfl>; + $src = $src . $cont; + $verchg = -1; + } + print $dstfl $src; + if ($verchg && $src =~ m|^# Begin Project|) { + print $dstfl "# PROP AllowPerConfigDependencies 0\n"; + } + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted VC5 project " . $oname . " to VC6 in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub tow3 { + + if (m|\.dsp$| || m|\.mak$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $_, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + while ($src =~ m|\\\n$|) { + $src = $src . <$srcfl> + } + if ($src =~ s|(\bCPP.*) /W4(.*)|$1 /W3$2|) { + $verchg = -1; + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted project " . $oname . " to warn:3 in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub tow4 { + + if (m|\.dsp$| || m|\.mak$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $_, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + while ($src =~ m|\\\n$|) { + $src = $src . <$srcfl> + } + if ($src =~ s|(\bCPP.*) /W3(.*)|$1 /W4$2|) { + $verchg = -1; + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted project " . $oname . " to warn:4 " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub tovc64 { + + if (m|\.dsp$| || m|\.mak$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $_, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + while ($src =~ m|\\\n$|) { + $src = $src . <$srcfl> + } + if ($src =~ s|Win32 \(x86\) (Release)|Win32 (IA64) $1|s) { + $verchg = -1; + } + if ($src =~ s|Win32 \(x86\) (Debug)|Win32 (IA64) $1|s) { + $verchg = -1; + } + if ($src =~ s| - Win32 (Release)| - Win32 (IA64) $1|s) { + $verchg = -1; + } + if ($src =~ s| - Win32 (Debug)| - Win32 (IA64) $1|s) { + $verchg = -1; + } + # Cross compilation exceptions + if (!(m|gen[^/]*$| || m|dftables[^/]*$|)) { + if ($src =~ s|(\bCPP.* /W3)(.*) /FD(.*)|$1 /As64 /Wp64$2$3|s) { + $verchg = -1; + } + if ($src =~ s|(\bLINK.*/machine):I386(.*)|$1:IA64$2|s) { + $verchg = -1; + } + } + else { + if ($src =~ s|(\bCPP.* /W3)(.*) /FD(.*)|$1 /As32 /Wp64$2$3|s) { + $verchg = -1; + } + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted build file " . $oname . " to Win64 in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub todebugpools { + + if (m|\.dsp$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $oname, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ s|^(# ADD CPP .* /D "_DEBUG" )|$1/D "APR_POOL_DEBUG" |) { + $verchg = -1; + if ($oname =~ /apr\.dsp$/) { + $src =~ s|^(# ADD CPP .* /D "_DEBUG" )|$1/D "POOL_DEBUG" |; + } + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted project " . $oname . " to debug pools in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub tobrowsesources { + + if (m|\.dsp$|) { + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; + $srcfl = new IO::File $oname, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ s|^(# ADD CPP .*)( /Fd)|$1 /Fr "/httpd-2.0/srclib/apr"$2|) { + $verchg = -1; + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted project " . $oname . " to browse sources in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + +sub frommakefiles { + + if (m|\.mak\.in$|) { + $oname = $_; + $dname = $_; + $_ =~ s/\.mak\.in/.dsp/; + $verchg = 0; + $srcfl = new IO::File $oname, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ s|^(# ADD CPP .*)( /Fd)|$1 /Fr "/httpd-2.0/srclib/apr"$2|) { + $verchg = -1; + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Converted project " . $oname . " to browse sources in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + } +} + + +sub onemake { + + if ($dsptype == 0) { + $cdefs = qq{/D "WIN32" /D "_CONSOLE"}; + $lmodel = qq{/subsystem:console}; + $targname = "Win32 (x86) Console Application"; + $targid = "0x0103"; + $debpath = "Debug"; $relpath = "Release"; + } elsif ($dsptype == 1) { + $cdefs = qq{/D "WIN32" /D "_WINDOWS"}; + $lmodel = qq{/subsystem:windows /dll}; + $targname = "Win32 (x86) Dynamic-Link Library"; + $targid = "0x0102"; + $debpath = "Debug"; $relpath = "Release"; + } elsif($dsptype == 2) { + $cdefs = qq{/D "WIN32" /D "_CONSOLE"}; + $lmodel = qq{/subsystem:console}; + $targname = "Win32 (x86) Static Library"; + $targid = "0x0104"; + $debpath = "LibD"; $relpath = "LibR"; + } + $file = dspheader(); + + + $second = ""; + + $model = "Release"; + $usedebuglib = "0"; + $debugdef = "NDEBUG"; + $cflags = "/MD /W3 /O2"; + $cincl = qq{/I "./include" /I "./os/win32" /I "./srclib/apr/include" /I "./srclib/apr-util/include"}; + $lflags = qq{/map}; + $file .= dsponemodel(); + + $second = "ELSE"; + $model = "Debug"; + $usedebuglib = "1"; + $debugdef = "_DEBUG"; + $cflags = "/MDd /W3 /GX /Zi /Od"; + $cincl = qq{/I "./include" /I "./os/win32" /I "./srclib/apr/include" /I "./srclib/apr-util/include"}; + $lflags = qq{/incremental:no /debug}; + $file .= dsponemodel(); + + $file .= qq{ +!ENDIF + +# Begin Target + +# Name "$name - Win32 Release" +# Name "$name - Win32 Debug" +}; + + $toroot = "."; + +#HERE IS OUR FOREACH! + $file .= qq{# Begin Source File + +SOURCE=./server/main.c +# End Source File +}; + + if ($dsptype == 0) { + #HERE IS OUR ICON! + $icon="$toroot/build/win32/apache.ico"; + $file .= qq{# Begin Source File + +SOURCE=$icon +# End Source File +}; + $icon = "icon=" . $icon . " "; + } + if ($dsptype == 0 || $dsptype == 1) { + $file .= qq{ +# Begin Source File + +SOURCE=./$name.rc +# End Source File +# Begin Source File + +SOURCE=$toroot/include/ap_release.h +# PROP Ignore_Default_Tool 1 +# Begin Custom Build - Creating Version Resource +InputPath=$toroot/include/ap_release.h $toroot/build/win32/win32ver.awk + +"./$name.rc" : \$(SOURCE) "\$(INTDIR)" "\$(OUTDIR)" + awk -f $toroot/build/win32/win32ver.awk $name "Apache HTTP Server" $toroot/include/ap_release.h $icon> ./Apache.rc + +# End Custom Build +# End Source File +}; + } + $file .= qq{ +# End Target +# End Project +}; + print $file; +} + +sub dspheader { + if ($dsptype == 1) { + $midl = "MTL=midl.exe\n"; + } else { + $midl = "" + } +qq{# Microsoft Developer Studio Project File - Name="$name" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "$targname" $targid + +CFG=$name - Win32 Release +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "$name.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "$name.mak" CFG="$name - Win32 Release" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "$name - Win32 Release" (based on "$targname") +!MESSAGE "$name - Win32 Debug" (based on "$targname") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +${midl}RSC=rc.exe +}; +} +sub dsponemodel { + if ($model eq "Release") { + $targpath = $relpath; + } else { + $targpath = $debpath; + } + if ($dsptype == 1) { + $midl = +qq{# ADD BASE MTL /nologo /D "$debugdef" /win32 +# ADD MTL /nologo /D "$debugdef" /mktyplib203 /win32 +}; } + if ($dsptype == 2) { + $linkop = qq{LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo +}; + } else { + $linkop = qq{LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo $lmodel $lflags /machine:I386 +# ADD LINK32 kernel32.lib user32.lib advapi32.lib ws2_32.lib mswsock.lib /nologo $lmodel $lflags /machine:I386 +}; + } + +qq{ +!${second}IF "\$(CFG)" == "$name - Win32 $model" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries $usedebuglib +# PROP BASE Output_Dir "$targpath" +# PROP BASE Intermediate_Dir "$targpath" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries $usedebuglib +# PROP Output_Dir "$targpath" +# PROP Intermediate_Dir "$targpath" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo $cflags $cincl /D "$debugdef" $cdefs /FD /c +# ADD CPP /nologo $cflags $cincl /D "$debugdef" $cdefs /Fd"$targpath/$name" /FD /c +${midl}# ADD BASE RSC /l 0x409 /d "$debugdef" +# ADD RSC /l 0x409 /d "$debugdef" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +$linkop}; +} \ No newline at end of file diff --git a/srclib/apr/build/find_apr.m4 b/srclib/apr/build/find_apr.m4 new file mode 100644 index 0000000000..117fb06f25 --- /dev/null +++ b/srclib/apr/build/find_apr.m4 @@ -0,0 +1,166 @@ +dnl -------------------------------------------------------- -*- autoconf -*- +dnl Copyright 2000-2005 The Apache Software Foundation +dnl +dnl Licensed under the Apache License, Version 2.0 (the "License"); +dnl you may not use this file except in compliance with the License. +dnl You may obtain a copy of the License at +dnl +dnl http://www.apache.org/licenses/LICENSE-2.0 +dnl +dnl Unless required by applicable law or agreed to in writing, software +dnl distributed under the License is distributed on an "AS IS" BASIS, +dnl WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +dnl See the License for the specific language governing permissions and +dnl limitations under the License. + +dnl +dnl find_apr.m4 : locate the APR include files and libraries +dnl +dnl This macro file can be used by applications to find and use the APR +dnl library. It provides a standardized mechanism for using APR. It supports +dnl embedding APR into the application source, or locating an installed +dnl copy of APR. +dnl +dnl APR_FIND_APR(srcdir, builddir, implicit-install-check, acceptable-majors) +dnl +dnl where srcdir is the location of the bundled APR source directory, or +dnl empty if source is not bundled. +dnl +dnl where builddir is the location where the bundled APR will will be built, +dnl or empty if the build will occur in the srcdir. +dnl +dnl where implicit-install-check set to 1 indicates if there is no +dnl --with-apr option specified, we will look for installed copies. +dnl +dnl where acceptable-majors is a space separated list of acceptable major +dnl version numbers. Often only a single major version will be acceptable. +dnl If multiple versions are specified, and --with-apr=PREFIX or the +dnl implicit installed search are used, then the first (leftmost) version +dnl in the list that is found will be used. Currently defaults to [0 1]. +dnl +dnl Sets the following variables on exit: +dnl +dnl apr_found : "yes", "no", "reconfig" +dnl +dnl apr_config : If the apr-config tool exists, this refers to it. If +dnl apr_found is "reconfig", then the bundled directory +dnl should be reconfigured *before* using apr_config. +dnl +dnl Note: this macro file assumes that apr-config has been installed; it +dnl is normally considered a required part of an APR installation. +dnl +dnl If a bundled source directory is available and needs to be (re)configured, +dnl then apr_found is set to "reconfig". The caller should reconfigure the +dnl (passed-in) source directory, placing the result in the build directory, +dnl as appropriate. +dnl +dnl If apr_found is "yes" or "reconfig", then the caller should use the +dnl value of apr_config to fetch any necessary build/link information. +dnl + +AC_DEFUN([APR_FIND_APR], [ + apr_found="no" + + if test "$target_os" = "os2-emx"; then + # Scripts don't pass test -x on OS/2 + TEST_X="test -f" + else + TEST_X="test -x" + fi + + ifelse([$4], [], [ + ifdef(AC_WARNING,AC_WARNING([$0: missing argument 4 (acceptable-majors): Defaulting to APR 0.x then APR 1.x])) + acceptable_majors="0 1"], + [acceptable_majors="$4"]) + + apr_temp_acceptable_apr_config="" + for apr_temp_major in $acceptable_majors + do + case $apr_temp_major in + 0) + apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-config" + ;; + *) + apr_temp_acceptable_apr_config="$apr_temp_acceptable_apr_config apr-$apr_temp_major-config" + ;; + esac + done + + AC_MSG_CHECKING(for APR) + AC_ARG_WITH(apr, + [ --with-apr=PATH prefix for installed APR, path to APR build tree, + or the full path to apr-config], + [ + if test "$withval" = "no" || test "$withval" = "yes"; then + AC_MSG_ERROR([--with-apr requires a directory or file to be provided]) + fi + + for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config + do + for lookdir in "$withval/bin" "$withval" + do + if $TEST_X "$lookdir/$apr_temp_apr_config_file"; then + apr_found="yes" + apr_config="$lookdir/$apr_temp_apr_config_file" + break 2 + fi + done + done + + if test "$apr_found" != "yes" && $TEST_X "$withval" && $withval --help > /dev/null 2>&1 ; then + apr_found="yes" + apr_config="$withval" + fi + + dnl if --with-apr is used, it is a fatal error for its argument + dnl to be invalid + if test "$apr_found" != "yes"; then + AC_MSG_ERROR([the --with-apr parameter is incorrect. It must specify an install prefix, a build directory, or an apr-config file.]) + fi + ],[ + dnl If we allow installed copies, check those before using bundled copy. + if test -n "$3" && test "$3" = "1"; then + for apr_temp_apr_config_file in $apr_temp_acceptable_apr_config + do + if $apr_temp_apr_config_file --help > /dev/null 2>&1 ; then + apr_found="yes" + apr_config="$apr_temp_apr_config_file" + break + else + dnl look in some standard places + for lookdir in /usr /usr/local /usr/local/apr /opt/apr /usr/local/apache2; do + if $TEST_X "$lookdir/bin/$apr_temp_apr_config_file"; then + apr_found="yes" + apr_config="$lookdir/bin/$apr_temp_apr_config_file" + break 2 + fi + done + fi + done + fi + dnl if we have not found anything yet and have bundled source, use that + if test "$apr_found" = "no" && test -d "$1"; then + apr_temp_abs_srcdir="`cd $1 && pwd`" + apr_found="reconfig" + apr_bundled_major="`sed -n '/#define.*APR_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p' \"$1/include/apr_version.h\"`" + case $apr_bundled_major in + "") + AC_MSG_ERROR([failed to find major version of bundled APR]) + ;; + 0) + apr_temp_apr_config_file="apr-config" + ;; + *) + apr_temp_apr_config_file="apr-$apr_bundled_major-config" + ;; + esac + if test -n "$2"; then + apr_config="$2/$apr_temp_apr_config_file" + else + apr_config="$1/$apr_temp_apr_config_file" + fi + fi + ]) + + AC_MSG_RESULT($apr_found) +]) diff --git a/srclib/apr/build/fixwin32mak.pl b/srclib/apr/build/fixwin32mak.pl new file mode 100644 index 0000000000..9ee8918e90 --- /dev/null +++ b/srclib/apr/build/fixwin32mak.pl @@ -0,0 +1,76 @@ +# +# fixwin32mak.pl ::: Apache/Win32 maintanace program +# +# This program, launched from the build/ directory, replaces all nasty absoulute paths +# in the win32 .mak files with the appropriate relative root. +# +# Run this program prior to committing or packaging any newly exported make files. + +use Cwd; +use IO::File; +use File::Find; + +$root = cwd; +# ignore our own direcory (allowing us to move into any parallel tree) +$root =~ s|^.:(.*)?$|cd "$1|; +$root =~ s|/|\\\\|g; +print "Testing " . $root . "\n"; +find(\&fixcwd, '.'); + +sub fixcwd { + if (m|.mak$|) { + $thisroot = $File::Find::dir; + $thisroot =~ s|^./(.*)$|$1|; + $thisroot =~ s|/|\\\\|g; + $thisroot = $root . "\\\\" . $thisroot; + $oname = $_; + $tname = '.#' . $_; + $verchg = 0; +#print "Processing " . $thisroot . " of " . $_ . "\n"; + $srcfl = new IO::File $_, "r" || die; + $dstfl = new IO::File $tname, "w" || die; + while ($src = <$srcfl>) { + if ($src =~ m|^\s*($root[^\"]*)\".*$|) { +#print "Found " . $1 . "\"\n"; + $orig = $thisroot; + $repl = "cd \"."; + while (!($src =~ s|$orig|$repl|)) { +#print "Tried replacing " . $orig . " with " . $repl . "\n"; + if (!($orig =~ s|^(.*)\\\\[^\\]+$|$1|)) { + break; + } + $repl .= "\\.."; + } +#print "Replaced " . $orig . " with " . $repl . "\n"; + $verchg = -1; + } + print $dstfl $src; + } + undef $srcfl; + undef $dstfl; + if ($verchg) { + unlink $oname || die; + rename $tname, $oname || die; + print "Corrected absolute paths within " . $oname . " in " . $File::Find::dir . "\n"; + } + else { + unlink $tname; + } + $dname = $oname; + $dname =~ s/.mak$/.dsp/; + @dstat = stat($dname); + @ostat = stat($oname); + if ($ostat[9] && $dstat[9] && ($ostat[9] != $dstat[9])) { + @onames = ($oname); + utime $dstat[9], $dstat[9], @onames; + print "Touched datestamp for " . $oname . " in " . $File::Find::dir . "\n"; + } + $oname =~ s/.mak$/.dep/; + @ostat = stat($oname); + if ($ostat[9] && $dstat[9] && ($ostat[9] != $dstat[9])) { + @onames = ($oname); + utime $dstat[9], $dstat[9], @onames; + print "Touched datestamp for " . $oname . " in " . $File::Find::dir . "\n"; + } + } +} diff --git a/srclib/apr/build/gen-build.py b/srclib/apr/build/gen-build.py new file mode 100755 index 0000000000..8582741de8 --- /dev/null +++ b/srclib/apr/build/gen-build.py @@ -0,0 +1,172 @@ +#!/usr/bin/env python +# +# USAGE: gen-build.py TYPE +# +# where TYPE is one of: make, dsp, vcproj +# +# It reads build.conf from the current directory, and produces its output +# into the current directory. +# + + +import os +import ConfigParser +import getopt +import string +import glob +import re + +#import ezt + +# +# legal platforms: aix, beos, netware, os2, os390, unix, win32 +# 'make' users: aix, beos, os2, os390, unix +# +PLATFORMS = [ 'aix', 'beos', 'netware', 'os2', 'os390', 'unix', 'win32' ] +MAKE_PLATFORMS = [ + ('unix', None), + ('aix', 'unix'), + ('beos', 'unix'), + ('os2', 'unix'), + ('os390', 'unix'), + ] +# note: MAKE_PLATFORMS is an ordered set. we want to generate unix symbols +# first, so that the later platforms can reference them. + + +def main(): + parser = ConfigParser.ConfigParser() + parser.read('build.conf') + + headers = get_files(parser.get('options', 'headers')) + + # compute the relevant headers, along with the implied includes + legal_deps = { } + for fname in headers: + legal_deps[os.path.basename(fname)] = fname + + h_deps = { } + for fname in headers: + h_deps[os.path.basename(fname)] = extract_deps(fname, legal_deps) + resolve_deps(h_deps) + + f = open('build-outputs.mk', 'w') + f.write('# DO NOT EDIT. AUTOMATICALLY GENERATED.\n\n') + + # write out the platform-independent files + files = get_files(parser.get('options', 'paths')) + objects, dirs = write_objects(f, legal_deps, h_deps, files) + f.write('\nOBJECTS_all = %s\n\n' % string.join(objects)) + + # for each platform and each subdirectory holding platform-specific files, + # write out their compilation rules, and an OBJECT__ symbol. + for platform, parent in MAKE_PLATFORMS: + + # record the object symbols to build for each platform + group = [ '$(OBJECTS_all)' ] + + for subdir in string.split(parser.get('options', 'platform_dirs')): + path = '%s/%s' % (subdir, platform) + if not os.path.exists(path): + # this subdir doesn't have a subdir for this platform, so we'll + # use the parent-platform's set of symbols + if parent: + group.append('$(OBJECTS_%s_%s)' % (subdir, parent)) + continue + + # remember that this directory has files/objects + dirs[path] = None + + # write out the compilation lines for this subdir + files = get_files(path + '/*.c') + objects, _unused = write_objects(f, legal_deps, h_deps, files) + + symname = 'OBJECTS_%s_%s' % (subdir, platform) + + # and write the symbol for the whole group + f.write('\n%s = %s\n\n' % (symname, string.join(objects))) + + # and include that symbol in the group + group.append('$(%s)' % symname) + + # write out a symbol which contains the necessary files + f.write('OBJECTS_%s = %s\n\n' % (platform, string.join(group))) + + f.write('HEADERS = $(top_srcdir)/%s\n\n' % string.join(headers, ' $(top_srcdir)/')) + f.write('SOURCE_DIRS = %s $(EXTRA_SOURCE_DIRS)\n\n' % string.join(dirs.keys())) + + # Build a list of all necessary directories in build tree + alldirs = { } + for dir in dirs.keys(): + d = dir + while d: + alldirs[d] = None + d = os.path.dirname(d) + + # Sort so 'foo' is before 'foo/bar' + keys = alldirs.keys() + keys.sort() + f.write('BUILD_DIRS = %s\n\n' % string.join(keys)) + + f.write('.make.dirs: $(srcdir)/build-outputs.mk\n' \ + '\t@for d in $(BUILD_DIRS); do test -d $$d || mkdir $$d; done\n' \ + '\t@echo timestamp > $@\n') + + +def write_objects(f, legal_deps, h_deps, files): + dirs = { } + objects = [ ] + + for file in files: + assert file[-2:] == '.c' + obj = file[:-2] + '.lo' + objects.append(obj) + + dirs[os.path.dirname(file)] = None + + # what headers does this file include, along with the implied headers + deps = extract_deps(file, legal_deps) + for hdr in deps.keys(): + deps.update(h_deps.get(hdr, {})) + + f.write('%s: %s .make.dirs %s\n' % (obj, file, string.join(deps.values()))) + + return objects, dirs + + +def extract_deps(fname, legal_deps): + "Extract the headers this file includes." + deps = { } + for line in open(fname).readlines(): + if line[:8] != '#include': + continue + inc = _re_include.match(line).group(1) + if inc in legal_deps.keys(): + deps[inc] = legal_deps[inc] + return deps +_re_include = re.compile('#include *["<](.*)[">]') + + +def resolve_deps(header_deps): + "Alter the provided dictionary to flatten includes-of-includes." + altered = 1 + while altered: + altered = 0 + for hdr, deps in header_deps.items(): + # print hdr, deps + start = len(deps) + for dep in deps.keys(): + deps.update(header_deps.get(dep, {})) + if len(deps) != start: + altered = 1 + + +def get_files(patterns): + files = [ ] + for pat in string.split(patterns): + files.extend(glob.glob(pat)) + return files + + +if __name__ == '__main__': + main() diff --git a/srclib/apr/build/get-version.sh b/srclib/apr/build/get-version.sh new file mode 100755 index 0000000000..fd685b22a8 --- /dev/null +++ b/srclib/apr/build/get-version.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# extract version numbers from a header file +# +# USAGE: get-version.sh CMD VERSION_HEADER PREFIX +# where CMD is one of: all, major, libtool +# where PREFIX is the prefix to {MAJOR|MINOR|PATCH}_VERSION defines +# +# get-version.sh all returns a dotted version number +# get-version.sh major returns just the major version number +# get-version.sh libtool returns a version "libtool -version-info" format +# + +if test $# != 3; then + echo "USAGE: $0 CMD VERSION_HEADER PREFIX" + echo " where CMD is one of: all, major, libtool" + exit 1 +fi + +major_sed="/#define.*$3_MAJOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" +minor_sed="/#define.*$3_MINOR_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" +patch_sed="/#define.*$3_PATCH_VERSION/s/^[^0-9]*\([0-9]*\).*$/\1/p" +major="`sed -n $major_sed $2`" +minor="`sed -n $minor_sed $2`" +patch="`sed -n $patch_sed $2`" + +if test "$1" = "all"; then + echo ${major}.${minor}.${patch} +elif test "$1" = "major"; then + echo ${major} +elif test "$1" = "libtool"; then + # Yes, ${minor}:${patch}:${minor} is correct due to libtool idiocy. + echo ${minor}:${patch}:${minor} +else + echo "ERROR: unknown version CMD ($1)" + exit 1 +fi diff --git a/srclib/apr/build/install.sh b/srclib/apr/build/install.sh new file mode 100755 index 0000000000..9a8821fa29 --- /dev/null +++ b/srclib/apr/build/install.sh @@ -0,0 +1,112 @@ +#!/bin/sh +## +## install.sh -- install a program, script or datafile +## +## Based on `install-sh' from the X Consortium's X11R5 distribution +## as of 89/12/18 which is freely available. +## Cleaned up for Apache's Autoconf-style Interface (APACI) +## by Ralf S. Engelschall +## +# +# This script falls under the Apache License. +# See http://www.apache.org/docs/LICENSE + + +# +# put in absolute paths if you don't have them in your path; +# or use env. vars. +# +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" + +# +# parse argument line +# +instcmd="$mvprog" +chmodcmd="" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +ext="" +src="" +dst="" +while [ "x$1" != "x" ]; do + case $1 in + -c) instcmd="$cpprog" + shift; continue + ;; + -m) chmodcmd="$chmodprog $2" + shift; shift; continue + ;; + -o) chowncmd="$chownprog $2" + shift; shift; continue + ;; + -g) chgrpcmd="$chgrpprog $2" + shift; shift; continue + ;; + -s) stripcmd="$stripprog" + shift; continue + ;; + -S) stripcmd="$stripprog $2" + shift; shift; continue + ;; + -e) ext="$2" + shift; shift; continue + ;; + *) if [ "x$src" = "x" ]; then + src=$1 + else + dst=$1 + fi + shift; continue + ;; + esac +done +if [ "x$src" = "x" ]; then + echo "install.sh: no input file specified" + exit 1 +fi +if [ "x$dst" = "x" ]; then + echo "install.sh: no destination specified" + exit 1 +fi + +# +# If destination is a directory, append the input filename; if +# your system does not like double slashes in filenames, you may +# need to add some logic +# +if [ -d $dst ]; then + dst="$dst/`basename $src`" +fi + +# Add a possible extension (such as ".exe") to src and dst +src="$src$ext" +dst="$dst$ext" + +# Make a temp file name in the proper directory. +dstdir=`dirname $dst` +dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name +$instcmd $src $dsttmp + +# And set any options; do chmod last to preserve setuid bits +if [ "x$chowncmd" != "x" ]; then $chowncmd $dsttmp; fi +if [ "x$chgrpcmd" != "x" ]; then $chgrpcmd $dsttmp; fi +if [ "x$stripcmd" != "x" ]; then $stripcmd $dsttmp; fi +if [ "x$chmodcmd" != "x" ]; then $chmodcmd $dsttmp; fi + +# Now rename the file to the real destination. +$rmcmd $dst +$mvcmd $dsttmp $dst + +exit 0 + diff --git a/srclib/apr/build/jlibtool.c b/srclib/apr/build/jlibtool.c new file mode 100644 index 0000000000..b21c40dec3 --- /dev/null +++ b/srclib/apr/build/jlibtool.c @@ -0,0 +1,1857 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __EMX__ +# define SHELL_CMD "sh" +# define GEN_EXPORTS "emxexp" +# define DEF2IMPLIB_CMD "emximp" +# define SHARE_SW "-Zdll -Zmtd" +# define USE_OMF 1 +# define TRUNCATE_DLL_NAME +# define DYNAMIC_LIB_EXT "dll" +# define EXE_EXT ".exe" + +# if USE_OMF + /* OMF is the native format under OS/2 */ +# define STATIC_LIB_EXT "lib" +# define OBJECT_EXT "obj" +# define LIBRARIAN "emxomfar" +# define LIBRARIAN_OPTS "cr" +# else + /* but the alternative, a.out, can fork() which is sometimes necessary */ +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +# endif +#endif + +#if defined(__APPLE__) +# define SHELL_CMD "/bin/sh" +# define DYNAMIC_LIB_EXT "dylib" +# define MODULE_LIB_EXT "so" +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +/* man libtool(1) documents ranlib option of -c. */ +# define RANLIB "ranlib" +# define PIC_FLAG "-fPIC -fno-common" +# define SHARED_OPTS "-dynamiclib" +# define MODULE_OPTS "-bundle" +# define DYNAMIC_LINK_OPTS "-flat_namespace -undefined suppress" +# define dynamic_link_version_func darwin_dynamic_link_function +# define DYNAMIC_INSTALL_NAME "-install_name" +# define DYNAMIC_LINK_NO_INSTALL "-dylib_file" +# define HAS_REALPATH +/*-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 */ +# define LD_LIBRARY_PATH "DYLD_LIBRARY_PATH" +#endif + +#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) +# define SHELL_CMD "/bin/sh" +# define DYNAMIC_LIB_EXT "so" +# define MODULE_LIB_EXT "so" +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +# define RANLIB "ranlib" +# define PIC_FLAG "-fPIC" +# define RPATH "-rpath" +# define SHARED_OPTS "-shared" +# define MODULE_OPTS "-shared" +# define DYNAMIC_LINK_OPTS "-export-dynamic" +# define LINKER_FLAG_PREFIX "-Wl," +# define ADD_MINUS_L +# define LD_RUN_PATH "LD_RUN_PATH" +# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" +#endif + +#if defined(sun) +# define SHELL_CMD "/bin/sh" +# define DYNAMIC_LIB_EXT "so" +# define MODULE_LIB_EXT "so" +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +# define RANLIB "ranlib" +# define PIC_FLAG "-KPIC" +# define RPATH "-R" +# define SHARED_OPTS "-G" +# define MODULE_OPTS "-G" +# define DYNAMIC_LINK_OPTS "" +# define LINKER_FLAG_NO_EQUALS +# define ADD_MINUS_L +# define HAS_REALPATH +# define LD_RUN_PATH "LD_RUN_PATH" +# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" +#endif + +#if defined(_OSD_POSIX) +# define SHELL_CMD "/usr/bin/sh" +# define DYNAMIC_LIB_EXT "so" +# define MODULE_LIB_EXT "so" +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +# define SHARED_OPTS "-G" +# define MODULE_OPTS "-G" +# define LINKER_FLAG_PREFIX "-Wl," +# define NEED_SNPRINTF +#endif + +#if defined(sinix) && defined(mips) && defined(__SNI_TARG_UNIX) +# define SHELL_CMD "/usr/bin/sh" +# define DYNAMIC_LIB_EXT "so" +# define MODULE_LIB_EXT "so" +# define STATIC_LIB_EXT "a" +# define OBJECT_EXT "o" +# define LIBRARIAN "ar" +# define LIBRARIAN_OPTS "cr" +# define RPATH "-Brpath" +# define SHARED_OPTS "-G" +# define MODULE_OPTS "-G" +# define DYNAMIC_LINK_OPTS "-Wl,-Blargedynsym" +# define LINKER_FLAG_PREFIX "-Wl," +# define NEED_SNPRINTF +# define LD_RUN_PATH "LD_RUN_PATH" +# define LD_LIBRARY_PATH "LD_LIBRARY_PATH" +#endif + +#ifndef SHELL_CMD +#error Unsupported platform: Please add defines for SHELL_CMD etc. for your platform. +#endif + +#ifdef NEED_SNPRINTF +#include +#endif + +#ifdef __EMX__ +#include +#endif + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + + +/* We want to say we are libtool 1.4 for shlibtool compatibility. */ +#define VERSION "1.4" + +enum tool_mode_t { + mUnknown, + mCompile, + mLink, + mInstall, +}; + +enum output_t { + otGeneral, + otObject, + otProgram, + otLibrary, + otStaticLibraryOnly, + otDynamicLibraryOnly, + otModule, +}; + +enum pic_mode_e { + pic_UNKNOWN, + pic_PREFER, + pic_AVOID, +}; + +enum lib_type { + type_UNKNOWN, + type_DYNAMIC_LIB, + type_STATIC_LIB, + type_MODULE_LIB, + type_OBJECT, +}; + +typedef struct { + const char **vals; + int num; +} count_chars; + +typedef struct { + const char *normal; + const char *install; +} library_name; + +typedef struct { + count_chars *normal; + count_chars *install; + count_chars *dependencies; +} library_opts; + +typedef struct { + int silent; + int shared; + int export_all; + int dry_run; + enum pic_mode_e pic_mode; + int export_dynamic; + int no_install; +} options_t; + +typedef struct { + enum tool_mode_t mode; + enum output_t output; + options_t options; + + char *output_name; + char *fake_output_name; + char *basename; + + const char *install_path; + const char *compiler; + const char *program; + count_chars *program_opts; + + count_chars *arglist; + count_chars *tmp_dirs; + count_chars *obj_files; + count_chars *dep_rpaths; + count_chars *rpaths; + + library_name static_name; + library_name shared_name; + library_name module_name; + + library_opts static_opts; + library_opts shared_opts; + + const char *version_info; +} command_t; + +#ifdef RPATH +void add_rpath(count_chars *cc, const char *path); +#endif + +#if defined(NEED_SNPRINTF) +/* Write at most n characters to the buffer in str, return the + * number of chars written or -1 if the buffer would have been + * overflowed. + * + * This is portable to any POSIX-compliant system has /dev/null + */ +static FILE *f=NULL; +static int vsnprintf( char *str, size_t n, const char *fmt, va_list ap ) +{ + int res; + + if (f == NULL) + f = fopen("/dev/null","w"); + if (f == NULL) + return -1; + + setvbuf( f, str, _IOFBF, n ); + + res = vfprintf( f, fmt, ap ); + + if ( res > 0 && res < n ) { + res = vsprintf( str, fmt, ap ); + } + return res; +} +static int snprintf( char *str, size_t n, const char *fmt, ... ) +{ + va_list ap; + int res; + + va_start( ap, fmt ); + res = vsnprintf( str, n, fmt, ap ); + va_end( ap ); + return res; +} +#endif + +void init_count_chars(count_chars *cc) +{ + cc->vals = (const char**)malloc(PATH_MAX); + cc->num = 0; +} + +void clear_count_chars(count_chars *cc) +{ + int i; + for (i = 0; i < cc->num; i++) { + cc->vals[i] = 0; + } + + cc->num = 0; +} + +void push_count_chars(count_chars *cc, const char *newval) +{ + cc->vals[cc->num++] = newval; +} + +void insert_count_chars(count_chars *cc, const char *newval, int position) +{ + int i; + + for (i = cc->num; i > position; i--) { + cc->vals[i] = cc->vals[i-1]; + } + + cc->vals[position] = newval; + cc->num++; +} + +void append_count_chars(count_chars *cc, count_chars *cctoadd) +{ + int i; + for (i = 0; i < cctoadd->num; i++) { + if (cctoadd->vals[i]) { + push_count_chars(cc, cctoadd->vals[i]); + } + } +} + +const char *flatten_count_chars(count_chars *cc) +{ + int i, size; + char *newval; + + size = 0; + for (i = 0; i < cc->num; i++) { + if (cc->vals[i]) { + size += strlen(cc->vals[i]) + 1; + } + } + + newval = (char*)malloc(size + 1); + newval[size] = 0; + + for (i = 0; i < cc->num; i++) { + if (cc->vals[i]) { + strcat(newval, cc->vals[i]); + strcat(newval, " "); + } + } + + return newval; +} + +char *shell_esc(const char *str) +{ + int in_quote = 0; + char *cmd; + unsigned char *d; + const unsigned char *s; + + cmd = (char *)malloc(2 * strlen(str) + 1); + d = (unsigned char *)cmd; + s = (const unsigned char *)str; + + for (; *s; ++s) { + if (*s == '"') { + *d++ = '\\'; + in_quote++; + } + else if (*s == '\\' || (*s == ' ' && (in_quote % 2))) { + *d++ = '\\'; + } + *d++ = *s; + } + + *d = '\0'; + return cmd; +} + +int external_spawn(command_t *cmd, const char *file, const char **argv) +{ + if (!cmd->options.silent) { + const char **argument = argv; + printf("Executing: "); + while (*argument) { + printf("%s ", *argument); + argument++; + } + puts(""); + } + + if (cmd->options.dry_run) { + return 0; + } +#ifdef __EMX__ + return spawnvp(P_WAIT, file, argv); +#else + { + pid_t pid; + pid = fork(); + if (pid == 0) { + return execvp(argv[0], (char**)argv); + } + else { + int statuscode; + waitpid(pid, &statuscode, 0); + if (WIFEXITED(statuscode)) { + return WEXITSTATUS(statuscode); + } + return 0; + } + } +#endif +} + +int run_command(command_t *cmd_data, count_chars *cc) +{ + char *command; + const char *spawn_args[4]; + count_chars tmpcc; + + init_count_chars(&tmpcc); + + if (cmd_data->program) { + push_count_chars(&tmpcc, cmd_data->program); + } + + append_count_chars(&tmpcc, cmd_data->program_opts); + + append_count_chars(&tmpcc, cc); + + command = shell_esc(flatten_count_chars(&tmpcc)); + + spawn_args[0] = SHELL_CMD; + spawn_args[1] = "-c"; + spawn_args[2] = command; + spawn_args[3] = NULL; + return external_spawn(cmd_data, spawn_args[0], (const char**)spawn_args); +} + +/* + * print configuration + * shlibpath_var is used in configure. + */ +void print_config() +{ +#ifdef LD_RUN_PATH + printf("runpath_var=%s\n", LD_RUN_PATH); +#endif +#ifdef LD_LIBRARY_PATH + printf("shlibpath_var=%s\n", LD_LIBRARY_PATH); +#endif +#ifdef SHELL_CMD + printf("SHELL=\"%s\"\n", SHELL_CMD); +#endif +} +/* + * Add a directory to the runtime library search path. + */ +void add_runtimedirlib(char *arg, command_t *cmd_data) +{ +#ifdef RPATH + add_rpath(cmd_data->shared_opts.dependencies, arg); +#else +#endif +} + +int parse_long_opt(char *arg, command_t *cmd_data) +{ + char *equal_pos = strchr(arg, '='); + char var[50]; + char value[500]; + + if (equal_pos) { + strncpy(var, arg, equal_pos - arg); + var[equal_pos - arg] = 0; + strcpy(value, equal_pos + 1); + } else { + strcpy(var, arg); + } + + if (strcmp(var, "silent") == 0) { + cmd_data->options.silent = 1; + } else if (strcmp(var, "mode") == 0) { + if (strcmp(value, "compile") == 0) { + cmd_data->mode = mCompile; + cmd_data->output = otObject; + } + + if (strcmp(value, "link") == 0) { + cmd_data->mode = mLink; + cmd_data->output = otLibrary; + } + + if (strcmp(value, "install") == 0) { + cmd_data->mode = mInstall; + } + } else if (strcmp(var, "shared") == 0) { + if (cmd_data->mode == mLink) { + cmd_data->output = otDynamicLibraryOnly; + } + cmd_data->options.shared = 1; + } else if (strcmp(var, "export-all") == 0) { + cmd_data->options.export_all = 1; + } else if (strcmp(var, "dry-run") == 0) { + printf("Dry-run mode on!\n"); + cmd_data->options.dry_run = 1; + } else if (strcmp(var, "version") == 0) { + printf("Version " VERSION "\n"); + } else if (strcmp(var, "help") == 0) { + printf("Sorry. No help available.\n"); + } else if (strcmp(var, "config") == 0) { + print_config(); + } else if (strcmp(var, "tag") == 0) { + if (strcmp(value, "CC") == 0) { + /* Do nothing. */ + } + if (strcmp(value, "CXX") == 0) { + /* Do nothing. */ + } + } else { + return 0; + } + + return 1; +} + +/* Return 1 if we eat it. */ +int parse_short_opt(char *arg, command_t *cmd_data) +{ + if (strcmp(arg, "export-dynamic") == 0) { + cmd_data->options.export_dynamic = 1; + return 1; + } + + if (strcmp(arg, "module") == 0) { + cmd_data->output = otModule; + return 1; + } + + if (strcmp(arg, "Zexe") == 0) { + return 1; + } + + if (strcmp(arg, "avoid-version") == 0) { + return 1; + } + + if (strcmp(arg, "prefer-pic") == 0) { + cmd_data->options.pic_mode = pic_PREFER; + return 1; + } + + if (strcmp(arg, "prefer-non-pic") == 0) { + cmd_data->options.pic_mode = pic_AVOID; + return 1; + } + + if (strcmp(arg, "static") == 0) { + /* Don't respect it for now. */ + return 1; + } + + if (cmd_data->mode == mLink) { + if (strcmp(arg, "no-install") == 0) { + cmd_data->options.no_install = 1; + return 1; + } + if (arg[0] == 'L' || arg[0] == 'l') { + /* Hack... */ + arg--; + push_count_chars(cmd_data->shared_opts.dependencies, arg); + return 1; + } else if (arg[0] == 'R' && arg[1]) { + /* -Rdir Add dir to runtime library search path. */ + add_runtimedirlib(&arg[1], cmd_data); + return 1; + } + } + return 0; +} + +char *truncate_dll_name(char *path) +{ + /* Cut DLL name down to 8 characters after removing any mod_ prefix */ + char *tmppath = strdup(path); + char *newname = strrchr(tmppath, '/') + 1; + char *ext = strrchr(tmppath, '.'); + int len; + + if (ext == NULL) + return tmppath; + + len = ext - newname; + + if (strncmp(newname, "mod_", 4) == 0) { + strcpy(newname, newname + 4); + len -= 4; + } + + if (len > 8) { + strcpy(newname + 8, strchr(newname, '.')); + } + + return tmppath; +} + +long safe_strtol(const char *nptr, const char **endptr, int base) +{ + long rv; + + errno = 0; + + rv = strtol(nptr, (char**)endptr, 10); + + if (errno == ERANGE) { + return 0; + } + + return rv; +} + +/* version_info is in the form of MAJOR:MINOR:PATCH */ +const char *darwin_dynamic_link_function(const char *version_info) +{ + char *newarg; + long major, minor, patch; + + major = 0; + minor = 0; + patch = 0; + + if (version_info) { + major = safe_strtol(version_info, &version_info, 10); + + if (version_info) { + if (version_info[0] == ':') { + version_info++; + } + + minor = safe_strtol(version_info, &version_info, 10); + + if (version_info) { + if (version_info[0] == ':') { + version_info++; + } + + patch = safe_strtol(version_info, &version_info, 10); + + } + } + } + + /* Avoid -dylib_compatibility_version must be greater than zero errors. */ + if (major == 0) { + major = 1; + } + newarg = (char*)malloc(100); + snprintf(newarg, 99, + "-compatibility_version %ld -current_version %ld.%ld", + major, major, minor); + + return newarg; +} + +/* genlib values + * 0 - static + * 1 - dynamic + * 2 - module + */ +char *gen_library_name(const char *name, int genlib) +{ + char *newarg, *newext; + + newarg = (char *)malloc(strlen(name) + 10); + strcpy(newarg, ".libs/"); + + if (genlib == 2 && strncmp(name, "lib", 3) == 0) { + name += 3; + } + + strcat(newarg, name); + + newext = strrchr(newarg, '.') + 1; + + switch (genlib) { + case 0: + strcpy(newext, STATIC_LIB_EXT); + break; + case 1: + strcpy(newext, DYNAMIC_LIB_EXT); + break; + case 2: + strcpy(newext, MODULE_LIB_EXT); + break; + } + + return newarg; +} + +/* genlib values + * 0 - static + * 1 - dynamic + * 2 - module + */ +char *gen_install_name(const char *name, int genlib) +{ + struct stat sb; + char *newname; + int rv; + + newname = gen_library_name(name, genlib); + + /* Check if it exists. If not, return NULL. */ + rv = stat(newname, &sb); + + if (rv) { + return NULL; + } + + return newname; +} + +char *check_object_exists(command_t *cmd, const char *arg, int arglen) +{ + char *newarg, *ext; + int pass, rv; + + newarg = (char *)malloc(arglen + 10); + memcpy(newarg, arg, arglen); + newarg[arglen] = 0; + ext = newarg + arglen; + + pass = 0; + + do { + struct stat sb; + + switch (pass) { + case 0: + strcpy(ext, OBJECT_EXT); + break; +/* + case 1: + strcpy(ext, NO_PIC_EXT); + break; +*/ + default: + break; + } + + if (!cmd->options.silent) { + printf("Checking (obj): %s\n", newarg); + } + rv = stat(newarg, &sb); + } + while (rv != 0 && ++pass < 1); + + if (rv == 0) { + if (pass == 1) { + cmd->options.pic_mode = pic_AVOID; + } + return newarg; + } + + return NULL; +} + +/* libdircheck values: + * 0 - no .libs suffix + * 1 - .libs suffix + */ +char *check_library_exists(command_t *cmd, const char *arg, int pathlen, + int libdircheck, enum lib_type *libtype) +{ + char *newarg, *ext; + int pass, rv, newpathlen; + + newarg = (char *)malloc(strlen(arg) + 10); + strcpy(newarg, arg); + newarg[pathlen] = 0; + + newpathlen = pathlen; + if (libdircheck) { + strcat(newarg, ".libs/"); + newpathlen += sizeof(".libs/") - 1; + } + + strcpy(newarg+newpathlen, arg+pathlen); + ext = strrchr(newarg, '.') + 1; + + pass = 0; + + do { + struct stat sb; + + switch (pass) { + case 0: + if (cmd->options.pic_mode != pic_AVOID || cmd->options.shared) { + strcpy(ext, DYNAMIC_LIB_EXT); + *libtype = type_DYNAMIC_LIB; + break; + } + pass = 1; + case 1: + strcpy(ext, STATIC_LIB_EXT); + *libtype = type_STATIC_LIB; + break; + case 2: + strcpy(ext, MODULE_LIB_EXT); + *libtype = type_MODULE_LIB; + break; + case 3: + strcpy(ext, OBJECT_EXT); + *libtype = type_OBJECT; + break; + default: + *libtype = type_UNKNOWN; + break; + } + + if (!cmd->options.silent) { + printf("Checking (lib): %s\n", newarg); + } + rv = stat(newarg, &sb); + } + while (rv != 0 && ++pass < 4); + + if (rv == 0) { + return newarg; + } + + return NULL; +} + +char * load_install_path(const char *arg) +{ + FILE *f; + char *path; + + path = malloc(PATH_MAX); + + f = fopen(arg,"r"); + if (f == NULL) { + return NULL; + } + fgets(path, PATH_MAX, f); + fclose(f); + if (path[strlen(path)-1] == '\n') { + path[strlen(path)-1] = '\0'; + } + /* Check that we have an absolute path. + * Otherwise the file could be a GNU libtool file. + */ + if (path[0] != '/') { + return NULL; + } + return path; +} + +char * load_noinstall_path(const char *arg, int pathlen) +{ + char *newarg, *expanded_path; + int newpathlen; + + newarg = (char *)malloc(strlen(arg) + 10); + strcpy(newarg, arg); + newarg[pathlen] = 0; + + newpathlen = pathlen; + strcat(newarg, ".libs"); + newpathlen += sizeof(".libs") - 1; + newarg[newpathlen] = 0; + +#ifdef HAS_REALPATH + expanded_path = malloc(PATH_MAX); + expanded_path = realpath(newarg, expanded_path); + /* Uh, oh. There was an error. Fall back on our first guess. */ + if (!expanded_path) { + expanded_path = newarg; + } +#else + /* We might get ../ or something goofy. Oh, well. */ + expanded_path = newarg; +#endif + + return expanded_path; +} + +/* Read the final install location and add it to runtime library search path. */ +#ifdef RPATH +void add_rpath(count_chars *cc, const char *path) +{ + int size = 0; + char *tmp; + +#ifdef LINKER_FLAG_PREFIX + size = strlen(LINKER_FLAG_PREFIX); +#endif + size = size + strlen(path) + strlen(RPATH) + 2; + tmp = malloc(size); + if (tmp == NULL) { + return; + } +#ifdef LINKER_FLAG_PREFIX + strcpy(tmp, LINKER_FLAG_PREFIX); + strcat(tmp, RPATH); +#else + strcpy(tmp, RPATH); +#endif +#ifndef LINKER_FLAG_NO_EQUALS + strcat(tmp, "="); +#endif + strcat(tmp, path); + + push_count_chars(cc, tmp); +} + +void add_rpath_file(count_chars *cc, const char *arg) +{ + const char *path; + + path = load_install_path(arg); + if (path) { + add_rpath(cc, path); + } +} + +void add_rpath_noinstall(count_chars *cc, const char *arg, int pathlen) +{ + const char *path; + + path = load_noinstall_path(arg, pathlen); + if (path) { + add_rpath(cc, path); + } +} +#endif + +#ifdef DYNAMIC_LINK_NO_INSTALL +void add_dylink_noinstall(count_chars *cc, const char *arg, int pathlen, + int extlen) +{ + const char *install_path, *current_path, *name; + char *exp_argument; + int i_p_len, c_p_len, name_len, dyext_len, cur_len; + + install_path = load_install_path(arg); + current_path = load_noinstall_path(arg, pathlen); + + if (!install_path || !current_path) { + return; + } + + push_count_chars(cc, DYNAMIC_LINK_NO_INSTALL); + + i_p_len = strlen(install_path); + c_p_len = strlen(current_path); + + name = arg+pathlen; + name_len = extlen-pathlen; + dyext_len = sizeof(DYNAMIC_LIB_EXT) - 1; + + /* No, we need to replace the extension. */ + exp_argument = (char *)malloc(i_p_len + c_p_len + (name_len*2) + + (dyext_len*2) + 2); + + cur_len = 0; + strcpy(exp_argument, install_path); + cur_len += i_p_len; + exp_argument[cur_len++] = '/'; + strncpy(exp_argument+cur_len, name, extlen-pathlen); + cur_len += name_len; + strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT); + cur_len += dyext_len; + exp_argument[cur_len++] = ':'; + strcpy(exp_argument+cur_len, current_path); + cur_len += c_p_len; + exp_argument[cur_len++] = '/'; + strncpy(exp_argument+cur_len, name, extlen-pathlen); + cur_len += name_len; + strcpy(exp_argument+cur_len, DYNAMIC_LIB_EXT); + cur_len += dyext_len; + + push_count_chars(cc, exp_argument); +} +#endif + +/* use -L -llibname to allow to use installed libraries */ +void add_minus_l(count_chars *cc, const char *arg) +{ + char *newarg; + char *name = strrchr(arg, '/'); + char *file = strrchr(arg, '.'); + char *lib = strstr(name, "lib"); + + if (name !=NULL && file != NULL && lib == name+1) { + *name = '\0'; + *file = '\0'; + file = name; + file = file+4; + push_count_chars(cc, "-L"); + push_count_chars(cc, arg); + /* we need one argument like -lapr-1 */ + newarg = malloc(strlen(file) + 3); + strcpy(newarg, "-l"); + strcat(newarg, file); + push_count_chars(cc, newarg); + } else { + push_count_chars(cc, arg); + } +} + +void add_linker_flag_prefix(count_chars *cc, const char *arg) +{ +#ifndef LINKER_FLAG_PREFIX + push_count_chars(cc, arg); +#else + char *newarg; + newarg = (char*)malloc(strlen(arg) + sizeof(LINKER_FLAG_PREFIX) + 1); + strcpy(newarg, LINKER_FLAG_PREFIX); + strcat(newarg, arg); + push_count_chars(cc, newarg); +#endif +} + +int parse_input_file_name(char *arg, command_t *cmd_data) +{ + char *ext = strrchr(arg, '.'); + char *name = strrchr(arg, '/'); + int pathlen; + enum lib_type libtype; + char *newarg; + + if (!ext) { + return 0; + } + + ext++; + + if (name == NULL) { + name = strrchr(arg, '\\'); + + if (name == NULL) { + name = arg; + } else { + name++; + } + } else { + name++; + } + + pathlen = name - arg; + + if (strcmp(ext, "lo") == 0) { + newarg = check_object_exists(cmd_data, arg, ext - arg); + if (!newarg) { + printf("Can not find suitable object file for %s\n", arg); + exit(1); + } + if (cmd_data->mode != mLink) { + push_count_chars(cmd_data->arglist, newarg); + } + else { + push_count_chars(cmd_data->obj_files, newarg); + } + return 1; + } + + if (strcmp(ext, "la") == 0) { + switch (cmd_data->mode) { + case mLink: + /* Try the .libs dir first! */ + newarg = check_library_exists(cmd_data, arg, pathlen, 1, &libtype); + if (!newarg) { + /* Try the normal dir next. */ + newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype); + if (!newarg) { + printf("Can not find suitable library for %s\n", arg); + exit(1); + } + } + + /* It is not ok to just add the file: a library may added with: + 1 - -L path library_name. (For *.so in Linux). + 2 - library_name. + */ +#ifdef ADD_MINUS_L + if (libtype == type_DYNAMIC_LIB) { + add_minus_l(cmd_data->shared_opts.dependencies, newarg); + } else { + push_count_chars(cmd_data->shared_opts.dependencies, newarg); + } +#else + push_count_chars(cmd_data->shared_opts.dependencies, newarg); +#endif + if (libtype == type_DYNAMIC_LIB) { + if (cmd_data->options.no_install) { +#ifdef RPATH + add_rpath_noinstall(cmd_data->shared_opts.dependencies, + arg, pathlen); +#endif +#ifdef DYNAMIC_LINK_NO_INSTALL + /* + * This doesn't work as Darwin's linker has no way to + * override at link-time the search paths for a + * non-installed library. + */ + /* + add_dylink_noinstall(cmd_data->shared_opts.dependencies, + arg, pathlen, ext - arg); + */ +#endif + } + else { +#ifdef RPATH + add_rpath_file(cmd_data->shared_opts.dependencies, arg); +#endif + } + } + break; + case mInstall: + /* If we've already recorded a library to install, we're most + * likely getting the .la file that we want to install as. + * The problem is that we need to add it as the directory, + * not the .la file itself. Otherwise, we'll do odd things. + */ + if (cmd_data->output == otLibrary) { + arg[pathlen] = '\0'; + push_count_chars(cmd_data->arglist, arg); + } + else { + cmd_data->output = otLibrary; + cmd_data->output_name = arg; + cmd_data->static_name.install = gen_install_name(arg, 0); + cmd_data->shared_name.install = gen_install_name(arg, 1); + cmd_data->module_name.install = gen_install_name(arg, 2); + } + break; + default: + break; + } + return 1; + } + + if (strcmp(ext, "c") == 0) { + /* If we don't already have an idea what our output name will be. */ + if (cmd_data->basename == NULL) { + cmd_data->basename = (char *)malloc(strlen(arg) + 4); + strcpy(cmd_data->basename, arg); + strcpy(strrchr(cmd_data->basename, '.') + 1, "lo"); + + cmd_data->fake_output_name = strrchr(cmd_data->basename, '/'); + if (cmd_data->fake_output_name) { + cmd_data->fake_output_name++; + } + else { + cmd_data->fake_output_name = cmd_data->basename; + } + } + } + + return 0; +} + +int parse_output_file_name(char *arg, command_t *cmd_data) +{ + char *name = strrchr(arg, '/'); + char *ext = strrchr(arg, '.'); + char *newarg = NULL; + int pathlen; + + cmd_data->fake_output_name = arg; + + if (name) { + name++; + } + else { + name = strrchr(arg, '\\'); + + if (name == NULL) { + name = arg; + } + else { + name++; + } + } + + if (!ext) { + cmd_data->basename = arg; + cmd_data->output = otProgram; +#if defined(_OSD_POSIX) + cmd_data->options.pic_mode = pic_AVOID; +#endif + newarg = (char *)malloc(strlen(arg) + 5); + strcpy(newarg, arg); +#ifdef EXE_EXT + strcat(newarg, EXE_EXT); +#endif + cmd_data->output_name = newarg; + return 1; + } + + ext++; + pathlen = name - arg; + + if (strcmp(ext, "la") == 0) { + assert(cmd_data->mode == mLink); + + cmd_data->basename = arg; + cmd_data->static_name.normal = gen_library_name(arg, 0); + cmd_data->shared_name.normal = gen_library_name(arg, 1); + cmd_data->module_name.normal = gen_library_name(arg, 2); + cmd_data->static_name.install = gen_install_name(arg, 0); + cmd_data->shared_name.install = gen_install_name(arg, 1); + cmd_data->module_name.install = gen_install_name(arg, 2); + +#ifdef TRUNCATE_DLL_NAME + if (shared) { + arg = truncate_dll_name(arg); + } +#endif + + cmd_data->output_name = arg; + return 1; + } + + if (strcmp(ext, "lo") == 0) { + cmd_data->basename = arg; + cmd_data->output = otObject; + newarg = (char *)malloc(strlen(arg) + 2); + strcpy(newarg, arg); + ext = strrchr(newarg, '.') + 1; + strcpy(ext, OBJECT_EXT); + cmd_data->output_name = newarg; + return 1; + } + + return 0; +} + +/* returns just a file's name without path or extension */ +char *nameof(char *fullpath) +{ + char buffer[1024]; + char *ext; + char *name = strrchr(fullpath, '/'); + + if (name == NULL) { + name = strrchr(fullpath, '\\'); + } + + if (name == NULL) { + name = fullpath; + } else { + name++; + } + + strcpy(buffer, name); + ext = strrchr(buffer, '.'); + + if (ext) { + *ext = 0; + return strdup(buffer); + } + + return name; +} + +void parse_args(int argc, char *argv[], command_t *cmd_data) +{ + int a; + char *arg; + int argused; + + for (a = 1; a < argc; a++) { + arg = argv[a]; + argused = 1; + + if (arg[0] == '-') { + if (arg[1] == '-') { + argused = parse_long_opt(arg + 2, cmd_data); + } + else { + argused = parse_short_opt(arg + 1, cmd_data); + } + + /* We haven't done anything with it yet, try some of the + * more complicated short opts... */ + if (argused == 0 && a + 1 < argc) { + if (arg[1] == 'o' && !arg[2]) { + arg = argv[++a]; + argused = parse_output_file_name(arg, cmd_data); + } else if (strcmp(arg+1, "MT") == 0) { + if (!cmd_data->options.silent) { + printf("Adding: %s", arg); + } + push_count_chars(cmd_data->arglist, arg); + arg = argv[++a]; + if (!cmd_data->options.silent) { + printf(" %s\n", arg); + } + push_count_chars(cmd_data->arglist, arg); + argused = 1; + } else if (strcmp(arg+1, "rpath") == 0) { + /* Aha, we should try to link both! */ + cmd_data->install_path = argv[++a]; + argused = 1; + } else if (strcmp(arg+1, "version-info") == 0) { + /* Store for later deciphering */ + cmd_data->version_info = argv[++a]; + argused = 1; + } else if (strcmp(arg+1, "export-symbols-regex") == 0) { + /* Skip the argument. */ + ++a; + argused = 1; + } else if (arg[1] == 'R' && !arg[2]) { + /* -R dir Add dir to runtime library search path. */ + add_runtimedirlib(argv[++a], cmd_data); + argused = 1; + } + } + } else { + argused = parse_input_file_name(arg, cmd_data); + } + + if (!argused) { + if (!cmd_data->options.silent) { + printf("Adding: %s\n", arg); + } + push_count_chars(cmd_data->arglist, arg); + } + } + +} + +int explode_static_lib(const char *lib, command_t *cmd_data) +{ + char tmpdir[1024]; + char savewd[1024]; + char cmd[1024]; + const char *name; + DIR *dir; + struct dirent *entry; + + /* Bah! */ + if (cmd_data->options.dry_run) { + return 0; + } + + strcpy(tmpdir, lib); + strcat(tmpdir, ".exploded"); + + mkdir(tmpdir, 0); + push_count_chars(cmd_data->tmp_dirs, strdup(tmpdir)); + getcwd(savewd, sizeof(savewd)); + + if (chdir(tmpdir) != 0) + return 1; + + strcpy(cmd, LIBRARIAN " x "); + name = strrchr(lib, '/'); + + if (name) { + name++; + } else { + name = lib; + } + + strcat(cmd, "../"); + strcat(cmd, name); + system(cmd); + chdir(savewd); + dir = opendir(tmpdir); + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_name[0] != '.') { + strcpy(cmd, tmpdir); + strcat(cmd, "/"); + strcat(cmd, entry->d_name); + push_count_chars(cmd_data->arglist, strdup(cmd)); + } + } + + closedir(dir); + return 0; +} + +#ifdef GEN_EXPORTS +void generate_def_file(command_t *cmd_data) +{ + char def_file[1024]; + char implib_file[1024]; + char *ext; + FILE *hDef; + char *export_args[1024]; + int num_export_args = 0; + char *cmd; + int cmd_size = 0; + int a; + + if (cmd_data->output_name) { + strcpy(def_file, cmd_data->output_name); + strcat(def_file, ".def"); + hDef = fopen(def_file, "w"); + + if (hDef != NULL) { + fprintf(hDef, "LIBRARY '%s' INITINSTANCE\n", nameof(cmd_data->output_name)); + fprintf(hDef, "DATA NONSHARED\n"); + fprintf(hDef, "EXPORTS\n"); + fclose(hDef); + + for (a = 0; a < cmd_data->num_obj_files; a++) { + cmd_size += strlen(cmd_data->obj_files[a]) + 1; + } + + cmd_size += strlen(GEN_EXPORTS) + strlen(def_file) + 3; + cmd = (char *)malloc(cmd_size); + strcpy(cmd, GEN_EXPORTS); + + for (a=0; a < cmd_data->num_obj_files; a++) { + strcat(cmd, " "); + strcat(cmd, cmd_data->obj_files[a] ); + } + + strcat(cmd, ">>"); + strcat(cmd, def_file); + puts(cmd); + export_args[num_export_args++] = SHELL_CMD; + export_args[num_export_args++] = "-c"; + export_args[num_export_args++] = cmd; + export_args[num_export_args++] = NULL; + external_spawn(cmd_data, export_args[0], (const char**)export_args); + cmd_data->arglist[cmd_data->num_args++] = strdup(def_file); + + /* Now make an import library for the dll */ + num_export_args = 0; + export_args[num_export_args++] = DEF2IMPLIB_CMD; + export_args[num_export_args++] = "-o"; + + strcpy(implib_file, ".libs/"); + strcat(implib_file, cmd_data->basename); + ext = strrchr(implib_file, '.'); + + if (ext) + *ext = 0; + + strcat(implib_file, "."); + strcat(implib_file, STATIC_LIB_EXT); + + export_args[num_export_args++] = implib_file; + export_args[num_export_args++] = def_file; + export_args[num_export_args++] = NULL; + external_spawn(cmd_data, export_args[0], (const char**)export_args); + + } + } +} +#endif + +const char* expand_path(const char *relpath) +{ + char foo[PATH_MAX], *newpath; + + getcwd(foo, PATH_MAX-1); + newpath = (char*)malloc(strlen(foo)+strlen(relpath)+2); + strcat(newpath, foo); + strcat(newpath, "/"); + strcat(newpath, relpath); + return newpath; +} + +void link_fixup(command_t *c) +{ + /* If we were passed an -rpath directive, we need to build + * shared objects too. Otherwise, we should only create static + * libraries. + */ + if (!c->install_path && (c->output == otDynamicLibraryOnly || + c->output == otModule || c->output == otLibrary)) { + c->output = otStaticLibraryOnly; + } + + if (c->output == otDynamicLibraryOnly || + c->output == otModule || + c->output == otLibrary) { + + push_count_chars(c->shared_opts.normal, "-o"); + if (c->output == otModule) { + push_count_chars(c->shared_opts.normal, c->module_name.normal); + } + else { + char *tmp; + push_count_chars(c->shared_opts.normal, c->shared_name.normal); +#ifdef DYNAMIC_INSTALL_NAME + push_count_chars(c->shared_opts.normal, DYNAMIC_INSTALL_NAME); + + tmp = (char*)malloc(PATH_MAX); + strcat(tmp, c->install_path); + strcat(tmp, strrchr(c->shared_name.normal, '/')); + push_count_chars(c->shared_opts.normal, tmp); +#endif + } + + append_count_chars(c->shared_opts.normal, c->obj_files); + append_count_chars(c->shared_opts.normal, c->shared_opts.dependencies); + + if (c->options.export_all) { +#ifdef GEN_EXPORTS + generate_def_file(c); +#endif + } + } + + if (c->output == otLibrary || c->output == otStaticLibraryOnly) { + push_count_chars(c->static_opts.normal, "-o"); + push_count_chars(c->static_opts.normal, c->output_name); + } + + if (c->output == otProgram) { + if (c->output_name) { + push_count_chars(c->arglist, "-o"); + push_count_chars(c->arglist, c->output_name); + append_count_chars(c->arglist, c->obj_files); + append_count_chars(c->arglist, c->shared_opts.dependencies); +#ifdef DYNAMIC_LINK_OPTS + if (c->options.pic_mode != pic_AVOID) { + push_count_chars(c->arglist, DYNAMIC_LINK_OPTS); + } +#endif + } + } +} + +void post_parse_fixup(command_t *cmd_data) +{ + switch (cmd_data->mode) + { + case mCompile: +#ifdef PIC_FLAG + if (cmd_data->options.pic_mode != pic_AVOID) { + push_count_chars(cmd_data->arglist, PIC_FLAG); + } +#endif + if (cmd_data->output_name) { + push_count_chars(cmd_data->arglist, "-o"); + push_count_chars(cmd_data->arglist, cmd_data->output_name); + } + break; + case mLink: + link_fixup(cmd_data); + break; + case mInstall: + if (cmd_data->output == otLibrary) { + link_fixup(cmd_data); + } + default: + break; + } + +#if USE_OMF + if (cmd_data->output == otObject || + cmd_data->output == otProgram || + cmd_data->output == otLibrary || + cmd_data->output == otDynamicLibraryOnly) { + push_count_chars(cmd_data->arglist, "-Zomf"); + } +#endif + + if (cmd_data->options.shared && + (cmd_data->output == otObject || + cmd_data->output == otLibrary || + cmd_data->output == otDynamicLibraryOnly)) { +#ifdef SHARE_SW + push_count_chars(cmd_data->arglist, SHARE_SW); +#endif + } +} + +int run_mode(command_t *cmd_data) +{ + int rv; + count_chars *cctemp; + + cctemp = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cctemp); + + switch (cmd_data->mode) + { + case mCompile: + rv = run_command(cmd_data, cmd_data->arglist); + if (rv) { + return rv; + } + break; + case mInstall: + /* Well, we'll assume it's a file going to a directory... */ + /* For brain-dead install-sh based scripts, we have to repeat + * the command N-times. install-sh should die. + */ + if (!cmd_data->output_name) { + rv = run_command(cmd_data, cmd_data->arglist); + if (rv) { + return rv; + } + } + if (cmd_data->output_name) { + append_count_chars(cctemp, cmd_data->arglist); + insert_count_chars(cctemp, + cmd_data->output_name, + cctemp->num - 1); + rv = run_command(cmd_data, cctemp); + if (rv) { + return rv; + } + clear_count_chars(cctemp); + } + if (cmd_data->static_name.install) { + append_count_chars(cctemp, cmd_data->arglist); + insert_count_chars(cctemp, + cmd_data->static_name.install, + cctemp->num - 1); + rv = run_command(cmd_data, cctemp); + if (rv) { + return rv; + } + clear_count_chars(cctemp); + } + if (cmd_data->shared_name.install) { + append_count_chars(cctemp, cmd_data->arglist); + insert_count_chars(cctemp, + cmd_data->shared_name.install, + cctemp->num - 1); + rv = run_command(cmd_data, cctemp); + if (rv) { + return rv; + } + clear_count_chars(cctemp); + } + if (cmd_data->module_name.install) { + append_count_chars(cctemp, cmd_data->arglist); + insert_count_chars(cctemp, + cmd_data->module_name.install, + cctemp->num - 1); + rv = run_command(cmd_data, cctemp); + if (rv) { + return rv; + } + clear_count_chars(cctemp); + } + break; + case mLink: + if (!cmd_data->options.dry_run) { + /* Check first to see if the dir already exists! */ + mode_t old_umask; + + old_umask = umask(0); + umask(old_umask); + + mkdir(".libs", ~old_umask); + } + + if (cmd_data->output == otStaticLibraryOnly || + cmd_data->output == otLibrary) { +#ifdef RANLIB + const char *lib_args[3]; +#endif + /* Removes compiler! */ + cmd_data->program = LIBRARIAN; + push_count_chars(cmd_data->program_opts, LIBRARIAN_OPTS); + push_count_chars(cmd_data->program_opts, + cmd_data->static_name.normal); + + rv = run_command(cmd_data, cmd_data->obj_files); + if (rv) { + return rv; + } + +#ifdef RANLIB + lib_args[0] = RANLIB; + lib_args[1] = cmd_data->static_name.normal; + lib_args[2] = NULL; + external_spawn(cmd_data, RANLIB, lib_args); +#endif + } + + if (cmd_data->output == otDynamicLibraryOnly || + cmd_data->output == otModule || + cmd_data->output == otLibrary) { + cmd_data->program = NULL; + clear_count_chars(cmd_data->program_opts); + + append_count_chars(cmd_data->program_opts, cmd_data->arglist); + if (cmd_data->output != otModule) { +#ifdef SHARED_OPTS + push_count_chars(cmd_data->program_opts, SHARED_OPTS); +#endif +#ifdef dynamic_link_version_func + push_count_chars(cmd_data->program_opts, + dynamic_link_version_func(cmd_data->version_info)); +#endif + } + if (cmd_data->output == otModule) { +#ifdef MODULE_OPTS + push_count_chars(cmd_data->program_opts, MODULE_OPTS); +#endif + } +#ifdef DYNAMIC_LINK_OPTS + if (cmd_data->options.pic_mode != pic_AVOID) { + push_count_chars(cmd_data->program_opts, + DYNAMIC_LINK_OPTS); + } +#endif + rv = run_command(cmd_data, cmd_data->shared_opts.normal); + if (rv) { + return rv; + } + } + if (cmd_data->output == otProgram) { + rv = run_command(cmd_data, cmd_data->arglist); + if (rv) { + return rv; + } + } + break; + default: + break; + } + + return 0; +} + +void cleanup_tmp_dir(const char *dirname) +{ + DIR *dir; + struct dirent *entry; + char fullname[1024]; + + dir = opendir(dirname); + + if (dir == NULL) + return; + + while ((entry = readdir(dir)) != NULL) { + if (entry->d_name[0] != '.') { + strcpy(fullname, dirname); + strcat(fullname, "/"); + strcat(fullname, entry->d_name); + remove(fullname); + } + } + + rmdir(dirname); +} + +void cleanup_tmp_dirs(command_t *cmd_data) +{ + int d; + + for (d = 0; d < cmd_data->tmp_dirs->num; d++) { + cleanup_tmp_dir(cmd_data->tmp_dirs->vals[d]); + } +} + +int ensure_fake_uptodate(command_t *cmd_data) +{ + /* FIXME: could do the stat/touch here, but nah... */ + const char *touch_args[3]; + + if (cmd_data->mode == mInstall) { + return 0; + } + + touch_args[0] = "touch"; + touch_args[1] = cmd_data->fake_output_name; + touch_args[2] = NULL; + return external_spawn(cmd_data, "touch", touch_args); +} + +/* Store the install path in the *.la file */ +int add_for_runtime(command_t *cmd_data) +{ + if (cmd_data->mode == mInstall) { + return 0; + } + if (cmd_data->output == otDynamicLibraryOnly || + cmd_data->output == otLibrary) { + FILE *f=fopen(cmd_data->fake_output_name,"w"); + if (f == NULL) { + return -1; + } + fprintf(f,"%s\n", cmd_data->install_path); + fclose(f); + return(0); + } else { + return(ensure_fake_uptodate(cmd_data)); + } +} + +int main(int argc, char *argv[]) +{ + int rc; + command_t cmd_data; + + memset(&cmd_data, 0, sizeof(cmd_data)); + + cmd_data.options.pic_mode = pic_UNKNOWN; + + cmd_data.program_opts = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.program_opts); + cmd_data.arglist = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.arglist); + cmd_data.tmp_dirs = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.tmp_dirs); + cmd_data.obj_files = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.obj_files); + cmd_data.dep_rpaths = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.dep_rpaths); + cmd_data.rpaths = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.rpaths); + cmd_data.static_opts.normal = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.static_opts.normal); + cmd_data.shared_opts.normal = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.shared_opts.normal); + cmd_data.shared_opts.dependencies = (count_chars*)malloc(sizeof(count_chars)); + init_count_chars(cmd_data.shared_opts.dependencies); + + cmd_data.mode = mUnknown; + cmd_data.output = otGeneral; + + parse_args(argc, argv, &cmd_data); + post_parse_fixup(&cmd_data); + + if (cmd_data.mode == mUnknown) { + exit(0); + } + + rc = run_mode(&cmd_data); + + if (!rc) { + add_for_runtime(&cmd_data); + } + + cleanup_tmp_dirs(&cmd_data); + return rc; +} diff --git a/srclib/apr/build/libapr_app.dsp b/srclib/apr/build/libapr_app.dsp new file mode 100644 index 0000000000..ac80e7ea53 --- /dev/null +++ b/srclib/apr/build/libapr_app.dsp @@ -0,0 +1,93 @@ +# Microsoft Developer Studio Project File - Name="libapr_app" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=libapr_app - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libapr_app.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libapr_app.mak" CFG="libapr_app - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libapr_app - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "libapr_app - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libapr_app - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "../include" /I "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fd"Release\libapr_app_src" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Release\libapr_app-1.lib" + +!ELSEIF "$(CFG)" == "libapr_app - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../include" /I "../include/arch" /I "../include/arch/win32" /I "../include/arch/unix" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "APR_APP" /Fd"Debug\libapr_app_src" /FD /c +# ADD BASE RSC /l 0x409 +# ADD RSC /l 0x409 +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"Debug\libapr_app-1.lib" + +!ENDIF + +# Begin Target + +# Name "libapr_app - Win32 Release" +# Name "libapr_app - Win32 Debug" +# Begin Source File + +SOURCE=..\misc\win32\apr_app.c +# End Source File +# Begin Source File + +SOURCE=..\misc\win32\internal.c +# End Source File +# End Target +# End Project diff --git a/srclib/apr/build/lineends.pl b/srclib/apr/build/lineends.pl new file mode 100644 index 0000000000..f91a9d30c5 --- /dev/null +++ b/srclib/apr/build/lineends.pl @@ -0,0 +1,149 @@ +#!/usr/local/bin/perl +# +# Heuristically converts line endings to the current OS's preferred format +# +# All existing line endings must be identical (e.g. lf's only, or even +# the accedental cr.cr.lf sequence.) If some lines end lf, and others as +# cr.lf, the file is presumed binary. If the cr character appears anywhere +# except prefixed to an lf, the file is presumed binary. If there is no +# change in the resulting file size, or the file is binary, the conversion +# is discarded. +# +# Todo: Handle NULL stdin characters gracefully. +# + +use IO::File; +use File::Find; + +# The ignore list is '-' seperated, with this leading hyphen and +# trailing hyphens in ever concatinated list below. +$ignore = "-"; + +# Image formats +$ignore .= "gif-jpg-jpeg-png-ico-bmp-"; + +# Archive formats +$ignore .= "tar-gz-z-zip-jar-war-"; + +# Many document formats +$ignore .= "eps-psd-pdf-ai-"; + +# Some encodings +$ignore .= "ucs2-ucs4-"; + +# Some binary objects +$ignore .= "class-so-dll-exe-obj-"; + +# Some build env files in NW/Win32 +$ignore .= "mcp-xdc-ncb-opt-pdb-ilk-sbr-"; + +$preservedate = 1; + +$forceending = 0; + +$givenpaths = 0; + +$notnative = 0; + +while (defined @ARGV[0]) { + if (@ARGV[0] eq '--touch') { + $preservedate = 0; + } + elsif (@ARGV[0] eq '--nocr') { + $notnative = -1; + } + elsif (@ARGV[0] eq '--cr') { + $notnative = 1; + } + elsif (@ARGV[0] eq '--force') { + $forceending = 1; + } + elsif (@ARGV[0] eq '--FORCE') { + $forceending = 2; + } + elsif (@ARGV[0] =~ m/^-/) { + die "What is " . @ARGV[0] . " supposed to mean?\n\n" + . "Syntax:\t$0 [option()s] [path(s)]\n\n" . <<'OUTCH' +Where: paths specifies the top level directory to convert (default of '.') + options are; + + --cr keep/add one ^M + --nocr remove ^M's + --touch the datestamp (default: keeps date/attribs) + --force mismatched corrections (unbalanced ^M's) + --FORCE all files regardless of file name! + +OUTCH + } + else { + find(\&totxt, @ARGV[0]); + print "scanned " . @ARGV[0] . "\n"; + $givenpaths = 1; + } + shift @ARGV; +} + +if (!$givenpaths) { + find(\&totxt, '.'); + print "did .\n"; +} + +sub totxt { + $oname = $_; + $tname = '.#' . $_; + if (!-f) { + return; + } + @exts = split /\./; + if ($forceending < 2) { + while ($#exts && ($ext = pop(@exts))) { + if ($ignore =~ m|-$ext-|i) { + return; + } + } + } + @ostat = stat($oname); + $srcfl = new IO::File $oname, "r" or die; + $dstfl = new IO::File $tname, "w" or die; + binmode $srcfl; + if ($notnative) { + binmode $dstfl; + } + undef $t; + while (<$srcfl>) { + if (s/(\r*)\n$/\n/) { + $n = length $1; + if (!defined $t) { + $t = $n; + } + if (!$forceending && (($n != $t) || m/\r/)) { + print "mismatch in " .$oname. ":" .$n. " expected " .$t. "\n"; + undef $t; + last; + } + elsif ($notnative > 0) { + s/\n$/\r\n/; + } + } + print $dstfl $_; + } + if (defined $t && (tell $srcfl == tell $dstfl)) { + undef $t; + } + undef $srcfl; + undef $dstfl; + if (defined $t) { + unlink $oname or die; + rename $tname, $oname or die; + @anames = ($oname); + if ($preservedate) { + utime $ostat[9], $ostat[9], @anames; + } + chmod $ostat[2] & 07777, @anames; + chown $ostat[5], $ostat[6], @anames; + print "Converted file " . $oname . " to text in " . $File::Find::dir . "\n"; + } + else { + unlink $tname or die; + } +} diff --git a/srclib/apr/build/make_exports.awk b/srclib/apr/build/make_exports.awk new file mode 100644 index 0000000000..1d12fc65ab --- /dev/null +++ b/srclib/apr/build/make_exports.awk @@ -0,0 +1,150 @@ + +BEGIN { + printf("/*\n") + printf(" * THIS FILE WAS AUTOGENERATED BY make_exports.awk\n") + printf(" *\n") + printf(" * This is an ugly hack that needs to be here, so\n") + printf(" * that libtool will link all of the APR functions\n") + printf(" * into server regardless of whether the base server\n") + printf(" * uses them.\n") + printf(" */\n") + printf("\n") + printf("#define CORE_PRIVATE\n") + printf("\n") + + for (i = 1; i < ARGC; i++) { + file = ARGV[i] + sub("([^/]*[/])*", "", file) + printf("#include \"%s\"\n", file) + } + + printf("\n") + printf("const void *ap_ugly_hack = NULL;\n") + printf("\n") + + TYPE_NORMAL = 0 + TYPE_HEADER = 1 + + stackptr = 0 +} + +function push(line) { + stack[stackptr] = line + stackptr++ +} + +function do_output() { + printf("/*\n") + printf(" * %s\n", FILENAME) + printf(" */\n") + + for (i = 0; i < stackptr; i++) { + printf("%s\n", stack[i]) + } + + stackptr = 0 + + printf("\n"); +} + +function enter_scope(type) { + scope++ + scope_type[scope] = type + scope_stack[scope] = stackptr + delete scope_used[scope] +} + +function leave_scope() { + used = scope_used[scope] + + if (!used) + stackptr = scope_stack[scope] + + scope-- + if (used) { + scope_used[scope] = 1 + + if (!scope) + do_output() + } +} + +function add_symbol(symbol) { + if (!index(symbol, "#")) { + push("const void *ap_hack_" symbol " = (const void *)" symbol ";") + scope_used[scope] = 1 + } +} + +/^[ \t]*AP[RUI]?_(CORE_)?DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ { + sub("[ \t]*AP[RUI]?_(CORE_)?DECLARE[^(]*[(][^)]*[)][ \t]*", "") + sub("[(].*", "") + sub("([^ ]* (^([ \t]*[(])))+", "") + + add_symbol($0) + next +} + +/^[ \t]*AP_DECLARE_HOOK[^(]*[(][^)]*/ { + split($0, args, ",") + symbol = args[2] + sub("^[ \t]+", "", symbol) + sub("[ \t]+$", "", symbol) + + add_symbol("ap_hook_" symbol) + add_symbol("ap_hook_get_" symbol) + add_symbol("ap_run_" symbol) + next +} + +/^[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_pool_get") + next +} + +/^[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_inherit_set") + next +} + +/^[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_inherit_unset") + next +} + +/^#[ \t]*if(ndef| !defined[(])([^_]*_)*H/ { + enter_scope(TYPE_HEADER) + next +} + +/^#[ \t]*if([n]?def)? / { + enter_scope(TYPE_NORMAL) + push($0) + next +} + +/^#[ \t]*endif/ { + if (scope_type[scope] == TYPE_NORMAL) + push($0) + + leave_scope() + next +} + +/^#[ \t]*else/ { + push($0) + next +} + +/^#[ \t]*elif/ { + push($0) + next +} + + diff --git a/srclib/apr/build/make_nw_export.awk b/srclib/apr/build/make_nw_export.awk new file mode 100644 index 0000000000..291ecc0b2c --- /dev/null +++ b/srclib/apr/build/make_nw_export.awk @@ -0,0 +1,78 @@ +# Based on apr's make_export.awk, which is +# based on Ryan Bloom's make_export.pl + +BEGIN { + printf(" (APRLIB)\n") +} + +# List of functions that we don't support, yet?? +#/apr_##name##_set_inherit/{next} +#/apr_##name##_unset_inherit/{next} + + +function add_symbol (sym_name) { + if (count) { + found++ + } + gsub (/ /, "", sym_name) + line = line sym_name ",\n" + + if (count == 0) { + printf(" %s", line) + line = "" + } +} + +/^[ \t]*AP[RUI]?_DECLARE[^(]*[(][^)]*[)]([^ ]* )*[^(]+[(]/ { + sub("[ \t]*AP[RUI]?_DECLARE[^(]*[(][^)]*[)][ \t]*", "") + sub("[(].*", "") + sub("([^ ]* (^([ \t]*[(])))+", "") + + add_symbol($0) + next +} + +/^[ \t]*AP_DECLARE_HOOK[^(]*[(][^)]*/ { + split($0, args, ",") + symbol = args[2] + sub("^[ \t]+", "", symbol) + sub("[ \t]+$", "", symbol) + + add_symbol("ap_hook_" symbol) + add_symbol("ap_hook_get_" symbol) + add_symbol("ap_run_" symbol) + next +} + +/^[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_POOL_DECLARE_ACCESSOR[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_pool_get") + next +} + +/^[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_DECLARE_INHERIT_SET[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_inherit_set") + next +} + +/^[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(][^)]*[)]/ { + sub("[ \t]*APR_DECLARE_INHERIT_UNSET[^(]*[(]", "", $0) + sub("[)].*$", "", $0) + add_symbol("apr_" $0 "_inherit_unset") + next +} + +/^[ \t]*AP[RUI]?_DECLARE_DATA .*;$/ { + varname = $NF; + gsub( /[*;]/, "", varname); + gsub( /\[.*\]/, "", varname); + add_symbol(varname); +} + + +#END { +# printf(" %s", line) +#} diff --git a/srclib/apr/build/make_var_export.awk b/srclib/apr/build/make_var_export.awk new file mode 100644 index 0000000000..59922758d5 --- /dev/null +++ b/srclib/apr/build/make_var_export.awk @@ -0,0 +1,59 @@ +# Based on apr's make_export.awk, which is +# based on Ryan Bloom's make_export.pl + +/^#[ \t]*if(def)? (AP[RUI]?_|!?defined).*/ { + if (old_filename != FILENAME) { + if (old_filename != "") printf("%s", line) + macro_no = 0 + found = 0 + count = 0 + old_filename = FILENAME + line = "" + } + macro_stack[macro_no++] = macro + macro = substr($0, length($1)+2) + count++ + line = line "#ifdef " macro "\n" + next +} + +/^#[ \t]*endif/ { + if (count > 0) { + count-- + line = line "#endif /* " macro " */\n" + macro = macro_stack[--macro_no] + } + if (count == 0) { + if (found != 0) { + printf("%s", line) + } + line = "" + } + next +} + +function add_symbol (sym_name) { + if (count) { + found++ + } + for (i = 0; i < count; i++) { + line = line "\t" + } + line = line sym_name "\n" + + if (count == 0) { + printf("%s", line) + line = "" + } +} + +/^[ \t]*(extern[ \t]+)?AP[RUI]?_DECLARE_DATA .*;$/ { + varname = $NF; + gsub( /[*;]/, "", varname); + gsub( /\[.*\]/, "", varname); + add_symbol(varname); +} + +END { + printf("%s", line) +} diff --git a/srclib/apr/build/mkdir.sh b/srclib/apr/build/mkdir.sh new file mode 100755 index 0000000000..b947c92606 --- /dev/null +++ b/srclib/apr/build/mkdir.sh @@ -0,0 +1,37 @@ +#!/bin/sh +## +## mkdir.sh -- make directory hierarchy +## +## Based on `mkinstalldirs' from Noah Friedman +## as of 1994-03-25, which was placed in the Public Domain. +## Cleaned up for Apache's Autoconf-style Interface (APACI) +## by Ralf S. Engelschall +## +# +# This script falls under the Apache License. +# See http://www.apache.org/docs/LICENSE + + +umask 022 +errstatus=0 +for file in ${1+"$@"} ; do + set fnord `echo ":$file" |\ + sed -e 's/^:\//%/' -e 's/^://' -e 's/\// /g' -e 's/^%/\//'` + shift + pathcomp= + for d in ${1+"$@"}; do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + ?: ) pathcomp="$pathcomp/" + continue ;; + esac + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" 1>&2 + mkdir "$pathcomp" || errstatus=$? + fi + pathcomp="$pathcomp/" + done +done +exit $errstatus + diff --git a/srclib/apr/build/nw_export.inc b/srclib/apr/build/nw_export.inc new file mode 100644 index 0000000000..91c177a1ed --- /dev/null +++ b/srclib/apr/build/nw_export.inc @@ -0,0 +1,82 @@ +/* Must include apr.h first so that we can undefine + the standard prototypes macros after it messes with + them. */ +#include "apr.h" + +#undef APR_DECLARE +#undef APR_DECLARE_NONSTD +#undef APR_DECLARE_HOOK +#undef APR_POOL_DECLARE_ACCESSOR +#undef APR_DECLARE_DATA + +/* Preprocess all of the standard APR headers. */ +#include "apr_allocator.h" +#include "apr_atomic.h" +#include "apr_dso.h" +#include "apr_env.h" +#include "apr_errno.h" +#include "apr_file_info.h" +#include "apr_file_io.h" +#include "apr_fnmatch.h" +#include "apr_general.h" +#include "apr_getopt.h" +#include "apr_global_mutex.h" +#include "apr_hash.h" +#include "apr_inherit.h" +#include "apr_lib.h" +#include "apr_mmap.h" +#include "apr_network_io.h" +#include "apr_poll.h" +#include "apr_pools.h" +#include "apr_portable.h" +#include "apr_proc_mutex.h" +#include "apr_ring.h" +#include "apr_random.h" +#include "apr_shm.h" +#include "apr_signal.h" +#include "apr_strings.h" +#include "apr_support.h" +#include "apr_tables.h" +#include "apr_thread_cond.h" +#include "apr_thread_mutex.h" +#include "apr_thread_proc.h" +#include "apr_thread_rwlock.h" +#include "apr_time.h" +#include "apr_user.h" +#include "apr_version.h" +#include "apr_want.h" + + +/* Must include apu.h first so that we can undefine + the standard prototypes macros after it messes with + them. */ +#include "apu.h" + +#undef APU_DECLARE +#undef APU_DECLARE_NONSTD +#undef APU_DECLARE_DATA + +/* Preprocess all of the standard APR headers. */ +#include "apr_anylock.h" +#include "apr_base64.h" +#include "apr_buckets.h" +#include "apr_date.h" +#include "apr_dbm.h" +#include "apr_hooks.h" +#include "apr_ldap.h" +#include "apr_ldap_url.h" +#include "apr_md4.h" +#include "apr_md5.h" +#include "apr_optional.h" +#include "apr_optional_hooks.h" +#include "apr_queue.h" +#include "apr_reslist.h" +#include "apr_rmm.h" +#include "apr_sdbm.h" +#include "apr_sha1.h" +#include "apr_strmatch.h" +#include "apr_uri.h" +#include "apr_uuid.h" +#include "apr_xlate.h" +#include "apr_xml.h" +#include "apu_want.h" diff --git a/srclib/apr/build/nw_ver.awk b/srclib/apr/build/nw_ver.awk new file mode 100644 index 0000000000..ae82305a11 --- /dev/null +++ b/srclib/apr/build/nw_ver.awk @@ -0,0 +1,25 @@ +BEGIN { + + # fetch APR version numbers from input file and writes them to STDOUT + + while ((getline < ARGV[1]) > 0) { + if (match ($0, /^#define APR_MAJOR_VERSION/)) { + ver_major = $3; + } + else if (match ($0, /^#define APR_MINOR_VERSION/)) { + ver_minor = $3; + } + else if (match ($0, /^#define APR_PATCH_VERSION/)) { + ver_str_patch = $3; + if (match (ver_str_patch, /[0-9][0-9]*/)) { + ver_patch = substr(ver_str_patch, RSTART, RLENGTH); + } + } + } + ver = ver_major "," ver_minor "," ver_patch; + ver_str = ver_major "." ver_minor "." ver_str_patch; + + print "VERSION = " ver ""; + print "VERSION_STR = " ver_str ""; + +} diff --git a/srclib/apr/build/pkg/README b/srclib/apr/build/pkg/README new file mode 100644 index 0000000000..ce1c9b73a9 --- /dev/null +++ b/srclib/apr/build/pkg/README @@ -0,0 +1,20 @@ +The script in this directory will attempt to build a Solaris package +out of a source tree for APR. + +To build a package, make sure you are in the root of the source tree, +and run: + +build/pkg/buildpkg.sh + +A Solaris package called apr---local.gz will be +created in the root of the source tree. + +By default, if you attempt to build packages for apr-util, it will +search for the sources for apr in: + +../apr + +You may override the location of apr like so: + +build/pkg/buildpkg.sh --with-apr=some/other/path + diff --git a/srclib/apr/build/pkg/buildpkg.sh b/srclib/apr/build/pkg/buildpkg.sh new file mode 100755 index 0000000000..273c664aa1 --- /dev/null +++ b/srclib/apr/build/pkg/buildpkg.sh @@ -0,0 +1,72 @@ +#!/bin/sh +# Copyright 2000-2005 The Apache Software Foundation or its licensors, as +# applicable. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +# buildpkg.sh: This script builds a Solaris PKG from the source tree +# provided. + +PREFIX=/usr/local +TEMPDIR=/var/tmp/$USER/apr-root +rm -rf $TEMPDIR + +apr_src_dir=. + +while test $# -gt 0 +do + # Normalize + case "$1" in + -*=*) optarg=`echo "$1" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + case "$1" in + --with-apr=*) + apr_src_dir=$optarg + ;; + esac + + shift +done + +if [ -f "$apr_src_dir/configure.in" ]; then + cd $apr_src_dir +else + echo "The apr source could not be found within $apr_src_dir" + echo "Usage: buildpkg [--with-apr=dir]" + exit 1 +fi + +./configure --prefix=$PREFIX +make +make install DESTDIR=$TEMPDIR +rm $TEMPDIR$PREFIX/lib/apr.exp +. build/pkg/pkginfo +cp build/pkg/pkginfo $TEMPDIR$PREFIX + +current=`pwd` +cd $TEMPDIR$PREFIX +echo "i pkginfo=./pkginfo" > prototype +find . -print | grep -v ./prototype | grep -v ./pkginfo | pkgproto | awk '{print $1" "$2" "$3" "$4" root bin"}' >> prototype +mkdir $TEMPDIR/pkg +pkgmk -r $TEMPDIR$PREFIX -d $TEMPDIR/pkg + +cd $current +pkgtrans -s $TEMPDIR/pkg $current/$NAME-$VERSION-$ARCH-local +gzip $current/$NAME-$VERSION-$ARCH-local + +rm -rf $TEMPDIR + diff --git a/srclib/apr/build/pkg/pkginfo.in b/srclib/apr/build/pkg/pkginfo.in new file mode 100644 index 0000000000..f389b26901 --- /dev/null +++ b/srclib/apr/build/pkg/pkginfo.in @@ -0,0 +1,11 @@ +PKG="ASFapr-1" +NAME="apr" +ARCH="@target_cpu@" +VERSION="@APR_DOTTED_VERSION@" +CATEGORY="application" +VENDOR="Apache Software Foundation" +EMAIL="dev@apr.apache.org" +PSTAMP="dev@apr.apache.org" +BASEDIR="@prefix@" +CLASSES="none" + diff --git a/srclib/apr/build/prebuildNW.bat b/srclib/apr/build/prebuildNW.bat new file mode 100755 index 0000000000..941d920c9b --- /dev/null +++ b/srclib/apr/build/prebuildNW.bat @@ -0,0 +1,48 @@ +@echo off + +if not "%NovellLibC%" == "" goto CheckNDK +set NovellLibC=\novell\ndk\libc +@echo Could not find the NovellLibC environment variable +@echo Setting NovellLibC = %NovellLibC% +@echo --------------------- + +:CheckNDK +if exist %NovellLibC%\include\netware.h goto NDKOK +@echo The path to the NDK "%NovellLibC%" is invalid. +@echo Please set then NovellLibC environment variable to the location of the NDK +@echo --------------------- +goto Done + +:NDKOK +@echo # As part of the pre-build process, the utility GenURI.NLM +@echo # (Gen URI Delims) must be built, copied to a NetWare server +@echo # and run using the following command: +@echo # +@echo # "sys:\genuri >sys:\uri_delims.h" +@echo # +@echo # The file "sys:\uri_delims.h" must then be copied to +@echo # "apr-util\uri\uri_delims.h" on the build machine. + +@echo Fixing up the APR headers +copy ..\include\apr.hnw ..\include\apr.h + +@echo Fixing up the APR-Util headers +copy ..\..\apr-util\include\apu.hnw ..\..\apr-util\include\apu.h +copy ..\..\apr-util\include\apu_want.hnw ..\..\apr-util\include\apu_want.h +copy ..\..\apr-util\include\apr_ldap.hnw ..\..\apr-util\include\apr_ldap.h +copy ..\..\apr-util\include\private\apu_config.hw ..\..\apr-util\include\private\apu_config.h +copy ..\..\apr-util\xml\expat\lib\expat.h.in ..\..\apr-util\xml\expat\lib\expat.h +copy ..\..\apr-util\xml\expat\lib\config.hnw ..\..\apr-util\xml\expat\lib\config.h +copy ..\..\apr-util\include\private\apu_select_dbm.hw ..\..\apr-util\include\private\apu_select_dbm.h + +@echo Fixing up the pcre headers +copy ..\..\pcre\config.hw ..\..\pcre\config.h +copy ..\..\pcre\pcre.hw ..\..\pcre\pcre.h + +@echo Generating the import list... +set MWCIncludes=..\include;..\include\arch\netware;..\include\arch\unix;..\..\apr-util\include;+%NovellLibC% +mwccnlm -P nw_export.inc -d NETWARE -EP +awk -f make_nw_export.awk nw_export.i |sort >..\aprlib.imp + +:Done +pause diff --git a/srclib/apr/build/rpm/apr.spec.in b/srclib/apr/build/rpm/apr.spec.in new file mode 100644 index 0000000000..7d113c35a6 --- /dev/null +++ b/srclib/apr/build/rpm/apr.spec.in @@ -0,0 +1,96 @@ + +%define aprver 1 + +Summary: Apache Portable Runtime library +Name: apr +Version: APR_VERSION +Release: APR_RELEASE +License: Apache Software License +Group: System Environment/Libraries +URL: http://apr.apache.org/ +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-buildroot +BuildPrereq: autoconf, libtool, doxygen + +%description +The mission of the Apache Portable Runtime (APR) is to provide a +free library of C data structures and routines, forming a system +portability layer to as many operating systems as possible, +including Unices, MS Win32, BeOS and OS/2. + +%package devel +Group: Development/Libraries +Summary: APR library development kit +Requires: apr = %{version} + +%description devel +This package provides the support files which can be used to +build applications using the APR library. The mission of the +Apache Portable Runtime (APR) is to provide a free library of +C data structures and routines. + +%prep +%setup -q + +%build +# regenerate configure script etc. +./buildconf +%configure \ + --prefix=/usr \ + --includedir=%{_includedir}/apr-%{aprver} \ + --with-installbuilddir=%{_libdir}/apr/build-%{aprver} \ + --with-devrandom=/dev/urandom \ + CC=gcc CXX=g++ +make %{?_smp_mflags} && make dox + +%check +# Run non-interactive tests +pushd test +make %{?_smp_mflags} testall CFLAGS=-fno-strict-aliasing +./testall -v || exit 1 +popd + +%install +rm -rf $RPM_BUILD_ROOT +make install DESTDIR=$RPM_BUILD_ROOT + +# Move docs to more convenient location +mv docs/dox/html html + +# Unpackaged files: +rm -f $RPM_BUILD_ROOT%{_libdir}/apr.exp + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files +%defattr(-,root,root,-) +%doc CHANGES LICENSE NOTICE +%{_libdir}/libapr-%{aprver}.so.* + +%files devel +%defattr(-,root,root,-) +%doc docs/APRDesign.html docs/canonical_filenames.html +%doc docs/incomplete_types docs/non_apr_programs +%doc --parents html +%{_bindir}/apr*config +%{_libdir}/libapr-%{aprver}.*a +%{_libdir}/libapr-%{aprver}.so +%dir %{_libdir}/apr +%dir %{_libdir}/apr/build-%{aprver} +%{_libdir}/apr/build-%{aprver}/* +%{_libdir}/pkgconfig/apr-%{aprver}.pc +%dir %{_includedir}/apr-%{aprver} +%{_includedir}/apr-%{aprver}/*.h + +%changelog +* Tue Jun 22 2004 Graham Leggett 1.0.0-1 +- update to support v1.0.0 of APR + +* Tue Jun 22 2004 Graham Leggett 1.0.0-1 +- derived from Fedora Core apr.spec + diff --git a/srclib/apr/build/run-gcov.sh b/srclib/apr/build/run-gcov.sh new file mode 100755 index 0000000000..98f911fc89 --- /dev/null +++ b/srclib/apr/build/run-gcov.sh @@ -0,0 +1,130 @@ +#!/bin/sh + +if [ ! -d coverage ]; then + mkdir coverage +fi +cd coverage + +# It would be really nice to find a better way to do this than copying the +# HTML into this script. But, I am being lazy right now. +cat > index.html << EOF + + + + + + + Test Coverage + + +

The Apache Portable Runtime Project

+ + + + + + + + +
+ ApacheCon +

Get Involved

+ +
  • CVS
  • +
  • Mailing Lists
  • +
  • Snapshots
  • +
  • Build on Win32
  • +
  • Build on Unix
  • +
    +

    Download!

    + +
  • from a mirror
  • +
    +

    Docs

    + +
  • APR
  • +
  • APR-util
  • +
  • APR-iconv
  • +
    +

    Guidelines

    + +
  • Project Guidelines
  • +
  • Contributing
  • +
  • Version Numbers
  • +
    +

    Miscellaneous

    + +
  • License
  • +
  • Projects using APR
  • +
    +
    + + + +
    + + APR Test Coverage + +
    +
    +

    This should give us some idea of how well our tests actually stress our +code. To generate this data, do the following:

    + +
  • ./buildconf
  • +
  • CFLAGS="-fprofile-arcs -ftest-coverage ./configure
  • +
  • make
  • +
  • cd test
  • +
  • make
  • +
  • ./testall
  • +
  • cd ..
  • +
  • make gcov
  • +
    +

    Note that this will only generate test coverage data for the testall script, +but all tests should be moving to the unified framework, so this is correct.

    +
    + + +EOF + +for i in `find .. -name "*.bb" -maxdepth 1 | sort`; do + percent=`gcov $i -o .. | grep "%" | awk -F'%' {'print $1'}` + name=`echo $i | awk -F'/' {'print $2'}` + basename=`echo $name | awk -F'.' {'print $1'}` + + if [ "x$percent" = "x" ]; then + echo "" >> index.html + echo "" >> index.html + echo "
    Error generating data for $basename
    " >> index.html + continue; + fi + intpercent=`echo "$percent/1" | bc` + if [ $intpercent -lt 33 ]; then + color="#ffaaaa" + else if [ $intpercent -lt 66 ]; then + color="#ffff77" + else + color="#aaffaa" + fi + fi + + echo "
    $basename
    " >> index.html + echo "
    $percent% tested" >> index.html +done + +echo "

    Last generated `date`

    " >> index.html + +cat >> index.html << EOF +
    + +

    + + Copyright © 1999-2004, The Apache Software Foundation + +
    + + + +EOF diff --git a/srclib/apr/build/win32ver.awk b/srclib/apr/build/win32ver.awk new file mode 100644 index 0000000000..2cd31eba94 --- /dev/null +++ b/srclib/apr/build/win32ver.awk @@ -0,0 +1,121 @@ +BEGIN { + + # ff bits: 1(debug), 2(prerelease), 4(patched), 8(vendor) and 32(special) + # debug is summed based on the /Define _DEBUG + # prerelease is based on the -dev extension, + # patched is based on a non-standard "-ver" extension, + # special and vendor are toggled by their args. + # + ff = 0; + + file=ARGV[1]; + desc=ARGV[2]; + rel_h=ARGV[3]; + + filename = file; + if (match(file, /\./)) { + sub(/\.[^\.]*$/, "", file); + } + + i = 4; + while (length(ARGV[i])) { + if (match(ARGV[i], /icon=/)) { + icon = substr(ARGV[i], 6); + } + if (match(ARGV[i], /vendor=/)) { + vendor = substr(ARGV[i], 8); + ff = ff + 8; + } + if (match(ARGV[i], /special=/)) { + special = substr(ARGV[i], 9); + ff = ff + 32; + } + i = i + 1 + } + + i = i - 1; + while (i) { + delete ARGV[i]; + i = i - 1; + } + + while ((getline < rel_h) > 0) { + if (match ($0, /^#define AP._MAJOR_VERSION/)) { + ver_major = $3; + } + if (match ($0, /^#define AP._MINOR_VERSION/)) { + ver_minor = $3; + } + if (match ($0, /^#define AP._PATCH_VERSION/)) { + ver_patch = $3; + } + if (match ($0, /^#define AP._IS_DEV_VERSION/)) { + ver_suffix = "-dev"; + ver_build = "0"; + } + if (match ($0, /^#undef AP._IS_DEV_VERSION/)) { + ver_build = "100"; + } + if (match ($0, /^.*Copyright /)) { + copyright = substr($0, RLENGTH + 1); + } + } + ver = ver_major "." ver_minor "." ver_patch ver_suffix; + verc = ver_major "," ver_minor "," ver_patch "," ver_build; + + if (length(vendor)) { + ff = ff + 8; + } + + if (length(icon)) { + print "1 ICON DISCARDABLE \"" icon "\""; + } + print "1 VERSIONINFO"; + print " FILEVERSION " verc ""; + print " PRODUCTVERSION " verc ""; + print " FILEFLAGSMASK 0x3fL"; + print "#if defined(_DEBUG)" + print " FILEFLAGS 0x" sprintf("%02x", ff + 1) "L"; + print "#else" + print " FILEFLAGS 0x" sprintf("%02x", ff) "L"; + print "#endif" + print " FILEOS 0x40004L"; + print " FILETYPE 0x1L"; + print " FILESUBTYPE 0x0L"; + print "BEGIN"; + print " BLOCK \"StringFileInfo\""; + print " BEGIN"; + print " BLOCK \"040904b0\""; + print " BEGIN"; + print " VALUE \"Comments\", "\ + "\"Licensed under the Apache License, Version 2.0 (the \"\"License\"\"); "\ + "you may not use this file except in compliance with the License. "\ + "You may obtain a copy of the License at\\r\\n\\r\\n"\ + "http://www.apache.org/licenses/LICENSE-2.0\\r\\n\\r\\n"\ + "Unless required by applicable law or agreed to in writing, "\ + "software distributed under the License is distributed on an "\ + "\"\"AS IS\"\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, "\ + "either express or implied. See the License for the specific "\ + "language governing permissions and limitations under the License.\\0\""; + print " VALUE \"CompanyName\", \"Apache Software Foundation\\0\""; + print " VALUE \"FileDescription\", \"" desc "\\0\""; + print " VALUE \"FileVersion\", \"" ver "\\0\""; + print " VALUE \"InternalName\", \"" file "\\0\""; + print " VALUE \"LegalCopyright\", \"Copyright " copyright "\\0\""; + print " VALUE \"OriginalFilename\", \"" filename "\\0\""; + if (vendor) { + print " VALUE \"PrivateBuild\", \"" vendor "\\0\""; + } + if (special) { + print " VALUE \"SpecialBuild\", \"" vendor "\\0\""; + } + print " VALUE \"ProductName\", \"Apache Portable Runtime\\0\""; + print " VALUE \"ProductVersion\", \"" ver "\\0\""; + print " END"; + print " END"; + print " BLOCK \"VarFileInfo\""; + print " BEGIN"; + print " VALUE \"Translation\", 0x409, 1200"; + print " END"; + print "END"; +} diff --git a/srclib/apr/buildconf b/srclib/apr/buildconf new file mode 100755 index 0000000000..b16441f4ab --- /dev/null +++ b/srclib/apr/buildconf @@ -0,0 +1,102 @@ +#!/bin/sh +# Copyright 2000-2004 The Apache Software Foundation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# + +# buildconf: Build the support scripts needed to compile from a +# checked-out version of the source code. + +# Verify that the builder has the right config tools installed +# +build/buildcheck.sh || exit 1 + +libtoolize=`build/PrintPath glibtoolize libtoolize libtoolize15 libtoolize14` +if [ "x$libtoolize" = "x" ]; then + echo "libtoolize not found in path" + exit 1 +fi + +# Create the libtool helper files +# +# Note: we copy (rather than link) them to simplify distribution. +# Note: APR supplies its own config.guess and config.sub -- we do not +# rely on libtool's versions +# +echo "Copying libtool helper files ..." + +# Remove any libtool files so one can switch between libtool 1.3 +# and libtool 1.4 by simply rerunning the buildconf script. +(cd build ; rm -f ltconfig ltmain.sh libtool.m4) + +$libtoolize --copy --automake + +if [ -f libtool.m4 ]; then + ltfile=`pwd`/libtool.m4 +else + ltpath=`dirname $libtoolize` + ltfile=${LIBTOOL_M4-`cd $ltpath/../share/aclocal ; pwd`/libtool.m4} +fi + +if [ ! -f $ltfile ]; then + echo "$ltfile not found" + exit 1 +fi + +echo "buildconf: Using libtool.m4 at ${ltfile}." + +cat $ltfile | sed -e 's/LIBTOOL=\(.*\)top_build/LIBTOOL=\1apr_build/' > build/libtool.m4 + +# libtool.m4 from 1.6 requires ltsugar.m4 +if [ -f ltsugar.m4 ]; then + rm -f build/ltsugar.m4 + mv ltsugar.m4 build/ltsugar.m4 +fi + +# Clean up any leftovers +rm -f aclocal.m4 libtool.m4 + +# +# Generate the autoconf header and ./configure +# +echo "Creating include/arch/unix/apr_private.h.in ..." +${AUTOHEADER:-autoheader} + +echo "Creating configure ..." +### do some work to toss config.cache? +${AUTOCONF:-autoconf} + +# Remove autoconf 2.5x's cache directory +rm -rf autom4te*.cache + +echo "Generating 'make' outputs ..." +build/gen-build.py make + +# Create RPM Spec file +if [ -f `which cut` ]; then + echo rebuilding rpm spec file + ( REVISION=`build/get-version.sh all include/apr_version.h APR` + VERSION=`echo $REVISION | cut -d- -s -f1` + RELEASE=`echo $REVISION | cut -d- -s -f2` + if [ "x$VERSION" = "x" ]; then + VERSION=$REVISION + RELEASE=1 + fi + cat ./build/rpm/apr.spec.in | \ + sed -e "s/APR_VERSION/$VERSION/" \ + -e "s/APR_RELEASE/$RELEASE/" \ + > apr.spec ) +fi + +exit 0 diff --git a/srclib/apr/config.layout b/srclib/apr/config.layout new file mode 100644 index 0000000000..0f42e84e27 --- /dev/null +++ b/srclib/apr/config.layout @@ -0,0 +1,231 @@ +## +## config.layout -- Pre-defined Installation Path Layouts +## +## Hints: +## - layouts can be loaded with configure's --enable-layout=ID option +## - when no --enable-layout option is given, the default layout is `apr' +## - a trailing plus character (`+') on paths is replaced with a +## `/' suffix where is currently hardcoded to 'apr'. +## (This may become a configurable parameter at some point.) +## + +# Classical APR path layout designed for parallel installs. + + prefix: /usr/local/apr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/bin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/modules + mandir: ${prefix}/man + sysconfdir: ${prefix}/conf + datadir: ${prefix} + installbuilddir: ${datadir}/build-${APR_MAJOR_VERSION} + includedir: ${prefix}/include/apr-${APR_MAJOR_VERSION} + localstatedir: ${prefix} + libsuffix: -${APR_MAJOR_VERSION} + + +# Classical single-installation APR path layout. + + prefix: /usr/local/apr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/bin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/modules + mandir: ${prefix}/man + sysconfdir: ${prefix}/conf + datadir: ${prefix} + installbuilddir: ${datadir}/build + includedir: ${prefix}/include + localstatedir: ${prefix} + + +# GNU standards conforming path layout. +# See FSF's GNU project `make-stds' document for details. + + prefix: /usr/local + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec + mandir: ${prefix}/man + sysconfdir: ${prefix}/etc+ + datadir: ${prefix}/share+ + installbuilddir: ${datadir}/build + includedir: ${prefix}/include+ + localstatedir: ${prefix}/var+ + runtimedir: ${localstatedir}/run + + +# Mac OS X Server (Rhapsody) + + prefix: /Local/Library/WebServer + exec_prefix: /usr + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: /System/Library/apr/Modules + mandir: ${exec_prefix}/share/man + sysconfdir: ${prefix}/Configuration + datadir: ${prefix} + installbuilddir: /System/Library/apr/Build + includedir: /System/Library/Frameworks/apr.framework/Versions/2.0/Headers + localstatedir: /var + runtimedir: ${prefix}/Logs + + +# Darwin/Mac OS Layout + + prefix: /usr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec+ + mandir: ${prefix}/share/man + datadir: /Library/WebServer + sysconfdir: /etc+ + installbuilddir: ${prefix}/share/httpd/build + includedir: ${prefix}/include+ + localstatedir: /var + runtimedir: ${localstatedir}/run + + +# Red Hat Linux 7.x layout + + prefix: /usr + exec_prefix: ${prefix} + bindir: ${prefix}/bin + sbindir: ${prefix}/sbin + libdir: ${prefix}/lib + libexecdir: ${prefix}/lib/apr + mandir: ${prefix}/man + sysconfdir: /etc/httpd/conf + datadir: /var/www + installbuilddir: ${datadir}/build + includedir: ${prefix}/include/apr + localstatedir: /var + runtimedir: ${localstatedir}/run + + +# According to the /opt filesystem conventions + + prefix: /opt/apr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec + mandir: ${prefix}/man + sysconfdir: /etc${prefix} + datadir: ${prefix}/share + installbuilddir: ${datadir}/build + includedir: ${prefix}/include + localstatedir: /var${prefix} + runtimedir: ${localstatedir}/run + + +# BeOS layout... + + prefix: /boot/home/apr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/bin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec + mandir: ${prefix}/man + sysconfdir: ${prefix}/conf + datadir: ${prefix} + installbuilddir: ${datadir}/build + includedir: ${prefix}/include + localstatedir: ${prefix} + runtimedir: ${localstatedir}/logs + + +# SuSE 6.x layout + + prefix: /usr + exec_prefix: ${prefix} + bindir: ${prefix}/bin + sbindir: ${prefix}/sbin + libdir: ${prefix}/lib + libexecdir: ${prefix}/lib/apr + mandir: ${prefix}/share/man + sysconfdir: /etc/httpd + datadir: /usr/local/httpd + installbuilddir: ${datadir}/build + includedir: ${prefix}/include/apr + localstatedir: /var/lib/httpd + runtimedir: /var/run + + +# BSD/OS layout + + prefix: /var/www + exec_prefix: /usr/contrib + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/bin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec/apr + mandir: ${exec_prefix}/man + sysconfdir: ${prefix}/conf + datadir: ${prefix} + installbuilddir: ${datadir}/build + includedir: ${exec_prefix}/include/apr + localstatedir: /var + runtimedir: ${localstatedir}/run + + +# Solaris 8 Layout + + prefix: /usr/apr + exec_prefix: ${prefix} + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/bin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/libexec + mandir: ${exec_prefix}/man + sysconfdir: /etc/apr + datadir: /var/apr + installbuilddir: ${datadir}/build + includedir: ${exec_prefix}/include + localstatedir: ${prefix} + runtimedir: /var/run + + +# OpenBSD Layout + + prefix: /var/www + exec_prefix: /usr + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/lib/apr/modules + mandir: ${exec_prefix}/share/man + sysconfdir: ${prefix}/conf + datadir: ${prefix} + installbuilddir: ${prefix}/build + includedir: ${exec_prefix}/lib/apr/include + localstatedir: ${prefix} + runtimedir: ${prefix}/logs + + +# Debian layout + + prefix: + exec_prefix: ${prefix}/usr + bindir: ${exec_prefix}/bin + sbindir: ${exec_prefix}/sbin + libdir: ${exec_prefix}/lib + libexecdir: ${exec_prefix}/lib/apr/modules + mandir: ${exec_prefix}/share/man + datadir: ${exec_prefix}/share/apr + includedir: ${exec_prefix}/include/apr-${APR_MAJOR_VERSION} + localstatedir: ${prefix}/var/run + runtimedir: ${prefix}/var/run + infodir: ${exec_prefix}/share/info + libsuffix: -${APR_MAJOR_VERSION} + diff --git a/srclib/apr/configure.in b/srclib/apr/configure.in new file mode 100644 index 0000000000..ae5fa6e9fb --- /dev/null +++ b/srclib/apr/configure.in @@ -0,0 +1,2075 @@ +dnl +dnl Autoconf configuration file for APR +dnl +dnl Process this file with autoconf to produce a configure script. +dnl Use ./buildconf to prepare build files and run autoconf for APR. + +AC_PREREQ(2.50) + +AC_INIT(build/apr_common.m4) +AC_CONFIG_HEADER(include/arch/unix/apr_private.h) +AC_CONFIG_AUX_DIR(build) + +dnl +dnl Include our own M4 macros along with those for libtool +dnl +sinclude(build/apr_common.m4) +sinclude(build/apr_network.m4) +sinclude(build/apr_threads.m4) +sinclude(build/apr_hints.m4) +sinclude(build/libtool.m4) +sinclude(build/ltsugar.m4) + +dnl Hard-coded inclusion at the tail end of apr_private.h: +AH_BOTTOM([ +/* switch this on if we have a BeOS version below BONE */ +#if BEOS && !HAVE_BONE_VERSION +#define BEOS_R5 1 +#else +#define BEOS_BONE 1 +#endif + +/* + * Include common private declarations. + */ +#include "../apr_private_common.h" +]) + +dnl Save user-defined environment settings for later restoration +dnl +APR_SAVE_THE_ENVIRONMENT(CPPFLAGS) +APR_SAVE_THE_ENVIRONMENT(CFLAGS) +APR_SAVE_THE_ENVIRONMENT(LDFLAGS) +APR_SAVE_THE_ENVIRONMENT(LIBS) +APR_SAVE_THE_ENVIRONMENT(INCLUDES) + +dnl Generate ./config.nice for reproducing runs of configure +dnl +APR_CONFIG_NICE(config.nice) + +AC_CANONICAL_SYSTEM +echo "Configuring APR library" +echo "Platform: $host" + +dnl Some initial steps for configuration. We setup the default directory +dnl and which files are to be configured. + +dnl Setup the directory macros now + +# Absolute source/build directory +apr_srcdir=`(cd $srcdir && pwd)` +apr_builddir=`pwd` +AC_SUBST(apr_srcdir) +AC_SUBST(apr_builddir) + +if test "$apr_builddir" != "$apr_srcdir"; then + USE_VPATH=1 + APR_CONFIG_LOCATION=build +else + APR_CONFIG_LOCATION=source +fi + +AC_SUBST(APR_CONFIG_LOCATION) + +# Libtool might need this symbol -- it must point to the location of +# the generated libtool script (not necessarily the "top" build dir). +# +top_builddir="$apr_builddir" +AC_SUBST(top_builddir) + +# Directory containing apr build macros, helpers, and make rules +# NOTE: make rules (apr_rules.mk) will be in the builddir for vpath +# +apr_buildout=$apr_builddir/build +apr_builders=$apr_srcdir/build +AC_SUBST(apr_builders) + +MKDIR=$apr_builders/mkdir.sh + +dnl Initialize mkdir -p functionality. +APR_MKDIR_P_CHECK($apr_builders/mkdir.sh) + +# get our version information +get_version="$apr_builders/get-version.sh" +version_hdr="$apr_srcdir/include/apr_version.h" +APR_MAJOR_VERSION="`$get_version major $version_hdr APR`" +APR_DOTTED_VERSION="`$get_version all $version_hdr APR`" + +AC_SUBST(APR_DOTTED_VERSION) +AC_SUBST(APR_MAJOR_VERSION) + +echo "APR Version: ${APR_DOTTED_VERSION}" + +dnl Enable the layout handling code, then reparse the prefix-style +dnl arguments due to autoconf being a PITA. +APR_ENABLE_LAYOUT(apr) +APR_PARSE_ARGUMENTS + +dnl Set optional CC hints here in case autoconf makes an inappropriate choice. +dnl This allows us to suggest what the compiler should be, but still +dnl allows the user to override CC externally. +APR_CC_HINTS + +dnl Do the various CC checks *before* preloading values. The preload code +dnl may need to use compiler characteristics to make decisions. This macro +dnl can only be used once within a configure script, so this prevents a +dnl preload section from invoking the macro to get compiler info. +AC_PROG_CC + +dnl Preload +APR_PRELOAD + +dnl These added to allow default directories to be used... +DEFAULT_OSDIR="unix" +echo "(Default will be ${DEFAULT_OSDIR})" + +apr_modules="file_io network_io threadproc misc locks time mmap shmem user memory atomic poll support random" + +dnl Checks for programs. +AC_PROG_MAKE_SET +AC_PROG_CPP +AC_PROG_AWK +AC_PROG_LN_S +AC_PROG_RANLIB +AC_PROG_INSTALL +AC_CHECK_PROG(RM, rm, rm) +AC_CHECK_PROG(AS, as, as) +AC_CHECK_PROG(ASCPP, cpp, cpp) +AC_CHECK_TOOL(AR, ar, ar) + +dnl Various OS checks that apparently set required flags +AC_AIX +AC_ISC_POSIX +AC_MINIX + +APR_EBCDIC + +dnl this is our library name +APR_LIBNAME="apr${libsuffix}" +AC_SUBST(APR_LIBNAME) + +dnl prep libtool +dnl +echo "performing libtool configuration..." + +AC_ARG_ENABLE(experimental-libtool,[ --enable-experimental-libtool Use experimental custom libtool], + [experimental_libtool=$enableval],[experimental_libtool=no]) + +case $host in +*-os2*) + # Use a custom-made libtool replacement + echo "using aplibtool" + LIBTOOL="$srcdir/build/aplibtool" + gcc $CFLAGS $CPPFLAGS -o $LIBTOOL.exe $LIBTOOL.c + ;; +*) + if test "x$LTFLAGS" = "x"; then + LTFLAGS='--silent' + fi + if test "$experimental_libtool" = "yes"; then + # Use a custom-made libtool replacement + echo "using jlibtool" + LIBTOOL="$apr_builddir/libtool" + LIBTOOL_SRC="$apr_srcdir/build/jlibtool.c" + $CC $CFLAGS $CPPFLAGS -o $LIBTOOL $LIBTOOL_SRC + eval `$apr_builddir/libtool --config | grep "^shlibpath_var=[[A-Z_]]*$"` + if test "x$shlibpath_var" = "x"; then + shlibpath_var=REPLACE_WITH_YOUR_SHLIBPATH_VAR + fi + else + dnl libtoolize requires that the following not be indented +AC_PROG_LIBTOOL + # get libtool's setting of shlibpath_var + eval `grep "^shlibpath_var=[[A-Z_]]*$" $apr_builddir/libtool` + if test "x$shlibpath_var" = "x"; then + shlibpath_var=REPLACE_WITH_YOUR_SHLIBPATH_VAR + fi + fi + ;; +esac + +AC_ARG_WITH(installbuilddir, [ --with-installbuilddir=DIR location to store APR build files (defaults to '${datadir}/build')], + [ installbuilddir=$withval ], [ installbuilddir="${datadir}/build-${APR_MAJOR_VERSION}" ] ) +AC_SUBST(installbuilddir) + +AC_ARG_WITH(libtool, [ --without-libtool avoid using libtool to link the library], + [ use_libtool=$withval ], [ use_libtool="yes" ] ) + +if test "x$use_libtool" = "xyes"; then + lt_compile='$(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -o $@ -c $< && touch $@' + LT_VERSION="-version-info `$get_version libtool $version_hdr APR`" + link="\$(LIBTOOL) \$(LTFLAGS) --mode=link \$(LT_LDFLAGS) \$(COMPILE) ${LT_VERSION} \$(ALL_LDFLAGS) -o \$@" + so_ext='lo' + lib_target='-rpath $(libdir) $(OBJECTS)' + export_lib_target='-rpath \$(libdir) \$(OBJECTS)' +else + lt_compile='$(COMPILE) -o $@ -c $<' + link='$(AR) cr $(TARGET_LIB) $(OBJECTS); $(RANLIB) $(TARGET_LIB)' + so_ext='o' + lib_target='' + export_lib_target='' +fi + +case $host in + *-solaris2*) + apr_platform_runtime_link_flag="-R" + ;; + *) + ;; +esac + +AC_SUBST(lt_compile) +AC_SUBST(link) +AC_SUBST(so_ext) +AC_SUBST(lib_target) +AC_SUBST(export_lib_target) +AC_SUBST(shlibpath_var) +AC_SUBST(LTFLAGS) +AC_SUBST(LT_LDFLAGS) + +dnl ----------------------------- Checks for compiler flags +nl=' +' +echo "${nl}Check for compiler flags..." + +dnl AC_PROG_CC sets -g in CFLAGS (and -O2 for gcc) by default. +dnl On OS/390 this causes the compiler to insert extra debugger +dnl hook instructions. That's fine for debug/maintainer builds, not fine +dnl otherwise. + +case $host in + *os390) + if test "$ac_test_CFLAGS" != set; then + APR_REMOVEFROM(CFLAGS,-g) + fi + ;; +esac + +AC_ARG_ENABLE(debug,[ --enable-debug Turn on debugging and compile time warnings], + [APR_ADDTO(CFLAGS,-g) + if test "$GCC" = "yes"; then + APR_ADDTO(CFLAGS,-Wall) + elif test "$AIX_XLC" = "yes"; then + APR_ADDTO(CFLAGS,-qfullpath) + fi +])dnl + +AC_ARG_ENABLE(maintainer-mode,[ --enable-maintainer-mode Turn on debugging and compile time warnings], + [APR_ADDTO(CFLAGS,-g) + if test "$GCC" = "yes"; then + APR_ADDTO(CFLAGS,[-Wall -Wmissing-prototypes -Wstrict-prototypes -Wmissing-declarations]) + elif test "$AIX_XLC" = "yes"; then + APR_ADDTO(CFLAGS,-qfullpath -qinitauto=FE -qcheck=all -qinfo=pro) + fi +])dnl + +AC_ARG_ENABLE(profile,[ --enable-profile Turn on profiling for the build (GCC)], + if test "$GCC" = "yes"; then + APR_ADDTO(CFLAGS, -pg) + APR_REMOVEFROM(CFLAGS, -g) + if test "$host" = "i586-pc-beos"; then + APR_REMOVEFROM(CFLAGS, -O2) + APR_ADDTO(CFLAGS, -O1) + APR_ADDTO(LDFLAGS, -p) + fi + fi +)dnl + +AC_ARG_ENABLE(pool-debug, + [ --enable-pool-debug[[=yes|no|verbose|verbose-alloc|lifetime|owner|all]] Turn on pools debugging], + [ if test -z "$enableval"; then + APR_ADDTO(CPPFLAGS, -DAPR_POOL_DEBUG=1) + elif test ! "$enableval" = "no"; then + apr_pool_debug=1 + + for i in $enableval + do + flag=0 + + case $i in + yes) + flag=1 + ;; + verbose) + flag=2 + ;; + lifetime) + flag=4 + ;; + owner) + flag=8 + ;; + verbose-alloc) + flag=16 + ;; + all) + apr_pool_debug=31 + ;; + *) + ;; + esac + + if test $flag -gt 0; then + apr_pool_debug=`expr '(' $apr_pool_debug - $apr_pool_debug % \ + '(' $flag '*' 2 ')' ')' + $flag + $apr_pool_debug % $flag` + fi + done + + APR_ADDTO(CPPFLAGS, -DAPR_POOL_DEBUG=$apr_pool_debug) + fi + ]) + +dnl Electric Fence malloc checker. +dnl --with-efence specifies the path to Electric Fence +AC_ARG_WITH(efence, + [ --with-efence[[=DIR]] path to Electric Fence installation], + [ apr_efence_dir="$withval" + if test "$apr_efence_dir" != "yes"; then + APR_ADDTO(LDFLAGS,[-L$apr_efence_dir/lib]) + if test "x$apr_platform_runtime_link_flag" != "x"; then + APR_ADDTO(LDFLAGS, + [$apr_platform_runtime_link_flag$apr_efence_dir/lib]) + fi + fi + AC_CHECK_LIB(efence, malloc, + [ APR_ADDTO(LIBS,-lefence) ], + [ AC_MSG_ERROR(Electric Fence requested but not detected) ]) + ]) + +if test "$host" = "i586-pc-beos"; then + AC_ARG_ENABLE(malloc-debug,[ --enable-malloc-debug Switch on malloc_debug for BeOS], + APR_REMOVEFROM(CFLAGS, -O2) + APR_ADDTO(CPPFLAGS, -fcheck-memory-usage -D_KERNEL_MODE) + ) dnl +fi + +# this is the place to put specific options for platform/compiler +# combinations +case "$host:$CC" in + *-hp-hpux*:cc ) + APR_ADDTO(CFLAGS,[-Ae +Z]) + case $host in + ia64-* ) + ;; + * ) + if echo "$CFLAGS " | grep '+DA' >/dev/null; then : + else + APR_ADDTO(CFLAGS,[+DAportable]) + fi + ;; + esac + ;; + powerpc-*-beos:mwcc* ) + APR_SETVAR(CPP,[mwcc -E]) + APR_SETVAR(CC,mwcc) + APR_SETVAR(AR,ar) + ;; +esac + +dnl Check the depend program we can use +APR_CHECK_DEPEND + +proc_mutex_is_global=0 + +config_subdirs="none" +INSTALL_SUBDIRS="none" +OBJECTS_PLATFORM='$(OBJECTS_unix)' + +case $host in + i386-ibm-aix* | *-ibm-aix[1-2].* | *-ibm-aix3.* | *-ibm-aix4.1 | *-ibm-aix4.1.* | *-ibm-aix4.2 | *-ibm-aix4.2.*) + OSDIR="aix" + APR_ADDTO(LDFLAGS,-lld) + eolstr="\\n" + OBJECTS_PLATFORM='$(OBJECTS_aix)' + ;; + *-os2*) + APR_ADDTO(CPPFLAGS,-DOS2) + APR_ADDTO(CFLAGS,-Zmt) + AC_CHECK_LIB(bsd, random) + OSDIR="os2" + enable_threads="system_threads" + eolstr="\\r\\n" + file_as_socket="0" + proc_mutex_is_global=1 + OBJECTS_PLATFORM='$(OBJECTS_os2)' + ;; + *beos*) + OSDIR="beos" + APR_ADDTO(CPPFLAGS,-DBEOS) + enable_threads="system_threads" + native_mmap_emul="1" + APR_CHECK_DEFINE(BONE_VERSION, sys/socket.h) + eolstr="\\n" + osver=`uname -r` + proc_mutex_is_global=1 + OBJECTS_PLATFORM='$(OBJECTS_beos)' + case $osver in + 5.0.4) + file_as_socket="1" + ;; + *) + file_as_socket="0" + ;; + esac + ;; + *os390) + OSDIR="os390" + OBJECTS_PLATFORM='$(OBJECTS_os390)' + eolstr="\\n" + ;; + *os400) + OSDIR="as400" + eolstr="\\n" + ;; + *cygwin*) + OSDIR="unix" + APR_ADDTO(CPPFLAGS,-DCYGWIN) + enable_threads="no" + eolstr="\\n" + ;; + *hpux10* ) + enable_threads="no" + OSDIR="unix" + eolstr="\\n" + ;; + *) + OSDIR="unix" + eolstr="\\n" + ;; +esac + +AC_SUBST(OBJECTS_PLATFORM) + +# Check whether LFS has explicitly been disabled +AC_ARG_ENABLE(lfs,[ --disable-lfs Disable large file support on 32-bit platforms], +[apr_lfs_choice=$enableval], [apr_lfs_choice=yes]) + +if test "$apr_lfs_choice" = "yes"; then + # Check whether the transitional LFS API is sufficient + AC_CACHE_CHECK([whether to enable -D_LARGEFILE64_SOURCE], [apr_cv_use_lfs64], [ + apr_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -D_LARGEFILE64_SOURCE" + AC_TRY_RUN([ +#include +#include +#include +#include +#include +#include + +void main(void) +{ + int fd, ret = 0; + struct stat64 st; + off64_t off = 4242; + + if (sizeof(off64_t) != 8 || sizeof(off_t) != 4) + exit(1); + if ((fd = open("conftest.lfs", O_LARGEFILE|O_CREAT|O_WRONLY)) < 0) + exit(2); + if (ftruncate64(fd, off) != 0) + ret = 3; + else if (fstat64(fd, &st) != 0 || st.st_size != off) + ret = 4; + else if (lseek64(fd, off, SEEK_SET) != off) + ret = 5; + else if (close(fd) != 0) + ret = 6; + else if (lstat64("conftest.lfs", &st) != 0 || st.st_size != off) + ret = 7; + else if (stat64("conftest.lfs", &st) != 0 || st.st_size != off) + ret = 8; + unlink("conftest.lfs"); + + exit(ret); +}], [apr_cv_use_lfs64=yes], [apr_cv_use_lfs64=no], [apr_cv_use_lfs64=no]) + CPPFLAGS=$apr_save_CPPFLAGS]) + if test "$apr_cv_use_lfs64" = "yes"; then + APR_ADDTO(CPPFLAGS, [-D_LARGEFILE64_SOURCE]) + fi +fi + +AC_ARG_ENABLE(nonportable-atomics, +[ --enable-nonportable-atomics Use optimized atomic code which may produce nonportable binaries], +[if test $enableval = yes; then + force_generic_atomics=no + else + force_generic_atomics=yes + fi +], +[case $host_cpu in + i[[456]]86) force_generic_atomics=yes ;; + *) force_generic_atomics=no ;; +esac +]) + +if test $force_generic_atomics = yes; then + AC_DEFINE([USE_GENERIC_ATOMICS], 1, + [Define if use of generic atomics is requested]) +fi + +AC_SUBST(proc_mutex_is_global) +AC_SUBST(eolstr) +AC_SUBST(INSTALL_SUBDIRS) + +# For some platforms we need a version string which allows easy numeric +# comparisons. +case $host in + *freebsd*) + # 3.4-RELEASE: 340 4.1.1-RELEASE: 411 + os_version=`uname -r | sed -e 's/\(.\)\.\(.\)\.\(.\).*/\1\2\3/' | sed -e 's/\(.\)\.\(.\)\-.*/\1\20/'` + ;; + *linux*) + os_version=`uname -r | sed -e 's/\(.\)\.\(.\)\.\(.\).*/\1\2\3/'` + ;; + *darwin*) + os_version=`uname -r | sed -e 's/\(.\)\.\(.\).*/\1\2/'` + ;; + *) + os_version=OS_VERSION_IS_NOT_SET + ;; +esac + +echo "${nl}Checking for libraries..." + +dnl ----------------------------- Checks for Any required Libraries +dnl Note: Autoconf will always append LIBS with an extra " " in AC_CHECK_LIB. +dnl It should check for LIBS being empty and set LIBS equal to the new value +dnl without the extra " " in that case, but they didn't do that. So, we +dnl end up LIBS="-lm -lcrypt -lnsl -ldl" which is an annoyance. +AC_SEARCH_LIBS(gethostbyname, nsl) +AC_SEARCH_LIBS(gethostname, nsl) +AC_SEARCH_LIBS(socket, socket) +AC_SEARCH_LIBS(crypt, crypt ufc) +AC_CHECK_LIB(truerand, main) +AC_SEARCH_LIBS(modf, m) + +dnl ----------------------------- Checking for Threads +echo "${nl}Checking for Threads..." + +if test -z "$enable_threads"; then + AC_ARG_ENABLE(threads, + [ --enable-threads Enable threading support in APR.], + [ enable_threads=$enableval] , + [ APR_CHECK_PTHREADS_H([ enable_threads="pthread" ] , + [ enable_threads="no" ] ) ] ) +fi + +if test "$enable_threads" = "no"; then + threads="0" + pthreadh="0" + pthreadser="0" +else + if test "$enable_threads" = "pthread"; then +# We have specified pthreads for our threading library, just make sure +# that we have everything we need + APR_PTHREADS_CHECK_SAVE + APR_PTHREADS_CHECK + APR_CHECK_PTHREADS_H([ + threads="1" + pthreadh="1" + pthreadser="1" ], [ + threads="0" + pthreadh="0" + pthreadser="0" + APR_PTHREADS_CHECK_RESTORE ] ) + elif test "$enable_threads" = "system_threads"; then + threads="1" + pthreadh="0" + pthreadser="0" + else +# We basically specified that we wanted threads, but not how to implement +# them. In this case, just look for pthreads. In the future, we can check +# for other threading libraries as well. + APR_PTHREADS_CHECK_SAVE + APR_PTHREADS_CHECK + APR_CHECK_PTHREADS_H([ + threads="1" + pthreadh="1" + pthreadser="1" ], [ + threads="0" + pthreadser="0" + pthreadh="0" + APR_PTHREADS_CHECK_RESTORE ] ) + fi + if test "$pthreadh" = "1"; then + APR_CHECK_PTHREAD_GETSPECIFIC_TWO_ARGS + APR_CHECK_PTHREAD_ATTR_GETDETACHSTATE_ONE_ARG + APR_CHECK_PTHREAD_RECURSIVE_MUTEX + AC_CHECK_FUNCS([pthread_key_delete pthread_rwlock_init \ + pthread_attr_setguardsize]) + + if test "$ac_cv_func_pthread_rwlock_init" = "yes"; then + dnl ----------------------------- Checking for pthread_rwlock_t + AC_CACHE_CHECK([for pthread_rwlock_t], [apr_cv_type_rwlock_t], + AC_TRY_COMPILE([#include +#include ], [pthread_rwlock_t *rwlock;], + [apr_cv_type_rwlock_t=yes], [apr_cv_type_rwlock_t=no], + [apr_cv_type_rwlock_t=no])) + if test "$apr_cv_type_rwlock_t" = "yes"; then + AC_DEFINE(HAVE_PTHREAD_RWLOCKS, 1, [Define if pthread rwlocks are available]) + fi + fi + fi +fi + +ac_cv_define_READDIR_IS_THREAD_SAFE=no +ac_cv_define_GETHOSTBYNAME_IS_THREAD_SAFE=no +ac_cv_define_GETHOSTBYADDR_IS_THREAD_SAFE=no +if test "$threads" = "1"; then + echo "APR will use threads" + AC_CHECK_LIB(c_r, readdir, + AC_DEFINE(READDIR_IS_THREAD_SAFE, 1, + [Define if readdir is thread safe])) + if test "x$apr_gethostbyname_is_thread_safe" = "x"; then + AC_CHECK_LIB(c_r, gethostbyname, apr_gethostbyname_is_thread_safe=yes) + fi + if test "$apr_gethostbyname_is_thread_safe" = "yes"; then + AC_DEFINE(GETHOSTBYNAME_IS_THREAD_SAFE, 1, + [Define if gethostbyname is thread safe]) + fi + if test "x$apr_gethostbyaddr_is_thread_safe" = "x"; then + AC_CHECK_LIB(c_r, gethostbyaddr, apr_gethostbyaddr_is_thread_safe=yes) + fi + if test "$apr_gethostbyaddr_is_thread_safe" = "yes"; then + AC_DEFINE(GETHOSTBYADDR_IS_THREAD_SAFE, 1, + [Define if gethostbyaddr is thread safe]) + fi + AC_CHECK_FUNCS(gethostbyname_r gethostbyaddr_r) +else + echo "APR will be non-threaded" +fi + +AC_CHECK_FUNCS(sigsuspend, [ have_sigsuspend="1" ], [ have_sigsuspend="0" ]) +AC_CHECK_FUNCS(sigwait, [ have_sigwait="1" ], [ have_sigwait="0" ]) +dnl AC_CHECK_FUNCS doesn't work for this on Tru64 since the function +dnl is renamed in signal.h. Todo: Autodetect +case $host in + *alpha*-dec-osf* ) + have_sigwait="1" + ;; +esac + +AC_SUBST(threads) +AC_SUBST(have_sigsuspend) +AC_SUBST(have_sigwait) + +AC_CHECK_FUNCS(poll kqueue port_create) + +# Check for the Linux epoll interface; epoll* may be available in libc +# but return ENOSYS on a pre-2.6 kernel, so do a run-time check. +AC_CACHE_CHECK([for epoll support], [apr_cv_epoll], +[AC_TRY_RUN([ +#include +#include + +int main() +{ + return epoll_create(5) == -1; +}], [apr_cv_epoll=yes], [apr_cv_epoll=no], [apr_cv_epoll=no])]) + +if test "$apr_cv_epoll" = "yes"; then + AC_DEFINE([HAVE_EPOLL], 1, [Define if the epoll interface is supported]) +fi + +dnl ----------------------------- Checking for missing POSIX thread functions +AC_CHECK_FUNCS([getpwnam_r getpwuid_r getgrnam_r getgrgid_r]) + +dnl ----------------------------- Checking for Shared Memory Support +echo "${nl}Checking for Shared Memory Support..." + +# The real-time POSIX extensions (e.g. shm_*, sem_*) may only +# be available if linking against librt. +AC_SEARCH_LIBS(shm_open, rt) + +case $host in + *-sysv*) + ac_includes_default="$ac_includes_default +#if HAVE_SYS_MUTEX_H /* needed to define lock_t for sys/shm.h */ +# include +#endif";; +esac + +AC_CHECK_HEADERS([sys/types.h sys/mman.h sys/ipc.h sys/mutex.h sys/shm.h sys/file.h kernel/OS.h os2.h]) +AC_CHECK_FUNCS([mmap munmap shm_open shm_unlink shmget shmat shmdt shmctl \ + create_area]) +APR_CHECK_DEFINE(MAP_ANON, sys/mman.h) +APR_CHECK_FILE(/dev/zero) + +# Not all systems can mmap /dev/zero (such as HP-UX). Check for that. +if test "$ac_cv_func_mmap" = "yes" && + test "$ac_cv_file__dev_zero" = "yes"; then + AC_MSG_CHECKING(for mmap that can map /dev/zero) + AC_TRY_RUN([ +#include +#include +#include +#ifdef HAVE_SYS_MMAN_H +#include +#endif + int main() + { + int fd; + void *m; + fd = open("/dev/zero", O_RDWR); + if (fd < 0) { + return 1; + } + m = mmap(0, sizeof(void*), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (m == (void *)-1) { /* aka MAP_FAILED */ + return 2; + } + if (munmap(m, sizeof(void*)) < 0) { + return 3; + } + return 0; + }], [], [ac_cv_file__dev_zero=no], [ac_cv_file__dev_zero=no]) + + AC_MSG_RESULT($ac_cv_file__dev_zero) +fi + +# Now we determine which one is our anonymous shmem preference. +haveshmgetanon="0" +havemmapzero="0" +havemmapanon="0" +APR_BEGIN_DECISION([anonymous shared memory allocation method]) +APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl + func:shmget func:shmat func:shmdt func:shmctl, + [haveshmgetanon="1" + APR_DECIDE(USE_SHMEM_SHMGET_ANON, [SysV IPC shmget()])]) +APR_IFALLYES(header:sys/mman.h func:mmap func:munmap file:/dev/zero, + [havemmapzero="1" + APR_DECIDE(USE_SHMEM_MMAP_ZERO, + [SVR4-style mmap() on /dev/zero])]) +APR_IFALLYES(header:sys/mman.h func:mmap func:munmap define:MAP_ANON, + [havemmapanon="1" + APR_DECIDE(USE_SHMEM_MMAP_ANON, + [4.4BSD-style mmap() via MAP_ANON])]) +APR_IFALLYES(header:os2.h, + [haveos2shm="1" + APR_DECIDE(USE_SHMEM_OS2_ANON, [OS/2 DosAllocSharedMem()])]) +APR_IFALLYES(header:kernel/OS.h func:create_area, + [havebeosshm="1" + APR_DECIDE(USE_SHMEM_BEOS_ANON, + [BeOS areas])]) +case $host in + *linux* ) + # Linux has problems with MM_SHMT_MMANON even though it reports + # that it has it. + # FIXME - find exact 2.3 version that MMANON was fixed in. It is + # confirmed fixed in 2.4 series. + if test $os_version -le "240"; then + APR_DECISION_OVERRIDE(USE_SHMEM_MMAP_ZERO USE_SHMEM_SHMGET_ANON) + fi + ;; + *hpux11* ) + APR_DECISION_OVERRIDE(USE_SHMEM_SHMGET_ANON) + ;; +esac +APR_END_DECISION +AC_DEFINE_UNQUOTED($ac_decision) + +useshmgetanon="0" +usemmapzero="0" +usemmapanon="0" + +case $ac_decision in + USE_SHMEM_SHMGET_ANON ) + useshmgetanon="1" + ;; + USE_SHMEM_MMAP_ZERO ) + usemmapzero="1" + ;; + USE_SHMEM_MMAP_ANON ) + usemmapanon="1" + ;; +esac + +AC_SUBST(useshmgetanon) +AC_SUBST(usemmapzero) +AC_SUBST(usemmapanon) +AC_SUBST(haveshmgetanon) +AC_SUBST(havemmapzero) +AC_SUBST(havemmapanon) + +# Now we determine which one is our name-based shmem preference. +havemmaptmp="0" +havemmapshm="0" +haveshmget="0" +havebeosarea="0" +haveos2shm="0" +APR_BEGIN_DECISION([namebased memory allocation method]) +APR_IFALLYES(header:sys/mman.h func:mmap func:munmap, + [havemmaptmp="1" + APR_DECIDE(USE_SHMEM_MMAP_TMP, + [Classical mmap() on temporary file])]) +APR_IFALLYES(header:sys/mman.h func:mmap func:munmap func:shm_open dnl + func:shm_unlink, + [havemmapshm="1" + APR_DECIDE(USE_SHMEM_MMAP_SHM, + [mmap() via POSIX.1 shm_open() on temporary file])]) +APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl + func:shmget func:shmat func:shmdt func:shmctl, + [haveshmget="1" + APR_DECIDE(USE_SHMEM_SHMGET, [SysV IPC shmget()])]) +APR_IFALLYES(header:kernel/OS.h func:create_area, + [havebeosshm="1" + APR_DECIDE(USE_SHMEM_BEOS, [BeOS areas])]) +APR_IFALLYES(header:os2.h, + [haveos2shm="1" + APR_DECIDE(USE_SHMEM_OS2, [OS/2 DosAllocSharedMem()])]) +case $host in + *linux* ) + # Linux has problems with MM_SHMT_MMANON even though it reports + # that it has it. + # FIXME - find exact 2.3 version that MMANON was fixed in. It is + # confirmed fixed in 2.4 series. + if test $os_version -le "240"; then + APR_DECISION_OVERRIDE(USE_SHMEM_MMAP_TMP USE_SHMEM_MMAP_SHM dnl + USE_SHMEM_SHMGET) + fi + ;; +esac +APR_END_DECISION +AC_DEFINE_UNQUOTED($ac_decision) + +usemmaptmp="0" +usemmapshm="0" +useshmget="0" +usebeosarea="0" +useos2shm="0" + +case $ac_decision in + USE_SHMEM_MMAP_TMP ) + usemmaptmp="1" + ;; + USE_SHMEM_MMAP_SHM ) + usemmapshm="1" + ;; + USE_SHMEM_SHMGET ) + useshmget="1" + ;; + USE_SHMEM_BEOS ) + usebeosarea="1" + ;; + USE_SHMEM_OS2 ) + useos2shm="1" + ;; +esac + +# Do we have any shared memory support? +if test "$usemmaptmp$usemmapshm$usemmapzero$useshmget$usemmapanon$usebeosarea$useos2shm" = "0000000"; then + sharedmem="0" +else + sharedmem="1" +fi + +AC_SUBST(usemmaptmp) +AC_SUBST(usemmapshm) +AC_SUBST(useshmget) +AC_SUBST(usebeosarea) +AC_SUBST(useos2shm) +AC_SUBST(havemmaptmp) +AC_SUBST(havemmapshm) +AC_SUBST(haveshmget) +AC_SUBST(havebeosarea) +AC_SUBST(haveos2shm) +AC_SUBST(sharedmem) + +dnl ----------------------------- Checks for Any required Functions +dnl Checks for library functions. (N.B. poll is further down) +AC_CHECK_FUNCS([alloca calloc setsid isinf isnan \ + getenv putenv setenv unsetenv \ + writev getifaddrs utime utimes]) +AC_CHECK_FUNCS(setrlimit, [ have_setrlimit="1" ], [ have_setrlimit="0" ]) +AC_CHECK_FUNCS(getrlimit, [ have_getrlimit="1" ], [ have_getrlimit="0" ]) +sendfile="0" +AC_CHECK_LIB(sendfile, sendfilev) +AC_CHECK_FUNCS(sendfile send_file sendfilev, [ sendfile="1" ]) + +dnl THIS MUST COME AFTER THE THREAD TESTS - FreeBSD doesn't always have a +dnl threaded poll() and we don't want to use sendfile on early FreeBSD +dnl systems if we are also using threads. + +AC_ARG_WITH(sendfile, [ --with-sendfile Override decision to use sendfile], + [ if test "$withval" = "yes"; then + sendfile="1" + else + sendfile="0" + fi ], [ + orig_sendfile=$sendfile + case $host in + *freebsd*) + if test $os_version -le "410"; then + if test "$threads" = "1"; then + sendfile="0" + fi + fi + ;; + *alpha*-dec-osf* ) + sendfile="0" + ;; + s390-*-linux-gnu) + # disable sendfile support for 2.2 on S/390 + if test $os_version -lt 240; then + sendfile="0" + fi + ;; + *aix*) + # compiler-independent check for 64-bit build + AC_CHECK_SIZEOF(void*, 4) + if test "x$ac_cv_sizeof_voidp" = "x8"; then + # sendfile not working for 64-bit build + sendfile="0" + fi + ;; + esac + if test "$orig_sendfile" != "$sendfile"; then + echo "sendfile support disabled to avoid system problem" + fi ] ) +AC_SUBST(sendfile) + +AC_CHECK_FUNCS(sigaction, [ have_sigaction="1" ], [ have_sigaction="0" ]) +AC_DECL_SYS_SIGLIST + +AC_CHECK_FUNCS(fork, [ fork="1" ], [ fork="0" ]) +APR_CHECK_INET_ADDR +APR_CHECK_INET_NETWORK +AC_SUBST(apr_inaddr_none) +AC_CHECK_FUNC(_getch) +AC_CHECK_FUNCS(strerror_r, [ strerror_r="1" ], [ strerror_r="0" ]) +if test "$strerror_r" = "1"; then + APR_CHECK_STRERROR_R_RC +fi +AC_CHECK_FUNCS(mmap, [ mmap="1" ], [ mmap="0" ]) +if test "$native_mmap_emul" = "1"; then + mmap="1" +fi +AC_CHECK_FUNCS(memmove, [ have_memmove="1" ], [have_memmove="0" ]) +AC_CHECK_FUNCS([getpass getpassphrase gmtime_r localtime_r mkstemp]) + +AC_SUBST(fork) +AC_SUBST(have_inet_addr) +AC_SUBST(tcp_nodelay_inherited) +AC_SUBST(o_nonblock_inherited) +AC_SUBST(have_inet_network) +AC_SUBST(have_sigaction) +AC_SUBST(have_setrlimit) +AC_SUBST(have_getrlimit) +AC_SUBST(mmap) +AC_SUBST(have_memmove) + +APR_CHECK_SIGWAIT_ONE_ARG +APR_CHECK_DIRENT_INODE +APR_CHECK_DIRENT_TYPE + +dnl ----------------------------- Checks for Any required Headers +AC_HEADER_STDC + +APR_FLAG_HEADERS( + alloca.h \ + ByteOrder.h \ + conio.h \ + crypt.h \ + ctype.h \ + dir.h \ + dirent.h \ + dl.h \ + dlfcn.h \ + errno.h \ + fcntl.h \ + grp.h \ + io.h \ + limits.h \ + mach-o/dyld.h \ + malloc.h \ + memory.h \ + netdb.h \ + osreldate.h \ + poll.h \ + process.h \ + pwd.h \ + semaphore.h \ + signal.h \ + stdarg.h \ + stddef.h \ + stdio.h \ + stdlib.h \ + string.h \ + strings.h \ + sysapi.h \ + sysgtime.h \ + termios.h \ + time.h \ + tpfeq.h \ + tpfio.h \ + unistd.h \ + unix.h \ + arpa/inet.h \ + kernel/OS.h \ + net/errno.h \ + netinet/in.h \ + netinet/sctp.h \ + netinet/sctp_uio.h \ + sys/file.h \ + sys/ioctl.h \ + sys/mman.h \ + sys/poll.h \ + sys/resource.h \ + sys/select.h \ + sys/sem.h \ + sys/sendfile.h \ + sys/signal.h \ + sys/socket.h \ + sys/sockio.h \ + sys/stat.h \ + sys/sysctl.h \ + sys/syslimits.h \ + sys/time.h \ + sys/types.h \ + sys/uio.h \ + sys/un.h \ + sys/wait.h) + +# IRIX 6.5 has a problem in which prevents it from +# being included by itself. Check for manually, +# including another header file first. +AC_CACHE_CHECK([for netinet/tcp.h], [apr_cv_hdr_netinet_tcp_h], +[AC_TRY_CPP( +[#ifdef HAVE_NETINET_IN_H +#include +#endif +#include +], [apr_cv_hdr_netinet_tcp_h=yes], [apr_cv_hdr_netinet_tcp_h=no])]) +if test "$apr_cv_hdr_netinet_tcp_h" = "yes"; then + netinet_tcph=1 + AC_DEFINE([HAVE_NETINET_TCP_H], 1, [Defined if netinet/tcp.h is present]) +else + netinet_tcph=0 +fi + +AC_SUBST(arpa_ineth) +AC_SUBST(conioh) +AC_SUBST(ctypeh) +AC_SUBST(crypth) +AC_SUBST(errnoh) +AC_SUBST(direnth) +AC_SUBST(fcntlh) +AC_SUBST(ioh) +AC_SUBST(limitsh) +AC_SUBST(netdbh) +AC_SUBST(sys_syslimitsh) +AC_SUBST(netinet_inh) +AC_SUBST(netinet_sctph) +AC_SUBST(netinet_sctp_uioh) +AC_SUBST(netinet_tcph) +AC_SUBST(stdargh) +AC_SUBST(stdioh) +AC_SUBST(stdlibh) +AC_SUBST(stringh) +AC_SUBST(stringsh) +AC_SUBST(sys_ioctlh) +AC_SUBST(sys_sendfileh) +AC_SUBST(sys_signalh) +AC_SUBST(sys_socketh) +AC_SUBST(sys_sockioh) +AC_SUBST(sys_typesh) +AC_SUBST(sys_timeh) +AC_SUBST(sys_uioh) +AC_SUBST(sys_unh) +AC_SUBST(timeh) +AC_SUBST(unistdh) +AC_SUBST(signalh) +AC_SUBST(sys_waith) +AC_SUBST(pthreadh) +AC_SUBST(semaphoreh) + +# Checking for h_errno in +if test "$netdbh" = "1"; then + APR_CHECK_H_ERRNO_FLAG + if test "$ac_cv_h_errno_cflags" = "no"; then + AC_MSG_ERROR([can not find h_errno in netdb.h]) + fi +fi + +dnl ----------------------------- Checks for standard typedefs +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_UID_T +AC_CHECK_TYPE(ssize_t, int) +AC_C_INLINE +AC_C_CONST +AC_FUNC_SETPGRP + +APR_CHECK_SOCKLEN_T + +dnl Checks for pointer size +AC_CHECK_SIZEOF(void*, 4) + +if test "x$ac_cv_sizeof_voidp" != "x"; then + voidp_size=$ac_cv_sizeof_voidp +else + AC_ERROR([Cannot determine size of void*]) +fi + +dnl Checks for integer size +AC_CHECK_SIZEOF(char, 1) +AC_CHECK_SIZEOF(int, 4) +AC_CHECK_SIZEOF(long, 4) +AC_CHECK_SIZEOF(short, 2) +AC_CHECK_SIZEOF(long long, 8) + +if test "$ac_cv_sizeof_short" = "2"; then + short_value=short +fi +if test "$ac_cv_sizeof_int" = "4"; then + int_value=int +fi +# Now we need to find what apr_int64_t (sizeof == 8) will be. +# The first match is our preference. +if test "$ac_cv_sizeof_int" = "8"; then + int64_literal='#define APR_INT64_C(val) (val)' + uint64_literal='#define APR_UINT64_C(val) (val##U)' + int64_t_fmt='#define APR_INT64_T_FMT "d"' + uint64_t_fmt='#define APR_UINT64_T_FMT "u"' + uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "x"' + int64_value="int" + long_value=int + int64_strfn="strtoi" +elif test "$ac_cv_sizeof_long" = "8"; then + int64_literal='#define APR_INT64_C(val) (val##L)' + uint64_literal='#define APR_UINT64_C(val) (val##UL)' + int64_t_fmt='#define APR_INT64_T_FMT "ld"' + uint64_t_fmt='#define APR_UINT64_T_FMT "lu"' + uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "lx"' + int64_value="long" + long_value=long + int64_strfn="strtol" +elif test "$ac_cv_sizeof_long_long" = "8"; then + int64_literal='#define APR_INT64_C(val) (val##LL)' + uint64_literal='#define APR_UINT64_C(val) (val##ULL)' + # Linux, Solaris, FreeBSD all support ll with printf. + # BSD 4.4 originated 'q'. Solaris is more popular and + # doesn't support 'q'. Solaris wins. Exceptions can + # go to the OS-dependent section. + int64_t_fmt='#define APR_INT64_T_FMT "lld"' + uint64_t_fmt='#define APR_UINT64_T_FMT "llu"' + uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "llx"' + int64_value="long long" + long_value="long long" + int64_strfn="strtoll" +elif test "$ac_cv_sizeof_longlong" = "8"; then + int64_literal='#define APR_INT64_C(val) (val##LL)' + uint64_literal='#define APR_UINT64_C(val) (val##ULL)' + int64_t_fmt='#define APR_INT64_T_FMT "qd"' + uint64_t_fmt='#define APR_UINT64_T_FMT "qu"' + uint64_t_hex_fmt='#define APR_UINT64_T_HEX_FMT "qx"' + int64_value="__int64" + long_value="__int64" + int64_strfn="strtoll" +else + # int64_literal may be overriden if your compiler thinks you have + # a 64-bit value but APR does not agree. + AC_ERROR([could not detect a 64-bit integer type]) +fi + +# If present, allow the C99 macro INT64_C to override our conversion. +# +# HP-UX's ANSI C compiler provides this without any includes, so we +# will first look for INT64_C without adding stdint.h +AC_CACHE_CHECK([for INT64_C], [apr_cv_define_INT64_C], [ +AC_EGREP_CPP(YES_IS_DEFINED, +[#ifdef INT64_C +YES_IS_DEFINED +#endif], [apr_cv_define_INT64_C=yes], [ + # Now check for INT64_C in stdint.h + AC_EGREP_CPP(YES_IS_DEFINED, [#include +#ifdef INT64_C +YES_IS_DEFINED +#endif], [apr_cv_define_INT64_C=yes], [apr_cv_define_INT64_C=no])])]) + +if test "$apr_cv_define_INT64_C" = "yes"; then + int64_literal='#define APR_INT64_C(val) INT64_C(val)' + uint64_literal='#define APR_UINT64_C(val) UINT64_C(val)' + stdint=1 +else + stdint=0 +fi + +if test "$ac_cv_type_size_t" = "yes"; then + size_t_value="size_t" +else + size_t_value="apr_int32_t" +fi +if test "$ac_cv_type_ssize_t" = "yes"; then + ssize_t_value="ssize_t" +else + ssize_t_value="apr_int32_t" +fi +if test "$ac_cv_socklen_t" = "yes"; then + socklen_t_value="socklen_t" + case $host in + *-hp-hpux*) + if test "$ac_cv_sizeof_long" = "8"; then + # 64-bit HP-UX requires 32-bit socklens in + # kernel, but user-space declarations say + # 64-bit (socklen_t == size_t == long). + # This will result in many compile warnings, + # but we're functionally busted otherwise. + socklen_t_value="int" + fi + ;; + esac +else + socklen_t_value="int" +fi + +APR_CHECK_SIZEOF_EXTENDED([#include ], ssize_t, 8) + +if test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_int"; then + ssize_t_fmt='#define APR_SSIZE_T_FMT "d"' +elif test "$ac_cv_sizeof_ssize_t" = "$ac_cv_sizeof_long"; then + ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' +else + ssize_t_fmt='#error Can not determine the proper size for ssize_t' +fi + +APR_CHECK_SIZEOF_EXTENDED([#include ], size_t, 8) + +if test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_int"; then + size_t_fmt='#define APR_SIZE_T_FMT "d"' +elif test "$ac_cv_sizeof_size_t" = "$ac_cv_sizeof_long"; then + size_t_fmt='#define APR_SIZE_T_FMT "ld"' +else + size_t_fmt='#error Can not determine the proper size for size_t' +fi + +APR_CHECK_SIZEOF_EXTENDED([#include ], off_t, 8) + +if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then + # Enable LFS + aprlfs=1 + AC_CHECK_FUNCS([mmap64 sendfile64 sendfilev64 mkstemp64]) +else + aprlfs=0 +fi + +AC_MSG_CHECKING([which type to use for apr_off_t]) +if test "${ac_cv_sizeof_off_t}${apr_cv_use_lfs64}" = "4yes"; then + # LFS is go! + off_t_fmt='#define APR_OFF_T_FMT APR_INT64_T_FMT' + off_t_value='off64_t' + off_t_strfn='apr_strtoi64' +elif test "${ac_cv_sizeof_off_t}x${ac_cv_sizeof_long}" = "4x4"; then + # Special case: off_t may change size with _FILE_OFFSET_BITS + # on 32-bit systems with LFS support. To avoid compatibility + # issues when other packages do define _FILE_OFFSET_BITS, + # hard-code apr_off_t to long. + off_t_value=long + off_t_fmt='#define APR_OFF_T_FMT "ld"' + off_t_strfn='strtol' +elif test "$ac_cv_type_off_t" = "yes"; then + off_t_value=off_t + # off_t is more commonly a long than an int; prefer that case + # where int and long are the same size. + if test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long"; then + off_t_fmt='#define APR_OFF_T_FMT "ld"' + off_t_strfn='strtol' + elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_int"; then + off_t_fmt='#define APR_OFF_T_FMT "d"' + off_t_strfn='strtoi' + elif test "$ac_cv_sizeof_off_t" = "$ac_cv_sizeof_long_long"; then + off_t_fmt='#define APR_OFF_T_FMT APR_INT64_T_FMT' + off_t_strfn='apr_strtoi64' + else + AC_ERROR([could not determine the size of off_t]) + fi +else + # Fallback on int + off_t_value=apr_int32_t + off_t_fmt=d + off_t_strfn='strtoi' +fi +AC_MSG_RESULT($off_t_value) + +APR_CHECK_SIZEOF_EXTENDED([#include ], pid_t, 8) + +if test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_short"; then + pid_t_fmt='#define APR_PID_T_FMT "hd"' +elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_int"; then + pid_t_fmt='#define APR_PID_T_FMT "d"' +elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long"; then + pid_t_fmt='#define APR_PID_T_FMT "ld"' +elif test "$ac_cv_sizeof_pid_t" = "$ac_cv_sizeof_long_long"; then + pid_t_fmt='#define APR_PID_T_FMT APR_INT64_T_FMT' +else + pid_t_fmt='#error Can not determine the proper size for pid_t' +fi + +# Checks for endianness +AC_C_BIGENDIAN +if test $ac_cv_c_bigendian = yes; then + bigendian=1 +else + bigendian=0 +fi + +# Basically, we have tried to figure out the correct format strings +# for APR types which vary between platforms, but we don't always get +# it right. If you find that we don't get it right for your platform, +# you can override our decision below. +case $host in + s390*linux*) + # uniquely, the 31-bit Linux/s390 uses "unsigned long int" + # for size_t rather than "unsigned int": + size_t_fmt='#define APR_SIZE_T_FMT "lu"' + ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' + ;; + *-os2*) + size_t_fmt='#define APR_SIZE_T_FMT "lu"' + ;; + *-solaris*) + pid_t_fmt='#define APR_PID_T_FMT "ld"' + ;; + *aix4*|*aix5*) + ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' + size_t_fmt='#define APR_SIZE_T_FMT "ld"' + ;; + *beos*) + ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' + size_t_fmt='#define APR_SIZE_T_FMT "ld"' + ;; + *apple-darwin*) + ssize_t_fmt='#define APR_SSIZE_T_FMT "d"' + size_t_fmt='#define APR_SIZE_T_FMT "lu"' + ;; +esac + +AC_SUBST(voidp_size) +AC_SUBST(short_value) +AC_SUBST(int_value) +AC_SUBST(long_value) +AC_SUBST(int64_value) +AC_SUBST(off_t_value) +AC_SUBST(size_t_value) +AC_SUBST(ssize_t_value) +AC_SUBST(socklen_t_value) +AC_SUBST(int64_t_fmt) +AC_SUBST(uint64_t_fmt) +AC_SUBST(uint64_t_hex_fmt) +AC_SUBST(ssize_t_fmt) +AC_SUBST(size_t_fmt) +AC_SUBST(off_t_fmt) +AC_SUBST(pid_t_fmt) +AC_SUBST(int64_literal) +AC_SUBST(uint64_literal) +AC_SUBST(stdint) +AC_SUBST(bigendian) +AC_SUBST(aprlfs) + +dnl ----------------------------- Checking for string functions +AC_CHECK_FUNCS(strnicmp, have_strnicmp="1", have_strnicmp="0") +AC_CHECK_FUNCS(strncasecmp, have_strncasecmp="1", have_strncasecmp="0") +AC_CHECK_FUNCS(stricmp, have_stricmp="1", have_stricmp="0") +AC_CHECK_FUNCS(strcasecmp, have_strcasecmp="1", have_strcasecmp="0") +AC_CHECK_FUNCS(strdup, have_strdup="1", have_strdup="0") +AC_CHECK_FUNCS(strstr, have_strstr="1", have_strstr="0") +AC_CHECK_FUNCS(memchr, have_memchr="1", have_memchr="0") +AC_CHECK_FUNC($int64_strfn, have_int64_strfn="1", have_int64_strfn="0") + +dnl ----------------------------- We have a fallback position +if test "$have_int64_strfn" = "0" && test "$int64_strfn" = "strtoll"; then + int64_strfn="strtoq" + AC_CHECK_FUNC(strtoq, [have_int64_strfn=1], [have_int64_strfn=0]) +fi + +if test "$have_int64_strfn" = "1"; then + AC_DEFINE_UNQUOTED(APR_INT64_STRFN, [$int64_strfn], + [Define as function which can be used for conversion of strings to apr_int64_t]) +fi + +AC_SUBST(have_strnicmp) +AC_SUBST(have_strncasecmp) +AC_SUBST(have_stricmp) +AC_SUBST(have_strcasecmp) +AC_SUBST(have_strdup) +AC_SUBST(have_strstr) +AC_SUBST(have_memchr) + +if test "$off_t_strfn" = "apr_strtoi64" && test "$have_int64_strfn" = "1"; then + off_t_strfn=$int64_strfn +fi +AC_DEFINE_UNQUOTED(APR_OFF_T_STRFN, [$off_t_strfn], + [Define as function used for conversion of strings to apr_off_t]) + +dnl ----------------------------- Checking for DSO support +echo "${nl}Checking for DSO..." +AC_ARG_ENABLE(dso, + [ --disable-dso Disable DSO support ], + [if test "x$enableval" = "xyes"; then + dsotype=any + else + dsotype=$enableval + fi + ], [dsotype=any]) + +if test "$dsotype" = "any"; then + # Darwin: + AC_CHECK_FUNC(NSLinkModule, [dsotype=dyld]) + if test "$dsotype" = "any"; then + # Original HP-UX: + AC_CHECK_LIB(dld, shl_load, [dsotype=shl; APR_ADDTO(LIBS,-ldld)]) + fi + # Normal POSIX: + if test "$dsotype" = "any"; then + AC_CHECK_FUNC(dlopen, [dsotype=dlfcn]) + fi + if test "$dsotype" = "any"; then + AC_CHECK_LIB(dl, dlopen, [dsotype=dlfcn; APR_ADDTO(LIBS,-ldl)]) + fi + if test "$dsotype" = "dlfcn"; then + # ReliantUnix has dlopen() in libc but dlsym() in libdl :( + AC_CHECK_FUNC(dlsym, [], + [AC_CHECK_LIB(dl, dlsym, + [APR_ADDTO(LIBS, -ldl)], + [dsotype=any + echo "Weird: dlopen() was found but dlsym() was not found!"])]) + fi + if test "$dsotype" = "any"; then + # BeOS: + AC_CHECK_LIB(root, load_image, [dsotype=other]) + fi + # Everything else: + if test "$dsotype" = "any"; then + case $host in + *os390|*-os2*|*os400|*-aix*) dsotype=other ;; + esac + fi +fi + +if test "$dsotype" = "any"; then + AC_MSG_ERROR([Could not detect suitable DSO implementation]) +elif test "$dsotype" = "no"; then + aprdso="0" +else + case "$dsotype" in + dlfcn) AC_DEFINE(DSO_USE_DLFCN, 1, [Define if DSO support uses dlfcn.h]);; + shl) AC_DEFINE(DSO_USE_SHL, 1, [Define if DSO support uses shl_load]);; + dyld) AC_DEFINE(DSO_USE_DYLD, 1, [Define if DSO support uses dyld.h]);; + other) ;; # Use whatever is in dso/OSDIR + *) AC_MSG_ERROR([Unknown DSO implementation "$dsotype"]);; + esac + aprdso="1" + apr_modules="$apr_modules dso" +fi + +AC_SUBST(aprdso) + +dnl ----------------------------- Checking for Processes +echo "${nl}Checking for Processes..." + +AC_CHECK_FUNCS(waitpid) + +AC_ARG_ENABLE(other-child, + [ --enable-other-child Enable reliable child processes ], + [ if test "$enableval" = "yes"; then + oc="1" + else + oc="0" + fi ], + [ oc=1 ] ) + +AC_SUBST(oc) + +AC_MSG_CHECKING(for Variable Length Arrays) +APR_TRY_COMPILE_NO_WARNING([], +[ + int foo[argc]; + foo[0] = 0; +], vla_msg=yes, vla_msg=no ) +AC_MSG_RESULT([$vla_msg]) +if test "$vla_msg" = "yes"; then + AC_DEFINE(HAVE_VLA, 1, [Define if C compiler supports VLA]) +fi + +AC_CACHE_CHECK(struct rlimit,ac_cv_struct_rlimit,[ +AC_TRY_RUN([ +#include +#include +#include +main() +{ + struct rlimit limit; + limit.rlim_cur = 0; + limit.rlim_max = 0; + exit(0); +}], [ + ac_cv_struct_rlimit=yes ], [ + ac_cv_struct_rlimit=no ], [ + ac_cv_struct_rlimit=no ] ) ] ) +struct_rlimit=0 +test "x$ac_cv_struct_rlimit" = xyes && struct_rlimit=1 +AC_SUBST(struct_rlimit) + +dnl ----------------------------- Checking for Locking Characteristics +echo "${nl}Checking for Locking..." + +AC_CHECK_FUNCS(semget semctl flock) +AC_CHECK_HEADERS(semaphore.h OS.h) +AC_CHECK_FUNCS(sem_close sem_unlink sem_post sem_wait create_sem) + +# Some systems return ENOSYS from sem_open. +AC_CACHE_CHECK(for working sem_open,ac_cv_func_sem_open,[ +AC_TRY_RUN([ +#include +#include +#include +#include +main() +{ + sem_t *psem; + const char *sem_name = "/apr_autoconf"; + + psem = sem_open(sem_name, O_CREAT, 0644, 1); + if (psem == (sem_t *)SEM_FAILED) { + exit(1); + } + sem_close(psem); + sem_unlink(sem_name); + exit(0); +}], [ac_cv_func_sem_open=yes], [ac_cv_func_sem_open=no], +[ac_cv_func_sem_open=no])]) + +# It's stupid, but not all platforms have union semun, even those that need it. +AC_MSG_CHECKING(for union semun in sys/sem.h) +AC_TRY_COMPILE([ +#include +#include +#include +],[ +union semun arg; +semctl(0, 0, 0, arg); +], [have_union_semun="1" union_semun=yes ] +msg=yes, [ +have_union_semun="0" +msg=no ] ) +AC_MSG_RESULT([$msg]) +AC_SUBST(have_union_semun) + +dnl Checks for libraries. +APR_CHECK_DEFINE(LOCK_EX, sys/file.h) +APR_CHECK_DEFINE(F_SETLK, fcntl.h) +APR_CHECK_DEFINE(SEM_UNDO, sys/sem.h) + +# We are assuming that if the platform doesn't have POLLIN, it doesn't have +# any POLL definitions. +APR_CHECK_DEFINE_FILES(POLLIN, poll.h sys/poll.h) + +if test "$threads" = "1"; then + APR_CHECK_DEFINE(PTHREAD_PROCESS_SHARED, pthread.h) + AC_CHECK_FUNCS(pthread_mutexattr_setpshared) + # Some systems have setpshared and define PROCESS_SHARED, but don't + # really support PROCESS_SHARED locks. So, we must validate that we + # can go through the steps without receiving some sort of system error. + # Linux and older versions of AIX have this problem. + APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED func:pthread_mutexattr_setpshared, [ + AC_CACHE_CHECK([for working PROCESS_SHARED locks], apr_cv_process_shared_works, [ + AC_TRY_RUN([ +#include +#include + int main() + { + pthread_mutex_t mutex; + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr)) + exit(1); + if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) + exit(2); + if (pthread_mutex_init(&mutex, &attr)) + exit(3); + if (pthread_mutexattr_destroy(&attr)) + exit(4); + if (pthread_mutex_destroy(&mutex)) + exit(5); + exit(0); + }], [apr_cv_process_shared_works=yes], [apr_cv_process_shared_works=no])]) + # Override detection of pthread_mutexattr_setpshared + ac_cv_func_pthread_mutexattr_setpshared=$apr_cv_process_shared_works]) + + if test "$ac_cv_func_pthread_mutexattr_setpshared" = "yes"; then + AC_CHECK_FUNCS(pthread_mutexattr_setrobust_np) + if test "$ac_cv_func_pthread_mutexattr_setrobust_np" = "no"; then + AC_CACHE_CHECK([for pthread_mutexattr_setrobust_np with _POSIX_THREAD_PRIO_INHERIT], + [apr_cv_setrobust_with_prio_inherit], [ + AC_TRY_COMPILE([#define _POSIX_THREAD_PRIO_INHERIT +#include +#include ],[ + int main() + { + pthread_mutexattr_t attr; + pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP); + return 0; + }], [apr_cv_setrobust_with_prio_inherit=yes], [apr_cv_setrobust_with_prio_inherit=no])]) + if test "$apr_cv_setrobust_with_prio_inherit" = "yes"; then + ac_cv_func_pthread_mutexattr_setrobust_np=yes + APR_ADDTO(CPPFLAGS, -D_POSIX_THREAD_PRIO_INHERIT) + fi + fi + fi +fi + +# See which lock mechanisms we can support on this system. +APR_IFALLYES(header:semaphore.h func:sem_open func:sem_close dnl + func:sem_unlink func:sem_post func:sem_wait, + hasposixser="1", hasposixser="0") +APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, hassysvser="1", + hassysvser="0") +APR_IFALLYES(func:flock define:LOCK_EX, hasflockser="1", hasflockser="0") +APR_IFALLYES(header:fcntl.h define:F_SETLK, hasfcntlser="1", hasfcntlser="0") +# note: the current APR use of shared mutex requires /dev/zero +APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl + func:pthread_mutexattr_setpshared dnl + file:/dev/zero, + hasprocpthreadser="1", hasprocpthreadser="0") +APR_IFALLYES(header:OS.h func:create_sem, hasbeossem="1", hasbeossem="0") + +# See which lock mechanism we'll select by default on this system. +# The last APR_DECIDE to execute sets the default. +# At this stage, we match the ordering in Apache 1.3 +# which is (highest to lowest): sysvsem -> fcntl -> flock. +# POSIX semaphores and cross-process pthread mutexes are not +# used by default since they have less desirable behaviour when +# e.g. a process holding the mutex segfaults. +# The BEOSSEM decision doesn't require any substitutions but is +# included here to prevent the fcntl() branch being selected +# from the decision making. +APR_BEGIN_DECISION([apr_lock implementation method]) +APR_IFALLYES(func:flock define:LOCK_EX, + APR_DECIDE(USE_FLOCK_SERIALIZE, [4.2BSD-style flock()])) +APR_IFALLYES(header:fcntl.h define:F_SETLK, + APR_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()])) +APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, + APR_DECIDE(USE_SYSVSEM_SERIALIZE, [SysV IPC semget()])) +APR_IFALLYES(header:OS.h func:create_sem, + APR_DECIDE(USE_BEOSSEM, [BeOS Semaphores])) +if test "x$apr_lock_method" != "x"; then + APR_DECISION_FORCE($apr_lock_method) +fi +APR_END_DECISION +AC_DEFINE_UNQUOTED($ac_decision) + +flockser="0" +sysvser="0" +posixser="0" +procpthreadser="0" +fcntlser="0" +case $ac_decision in + USE_FLOCK_SERIALIZE ) + flockser="1" + ;; + USE_FCNTL_SERIALIZE ) + fcntlser="1" + ;; + USE_SYSVSEM_SERIALIZE ) + sysvser="1" + ;; + USE_POSIXSEM_SERIALIZE ) + posixser="1" + ;; + USE_PROC_PTHREAD_SERIALIZE ) + procpthreadser="1" + ;; + USE_BEOSSEM ) + beossem="1" + ;; +esac + +AC_SUBST(hasflockser) +AC_SUBST(hassysvser) +AC_SUBST(hasposixser) +AC_SUBST(hasfcntlser) +AC_SUBST(hasprocpthreadser) +AC_SUBST(flockser) +AC_SUBST(sysvser) +AC_SUBST(posixser) +AC_SUBST(fcntlser) +AC_SUBST(procpthreadser) +AC_SUBST(pthreadser) + +AC_MSG_CHECKING(if all interprocess locks affect threads) +if test "x$apr_process_lock_is_global" = "xyes"; then + proclockglobal="1" + AC_MSG_RESULT(yes) +else + proclockglobal="0" + AC_MSG_RESULT(no) +fi + +AC_SUBST(proclockglobal) + +AC_MSG_CHECKING(if POSIX sems affect threads in the same process) +if test "x$apr_posixsem_is_global" = "xyes"; then + AC_DEFINE(POSIXSEM_IS_GLOBAL, 1, + [Define if POSIX semaphores affect threads within the process]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING(if SysV sems affect threads in the same process) +if test "x$apr_sysvsem_is_global" = "xyes"; then + AC_DEFINE(SYSVSEM_IS_GLOBAL, 1, + [Define if SysV semaphores affect threads within the process]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING(if fcntl locks affect threads in the same process) +if test "x$apr_fcntl_is_global" = "xyes"; then + AC_DEFINE(FCNTL_IS_GLOBAL, 1, + [Define if fcntl locks affect threads within the process]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_MSG_CHECKING(if flock locks affect threads in the same process) +if test "x$apr_flock_is_global" = "xyes"; then + AC_DEFINE(FLOCK_IS_GLOBAL, 1, + [Define if flock locks affect threads within the process]) + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +dnl ----------------------------- Checking for /dev/random +AC_MSG_CHECKING(for entropy source) + +AC_ARG_WITH(egd, + [ --with-egd[[=DIR]] use EGD-compatible socket], + [ AC_DEFINE(HAVE_EGD, 1, [Define if EGD is supported]) + if test "$withval" = "yes"; then + AC_DEFINE_UNQUOTED(EGD_DEFAULT_SOCKET, ["/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy"], + [Define to list of paths to EGD sockets]) + else + AC_DEFINE_UNQUOTED(EGD_DEFAULT_SOCKET, ["$withval"]) + fi + AC_MSG_RESULT(EGD-compatible daemon) + rand="1" + ]) + +if test "$rand" != "1"; then + AC_ARG_WITH(devrandom, + [ --with-devrandom[[=DEV]] use /dev/random or compatible [[searches by default]]], + [ apr_devrandom="$withval" ], [ apr_devrandom="yes" ]) + + if test "$apr_devrandom" = "yes"; then + # /dev/random on OpenBSD doesn't provide random data, so + # prefer /dev/arandom, which does; see random(4). + for f in /dev/arandom /dev/random /dev/urandom; do + if test -r $f; then + apr_devrandom=$f + rand=1 + break + fi + done + elif test "$apr_devrandom" != "no"; then + if test -r "$apr_devrandom"; then + rand="1" + else + AC_ERROR([$apr_devrandom not found or unreadable.]) + fi + fi + + if test "$rand" = "1"; then + AC_DEFINE_UNQUOTED(DEV_RANDOM, ["$apr_devrandom"], [Define to path of random device]) + AC_MSG_RESULT([$apr_devrandom]) + fi +fi + +if test "$rand" != "1"; then + case $host in + # we have built in support for OS/2 + *-os2*) + AC_MSG_RESULT([Using OS/2 builtin random]) + rand="1" + ;; + *) + if test "$rand" != "1"; then + if test "$ac_cv_lib_truerand_main" = "yes"; then + AC_DEFINE(HAVE_TRUERAND, 1, [Define if truerand is supported]) + AC_MSG_RESULT(truerand) + rand="1" + else + AC_MSG_RESULT(not found) + rand="0" + fi + fi + ;; + esac +fi + +AC_SUBST(rand) + +dnl ----------------------------- Checking for UUID Support +echo "${nl}Checking for OS UUID Support..." +osuuid="0" + +AC_CHECK_HEADERS(uuid/uuid.h uuid.h) + +# Check for uuid_generate in libc or libuuid +AC_SEARCH_LIBS(uuid_generate, uuid) + +AC_CHECK_FUNCS([uuid_generate uuid_create], [osuuid=1; break]) + +AC_SUBST(osuuid) + + +dnl ----------------------------- Checking for Time Support +echo "${nl}Checking for Time Support..." + +AC_CHECK_MEMBERS([struct tm.tm_gmtoff, struct tm.__tm_gmtoff],,,[ +#include +#include ]) + +dnl ----------------------------- Checking for Networking Support +echo "${nl}Checking for Networking support..." +AC_MSG_CHECKING(for in_addr in netinet/in.h) +AC_TRY_COMPILE([ +#include +#include +],[ +struct in_addr arg; +arg.s_addr = htonl(INADDR_ANY); +], [ have_in_addr="1" +msg=yes ] , [ have_in_addr="0" +msg=no ]) +AC_MSG_RESULT([$msg]) + +AC_MSG_CHECKING([if fd == socket on this platform]) +if test "x$file_as_socket" != "x0" ; then + file_as_socket="1"; + echo "yes" +else + echo "no" +fi + +AC_SUBST(have_in_addr) +AC_SUBST(file_as_socket) + +if test "$ac_cv_func_poll $file_as_socket" = "yes 1"; then + AC_DEFINE(WAITIO_USES_POLL, 1, + [Define if apr_wait_for_io_or_timeout() uses poll(2)]) +fi + +# Check the types only if we have gethostbyname_r +if test "$ac_cv_func_gethostbyname_r" = "yes"; then + APR_CHECK_GETHOSTBYNAME_R_STYLE +fi + +APR_CHECK_TCP_NODELAY_INHERITED +APR_CHECK_O_NONBLOCK_INHERITED + +# Look for a way of corking TCP... +APR_CHECK_DEFINE(TCP_CORK, netinet/tcp.h) +APR_CHECK_DEFINE(TCP_NOPUSH, netinet/tcp.h) +apr_tcp_nopush_flag="0" +have_corkable_tcp="0" +if test "x$ac_cv_define_TCP_CORK" = "xyes"; then + apr_tcp_nopush_flag="TCP_CORK" + have_corkable_tcp="1" +else + case $host in + *linux*) + AC_EGREP_CPP(yes,[ +#include +#ifdef TCP_CORK +yes +#endif + ],[ + apr_tcp_nopush_flag="3" + have_corkable_tcp="1" + ]) + ;; + *) + ;; + esac +fi +if test "x$ac_cv_define_TCP_NOPUSH" = "xyes"; then + apr_tcp_nopush_flag="TCP_NOPUSH" + have_corkable_tcp="1" +fi + +APR_CHECK_DEFINE(SO_ACCEPTFILTER, sys/socket.h) +if test "x$ac_cv_define_SO_ACCEPTFILTER" = "xyes"; then + acceptfilter="1" +else + acceptfilter="0" +fi + +APR_CHECK_SCTP +APR_CHECK_MCAST + +AC_SUBST(apr_tcp_nopush_flag) +AC_SUBST(have_corkable_tcp) +AC_SUBST(acceptfilter) +AC_SUBST(have_sctp) + +AC_CHECK_FUNCS(set_h_errno) + +echo "${nl}Checking for IPv6 Networking support..." +dnl Start of checking for IPv6 support... + +AC_ARG_ENABLE(ipv6, + [ --disable-ipv6 Disable IPv6 support in APR.], + [ if test "$enableval" = "no"; then + user_disabled_ipv6=1 + fi ], + [ user_disabled_ipv6=0 ] ) + +case $host in + *) + broken_ipv6=0 +esac + +AC_SEARCH_LIBS(getaddrinfo, socket inet6) +AC_SEARCH_LIBS(gai_strerror, socket inet6) +AC_SEARCH_LIBS(getnameinfo, socket inet6) +AC_CHECK_FUNCS(gai_strerror) +APR_CHECK_WORKING_GETADDRINFO +APR_CHECK_NEGATIVE_EAI +APR_CHECK_WORKING_GETNAMEINFO +APR_CHECK_SOCKADDR_IN6 +APR_CHECK_SOCKADDR_STORAGE + +have_ipv6="0" +if test "$user_disabled_ipv6" = 1; then + ipv6_result="no -- disabled by user" +else + if test "x$broken_ipv6" = "x0"; then + if test "x$have_sockaddr_in6" = "x1"; then + if test "x$ac_cv_working_getaddrinfo" = "xyes"; then + if test "x$ac_cv_working_getnameinfo" = "xyes"; then + APR_CHECK_GETADDRINFO_ADDRCONFIG + have_ipv6="1" + ipv6_result="yes" + else + ipv6_result="no -- no getnameinfo" + fi + else + ipv6_result="no -- no working getaddrinfo" + fi + else + ipv6_result="no -- no sockaddr_in6" + fi + else + ipv6_result="no -- the platform has known problems supporting IPv6" + fi +fi + +AC_MSG_CHECKING(if APR supports IPv6) +AC_MSG_RESULT($ipv6_result) + +AC_SUBST(have_ipv6) + +# hstrerror is only needed if IPv6 is not enabled, +# so getaddrinfo/gai_strerror are not used. +if test $have_ipv6 = 0; then + AC_SEARCH_LIBS(hstrerror, resolv, + [AC_DEFINE(HAVE_HSTRERROR, 1, [Define if hstrerror is present])]) +fi + +dnl Check for langinfo support + +AC_CHECK_HEADERS(langinfo.h) +AC_CHECK_FUNCS(nl_langinfo) + +dnl ----------------------------- Finalize the variables + +echo "${nl}Restore user-defined environment settings..." + +APR_RESTORE_THE_ENVIRONMENT(CPPFLAGS, EXTRA_) +APR_RESTORE_THE_ENVIRONMENT(CFLAGS, EXTRA_) +APR_RESTORE_THE_ENVIRONMENT(LDFLAGS, EXTRA_) +APR_RESTORE_THE_ENVIRONMENT(LIBS, EXTRA_) +APR_RESTORE_THE_ENVIRONMENT(INCLUDES, EXTRA_) +AC_SUBST(NOTEST_CPPFLAGS) +AC_SUBST(NOTEST_CFLAGS) +AC_SUBST(NOTEST_LDFLAGS) +AC_SUBST(NOTEST_LIBS) +AC_SUBST(NOTEST_INCLUDES) + +dnl ----------------------------- Construct the files + +AC_SUBST(LDLIBS) +AC_SUBST(INCLUDES) +AC_SUBST(AR) +AC_SUBST(RM) +AC_SUBST(OSDIR) +AC_SUBST(DEFAULT_OSDIR) +AC_SUBST(EXEEXT) +AC_SUBST(LIBTOOL_LIBS) + +# +# BSD/OS (BSDi) needs to use a different include syntax in the Makefiles +# +case $host in +*bsdi*) + # Check whether they've installed GNU make + if make --version > /dev/null 2>&1; then + INCLUDE_RULES="include $apr_buildout/apr_rules.mk" + INCLUDE_OUTPUTS="include $apr_srcdir/build-outputs.mk" + else + # BSDi make + INCLUDE_RULES=".include \"$apr_buildout/apr_rules.mk\"" + INCLUDE_OUTPUTS=".include \"$apr_srcdir/build-outputs.mk\"" + fi + ;; +*) + INCLUDE_RULES="include $apr_buildout/apr_rules.mk" + INCLUDE_OUTPUTS="include $apr_srcdir/build-outputs.mk" + ;; +esac +AC_SUBST(INCLUDE_RULES) +AC_SUBST(INCLUDE_OUTPUTS) + +AC_CONFIG_FILES([Makefile + include/apr.h + build/apr_rules.mk + build/pkg/pkginfo + apr-$APR_MAJOR_VERSION-config:apr-config.in + apr.pc]) + +if test -d $srcdir/test; then + AC_CONFIG_FILES([test/Makefile test/internal/Makefile]) +fi + +dir=include/arch/unix +test -d $dir || $MKDIR $dir + +AC_CONFIG_COMMANDS([default], [ +# Commands run at the end of config.status: +for i in $APR_SAVE_HEADERS; do + if cmp -s $i $i.save 2>/dev/null; then + mv $i.save $i + AC_MSG_NOTICE([$i is unchanged]) + fi + rm -f $i.save +done +chmod +x apr-$APR_MAJOR_VERSION-config +],[ +dnl This section is expanded by configure UNQUOTED so variable +dnl references must be backslash-escaped as necessary. + +# Commands run at the beginning of config.status: +APR_SAVE_HEADERS="include/apr.h include/arch/unix/apr_private.h" +APR_MAJOR_VERSION=$APR_MAJOR_VERSION + +for apri in \${APR_SAVE_HEADERS}; do + test -r \${apri} && mv \${apri} \${apri}.save +done +]) + +AC_OUTPUT diff --git a/srclib/apr/docs/APRDesign.html b/srclib/apr/docs/APRDesign.html new file mode 100644 index 0000000000..7d1caeb8d4 --- /dev/null +++ b/srclib/apr/docs/APRDesign.html @@ -0,0 +1,399 @@ + +APR Design Document + +

    Design of APR

    + +

    The Apache Portable Run-time libraries have been designed to provide a common +interface to low level routines across any platform. The original goal of APR +was to combine all code in Apache to one common code base. This is not the +correct approach however, so the goal of APR has changed. There are places +where common code is not a good thing. For example, how to map requests +to either threads or processes should be platform specific. APR's place +is now to combine any code that can be safely combined without sacrificing +performance.

    + +

    To this end we have created a set of operations that are required for cross +platform development. There may be other types that are desired and those +will be implemented in the future.

    + +

    This document will discuss the structure of APR, and how best to contribute +code to the effort.

    + +

    APR On Windows and Netware

    + +

    APR on Windows and Netware is different from APR on all other systems, +because those platforms don't use autoconf. On Unix, apr_private.h (private to +APR) and apr.h (public, used by applications that use APR) are generated by +autoconf from acconfig.h and apr.h.in respectively. On Windows (and Netware), +apr_private.h and apr.h are created from apr_private.hw (apr_private.hwn) +and apr.hw (apr.hwn) respectively.

    + +

    + If you add code to acconfig.h or tests to configure.in or aclocal.m4, + please give some thought to whether or not Windows and Netware need + these additions as well. A general rule of thumb, is that if it is + a feature macro, such as APR_HAS_THREADS, Windows and Netware need it. + In other words, if the definition is going to be used in a public APR + header file, such as apr_general.h, Windows needs it. + + The only time it is safe to add a macro or test without also adding + the macro to apr*.h[n]w, is if the macro tells APR how to build. For + example, a test for a header file does not need to be added to Windows. +

    + +

    APR Features

    + +

    One of the goals of APR is to provide a common set of features across all +platforms. This is an admirable goal, it is also not realistic. We cannot +expect to be able to implement ALL features on ALL platforms. So we are +going to do the next best thing. Provide a common interface to ALL APR +features on MOST platforms.

    + +

    APR developers should create FEATURE MACROS for any feature that is not +available on ALL platforms. This should be a simple definition which has +the form:

    + +APR_HAS_FEATURE + +

    This macro should evaluate to true if APR has this feature on this platform. +For example, Linux and Windows have mmap'ed files, and APR is providing an +interface for mmapp'ing a file. On both Linux and Windows, APR_HAS_MMAP +should evaluate to one, and the ap_mmap_* functions should map files into +memory and return the appropriate status codes.

    + +

    If your OS of choice does not have mmap'ed files, APR_HAS_MMAP should +evaluate to zero, and all ap_mmap_* functions should not be defined. The +second step is a precaution that will allow us to break at compile time if a +programmer tries to use unsupported functions.

    + +

    APR types

    + +

    The base types in APR

    + +
      +
    • dso
      + Shared library routines +
    • mmap
      + Memory-mapped files +
    • poll
      + Polling I/O +
    • time
      + Time +
    • user
      + Users and groups +
    • locks
      + Process and thread locks (critical sections) +
    • shmem
      + Shared memory +
    • file_io
      + File I/O, including pipes +
    • atomic
      + Atomic integer operations +
    • strings
      + String handling routines +
    • memory
      + Pool-based memory allocation +
    • passwd
      + Reading passwords from the terminal +
    • tables
      + Tables and hashes +
    • network_io
      + Network I/O +
    • threadproc
      + Threads and processes +
    • misc
      + Any APR type which doesn't have any other place to belong. This + should be used sparingly. +
    • support
      + Functions meant to be used across multiple APR types. This area + is for internal functions only. If a function is exposed, it should + not be put here. +
    + +

    Directory Structure

    + +

    Each type has a base directory. Inside this base directory, are +subdirectories, which contain the actual code. These subdirectories are named +after the platforms the are compiled on. Unix is also used as a common +directory. If the code you are writing is POSIX based, you should look at the +code in the unix directory. A good rule of thumb, is that if more than half +your code needs to be ifdef'ed out, and the structures required for your code +are substantively different from the POSIX code, you should create a new +directory.

    + +

    Currently, the APR code is written for Unix, BeOS, Windows, and OS/2. An +example of the directory structure is the file I/O directory:

    + +
    +apr
    +  |
    +   ->  file_io
    +          |
    +           -> unix            The Unix and common base code
    +          |
    +           -> win32           The Windows code
    +          | 
    +           -> os2             The OS/2 code
    +
    + +

    Obviously, BeOS does not have a directory. This is because BeOS is currently +using the Unix directory for it's file_io.

    + +

    There are a few special top level directories. These are test and include. +Test is a directory which stores all test programs. It is expected +that if a new type is developed, there will also be a new test program, to +help people port this new type to different platforms. A small document +describing how to create new tests that integrate with the test suite can be +found in the test/ directory. Include is a directory which stores all +required APR header files for external use.

    + +

    Creating an APR Type

    + +

    The current design of APR requires that most APR types be incomplete. +It is not possible to write flexible portable code if programs can access +the internals of APR types. This is because different platforms are +likely to define different native types. There are only two execptions to +this rule:

    + +
      +
    • The first exception to this rule is if the type can only reasonably be +implemented one way. For example, time is a complete type because there +is only one reasonable time implementation. + +
    • The second exception to the incomplete type rule can be found in +apr_portable.h. This file defines the native types for each platform. +Using these types, it is possible to extract native types for any APR type.

      +
    + +

    For this reason, each platform defines a structure in their own directories. +Those structures are then typedef'ed in an external header file. For example +in file_io/unix/fileio.h:

    + +
    +    struct ap_file_t {
    +        apr_pool_t *cntxt;
    +        int filedes;
    +        FILE *filehand;
    +        ...
    +    }
    +
    + +

    In include/apr_file_io.h:

    + + typedef struct ap_file_t ap_file_t; + + +

    This will cause a compiler error if somebody tries to access the filedes +field in this structure. Windows does not have a filedes field, so obviously, +it is important that programs not be able to access these.

    + +

    You may notice the apr_pool_t field. Most APR types have this field. This +type is used to allocate memory within APR. Because every APR type has a pool, +any APR function can allocate memory if it needs to. This is very important +and it is one of the reasons that APR works. If you create a new type, you +must add a pool to it. If you do not, then all functions that operate on that +type will need a pool argument.

    + +

    New Function

    + +

    When creating a new function, please try to adhere to these rules.

    + +
      +
    • Result arguments should be the first arguments. +
    • If a function needs a pool, it should be the last argument. +
    • These rules are flexible, especially if it makes the code easier + to understand because it mimics a standard function. +
    + +

    Documentation

    + +

    Whenever a new function is added to APR, it MUST be documented. New +functions will not be committed unless there are docs to go along with them. +The documentation should be a comment block above the function in the header +file.

    + +

    The format for the comment block is:

    + +
    +    /**
    +     * Brief description of the function
    +     * @param parma_1_name explanation
    +     * @param parma_2_name explanation
    +     * @param parma_n_name explanation
    +     * @tip Any extra information people should know.
    +     * @deffunc function prototype if required
    +     */ 
    +
    + +

    For an actual example, look at any file in the include directory. The +reason the docs are in the header files is to ensure that the docs always +reflect the current code. If you change paramters or return values for a +function, please be sure to update the documentation.

    + +

    APR Error reporting

    + +

    Most APR functions should return an ap_status_t type. The only time an +APR function does not return an ap_status_t is if it absolutely CAN NOT +fail. Examples of this would be filling out an array when you know you are +not beyond the array's range. If it cannot fail on your platform, but it +could conceivably fail on another platform, it should return an ap_status_t. +Unless you are sure, return an ap_status_t.

    + + + This includes functions that return TRUE/FALSE values. How that + is handled is discussed below + + +

    All platforms return errno values unchanged. Each platform can also have +one system error type, which can be returned after an offset is added. +There are five types of error values in APR, each with it's own offset.

    + + +
    +    Name			Purpose
    +0) 			This is 0 for all platforms and isn't really defined
    + 			anywhere, but it is the offset for errno values.
    +			(This has no name because it isn't actually defined, 
    +                        but for completeness we are discussing it here).
    +
    +1) APR_OS_START_ERROR	This is platform dependent, and is the offset at which
    +			APR errors start to be defined.  Error values are 
    +			defined as anything which caused the APR function to 
    +			fail.  APR errors in this range should be named 
    +			APR_E* (i.e. APR_ENOSOCKET)
    +
    +2) APR_OS_START_STATUS	This is platform dependent, and is the offset at which
    +			APR status values start.  Status values do not indicate
    +			success or failure, and should be returned if 
    +			APR_SUCCESS does not make sense.  APR status codes in 
    +			this range should be name APR_* (i.e. APR_DETACH)
    +
    +4) APR_OS_START_USEERR	This is platform dependent, and is the offset at which
    +			APR apps can begin to add their own error codes.
    +
    +3) APR_OS_START_SYSERR	This is platform dependent, and is the offset at which
    +			system error values begin.
    +
    + +The difference in naming between APR_OS_START_ERROR and +APR_OS_START_STATUS mentioned above allows programmers to easily determine if +the error code indicates an error condition or a status codition. + +

    If your function has multiple return codes that all indicate success, but +with different results, or if your function can only return PASS/FAIL, you +should still return an apr_status_t. In the first case, define one +APR status code for each return value, an example of this is +apr_proc_wait, which can only return APR_CHILDDONE, +APR_CHILDNOTDONE, or an error code. In the second case, please return +APR_SUCCESS for PASS, and define a new APR status code for failure, an +example of this is apr_compare_users, which can only return +APR_SUCCESS, APR_EMISMATCH, or an error code.

    + +

    All of these definitions can be found in apr_errno.h for all platforms. When +an error occurs in an APR function, the function must return an error code. +If the error occurred in a system call and that system call uses errno to +report an error, then the code is returned unchanged. For example:

    + +
    +    if (open(fname, oflags, 0777) < 0)
    +        return errno;
    +
    + +

    The next place an error can occur is a system call that uses some error value +other than the primary error value on a platform. This can also be handled +by APR applications. For example:

    + +
    +    if (CreateFile(fname, oflags, sharemod, NULL, 
    +                   createflags, attributes, 0) == INVALID_HANDLE_VALUE
    +        return (GetLAstError() + APR_OS_START_SYSERR);
    +
    + +

    These two examples implement the same function for two different platforms. +Obviously even if the underlying problem is the same on both platforms, this +will result in two different error codes being returned. This is OKAY, and +is correct for APR. APR relies on the fact that most of the time an error +occurs, the program logs the error and continues, it does not try to +programatically solve the problem. This does not mean we have not provided +support for programmatically solving the problem, it just isn't the default +case. We'll get to how this problem is solved in a little while.

    + +

    If the error occurs in an APR function but it is not due to a system call, +but it is actually an APR error or just a status code from APR, then the +appropriate code should be returned. These codes are defined in apr_errno.h +and should be self explanatory.

    + +

    No APR code should ever return a code between APR_OS_START_USEERR and +APR_OS_START_SYSERR, those codes are reserved for APR applications.

    + +

    To programmatically correct an error in a running application, the error +codes need to be consistent across platforms. This should make sense. APR +has provided macros to test for status code equivalency. For example, to +determine if the code that you received from the APR function means EOF, you +would use the macro APR_STATUS_IS_EOF().

    + +

    Why did APR take this approach? There are two ways to deal with error +codes portably.

    + +
      +
    1. Return the same error code across all platforms. +
    2. Return platform specific error codes and convert them when necessary. +
    + +

    The problem with option number one is that it takes time to convert error +codes to a common code, and most of the time programs want to just output +an error string. If we convert all errors to a common subset, we have four +steps to output an error string:

    + +

    The seocnd problem with option 1, is that it is a lossy conversion. For +example, Windows and OS/2 have a couple hundred error codes, but POSIX errno +only defines about 50 errno values. This means that if we convert to a +canonical error value immediately, there is no way for the programmer to +get the actual system error.

    + +
    +    make syscall that fails
    +        convert to common error code                 step 1
    +        return common error code
    +            check for success
    +            call error output function               step 2
    +                convert back to system error         step 3
    +                output error string                  step 4
    +
    + +

    By keeping the errors platform specific, we can output error strings in two +steps.

    + +
    +    make syscall that fails
    +        return error code
    +            check for success
    +            call error output function               step 1
    +                output error string                  step 2
    +
    + +

    Less often, programs change their execution based on what error was returned. +This is no more expensive using option 2 than it is using option 1, but we +put the onus of converting the error code on the programmer themselves. +For example, using option 1:

    + +
    +    make syscall that fails
    +        convert to common error code
    +        return common error code
    +            decide execution based on common error code
    +
    + +

    Using option 2:

    + +
    +    make syscall that fails
    +        return error code
    +            convert to common error code (using ap_canonical_error)
    +            decide execution based on common error code
    +
    + +

    Finally, there is one more operation on error codes. You can get a string +that explains in human readable form what has happened. To do this using +APR, call ap_strerror().

    + diff --git a/srclib/apr/docs/canonical_filenames.html b/srclib/apr/docs/canonical_filenames.html new file mode 100644 index 0000000000..10867d3796 --- /dev/null +++ b/srclib/apr/docs/canonical_filenames.html @@ -0,0 +1,156 @@ + +APR Canonical Filenames + +

    APR Canonical Filename

    + +

    Requirements

    + +

    APR porters need to address the underlying discrepancies between +file systems. To achieve a reasonable degree of security, the +program depending upon APR needs to know that two paths may be +compared, and that a mismatch is guarenteed to reflect that the +two paths do not return the same resource

    . + +

    The first discrepancy is in volume roots. Unix and pure deriviates +have only one root path, "/". Win32 and OS2 share root paths of +the form "D:/", D: is the volume designation. However, this can +be specified as "//./D:/" as well, indicating D: volume of the +'this' machine. Win32 and OS2 also may employ a UNC root path, +of the form "//server/share/" where share is a share-point of the +specified network server. Finally, NetWare root paths are of the +form "server/volume:/", or the simpler "volume:/" syntax for 'this' +machine. All these non-Unix file systems accept volume:path, +without a slash following the colon, as a path relative to the +current working directory, which APR will treat as ambigious, that +is, neither an absolute nor a relative path per se.

    + +

    The second discrepancy is in the meaning of the 'this' directory. +In general, 'this' must be eliminated from the path where it occurs. +The syntax "path/./" and "path/" are both aliases to path. However, +this isn't file system independent, since the double slash "//" has +a special meaning on OS2 and Win32 at the start of the path name, +and is invalid on those platforms before the "//server/share/" UNC +root path is completed. Finally, as noted above, "//./volume/" is +legal root syntax on WinNT, and perhaps others.

    + +

    The third discrepancy is in the context of the 'parent' directory. +When "parent/path/.." occurs, the path must be unwound to "parent". +It's also critical to simply truncate leading "/../" paths to "/", +since the parent of the root is root. This gets tricky on the +Win32 and OS2 platforms, since the ".." element is invalid before +the "//server/share/" is complete, and the "//server/share/../" +seqence is the complete UNC root "//server/share/". In relative +paths, leading ".." elements are significant, until they are merged +with an absolute path. The relative form must only retain the ".." +segments as leading segments, to be resolved once merged to another +relative or an absolute path.

    + +

    The fourth discrepancy occurs with acceptance of alternate character +codes for the same element. Path seperators are not retained within +the APR canonical forms. The OS filesystem and APR (slashed) forms +can both be returned as strings, to be used in the proper context. +Unix, Win32 and Netware all accept slashes and backslashes as the +same path seperator symbol, although unix strictly accepts slashes. +While the APR form of the name strictly uses slashes, always consider +that there could be a platform that actually accepts slashes as a +character within a segment name.

    + +

    The fifth and worst discrepancy plauges Win32, OS2, Netware, and some +filesystems mounted in Unix. Case insensitivity can permit the same +file to slip through in both it's proper case and alternate cases. +Simply changing the case is insufficient for any character set beyond +ASCII, since various dilectic forms of characters suffer from one to +many or many to one translations. An example would be u-umlaut, which +might be accepted as a single character u-umlaut, a two character +sequence u and the zero-width umlaut, the upper case form of the same, +or perhaps even a captial U alone. This can be handled in different +ways depending on the purposes of the APR based program, but the one +requirement is that the path must be absolute in order to resolve these +ambiguities. Methods employed include comparison of device and inode +file uniqifiers, which is a fairly fast operation, or quering the OS +for the true form of the name, which can be much slower. Only the +acknowledgement of the file names by the OS can validate the equality +of two different cases of the same filename.

    + +

    The sixth discrepancy, illegal or insignificant characters, is especially +significant in non-unix file systems. Trailing periods are accepted +but never stored, therefore trailing periods must be ignored for any +form of comparison. And all OS's have certain expectations of what +characters are illegal (or undesireable due to confusion.)

    + +

    A final warning, canonical functions don't transform or resolve case +or character ambiguity issues until they are resolved into an absolute +path. The relative canonical path, while useful, while useful for URL +or similar identifiers, cannot be used for testing or comparison of file +system objects.

    + +
    + +

    Canonical API

    + +Functions to manipulate the apr_canon_file_t (an opaque type) include: + +
      +
    • Create canon_file_t (from char* path and canon_file_t parent path) +
    • Merged canon_file_t (from path and parent, both canon_file_t) +
    • Get char* path of all or some segments +
    • Get path flags of IsRelative, IsVirtualRoot, and IsAbsolute +
    • Compare two canon_file_t structures for file equality +
    + +

    The path is corrected to the file system case only if is in absolute +form. The apr_canon_file_t should be preserved as long as possible and +used as the parent to create child entries to reduce the number of expensive +stat and case canonicalization calls to the OS.

    + +

    The comparison operation provides that the APR can postpone correction +of case by simply relying upon the device and inode for equivilance. The +stat implementation provides that two files are the same, while their +strings are not equivilant, and eliminates the need for the operating +system to return the proper form of the name.

    + +

    In any case, returning the char* path, with a flag to request the proper +case, forces the OS calls to resolve the true names of each segment. Where +there is a penality for this operation and the stat device and inode test +is faster, case correction is postponed until the char* result is requested. +On platforms that identify the inode, device, or proper name interchangably +with no penalities, this may occur when the name is initially processed.

    + +
    + +

    Unix Example

    + +

    First the simplest case:

    + +
    +Parse Canonical Name 
    +accepts parent path as canonical_t
    +        this path as string
    +
    +Split this path Segments on '/'
    +
    +For each of this path Segments
    +  If first Segment
    +    If this Segment is Empty ([nothing]/)
    +      Append this Root Segment (don't merge)
    +      Continue to next Segment
    +    Else is relative
    +      Append parent Segments (to merge)
    +      Continue with this Segment
    +  If Segment is '.' or empty (2 slashes)
    +    Discard this Segment
    +    Continue with next Segment
    +  If Segment is '..'
    +    If no previous Segment or previous Segment is '..'
    +      Append this Segment
    +      Continue with next Segment
    +    If previous Segment and previous is not Root Segment
    +      Discard previous Segment
    +    Discard this Segment
    +    Continue with next Segment
    +  Append this Relative Segment
    +  Continue with next Segment        
    +
    + + + \ No newline at end of file diff --git a/srclib/apr/docs/doxygen.conf b/srclib/apr/docs/doxygen.conf new file mode 100644 index 0000000000..29c2cbf694 --- /dev/null +++ b/srclib/apr/docs/doxygen.conf @@ -0,0 +1,38 @@ +PROJECT_NAME="Apache Portable Runtime" + +INPUT=. +QUIET=YES +RECURSIVE=YES +FILE_PATTERNS=*.h + +OUTPUT_DIRECTORY=docs/dox + +MACRO_EXPANSION=YES +EXPAND_ONLY_PREDEF=YES +#EXPAND_AS_DEFINED= +# not sure why this doesn't work as EXPAND_AS_DEFINED, it should! +PREDEFINED="APR_DECLARE(x)=x" \ + "APR_DECLARE_NONSTD(x)=x" \ + "APR_DECLARE_DATA" \ + "APR_POOL_DECLARE_ACCESSOR(x)=apr_pool_t* apr_##x##_pool_get (const apr_##x##_t *the##x)" \ + "APR_DECLARE_INHERIT_SET(x)=apr_status_t apr_##x##_inherit_set(apr_##x##_t *the##x)" \ + "APR_DECLARE_INHERIT_UNSET(x)=apr_status_t apr_##x##_inherit_unset(apr_##x##_t *the##x)" \ + "APR_HAS_THREADS" \ + "__attribute__(x)=" \ + DOXYGEN= + +OPTIMIZE_OUTPUT_FOR_C=YES +STRIP_CODE_COMMENTS=NO + +FULL_PATH_NAMES=NO +CASE_SENSE_NAMES=NO +# some autoconf guru needs to make configure set this correctly... +# in the meantime, simply listing the headers should be alright +#STRIP_FROM_PATH=/buildpath/apr + +EXCLUDE_PATTERNS="*/acconfig.h" \ + "*/test/*" \ + "*/arch/*" + +GENERATE_TAGFILE=docs/dox/apr.tag + diff --git a/srclib/apr/docs/incomplete_types b/srclib/apr/docs/incomplete_types new file mode 100644 index 0000000000..cbed777423 --- /dev/null +++ b/srclib/apr/docs/incomplete_types @@ -0,0 +1,84 @@ +The question has been asked multiple times, "Why is APR using Incomplete +types?" This document will try to explain that. + +Incomplete types are used in APR because they can enforce portability, and +they make the APR developers job easier, as well as allowing APR to use native +types on all platforms. Imagine a scenario where APR wasn't using incomplete +types. The ap_file_t type would have to be defined as: + +typedef struct ap_file_t { + ap_pool_t *pool + char *fname; + int eof_hit; + int pipe; + ap_interval_time_t timeout; +#ifdef WIN32 + HANDLE file_handle; + DWORD dwFileAttributes; +#elif defined(OS2) + HFILE filedes; + HEV PipeSem +#else + int filedes; + int ungetchar; +#endif + +#ifndef WIN32 + int buffered; + ap_int32_flags + int isopen; + + /* Stuff for buffered mode */ + char *buffer; + int bufpos; + unsigned long dataRead; + int direction; + unsigned long filePtr; + ap_lock_t *mutex; +#endif +} ap_file_t; + +This captures the essense of what is currently being defined for ap_file_t +using incomplete types. However, using this structure leads developers to +believe that they are safe accessing any of the fields in this structure. +This is not true. On some platforms, such as Windows, about half of the +structure disappears. We could combine some of these definitions with +macros, for example: + +#ifdef WIN32 +#define filetype HANDLE +#elif OS2 +#define filetype HFILE +#else +#define filetype int +#endif + +And then in the defintion for ap_file_t, we could say: + filetype filedes; + +This gets rid of some of the complexity, by moving it off to the side, but +it is still not safe for a programmers to access the filedes field directly +outside of APR, because the programmer has no way of knowing what the actual +type is. So for example printing the filedes using printf would yield wildly +varying results on Windows and OS2 when compared to Unix. + +Another option also presents itself. Stick strictly to POSIX. This means +that all code can be shared on any POSIX compliant platform. The problem +with this is performance. One of the benefits to APR, is that it allows +developers to easily use native types on all platforms with the same code. +This has proven to provide a substantial performance boost on most non-Unix +platforms. + +Having said all of that, sometimes incomplete types just don't make sense. +For example, the first implementation of time functions used incomplete types, +which added a layer of complexity that turned out to be unnecessary. If +a platform cannot provide a simple number that represents the number of seconds +elapsed since a specifed date and time, then APR doesn't really want to +provide support for that platform. + +APR is trying hard to provide a balance of incomplete and complete types, +but like all things, sometimes the developers make mistakes. If you are +using APR and find that there is an incomplete type that doesn't need to be +an incomplete type, please let us know, we are more than willing to listen +and design parts of APR that do not use incomplete types. + diff --git a/srclib/apr/docs/non_apr_programs b/srclib/apr/docs/non_apr_programs new file mode 100644 index 0000000000..5003a8bd55 --- /dev/null +++ b/srclib/apr/docs/non_apr_programs @@ -0,0 +1,47 @@ +How do I use APR'ized programs in connection with programs that don't +use APR? These darn incomplete types don't let me fill out the APR types. + +The APR developers acknowledge that most programs are not using APR, and +we don't expect them to migrate to using APR just because APR has been +released. So, we have provided a way for non-APR'ized programs to interact +very cleanly with APR. + +There are a set of functions, all documented in apr_portable.h, which allow +a programmer to either get a native type from an APR type, or to setup an +APR type from a native type. + +For example, if you are writing an add-on to another program that does not use +APR for file I/O, but you (in your infinite wisdom) want to use APR to make +sure your section is portable. Assume the program provides a type foo_t with +a file descriptor in it (fd). + +void function_using_apr(foo_t non_apr_struct, ap_pool_t *p) +{ + ap_file_t *apr_file = NULL; + + ap_put_os_file(&apr_file, &non_apr_struct->fd, p); + + ... +} + +There are portable functions for each APR incomplete type. They are all +called ap_put_os_foobar(), and they each take the same basic arguments, a +pointer to a pointer to the incomplete type (the last pointer in that list +should be NULL), a pointer to the native type, and a pool. Each of these can +be found in apr_portable.h. + +If you have to do the exact opposite (take an APR type and convert it to a +native type, there are functions for that too. For example: + +void function_not_using_apr(apr_file_t *apr_file) +{ + int unix_file_desc; + + ap_get_os_file(&unix_file_desc, apr_file); + + ... +} + +For each ap_put_os_foobar, there is a corresponding ap_get_os_file. These are +also documented in apr_portable.h. + diff --git a/srclib/apr/docs/pool-design.html b/srclib/apr/docs/pool-design.html new file mode 100644 index 0000000000..0669bdfc99 --- /dev/null +++ b/srclib/apr/docs/pool-design.html @@ -0,0 +1,100 @@ + + + Using APR Pools + + +
    + Last modified at [$Date$] +
    + +

    Using APR Pools

    + +

    + From Subversion, we + have learned a lot about how to use pools in a heavily + structured/object-based environment. + Apache httpd is a + completely different beast: "allocate a request pool. use + it. destroy it." +

    + +

    + In a complex app, that request-style of behavior is not + present. Luckily, the "proper" use of pools can be described in + just a few rules: +

    + +
      +
    • + Objects should not have their own pools. An object is + allocated into a pool defined by the constructor's caller. The + caller knows the lifetime of the object and + will manage it via the pool. Generally, this also means that + objects will not have a "close" or a "free" since those + operations will happen implicitly as part of the destruction + of the pool the objects live within. +
    • + +
    • +

      + Functions should not create/destroy pools for their + operation; they should use a pool provided by the + caller. Again, the caller knows more about + how the function will be used, how often, how many times, + etc. Thus, it should be in charge of the function's memory + usage. +

      +

      + As an example, the caller might know that the app will exit + upon the function's return. Thus, the function would be + creating extra work if it built and destroyed a + pool. Instead, it should use the passed-in pool, which the + caller is going to be tossing as part of app-exit anyways. +

      +
    • + +
    • +

      + Whenever an unbounded iteration occurs, a subpool should be + used. The general pattern is: +

      +
      +
      +subpool = apr_create_subpool(pool);
      +for (i = 0; i < n; ++i) {
      +  apr_pool_clear(subpool);
      +
      +  do_operation(..., subpool);
      +}
      +apr_pool_destroy(subpool);
      +
      +

      + This pattern prevents the 'pool' from growing unbounded and + consuming all of memory. Note that it is slightly more + optimal to clear the pool on loop-entry. This pattern also + allows for a 'continue' to occur within the loop, + yet still ensure the pool will be cleared. +

      +
    • + +
    • + Given all of the above, it is pretty well mandatory to pass a + pool to every function. Since objects are not + recording pools for themselves, and the caller is always + supposed to be managing memory, then each function needs a + pool, rather than relying on some hidden magic pool. In + limited cases, objects may record the pool used for their + construction so that they can construct sub-parts, but these + cases should be examined carefully. Internal pools can lead to + unbounded pool usage if the object is not careful. +
    • +
    + +
    +
    Greg Stein
    + + +Last modified: Wed Jun 25 14:50:19 PDT 2003 + + + diff --git a/srclib/apr/docs/win32_builds.html b/srclib/apr/docs/win32_builds.html new file mode 100644 index 0000000000..ad57d8e138 --- /dev/null +++ b/srclib/apr/docs/win32_builds.html @@ -0,0 +1,57 @@ + +APR Win32 Builds and Debugging + +

    APR Win32 Builds and Debugging

    + +

    Configuration and Flavors

    + +

    The Win32 APR Developer Studio projects consist of

    + +
    +
    apr/apr.dsp
    +
    Builds the static apr.lib library (-D APR_DECLARE_STATIC)
    +
    apr/libapr.dsp
    +
    Builds the dynamic libapr.dll library (no define required)
    +
    apr-util/aprutil.dsp
    +
    Builds the static aprutil.lib library (-D APU_DECLARE_STATIC)
    +
    apr-util/libaprutil.dsp
    +
    Builds the dynamic libaprutil.dll library (no define required)
    +
    apr-iconv/apriconv.dsp
    +
    Builds the static apriconv.lib library (-D API_DECLARE_STATIC)
    +
    apr-iconv/libapriconv.dsp
    +
    Builds the dynamic libapriconv.dll library (no define required)
    +
    + +

    In order to prepare to use one of the static libraries above, + your application must be compiled with the define shown above, so that the + correct linkage is created. The APR authors intended the use of dynamic + libraries by default, so application authors do not need any special + defines in order to link to the dynamic library flavors.

    + +

    In order to build APR, you must use the proper dependencies. A good + example of those dependencies is given in the apr-util/aprutil.dsw + Developer Studio workspace. You can borrow the parts of that structure + your application needs, that workspace defines both the dynamic and static + library dependencies.

    + +

    The APR libraries (dynamic and static) are compiled with debugging symbols, + even in Release builds. The dynamic library symbols are always usable, + simply keep the correspond .pdb file in the same path as the library .dll. + (E.g. both libapr.dll and libapr.pdb should be copied to the same path.)

    + +

    The static symbols will only be fully usable if your application does not + link with the /pdbtype:sept flag! At the time your application links to + an APR library, the corresponding _src.pdb file should exist in the original + path the library was built, or it may be sufficient to keep the _src.pdb file + in the same path as the library file. (E.g. apr.lib and apr_src.pdb should + reside together in your lib directory.) The later option is unconfirmed.

    + +

    In order to keep the symbols compiled into the static library, your application + must use the linker's /debug flag. If you do not want the application to be + debuggable with its corresponding .pdb file, omit the /debug flag and all debug + symbolic information is discarded. Note that your application can only be + debugged with the corresponding .pdb file created by the linker, unless you use + /debugtype:coff or /debugtype:both in your link options.

    + + + diff --git a/srclib/apr/dso/aix/dso.c b/srclib/apr/dso/aix/dso.c new file mode 100644 index 0000000000..0b4736adde --- /dev/null +++ b/srclib/apr/dso/aix/dso.c @@ -0,0 +1,714 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * dso.c -- DSO system function emulation for AIX + * + * This is *only* intended for AIX < 4.3. + */ + +/* + * Based on libdl (dlfcn.c/dlfcn.h) which is + * Copyright (c) 1992,1993,1995,1996,1997,1988 + * Jens-Uwe Mager, Helios Software GmbH, Hannover, Germany. + * + * Not derived from licensed software. + * + * Permission is granted to freely use, copy, modify, and redistribute + * this software, provided that the author is not construed to be liable + * for any results of using the software, alterations are clearly marked + * as such, and this notice is not modified. + * + * Changes marked with `--jwe' were made on April 7 1996 by + * John W. Eaton to support g++ + * + * Bundled, stripped and adjusted on April 1998 as one single source file + * for inclusion into the Apache HTTP server by + * Ralf S. Engelschall + * + * Added to APR by David Reid April 2000 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "apr_arch_dso.h" +#include "apr_portable.h" + +#if APR_HAS_DSO + +#undef FREAD +#undef FWRITE +#include + +/* + * AIX 4.3 does remove some useful definitions from ldfcn.h. Define + * these here to compensate for that lossage. + */ +#ifndef BEGINNING +#define BEGINNING SEEK_SET +#endif +#ifndef FSEEK +#define FSEEK(ldptr,o,p) fseek(IOPTR(ldptr),(p==BEGINNING)?(OFFSET(ldptr) +o):o,p) +#endif +#ifndef FREAD +#define FREAD(p,s,n,ldptr) fread(p,s,n,IOPTR(ldptr)) +#endif + +/* + * Mode flags for the dlopen routine. + */ +#undef RTLD_LAZY +#define RTLD_LAZY 1 /* lazy function call binding */ +#undef RTLD_NOW +#define RTLD_NOW 2 /* immediate function call binding */ +#undef RTLD_GLOBAL +#define RTLD_GLOBAL 0x100 /* allow symbols to be global */ + +/* + * To be able to initialize, a library may provide a dl_info structure + * that contains functions to be called to initialize and terminate. + */ +struct dl_info { + void (*init) (void); + void (*fini) (void); +}; + +/* APR functions... + * + * As the AIX functions have been declared in the header file we just + * add the basic "wrappers" here. + */ + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->pool = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + + if (dso->handle != NULL && dlclose(dso->handle) != 0) + return APR_EINIT; + dso->handle = NULL; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx) +{ + void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL); + + *res_handle = apr_pcalloc(ctx, sizeof(*res_handle)); + + if(os_handle == NULL) { + (*res_handle)->errormsg = dlerror(); + return APR_EDSOOPEN; + } + + (*res_handle)->handle = (void*)os_handle; + (*res_handle)->pool = ctx; + (*res_handle)->errormsg = NULL; + + apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname) +{ + void *retval = dlsym(handle->handle, symname); + + if (retval == NULL) { + handle->errormsg = dlerror(); + return APR_ESYMNOTFOUND; + } + + *ressym = retval; + return APR_SUCCESS; +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen) +{ + if (dso->errormsg) { + apr_cpystrn(buffer, dso->errormsg, buflen); + return dso->errormsg; + } + return "No Error"; +} + + + +/* + * We simulate dlopen() et al. through a call to load. Because AIX has + * no call to find an exported symbol we read the loader section of the + * loaded module and build a list of exported symbols and their virtual + * address. + */ + +typedef struct { + char *name; /* the symbols's name */ + void *addr; /* its relocated virtual address */ +} Export, *ExportPtr; + +/* + * xlC uses the following structure to list its constructors and + * destructors. This is gleaned from the output of munch. + */ +typedef struct { + void (*init) (void); /* call static constructors */ + void (*term) (void); /* call static destructors */ +} Cdtor, *CdtorPtr; + +typedef void (*GccCDtorPtr) (void); + +/* + * The void * handle returned from dlopen is actually a ModulePtr. + */ +typedef struct Module { + struct Module *next; + char *name; /* module name for refcounting */ + int refCnt; /* the number of references */ + void *entry; /* entry point from load */ + struct dl_info *info; /* optional init/terminate functions */ + CdtorPtr cdtors; /* optional C++ constructors */ + GccCDtorPtr gcc_ctor; /* g++ constructors --jwe */ + GccCDtorPtr gcc_dtor; /* g++ destructors --jwe */ + int nExports; /* the number of exports found */ + ExportPtr exports; /* the array of exports */ +} Module, *ModulePtr; + +/* + * We keep a list of all loaded modules to be able to call the fini + * handlers and destructors at atexit() time. + */ +static ModulePtr modList; + +/* + * The last error from one of the dl* routines is kept in static + * variables here. Each error is returned only once to the caller. + */ +static char errbuf[BUFSIZ]; +static int errvalid; + +/* + * The `fixed' gcc header files on AIX 3.2.5 provide a prototype for + * strdup(). --jwe + */ +extern char *strdup(const char *); +static void caterr(char *); +static int readExports(ModulePtr); +static void terminate(void); +static void *findMain(void); + +void *dlopen(const char *path, int mode) +{ + register ModulePtr mp; + static void *mainModule; + + /* + * Upon the first call register a terminate handler that will + * close all libraries. Also get a reference to the main module + * for use with loadbind. + */ + if (!mainModule) { + if ((mainModule = findMain()) == NULL) + return NULL; + atexit(terminate); + } + /* + * Scan the list of modules if we have the module already loaded. + */ + for (mp = modList; mp; mp = mp->next) + if (strcmp(mp->name, path) == 0) { + mp->refCnt++; + return mp; + } + if ((mp = (ModulePtr) calloc(1, sizeof(*mp))) == NULL) { + errvalid++; + strcpy(errbuf, "calloc: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + if ((mp->name = strdup(path)) == NULL) { + errvalid++; + strcpy(errbuf, "strdup: "); + strcat(errbuf, strerror(errno)); + free(mp); + return NULL; + } + /* + * load should be declared load(const char *...). Thus we + * cast the path to a normal char *. Ugly. + */ + if ((mp->entry = (void *) loadAndInit((char *) path, L_NOAUTODEFER, NULL)) == NULL) { + free(mp->name); + free(mp); + errvalid++; + strcpy(errbuf, "dlopen: "); + strcat(errbuf, path); + strcat(errbuf, ": "); + /* + * If AIX says the file is not executable, the error + * can be further described by querying the loader about + * the last error. + */ + if (errno == ENOEXEC) { + char *tmp[BUFSIZ / sizeof(char *)]; + if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1) + strcpy(errbuf, strerror(errno)); + else { + char **p; + for (p = tmp; *p; p++) + caterr(*p); + } + } + else + strcat(errbuf, strerror(errno)); + return NULL; + } + mp->refCnt = 1; + mp->next = modList; + modList = mp; + if (loadbind(0, mainModule, mp->entry) == -1) { + dlclose(mp); + errvalid++; + strcpy(errbuf, "loadbind: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + /* + * If the user wants global binding, loadbind against all other + * loaded modules. + */ + if (mode & RTLD_GLOBAL) { + register ModulePtr mp1; + for (mp1 = mp->next; mp1; mp1 = mp1->next) + if (loadbind(0, mp1->entry, mp->entry) == -1) { + dlclose(mp); + errvalid++; + strcpy(errbuf, "loadbind: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + } + if (readExports(mp) == -1) { + dlclose(mp); + return NULL; + } + /* + * If there is a dl_info structure, call the init function. + */ + if (mp->info = (struct dl_info *) dlsym(mp, "dl_info")) { + if (mp->info->init) + (*mp->info->init) (); + } + else + errvalid = 0; + /* + * If the shared object was compiled using xlC we will need + * to call static constructors (and later on dlclose destructors). + */ + if (mp->cdtors = (CdtorPtr) dlsym(mp, "__cdtors")) { + CdtorPtr cp = mp->cdtors; + while (cp->init || cp->term) { + if (cp->init && cp->init != (void (*)(void)) 0xffffffff) + (*cp->init) (); + cp++; + } + /* + * If the shared object was compiled using g++, we will need + * to call global constructors using the _GLOBAL__DI function, + * and later, global destructors using the _GLOBAL_DD + * funciton. --jwe + */ + } + else if (mp->gcc_ctor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DI")) { + (*mp->gcc_ctor) (); + mp->gcc_dtor = (GccCDtorPtr) dlsym(mp, "_GLOBAL__DD"); + } + else + errvalid = 0; + return mp; +} + +/* + * Attempt to decipher an AIX loader error message and append it + * to our static error message buffer. + */ +static void caterr(char *s) +{ + register char *p = s; + + while (*p >= '0' && *p <= '9') + p++; + switch (atoi(s)) { + case L_ERROR_TOOMANY: + strcat(errbuf, "to many errors"); + break; + case L_ERROR_NOLIB: + strcat(errbuf, "can't load library"); + strcat(errbuf, p); + break; + case L_ERROR_UNDEF: + strcat(errbuf, "can't find symbol"); + strcat(errbuf, p); + break; + case L_ERROR_RLDBAD: + strcat(errbuf, "bad RLD"); + strcat(errbuf, p); + break; + case L_ERROR_FORMAT: + strcat(errbuf, "bad exec format in"); + strcat(errbuf, p); + break; + case L_ERROR_ERRNO: + strcat(errbuf, strerror(atoi(++p))); + break; + default: + strcat(errbuf, s); + break; + } +} + +void *dlsym(void *handle, const char *symbol) +{ + register ModulePtr mp = (ModulePtr) handle; + register ExportPtr ep; + register int i; + + /* + * Could speed up the search, but I assume that one assigns + * the result to function pointers anyways. + */ + for (ep = mp->exports, i = mp->nExports; i; i--, ep++) + if (strcmp(ep->name, symbol) == 0) + return ep->addr; + errvalid++; + strcpy(errbuf, "dlsym: undefined symbol "); + strcat(errbuf, symbol); + return NULL; +} + +const char *dlerror(void) +{ + if (errvalid) { + errvalid = 0; + return errbuf; + } + return NULL; +} + +int dlclose(void *handle) +{ + register ModulePtr mp = (ModulePtr) handle; + int result; + register ModulePtr mp1; + + if (--mp->refCnt > 0) + return 0; + if (mp->info && mp->info->fini) + (*mp->info->fini) (); + if (mp->cdtors) { + CdtorPtr cp = mp->cdtors; + while (cp->init || cp->term) { + if (cp->term && cp->init != (void (*)(void)) 0xffffffff) + (*cp->term) (); + cp++; + } + /* + * If the function to handle global destructors for g++ + * exists, call it. --jwe + */ + } + else if (mp->gcc_dtor) { + (*mp->gcc_dtor) (); + } + result = unload(mp->entry); + if (result == -1) { + errvalid++; + strcpy(errbuf, strerror(errno)); + } + if (mp->exports) { + register ExportPtr ep; + register int i; + for (ep = mp->exports, i = mp->nExports; i; i--, ep++) + if (ep->name) + free(ep->name); + free(mp->exports); + } + if (mp == modList) + modList = mp->next; + else { + for (mp1 = modList; mp1; mp1 = mp1->next) + if (mp1->next == mp) { + mp1->next = mp->next; + break; + } + } + free(mp->name); + free(mp); + return result; +} + +static void terminate(void) +{ + while (modList) + dlclose(modList); +} + +/* + * Build the export table from the XCOFF .loader section. + */ +static int readExports(ModulePtr mp) +{ + LDFILE *ldp = NULL; + SCNHDR sh, shdata; + LDHDR *lhp; + char *ldbuf; + LDSYM *ls; + int i; + ExportPtr ep; + struct ld_info *lp; + char *buf; + int size = 4 * 1024; + void *dataorg; + + /* + * The module might be loaded due to the LIBPATH + * environment variable. Search for the loaded + * module using L_GETINFO. + */ + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { + free(buf); + size += 4 * 1024; + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + } + if (i == -1) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + free(buf); + return -1; + } + /* + * Traverse the list of loaded modules. The entry point + * returned by load() does actually point to the TOC + * entry contained in the data segment. + */ + lp = (struct ld_info *) buf; + while (lp) { + if ((unsigned long) mp->entry >= (unsigned long) lp->ldinfo_dataorg && + (unsigned long) mp->entry < (unsigned long) lp->ldinfo_dataorg + + lp->ldinfo_datasize) { + dataorg = lp->ldinfo_dataorg; + ldp = ldopen(lp->ldinfo_filename, ldp); + break; + } + if (lp->ldinfo_next == 0) + lp = NULL; + else + lp = (struct ld_info *) ((char *) lp + lp->ldinfo_next); + } + free(buf); + if (!ldp) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + return -1; + } + if (TYPE(ldp) != U802TOCMAGIC) { + errvalid++; + strcpy(errbuf, "readExports: bad magic"); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * Get the padding for the data section. This is needed for + * AIX 4.1 compilers. This is used when building the final + * function pointer to the exported symbol. + */ + if (ldnshread(ldp, _DATA, &shdata) != SUCCESS) { + errvalid++; + strcpy(errbuf, "readExports: cannot read data section header"); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) { + errvalid++; + strcpy(errbuf, "readExports: cannot read loader section header"); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * We read the complete loader section in one chunk, this makes + * finding long symbol names residing in the string table easier. + */ + if ((ldbuf = (char *) malloc(sh.s_size)) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) { + errvalid++; + strcpy(errbuf, "readExports: cannot seek to loader section"); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) { + errvalid++; + strcpy(errbuf, "readExports: cannot read loader section"); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + lhp = (LDHDR *) ldbuf; + ls = (LDSYM *) (ldbuf + LDHDRSZ); + /* + * Count the number of exports to include in our export table. + */ + for (i = lhp->l_nsyms; i; i--, ls++) { + if (!LDR_EXPORT(*ls)) + continue; + mp->nExports++; + } + if ((mp->exports = (ExportPtr) calloc(mp->nExports, sizeof(*mp->exports))) == NULL) { + errvalid++; + strcpy(errbuf, "readExports: "); + strcat(errbuf, strerror(errno)); + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return -1; + } + /* + * Fill in the export table. All entries are relative to + * the beginning of the data origin. + */ + ep = mp->exports; + ls = (LDSYM *) (ldbuf + LDHDRSZ); + for (i = lhp->l_nsyms; i; i--, ls++) { + char *symname; + char tmpsym[SYMNMLEN + 1]; + if (!LDR_EXPORT(*ls)) + continue; + if (ls->l_zeroes == 0) + symname = ls->l_offset + lhp->l_stoff + ldbuf; + else { + /* + * The l_name member is not zero terminated, we + * must copy the first SYMNMLEN chars and make + * sure we have a zero byte at the end. + */ + strncpy(tmpsym, ls->l_name, SYMNMLEN); + tmpsym[SYMNMLEN] = '\0'; + symname = tmpsym; + } + ep->name = strdup(symname); + ep->addr = (void *) ((unsigned long) dataorg + + ls->l_value - shdata.s_vaddr); + ep++; + } + free(ldbuf); + while (ldclose(ldp) == FAILURE); + return 0; +} + +/* + * Find the main modules data origin. This is used as export pointer + * for loadbind() to be able to resolve references to the main part. + */ +static void *findMain(void) +{ + struct ld_info *lp; + char *buf; + int size = 4 * 1024; + int i; + void *ret; + + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) { + free(buf); + size += 4 * 1024; + if ((buf = malloc(size)) == NULL) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + return NULL; + } + } + if (i == -1) { + errvalid++; + strcpy(errbuf, "findMain: "); + strcat(errbuf, strerror(errno)); + free(buf); + return NULL; + } + /* + * The first entry is the main module. The data segment + * starts with the TOC entries for all exports, so the + * data segment origin works as argument for loadbind. + */ + lp = (struct ld_info *) buf; + ret = lp->ldinfo_dataorg; + free(buf); + return ret; +} + +#endif diff --git a/srclib/apr/dso/beos/dso.c b/srclib/apr/dso/beos/dso.c new file mode 100644 index 0000000000..797c11089b --- /dev/null +++ b/srclib/apr/dso/beos/dso.c @@ -0,0 +1,98 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_dso.h" +#include "apr_portable.h" + +#if APR_HAS_DSO + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + + if (dso->handle > 0 && unload_add_on(dso->handle) < B_NO_ERROR) + return APR_EINIT; + dso->handle = -1; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *pool) +{ + image_id newid = -1; + + *res_handle = apr_pcalloc(pool, sizeof(*res_handle)); + + if((newid = load_add_on(path)) < B_NO_ERROR) { + (*res_handle)->errormsg = strerror(newid); + return APR_EDSOOPEN; + } + + (*res_handle)->pool = pool; + (*res_handle)->handle = newid; + + apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, apr_dso_handle_t *handle, + const char *symname) +{ + int err; + + if (symname == NULL) + return APR_ESYMNOTFOUND; + + err = get_image_symbol(handle->handle, symname, B_SYMBOL_TYPE_ANY, + ressym); + + if(err != B_OK) + return APR_ESYMNOTFOUND; + + return APR_SUCCESS; +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen) +{ + strncpy(buffer, strerror(errno), buflen); + return buffer; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->pool = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +#endif diff --git a/srclib/apr/dso/netware/dso.c b/srclib/apr/dso/netware/dso.c new file mode 100644 index 0000000000..9bc24d72ce --- /dev/null +++ b/srclib/apr/dso/netware/dso.c @@ -0,0 +1,137 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_dso.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#include +#include + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->pool = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + sym_list *symbol = NULL; + void *NLMHandle = getnlmhandle(); + + if (dso->handle == NULL) + return APR_SUCCESS; + + if (dso->symbols != NULL) { + symbol = dso->symbols; + while (symbol) { + UnImportPublicObject(NLMHandle, symbol->symbol); + symbol = symbol->next; + } + } + + if (dlclose(dso->handle) != 0) + return APR_EINIT; + + dso->handle = NULL; + dso->symbols = NULL; + dso->path = NULL; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *pool) +{ + + void *os_handle = NULL; + char *fullpath = NULL; + apr_status_t rv; + + if ((rv = apr_filepath_merge(&fullpath, NULL, path, + APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) { + return rv; + } + + os_handle = dlopen(fullpath, RTLD_NOW | RTLD_LOCAL); + + *res_handle = apr_pcalloc(pool, sizeof(**res_handle)); + + if(os_handle == NULL) { + (*res_handle)->errormsg = dlerror(); + return APR_EDSOOPEN; + } + + (*res_handle)->handle = (void*)os_handle; + (*res_handle)->pool = pool; + (*res_handle)->errormsg = NULL; + (*res_handle)->symbols = NULL; + (*res_handle)->path = apr_pstrdup(pool, fullpath); + + apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname) +{ + sym_list *symbol = NULL; + void *retval = dlsym(handle->handle, symname); + + if (retval == NULL) { + handle->errormsg = dlerror(); + return APR_ESYMNOTFOUND; + } + + symbol = apr_pcalloc(handle->pool, sizeof(sym_list)); + symbol->next = handle->symbols; + handle->symbols = symbol; + symbol->symbol = apr_pstrdup(handle->pool, symname); + + *ressym = retval; + + return APR_SUCCESS; +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, + apr_size_t buflen) +{ + if (dso->errormsg) { + apr_cpystrn(buffer, dso->errormsg, buflen); + return dso->errormsg; + } + return "No Error"; +} + diff --git a/srclib/apr/dso/os2/dso.c b/srclib/apr/dso/os2/dso.c new file mode 100644 index 0000000000..7e735841e2 --- /dev/null +++ b/srclib/apr/dso/os2/dso.c @@ -0,0 +1,132 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_dso.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include +#include + +#if APR_HAS_DSO + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + int rc; + + if (dso->handle == 0) + return APR_SUCCESS; + + rc = DosFreeModule(dso->handle); + + if (rc == 0) + dso->handle = 0; + + return APR_FROM_OS_ERROR(rc); +} + + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, const char *path, apr_pool_t *ctx) +{ + char failed_module[200]; + HMODULE handle; + int rc; + + *res_handle = apr_pcalloc(ctx, sizeof(**res_handle)); + (*res_handle)->cont = ctx; + (*res_handle)->load_error = APR_SUCCESS; + (*res_handle)->failed_module = NULL; + + if ((rc = DosLoadModule(failed_module, sizeof(failed_module), path, &handle)) != 0) { + (*res_handle)->load_error = APR_FROM_OS_ERROR(rc); + (*res_handle)->failed_module = apr_pstrdup(ctx, failed_module); + return APR_FROM_OS_ERROR(rc); + } + + (*res_handle)->handle = handle; + apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->cont, handle, dso_cleanup); +} + + + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname) +{ + PFN func; + int rc; + + if (symname == NULL || ressym == NULL) + return APR_ESYMNOTFOUND; + + if ((rc = DosQueryProcAddr(handle->handle, 0, symname, &func)) != 0) { + handle->load_error = APR_FROM_OS_ERROR(rc); + return handle->load_error; + } + + *ressym = func; + return APR_SUCCESS; +} + + + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, apr_size_t buflen) +{ + char message[200]; + apr_strerror(dso->load_error, message, sizeof(message)); + + if (dso->failed_module != NULL) { + strcat(message, " ("); + strcat(message, dso->failed_module); + strcat(message, ")"); + } + + apr_cpystrn(buffer, message, buflen); + return buffer; +} + + + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->cont = pool; + (*aprdso)->load_error = APR_SUCCESS; + (*aprdso)->failed_module = NULL; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +#endif diff --git a/srclib/apr/dso/os390/dso.c b/srclib/apr/dso/os390/dso.c new file mode 100644 index 0000000000..0dcac7a8e5 --- /dev/null +++ b/srclib/apr/dso/os390/dso.c @@ -0,0 +1,109 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_portable.h" +#include "apr_strings.h" +#include "apr_arch_dso.h" +#include +#include + +#if APR_HAS_DSO + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->pool = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + int rc; + + if (dso->handle == 0) + return APR_SUCCESS; + + rc = dllfree(dso->handle); + + if (rc == 0) { + dso->handle = 0; + return APR_SUCCESS; + } + dso->failing_errno = errno; + return errno; +} + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx) +{ + dllhandle *handle; + int rc; + + *res_handle = apr_pcalloc(ctx, sizeof(*res_handle)); + (*res_handle)->pool = ctx; + if ((handle = dllload(path)) != NULL) { + (*res_handle)->handle = handle; + apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; + } + + (*res_handle)->failing_errno = errno; + return errno; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname) +{ + void *func_ptr; + void *var_ptr; + + if ((var_ptr = dllqueryvar(handle->handle, symname)) != NULL) { + *ressym = var_ptr; + return APR_SUCCESS; + } + if ((func_ptr = (void *)dllqueryfn(handle->handle, symname)) != NULL) { + *ressym = func_ptr; + return APR_SUCCESS; + } + handle->failing_errno = errno; + return errno; +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *handle, char *buffer, + apr_size_t buflen) +{ + apr_cpystrn(buffer, strerror(handle->failing_errno), buflen); + return buffer; +} + +#endif diff --git a/srclib/apr/dso/unix/dso.c b/srclib/apr/dso/unix/dso.c new file mode 100644 index 0000000000..7390872291 --- /dev/null +++ b/srclib/apr/dso/unix/dso.c @@ -0,0 +1,251 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_dso.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#if APR_HAS_DSO + +#if !defined(DSO_USE_DLFCN) && !defined(DSO_USE_SHL) && !defined(DSO_USE_DYLD) +#error No DSO implementation specified. +#endif + +#ifdef HAVE_STDDEF_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include /* malloc(), free() */ +#endif +#if APR_HAVE_STRING_H +#include /* for strerror() on HP-UX */ +#endif + +#if defined(DSO_USE_DYLD) +#define DYLD_LIBRARY_HANDLE (void *)-1 +#endif + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->pool = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + + if (dso->handle == NULL) + return APR_SUCCESS; + +#if defined(DSO_USE_SHL) + shl_unload((shl_t)dso->handle); +#elif defined(DSO_USE_DYLD) + if (dso->handle != DYLD_LIBRARY_HANDLE) { + NSUnLinkModule(dso->handle, FALSE); + } +#elif defined(DSO_USE_DLFCN) + if (dlclose(dso->handle) != 0) + return APR_EINIT; +#endif + dso->handle = NULL; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *pool) +{ +#if defined(DSO_USE_SHL) + shl_t os_handle = shl_load(path, BIND_IMMEDIATE, 0L); + +#elif defined(DSO_USE_DYLD) + NSObjectFileImage image; + NSModule os_handle = NULL; + NSObjectFileImageReturnCode dsoerr; + const char* err_msg = NULL; + dsoerr = NSCreateObjectFileImageFromFile(path, &image); + + if (dsoerr == NSObjectFileImageSuccess) { +#if defined(NSLINKMODULE_OPTION_RETURN_ON_ERROR) && defined(NSLINKMODULE_OPTION_NONE) + os_handle = NSLinkModule(image, path, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_NONE); + /* If something went wrong, get the errors... */ + if (!os_handle) { + NSLinkEditErrors errors; + int errorNumber; + const char *fileName; + NSLinkEditError(&errors, &errorNumber, &fileName, &err_msg); + } +#else + os_handle = NSLinkModule(image, path, FALSE); +#endif + NSDestroyObjectFileImage(image); + } + else if ((dsoerr == NSObjectFileImageFormat || + dsoerr == NSObjectFileImageInappropriateFile) && + NSAddLibrary(path) == TRUE) { + os_handle = (NSModule)DYLD_LIBRARY_HANDLE; + } + else { + err_msg = "cannot create object file image or add library"; + } + +#elif defined(DSO_USE_DLFCN) +#if defined(OSF1) || defined(SEQUENT) || defined(SNI) ||\ + (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) ||\ + defined(__DragonFly__) + void *os_handle = dlopen((char *)path, RTLD_NOW | RTLD_GLOBAL); + +#else + int flags = RTLD_NOW | RTLD_GLOBAL; + void *os_handle; +#ifdef _AIX + if (strchr(path + 1, '(') && path[strlen(path) - 1] == ')') + { + /* This special archive.a(dso.so) syntax is required for + * the way libtool likes to build shared libraries on AIX. + * dlopen() support for such a library requires that the + * RTLD_MEMBER flag be enabled. + */ + flags |= RTLD_MEMBER; + } +#endif + os_handle = dlopen(path, flags); +#endif +#endif /* DSO_USE_x */ + + *res_handle = apr_pcalloc(pool, sizeof(**res_handle)); + + if(os_handle == NULL) { +#if defined(DSO_USE_SHL) + (*res_handle)->errormsg = strerror(errno); + return APR_EDSOOPEN; +#elif defined(DSO_USE_DYLD) + (*res_handle)->errormsg = (err_msg) ? err_msg : "link failed"; + return APR_EDSOOPEN; +#elif defined(DSO_USE_DLFCN) + (*res_handle)->errormsg = dlerror(); + return APR_EDSOOPEN; +#endif + } + + (*res_handle)->handle = (void*)os_handle; + (*res_handle)->pool = pool; + (*res_handle)->errormsg = NULL; + + apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname) +{ +#if defined(DSO_USE_SHL) + void *symaddr = NULL; + int status; + + errno = 0; + status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_PROCEDURE, &symaddr); + if (status == -1 && errno == 0) /* try TYPE_DATA instead */ + status = shl_findsym((shl_t *)&handle->handle, symname, TYPE_DATA, &symaddr); + if (status == -1) + return APR_ESYMNOTFOUND; + *ressym = symaddr; + return APR_SUCCESS; + +#elif defined(DSO_USE_DYLD) + void *retval = NULL; + NSSymbol symbol; + char *symname2 = (char*)malloc(sizeof(char)*(strlen(symname)+2)); + sprintf(symname2, "_%s", symname); +#ifdef NSLINKMODULE_OPTION_PRIVATE + if (handle->handle == DYLD_LIBRARY_HANDLE) { + symbol = NSLookupAndBindSymbol(symname2); + } + else { + symbol = NSLookupSymbolInModule((NSModule)handle->handle, symname2); + } +#else + symbol = NSLookupAndBindSymbol(symname2); +#endif + free(symname2); + if (symbol == NULL) { + handle->errormsg = "undefined symbol"; + return APR_ESYMNOTFOUND; + } + retval = NSAddressOfSymbol(symbol); + if (retval == NULL) { + handle->errormsg = "cannot resolve symbol"; + return APR_ESYMNOTFOUND; + } + *ressym = retval; + return APR_SUCCESS; +#elif defined(DSO_USE_DLFCN) + +#if defined(DLSYM_NEEDS_UNDERSCORE) + void *retval; + char *symbol = (char*)malloc(sizeof(char)*(strlen(symname)+2)); + sprintf(symbol, "_%s", symname); + retval = dlsym(handle->handle, symbol); + free(symbol); +#elif defined(SEQUENT) || defined(SNI) + void *retval = dlsym(handle->handle, (char *)symname); +#else + void *retval = dlsym(handle->handle, symname); +#endif /* DLSYM_NEEDS_UNDERSCORE */ + + if (retval == NULL) { + handle->errormsg = dlerror(); + return APR_ESYMNOTFOUND; + } + + *ressym = retval; + + return APR_SUCCESS; +#endif /* DSO_USE_x */ +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer, + apr_size_t buflen) +{ + if (dso->errormsg) { + apr_cpystrn(buffer, dso->errormsg, buflen); + return dso->errormsg; + } + return "No Error"; +} + +#endif diff --git a/srclib/apr/dso/win32/dso.c b/srclib/apr/dso/win32/dso.c new file mode 100644 index 0000000000..17651db012 --- /dev/null +++ b/srclib/apr/dso/win32/dso.c @@ -0,0 +1,167 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_dso.h" +#include "apr_strings.h" +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_arch_utf8.h" + +#if APR_HAS_DSO + +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso, + apr_os_dso_handle_t osdso, + apr_pool_t *pool) +{ + *aprdso = apr_pcalloc(pool, sizeof **aprdso); + (*aprdso)->handle = osdso; + (*aprdso)->cont = pool; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso, + apr_dso_handle_t *aprdso) +{ + *osdso = aprdso->handle; + return APR_SUCCESS; +} + +static apr_status_t dso_cleanup(void *thedso) +{ + apr_dso_handle_t *dso = thedso; + + if (dso->handle != NULL && !FreeLibrary(dso->handle)) { + return apr_get_os_error(); + } + dso->handle = NULL; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_load(struct apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx) +{ + HINSTANCE os_handle; + apr_status_t rv; +#ifndef _WIN32_WCE + UINT em; +#endif + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) + != APR_SUCCESS) { + *res_handle = apr_pcalloc(ctx, sizeof(**res_handle)); + return ((*res_handle)->load_error = rv); + } + /* Prevent ugly popups from killing our app */ +#ifndef _WIN32_WCE + em = SetErrorMode(SEM_FAILCRITICALERRORS); +#endif + os_handle = LoadLibraryExW(wpath, NULL, 0); + if (!os_handle) + os_handle = LoadLibraryExW(wpath, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!os_handle) + rv = apr_get_os_error(); +#ifndef _WIN32_WCE + SetErrorMode(em); +#endif + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char fspec[APR_PATH_MAX], *p = fspec; + /* Must convert path from / to \ notation. + * Per PR2555, the LoadLibraryEx function is very picky about slashes. + * Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL. + * LoadLibrary in the MS PSDK also reveals that it -explicitly- states + * that backslashes must be used for the LoadLibrary family of calls. + */ + apr_cpystrn(fspec, path, sizeof(fspec)); + while ((p = strchr(p, '/')) != NULL) + *p = '\\'; + + /* Prevent ugly popups from killing our app */ + em = SetErrorMode(SEM_FAILCRITICALERRORS); + os_handle = LoadLibraryEx(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); + if (!os_handle) + os_handle = LoadLibraryEx(path, NULL, 0); + if (!os_handle) + rv = apr_get_os_error(); + else + rv = APR_SUCCESS; + SetErrorMode(em); + } +#endif + + *res_handle = apr_pcalloc(ctx, sizeof(**res_handle)); + (*res_handle)->cont = ctx; + + if (rv) { + return ((*res_handle)->load_error = rv); + } + + (*res_handle)->handle = (void*)os_handle; + (*res_handle)->load_error = APR_SUCCESS; + + apr_pool_cleanup_register(ctx, *res_handle, dso_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dso_unload(struct apr_dso_handle_t *handle) +{ + return apr_pool_cleanup_run(handle->cont, handle, dso_cleanup); +} + +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + struct apr_dso_handle_t *handle, + const char *symname) +{ +#ifdef _WIN32_WCE + apr_size_t symlen = strlen(symname) + 1; + apr_size_t wsymlen = 256; + apr_wchar_t wsymname[256]; + apr_status_t rv; + + rv = apr_conv_utf8_to_ucs2(wsymname, &wsymlen, symname, &symlen); + if (rv != APR_SUCCESS) { + return rv; + } + else if (symlen) { + return APR_ENAMETOOLONG; + } + + *ressym = (apr_dso_handle_sym_t)GetProcAddressW(handle->handle, wsymname); +#else + *ressym = (apr_dso_handle_sym_t)GetProcAddress(handle->handle, symname); +#endif + if (!*ressym) { + return apr_get_os_error(); + } + return APR_SUCCESS; +} + +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize) +{ + return apr_strerror(dso->load_error, buf, bufsize); +} + +#endif diff --git a/srclib/apr/emacs-mode b/srclib/apr/emacs-mode new file mode 100644 index 0000000000..2c7abe9835 --- /dev/null +++ b/srclib/apr/emacs-mode @@ -0,0 +1,15 @@ +;; M-x load-file +;; or emacs -l +;; to use this style: C-c . apache +(c-add-style "apache" + '((inclass . ++) + (defun-block-intro . ++) + (statement-block-intro . ++) + (substatement . ++) + (brace-list-intro . ++) + (statement-case-intro . ++) + (inextern-lang . 0) + )) +(setq-default indent-tabs-mode nil) +;; if you forgot to do this at startup, then M-x eval-expression +;; (setq indent-tabs-mode nil) on each buffer diff --git a/srclib/apr/file_io/netware/filepath.c b/srclib/apr/file_io/netware/filepath.c new file mode 100644 index 0000000000..e4bb3f36cb --- /dev/null +++ b/srclib/apr/file_io/netware/filepath.c @@ -0,0 +1,4 @@ +/* NetWare & Win32 have much in common with regards to file names (both are + * DOSish) so it makes sense to share some code + */ +#include "../win32/filepath.c" diff --git a/srclib/apr/file_io/netware/filestat.c b/srclib/apr/file_io/netware/filestat.c new file mode 100644 index 0000000000..1fb31d9ee1 --- /dev/null +++ b/srclib/apr/file_io/netware/filestat.c @@ -0,0 +1,389 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "fsio.h" +#include "nks/dirio.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_hash.h" +#include "apr_thread_rwlock.h" + +#ifdef HAVE_UTIME_H +#include +#endif + +#define APR_HAS_PSA + +static apr_filetype_e filetype_from_mode(mode_t mode) +{ + apr_filetype_e type = APR_NOFILE; + + if (S_ISREG(mode)) + type = APR_REG; + else if (S_ISDIR(mode)) + type = APR_DIR; + else if (S_ISCHR(mode)) + type = APR_CHR; + else if (S_ISBLK(mode)) + type = APR_BLK; + else if (S_ISFIFO(mode)) + type = APR_PIPE; + else if (S_ISLNK(mode)) + type = APR_LNK; + else if (S_ISSOCK(mode)) + type = APR_SOCK; + else + type = APR_UNKFILE; + return type; +} + +static void fill_out_finfo(apr_finfo_t *finfo, struct stat *info, + apr_int32_t wanted) +{ + finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK + | APR_FINFO_OWNER | APR_FINFO_PROT; + finfo->protection = apr_unix_mode2perms(info->st_mode); + finfo->filetype = filetype_from_mode(info->st_mode); + finfo->user = info->st_uid; + finfo->group = info->st_gid; + finfo->size = info->st_size; + finfo->inode = info->st_ino; + finfo->device = info->st_dev; + finfo->nlink = info->st_nlink; + apr_time_ansi_put(&finfo->atime, info->st_atime.tv_sec); + apr_time_ansi_put(&finfo->mtime, info->st_mtime.tv_sec); + apr_time_ansi_put(&finfo->ctime, info->st_ctime.tv_sec); + /* ### needs to be revisited + * if (wanted & APR_FINFO_CSIZE) { + * finfo->csize = info->st_blocks * 512; + * finfo->valid |= APR_FINFO_CSIZE; + * } + */ +} + +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile) +{ + struct stat info; + + if (thefile->buffered) { + apr_status_t rv = apr_file_flush(thefile); + if (rv != APR_SUCCESS) + return rv; + } + + if (fstat(thefile->filedes, &info) == 0) { + finfo->pool = thefile->pool; + finfo->fname = thefile->fname; + fill_out_finfo(finfo, &info, wanted); + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, + apr_fileperms_t perms) +{ + mode_t mode = apr_unix_perms2mode(perms); + + if (chmod(fname, mode) == -1) + return errno; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + /* Don't do anything if we can't handle the requested attributes */ + if (!(attr_mask & (APR_FILE_ATTR_READONLY + | APR_FILE_ATTR_EXECUTABLE))) + return APR_SUCCESS; + + status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool); + if (status) + return status; + + /* ### TODO: should added bits be umask'd? */ + if (attr_mask & APR_FILE_ATTR_READONLY) + { + if (attributes & APR_FILE_ATTR_READONLY) + { + finfo.protection &= ~APR_UWRITE; + finfo.protection &= ~APR_GWRITE; + finfo.protection &= ~APR_WWRITE; + } + else + { + /* ### umask this! */ + finfo.protection |= APR_UWRITE; + finfo.protection |= APR_GWRITE; + finfo.protection |= APR_WWRITE; + } + } + + if (attr_mask & APR_FILE_ATTR_EXECUTABLE) + { + if (attributes & APR_FILE_ATTR_EXECUTABLE) + { + /* ### umask this! */ + finfo.protection |= APR_UEXECUTE; + finfo.protection |= APR_GEXECUTE; + finfo.protection |= APR_WEXECUTE; + } + else + { + finfo.protection &= ~APR_UEXECUTE; + finfo.protection &= ~APR_GEXECUTE; + finfo.protection &= ~APR_WEXECUTE; + } + } + + return apr_file_perms_set(fname, finfo.protection); +} + +#ifndef APR_HAS_PSA +static apr_status_t stat_cache_cleanup(void *data) +{ + apr_pool_t *p = (apr_pool_t *)getGlobalPool(); + apr_hash_index_t *hi; + apr_hash_t *statCache = (apr_hash_t*)data; + char *key; + apr_ssize_t keylen; + NXPathCtx_t pathctx; + + for (hi = apr_hash_first(p, statCache); hi; hi = apr_hash_next(hi)) { + apr_hash_this(hi, (const void**)&key, &keylen, (void**)&pathctx); + + if (pathctx) { + NXFreePathContext(pathctx); + } + } + + return APR_SUCCESS; +} + +int cstat (NXPathCtx_t ctx, char *path, struct stat *buf, unsigned long requestmap, apr_pool_t *p) +{ + apr_pool_t *gPool = (apr_pool_t *)getGlobalPool(); + apr_hash_t *statCache = NULL; + apr_thread_rwlock_t *rwlock = NULL; + + NXPathCtx_t pathctx = 0; + char *ptr = NULL, *tr; + int len = 0, x; + char *ppath; + char *pinfo; + + if (ctx == 1) { + + /* If there isn't a global pool then just stat the file + and return */ + if (!gPool) { + char poolname[50]; + + if (apr_pool_create(&gPool, NULL) != APR_SUCCESS) { + return getstat(ctx, path, buf, requestmap); + } + + setGlobalPool(gPool); + apr_pool_tag(gPool, apr_pstrdup(gPool, "cstat_mem_pool")); + + statCache = apr_hash_make(gPool); + apr_pool_userdata_set ((void*)statCache, "STAT_CACHE", stat_cache_cleanup, gPool); + + apr_thread_rwlock_create(&rwlock, gPool); + apr_pool_userdata_set ((void*)rwlock, "STAT_CACHE_LOCK", apr_pool_cleanup_null, gPool); + } + else { + apr_pool_userdata_get((void**)&statCache, "STAT_CACHE", gPool); + apr_pool_userdata_get((void**)&rwlock, "STAT_CACHE_LOCK", gPool); + } + + if (!gPool || !statCache || !rwlock) { + return getstat(ctx, path, buf, requestmap); + } + + for (x = 0,tr = path;*tr != '\0';tr++,x++) { + if (*tr == '\\' || *tr == '/') { + ptr = tr; + len = x; + } + if (*tr == ':') { + ptr = "\\"; + len = x; + } + } + + if (ptr) { + ppath = apr_pstrndup (p, path, len); + strlwr(ppath); + if (ptr[1] != '\0') { + ptr++; + } + /* If the path ended in a trailing slash then our result path + will be a single slash. To avoid stat'ing the root with a + slash, we need to make sure we stat the current directory + with a dot */ + if (((*ptr == '/') || (*ptr == '\\')) && (*(ptr+1) == '\0')) { + pinfo = apr_pstrdup (p, "."); + } + else { + pinfo = apr_pstrdup (p, ptr); + } + } + + /* If we have a statCache then try to pull the information + from the cache. Otherwise just stat the file and return.*/ + if (statCache) { + apr_thread_rwlock_rdlock(rwlock); + pathctx = (NXPathCtx_t) apr_hash_get(statCache, ppath, APR_HASH_KEY_STRING); + apr_thread_rwlock_unlock(rwlock); + if (pathctx) { + return getstat(pathctx, pinfo, buf, requestmap); + } + else { + int err; + + err = NXCreatePathContext(0, ppath, 0, NULL, &pathctx); + if (!err) { + apr_thread_rwlock_wrlock(rwlock); + apr_hash_set(statCache, apr_pstrdup(gPool,ppath) , APR_HASH_KEY_STRING, (void*)pathctx); + apr_thread_rwlock_unlock(rwlock); + return getstat(pathctx, pinfo, buf, requestmap); + } + } + } + } + return getstat(ctx, path, buf, requestmap); +} +#endif + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, + const char *fname, + apr_int32_t wanted, apr_pool_t *pool) +{ + struct stat info; + int srv; + NXPathCtx_t pathCtx = 0; + + getcwdpath(NULL, &pathCtx, CTX_ACTUAL_CWD); +#ifdef APR_HAS_PSA + srv = getstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT); +#else + srv = cstat(pathCtx, (char*)fname, &info, ST_STAT_BITS|ST_NAME_BIT, pool); +#endif + errno = srv; + + if (srv == 0) { + finfo->pool = pool; + finfo->fname = fname; + fill_out_finfo(finfo, &info, wanted); + if (wanted & APR_FINFO_LINK) + wanted &= ~APR_FINFO_LINK; + if (wanted & APR_FINFO_NAME) { + finfo->name = apr_pstrdup(pool, info.st_name); + finfo->valid |= APR_FINFO_NAME; + } + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { +#if !defined(ENOENT) || !defined(ENOTDIR) +#error ENOENT || ENOTDIR not defined; please see the +#error comments at this line in the source for a workaround. + /* + * If ENOENT || ENOTDIR is not defined in one of the your OS's + * include files, APR cannot report a good reason why the stat() + * of the file failed; there are cases where it can fail even though + * the file exists. This opens holes in Apache, for example, because + * it becomes possible for someone to get a directory listing of a + * directory even though there is an index (eg. index.html) file in + * it. If you do not have a problem with this, delete the above + * #error lines and start the compile again. If you need to do this, + * please submit a bug report to http://www.apache.org/bug_report.html + * letting us know that you needed to do this. Please be sure to + * include the operating system you are using. + */ + /* WARNING: All errors will be handled as not found + */ +#if !defined(ENOENT) + return APR_ENOENT; +#else + /* WARNING: All errors but not found will be handled as not directory + */ + if (errno != ENOENT) + return APR_ENOENT; + else + return errno; +#endif +#else /* All was defined well, report the usual: */ + return errno; +#endif + } +} + +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool); + if (status) { + return status; + } + +#ifdef HAVE_UTIMES + { + struct timeval tvp[2]; + + tvp[0].tv_sec = apr_time_sec(finfo.atime); + tvp[0].tv_usec = apr_time_usec(finfo.atime); + tvp[1].tv_sec = apr_time_sec(mtime); + tvp[1].tv_usec = apr_time_usec(mtime); + + if (utimes(fname, tvp) == -1) { + return errno; + } + } +#elif defined(HAVE_UTIME) + { + struct utimbuf buf; + + buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC); + buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC); + + if (utime(fname, &buf) == -1) { + return errno; + } + } +#else + return APR_ENOTIMPL; +#endif + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/netware/filesys.c b/srclib/apr/file_io/netware/filesys.c new file mode 100644 index 0000000000..5009764421 --- /dev/null +++ b/srclib/apr/file_io/netware/filesys.c @@ -0,0 +1,106 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" + +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p) +{ +/* See the Windows code to figure out what to do here. + It probably checks to make sure that the root exists + and case it correctly according to the file system. +*/ + *rootpath = apr_pstrdup(p, root); + return APR_SUCCESS; +} + +apr_status_t filepath_has_drive(const char *rootpath, int only, apr_pool_t *p) +{ + char *s; + + if (rootpath) { + s = strchr (rootpath, ':'); + if (only) + /* Test if the path only has a drive/volume and nothing else + */ + return (s && (s != rootpath) && !s[1]); + else + /* Test if the path includes a drive/volume + */ + return (s && (s != rootpath)); + } + return 0; +} + +apr_status_t filepath_compare_drive(const char *path1, const char *path2, apr_pool_t *p) +{ + char *s1, *s2; + + if (path1 && path2) { + s1 = strchr (path1, ':'); + s2 = strchr (path2, ':'); + + /* Make sure that they both have a drive/volume delimiter + and are the same size. Then see if they match. + */ + if (s1 && s2 && ((s1-path1) == (s2-path2))) { + return strnicmp (s1, s2, s1-path1); + } + } + return -1; +} + +APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; + char *ptr; + + /* use getcwdpath to make sure that we get the volume name*/ + if (!getcwdpath(path, NULL, 0)) { + if (errno == ERANGE) + return APR_ENAMETOOLONG; + else + return errno; + } + /* Strip off the server name if there is one*/ + ptr = strpbrk(path, "\\/:"); + if (!ptr) { + return APR_ENOENT; + } + if (*ptr == ':') { + ptr = path; + } + *rootpath = apr_pstrdup(p, ptr); + if (!(flags & APR_FILEPATH_NATIVE)) { + for (ptr = *rootpath; *ptr; ++ptr) { + if (*ptr == '\\') + *ptr = '/'; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath, + apr_pool_t *p) +{ + if (chdir2(rootpath) != 0) + return errno; + return APR_SUCCESS; +} + + diff --git a/srclib/apr/file_io/netware/flock.c b/srclib/apr/file_io/netware/flock.c new file mode 100644 index 0000000000..bd4beb037c --- /dev/null +++ b/srclib/apr/file_io/netware/flock.c @@ -0,0 +1,39 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "apr_arch_file_io.h" + + +apr_status_t apr_file_lock(apr_file_t *thefile, int type) +{ + int fc; + + fc = (type & APR_FLOCK_NONBLOCK) ? NX_RANGE_LOCK_TRYLOCK : NX_RANGE_LOCK_CHECK; + + if(NXFileRangeLock(thefile->filedes,fc, 0, 0) == -1) + return errno; + + return APR_SUCCESS; +} + +apr_status_t apr_file_unlock(apr_file_t *thefile) +{ + if(NXFileRangeUnlock(thefile->filedes,NX_RANGE_LOCK_CANCEL,0 , 0) == -1) + return errno; + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/netware/mktemp.c b/srclib/apr/file_io/netware/mktemp.c new file mode 100644 index 0000000000..f1568bdd64 --- /dev/null +++ b/srclib/apr/file_io/netware/mktemp.c @@ -0,0 +1,50 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_strings.h" /* prototype of apr_mkstemp() */ +#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_portable.h" /* for apr_os_file_put() */ + +#include /* for mkstemp() - Single Unix */ + +APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_int32_t flags, apr_pool_t *p) +{ + int fd; + apr_status_t rv; + + flags = (!flags) ? APR_CREATE | APR_READ | APR_WRITE | + APR_DELONCLOSE : flags & ~APR_EXCL; + + fd = mkstemp(template); + if (fd == -1) { + return errno; + } + /* We need to reopen the file to get rid of the o_excl flag. + * Otherwise file locking will not allow the file to be shared. + */ + close(fd); + if ((rv = apr_file_open(fp, template, flags|APR_FILE_NOCLEANUP, + APR_UREAD | APR_UWRITE, p)) == APR_SUCCESS) { + + apr_pool_cleanup_register((*fp)->pool, (void *)(*fp), + apr_unix_file_cleanup, apr_unix_file_cleanup); + } + + return rv; +} + diff --git a/srclib/apr/file_io/netware/pipe.c b/srclib/apr/file_io/netware/pipe.c new file mode 100644 index 0000000000..2763bd97f5 --- /dev/null +++ b/srclib/apr/file_io/netware/pipe.c @@ -0,0 +1,187 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_inherit.h" + +static apr_status_t pipeblock(apr_file_t *thepipe) +{ +#ifdef USE_FLAGS + int err; + unsigned long flags; + + if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1) + { + flags &= ~FNDELAY; + fcntl(thepipe->filedes, F_SETFL, flags); + } +#else + errno = 0; + fcntl(thepipe->filedes, F_SETFL, 0); +#endif + + if (errno) + return errno; + + thepipe->blocking = BLK_ON; + return APR_SUCCESS; +} + +static apr_status_t pipenonblock(apr_file_t *thepipe) +{ +#ifdef USE_FLAGS + int err; + unsigned long flags; + + errno = 0; + if (fcntl(thepipe->filedes, F_GETFL, &flags) != -1) + { + flags |= FNDELAY; + fcntl(thepipe->filedes, F_SETFL, flags); + } +#else + errno = 0; + fcntl(thepipe->filedes, F_SETFL, FNDELAY); +#endif + + if (errno) + return errno; + + thepipe->blocking = BLK_OFF; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout) +{ + if (thepipe->is_pipe == 1) { + thepipe->timeout = timeout; + if (timeout >= 0) { + if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */ + return pipenonblock(thepipe); + } + } + else { + if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */ + return pipeblock(thepipe); + } + } + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout) +{ + if (thepipe->is_pipe == 1) { + *timeout = thepipe->timeout; + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *pool) +{ + int *dafile = thefile; + + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->eof_hit = 0; + (*file)->is_pipe = 1; + (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */ + (*file)->timeout = -1; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->filedes = *dafile; + if (!register_cleanup) { + (*file)->flags = APR_FILE_NOCLEANUP; + } + (*file)->buffered = 0; +#if APR_HAS_THREADS + (*file)->thlock = NULL; +#endif + if (register_cleanup) { + apr_pool_cleanup_register((*file)->pool, (void *)(*file), + apr_unix_file_cleanup, + apr_pool_cleanup_null); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *pool) +{ + return apr_os_pipe_put_ex(file, thefile, 0, pool); +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool) +{ + int filedes[2]; + int err; + + if (pipe(filedes) == -1) { + return errno; + } + + (*in) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*out) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + + (*in)->pool = + (*out)->pool = pool; + (*in)->filedes = filedes[0]; + (*out)->filedes = filedes[1]; + (*in)->flags = APR_INHERIT; + (*out)->flags = APR_INHERIT; + (*in)->is_pipe = + (*out)->is_pipe = 1; + (*out)->fname = + (*in)->fname = NULL; + (*in)->buffered = + (*out)->buffered = 0; + (*in)->blocking = + (*out)->blocking = BLK_ON; + (*in)->timeout = + (*out)->timeout = -1; + (*in)->ungetchar = -1; + (*in)->thlock = + (*out)->thlock = NULL; + (void) apr_pollset_create(&(*in)->pollset, 1, pool, 0); + (void) apr_pollset_create(&(*out)->pollset, 1, pool, 0); + + apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup, + apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + + + diff --git a/srclib/apr/file_io/os2/copy.c b/srclib/apr/file_io/os2/copy.c new file mode 100644 index 0000000000..f4ce010f8f --- /dev/null +++ b/srclib/apr/file_io/os2/copy.c @@ -0,0 +1 @@ +#include "../unix/copy.c" diff --git a/srclib/apr/file_io/os2/dir.c b/srclib/apr/file_io/os2/dir.c new file mode 100644 index 0000000000..8a140248d8 --- /dev/null +++ b/srclib/apr/file_io/os2/dir.c @@ -0,0 +1,167 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include + +static apr_status_t dir_cleanup(void *thedir) +{ + apr_dir_t *dir = thedir; + return apr_dir_close(dir); +} + + + +APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, apr_pool_t *pool) +{ + apr_dir_t *thedir = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t)); + + if (thedir == NULL) + return APR_ENOMEM; + + thedir->pool = pool; + thedir->dirname = apr_pstrdup(pool, dirname); + + if (thedir->dirname == NULL) + return APR_ENOMEM; + + thedir->handle = 0; + thedir->validentry = FALSE; + *new = thedir; + apr_pool_cleanup_register(pool, thedir, dir_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir) +{ + int rv = 0; + + if (thedir->handle) { + rv = DosFindClose(thedir->handle); + + if (rv == 0) { + thedir->handle = 0; + } + } + + return APR_FROM_OS_ERROR(rv); +} + + + +APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir) +{ + int rv; + ULONG entries = 1; + + if (thedir->handle == 0) { + thedir->handle = HDIR_CREATE; + rv = DosFindFirst(apr_pstrcat(thedir->pool, thedir->dirname, "/*", NULL), &thedir->handle, + FILE_ARCHIVED|FILE_DIRECTORY|FILE_SYSTEM|FILE_HIDDEN|FILE_READONLY, + &thedir->entry, sizeof(thedir->entry), &entries, FIL_STANDARD); + } else { + rv = DosFindNext(thedir->handle, &thedir->entry, sizeof(thedir->entry), &entries); + } + + finfo->pool = thedir->pool; + finfo->fname = NULL; + finfo->valid = 0; + + if (rv == 0 && entries == 1) { + thedir->validentry = TRUE; + + /* We passed a name off the stack that has popped */ + finfo->fname = NULL; + finfo->size = thedir->entry.cbFile; + finfo->csize = thedir->entry.cbFileAlloc; + + /* Only directories & regular files show up in directory listings */ + finfo->filetype = (thedir->entry.attrFile & FILE_DIRECTORY) ? APR_DIR : APR_REG; + + apr_os2_time_to_apr_time(&finfo->mtime, thedir->entry.fdateLastWrite, + thedir->entry.ftimeLastWrite); + apr_os2_time_to_apr_time(&finfo->atime, thedir->entry.fdateLastAccess, + thedir->entry.ftimeLastAccess); + apr_os2_time_to_apr_time(&finfo->ctime, thedir->entry.fdateCreation, + thedir->entry.ftimeCreation); + + finfo->name = thedir->entry.achName; + finfo->valid = APR_FINFO_NAME | APR_FINFO_MTIME | APR_FINFO_ATIME | + APR_FINFO_CTIME | APR_FINFO_TYPE | APR_FINFO_SIZE | + APR_FINFO_CSIZE; + + return APR_SUCCESS; + } + + thedir->validentry = FALSE; + + if (rv) + return APR_FROM_OS_ERROR(rv); + + return APR_ENOENT; +} + + + +APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir) +{ + return apr_dir_close(thedir); +} + + + +APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, apr_pool_t *pool) +{ + return APR_FROM_OS_ERROR(DosCreateDir(path, NULL)); +} + + + +APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool) +{ + return APR_FROM_OS_ERROR(DosDeleteDir(path)); +} + + + +APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir) +{ + if (dir == NULL) { + return APR_ENODIR; + } + *thedir = &dir->handle; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir, + apr_pool_t *pool) +{ + if ((*dir) == NULL) { + (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t)); + (*dir)->pool = pool; + } + (*dir)->handle = *thedir; + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/os2/dir_make_recurse.c b/srclib/apr/file_io/os2/dir_make_recurse.c new file mode 100644 index 0000000000..9cde1a987d --- /dev/null +++ b/srclib/apr/file_io/os2/dir_make_recurse.c @@ -0,0 +1,86 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include + +#define IS_SEP(c) (c == '/' || c == '\\') + +/* Remove trailing separators that don't affect the meaning of PATH. */ +static const char *path_canonicalize(const char *path, apr_pool_t *pool) +{ + /* At some point this could eliminate redundant components. For + * now, it just makes sure there is no trailing slash. */ + apr_size_t len = strlen(path); + apr_size_t orig_len = len; + + while ((len > 0) && IS_SEP(path[len - 1])) { + len--; + } + + if (len != orig_len) { + return apr_pstrndup(pool, path, len); + } + else { + return path; + } +} + + + +/* Remove one component off the end of PATH. */ +static char *path_remove_last_component(const char *path, apr_pool_t *pool) +{ + const char *newpath = path_canonicalize(path, pool); + int i; + + for (i = strlen(newpath) - 1; i >= 0; i--) { + if (IS_SEP(path[i])) { + break; + } + } + + return apr_pstrndup(pool, path, (i < 0) ? 0 : i); +} + + + +apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_status_t apr_err = APR_SUCCESS; + + apr_err = apr_dir_make(path, perm, pool); /* Try to make PATH right out */ + + if (APR_STATUS_IS_EEXIST(apr_err)) { /* It's OK if PATH exists */ + return APR_SUCCESS; + } + + if (APR_STATUS_IS_ENOENT(apr_err)) { /* Missing an intermediate dir */ + char *dir; + + dir = path_remove_last_component(path, pool); + apr_err = apr_dir_make_recursive(dir, perm, pool); + + if (!apr_err) { + apr_err = apr_dir_make(path, perm, pool); + } + } + + return apr_err; +} diff --git a/srclib/apr/file_io/os2/fileacc.c b/srclib/apr/file_io/os2/fileacc.c new file mode 100644 index 0000000000..0b0c26d24a --- /dev/null +++ b/srclib/apr/file_io/os2/fileacc.c @@ -0,0 +1,18 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../unix/fileacc.c" + diff --git a/srclib/apr/file_io/os2/filedup.c b/srclib/apr/file_io/os2/filedup.c new file mode 100644 index 0000000000..d592033a0f --- /dev/null +++ b/srclib/apr/file_io/os2/filedup.c @@ -0,0 +1,125 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include +#include "apr_arch_inherit.h" + +static apr_status_t file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p) +{ + int rv; + apr_file_t *dup_file; + + if (*new_file == NULL) { + dup_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t)); + + if (dup_file == NULL) { + return APR_ENOMEM; + } + + dup_file->filedes = -1; + } else { + dup_file = *new_file; + } + + dup_file->pool = p; + rv = DosDupHandle(old_file->filedes, &dup_file->filedes); + + if (rv) { + return APR_FROM_OS_ERROR(rv); + } + + dup_file->fname = apr_pstrdup(dup_file->pool, old_file->fname); + dup_file->buffered = old_file->buffered; + dup_file->isopen = old_file->isopen; + dup_file->flags = old_file->flags & ~APR_INHERIT; + /* TODO - dup pipes correctly */ + dup_file->pipe = old_file->pipe; + + if (*new_file == NULL) { + apr_pool_cleanup_register(dup_file->pool, dup_file, apr_file_cleanup, + apr_pool_cleanup_null); + *new_file = dup_file; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, apr_file_t *old_file, apr_pool_t *p) +{ + if (*new_file) { + apr_file_close(*new_file); + (*new_file)->filedes = -1; + } + + return file_dup(new_file, old_file, p); +} + + + +APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, apr_file_t *old_file, apr_pool_t *p) +{ + return file_dup(&new_file, old_file, p); +} + + + +APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p) +{ + *new_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t)); + memcpy(*new_file, old_file, sizeof(apr_file_t)); + (*new_file)->pool = p; + + if (old_file->buffered) { + (*new_file)->buffer = apr_palloc(p, APR_FILE_BUFSIZE); + + if (old_file->direction == 1) { + memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos); + } + else { + memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead); + } + + if (old_file->mutex) { + apr_thread_mutex_create(&((*new_file)->mutex), + APR_THREAD_MUTEX_DEFAULT, p); + apr_thread_mutex_destroy(old_file->mutex); + } + } + + if (old_file->fname) { + (*new_file)->fname = apr_pstrdup(p, old_file->fname); + } + + if (!(old_file->flags & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register(p, (void *)(*new_file), + apr_file_cleanup, + apr_file_cleanup); + } + + old_file->filedes = -1; + apr_pool_cleanup_kill(old_file->pool, (void *)old_file, + apr_file_cleanup); + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/os2/filepath.c b/srclib/apr/file_io/os2/filepath.c new file mode 100644 index 0000000000..827a6551d5 --- /dev/null +++ b/srclib/apr/file_io/os2/filepath.c @@ -0,0 +1,16 @@ +/* Copyright 2004-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "../win32/filepath.c" diff --git a/srclib/apr/file_io/os2/filepath_util.c b/srclib/apr/file_io/os2/filepath_util.c new file mode 100644 index 0000000000..a89c173e54 --- /dev/null +++ b/srclib/apr/file_io/os2/filepath_util.c @@ -0,0 +1 @@ +#include "../unix/filepath_util.c" diff --git a/srclib/apr/file_io/os2/filestat.c b/srclib/apr/file_io/os2/filestat.c new file mode 100644 index 0000000000..0414c7150c --- /dev/null +++ b/srclib/apr/file_io/os2/filestat.c @@ -0,0 +1,229 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOS +#define INCL_DOSERRORS +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include +#include "apr_strings.h" + + +static void FS3_to_finfo(apr_finfo_t *finfo, FILESTATUS3 *fstatus) +{ + finfo->protection = (fstatus->attrFile & FILE_READONLY) ? 0x555 : 0x777; + + if (fstatus->attrFile & FILE_DIRECTORY) + finfo->filetype = APR_DIR; + else + finfo->filetype = APR_REG; + /* XXX: No other possible types from FS3? */ + + finfo->user = 0; + finfo->group = 0; + finfo->inode = 0; + finfo->device = 0; + finfo->size = fstatus->cbFile; + finfo->csize = fstatus->cbFileAlloc; + apr_os2_time_to_apr_time(&finfo->atime, fstatus->fdateLastAccess, + fstatus->ftimeLastAccess ); + apr_os2_time_to_apr_time(&finfo->mtime, fstatus->fdateLastWrite, + fstatus->ftimeLastWrite ); + apr_os2_time_to_apr_time(&finfo->ctime, fstatus->fdateCreation, + fstatus->ftimeCreation ); + finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT | APR_FINFO_SIZE + | APR_FINFO_CSIZE | APR_FINFO_MTIME + | APR_FINFO_CTIME | APR_FINFO_ATIME | APR_FINFO_LINK; +} + + + +static apr_status_t handle_type(apr_filetype_e *ftype, HFILE file) +{ + ULONG filetype, fileattr, rc; + + rc = DosQueryHType(file, &filetype, &fileattr); + + if (rc == 0) { + switch (filetype & 0xff) { + case 0: + *ftype = APR_REG; + break; + + case 1: + *ftype = APR_CHR; + break; + + case 2: + *ftype = APR_PIPE; + break; + + default: + /* Brian, is this correct??? + */ + *ftype = APR_UNKFILE; + break; + } + + return APR_SUCCESS; + } + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted, + apr_file_t *thefile) +{ + ULONG rc; + FILESTATUS3 fstatus; + + if (thefile->isopen) { + if (thefile->buffered) { + apr_status_t rv = apr_file_flush(thefile); + + if (rv != APR_SUCCESS) { + return rv; + } + } + + rc = DosQueryFileInfo(thefile->filedes, FIL_STANDARD, &fstatus, sizeof(fstatus)); + } + else + rc = DosQueryPathInfo(thefile->fname, FIL_STANDARD, &fstatus, sizeof(fstatus)); + + if (rc == 0) { + FS3_to_finfo(finfo, &fstatus); + finfo->fname = thefile->fname; + + if (finfo->filetype == APR_REG) { + if (thefile->isopen) { + return handle_type(&finfo->filetype, thefile->filedes); + } + } else { + return APR_SUCCESS; + } + } + + finfo->protection = 0; + finfo->filetype = APR_NOFILE; + return APR_FROM_OS_ERROR(rc); +} + +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, apr_fileperms_t perms) +{ + return APR_ENOTIMPL; +} + + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *cont) +{ + ULONG rc; + FILESTATUS3 fstatus; + + finfo->protection = 0; + finfo->filetype = APR_NOFILE; + finfo->name = NULL; + rc = DosQueryPathInfo(fname, FIL_STANDARD, &fstatus, sizeof(fstatus)); + + if (rc == 0) { + FS3_to_finfo(finfo, &fstatus); + finfo->fname = fname; + + if (wanted & APR_FINFO_NAME) { + ULONG count = 1; + HDIR hDir = HDIR_SYSTEM; + FILEFINDBUF3 ffb; + rc = DosFindFirst(fname, &hDir, + FILE_DIRECTORY|FILE_HIDDEN|FILE_SYSTEM|FILE_ARCHIVED, + &ffb, sizeof(ffb), &count, FIL_STANDARD); + if (rc == 0 && count == 1) { + finfo->name = apr_pstrdup(cont, ffb.achName); + finfo->valid |= APR_FINFO_NAME; + } + } + } else if (rc == ERROR_INVALID_ACCESS) { + memset(finfo, 0, sizeof(apr_finfo_t)); + finfo->valid = APR_FINFO_TYPE | APR_FINFO_PROT; + finfo->protection = 0666; + finfo->filetype = APR_CHR; + + if (wanted & APR_FINFO_NAME) { + finfo->name = apr_pstrdup(cont, fname); + finfo->valid |= APR_FINFO_NAME; + } + } else { + return APR_FROM_OS_ERROR(rc); + } + + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *cont) +{ + FILESTATUS3 fs3; + ULONG rc; + + /* Don't do anything if we can't handle the requested attributes */ + if (!(attr_mask & (APR_FILE_ATTR_READONLY + | APR_FILE_ATTR_HIDDEN))) + return APR_SUCCESS; + + rc = DosQueryPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3)); + if (rc == 0) { + ULONG old_attr = fs3.attrFile; + + if (attr_mask & APR_FILE_ATTR_READONLY) + { + if (attributes & APR_FILE_ATTR_READONLY) { + fs3.attrFile |= FILE_READONLY; + } else { + fs3.attrFile &= ~FILE_READONLY; + } + } + + if (attr_mask & APR_FILE_ATTR_HIDDEN) + { + if (attributes & APR_FILE_ATTR_HIDDEN) { + fs3.attrFile |= FILE_HIDDEN; + } else { + fs3.attrFile &= ~FILE_HIDDEN; + } + } + + if (fs3.attrFile != old_attr) { + rc = DosSetPathInfo(fname, FIL_STANDARD, &fs3, sizeof(fs3), 0); + } + } + + return APR_FROM_OS_ERROR(rc); +} + + +/* ### Somebody please write this! */ +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/file_io/os2/filesys.c b/srclib/apr/file_io/os2/filesys.c new file mode 100644 index 0000000000..cf3b832988 --- /dev/null +++ b/srclib/apr/file_io/os2/filesys.c @@ -0,0 +1,148 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include + +/* OS/2 Exceptions: + * + * Note that trailing spaces and trailing periods are never recorded + * in the file system. + * + * Leading spaces and periods are accepted, however. + * The * ? < > codes all have wildcard side effects + * The " / \ : are exclusively component separator tokens + * The system doesn't accept | for any (known) purpose + * Oddly, \x7f _is_ acceptable ;) + */ + +const char c_is_fnchar[256] = +{/* Reject all ctrl codes... */ + 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, + /* " * / : < > ? */ + 1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,1,0,1,0,0, + /* \ */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1, + /* | */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1, + /* High bit codes are accepted */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + + +#define IS_SLASH(c) (c == '/' || c == '\\') + + +apr_status_t filepath_root_test(char *path, apr_pool_t *p) +{ + char drive = apr_toupper(path[0]); + + if (drive >= 'A' && drive <= 'Z' && path[1] == ':' && IS_SLASH(path[2])) + return APR_SUCCESS; + + return APR_EBADPATH; +} + + +apr_status_t filepath_drive_get(char **rootpath, char drive, + apr_int32_t flags, apr_pool_t *p) +{ + char path[APR_PATH_MAX]; + char *pos; + ULONG rc; + ULONG bufsize = sizeof(path) - 3; + + path[0] = drive; + path[1] = ':'; + path[2] = '/'; + + rc = DosQueryCurrentDir(apr_toupper(drive) - 'A', path+3, &bufsize); + + if (rc) { + return APR_FROM_OS_ERROR(rc); + } + + if (!(flags & APR_FILEPATH_NATIVE)) { + for (pos=path; *pos; pos++) { + if (*pos == '\\') + *pos = '/'; + } + } + + *rootpath = apr_pstrdup(p, path); + return APR_SUCCESS; +} + + +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p) +{ + if (root[0] && apr_islower(root[0]) && root[1] == ':') { + *rootpath = apr_pstrdup(p, root); + (*rootpath)[0] = apr_toupper((*rootpath)[0]); + } + else { + *rootpath = root; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; + ULONG drive; + ULONG drivemap; + ULONG rv, pathlen = sizeof(path) - 3; + char *pos; + + DosQueryCurrentDisk(&drive, &drivemap); + path[0] = '@' + drive; + strcpy(path+1, ":\\"); + rv = DosQueryCurrentDir(drive, path+3, &pathlen); + + *defpath = apr_pstrdup(p, path); + + if (!(flags & APR_FILEPATH_NATIVE)) { + for (pos=*defpath; *pos; pos++) { + if (*pos == '\\') + *pos = '/'; + } + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p) +{ + ULONG rv = 0; + + if (path[1] == ':') + rv = DosSetDefaultDisk(apr_toupper(path[0]) - '@'); + + if (rv == 0) + rv = DosSetCurrentDir(path); + + return APR_FROM_OS_ERROR(rv); +} diff --git a/srclib/apr/file_io/os2/flock.c b/srclib/apr/file_io/os2/flock.c new file mode 100644 index 0000000000..4c5e54d93f --- /dev/null +++ b/srclib/apr/file_io/os2/flock.c @@ -0,0 +1,37 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" + +APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type) +{ + FILELOCK lockrange = { 0, 0x7fffffff }; + ULONG rc; + + rc = DosSetFileLocks(thefile->filedes, NULL, &lockrange, + (type & APR_FLOCK_NONBLOCK) ? 0 : (ULONG)-1, + (type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED); + return APR_FROM_OS_ERROR(rc); +} + +APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile) +{ + FILELOCK unlockrange = { 0, 0x7fffffff }; + ULONG rc; + + rc = DosSetFileLocks(thefile->filedes, &unlockrange, NULL, 0, 0); + return APR_FROM_OS_ERROR(rc); +} diff --git a/srclib/apr/file_io/os2/fullrw.c b/srclib/apr/file_io/os2/fullrw.c new file mode 100644 index 0000000000..cf6294882b --- /dev/null +++ b/srclib/apr/file_io/os2/fullrw.c @@ -0,0 +1 @@ +#include "../unix/fullrw.c" diff --git a/srclib/apr/file_io/os2/maperrorcode.c b/srclib/apr/file_io/os2/maperrorcode.c new file mode 100644 index 0000000000..2ea84bb4d5 --- /dev/null +++ b/srclib/apr/file_io/os2/maperrorcode.c @@ -0,0 +1,95 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOSERRORS +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include +#include +#include "apr_errno.h" + +static int errormap[][2] = { + { NO_ERROR, APR_SUCCESS }, + { ERROR_FILE_NOT_FOUND, APR_ENOENT }, + { ERROR_PATH_NOT_FOUND, APR_ENOENT }, + { ERROR_TOO_MANY_OPEN_FILES, APR_EMFILE }, + { ERROR_ACCESS_DENIED, APR_EACCES }, + { ERROR_SHARING_VIOLATION, APR_EACCES }, + { ERROR_INVALID_PARAMETER, APR_EINVAL }, + { ERROR_OPEN_FAILED, APR_ENOENT }, + { ERROR_DISK_FULL, APR_ENOSPC }, + { ERROR_FILENAME_EXCED_RANGE, APR_ENAMETOOLONG }, + { ERROR_INVALID_FUNCTION, APR_EINVAL }, + { ERROR_INVALID_HANDLE, APR_EBADF }, + { ERROR_NEGATIVE_SEEK, APR_ESPIPE }, + { ERROR_NO_SIGNAL_SENT, ESRCH }, + { ERROR_NO_DATA, APR_EAGAIN }, + { SOCEINTR, EINTR }, + { SOCEWOULDBLOCK, EWOULDBLOCK }, + { SOCEINPROGRESS, EINPROGRESS }, + { SOCEALREADY, EALREADY }, + { SOCENOTSOCK, ENOTSOCK }, + { SOCEDESTADDRREQ, EDESTADDRREQ }, + { SOCEMSGSIZE, EMSGSIZE }, + { SOCEPROTOTYPE, EPROTOTYPE }, + { SOCENOPROTOOPT, ENOPROTOOPT }, + { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, + { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, + { SOCEOPNOTSUPP, EOPNOTSUPP }, + { SOCEPFNOSUPPORT, EPFNOSUPPORT }, + { SOCEAFNOSUPPORT, EAFNOSUPPORT }, + { SOCEADDRINUSE, EADDRINUSE }, + { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, + { SOCENETDOWN, ENETDOWN }, + { SOCENETUNREACH, ENETUNREACH }, + { SOCENETRESET, ENETRESET }, + { SOCECONNABORTED, ECONNABORTED }, + { SOCECONNRESET, ECONNRESET }, + { SOCENOBUFS, ENOBUFS }, + { SOCEISCONN, EISCONN }, + { SOCENOTCONN, ENOTCONN }, + { SOCESHUTDOWN, ESHUTDOWN }, + { SOCETOOMANYREFS, ETOOMANYREFS }, + { SOCETIMEDOUT, ETIMEDOUT }, + { SOCECONNREFUSED, ECONNREFUSED }, + { SOCELOOP, ELOOP }, + { SOCENAMETOOLONG, ENAMETOOLONG }, + { SOCEHOSTDOWN, EHOSTDOWN }, + { SOCEHOSTUNREACH, EHOSTUNREACH }, + { SOCENOTEMPTY, ENOTEMPTY }, + { SOCEPIPE, EPIPE } +}; + +#define MAPSIZE (sizeof(errormap)/sizeof(errormap[0])) + +int apr_canonical_error(apr_status_t err) +{ + int rv = -1, index; + + if (err < APR_OS_START_SYSERR) + return err; + + err -= APR_OS_START_SYSERR; + + for (index=0; index + +apr_status_t apr_file_cleanup(void *thefile) +{ + apr_file_t *file = thefile; + return apr_file_close(file); +} + + + +APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, apr_int32_t flag, apr_fileperms_t perm, apr_pool_t *pool) +{ + int oflags = 0; + int mflags = OPEN_FLAGS_FAIL_ON_ERROR|OPEN_SHARE_DENYNONE; + int rv; + ULONG action; + apr_file_t *dafile = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t)); + + dafile->pool = pool; + dafile->isopen = FALSE; + dafile->eof_hit = FALSE; + dafile->buffer = NULL; + dafile->flags = flag; + dafile->blocking = BLK_ON; + + if ((flag & APR_READ) && (flag & APR_WRITE)) { + mflags |= OPEN_ACCESS_READWRITE; + } else if (flag & APR_READ) { + mflags |= OPEN_ACCESS_READONLY; + } else if (flag & APR_WRITE) { + mflags |= OPEN_ACCESS_WRITEONLY; + } else { + dafile->filedes = -1; + return APR_EACCES; + } + + dafile->buffered = (flag & APR_BUFFERED) > 0; + + if (dafile->buffered) { + dafile->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + rv = apr_thread_mutex_create(&dafile->mutex, 0, pool); + + if (rv) + return rv; + } + + if (flag & APR_CREATE) { + oflags |= OPEN_ACTION_CREATE_IF_NEW; + + if (!(flag & APR_EXCL) && !(flag & APR_TRUNCATE)) { + oflags |= OPEN_ACTION_OPEN_IF_EXISTS; + } + } + + if ((flag & APR_EXCL) && !(flag & APR_CREATE)) + return APR_EACCES; + + if (flag & APR_TRUNCATE) { + oflags |= OPEN_ACTION_REPLACE_IF_EXISTS; + } else if ((oflags & 0xFF) == 0) { + oflags |= OPEN_ACTION_OPEN_IF_EXISTS; + } + + rv = DosOpen(fname, &(dafile->filedes), &action, 0, 0, oflags, mflags, NULL); + + if (rv == 0 && (flag & APR_APPEND)) { + ULONG newptr; + rv = DosSetFilePtr(dafile->filedes, 0, FILE_END, &newptr ); + + if (rv) + DosClose(dafile->filedes); + } + + if (rv != 0) + return APR_FROM_OS_ERROR(rv); + + dafile->isopen = TRUE; + dafile->fname = apr_pstrdup(pool, fname); + dafile->filePtr = 0; + dafile->bufpos = 0; + dafile->dataRead = 0; + dafile->direction = 0; + dafile->pipe = FALSE; + + if (!(flag & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register(dafile->pool, dafile, apr_file_cleanup, apr_file_cleanup); + } + + *new = dafile; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file) +{ + ULONG rc; + apr_status_t status; + + if (file && file->isopen) { + apr_file_flush(file); + rc = DosClose(file->filedes); + + if (rc == 0) { + file->isopen = FALSE; + status = APR_SUCCESS; + + if (file->flags & APR_DELONCLOSE) { + status = APR_FROM_OS_ERROR(DosDelete(file->fname)); + } + } else { + return APR_FROM_OS_ERROR(rc); + } + } + + if (file->buffered) + apr_thread_mutex_destroy(file->mutex); + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool) +{ + ULONG rc = DosDelete(path); + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, const char *to_path, + apr_pool_t *p) +{ + ULONG rc = DosMove(from_path, to_path); + + if (rc == ERROR_ACCESS_DENIED) { + rc = DosDelete(to_path); + + if (rc == 0 || rc == ERROR_FILE_NOT_FOUND) { + rc = DosMove(from_path, to_path); + } + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, apr_file_t *file) +{ + *thefile = file->filedes; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, apr_os_file_t *thefile, apr_int32_t flags, apr_pool_t *pool) +{ + apr_os_file_t *dafile = thefile; + + (*file) = apr_palloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->filedes = *dafile; + (*file)->isopen = TRUE; + (*file)->eof_hit = FALSE; + (*file)->flags = flags; + (*file)->pipe = FALSE; + (*file)->buffered = (flags & APR_BUFFERED) > 0; + + if ((*file)->buffered) { + apr_status_t rv; + + (*file)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + rv = apr_thread_mutex_create(&(*file)->mutex, 0, pool); + + if (rv) + return rv; + } + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr) +{ + if (!fptr->isopen || fptr->eof_hit == 1) { + return APR_EOF; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool) +{ + apr_os_file_t fd = 2; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + + + +APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool) +{ + apr_os_file_t fd = 1; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + + +APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool) +{ + apr_os_file_t fd = 0; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + +APR_POOL_IMPLEMENT_ACCESSOR(file); + +APR_IMPLEMENT_INHERIT_SET(file, flags, pool, apr_file_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, apr_file_cleanup) + diff --git a/srclib/apr/file_io/os2/pipe.c b/srclib/apr/file_io/os2/pipe.c new file mode 100644 index 0000000000..1e18946848 --- /dev/null +++ b/srclib/apr/file_io/os2/pipe.c @@ -0,0 +1,177 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOSERRORS +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include +#include + +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool) +{ + ULONG filedes[2]; + ULONG rc, action; + static int id = 0; + char pipename[50]; + + sprintf(pipename, "/pipe/%d.%d", getpid(), id++); + rc = DosCreateNPipe(pipename, filedes, NP_ACCESS_INBOUND, NP_NOWAIT|1, 4096, 4096, 0); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + rc = DosConnectNPipe(filedes[0]); + + if (rc && rc != ERROR_PIPE_NOT_CONNECTED) { + DosClose(filedes[0]); + return APR_FROM_OS_ERROR(rc); + } + + rc = DosOpen (pipename, filedes+1, &action, 0, FILE_NORMAL, + OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, + OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE, + NULL); + + if (rc) { + DosClose(filedes[0]); + return APR_FROM_OS_ERROR(rc); + } + + (*in) = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t)); + rc = DosCreateEventSem(NULL, &(*in)->pipeSem, DC_SEM_SHARED, FALSE); + + if (rc) { + DosClose(filedes[0]); + DosClose(filedes[1]); + return APR_FROM_OS_ERROR(rc); + } + + rc = DosSetNPipeSem(filedes[0], (HSEM)(*in)->pipeSem, 1); + + if (!rc) { + rc = DosSetNPHState(filedes[0], NP_WAIT); + } + + if (rc) { + DosClose(filedes[0]); + DosClose(filedes[1]); + DosCloseEventSem((*in)->pipeSem); + return APR_FROM_OS_ERROR(rc); + } + + (*in)->pool = pool; + (*in)->filedes = filedes[0]; + (*in)->fname = apr_pstrdup(pool, pipename); + (*in)->isopen = TRUE; + (*in)->buffered = FALSE; + (*in)->flags = 0; + (*in)->pipe = 1; + (*in)->timeout = -1; + (*in)->blocking = BLK_ON; + apr_pool_cleanup_register(pool, *in, apr_file_cleanup, apr_pool_cleanup_null); + + (*out) = (apr_file_t *)apr_palloc(pool, sizeof(apr_file_t)); + (*out)->pool = pool; + (*out)->filedes = filedes[1]; + (*out)->fname = apr_pstrdup(pool, pipename); + (*out)->isopen = TRUE; + (*out)->buffered = FALSE; + (*out)->flags = 0; + (*out)->pipe = 1; + (*out)->timeout = -1; + (*out)->blocking = BLK_ON; + apr_pool_cleanup_register(pool, *out, apr_file_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, apr_fileperms_t perm, apr_pool_t *pool) +{ + /* Not yet implemented, interface not suitable */ + return APR_ENOTIMPL; +} + + + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout) +{ + if (thepipe->pipe == 1) { + thepipe->timeout = timeout; + + if (thepipe->timeout >= 0) { + if (thepipe->blocking != BLK_OFF) { + thepipe->blocking = BLK_OFF; + return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_NOWAIT)); + } + } + else if (thepipe->timeout == -1) { + if (thepipe->blocking != BLK_ON) { + thepipe->blocking = BLK_ON; + return APR_FROM_OS_ERROR(DosSetNPHState(thepipe->filedes, NP_WAIT)); + } + } + } + return APR_EINVAL; +} + + + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout) +{ + if (thepipe->pipe == 1) { + *timeout = thepipe->timeout; + return APR_SUCCESS; + } + return APR_EINVAL; +} + + + +APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *pool) +{ + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->isopen = TRUE; + (*file)->pipe = 1; + (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */ + (*file)->timeout = -1; + (*file)->filedes = *thefile; + + if (register_cleanup) { + apr_pool_cleanup_register(pool, *file, apr_file_cleanup, + apr_pool_cleanup_null); + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *pool) +{ + return apr_os_pipe_put_ex(file, thefile, 0, pool); +} diff --git a/srclib/apr/file_io/os2/readwrite.c b/srclib/apr/file_io/os2/readwrite.c new file mode 100644 index 0000000000..81f50f9784 --- /dev/null +++ b/srclib/apr/file_io/os2/readwrite.c @@ -0,0 +1,360 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOS +#define INCL_DOSERRORS + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include "apr_strings.h" + +#include + +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) +{ + ULONG rc = 0; + ULONG bytesread; + + if (!thefile->isopen) { + *nbytes = 0; + return APR_EBADF; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + ULONG blocksize; + ULONG size = *nbytes; + + apr_thread_mutex_lock(thefile->mutex); + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = 0; + thefile->direction = 0; + thefile->dataRead = 0; + } + + while (rc == 0 && size > 0) { + if (thefile->bufpos >= thefile->dataRead) { + ULONG bytesread; + rc = DosRead(thefile->filedes, thefile->buffer, + APR_FILE_BUFSIZE, &bytesread); + + if (bytesread == 0) { + if (rc == 0) + thefile->eof_hit = TRUE; + break; + } + + thefile->dataRead = bytesread; + thefile->filePtr += thefile->dataRead; + thefile->bufpos = 0; + } + + blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size; + memcpy(pos, thefile->buffer + thefile->bufpos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + *nbytes = rc == 0 ? pos - (char *)buf : 0; + apr_thread_mutex_unlock(thefile->mutex); + + if (*nbytes == 0 && rc == 0 && thefile->eof_hit) { + return APR_EOF; + } + + return APR_FROM_OS_ERROR(rc); + } else { + if (thefile->pipe) + DosResetEventSem(thefile->pipeSem, &rc); + + rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread); + + if (rc == ERROR_NO_DATA && thefile->timeout != 0) { + int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT); + + if (rcwait == 0) { + rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread); + } + else if (rcwait == ERROR_TIMEOUT) { + *nbytes = 0; + return APR_TIMEUP; + } + } + + if (rc) { + *nbytes = 0; + return APR_FROM_OS_ERROR(rc); + } + + *nbytes = bytesread; + + if (bytesread == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + + return APR_SUCCESS; + } +} + + + +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) +{ + ULONG rc = 0; + ULONG byteswritten; + + if (!thefile->isopen) { + *nbytes = 0; + return APR_EBADF; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + int blocksize; + int size = *nbytes; + + apr_thread_mutex_lock(thefile->mutex); + + if ( thefile->direction == 0 ) { + // Position file pointer for writing at the offset we are logically reading from + ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + if (offset != thefile->filePtr) + DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr ); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 1; + } + + while (rc == 0 && size > 0) { + if (thefile->bufpos == APR_FILE_BUFSIZE) // write buffer is full + rc = apr_file_flush(thefile); + + blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size; + memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + apr_thread_mutex_unlock(thefile->mutex); + return APR_FROM_OS_ERROR(rc); + } else { + if (thefile->flags & APR_APPEND) { + FILELOCK all = { 0, 0x7fffffff }; + ULONG newpos; + rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0); + + if (rc == 0) { + rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos); + + if (rc == 0) { + rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); + } + + DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0); + } + } else { + rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); + } + + if (rc) { + *nbytes = 0; + return APR_FROM_OS_ERROR(rc); + } + + *nbytes = byteswritten; + return APR_SUCCESS; + } +} + + + +#ifdef HAVE_WRITEV + +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes) +{ + int bytes; + if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { + *nbytes = 0; + return errno; + } + else { + *nbytes = bytes; + return APR_SUCCESS; + } +} +#endif + + + +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) +{ + ULONG rc; + ULONG byteswritten; + + if (!thefile->isopen) { + return APR_EBADF; + } + + rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten); + + if (rc) { + return APR_FROM_OS_ERROR(rc); + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) +{ + apr_off_t offset = -1; + return apr_file_seek(thefile, APR_CUR, &offset); +} + + +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) +{ + ULONG rc; + apr_size_t bytesread; + + if (!thefile->isopen) { + return APR_EBADF; + } + + bytesread = 1; + rc = apr_file_read(thefile, ch, &bytesread); + + if (rc) { + return rc; + } + + if (bytesread == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) +{ + apr_size_t len; + + len = strlen(str); + return apr_file_write(thefile, str, &len); +} + + +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) +{ + if (thefile->buffered) { + ULONG written = 0; + int rc = 0; + + if (thefile->direction == 1 && thefile->bufpos) { + rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written); + thefile->filePtr += written; + + if (rc == 0) + thefile->bufpos = 0; + } + + return APR_FROM_OS_ERROR(rc); + } else { + /* There isn't anything to do if we aren't buffering the output + * so just return success. + */ + return APR_SUCCESS; + } +} + + +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) +{ + apr_size_t readlen; + apr_status_t rv = APR_SUCCESS; + int i; + + for (i = 0; i < len-1; i++) { + readlen = 1; + rv = apr_file_read(thefile, str+i, &readlen); + + if (readlen != 1) { + rv = APR_EOF; + break; + } + + if (str[i] == '\n') { + i++; + break; + } + } + str[i] = 0; + if (i > 0) { + /* we stored chars; don't report EOF or any other errors; + * the app will find out about that on the next call + */ + return APR_SUCCESS; + } + return rv; +} + + + +APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, + const char *format, ...) +{ + int cc; + va_list ap; + char *buf; + int len; + + buf = malloc(HUGE_STRING_LEN); + if (buf == NULL) { + return 0; + } + va_start(ap, format); + len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap); + cc = apr_file_puts(buf, fptr); + va_end(ap); + free(buf); + return (cc == APR_SUCCESS) ? len : -1; +} + + + +apr_status_t apr_file_check_read(apr_file_t *fd) +{ + int rc; + + if (!fd->pipe) + return APR_SUCCESS; /* Not a pipe, assume no waiting */ + + rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN); + + if (rc == ERROR_TIMEOUT) + return APR_TIMEUP; + + return APR_FROM_OS_ERROR(rc); +} diff --git a/srclib/apr/file_io/os2/seek.c b/srclib/apr/file_io/os2/seek.c new file mode 100644 index 0000000000..40b02a8156 --- /dev/null +++ b/srclib/apr/file_io/os2/seek.c @@ -0,0 +1,114 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include +#include + + +static apr_status_t setptr(apr_file_t *thefile, unsigned long pos ) +{ + long newbufpos; + ULONG rc; + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = thefile->direction = thefile->dataRead = 0; + } + + newbufpos = pos - (thefile->filePtr - thefile->dataRead); + if (newbufpos >= 0 && newbufpos <= thefile->dataRead) { + thefile->bufpos = newbufpos; + rc = 0; + } else { + rc = DosSetFilePtr(thefile->filedes, pos, FILE_BEGIN, &thefile->filePtr ); + + if ( !rc ) + thefile->bufpos = thefile->dataRead = 0; + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset) +{ + if (!thefile->isopen) { + return APR_EBADF; + } + + thefile->eof_hit = 0; + + if (thefile->buffered) { + int rc = EINVAL; + apr_finfo_t finfo; + + switch (where) { + case APR_SET: + rc = setptr(thefile, *offset); + break; + + case APR_CUR: + rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset); + break; + + case APR_END: + rc = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile); + if (rc == APR_SUCCESS) + rc = setptr(thefile, finfo.size + *offset); + break; + } + + *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + return rc; + } else { + switch (where) { + case APR_SET: + where = FILE_BEGIN; + break; + + case APR_CUR: + where = FILE_CURRENT; + break; + + case APR_END: + where = FILE_END; + break; + } + + return APR_FROM_OS_ERROR(DosSetFilePtr(thefile->filedes, *offset, where, (ULONG *)offset)); + } +} + + + +APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *fp, apr_off_t offset) +{ + int rc = DosSetFileSize(fp->filedes, offset); + + if (rc != 0) { + return APR_FROM_OS_ERROR(rc); + } + + if (fp->buffered) { + return setptr(fp, offset); + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/os2/tempdir.c b/srclib/apr/file_io/os2/tempdir.c new file mode 100644 index 0000000000..6823569f29 --- /dev/null +++ b/srclib/apr/file_io/os2/tempdir.c @@ -0,0 +1 @@ +#include "../unix/tempdir.c" diff --git a/srclib/apr/file_io/unix/copy.c b/srclib/apr/file_io/unix/copy.c new file mode 100644 index 0000000000..8ee0f590a4 --- /dev/null +++ b/srclib/apr/file_io/unix/copy.c @@ -0,0 +1,112 @@ +/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" + +static apr_status_t apr_file_transfer_contents(const char *from_path, + const char *to_path, + apr_int32_t flags, + apr_fileperms_t to_perms, + apr_pool_t *pool) +{ + apr_file_t *s, *d; + apr_status_t status; + apr_finfo_t finfo; + apr_fileperms_t perms; + + /* Open source file. */ + status = apr_file_open(&s, from_path, APR_READ, APR_OS_DEFAULT, pool); + if (status) + return status; + + /* Maybe get its permissions. */ + if (to_perms == APR_FILE_SOURCE_PERMS) { + status = apr_file_info_get(&finfo, APR_FINFO_PROT, s); + if (status != APR_SUCCESS && status != APR_INCOMPLETE) { + apr_file_close(s); /* toss any error */ + return status; + } + perms = finfo.protection; + } + else + perms = to_perms; + + /* Open dest file. */ + status = apr_file_open(&d, to_path, flags, perms, pool); + if (status) { + apr_file_close(s); /* toss any error */ + return status; + } + + /* Copy bytes till the cows come home. */ + while (1) { + char buf[BUFSIZ]; + apr_size_t bytes_this_time = sizeof(buf); + apr_status_t read_err; + apr_status_t write_err; + + /* Read 'em. */ + read_err = apr_file_read(s, buf, &bytes_this_time); + if (read_err && !APR_STATUS_IS_EOF(read_err)) { + apr_file_close(s); /* toss any error */ + apr_file_close(d); /* toss any error */ + return read_err; + } + + /* Write 'em. */ + write_err = apr_file_write_full(d, buf, bytes_this_time, NULL); + if (write_err) { + apr_file_close(s); /* toss any error */ + apr_file_close(d); /* toss any error */ + return write_err; + } + + if (read_err && APR_STATUS_IS_EOF(read_err)) { + status = apr_file_close(s); + if (status) { + apr_file_close(d); /* toss any error */ + return status; + } + + /* return the results of this close: an error, or success */ + return apr_file_close(d); + } + } + /* NOTREACHED */ +} + +APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool) +{ + return apr_file_transfer_contents(from_path, to_path, + (APR_WRITE | APR_CREATE | APR_TRUNCATE), + perms, + pool); +} + +APR_DECLARE(apr_status_t) apr_file_append(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool) +{ + return apr_file_transfer_contents(from_path, to_path, + (APR_WRITE | APR_CREATE | APR_APPEND), + perms, + pool); +} diff --git a/srclib/apr/file_io/unix/dir.c b/srclib/apr/file_io/unix/dir.c new file mode 100644 index 0000000000..590380f2e2 --- /dev/null +++ b/srclib/apr/file_io/unix/dir.c @@ -0,0 +1,318 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#if APR_HAVE_SYS_SYSLIMITS_H +#include +#endif +#if APR_HAVE_LIMITS_H +#include +#endif + +static apr_status_t dir_cleanup(void *thedir) +{ + apr_dir_t *dir = thedir; + if (closedir(dir->dirstruct) == 0) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +#define PATH_SEPARATOR '/' + +/* Remove trailing separators that don't affect the meaning of PATH. */ +static const char *path_canonicalize (const char *path, apr_pool_t *pool) +{ + /* At some point this could eliminate redundant components. For + * now, it just makes sure there is no trailing slash. */ + apr_size_t len = strlen (path); + apr_size_t orig_len = len; + + while ((len > 0) && (path[len - 1] == PATH_SEPARATOR)) + len--; + + if (len != orig_len) + return apr_pstrndup (pool, path, len); + else + return path; +} + +/* Remove one component off the end of PATH. */ +static char *path_remove_last_component (const char *path, apr_pool_t *pool) +{ + const char *newpath = path_canonicalize (path, pool); + int i; + + for (i = (strlen(newpath) - 1); i >= 0; i--) { + if (path[i] == PATH_SEPARATOR) + break; + } + + return apr_pstrndup (pool, path, (i < 0) ? 0 : i); +} + +apr_status_t apr_dir_open(apr_dir_t **new, const char *dirname, + apr_pool_t *pool) +{ + /* On some platforms (e.g., Linux+GNU libc), d_name[] in struct + * dirent is declared with enough storage for the name. On other + * platforms (e.g., Solaris 8 for Intel), d_name is declared as a + * one-byte array. Note: gcc evaluates this at compile time. + */ + apr_size_t dirent_size = + (sizeof((*new)->entry->d_name) > 1 ? + sizeof(struct dirent) : sizeof (struct dirent) + 255); + + (*new) = (apr_dir_t *)apr_palloc(pool, sizeof(apr_dir_t)); + + (*new)->pool = pool; + (*new)->dirname = apr_pstrdup(pool, dirname); + (*new)->dirstruct = opendir(dirname); + (*new)->entry = apr_pcalloc(pool, dirent_size); + + if ((*new)->dirstruct == NULL) { + return errno; + } + else { + apr_pool_cleanup_register((*new)->pool, (void *)(*new), dir_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; + } +} + +apr_status_t apr_dir_close(apr_dir_t *thedir) +{ + return apr_pool_cleanup_run(thedir->pool, thedir, dir_cleanup); +} + +#ifdef DIRENT_TYPE +static apr_filetype_e filetype_from_dirent_type(int type) +{ + switch (type) { + case DT_REG: + return APR_REG; + case DT_DIR: + return APR_DIR; + case DT_LNK: + return APR_LNK; + case DT_CHR: + return APR_CHR; + case DT_BLK: + return APR_BLK; +#if defined(DT_FIFO) + case DT_FIFO: + return APR_PIPE; +#endif +#if !defined(BEOS) && defined(DT_SOCK) + case DT_SOCK: + return APR_SOCK; +#endif + default: + return APR_UNKFILE; + } +} +#endif + +apr_status_t apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir) +{ + apr_status_t ret = 0; +#ifdef DIRENT_TYPE + apr_filetype_e type; +#endif +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) \ + && !defined(READDIR_IS_THREAD_SAFE) + struct dirent *retent; + + ret = readdir_r(thedir->dirstruct, thedir->entry, &retent); + + /* Avoid the Linux problem where at end-of-directory thedir->entry + * is set to NULL, but ret = APR_SUCCESS. + */ + if(!ret && thedir->entry != retent) + ret = APR_ENOENT; + + /* Solaris is a bit strange, if there are no more entries in the + * directory, it returns EINVAL. Since this is against POSIX, we + * hack around the problem here. EINVAL is possible from other + * readdir implementations, but only if the result buffer is too small. + * since we control the size of that buffer, we should never have + * that problem. + */ + if (ret == EINVAL) { + ret = ENOENT; + } +#else + /* We're about to call a non-thread-safe readdir() that may + possibly set `errno', and the logic below actually cares about + errno after the call. Therefore we need to clear errno first. */ + errno = 0; + thedir->entry = readdir(thedir->dirstruct); + if (thedir->entry == NULL) { + /* If NULL was returned, this can NEVER be a success. Can it?! */ + if (errno == APR_SUCCESS) { + ret = APR_ENOENT; + } + else + ret = errno; + } +#endif + + /* No valid bit flag to test here - do we want one? */ + finfo->fname = NULL; + + if (ret) { + finfo->valid = 0; + return ret; + } + +#ifdef DIRENT_TYPE + type = filetype_from_dirent_type(thedir->entry->DIRENT_TYPE); + if (type != APR_UNKFILE) { + wanted &= ~APR_FINFO_TYPE; + } +#endif +#ifdef DIRENT_INODE + if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) { + wanted &= ~APR_FINFO_INODE; + } +#endif + + wanted &= ~APR_FINFO_NAME; + + if (wanted) + { + char fspec[APR_PATH_MAX]; + int off; + apr_cpystrn(fspec, thedir->dirname, sizeof(fspec)); + off = strlen(fspec); + if ((fspec[off - 1] != '/') && (off + 1 < sizeof(fspec))) + fspec[off++] = '/'; + apr_cpystrn(fspec + off, thedir->entry->d_name, sizeof(fspec) - off); + ret = apr_stat(finfo, fspec, APR_FINFO_LINK | wanted, thedir->pool); + /* We passed a stack name that will disappear */ + finfo->fname = NULL; + } + + if (wanted && (ret == APR_SUCCESS || ret == APR_INCOMPLETE)) { + wanted &= ~finfo->valid; + } + else { + /* We don't bail because we fail to stat, when we are only -required- + * to readdir... but the result will be APR_INCOMPLETE + */ + finfo->pool = thedir->pool; + finfo->valid = 0; +#ifdef DIRENT_TYPE + if (type != APR_UNKFILE) { + finfo->filetype = type; + finfo->valid |= APR_FINFO_TYPE; + } +#endif +#ifdef DIRENT_INODE + if (thedir->entry->DIRENT_INODE && thedir->entry->DIRENT_INODE != -1) { + finfo->inode = thedir->entry->DIRENT_INODE; + finfo->valid |= APR_FINFO_INODE; + } +#endif + } + + finfo->name = apr_pstrdup(thedir->pool, thedir->entry->d_name); + finfo->valid |= APR_FINFO_NAME; + + if (wanted) + return APR_INCOMPLETE; + + return APR_SUCCESS; +} + +apr_status_t apr_dir_rewind(apr_dir_t *thedir) +{ + rewinddir(thedir->dirstruct); + return APR_SUCCESS; +} + +apr_status_t apr_dir_make(const char *path, apr_fileperms_t perm, + apr_pool_t *pool) +{ + mode_t mode = apr_unix_perms2mode(perm); + + if (mkdir(path, mode) == 0) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +apr_status_t apr_dir_make_recursive(const char *path, apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_status_t apr_err = 0; + + apr_err = apr_dir_make (path, perm, pool); /* Try to make PATH right out */ + + if (apr_err == EEXIST) /* It's OK if PATH exists */ + return APR_SUCCESS; + + if (apr_err == ENOENT) { /* Missing an intermediate dir */ + char *dir; + + dir = path_remove_last_component(path, pool); + apr_err = apr_dir_make_recursive(dir, perm, pool); + + if (!apr_err) + apr_err = apr_dir_make (path, perm, pool); + } + + return apr_err; +} + +apr_status_t apr_dir_remove(const char *path, apr_pool_t *pool) +{ + if (rmdir(path) == 0) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +apr_status_t apr_os_dir_get(apr_os_dir_t **thedir, apr_dir_t *dir) +{ + if (dir == NULL) { + return APR_ENODIR; + } + *thedir = dir->dirstruct; + return APR_SUCCESS; +} + +apr_status_t apr_os_dir_put(apr_dir_t **dir, apr_os_dir_t *thedir, + apr_pool_t *pool) +{ + if ((*dir) == NULL) { + (*dir) = (apr_dir_t *)apr_pcalloc(pool, sizeof(apr_dir_t)); + (*dir)->pool = pool; + } + (*dir)->dirstruct = thedir; + return APR_SUCCESS; +} + + diff --git a/srclib/apr/file_io/unix/fileacc.c b/srclib/apr/file_io/unix/fileacc.c new file mode 100644 index 0000000000..542d90db87 --- /dev/null +++ b/srclib/apr/file_io/unix/fileacc.c @@ -0,0 +1,119 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_arch_file_io.h" + +/* A file to put ALL of the accessor functions for apr_file_t types. */ + +APR_DECLARE(apr_status_t) apr_file_name_get(const char **fname, + apr_file_t *thefile) +{ + *fname = thefile->fname; + return APR_SUCCESS; +} + +APR_DECLARE(apr_int32_t) apr_file_flags_get(apr_file_t *f) +{ + return f->flags; +} + +#if !defined(OS2) && !defined(WIN32) +mode_t apr_unix_perms2mode(apr_fileperms_t perms) +{ + mode_t mode = 0; + + if (perms & APR_USETID) + mode |= S_ISUID; + if (perms & APR_UREAD) + mode |= S_IRUSR; + if (perms & APR_UWRITE) + mode |= S_IWUSR; + if (perms & APR_UEXECUTE) + mode |= S_IXUSR; + + if (perms & APR_GSETID) + mode |= S_ISGID; + if (perms & APR_GREAD) + mode |= S_IRGRP; + if (perms & APR_GWRITE) + mode |= S_IWGRP; + if (perms & APR_GEXECUTE) + mode |= S_IXGRP; + +#ifdef S_ISVTX + if (perms & APR_WSTICKY) + mode |= S_ISVTX; +#endif + if (perms & APR_WREAD) + mode |= S_IROTH; + if (perms & APR_WWRITE) + mode |= S_IWOTH; + if (perms & APR_WEXECUTE) + mode |= S_IXOTH; + + return mode; +} + +apr_fileperms_t apr_unix_mode2perms(mode_t mode) +{ + apr_fileperms_t perms = 0; + + if (mode & S_ISUID) + perms |= APR_USETID; + if (mode & S_IRUSR) + perms |= APR_UREAD; + if (mode & S_IWUSR) + perms |= APR_UWRITE; + if (mode & S_IXUSR) + perms |= APR_UEXECUTE; + + if (mode & S_ISGID) + perms |= APR_GSETID; + if (mode & S_IRGRP) + perms |= APR_GREAD; + if (mode & S_IWGRP) + perms |= APR_GWRITE; + if (mode & S_IXGRP) + perms |= APR_GEXECUTE; + +#ifdef S_ISVTX + if (mode & S_ISVTX) + perms |= APR_WSTICKY; +#endif + if (mode & S_IROTH) + perms |= APR_WREAD; + if (mode & S_IWOTH) + perms |= APR_WWRITE; + if (mode & S_IXOTH) + perms |= APR_WEXECUTE; + + return perms; +} +#endif + +APR_DECLARE(apr_status_t) apr_file_data_get(void **data, const char *key, + apr_file_t *file) +{ + return apr_pool_userdata_get(data, key, file->pool); +} + +APR_DECLARE(apr_status_t) apr_file_data_set(apr_file_t *file, void *data, + const char *key, + apr_status_t (*cleanup)(void *)) +{ + return apr_pool_userdata_set(data, key, cleanup, file->pool); +} diff --git a/srclib/apr/file_io/unix/filedup.c b/srclib/apr/file_io/unix/filedup.c new file mode 100644 index 0000000000..fe792258ea --- /dev/null +++ b/srclib/apr/file_io/unix/filedup.c @@ -0,0 +1,158 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_thread_mutex.h" +#include "apr_arch_inherit.h" + +static apr_status_t file_dup(apr_file_t **new_file, + apr_file_t *old_file, apr_pool_t *p, + int which_dup) +{ + int rv; + + if (which_dup == 2) { + if ((*new_file) == NULL) { + /* We can't dup2 unless we have a valid new_file */ + return APR_EINVAL; + } + rv = dup2(old_file->filedes, (*new_file)->filedes); + } else { + rv = dup(old_file->filedes); + } + + if (rv == -1) + return errno; + + if (which_dup == 1) { + (*new_file) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t)); + (*new_file)->pool = p; + (*new_file)->filedes = rv; + } + + (*new_file)->fname = apr_pstrdup(p, old_file->fname); + (*new_file)->buffered = old_file->buffered; + + /* If the existing socket in a dup2 is already buffered, we + * have an existing and valid (hopefully) mutex, so we don't + * want to create it again as we could leak! + */ +#if APR_HAS_THREADS + if ((*new_file)->buffered && !(*new_file)->thlock && old_file->thlock) { + apr_thread_mutex_create(&((*new_file)->thlock), + APR_THREAD_MUTEX_DEFAULT, p); + } +#endif + /* As above, only create the buffer if we haven't already + * got one. + */ + if ((*new_file)->buffered && !(*new_file)->buffer) { + (*new_file)->buffer = apr_palloc(p, APR_FILE_BUFSIZE); + } + + /* this is the way dup() works */ + (*new_file)->blocking = old_file->blocking; + + /* make sure unget behavior is consistent */ + (*new_file)->ungetchar = old_file->ungetchar; + + /* apr_file_dup2() retains the original cleanup, reflecting + * the existing inherit and nocleanup flags. This means, + * that apr_file_dup2() cannot be called against an apr_file_t + * already closed with apr_file_close, because the expected + * cleanup was already killed. + */ + if (which_dup == 2) { + return APR_SUCCESS; + } + + /* apr_file_dup() retains all old_file flags with the exceptions + * of APR_INHERIT and APR_FILE_NOCLEANUP. + * The user must call apr_file_inherit_set() on the dupped + * apr_file_t when desired. + */ + (*new_file)->flags = old_file->flags + & ~(APR_INHERIT | APR_FILE_NOCLEANUP); + + apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file), + apr_unix_file_cleanup, + apr_unix_file_cleanup); +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0); +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, + apr_file_t *old_file, apr_pool_t *p) +{ + return file_dup(new_file, old_file, p, 1); +} + +APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, + apr_file_t *old_file, apr_pool_t *p) +{ + return file_dup(&new_file, old_file, p, 2); +} + +APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p) +{ + *new_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t)); + memcpy(*new_file, old_file, sizeof(apr_file_t)); + (*new_file)->pool = p; + if (old_file->buffered) { + (*new_file)->buffer = apr_palloc(p, APR_FILE_BUFSIZE); + if (old_file->direction == 1) { + memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos); + } + else { + memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead); + } +#if APR_HAS_THREADS + if (old_file->thlock) { + apr_thread_mutex_create(&((*new_file)->thlock), + APR_THREAD_MUTEX_DEFAULT, p); + apr_thread_mutex_destroy(old_file->thlock); + } +#endif /* APR_HAS_THREADS */ + } + if (old_file->fname) { + (*new_file)->fname = apr_pstrdup(p, old_file->fname); + } + if (!(old_file->flags & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register(p, (void *)(*new_file), + apr_unix_file_cleanup, + ((*new_file)->flags & APR_INHERIT) + ? apr_pool_cleanup_null + : apr_unix_file_cleanup); + } + + old_file->filedes = -1; + apr_pool_cleanup_kill(old_file->pool, (void *)old_file, + apr_unix_file_cleanup); +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0); +#endif + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/unix/filepath.c b/srclib/apr/file_io/unix/filepath.c new file mode 100644 index 0000000000..fd0b6a2500 --- /dev/null +++ b/srclib/apr/file_io/unix/filepath.c @@ -0,0 +1,309 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_strings.h" +#define APR_WANT_STRFUNC +#include "apr_want.h" +#if APR_HAVE_UNISTD_H +#include +#endif + +/* Win32 malpropism that can go away once everyone believes this + * code is golden, and I'm not testing it anymore :-) + */ +#if APR_HAVE_DIRENT_H +#include +#endif + +/* Any OS that requires/refuses trailing slashes should be dealt with here. + */ +APR_DECLARE(apr_status_t) apr_filepath_get(char **defpath, apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; + + if (!getcwd(path, sizeof(path))) { + if (errno == ERANGE) + return APR_ENAMETOOLONG; + else + return errno; + } + *defpath = apr_pstrdup(p, path); + + return APR_SUCCESS; +} + + +/* Any OS that requires/refuses trailing slashes should be dealt with here + */ +APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p) +{ + if (chdir(path) != 0) + return errno; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, + const char **inpath, + apr_int32_t flags, + apr_pool_t *p) +{ + if (**inpath == '/') { + *rootpath = apr_pstrdup(p, "/"); + do { + ++(*inpath); + } while (**inpath == '/'); + + return APR_SUCCESS; + } + + return APR_ERELATIVE; +} + +APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, + const char *rootpath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p) +{ + char *path; + apr_size_t rootlen; /* is the length of the src rootpath */ + apr_size_t maxlen; /* maximum total path length */ + apr_size_t keptlen; /* is the length of the retained rootpath */ + apr_size_t pathlen; /* is the length of the result path */ + apr_size_t seglen; /* is the end of the current segment */ + apr_status_t rv; + + /* Treat null as an empty path. + */ + if (!addpath) + addpath = ""; + + if (addpath[0] == '/') { + /* If addpath is rooted, then rootpath is unused. + * Ths violates any APR_FILEPATH_SECUREROOTTEST and + * APR_FILEPATH_NOTABSOLUTE flags specified. + */ + if (flags & APR_FILEPATH_SECUREROOTTEST) + return APR_EABOVEROOT; + if (flags & APR_FILEPATH_NOTABSOLUTE) + return APR_EABSOLUTE; + + /* If APR_FILEPATH_NOTABOVEROOT wasn't specified, + * we won't test the root again, it's ignored. + * Waste no CPU retrieving the working path. + */ + if (!rootpath && !(flags & APR_FILEPATH_NOTABOVEROOT)) + rootpath = ""; + } + else { + /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller + * requires a relative result. If the rootpath is + * ommitted, we do not retrieve the working path, + * if rootpath was supplied as absolute then fail. + */ + if (flags & APR_FILEPATH_NOTABSOLUTE) { + if (!rootpath) + rootpath = ""; + else if (rootpath[0] == '/') + return APR_EABSOLUTE; + } + } + + if (!rootpath) { + /* Start with the current working path. This is bass akwards, + * but required since the compiler (at least vc) doesn't like + * passing the address of a char const* for a char** arg. + */ + char *getpath; + rv = apr_filepath_get(&getpath, flags, p); + rootpath = getpath; + if (rv != APR_SUCCESS) + return errno; + + /* XXX: Any kernel subject to goofy, uncanonical results + * must run the rootpath against the user's given flags. + * Simplest would be a recursive call to apr_filepath_merge + * with an empty (not null) rootpath and addpath of the cwd. + */ + } + + rootlen = strlen(rootpath); + maxlen = rootlen + strlen(addpath) + 4; /* 4 for slashes at start, after + * root, and at end, plus trailing + * null */ + if (maxlen > APR_PATH_MAX) { + return APR_ENAMETOOLONG; + } + path = (char *)apr_palloc(p, maxlen); + + if (addpath[0] == '/') { + /* Ignore the given root path, strip off leading + * '/'s to a single leading '/' from the addpath, + * and leave addpath at the first non-'/' character. + */ + keptlen = 0; + while (addpath[0] == '/') + ++addpath; + path[0] = '/'; + pathlen = 1; + } + else { + /* If both paths are relative, fail early + */ + if (rootpath[0] != '/' && (flags & APR_FILEPATH_NOTRELATIVE)) + return APR_ERELATIVE; + + /* Base the result path on the rootpath + */ + keptlen = rootlen; + memcpy(path, rootpath, rootlen); + + /* Always '/' terminate the given root path + */ + if (keptlen && path[keptlen - 1] != '/') { + path[keptlen++] = '/'; + } + pathlen = keptlen; + } + + while (*addpath) { + /* Parse each segment, find the closing '/' + */ + const char *next = addpath; + while (*next && (*next != '/')) { + ++next; + } + seglen = next - addpath; + + if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) { + /* noop segment (/ or ./) so skip it + */ + } + else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') { + /* backpath (../) */ + if (pathlen == 1 && path[0] == '/') { + /* Attempt to move above root. Always die if the + * APR_FILEPATH_SECUREROOTTEST flag is specified. + */ + if (flags & APR_FILEPATH_SECUREROOTTEST) { + return APR_EABOVEROOT; + } + + /* Otherwise this is simply a noop, above root is root. + * Flag that rootpath was entirely replaced. + */ + keptlen = 0; + } + else if (pathlen == 0 + || (pathlen == 3 + && !memcmp(path + pathlen - 3, "../", 3)) + || (pathlen > 3 + && !memcmp(path + pathlen - 4, "/../", 4))) { + /* Path is already backpathed or empty, if the + * APR_FILEPATH_SECUREROOTTEST.was given die now. + */ + if (flags & APR_FILEPATH_SECUREROOTTEST) { + return APR_EABOVEROOT; + } + + /* Otherwise append another backpath. + */ + memcpy(path + pathlen, "../", 3); + pathlen += 3; + } + else { + /* otherwise crop the prior segment + */ + do { + --pathlen; + } while (pathlen && path[pathlen - 1] != '/'); + } + + /* Now test if we are above where we started and back up + * the keptlen offset to reflect the added/altered path. + */ + if (pathlen < keptlen) { + if (flags & APR_FILEPATH_SECUREROOTTEST) { + return APR_EABOVEROOT; + } + keptlen = pathlen; + } + } + else { + /* An actual segment, append it to the destination path + */ + if (*next) { + seglen++; + } + memcpy(path + pathlen, addpath, seglen); + pathlen += seglen; + } + + /* Skip over trailing slash to the next segment + */ + if (*next) { + ++next; + } + + addpath = next; + } + path[pathlen] = '\0'; + + /* keptlen will be the rootlen unless the addpath contained + * backpath elements. If so, and APR_FILEPATH_NOTABOVEROOT + * is specified (APR_FILEPATH_SECUREROOTTEST was caught above), + * compare the original root to assure the result path is + * still within given root path. + */ + if ((flags & APR_FILEPATH_NOTABOVEROOT) && keptlen < rootlen) { + if (strncmp(rootpath, path, rootlen)) { + return APR_EABOVEROOT; + } + if (rootpath[rootlen - 1] != '/' + && path[rootlen] && path[rootlen] != '/') { + return APR_EABOVEROOT; + } + } + + *newpath = path; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts, + const char *liststr, + apr_pool_t *p) +{ + return apr_filepath_list_split_impl(pathelts, liststr, ':', p); +} + +APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr, + apr_array_header_t *pathelts, + apr_pool_t *p) +{ + return apr_filepath_list_merge_impl(liststr, pathelts, ':', p); +} + +APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p) +{ + *style = APR_FILEPATH_ENCODING_LOCALE; + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/unix/filepath_util.c b/srclib/apr/file_io/unix/filepath_util.c new file mode 100644 index 0000000000..ec9b426090 --- /dev/null +++ b/srclib/apr/file_io/unix/filepath_util.c @@ -0,0 +1,111 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#define APR_WANT_STRFUNC +#define APR_WANT_MEMFUNC +#include "apr_want.h" + +#include "apr_errno.h" +#include "apr_pools.h" +#include "apr_strings.h" +#include "apr_tables.h" + +#include "apr_private.h" + +apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, + const char *liststr, + char separator, + apr_pool_t *p) +{ + char *path, *part, *ptr; + char separator_string[2] = { '\0', '\0' }; + apr_array_header_t *elts; + int nelts; + + separator_string[0] = separator; + /* Count the number of path elements. We know there'll be at least + one even if path is an empty string. */ + path = apr_pstrdup(p, liststr); + for (nelts = 0, ptr = path; ptr != NULL; ++nelts) + { + ptr = strchr(ptr, separator); + if (ptr) + ++ptr; + } + + /* Split the path into the array. */ + elts = apr_array_make(p, nelts, sizeof(char*)); + while ((part = apr_strtok(path, separator_string, &ptr)) != NULL) + { + if (*part == '\0') /* Ignore empty path components. */ + continue; + + *(char**)apr_array_push(elts) = part; + path = NULL; /* For the next call to apr_strtok */ + } + + *pathelts = elts; + return APR_SUCCESS; +} + + +apr_status_t apr_filepath_list_merge_impl(char **liststr, + apr_array_header_t *pathelts, + char separator, + apr_pool_t *p) +{ + apr_size_t path_size = 0; + char *path; + int i; + + /* This test isn't 100% certain, but it'll catch at least some + invalid uses... */ + if (pathelts->elt_size != sizeof(char*)) + return APR_EINVAL; + + /* Calculate the size of the merged path */ + for (i = 0; i < pathelts->nelts; ++i) + path_size += strlen(((char**)pathelts->elts)[i]); + + if (path_size == 0) + { + *liststr = NULL; + return APR_SUCCESS; + } + + if (i > 0) /* Add space for the separators */ + path_size += (i - 1); + + /* Merge the path components */ + path = *liststr = apr_palloc(p, path_size + 1); + for (i = 0; i < pathelts->nelts; ++i) + { + /* ### Hmmmm. Calling strlen twice on the same string. Yuck. + But is is better than reallocation in apr_pstrcat? */ + const char *part = ((char**)pathelts->elts)[i]; + apr_size_t part_size = strlen(part); + if (part_size == 0) /* Ignore empty path components. */ + continue; + + if (i > 0) + *path++ = separator; + memcpy(path, part, part_size); + path += part_size; + } + *path = '\0'; + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/unix/filestat.c b/srclib/apr/file_io/unix/filestat.c new file mode 100644 index 0000000000..d7a48663af --- /dev/null +++ b/srclib/apr/file_io/unix/filestat.c @@ -0,0 +1,282 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" + +#ifdef HAVE_UTIME +#include +#endif + +static apr_filetype_e filetype_from_mode(mode_t mode) +{ + apr_filetype_e type; + + switch (mode & S_IFMT) { + case S_IFREG: + type = APR_REG; break; + case S_IFDIR: + type = APR_DIR; break; + case S_IFLNK: + type = APR_LNK; break; + case S_IFCHR: + type = APR_CHR; break; + case S_IFBLK: + type = APR_BLK; break; +#if defined(S_IFFIFO) + case S_IFFIFO: + type = APR_PIPE; break; +#endif +#if !defined(BEOS) && defined(S_IFSOCK) + case S_IFSOCK: + type = APR_SOCK; break; +#endif + + default: + /* Work around missing S_IFxxx values above + * for Linux et al. + */ +#if !defined(S_IFFIFO) && defined(S_ISFIFO) + if (S_ISFIFO(mode)) { + type = APR_PIPE; + } else +#endif +#if !defined(BEOS) && !defined(S_IFSOCK) && defined(S_ISSOCK) + if (S_ISSOCK(mode)) { + type = APR_SOCK; + } else +#endif + type = APR_UNKFILE; + } + return type; +} + +static void fill_out_finfo(apr_finfo_t *finfo, struct_stat *info, + apr_int32_t wanted) +{ + finfo->valid = APR_FINFO_MIN | APR_FINFO_IDENT | APR_FINFO_NLINK + | APR_FINFO_OWNER | APR_FINFO_PROT; + finfo->protection = apr_unix_mode2perms(info->st_mode); + finfo->filetype = filetype_from_mode(info->st_mode); + finfo->user = info->st_uid; + finfo->group = info->st_gid; + finfo->size = info->st_size; + finfo->inode = info->st_ino; + finfo->device = info->st_dev; + finfo->nlink = info->st_nlink; + apr_time_ansi_put(&finfo->atime, info->st_atime); + apr_time_ansi_put(&finfo->mtime, info->st_mtime); + apr_time_ansi_put(&finfo->ctime, info->st_ctime); + /* ### needs to be revisited + * if (wanted & APR_FINFO_CSIZE) { + * finfo->csize = info->st_blocks * 512; + * finfo->valid |= APR_FINFO_CSIZE; + * } + */ +} + +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile) +{ + struct_stat info; + + if (thefile->buffered) { + apr_status_t rv = apr_file_flush(thefile); + if (rv != APR_SUCCESS) + return rv; + } + + if (fstat(thefile->filedes, &info) == 0) { + finfo->pool = thefile->pool; + finfo->fname = thefile->fname; + fill_out_finfo(finfo, &info, wanted); + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, + apr_fileperms_t perms) +{ + mode_t mode = apr_unix_perms2mode(perms); + + if (chmod(fname, mode) == -1) + return errno; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + /* Don't do anything if we can't handle the requested attributes */ + if (!(attr_mask & (APR_FILE_ATTR_READONLY + | APR_FILE_ATTR_EXECUTABLE))) + return APR_SUCCESS; + + status = apr_stat(&finfo, fname, APR_FINFO_PROT, pool); + if (status) + return status; + + /* ### TODO: should added bits be umask'd? */ + if (attr_mask & APR_FILE_ATTR_READONLY) + { + if (attributes & APR_FILE_ATTR_READONLY) + { + finfo.protection &= ~APR_UWRITE; + finfo.protection &= ~APR_GWRITE; + finfo.protection &= ~APR_WWRITE; + } + else + { + /* ### umask this! */ + finfo.protection |= APR_UWRITE; + finfo.protection |= APR_GWRITE; + finfo.protection |= APR_WWRITE; + } + } + + if (attr_mask & APR_FILE_ATTR_EXECUTABLE) + { + if (attributes & APR_FILE_ATTR_EXECUTABLE) + { + /* ### umask this! */ + finfo.protection |= APR_UEXECUTE; + finfo.protection |= APR_GEXECUTE; + finfo.protection |= APR_WEXECUTE; + } + else + { + finfo.protection &= ~APR_UEXECUTE; + finfo.protection &= ~APR_GEXECUTE; + finfo.protection &= ~APR_WEXECUTE; + } + } + + return apr_file_perms_set(fname, finfo.protection); +} + + +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool) +{ + apr_status_t status; + apr_finfo_t finfo; + + status = apr_stat(&finfo, fname, APR_FINFO_ATIME, pool); + if (status) { + return status; + } + +#ifdef HAVE_UTIMES + { + struct timeval tvp[2]; + + tvp[0].tv_sec = apr_time_sec(finfo.atime); + tvp[0].tv_usec = apr_time_usec(finfo.atime); + tvp[1].tv_sec = apr_time_sec(mtime); + tvp[1].tv_usec = apr_time_usec(mtime); + + if (utimes(fname, tvp) == -1) { + return errno; + } + } +#elif defined(HAVE_UTIME) + { + struct utimbuf buf; + + buf.actime = (time_t) (finfo.atime / APR_USEC_PER_SEC); + buf.modtime = (time_t) (mtime / APR_USEC_PER_SEC); + + if (utime(fname, &buf) == -1) { + return errno; + } + } +#else + return APR_ENOTIMPL; +#endif + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, + const char *fname, + apr_int32_t wanted, apr_pool_t *pool) +{ + struct_stat info; + int srv; + + if (wanted & APR_FINFO_LINK) + srv = lstat(fname, &info); + else + srv = stat(fname, &info); + + if (srv == 0) { + finfo->pool = pool; + finfo->fname = fname; + fill_out_finfo(finfo, &info, wanted); + if (wanted & APR_FINFO_LINK) + wanted &= ~APR_FINFO_LINK; + return (wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS; + } + else { +#if !defined(ENOENT) || !defined(ENOTDIR) +#error ENOENT || ENOTDIR not defined; please see the +#error comments at this line in the source for a workaround. + /* + * If ENOENT || ENOTDIR is not defined in one of the your OS's + * include files, APR cannot report a good reason why the stat() + * of the file failed; there are cases where it can fail even though + * the file exists. This opens holes in Apache, for example, because + * it becomes possible for someone to get a directory listing of a + * directory even though there is an index (eg. index.html) file in + * it. If you do not have a problem with this, delete the above + * #error lines and start the compile again. If you need to do this, + * please submit a bug report to http://www.apache.org/bug_report.html + * letting us know that you needed to do this. Please be sure to + * include the operating system you are using. + */ + /* WARNING: All errors will be handled as not found + */ +#if !defined(ENOENT) + return APR_ENOENT; +#else + /* WARNING: All errors but not found will be handled as not directory + */ + if (errno != ENOENT) + return APR_ENOENT; + else + return errno; +#endif +#else /* All was defined well, report the usual: */ + return errno; +#endif + } +} + + diff --git a/srclib/apr/file_io/unix/flock.c b/srclib/apr/file_io/unix/flock.c new file mode 100644 index 0000000000..9aeb4fe3ef --- /dev/null +++ b/srclib/apr/file_io/unix/flock.c @@ -0,0 +1,120 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" + +#if APR_HAVE_FCNTL_H +#include +#endif +#ifdef HAVE_SYS_FILE_H +#include +#endif + +APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type) +{ + int rc; + +#if defined(HAVE_FCNTL_H) + { + struct flock l = { 0 }; + int fc; + + l.l_whence = SEEK_SET; /* lock from current point */ + l.l_start = 0; /* begin lock at this offset */ + l.l_len = 0; /* lock to end of file */ + if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED) + l.l_type = F_RDLCK; + else + l.l_type = F_WRLCK; + + fc = (type & APR_FLOCK_NONBLOCK) ? F_SETLK : F_SETLKW; + + /* keep trying if fcntl() gets interrupted (by a signal) */ + while ((rc = fcntl(thefile->filedes, fc, &l)) < 0 && errno == EINTR) + continue; + + if (rc == -1) { + /* on some Unix boxes (e.g., Tru64), we get EACCES instead + * of EAGAIN; we don't want APR_STATUS_IS_EAGAIN() matching EACCES + * since that breaks other things, so fix up the retcode here + */ + if (errno == EACCES) { + return EAGAIN; + } + return errno; + } + } +#elif defined(HAVE_SYS_FILE_H) + { + int ltype; + + if ((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED) + ltype = LOCK_SH; + else + ltype = LOCK_EX; + if ((type & APR_FLOCK_NONBLOCK) != 0) + ltype |= LOCK_NB; + + /* keep trying if flock() gets interrupted (by a signal) */ + while ((rc = flock(thefile->filedes, ltype)) < 0 && errno == EINTR) + continue; + + if (rc == -1) + return errno; + } +#else +#error No file locking mechanism is available. +#endif + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile) +{ + int rc; + +#if defined(HAVE_FCNTL_H) + { + struct flock l = { 0 }; + + l.l_whence = SEEK_SET; /* lock from current point */ + l.l_start = 0; /* begin lock at this offset */ + l.l_len = 0; /* lock to end of file */ + l.l_type = F_UNLCK; + + /* keep trying if fcntl() gets interrupted (by a signal) */ + while ((rc = fcntl(thefile->filedes, F_SETLKW, &l)) < 0 + && errno == EINTR) + continue; + + if (rc == -1) + return errno; + } +#elif defined(HAVE_SYS_FILE_H) + { + /* keep trying if flock() gets interrupted (by a signal) */ + while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR) + continue; + + if (rc == -1) + return errno; + } +#else +#error No file locking mechanism is available. +#endif + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/unix/fullrw.c b/srclib/apr/file_io/unix/fullrw.c new file mode 100644 index 0000000000..78b8d55b15 --- /dev/null +++ b/srclib/apr/file_io/unix/fullrw.c @@ -0,0 +1,85 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" + + +APR_DECLARE(apr_status_t) apr_file_read_full(apr_file_t *thefile, void *buf, + apr_size_t nbytes, + apr_size_t *bytes_read) +{ + apr_status_t status; + apr_size_t total_read = 0; + + do { + apr_size_t amt = nbytes; + + status = apr_file_read(thefile, buf, &amt); + buf = (char *)buf + amt; + nbytes -= amt; + total_read += amt; + } while (status == APR_SUCCESS && nbytes > 0); + + if (bytes_read != NULL) + *bytes_read = total_read; + + return status; +} + +APR_DECLARE(apr_status_t) apr_file_write_full(apr_file_t *thefile, + const void *buf, + apr_size_t nbytes, + apr_size_t *bytes_written) +{ + apr_status_t status; + apr_size_t total_written = 0; + + do { + apr_size_t amt = nbytes; + + status = apr_file_write(thefile, buf, &amt); + buf = (char *)buf + amt; + nbytes -= amt; + total_written += amt; + } while (status == APR_SUCCESS && nbytes > 0); + + if (bytes_written != NULL) + *bytes_written = total_written; + + return status; +} + +APR_DECLARE(apr_status_t) apr_file_writev_full(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, + apr_size_t *bytes_written) +{ + apr_status_t rv = APR_SUCCESS; + int i; + apr_size_t amt = 0; + apr_size_t total = 0; + + for (i = 0; i < nvec && rv == APR_SUCCESS; i++) { + rv = apr_file_write_full(thefile, vec[i].iov_base, + vec[i].iov_len, &amt); + total += amt; + } + + if (bytes_written != NULL) + *bytes_written = total; + + return rv; +} diff --git a/srclib/apr/file_io/unix/mktemp.c b/srclib/apr/file_io/unix/mktemp.c new file mode 100644 index 0000000000..c516fac81b --- /dev/null +++ b/srclib/apr/file_io/unix/mktemp.c @@ -0,0 +1,210 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright (c) 1987, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "apr_private.h" +#include "apr_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_strings.h" /* prototype of apr_mkstemp() */ +#include "apr_arch_file_io.h" /* prototype of apr_mkstemp() */ +#include "apr_portable.h" /* for apr_os_file_put() */ + +#ifndef HAVE_MKSTEMP + +#if defined(SVR4) || defined(WIN32) || defined(NETWARE) +#ifdef SVR4 +#if HAVE_INTTYPES_H +#include +#endif +#endif +#define arc4random() rand() +#define seedrandom(a) srand(a) +#else +#if APR_HAVE_STDINT_H +#include +#endif +#define arc4random() random() +#define seedrandom(a) srandom(a) +#endif + +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_STAT_H +#include +#endif +#if APR_HAVE_FCNTL_H +#include +#endif +#include +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#endif + +static const unsigned char padchar[] = +"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; +static apr_uint32_t randseed=0; + +static int gettemp(char *path, apr_file_t **doopen, apr_int32_t flags, apr_pool_t *p) +{ + register char *start, *trv, *suffp; + char *pad; + apr_finfo_t sbuf; + apr_status_t rv; + apr_uint32_t randnum; + + if (randseed==0) { + randseed = (int)apr_time_now(); + seedrandom(randseed); + } + + for (trv = path; *trv; ++trv) + ; + suffp = trv; + --trv; + if (trv < path) { + return APR_EINVAL; + } + + /* Fill space with random characters */ + while (*trv == 'X') { + randnum = arc4random() % (sizeof(padchar) - 1); + *trv-- = padchar[randnum]; + } + start = trv + 1; + + /* + * check the target directory. + */ + for (;; --trv) { + if (trv <= path) + break; + if (*trv == '/') { + *trv = '\0'; + rv = apr_stat(&sbuf, path, APR_FINFO_TYPE, p); + *trv = '/'; + if (rv != APR_SUCCESS) + return rv; + if (sbuf.filetype != APR_DIR) { + return APR_ENOTDIR; + } + break; + } + } + + for (;;) { + if ((rv = apr_file_open(doopen, path, flags, + APR_UREAD | APR_UWRITE, p)) == APR_SUCCESS) + return APR_SUCCESS; + if (rv != APR_EEXIST) + return rv; + + /* If we have a collision, cycle through the space of filenames */ + for (trv = start;;) { + if (*trv == '\0' || trv == suffp) + return APR_EINVAL; /* XXX: is this the correct return code? */ + pad = strchr((char *)padchar, *trv); + if (pad == NULL || !*++pad) { + *trv++ = padchar[0]; + } + else { + *trv++ = *pad; + break; + } + } + } + /*NOTREACHED*/ +} + +#else + +#if APR_HAVE_STDLIB_H +#include /* for mkstemp() - Single Unix */ +#endif +#if APR_HAVE_UNISTD_H +#include /* for mkstemp() - FreeBSD */ +#endif +#endif /* !defined(HAVE_MKSTEMP) */ + +APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_int32_t flags, apr_pool_t *p) +{ +#ifdef HAVE_MKSTEMP + int fd; +#endif + flags = (!flags) ? APR_CREATE | APR_READ | APR_WRITE | APR_EXCL | + APR_DELONCLOSE : flags; +#ifndef HAVE_MKSTEMP + return gettemp(template, fp, flags, p); +#else + +#ifdef HAVE_MKSTEMP64 + fd = mkstemp64(template); +#else + fd = mkstemp(template); +#endif + + if (fd == -1) { + return errno; + } + /* XXX: We must reset several flags values as passed-in, since + * mkstemp didn't subscribe to our preference flags. + * + * We either have to unset the flags, or fix up the fd and other + * xthread and inherit bits appropriately. Since gettemp() above + * calls apr_file_open, our flags are respected in that code path. + */ + apr_os_file_put(fp, &fd, flags, p); + (*fp)->fname = apr_pstrdup(p, template); + + apr_pool_cleanup_register((*fp)->pool, (void *)(*fp), + apr_unix_file_cleanup, apr_unix_file_cleanup); +#endif + return APR_SUCCESS; +} + diff --git a/srclib/apr/file_io/unix/open.c b/srclib/apr/file_io/unix/open.c new file mode 100644 index 0000000000..55b9863024 --- /dev/null +++ b/srclib/apr/file_io/unix/open.c @@ -0,0 +1,280 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_thread_mutex.h" +#include "apr_arch_inherit.h" + +#ifdef NETWARE +#include "nks/dirio.h" +#include "apr_hash.h" +#include "fsio.h" +#endif + +apr_status_t apr_unix_file_cleanup(void *thefile) +{ + apr_file_t *file = thefile; + apr_status_t flush_rv = APR_SUCCESS, rv = APR_SUCCESS; + + if (file->buffered) { + flush_rv = apr_file_flush(file); + } + if (close(file->filedes) == 0) { + file->filedes = -1; + if (file->flags & APR_DELONCLOSE) { + unlink(file->fname); + } +#if APR_HAS_THREADS + if (file->thlock) { + rv = apr_thread_mutex_destroy(file->thlock); + } +#endif + } + else { + /* Are there any error conditions other than EINTR or EBADF? */ + rv = errno; + } + return rv != APR_SUCCESS ? rv : flush_rv; +} + +APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, + const char *fname, + apr_int32_t flag, + apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_os_file_t fd; + int oflags = 0; +#if APR_HAS_THREADS + apr_thread_mutex_t *thlock; + apr_status_t rv; +#endif + + if ((flag & APR_READ) && (flag & APR_WRITE)) { + oflags = O_RDWR; + } + else if (flag & APR_READ) { + oflags = O_RDONLY; + } + else if (flag & APR_WRITE) { + oflags = O_WRONLY; + } + else { + return APR_EACCES; + } + + if (flag & APR_CREATE) { + oflags |= O_CREAT; + if (flag & APR_EXCL) { + oflags |= O_EXCL; + } + } + if ((flag & APR_EXCL) && !(flag & APR_CREATE)) { + return APR_EACCES; + } + + if (flag & APR_APPEND) { + oflags |= O_APPEND; + } + if (flag & APR_TRUNCATE) { + oflags |= O_TRUNC; + } +#ifdef O_BINARY + if (flag & APR_BINARY) { + oflags |= O_BINARY; + } +#endif + +#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE) + oflags |= O_LARGEFILE; +#elif defined(O_LARGEFILE) + if (flag & APR_LARGEFILE) { + oflags |= O_LARGEFILE; + } +#endif + +#if APR_HAS_THREADS + if ((flag & APR_BUFFERED) && (flag & APR_XTHREAD)) { + rv = apr_thread_mutex_create(&thlock, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + return rv; + } + } +#endif + + if (perm == APR_OS_DEFAULT) { + fd = open(fname, oflags, 0666); + } + else { + fd = open(fname, oflags, apr_unix_perms2mode(perm)); + } + if (fd < 0) { + return errno; + } + + (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*new)->pool = pool; + (*new)->flags = flag; + (*new)->filedes = fd; + + (*new)->fname = apr_pstrdup(pool, fname); + + (*new)->blocking = BLK_ON; + (*new)->buffered = (flag & APR_BUFFERED) > 0; + + if ((*new)->buffered) { + (*new)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); +#if APR_HAS_THREADS + if ((*new)->flags & APR_XTHREAD) { + (*new)->thlock = thlock; + } +#endif + } + else { + (*new)->buffer = NULL; + } + + (*new)->is_pipe = 0; + (*new)->timeout = -1; + (*new)->ungetchar = -1; + (*new)->eof_hit = 0; + (*new)->filePtr = 0; + (*new)->bufpos = 0; + (*new)->dataRead = 0; + (*new)->direction = 0; +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new)->pollset, 1, pool, 0); +#endif + if (!(flag & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register((*new)->pool, (void *)(*new), + apr_unix_file_cleanup, + apr_unix_file_cleanup); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file) +{ + return apr_pool_cleanup_run(file->pool, file, apr_unix_file_cleanup); +} + +APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool) +{ + if (unlink(path) == 0) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, + const char *to_path, + apr_pool_t *p) +{ + if (rename(from_path, to_path) != 0) { + return errno; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file) +{ + *thefile = file->filedes; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, apr_pool_t *pool) +{ + int *dafile = thefile; + + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->eof_hit = 0; + (*file)->blocking = BLK_UNKNOWN; /* in case it is a pipe */ + (*file)->timeout = -1; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->filedes = *dafile; + (*file)->flags = flags | APR_FILE_NOCLEANUP; + (*file)->buffered = (flags & APR_BUFFERED) > 0; + +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0); +#endif + + if ((*file)->buffered) { + (*file)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); +#if APR_HAS_THREADS + if ((*file)->flags & APR_XTHREAD) { + apr_status_t rv; + rv = apr_thread_mutex_create(&((*file)->thlock), + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + return rv; + } + } +#endif + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr) +{ + if (fptr->eof_hit == 1) { + return APR_EOF; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, + apr_pool_t *pool) +{ + int fd = STDERR_FILENO; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + +APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, + apr_pool_t *pool) +{ + int fd = STDOUT_FILENO; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + +APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, + apr_pool_t *pool) +{ + int fd = STDIN_FILENO; + + return apr_os_file_put(thefile, &fd, 0, pool); +} + +APR_IMPLEMENT_INHERIT_SET(file, flags, pool, apr_unix_file_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, apr_unix_file_cleanup) + +APR_POOL_IMPLEMENT_ACCESSOR(file) diff --git a/srclib/apr/file_io/unix/pipe.c b/srclib/apr/file_io/unix/pipe.c new file mode 100644 index 0000000000..ec54432f7f --- /dev/null +++ b/srclib/apr/file_io/unix/pipe.c @@ -0,0 +1,236 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#include "apr_arch_inherit.h" + +/* Figure out how to get pipe block/nonblock on BeOS... + * Basically, BONE7 changed things again so that ioctl didn't work, + * but now fcntl does, hence we need to do this extra checking. + * The joys of beta programs. :-) + */ +#if BEOS +#if !BONE7 +# define BEOS_BLOCKING 1 +#else +# define BEOS_BLOCKING 0 +#endif +#endif + +static apr_status_t pipeblock(apr_file_t *thepipe) +{ +#if !BEOS_BLOCKING + int fd_flags; + + fd_flags = fcntl(thepipe->filedes, F_GETFL, 0); +# if defined(O_NONBLOCK) + fd_flags &= ~O_NONBLOCK; +# elif defined(O_NDELAY) + fd_flags &= ~O_NDELAY; +# elif defined(O_FNDELAY) + fd_flags &= ~O_FNDELAY; +# else + /* XXXX: this breaks things, but an alternative isn't obvious...*/ + return APR_ENOTIMPL; +# endif + if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) { + return errno; + } +#else /* BEOS_BLOCKING */ + +# if BEOS_BONE /* This only works on BONE 0-6 */ + int on = 0; + if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) { + return errno; + } +# else /* "classic" BeOS doesn't support this at all */ + return APR_ENOTIMPL; +# endif + +#endif /* !BEOS_BLOCKING */ + + thepipe->blocking = BLK_ON; + return APR_SUCCESS; +} + +static apr_status_t pipenonblock(apr_file_t *thepipe) +{ +#if !BEOS_BLOCKING + int fd_flags = fcntl(thepipe->filedes, F_GETFL, 0); + +# if defined(O_NONBLOCK) + fd_flags |= O_NONBLOCK; +# elif defined(O_NDELAY) + fd_flags |= O_NDELAY; +# elif defined(O_FNDELAY) + fd_flags |= O_FNDELAY; +# else + /* XXXX: this breaks things, but an alternative isn't obvious...*/ + return APR_ENOTIMPL; +# endif + if (fcntl(thepipe->filedes, F_SETFL, fd_flags) == -1) { + return errno; + } + +#else /* BEOS_BLOCKING */ + +# if BEOS_BONE /* This only works on BONE 0-6 */ + int on = 1; + if (ioctl(thepipe->filedes, FIONBIO, &on, sizeof(on)) < 0) { + return errno; + } +# else /* "classic" BeOS doesn't support this at all */ + return APR_ENOTIMPL; +# endif + +#endif /* !BEOS_BLOCKING */ + + thepipe->blocking = BLK_OFF; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout) +{ + if (thepipe->is_pipe == 1) { + thepipe->timeout = timeout; + if (timeout >= 0) { + if (thepipe->blocking != BLK_OFF) { /* blocking or unknown state */ + return pipenonblock(thepipe); + } + } + else { + if (thepipe->blocking != BLK_ON) { /* non-blocking or unknown state */ + return pipeblock(thepipe); + } + } + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout) +{ + if (thepipe->is_pipe == 1) { + *timeout = thepipe->timeout; + return APR_SUCCESS; + } + return APR_EINVAL; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *pool) +{ + int *dafile = thefile; + + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->eof_hit = 0; + (*file)->is_pipe = 1; + (*file)->blocking = BLK_UNKNOWN; /* app needs to make a timeout call */ + (*file)->timeout = -1; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->filedes = *dafile; + if (!register_cleanup) { + (*file)->flags = APR_FILE_NOCLEANUP; + } + (*file)->buffered = 0; +#if APR_HAS_THREADS + (*file)->thlock = NULL; +#endif + if (register_cleanup) { + apr_pool_cleanup_register((*file)->pool, (void *)(*file), + apr_unix_file_cleanup, + apr_pool_cleanup_null); + } +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0); +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *pool) +{ + return apr_os_pipe_put_ex(file, thefile, 0, pool); +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *pool) +{ + int filedes[2]; + + if (pipe(filedes) == -1) { + return errno; + } + + (*in) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*in)->pool = pool; + (*in)->filedes = filedes[0]; + (*in)->is_pipe = 1; + (*in)->fname = NULL; + (*in)->buffered = 0; + (*in)->blocking = BLK_ON; + (*in)->timeout = -1; + (*in)->ungetchar = -1; + (*in)->flags = APR_INHERIT; +#if APR_HAS_THREADS + (*in)->thlock = NULL; +#endif +#ifndef WAITIO_USES_POLL + (void) apr_pollset_create(&(*in)->pollset, 1, pool, 0); +#endif + (*out) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*out)->pool = pool; + (*out)->filedes = filedes[1]; + (*out)->is_pipe = 1; + (*out)->fname = NULL; + (*out)->buffered = 0; + (*out)->blocking = BLK_ON; + (*out)->flags = APR_INHERIT; + (*out)->timeout = -1; +#if APR_HAS_THREADS + (*out)->thlock = NULL; +#endif +#ifndef WAITIO_USES_POLL + (void) apr_pollset_create(&(*out)->pollset, 1, pool, 0); +#endif + apr_pool_cleanup_register((*in)->pool, (void *)(*in), apr_unix_file_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register((*out)->pool, (void *)(*out), apr_unix_file_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, apr_pool_t *pool) +{ + mode_t mode = apr_unix_perms2mode(perm); + + if (mkfifo(filename, mode) == -1) { + return errno; + } + return APR_SUCCESS; +} + + + diff --git a/srclib/apr/file_io/unix/readwrite.c b/srclib/apr/file_io/unix/readwrite.c new file mode 100644 index 0000000000..f2514bf3bd --- /dev/null +++ b/srclib/apr/file_io/unix/readwrite.c @@ -0,0 +1,441 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_thread_mutex.h" +#include "apr_support.h" + +/* The only case where we don't use wait_for_io_or_timeout is on + * pre-BONE BeOS, so this check should be sufficient and simpler */ +#if !BEOS_R5 +#define USE_WAIT_FOR_IO +#endif + +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) +{ + apr_ssize_t rv; + apr_size_t bytes_read; + + if (*nbytes <= 0) { + *nbytes = 0; + return APR_SUCCESS; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + apr_uint64_t blocksize; + apr_uint64_t size = *nbytes; + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_lock(thefile->thlock); + } +#endif + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = 0; + thefile->direction = 0; + thefile->dataRead = 0; + } + + rv = 0; + if (thefile->ungetchar != -1) { + *pos = (char)thefile->ungetchar; + ++pos; + --size; + thefile->ungetchar = -1; + } + while (rv == 0 && size > 0) { + if (thefile->bufpos >= thefile->dataRead) { + int bytesread = read(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE); + if (bytesread == 0) { + thefile->eof_hit = TRUE; + rv = APR_EOF; + break; + } + else if (bytesread == -1) { + rv = errno; + break; + } + thefile->dataRead = bytesread; + thefile->filePtr += thefile->dataRead; + thefile->bufpos = 0; + } + + blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size; + memcpy(pos, thefile->buffer + thefile->bufpos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + *nbytes = pos - (char *)buf; + if (*nbytes) { + rv = 0; + } +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_unlock(thefile->thlock); + } +#endif + return rv; + } + else { + bytes_read = 0; + if (thefile->ungetchar != -1) { + bytes_read = 1; + *(char *)buf = (char)thefile->ungetchar; + buf = (char *)buf + 1; + (*nbytes)--; + thefile->ungetchar = -1; + if (*nbytes == 0) { + *nbytes = bytes_read; + return APR_SUCCESS; + } + } + + do { + rv = read(thefile->filedes, buf, *nbytes); + } while (rv == -1 && errno == EINTR); +#ifdef USE_WAIT_FOR_IO + if (rv == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + thefile->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 1); + if (arv != APR_SUCCESS) { + *nbytes = bytes_read; + return arv; + } + else { + do { + rv = read(thefile->filedes, buf, *nbytes); + } while (rv == -1 && errno == EINTR); + } + } +#endif + *nbytes = bytes_read; + if (rv == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + if (rv > 0) { + *nbytes += rv; + return APR_SUCCESS; + } + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) +{ + apr_size_t rv; + + if (thefile->buffered) { + char *pos = (char *)buf; + int blocksize; + int size = *nbytes; + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_lock(thefile->thlock); + } +#endif + + if ( thefile->direction == 0 ) { + /* Position file pointer for writing at the offset we are + * logically reading from + */ + apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + if (offset != thefile->filePtr) + lseek(thefile->filedes, offset, SEEK_SET); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 1; + } + + rv = 0; + while (rv == 0 && size > 0) { + if (thefile->bufpos == APR_FILE_BUFSIZE) /* write buffer is full*/ + apr_file_flush(thefile); + + blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? + APR_FILE_BUFSIZE - thefile->bufpos : size; + memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_unlock(thefile->thlock); + } +#endif + return rv; + } + else { + do { + rv = write(thefile->filedes, buf, *nbytes); + } while (rv == (apr_size_t)-1 && errno == EINTR); +#ifdef USE_WAIT_FOR_IO + if (rv == (apr_size_t)-1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + thefile->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0); + if (arv != APR_SUCCESS) { + *nbytes = 0; + return arv; + } + else { + do { + do { + rv = write(thefile->filedes, buf, *nbytes); + } while (rv == (apr_size_t)-1 && errno == EINTR); + if (rv == (apr_size_t)-1 && + (errno == EAGAIN || errno == EWOULDBLOCK)) { + *nbytes /= 2; /* yes, we'll loop if kernel lied + * and we can't even write 1 byte + */ + } + else { + break; + } + } while (1); + } + } +#endif + if (rv == (apr_size_t)-1) { + (*nbytes) = 0; + return errno; + } + *nbytes = rv; + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes) +{ +#ifdef HAVE_WRITEV + int bytes; + + if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { + *nbytes = 0; + return errno; + } + else { + *nbytes = bytes; + return APR_SUCCESS; + } +#else + /** + * The problem with trying to output the entire iovec is that we cannot + * maintain the behavoir that a real writev would have. If we iterate + * over the iovec one at a time, we loose the atomic properties of + * writev(). The other option is to combine the entire iovec into one + * buffer that we could then send in one call to write(). This is not + * reasonable since we do not know how much data an iovec could contain. + * + * The only reasonable option, that maintains the semantics of a real + * writev(), is to only write the first iovec. Callers of file_writev() + * must deal with partial writes as they normally would. If you want to + * ensure an entire iovec is written, use apr_file_writev_full(). + */ + + *nbytes = vec[0].iov_len; + return apr_file_write(thefile, vec[0].iov_base, nbytes); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) +{ + apr_size_t nbytes = 1; + + return apr_file_write(thefile, &ch, &nbytes); +} + +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) +{ + thefile->ungetchar = (unsigned char)ch; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) +{ + apr_size_t nbytes = 1; + + return apr_file_read(thefile, ch, &nbytes); +} + +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) +{ + return apr_file_write_full(thefile, str, strlen(str), NULL); +} + +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) +{ + if (thefile->buffered) { + apr_int64_t written = 0; + + if (thefile->direction == 1 && thefile->bufpos) { + do { + written = write(thefile->filedes, thefile->buffer, thefile->bufpos); + } while (written == (apr_int64_t)-1 && errno == EINTR); + if (written == (apr_int64_t)-1) { + return errno; + } + thefile->filePtr += written; + thefile->bufpos = 0; + } + } + /* There isn't anything to do if we aren't buffering the output + * so just return success. + */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) +{ + apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */ + apr_size_t nbytes; + const char *str_start = str; + char *final = str + len - 1; + + if (len <= 1) { + /* sort of like fgets(), which returns NULL and stores no bytes + */ + return APR_SUCCESS; + } + + /* If we have an underlying buffer, we can be *much* more efficient + * and skip over the apr_file_read calls. + */ + if (thefile->buffered) { + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_lock(thefile->thlock); + } +#endif + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->direction = 0; + thefile->bufpos = 0; + thefile->dataRead = 0; + } + + while (str < final) { /* leave room for trailing '\0' */ + /* Force ungetc leftover to call apr_file_read. */ + if (thefile->bufpos < thefile->dataRead && + thefile->ungetchar == -1) { + *str = thefile->buffer[thefile->bufpos++]; + } + else { + nbytes = 1; + rv = apr_file_read(thefile, str, &nbytes); + if (rv != APR_SUCCESS) { + break; + } + } + if (*str == '\n') { + ++str; + break; + } + ++str; + } + +#if APR_HAS_THREADS + if (thefile->thlock) { + apr_thread_mutex_unlock(thefile->thlock); + } +#endif + } + else { + while (str < final) { /* leave room for trailing '\0' */ + nbytes = 1; + rv = apr_file_read(thefile, str, &nbytes); + if (rv != APR_SUCCESS) { + break; + } + if (*str == '\n') { + ++str; + break; + } + ++str; + } + } + + /* We must store a terminating '\0' if we've stored any chars. We can + * get away with storing it if we hit an error first. + */ + *str = '\0'; + if (str > str_start) { + /* we stored chars; don't report EOF or any other errors; + * the app will find out about that on the next call + */ + return APR_SUCCESS; + } + return rv; +} + +struct apr_file_printf_data { + apr_vformatter_buff_t vbuff; + apr_file_t *fptr; + char *buf; +}; + +static int file_printf_flush(apr_vformatter_buff_t *buff) +{ + struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff; + + if (apr_file_write_full(data->fptr, data->buf, + data->vbuff.curpos - data->buf, NULL)) { + return -1; + } + + data->vbuff.curpos = data->buf; + return 0; +} + +APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, + const char *format, ...) +{ + struct apr_file_printf_data data; + va_list ap; + int count; + + /* don't really need a HUGE_STRING_LEN anymore */ + data.buf = malloc(HUGE_STRING_LEN); + if (data.buf == NULL) { + return -1; + } + data.vbuff.curpos = data.buf; + data.vbuff.endpos = data.buf + HUGE_STRING_LEN; + data.fptr = fptr; + va_start(ap, format); + count = apr_vformatter(file_printf_flush, + (apr_vformatter_buff_t *)&data, format, ap); + /* apr_vformatter does not call flush for the last bits */ + if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data); + + va_end(ap); + + free(data.buf); + + return count; +} diff --git a/srclib/apr/file_io/unix/seek.c b/srclib/apr/file_io/unix/seek.c new file mode 100644 index 0000000000..48368cda51 --- /dev/null +++ b/srclib/apr/file_io/unix/seek.c @@ -0,0 +1,99 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" + +static apr_status_t setptr(apr_file_t *thefile, apr_off_t pos ) +{ + apr_off_t newbufpos; + int rc; + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = thefile->direction = thefile->dataRead = 0; + } + + newbufpos = pos - (thefile->filePtr - thefile->dataRead); + if (newbufpos >= 0 && newbufpos <= thefile->dataRead) { + thefile->bufpos = newbufpos; + rc = 0; + } + else { + rc = lseek(thefile->filedes, pos, SEEK_SET); + + if (rc != -1 ) { + thefile->bufpos = thefile->dataRead = 0; + thefile->filePtr = pos; + rc = 0; + } + else { + rc = errno; + } + } + + return rc; +} + + +APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset) +{ + apr_off_t rv; + + thefile->eof_hit = 0; + + if (thefile->buffered) { + int rc = EINVAL; + apr_finfo_t finfo; + + switch (where) { + case APR_SET: + rc = setptr(thefile, *offset); + break; + + case APR_CUR: + rc = setptr(thefile, thefile->filePtr - thefile->dataRead + thefile->bufpos + *offset); + break; + + case APR_END: + rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile); + if (rc == APR_SUCCESS) + rc = setptr(thefile, finfo.size + *offset); + break; + } + + *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + return rc; + } + else { + rv = lseek(thefile->filedes, *offset, where); + if (rv == -1) { + *offset = -1; + return errno; + } + else { + *offset = rv; + return APR_SUCCESS; + } + } +} + +apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset) +{ + if (ftruncate(fp->filedes, offset) == -1) { + return errno; + } + return setptr(fp, offset); +} diff --git a/srclib/apr/file_io/unix/tempdir.c b/srclib/apr/file_io/unix/tempdir.c new file mode 100644 index 0000000000..4409cd99d2 --- /dev/null +++ b/srclib/apr/file_io/unix/tempdir.c @@ -0,0 +1,130 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "apr_private.h" +#include "apr_file_io.h" +#include "apr_strings.h" +#include "apr_env.h" + + +/* Try to open a temporary file in the temporary dir, write to it, + and then close it. */ +static int test_tempdir(const char *temp_dir, apr_pool_t *p) +{ + apr_file_t *dummy_file; + char *path = apr_pstrcat(p, temp_dir, "/apr-tmp.XXXXXX", NULL); + + if (apr_file_mktemp(&dummy_file, path, 0, p) == APR_SUCCESS) { + if (apr_file_putc('!', dummy_file) == APR_SUCCESS) { + if (apr_file_close(dummy_file) == APR_SUCCESS) { + return 1; + } + } + } + return 0; +} + + +APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir, + apr_pool_t *p) +{ + apr_status_t apr_err; + const char *try_dirs[] = { "/tmp", "/usr/tmp", "/var/tmp" }; + const char *try_envs[] = { "TMP", "TEMP", "TMPDIR" }; + const char *dir; + char *cwd; + int i; + + /* Our goal is to find a temporary directory suitable for writing + into. We'll only pay the price once if we're successful -- we + cache our successful find. Here's the order in which we'll try + various paths: + + $TMP + $TEMP + $TMPDIR + "C:\TEMP" (windows only) + "SYS:\TMP" (netware only) + "/tmp" + "/var/tmp" + "/usr/tmp" + P_tmpdir (POSIX define) + `pwd` + + NOTE: This algorithm is basically the same one used by Python + 2.2's tempfile.py module. */ + + /* Try the environment first. */ + for (i = 0; i < (sizeof(try_envs) / sizeof(const char *)); i++) { + char *value; + apr_err = apr_env_get(&value, try_envs[i], p); + if ((apr_err == APR_SUCCESS) && value) { + apr_size_t len = strlen(value); + if (len && (len < APR_PATH_MAX) && test_tempdir(value, p)) { + dir = value; + goto end; + } + } + } + +#ifdef WIN32 + /* Next, on Win32, try the C:\TEMP directory. */ + if (test_tempdir("C:\\TEMP", p)) { + dir = "C:\\TEMP"; + goto end; + } +#endif +#ifdef NETWARE + /* Next, on NetWare, try the SYS:/TMP directory. */ + if (test_tempdir("SYS:/TMP", p)) { + dir = "SYS:/TMP"; + goto end; + } +#endif + + /* Next, try a set of hard-coded paths. */ + for (i = 0; i < (sizeof(try_dirs) / sizeof(const char *)); i++) { + if (test_tempdir(try_dirs[i], p)) { + dir = try_dirs[i]; + goto end; + } + } + +#ifdef P_tmpdir + /* + * If we have it, use the POSIX definition of where + * the tmpdir should be + */ + if (test_tempdir(P_tmpdir, p)) { + dir = P_tmpdir; + goto end; + } +#endif + + /* Finally, try the current working directory. */ + if (APR_SUCCESS == apr_filepath_get(&cwd, APR_FILEPATH_NATIVE, p)) { + if (test_tempdir(cwd, p)) { + dir = cwd; + goto end; + } + } + + /* We didn't find a suitable temp dir anywhere */ + return APR_EGENERAL; + +end: + *temp_dir = apr_pstrdup(p, dir); + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/win32/dir.c b/srclib/apr/file_io/win32/dir.c new file mode 100644 index 0000000000..92d896e616 --- /dev/null +++ b/srclib/apr/file_io/win32/dir.c @@ -0,0 +1,393 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_atime.h" + +#if APR_HAVE_ERRNO_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif + + +static apr_status_t dir_cleanup(void *thedir) +{ + apr_dir_t *dir = thedir; + if (dir->dirhand != INVALID_HANDLE_VALUE && !FindClose(dir->dirhand)) { + return apr_get_os_error(); + } + dir->dirhand = INVALID_HANDLE_VALUE; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, + apr_pool_t *pool) +{ + apr_status_t rv; + + apr_size_t len = strlen(dirname); + (*new) = apr_pcalloc(pool, sizeof(apr_dir_t)); + /* Leave room here to add and pop the '*' wildcard for FindFirstFile + * and double-null terminate so we have one character to change. + */ + (*new)->dirname = apr_palloc(pool, len + 3); + memcpy((*new)->dirname, dirname, len); + if (len && (*new)->dirname[len - 1] != '/') { + (*new)->dirname[len++] = '/'; + } + (*new)->dirname[len++] = '\0'; + (*new)->dirname[len] = '\0'; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + /* Create a buffer for the longest file name we will ever see + */ + (*new)->w.entry = apr_pcalloc(pool, sizeof(WIN32_FIND_DATAW)); + (*new)->name = apr_pcalloc(pool, APR_FILE_MAX * 3 + 1); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Note that we won't open a directory that is greater than MAX_PATH, + * including the trailing /* wildcard suffix. If a * won't fit, then + * neither will any other file name within the directory. + * The length not including the trailing '*' is stored as rootlen, to + * skip over all paths which are too long. + */ + if (len >= APR_PATH_MAX) { + (*new) = NULL; + return APR_ENAMETOOLONG; + } + (*new)->n.entry = apr_pcalloc(pool, sizeof(WIN32_FIND_DATAW)); + } +#endif + (*new)->rootlen = len - 1; + (*new)->pool = pool; + (*new)->dirhand = INVALID_HANDLE_VALUE; + apr_pool_cleanup_register((*new)->pool, (void *)(*new), dir_cleanup, + apr_pool_cleanup_null); + + rv = apr_dir_read(NULL, 0, *new); + if (rv != APR_SUCCESS) { + dir_cleanup(*new); + *new = NULL; + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *dir) +{ + apr_pool_cleanup_kill(dir->pool, dir, dir_cleanup); + return dir_cleanup(dir); +} + +APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir) +{ + apr_status_t rv; + char *fname; + /* The while loops below allow us to skip all invalid file names, so that + * we aren't reporting any files where their absolute paths are too long. + */ +#if APR_HAS_UNICODE_FS + apr_wchar_t wdirname[APR_PATH_MAX]; + apr_wchar_t *eos = NULL; + IF_WIN_OS_IS_UNICODE + { + /* This code path is always be invoked by apr_dir_open or + * apr_dir_rewind, so return without filling out the finfo. + */ + if (thedir->dirhand == INVALID_HANDLE_VALUE) + { + apr_status_t rv; + if (rv = utf8_to_unicode_path(wdirname, sizeof(wdirname) + / sizeof(apr_wchar_t), + thedir->dirname)) { + return rv; + } + eos = wcschr(wdirname, '\0'); + eos[0] = '*'; + eos[1] = '\0'; + thedir->dirhand = FindFirstFileW(wdirname, thedir->w.entry); + eos[0] = '\0'; + if (thedir->dirhand == INVALID_HANDLE_VALUE) { + return apr_get_os_error(); + } + thedir->bof = 1; + return APR_SUCCESS; + } + else if (thedir->bof) { + /* Noop - we already called FindFirstFileW from + * either apr_dir_open or apr_dir_rewind ... use + * that first record. + */ + thedir->bof = 0; + } + else if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) { + return apr_get_os_error(); + } + + while (thedir->rootlen && + thedir->rootlen + wcslen(thedir->w.entry->cFileName) >= APR_PATH_MAX) + { + if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) { + return apr_get_os_error(); + } + } + if (rv = unicode_to_utf8_path(thedir->name, APR_FILE_MAX * 3 + 1, + thedir->w.entry->cFileName)) + return rv; + fname = thedir->name; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* This code path is always be invoked by apr_dir_open or + * apr_dir_rewind, so return without filling out the finfo. + */ + if (thedir->dirhand == INVALID_HANDLE_VALUE) { + /* '/' terminated, so add the '*' and pop it when we finish */ + char *eop = strchr(thedir->dirname, '\0'); + eop[0] = '*'; + eop[1] = '\0'; + thedir->dirhand = FindFirstFileA(thedir->dirname, + thedir->n.entry); + eop[0] = '\0'; + if (thedir->dirhand == INVALID_HANDLE_VALUE) { + return apr_get_os_error(); + } + thedir->bof = 1; + return APR_SUCCESS; + } + else if (thedir->bof) { + /* Noop - we already called FindFirstFileW from + * either apr_dir_open or apr_dir_rewind ... use + * that first record. + */ + thedir->bof = 0; + } + else if (!FindNextFile(thedir->dirhand, thedir->n.entry)) { + return apr_get_os_error(); + } + while (thedir->rootlen && + thedir->rootlen + strlen(thedir->n.entry->cFileName) >= MAX_PATH) + { + if (!FindNextFileW(thedir->dirhand, thedir->w.entry)) { + return apr_get_os_error(); + } + } + fname = thedir->n.entry->cFileName; + } +#endif + + fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) thedir->w.entry, + 0, wanted); + finfo->pool = thedir->pool; + + finfo->valid |= APR_FINFO_NAME; + finfo->name = fname; + + if (wanted &= ~finfo->valid) { + /* Go back and get more_info if we can't answer the whole inquiry + */ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + /* Almost all our work is done. Tack on the wide file name + * to the end of the wdirname (already / delimited) + */ + if (!eos) + eos = wcschr(wdirname, '\0'); + wcscpy(eos, thedir->w.entry->cFileName); + rv = more_finfo(finfo, wdirname, wanted, MORE_OF_WFSPEC); + eos[0] = '\0'; + return rv; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { +#if APR_HAS_UNICODE_FS + /* Don't waste stack space on a second buffer, the one we set + * aside for the wide directory name is twice what we need. + */ + char *fspec = (char*)wdirname; +#else + char fspec[APR_PATH_MAX]; +#endif + apr_size_t dirlen = strlen(thedir->dirname); + if (dirlen >= sizeof(fspec)) + dirlen = sizeof(fspec) - 1; + apr_cpystrn(fspec, thedir->dirname, sizeof(fspec)); + apr_cpystrn(fspec + dirlen, fname, sizeof(fspec) - dirlen); + return more_finfo(finfo, fspec, wanted, MORE_OF_FSPEC); + } +#endif + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *dir) +{ + apr_status_t rv; + + /* this will mark the handle as invalid and we'll open it + * again if apr_dir_read() is subsequently called + */ + rv = dir_cleanup(dir); + + if (rv == APR_SUCCESS) + rv = apr_dir_read(NULL, 0, dir); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, + apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) { + return rv; + } + if (!CreateDirectoryW(wpath, NULL)) { + return apr_get_os_error(); + } + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + if (!CreateDirectory(path, NULL)) { + return apr_get_os_error(); + } +#endif + return APR_SUCCESS; +} + + +static apr_status_t dir_make_parent(char *path, + apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_status_t rv; + char *ch = strrchr(path, '\\'); + if (!ch) { + return APR_ENOENT; + } + + *ch = '\0'; + rv = apr_dir_make (path, perm, pool); /* Try to make straight off */ + + if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */ + rv = dir_make_parent(path, perm, pool); + + if (rv == APR_SUCCESS) { + rv = apr_dir_make (path, perm, pool); /* And complete the path */ + } + } + + *ch = '\\'; /* Always replace the slash before returning */ + return rv; +} + +APR_DECLARE(apr_status_t) apr_dir_make_recursive(const char *path, + apr_fileperms_t perm, + apr_pool_t *pool) +{ + apr_status_t rv = 0; + + rv = apr_dir_make (path, perm, pool); /* Try to make PATH right out */ + + if (APR_STATUS_IS_EEXIST(rv)) /* It's OK if PATH exists */ + return APR_SUCCESS; + + if (APR_STATUS_IS_ENOENT(rv)) { /* Missing an intermediate dir */ + char *dir; + + rv = apr_filepath_merge(&dir, "", path, APR_FILEPATH_NATIVE, pool); + + if (rv == APR_SUCCESS) + rv = dir_make_parent(dir, perm, pool); /* Make intermediate dirs */ + + if (rv == APR_SUCCESS) + rv = apr_dir_make (dir, perm, pool); /* And complete the path */ + } + return rv; +} + + +APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) { + return rv; + } + if (!RemoveDirectoryW(wpath)) { + return apr_get_os_error(); + } + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + if (!RemoveDirectory(path)) { + return apr_get_os_error(); + } +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, + apr_dir_t *dir) +{ + if (dir == NULL) { + return APR_ENODIR; + } + *thedir = dir->dirhand; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, + apr_os_dir_t *thedir, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/file_io/win32/filedup.c b/srclib/apr/file_io/win32/filedup.c new file mode 100644 index 0000000000..d2e3af46b0 --- /dev/null +++ b/srclib/apr/file_io/win32/filedup.c @@ -0,0 +1,179 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include +#include "apr_arch_inherit.h" + +APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, + apr_file_t *old_file, apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + HANDLE hproc = GetCurrentProcess(); + HANDLE newhand = NULL; + + if (!DuplicateHandle(hproc, old_file->filehand, + hproc, &newhand, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + return apr_get_os_error(); + } + + (*new_file) = (apr_file_t *) apr_pcalloc(p, sizeof(apr_file_t)); + (*new_file)->filehand = newhand; + (*new_file)->flags = old_file->flags & ~APR_INHERIT; + (*new_file)->pool = p; + (*new_file)->fname = apr_pstrdup(p, old_file->fname); + (*new_file)->append = old_file->append; + (*new_file)->buffered = FALSE; + (*new_file)->ungetchar = old_file->ungetchar; + +#if APR_HAS_THREADS + if (old_file->mutex) { + apr_thread_mutex_create(&((*new_file)->mutex), + APR_THREAD_MUTEX_DEFAULT, p); + } +#endif + + apr_pool_cleanup_register((*new_file)->pool, (void *)(*new_file), file_cleanup, + apr_pool_cleanup_null); + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0); + + return APR_SUCCESS; +#endif /* !defined(_WIN32_WCE) */ +} + +#define stdin_handle 0x01 +#define stdout_handle 0x02 +#define stderr_handle 0x04 + +APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, + apr_file_t *old_file, apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + DWORD stdhandle = 0; + HANDLE hproc = GetCurrentProcess(); + HANDLE newhand = NULL; + apr_int32_t newflags; + + /* dup2 is not supported literaly with native Windows handles. + * We can, however, emulate dup2 for the standard i/o handles, + * and close and replace other handles with duped handles. + * The os_handle will change, however. + */ + if (new_file->filehand == GetStdHandle(STD_ERROR_HANDLE)) { + stdhandle |= stderr_handle; + } + if (new_file->filehand == GetStdHandle(STD_OUTPUT_HANDLE)) { + stdhandle |= stdout_handle; + } + if (new_file->filehand == GetStdHandle(STD_INPUT_HANDLE)) { + stdhandle |= stdin_handle; + } + + if (stdhandle) { + if (!DuplicateHandle(hproc, old_file->filehand, + hproc, &newhand, 0, + TRUE, DUPLICATE_SAME_ACCESS)) { + return apr_get_os_error(); + } + if (((stdhandle & stderr_handle) && !SetStdHandle(STD_ERROR_HANDLE, newhand)) || + ((stdhandle & stdout_handle) && !SetStdHandle(STD_OUTPUT_HANDLE, newhand)) || + ((stdhandle & stdin_handle) && !SetStdHandle(STD_INPUT_HANDLE, newhand))) { + return apr_get_os_error(); + } + newflags = old_file->flags | APR_INHERIT; + } + else { + if (!DuplicateHandle(hproc, old_file->filehand, + hproc, &newhand, 0, + FALSE, DUPLICATE_SAME_ACCESS)) { + return apr_get_os_error(); + } + newflags = old_file->flags & ~APR_INHERIT; + } + + if (new_file->filehand && (new_file->filehand != INVALID_HANDLE_VALUE)) { + CloseHandle(new_file->filehand); + } + + new_file->flags = newflags; + new_file->filehand = newhand; + new_file->fname = apr_pstrdup(new_file->pool, old_file->fname); + new_file->append = old_file->append; + new_file->buffered = FALSE; + new_file->ungetchar = old_file->ungetchar; + +#if APR_HAS_THREADS + if (old_file->mutex) { + apr_thread_mutex_create(&(new_file->mutex), + APR_THREAD_MUTEX_DEFAULT, p); + } +#endif + + return APR_SUCCESS; +#endif /* !defined(_WIN32_WCE) */ +} + +APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p) +{ + *new_file = (apr_file_t *)apr_palloc(p, sizeof(apr_file_t)); + memcpy(*new_file, old_file, sizeof(apr_file_t)); + (*new_file)->pool = p; + if (old_file->buffered) { + (*new_file)->buffer = apr_palloc(p, APR_FILE_BUFSIZE); + if (old_file->direction == 1) { + memcpy((*new_file)->buffer, old_file->buffer, old_file->bufpos); + } + else { + memcpy((*new_file)->buffer, old_file->buffer, old_file->dataRead); + } + } + if (old_file->mutex) { + apr_thread_mutex_create(&((*new_file)->mutex), + APR_THREAD_MUTEX_DEFAULT, p); + apr_thread_mutex_destroy(old_file->mutex); + } + if (old_file->fname) { + (*new_file)->fname = apr_pstrdup(p, old_file->fname); + } + if (!(old_file->flags & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register(p, (void *)(*new_file), + file_cleanup, + file_cleanup); + } + + old_file->filehand = INVALID_HANDLE_VALUE; + apr_pool_cleanup_kill(old_file->pool, (void *)old_file, + file_cleanup); + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new_file)->pollset, 1, p, 0); + + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/win32/filepath.c b/srclib/apr/file_io/win32/filepath.c new file mode 100644 index 0000000000..67dcd71bd7 --- /dev/null +++ b/srclib/apr/file_io/win32/filepath.c @@ -0,0 +1,978 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include +#include + +#ifdef NETWARE +#include +#include +#endif + + /* WinNT accepts several odd forms of a 'root' path. Under Unicode + * calls (ApiFunctionW) the //?/C:/foo or //?/UNC/mach/share/foo forms + * are accepted. Ansi and Unicode functions both accept the //./C:/foo + * form under WinNT/2K. Since these forms are handled in the utf-8 to + * unicode translation phase, we don't want the user confused by them, so + * we will accept them but always return the canonical C:/ or //mach/share/ + * + * OS2 appears immune from the nonsense :) + */ + +APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, + const char **inpath, + apr_int32_t flags, + apr_pool_t *p) +{ + const char *testpath = *inpath; + char *newpath; +#ifdef NETWARE + char seperator[2] = { 0, 0}; + char server[APR_PATH_MAX+1]; + char volume[APR_PATH_MAX+1]; + char file[APR_PATH_MAX+1]; + char *volsep = NULL; + int elements; + + if (inpath && *inpath) + volsep = strchr (*inpath, ':'); + else + return APR_EBADPATH; + + if (strlen(*inpath) > APR_PATH_MAX) { + return APR_EBADPATH; + } + + seperator[0] = (flags & APR_FILEPATH_NATIVE) ? '\\' : '/'; + + /* Allocate and initialize each of the segment buffers + */ + server[0] = volume[0] = file[0] = '\0'; + + /* If we don't have a volume separator then don't bother deconstructing + the path since we won't use the deconstructed information anyway. + */ + if (volsep) { + /* Split the inpath into its separate parts. */ + deconstruct(testpath, server, volume, NULL, file, NULL, &elements, PATH_UNDEF); + + /* If we got a volume part then continue splitting out the root. + Otherwise we either have an incomplete or relative path + */ + if (volume && strlen(volume) > 0) { + newpath = apr_pcalloc(p, strlen(server)+strlen(volume)+5); + construct(newpath, server, volume, NULL, NULL, NULL, PATH_NETWARE); + + /* NetWare doesn't add the root slash so we need to add it manually. + */ + strcat(newpath, seperator); + *rootpath = newpath; + + /* Skip the inpath pointer down to the first non-root character + */ + newpath = volsep; + do { + ++newpath; + } while (*newpath && ((*newpath == '/') || (*newpath == '\\'))); + *inpath = newpath; + + /* Need to handle APR_FILEPATH_TRUENAME checking here. */ + + return APR_SUCCESS; + } + else + return APR_EBADPATH; + } + else if ((**inpath == '/') || (**inpath == '\\')) { + /* if we have a root path without a volume then just split + in same manner as unix although this path will be + incomplete. + */ + *rootpath = apr_pstrdup(p, seperator); + do { + ++(*inpath); + } while ((**inpath == '/') || (**inpath == '\\')); + } + else + return APR_ERELATIVE; + + return APR_EINCOMPLETE; + +#else /* ndef(NETWARE) */ + + char seperator[2]; + const char *delim1; + const char *delim2; + + seperator[0] = (flags & APR_FILEPATH_NATIVE) ? '\\' : '/'; + seperator[1] = 0; + + if (testpath[0] == '/' || testpath[0] == '\\') { + if (testpath[1] == '/' || testpath[1] == '\\') { + +#ifdef WIN32 /* //server/share isn't the only // delimited syntax */ + if ((testpath[2] == '?' || testpath[2] == '.') + && (testpath[3] == '/' || testpath[3] == '\\')) { + if (IS_FNCHAR(testpath[4]) && testpath[5] == ':') + { + apr_status_t rv; + testpath += 4; + /* given '//?/C: or //./C: let us try this + * all over again from the drive designator + */ + rv = apr_filepath_root(rootpath, &testpath, flags, p); + if (!rv || rv == APR_EINCOMPLETE) + *inpath = testpath; + return rv; + } + else if (strncasecmp(testpath + 4, "UNC", 3) == 0 + && (testpath[7] == '/' || testpath[7] == '\\') + && (testpath[2] == '?')) { + /* given '//?/UNC/machine/share, a little magic + * at the end makes this all work out by using + * 'C/machine' as the starting point and replacing + * the UNC delimiters with \'s, including the 'C' + */ + testpath += 6; + } + else + /* This must not be a path to a file, but rather + * a volume or device. Die for now. + */ + return APR_EBADPATH; + } +#endif /* WIN32 (non - //server/share syntax) */ + + /* Evaluate path of '//[machine/[share[/]]]' */ + delim1 = testpath + 2; + do { + /* Protect against //X/ where X is illegal */ + if (*delim1 && !IS_FNCHAR(*(delim1++))) + return APR_EBADPATH; + } while (*delim1 && *delim1 != '/' && *delim1 != '\\'); + + if (*delim1) { + apr_status_t rv; + delim2 = delim1 + 1; + while (*delim2 && *delim2 != '/' && *delim2 != '\\') { + /* Protect against //machine/X/ where X is illegal */ + if (!IS_FNCHAR(*(delim2++))) + return APR_EBADPATH; + } + + /* Copy the '//machine/[share[/]]' path, always providing + * an extra byte for the trailing slash. + */ + newpath = apr_pstrmemdup(p, testpath, delim2 - testpath + 1); + + if (delim2 == delim1 + 1) { + /* We found simply \\machine\, so give up already + */ + *rootpath = newpath; + *inpath = delim2; + return APR_EINCOMPLETE; + } + + if (flags & APR_FILEPATH_TRUENAME) { + /* Validate the \\Machine\Share\ designation, + * Win32 will argue about slashed in UNC paths, + * so use backslashes till we finish testing, + * and add the trailing backslash [required]. + * apr_pstrmemdup above guarentees us the new + * trailing null character. + */ + newpath[0] = '\\'; + newpath[1] = '\\'; + newpath[delim1 - testpath] = '\\'; + newpath[delim2 - testpath] = '\\'; + + rv = filepath_root_test(newpath, p); + if (rv) + return rv; + rv = filepath_root_case(&newpath, newpath, p); + if (rv) + return rv; + newpath[0] = seperator[0]; + newpath[1] = seperator[0]; + newpath[delim1 - testpath] = seperator[0]; + newpath[delim2 - testpath] = (*delim2 ? seperator[0] : '\0'); + } + else { + /* Give back the caller's own choice of delimiters + */ + newpath[0] = testpath[0]; + newpath[1] = testpath[1]; + newpath[delim1 - testpath] = *delim1; + newpath[delim2 - testpath] = *delim2; + } + + /* If this root included the trailing / or \ designation + * then lop off multiple trailing slashes and give back + * appropriate delimiters. + */ + if (*delim2) { + *inpath = delim2 + 1; + while (**inpath == '/' || **inpath == '\\') + ++*inpath; + } + else { + *inpath = delim2; + } + + *rootpath = newpath; + return APR_SUCCESS; + } + + /* Have path of '\\[machine]', if the machine is given, + * append same trailing slash as the leading slash + */ + delim1 = strchr(testpath, '\0'); + if (delim1 > testpath + 2) { + newpath = apr_pstrndup(p, testpath, delim1 - testpath + 1); + if (flags & APR_FILEPATH_TRUENAME) + newpath[delim1 - testpath] = seperator[0]; + else + newpath[delim1 - testpath] = newpath[0]; + newpath[delim1 - testpath + 1] = '\0'; + } + else { + newpath = apr_pstrndup(p, testpath, delim1 - testpath); + if (flags & APR_FILEPATH_TRUENAME) { + newpath[delim1 - testpath] = seperator[0]; + } + } + if (flags & APR_FILEPATH_TRUENAME) { + newpath[0] = seperator[0]; + newpath[1] = seperator[0]; + } + *rootpath = newpath; + *inpath = delim1; + return APR_EINCOMPLETE; + } + + /* Left with a path of '/', what drive are we asking about? + */ + *inpath = testpath + 1; + newpath = apr_palloc(p, 2); + if (flags & APR_FILEPATH_TRUENAME) + newpath[0] = seperator[0]; + else + newpath[0] = testpath[0]; + newpath[1] = '\0'; + *rootpath = newpath; + return APR_EINCOMPLETE; + } + + /* Evaluate path of 'd:[/]' */ + if (IS_FNCHAR(*testpath) && testpath[1] == ':') + { + apr_status_t rv; + /* Validate that D:\ drive exists, test must be rooted + * Note that posix/win32 insists a drive letter is upper case, + * so who are we to argue with a 'feature'. + * It is a safe fold, since only A-Z is legal, and has no + * side effects of legal mis-mapped non-us-ascii codes. + */ + newpath = apr_palloc(p, 4); + newpath[0] = testpath[0]; + newpath[1] = testpath[1]; + newpath[2] = seperator[0]; + newpath[3] = '\0'; + if (flags & APR_FILEPATH_TRUENAME) { + newpath[0] = apr_toupper(newpath[0]); + rv = filepath_root_test(newpath, p); + if (rv) + return rv; + } + /* Just give back the root the user handed to us. + */ + if (testpath[2] != '/' && testpath[2] != '\\') { + newpath[2] = '\0'; + *rootpath = newpath; + *inpath = testpath + 2; + return APR_EINCOMPLETE; + } + + /* strip off remaining slashes that designate the root, + * give the caller back their original choice of slash + * unless this is TRUENAME'ed + */ + *inpath = testpath + 3; + while (**inpath == '/' || **inpath == '\\') + ++*inpath; + if (!(flags & APR_FILEPATH_TRUENAME)) + newpath[2] = testpath[2]; + *rootpath = newpath; + return APR_SUCCESS; + } + + /* Nothing interesting */ + return APR_ERELATIVE; + +#endif /* ndef(NETWARE) */ +} + + +APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, + const char *basepath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; /* isn't null term */ + const char *baseroot = NULL; + const char *addroot; + apr_size_t rootlen; /* the length of the root portion of path, d:/ is 3 */ + apr_size_t baselen; /* the length of basepath (excluding baseroot) */ + apr_size_t keptlen; /* the length of the retained basepath (incl root) */ + apr_size_t pathlen; /* the length of the result path */ + apr_size_t segend; /* the end of the current segment */ + apr_size_t seglen; /* the length of the segment (excl trailing chars) */ + apr_status_t basetype = 0; /* from parsing the basepath's baseroot */ + apr_status_t addtype; /* from parsing the addpath's addroot */ + apr_status_t rv; +#ifndef NETWARE + int fixunc = 0; /* flag to complete an incomplete UNC basepath */ +#endif + + /* Treat null as an empty path, otherwise split addroot from the addpath + */ + if (!addpath) { + addpath = addroot = ""; + addtype = APR_ERELATIVE; + } + else { + /* This call _should_ test the path + */ + addtype = apr_filepath_root(&addroot, &addpath, + APR_FILEPATH_TRUENAME + | (flags & APR_FILEPATH_NATIVE), + p); + if (addtype == APR_SUCCESS) { + addtype = APR_EABSOLUTE; + } + else if (addtype == APR_ERELATIVE) { + addroot = ""; + } + else if (addtype != APR_EINCOMPLETE) { + /* apr_filepath_root was incomprehensible so fail already + */ + return addtype; + } + } + + /* If addpath is (even partially) rooted, then basepath is + * unused. Ths violates any APR_FILEPATH_SECUREROOTTEST + * and APR_FILEPATH_NOTABSOLUTE flags specified. + */ + if (addtype == APR_EABSOLUTE || addtype == APR_EINCOMPLETE) + { + if (flags & APR_FILEPATH_SECUREROOTTEST) + return APR_EABOVEROOT; + if (flags & APR_FILEPATH_NOTABSOLUTE) + return addtype; + } + + /* Optimized tests before we query the current working path + */ + if (!basepath) { + + /* If APR_FILEPATH_NOTABOVEROOT wasn't specified, + * we won't test the root again, it's ignored. + * Waste no CPU retrieving the working path. + */ + if (addtype == APR_EABSOLUTE && !(flags & APR_FILEPATH_NOTABOVEROOT)) { + basepath = baseroot = ""; + basetype = APR_ERELATIVE; + } + + /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller + * requires an absolutely relative result, So do not retrieve + * the working path. + */ + if (addtype == APR_ERELATIVE && (flags & APR_FILEPATH_NOTABSOLUTE)) { + basepath = baseroot = ""; + basetype = APR_ERELATIVE; + } + } + + if (!basepath) + { + /* Start with the current working path. This is bass akwards, + * but required since the compiler (at least vc) doesn't like + * passing the address of a char const* for a char** arg. + * We must grab the current path of the designated drive + * if addroot is given in drive-relative form (e.g. d:foo) + */ + char *getpath; +#ifndef NETWARE + if (addtype == APR_EINCOMPLETE && addroot[1] == ':') + rv = filepath_drive_get(&getpath, addroot[0], flags, p); + else +#endif + rv = apr_filepath_get(&getpath, flags, p); + if (rv != APR_SUCCESS) + return rv; + basepath = getpath; + } + + if (!baseroot) { + /* This call should _not_ test the path + */ + basetype = apr_filepath_root(&baseroot, &basepath, + (flags & APR_FILEPATH_NATIVE), p); + if (basetype == APR_SUCCESS) { + basetype = APR_EABSOLUTE; + } + else if (basetype == APR_ERELATIVE) { + baseroot = ""; + } + else if (basetype != APR_EINCOMPLETE) { + /* apr_filepath_root was incomprehensible so fail already + */ + return basetype; + } + } + baselen = strlen(basepath); + + /* If APR_FILEPATH_NOTABSOLUTE is specified, the caller + * requires an absolutely relative result. If the given + * basepath is not relative then fail. + */ + if ((flags & APR_FILEPATH_NOTABSOLUTE) && basetype != APR_ERELATIVE) + return basetype; + + /* The Win32 nightmare on unc street... start combining for + * many possible root combinations. + */ + if (addtype == APR_EABSOLUTE) + { + /* Ignore the given root path, and start with the addroot + */ + if ((flags & APR_FILEPATH_NOTABOVEROOT) + && strncmp(baseroot, addroot, strlen(baseroot))) + return APR_EABOVEROOT; + keptlen = 0; + rootlen = pathlen = strlen(addroot); + memcpy(path, addroot, pathlen); + } + else if (addtype == APR_EINCOMPLETE) + { + /* There are several types of incomplete paths, + * incomplete UNC paths (//foo/ or //), + * drives without rooted paths (d: as in d:foo), + * and simple roots (/ as in /foo). + * Deal with these in significantly different manners... + */ +#ifndef NETWARE + if ((addroot[0] == '/' || addroot[0] == '\\') && + (addroot[1] == '/' || addroot[1] == '\\')) + { + /* Ignore the given root path if the incomplete addpath is UNC, + * (note that the final result will be incomplete). + */ + if (flags & APR_FILEPATH_NOTRELATIVE) + return addtype; + if ((flags & APR_FILEPATH_NOTABOVEROOT) + && strncmp(baseroot, addroot, strlen(baseroot))) + return APR_EABOVEROOT; + fixunc = 1; + keptlen = 0; + rootlen = pathlen = strlen(addroot); + memcpy(path, addroot, pathlen); + } + else +#endif + if ((addroot[0] == '/' || addroot[0] == '\\') && !addroot[1]) + { + /* Bring together the drive or UNC root from the baseroot + * if the addpath is a simple root and basepath is rooted, + * otherwise disregard the basepath entirely. + */ + if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) + return basetype; + if (basetype != APR_ERELATIVE) { +#ifndef NETWARE + if (basetype == APR_INCOMPLETE + && (baseroot[0] == '/' || baseroot[0] == '\\') + && (baseroot[1] == '/' || baseroot[1] == '\\')) + fixunc = 1; +#endif + keptlen = rootlen = pathlen = strlen(baseroot); + memcpy(path, baseroot, pathlen); + } + else { + if (flags & APR_FILEPATH_NOTABOVEROOT) + return APR_EABOVEROOT; + keptlen = 0; + rootlen = pathlen = strlen(addroot); + memcpy(path, addroot, pathlen); + } + } +#ifdef NETWARE + else if (filepath_has_drive(addroot, DRIVE_ONLY, p)) + { + /* If the addroot is a drive (without a volume root) + * use the basepath _if_ it matches this drive letter! + * Otherwise we must discard the basepath. + */ + if (!filepath_compare_drive(addroot, baseroot, p) && + filepath_has_drive(baseroot, 0, p)) { +#else + else if (addroot[0] && addroot[1] == ':' && !addroot[2]) + { + /* If the addroot is a drive (without a volume root) + * use the basepath _if_ it matches this drive letter! + * Otherwise we must discard the basepath. + */ + if (addroot[0] == baseroot[0] && baseroot[1] == ':') { +#endif + /* Base the result path on the basepath + */ + if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) + return basetype; + rootlen = strlen(baseroot); + keptlen = pathlen = rootlen + baselen; + if (keptlen >= sizeof(path)) + return APR_ENAMETOOLONG; + memcpy(path, baseroot, rootlen); + memcpy(path + rootlen, basepath, baselen); + } + else { + if (flags & APR_FILEPATH_NOTRELATIVE) + return addtype; + if (flags & APR_FILEPATH_NOTABOVEROOT) + return APR_EABOVEROOT; + keptlen = 0; + rootlen = pathlen = strlen(addroot); + memcpy(path, addroot, pathlen); + } + } + else { + /* Now this is unexpected, we aren't aware of any other + * incomplete path forms! Fail now. + */ + return APR_EBADPATH; + } + } + else { /* addtype == APR_ERELATIVE */ + /* If both paths are relative, fail early + */ + if (basetype != APR_EABSOLUTE && (flags & APR_FILEPATH_NOTRELATIVE)) + return basetype; + +#ifndef NETWARE + /* An incomplete UNC path must be completed + */ + if (basetype == APR_INCOMPLETE + && (baseroot[0] == '/' || baseroot[0] == '\\') + && (baseroot[1] == '/' || baseroot[1] == '\\')) + fixunc = 1; +#endif + + /* Base the result path on the basepath + */ + rootlen = strlen(baseroot); + keptlen = pathlen = rootlen + baselen; + if (keptlen >= sizeof(path)) + return APR_ENAMETOOLONG; + memcpy(path, baseroot, rootlen); + memcpy(path + rootlen, basepath, baselen); + } + + /* '/' terminate the given root path unless it's already terminated + * or is an incomplete drive root. Correct the trailing slash unless + * we have an incomplete UNC path still to fix. + */ + if (pathlen && path[pathlen - 1] != ':') { + if (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\') { + if (pathlen + 1 >= sizeof(path)) + return APR_ENAMETOOLONG; + + path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/'); + } + /* XXX: wrong, but gotta figure out what I intended; + * else if (!fixunc) + * path[pathlen++] = ((flags & APR_FILEPATH_NATIVE) ? '\\' : '/'); + */ + } + + while (*addpath) + { + /* Parse each segment, find the closing '/' + */ + seglen = 0; + while (addpath[seglen] && addpath[seglen] != '/' + && addpath[seglen] != '\\') + ++seglen; + + /* Truncate all trailing spaces and all but the first two dots */ + segend = seglen; + while (seglen && (addpath[seglen - 1] == ' ' + || addpath[seglen - 1] == '.')) { + if (seglen > 2 || addpath[seglen - 1] != '.' || addpath[0] != '.') + --seglen; + else + break; + } + + if (seglen == 0 || (seglen == 1 && addpath[0] == '.')) + { + /* NOTE: win32 _hates_ '/ /' and '/. /' (yes, with spaces in there) + * so eliminate all preconceptions that it is valid. + */ + if (seglen < segend) + return APR_EBADPATH; + +#ifndef NETWARE + /* This isn't legal unless the unc path is completed + */ + if (fixunc) + return APR_EBADPATH; +#endif + + /* Otherwise, this is a noop segment (/ or ./) so ignore it + */ + } + else if (seglen == 2 && addpath[0] == '.' && addpath[1] == '.') + { + /* NOTE: win32 _hates_ '/.. /' (yes, with a space in there) + * and '/..../', some functions treat it as ".", and some + * fail! Eliminate all preconceptions that they are valid. + */ + if (seglen < segend && (seglen != 3 || addpath[2] != '.')) + return APR_EBADPATH; + +#ifndef NETWARE + /* This isn't legal unless the unc path is completed + */ + if (fixunc) + return APR_EBADPATH; +#endif + + /* backpath (../) when an absolute path is given */ + if (rootlen && (pathlen <= rootlen)) + { + /* Attempt to move above root. Always die if the + * APR_FILEPATH_SECUREROOTTEST flag is specified. + */ + if (flags & APR_FILEPATH_SECUREROOTTEST) + return APR_EABOVEROOT; + + /* Otherwise this is simply a noop, above root is root. + */ + } + else if (pathlen == 0 || + (pathlen >= 3 && (pathlen == 3 + || path[pathlen - 4] == ':') + && path[pathlen - 3] == '.' + && path[pathlen - 2] == '.' + && (path[pathlen - 1] == '/' + || path[pathlen - 1] == '\\'))) + { + /* Path is already backpathed or empty, if the + * APR_FILEPATH_SECUREROOTTEST.was given die now. + */ + if (flags & APR_FILEPATH_SECUREROOTTEST) + return APR_EABOVEROOT; + + /* Otherwise append another backpath. + */ + if (pathlen + 3 >= sizeof(path)) + return APR_ENAMETOOLONG; + memcpy(path + pathlen, ((flags & APR_FILEPATH_NATIVE) + ? "..\\" : "../"), 3); + pathlen += 3; + /* The 'root' part of this path now includes the ../ path, + * because that backpath will not be parsed by the truename + * code below. + */ + keptlen = pathlen; + } + else + { + /* otherwise crop the prior segment + */ + do { + --pathlen; + } while (pathlen && path[pathlen - 1] != '/' + && path[pathlen - 1] != '\\'); + + /* Now test if we are above where we started and back up + * the keptlen offset to reflect the added/altered path. + */ + if (pathlen < keptlen) + { + if (flags & APR_FILEPATH_SECUREROOTTEST) + return APR_EABOVEROOT; + keptlen = pathlen; + } + } + } + else /* not empty or dots */ + { +#ifndef NETWARE + if (fixunc) { + const char *testpath = path; + const char *testroot; + apr_status_t testtype; + apr_size_t i = (addpath[segend] != '\0'); + + /* This isn't legal unless the unc path is complete! + */ + if (seglen < segend) + return APR_EBADPATH; + if (pathlen + seglen + 1 >= sizeof(path)) + return APR_ENAMETOOLONG; + memcpy(path + pathlen, addpath, seglen + i); + + /* Always add the trailing slash to a UNC segment + */ + path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) + ? '\\' : '/'); + pathlen += seglen + 1; + + /* Recanonicalize the UNC root with the new UNC segment, + * and if we succeed, reset this test and the rootlen, + * and replace our path with the canonical UNC root path + */ + path[pathlen] = '\0'; + /* This call _should_ test the path + */ + testtype = apr_filepath_root(&testroot, &testpath, + APR_FILEPATH_TRUENAME + | (flags & APR_FILEPATH_NATIVE), + p); + if (testtype == APR_SUCCESS) { + rootlen = pathlen = (testpath - path); + memcpy(path, testroot, pathlen); + fixunc = 0; + } + else if (testtype != APR_EINCOMPLETE) { + /* apr_filepath_root was very unexpected so fail already + */ + return testtype; + } + } + else +#endif + { + /* An actual segment, append it to the destination path + */ + apr_size_t i = (addpath[segend] != '\0'); + if (pathlen + seglen + i >= sizeof(path)) + return APR_ENAMETOOLONG; + memcpy(path + pathlen, addpath, seglen + i); + if (i) + path[pathlen + seglen] = ((flags & APR_FILEPATH_NATIVE) + ? '\\' : '/'); + pathlen += seglen + i; + } + } + + /* Skip over trailing slash to the next segment + */ + if (addpath[segend]) + ++segend; + + addpath += segend; + } + + /* keptlen will be the baselen unless the addpath contained + * backpath elements. If so, and APR_FILEPATH_NOTABOVEROOT + * is specified (APR_FILEPATH_SECUREROOTTEST was caught above), + * compare the string beyond the root to assure the result path + * is still within given basepath. Note that the root path + * segment is thoroughly tested prior to path parsing. + */ + if (flags & APR_FILEPATH_NOTABOVEROOT) { + if (memcmp(basepath, path + rootlen, baselen)) + return APR_EABOVEROOT; + + /* Ahem... if we weren't given a trailing slash on the basepath, + * we better be sure that /foo wasn't replaced with /foobar! + */ + if (basepath[baselen - 1] != '/' && basepath[baselen - 1] != '\\' + && path[rootlen + baselen] && path[rootlen + baselen] != '/' + && path[rootlen + baselen] != '\\') + return APR_EABOVEROOT; + } + + if (addpath && (flags & APR_FILEPATH_TRUENAME)) { + /* We can always skip the root, it's already true-named. */ + if (rootlen > keptlen) + keptlen = rootlen; + if ((path[keptlen] == '/') || (path[keptlen] == '\\')) { + /* By rights, keptlen may grown longer than pathlen. + * we wont' use it again (in that case) so we don't care. + */ + ++keptlen; + } + /* Go through all the new segments */ + while (keptlen < pathlen) { + apr_finfo_t finfo; + char saveslash = 0; + seglen = 0; + /* find any slash and set it aside for a minute. */ + for (seglen = 0; keptlen + seglen < pathlen; ++seglen) { + if ((path[keptlen + seglen] == '/') || + (path[keptlen + seglen] == '\\')) { + saveslash = path[keptlen + seglen]; + break; + } + } + /* Null term for stat! */ + path[keptlen + seglen] = '\0'; + if ((rv = apr_stat(&finfo, path, + APR_FINFO_LINK | APR_FINFO_TYPE | APR_FINFO_NAME, p)) + == APR_SUCCESS) { + apr_size_t namelen = strlen(finfo.name); + +#if defined(OS2) /* only has case folding, never aliases that change the length */ + + if (memcmp(finfo.name, path + keptlen, seglen) != 0) { + memcpy(path + keptlen, finfo.name, namelen); + } +#else /* WIN32 || NETWARE; here there be aliases that gire and gimble and change length */ + + if ((namelen != seglen) || + (memcmp(finfo.name, path + keptlen, seglen) != 0)) + { + if (namelen <= seglen) { + memcpy(path + keptlen, finfo.name, namelen); + if ((namelen < seglen) && saveslash) { + memmove(path + keptlen + namelen + 1, + path + keptlen + seglen + 1, + pathlen - keptlen - seglen); + pathlen += namelen - seglen; + seglen = namelen; + } + } + else { /* namelen > seglen */ + if (pathlen + namelen - seglen >= sizeof(path)) + return APR_ENAMETOOLONG; + if (saveslash) { + memmove(path + keptlen + namelen + 1, + path + keptlen + seglen + 1, + pathlen - keptlen - seglen); + } + memcpy(path + keptlen, finfo.name, namelen); + pathlen += namelen - seglen; + seglen = namelen; + } + } +#endif /* !OS2 (Whatever that alias was we're over it) */ + + /* That's it, the rest is path info. + * I don't know how we aught to handle this. Should + * we define a new error to indicate 'more info'? + * Should we split out the rest of the path? + */ + if ((finfo.filetype != APR_DIR) && + (finfo.filetype != APR_LNK) && saveslash) + rv = APR_ENOTDIR; +#ifdef XXX_FIGURE_THIS_OUT + { + /* the example inserts a null between the end of + * the filename and the next segment, and increments + * the path length so we would return both segments. + */ + if (saveslash) { + keptlen += seglen; + path[keptlen] = saveslash; + if (pathlen + 1 >= sizeof(path)) + return APR_ENAMETOOLONG; + memmove(path + keptlen + 1, + path + keptlen, + pathlen - keptlen); + path[keptlen] = '\0'; + ++pathlen; + break; + } + } +#endif + } + + /* put back the '/' */ + if (saveslash) { + path[keptlen + seglen] = saveslash; + ++seglen; + } + keptlen += seglen; + + if (rv != APR_SUCCESS) { + if (APR_STATUS_IS_ENOENT(rv)) + break; + if (APR_STATUS_IS_EPATHWILD(rv)) + /* This path included wildcards. The path elements + * that did not contain wildcards are canonicalized, + * so we will return the path, although later elements + * don't necessarily exist, and aren't canonical. + */ + break; + else if (APR_STATUS_IS_ENOTDIR(rv)) + /* This is a little more serious, we just added a name + * onto a filename (think http's PATH_INFO) + * If the caller is foolish enough to do this, we expect + * the've already canonicalized the root) that they knew + * what they are doing :( + */ + break; + else + return rv; + } + } + } + + *newpath = apr_pmemdup(p, path, pathlen + 1); + (*newpath)[pathlen] = '\0'; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts, + const char *liststr, + apr_pool_t *p) +{ + return apr_filepath_list_split_impl(pathelts, liststr, ';', p); +} + +APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr, + apr_array_header_t *pathelts, + apr_pool_t *p) +{ + return apr_filepath_list_merge_impl(liststr, pathelts, ';', p); +} + + +APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + *style = APR_FILEPATH_ENCODING_UTF8; + return APR_SUCCESS; + } +#endif + + *style = APR_FILEPATH_ENCODING_LOCALE; + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/win32/filestat.c b/srclib/apr/file_io/win32/filestat.c new file mode 100644 index 0000000000..2d688fce76 --- /dev/null +++ b/srclib/apr/file_io/win32/filestat.c @@ -0,0 +1,760 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_time.h" +#include +#include "apr_arch_atime.h" +#include "apr_arch_misc.h" + +/* We have to assure that the file name contains no '*'s, or other + * wildcards when using FindFirstFile to recover the true file name. + */ +static apr_status_t test_safe_name(const char *name) +{ + /* Only accept ':' in the second position of the filename, + * as the drive letter delimiter: + */ + if (apr_isalpha(*name) && (name[1] == ':')) { + name += 2; + } + while (*name) { + if (!IS_FNCHAR(*name) && (*name != '\\') && (*name != '/')) { + if (*name == '?' || *name == '*') + return APR_EPATHWILD; + else + return APR_EBADPATH; + } + ++name; + } + return APR_SUCCESS; +} + +static apr_status_t free_localheap(void *heap) { + LocalFree(heap); + return APR_SUCCESS; +} + +static apr_gid_t worldid = NULL; + +static void free_world(void) +{ + if (worldid) { + FreeSid(worldid); + worldid = NULL; + } +} + +/* Left bit shifts from World scope to given scope */ +typedef enum prot_scope_e { + prot_scope_world = 0, + prot_scope_group = 4, + prot_scope_user = 8 +} prot_scope_e; + +static apr_fileperms_t convert_prot(ACCESS_MASK acc, prot_scope_e scope) +{ + /* These choices are based on the single filesystem bit that controls + * the given behavior. They are -not- recommended for any set protection + * function, such a function should -set- use GENERIC_READ/WRITE/EXECUTE + */ + apr_fileperms_t prot = 0; + if (acc & FILE_EXECUTE) + prot |= APR_WEXECUTE; + if (acc & FILE_WRITE_DATA) + prot |= APR_WWRITE; + if (acc & FILE_READ_DATA) + prot |= APR_WREAD; + return (prot << scope); +} + +static void resolve_prot(apr_finfo_t *finfo, apr_int32_t wanted, PACL dacl) +{ + TRUSTEE_W ident = {NULL, NO_MULTIPLE_TRUSTEE, TRUSTEE_IS_SID}; + ACCESS_MASK acc; + /* + * This function is only invoked for WinNT, + * there is no reason for os_level testing here. + */ + if ((wanted & APR_FINFO_WPROT) && !worldid) { + SID_IDENTIFIER_AUTHORITY SIDAuth = SECURITY_WORLD_SID_AUTHORITY; + if (AllocateAndInitializeSid(&SIDAuth, 1, SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, &worldid)) + atexit(free_world); + else + worldid = NULL; + } + if ((wanted & APR_FINFO_UPROT) && (finfo->valid & APR_FINFO_USER)) { + ident.TrusteeType = TRUSTEE_IS_USER; + ident.ptstrName = finfo->user; + /* GetEffectiveRightsFromAcl isn't supported under Win9x, + * which shouldn't come as a surprize. Since we are passing + * TRUSTEE_IS_SID, always skip the A->W layer. + */ + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + finfo->protection |= convert_prot(acc, prot_scope_user); + finfo->valid |= APR_FINFO_UPROT; + } + } + /* Windows NT: did not return group rights. + * Windows 2000 returns group rights information. + * Since WinNT kernels don't follow the unix model of + * group associations, this all all pretty mute. + */ + if ((wanted & APR_FINFO_GPROT) && (finfo->valid & APR_FINFO_GROUP)) { + ident.TrusteeType = TRUSTEE_IS_GROUP; + ident.ptstrName = finfo->group; + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + finfo->protection |= convert_prot(acc, prot_scope_group); + finfo->valid |= APR_FINFO_GPROT; + } + } + if ((wanted & APR_FINFO_WPROT) && (worldid)) { + ident.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ident.ptstrName = worldid; + if (GetEffectiveRightsFromAclW(dacl, &ident, &acc) == ERROR_SUCCESS) { + finfo->protection |= convert_prot(acc, prot_scope_world); + finfo->valid |= APR_FINFO_WPROT; + } + } +} + +static apr_status_t resolve_ident(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *pool) +{ + apr_file_t *thefile = NULL; + apr_status_t rv; + /* + * NT5 (W2K) only supports symlinks in the same manner as mount points. + * This code should eventually take that into account, for now treat + * every reparse point as a symlink... + * + * We must open the file with READ_CONTROL if we plan to retrieve the + * user, group or permissions. + */ + + if ((rv = apr_file_open(&thefile, fname, APR_OPENINFO + | ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0) + | ((wanted & (APR_FINFO_PROT | APR_FINFO_OWNER)) + ? APR_READCONTROL : 0), + APR_OS_DEFAULT, pool)) == APR_SUCCESS) { + rv = apr_file_info_get(finfo, wanted, thefile); + finfo->filehand = NULL; + apr_file_close(thefile); + } + else if (APR_STATUS_IS_EACCES(rv) && (wanted & (APR_FINFO_PROT + | APR_FINFO_OWNER))) { + /* We have a backup plan. Perhaps we couldn't grab READ_CONTROL? + * proceed without asking for that permission... + */ + if ((rv = apr_file_open(&thefile, fname, APR_OPENINFO + | ((wanted & APR_FINFO_LINK) ? APR_OPENLINK : 0), + APR_OS_DEFAULT, pool)) == APR_SUCCESS) { + rv = apr_file_info_get(finfo, wanted & ~(APR_FINFO_PROT + | APR_FINFO_OWNER), + thefile); + finfo->filehand = NULL; + apr_file_close(thefile); + } + } + + if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) + return (rv); + + /* We picked up this case above and had opened the link's properties */ + if (wanted & APR_FINFO_LINK) + finfo->valid |= APR_FINFO_LINK; + + return rv; +} + +static void guess_protection_bits(apr_finfo_t *finfo) +{ + /* Read, write execute for owner. In the Win9x environment, any + * readable file is executable (well, not entirely 100% true, but + * still looking for some cheap logic that would help us here.) + * The same holds on NT if a file doesn't have a DACL (e.g., on FAT) + */ + if (finfo->protection & APR_FREADONLY) { + finfo->protection |= APR_WREAD | APR_WEXECUTE; + } + else { + finfo->protection |= APR_WREAD | APR_WEXECUTE | APR_WWRITE; + } + finfo->protection |= (finfo->protection << prot_scope_group) + | (finfo->protection << prot_scope_user); + + finfo->valid |= APR_FINFO_UPROT | APR_FINFO_GPROT | APR_FINFO_WPROT; +} + +apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, + apr_int32_t wanted, int whatfile) +{ + PSID user = NULL, grp = NULL; + PACL dacl = NULL; + apr_status_t rv; + + if (apr_os_level < APR_WIN_NT) + guess_protection_bits(finfo); + else if (wanted & (APR_FINFO_PROT | APR_FINFO_OWNER)) + { + /* On NT this request is incredibly expensive, but accurate. + * Since the WinNT-only functions below are protected by the + * (apr_os_level < APR_WIN_NT) case above, we need no extra + * tests, but remember GetNamedSecurityInfo & GetSecurityInfo + * are not supported on 9x. + */ + SECURITY_INFORMATION sinf = 0; + PSECURITY_DESCRIPTOR pdesc = NULL; + if (wanted & (APR_FINFO_USER | APR_FINFO_UPROT)) + sinf |= OWNER_SECURITY_INFORMATION; + if (wanted & (APR_FINFO_GROUP | APR_FINFO_GPROT)) + sinf |= GROUP_SECURITY_INFORMATION; + if (wanted & APR_FINFO_PROT) + sinf |= DACL_SECURITY_INFORMATION; + if (whatfile == MORE_OF_WFSPEC) { + apr_wchar_t *wfile = (apr_wchar_t*) ufile; + int fix = 0; + if (wcsncmp(wfile, L"\\\\?\\", 4) == 0) { + fix = 4; + if (wcsncmp(wfile + fix, L"UNC\\", 4) == 0) + wfile[6] = L'\\', fix = 6; + } + rv = GetNamedSecurityInfoW(wfile + fix, + SE_FILE_OBJECT, sinf, + ((wanted & APR_FINFO_USER) ? &user : NULL), + ((wanted & APR_FINFO_GROUP) ? &grp : NULL), + ((wanted & APR_FINFO_PROT) ? &dacl : NULL), + NULL, &pdesc); + if (fix == 6) + wfile[6] = L'C'; + } + else if (whatfile == MORE_OF_FSPEC) + rv = GetNamedSecurityInfoA((char*)ufile, + SE_FILE_OBJECT, sinf, + ((wanted & APR_FINFO_USER) ? &user : NULL), + ((wanted & APR_FINFO_GROUP) ? &grp : NULL), + ((wanted & APR_FINFO_PROT) ? &dacl : NULL), + NULL, &pdesc); + else if (whatfile == MORE_OF_HANDLE) + rv = GetSecurityInfo((HANDLE)ufile, + SE_FILE_OBJECT, sinf, + ((wanted & APR_FINFO_USER) ? &user : NULL), + ((wanted & APR_FINFO_GROUP) ? &grp : NULL), + ((wanted & APR_FINFO_PROT) ? &dacl : NULL), + NULL, &pdesc); + else + return APR_INCOMPLETE; + if (rv == ERROR_SUCCESS) + apr_pool_cleanup_register(finfo->pool, pdesc, free_localheap, + apr_pool_cleanup_null); + else + user = grp = dacl = NULL; + + if (user) { + finfo->user = user; + finfo->valid |= APR_FINFO_USER; + } + + if (grp) { + finfo->group = grp; + finfo->valid |= APR_FINFO_GROUP; + } + + if (dacl) { + /* Retrieved the discresionary access list */ + resolve_prot(finfo, wanted, dacl); + } + else if (wanted & APR_FINFO_PROT) + guess_protection_bits(finfo); + } + + return ((wanted & ~finfo->valid) ? APR_INCOMPLETE : APR_SUCCESS); +} + + +/* This generic fillin depends upon byhandle to be passed as 0 when + * a WIN32_FILE_ATTRIBUTE_DATA or either WIN32_FIND_DATA [A or W] is + * passed for wininfo. When the BY_HANDLE_FILE_INFORMATION structure + * is passed for wininfo, byhandle is passed as 1 to offset the one + * dword discrepancy in offset of the High/Low size structure members. + * + * The generic fillin returns 1 if the caller should further inquire + * if this is a CHR filetype. If it's reasonably certain it can't be, + * then the function returns 0. + */ +int fillin_fileinfo(apr_finfo_t *finfo, + WIN32_FILE_ATTRIBUTE_DATA *wininfo, + int byhandle, apr_int32_t wanted) +{ + DWORD *sizes = &wininfo->nFileSizeHigh + byhandle; + int warn = 0; + + memset(finfo, '\0', sizeof(*finfo)); + + FileTimeToAprTime(&finfo->atime, &wininfo->ftLastAccessTime); + FileTimeToAprTime(&finfo->ctime, &wininfo->ftCreationTime); + FileTimeToAprTime(&finfo->mtime, &wininfo->ftLastWriteTime); + +#if APR_HAS_LARGE_FILES + finfo->size = (apr_off_t)sizes[1] + | ((apr_off_t)sizes[0] << 32); +#else + finfo->size = (apr_off_t)sizes[1]; + if (finfo->size < 0 || sizes[0]) + finfo->size = 0x7fffffff; +#endif + + if (wanted & APR_FINFO_LINK && + wininfo->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + finfo->filetype = APR_LNK; + } + else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + finfo->filetype = APR_DIR; + } + else if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_DEVICE) { + /* Warning: This test only succeeds on Win9x, on NT these files + * (con, aux, nul, lpt#, com# etc) escape early detection! + */ + finfo->filetype = APR_CHR; + } + else { + /* Warning: Short of opening the handle to the file, the 'FileType' + * appears to be unknowable (in any trustworthy or consistent sense) + * on WinNT/2K as far as PIPE, CHR, etc are concerned. + */ + if (!wininfo->ftLastWriteTime.dwLowDateTime + && !wininfo->ftLastWriteTime.dwHighDateTime + && !finfo->size) + warn = 1; + finfo->filetype = APR_REG; + } + + /* The following flags are [for this moment] private to Win32. + * That's the only excuse for not toggling valid bits to reflect them. + */ + if (wininfo->dwFileAttributes & FILE_ATTRIBUTE_READONLY) + finfo->protection = APR_FREADONLY; + + finfo->valid = APR_FINFO_ATIME | APR_FINFO_CTIME | APR_FINFO_MTIME + | APR_FINFO_SIZE | APR_FINFO_TYPE; /* == APR_FINFO_MIN */ + + /* Only byhandle optionally tests link targets, so tell that caller + * what it wants to hear, otherwise the byattributes is never + * reporting anything but the link. + */ + if (!byhandle || (wanted & APR_FINFO_LINK)) + finfo->valid |= APR_FINFO_LINK; + return warn; +} + + +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, apr_int32_t wanted, + apr_file_t *thefile) +{ + BY_HANDLE_FILE_INFORMATION FileInfo; + + if (thefile->buffered) { + apr_status_t rv = apr_file_flush(thefile); + if (rv != APR_SUCCESS) + return rv; + } + + if (!GetFileInformationByHandle(thefile->filehand, &FileInfo)) { + return apr_get_os_error(); + } + + fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) &FileInfo, 1, wanted); + + if (finfo->filetype == APR_REG) + { + /* Go the extra mile to be -certain- that we have a real, regular + * file, since the attribute bits aren't a certain thing. Even + * though fillin should have hinted if we *must* do this, we + * don't need to take chances while the handle is already open. + */ + DWORD FileType; + if (FileType = GetFileType(thefile->filehand)) { + if (FileType == FILE_TYPE_CHAR) { + finfo->filetype = APR_CHR; + } + else if (FileType == FILE_TYPE_PIPE) { + finfo->filetype = APR_PIPE; + } + /* Otherwise leave the original conclusion alone + */ + } + } + + finfo->pool = thefile->pool; + + /* ### The finfo lifetime may exceed the lifetime of thefile->pool + * but finfo's aren't managed in pools, so where on earth would + * we pstrdup the fname into??? + */ + finfo->fname = thefile->fname; + + /* Extra goodies known only by GetFileInformationByHandle() */ + finfo->inode = (apr_ino_t)FileInfo.nFileIndexLow + | ((apr_ino_t)FileInfo.nFileIndexHigh << 32); + finfo->device = FileInfo.dwVolumeSerialNumber; + finfo->nlink = FileInfo.nNumberOfLinks; + + finfo->valid |= APR_FINFO_IDENT | APR_FINFO_NLINK; + + /* If we still want something more (besides the name) go get it! + */ + if ((wanted &= ~finfo->valid) & ~APR_FINFO_NAME) { + return more_finfo(finfo, thefile->filehand, wanted, MORE_OF_HANDLE); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, + apr_fileperms_t perms) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *pool) +{ + /* XXX: is constant - needs testing - which requires a lighter-weight root test fn */ + int isroot = 0; + apr_status_t ident_rv = 0; + apr_status_t rv; +#if APR_HAS_UNICODE_FS + apr_wchar_t wfname[APR_PATH_MAX]; + +#endif + char *filename = NULL; + /* These all share a common subset of this structure */ + union { + WIN32_FIND_DATAW w; + WIN32_FIND_DATAA n; + WIN32_FILE_ATTRIBUTE_DATA i; + } FileInfo; + + /* Catch fname length == MAX_PATH since GetFileAttributesEx fails + * with PATH_NOT_FOUND. We would rather indicate length error than + * 'not found' + */ + if (strlen(fname) >= APR_PATH_MAX) { + return APR_ENAMETOOLONG; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + if ((wanted & (APR_FINFO_IDENT | APR_FINFO_NLINK)) + || (~wanted & APR_FINFO_LINK)) { + /* FindFirstFile and GetFileAttributesEx can't figure the inode, + * device or number of links, so we need to resolve with an open + * file handle. If the user has asked for these fields, fall over + * to the get file info by handle method. If we fail, or the user + * also asks for the file name, continue by our usual means. + * + * We also must use this method for a 'true' stat, that resolves + * a symlink (NTFS Junction) target. This is because all fileinfo + * on a Junction always returns the junction, opening the target + * is the only way to resolve the target's attributes. + */ + if ((ident_rv = resolve_ident(finfo, fname, wanted, pool)) + == APR_SUCCESS) + return ident_rv; + else if (ident_rv == APR_INCOMPLETE) + wanted &= ~finfo->valid; + } + + if (rv = utf8_to_unicode_path(wfname, sizeof(wfname) + / sizeof(apr_wchar_t), fname)) + return rv; + if (!(wanted & APR_FINFO_NAME)) { + if (!GetFileAttributesExW(wfname, GetFileExInfoStandard, + &FileInfo.i)) + return apr_get_os_error(); + } + else { + /* Guard against bogus wildcards and retrieve by name + * since we want the true name, and set aside a long + * enough string to handle the longest file name. + */ + char tmpname[APR_FILE_MAX * 3 + 1]; + HANDLE hFind; + if ((rv = test_safe_name(fname)) != APR_SUCCESS) { + return rv; + } + hFind = FindFirstFileW(wfname, &FileInfo.w); + if (hFind == INVALID_HANDLE_VALUE) + return apr_get_os_error(); + FindClose(hFind); + if (unicode_to_utf8_path(tmpname, sizeof(tmpname), + FileInfo.w.cFileName)) { + return APR_ENAMETOOLONG; + } + filename = apr_pstrdup(pool, tmpname); + } + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *root = NULL; + const char *test = fname; + rv = apr_filepath_root(&root, &test, APR_FILEPATH_NATIVE, pool); + isroot = (root && *root && !(*test)); + + if ((apr_os_level >= APR_WIN_98) && (!(wanted & APR_FINFO_NAME) || isroot)) + { + /* cannot use FindFile on a Win98 root, it returns \* + * GetFileAttributesExA is not available on Win95 + */ + if (!GetFileAttributesExA(fname, GetFileExInfoStandard, + &FileInfo.i)) { + return apr_get_os_error(); + } + } + else if (isroot) { + /* This is Win95 and we are trying to stat a root. Lie. + */ + if (GetDriveType(fname) != DRIVE_UNKNOWN) + { + finfo->pool = pool; + finfo->filetype = 0; + finfo->mtime = apr_time_now(); + finfo->protection |= APR_WREAD | APR_WEXECUTE | APR_WWRITE; + finfo->protection |= (finfo->protection << prot_scope_group) + | (finfo->protection << prot_scope_user); + finfo->valid |= APR_FINFO_TYPE | APR_FINFO_PROT + | APR_FINFO_MTIME + | (wanted & APR_FINFO_LINK); + return (wanted &= ~finfo->valid) ? APR_INCOMPLETE + : APR_SUCCESS; + } + else + return APR_FROM_OS_ERROR(ERROR_PATH_NOT_FOUND); + } + else { + /* Guard against bogus wildcards and retrieve by name + * since we want the true name, or are stuck in Win95, + * or are looking for the root of a Win98 drive. + */ + HANDLE hFind; + if ((rv = test_safe_name(fname)) != APR_SUCCESS) { + return rv; + } + hFind = FindFirstFileA(fname, &FileInfo.n); + if (hFind == INVALID_HANDLE_VALUE) { + return apr_get_os_error(); + } + FindClose(hFind); + filename = apr_pstrdup(pool, FileInfo.n.cFileName); + } + } +#endif + + if (ident_rv != APR_INCOMPLETE) { + if (fillin_fileinfo(finfo, (WIN32_FILE_ATTRIBUTE_DATA *) &FileInfo, + 0, wanted)) + { + /* Go the extra mile to assure we have a file. WinNT/2000 seems + * to reliably translate char devices to the path '\\.\device' + * so go ask for the full path. + */ + if (apr_os_level >= APR_WIN_NT) + { +#if APR_HAS_UNICODE_FS + apr_wchar_t tmpname[APR_FILE_MAX]; + apr_wchar_t *tmpoff = NULL; + if (GetFullPathNameW(wfname, sizeof(tmpname) / sizeof(apr_wchar_t), + tmpname, &tmpoff)) + { + if (!wcsncmp(tmpname, L"\\\\.\\", 4)) { +#else + /* Same initial logic as above, but + * only for WinNT/non-UTF-8 builds of APR: + */ + char tmpname[APR_FILE_MAX]; + char *tmpoff; + if (GetFullPathName(fname, sizeof(tmpname), tmpname, &tmpoff)) + { + if (!strncmp(tmpname, "\\\\.\\", 4)) { +#endif + if (tmpoff == tmpname + 4) { + finfo->filetype = APR_CHR; + } + /* For WHATEVER reason, CHR devices such as \\.\con + * or \\.\lpt1 *may*not* update tmpoff; in fact the + * resulting tmpoff is set to NULL. Guard against + * either case. + * + * This code is identical for wide and narrow chars... + */ + else if (!tmpoff) { + tmpoff = tmpname + 4; + while (*tmpoff) { + if (*tmpoff == '\\' || *tmpoff == '/') { + break; + } + ++tmpoff; + } + if (!*tmpoff) { + finfo->filetype = APR_CHR; + } + } + } + } + else { + finfo->valid &= ~APR_FINFO_TYPE; + } + + } + else { + finfo->valid &= ~APR_FINFO_TYPE; + } + } + finfo->pool = pool; + } + + if (filename && !isroot) { + finfo->name = filename; + finfo->valid |= APR_FINFO_NAME; + } + + if (wanted &= ~finfo->valid) { + /* Caller wants more than APR_FINFO_MIN | APR_FINFO_NAME */ +#if APR_HAS_UNICODE_FS + if (apr_os_level >= APR_WIN_NT) + return more_finfo(finfo, wfname, wanted, MORE_OF_WFSPEC); +#endif + return more_finfo(finfo, fname, wanted, MORE_OF_FSPEC); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool) +{ + DWORD flags; + apr_status_t rv; +#if APR_HAS_UNICODE_FS + apr_wchar_t wfname[APR_PATH_MAX]; +#endif + + /* Don't do anything if we can't handle the requested attributes */ + if (!(attr_mask & (APR_FILE_ATTR_READONLY + | APR_FILE_ATTR_HIDDEN))) + return APR_SUCCESS; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + if (rv = utf8_to_unicode_path(wfname, + sizeof(wfname) / sizeof(wfname[0]), + fname)) + return rv; + flags = GetFileAttributesW(wfname); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + flags = GetFileAttributesA(fname); + } +#endif + + if (flags == 0xFFFFFFFF) + return apr_get_os_error(); + + if (attr_mask & APR_FILE_ATTR_READONLY) + { + if (attributes & APR_FILE_ATTR_READONLY) + flags |= FILE_ATTRIBUTE_READONLY; + else + flags &= ~FILE_ATTRIBUTE_READONLY; + } + + if (attr_mask & APR_FILE_ATTR_HIDDEN) + { + if (attributes & APR_FILE_ATTR_HIDDEN) + flags |= FILE_ATTRIBUTE_HIDDEN; + else + flags &= ~FILE_ATTRIBUTE_HIDDEN; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + rv = SetFileAttributesW(wfname, flags); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + rv = SetFileAttributesA(fname, flags); + } +#endif + + if (rv == 0) + return apr_get_os_error(); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool) +{ + apr_file_t *thefile; + apr_status_t rv; + + rv = apr_file_open(&thefile, fname, + APR_READ | APR_WRITEATTRS, + APR_OS_DEFAULT, pool); + if (!rv) + { + FILETIME file_ctime; + FILETIME file_atime; + FILETIME file_mtime; + + if (!GetFileTime(thefile->filehand, + &file_ctime, &file_atime, &file_mtime)) + rv = apr_get_os_error(); + else + { + AprTimeToFileTime(&file_mtime, mtime); + if (!SetFileTime(thefile->filehand, + &file_ctime, &file_atime, &file_mtime)) + rv = apr_get_os_error(); + } + + apr_file_close(thefile); + } + + return rv; +} diff --git a/srclib/apr/file_io/win32/filesys.c b/srclib/apr/file_io/win32/filesys.c new file mode 100644 index 0000000000..6d6c2bce8f --- /dev/null +++ b/srclib/apr/file_io/win32/filesys.c @@ -0,0 +1,229 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" + +/* Win32 Exceptions: + * + * Note that trailing spaces and trailing periods are never recorded + * in the file system, except by a very obscure bug where any file + * that is created with a trailing space or period, followed by the + * ':' stream designator on an NTFS volume can never be accessed again. + * In other words, don't ever accept them when designating a stream! + * + * An interesting side effect is that two or three periods are both + * treated as the parent directory, although the fourth and on are + * not [strongly suggest all trailing periods are trimmed off, or + * down to two if there are no other characters.] + * + * Leading spaces and periods are accepted, however. + * The * ? < > codes all have wildcard side effects + * The " / \ : are exclusively component separator tokens + * The system doesn't accept | for any (known) purpose + * Oddly, \x7f _is_ acceptable ;) + */ + +/* apr_c_is_fnchar[] maps Win32's file name and shell escape symbols + * + * element & 1 == valid file name character [excluding delimiters] + * element & 2 == character should be shell (caret) escaped from cmd.exe + * + * this must be in-sync with Apache httpd's gen_test_char.c for cgi escaping. + */ + +const char apr_c_is_fnchar[256] = +{/* Reject all ctrl codes... Escape \n and \r (ascii 10 and 13) */ + 0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /* ! " # $ % & ' ( ) * + , - . / 0 1 2 3 4 5 6 7 8 9 : ; < = > ? */ + 1,1,2,1,3,3,3,3,3,3,2,1,1,1,1,0, 1,1,1,1,1,1,1,1,1,1,0,3,2,1,2,2, + /* @ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ \ ] ^ _ */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1, + /* ` a b c d e f g h i j k l m n o p q r s t u v w x y z { | } ~ */ + 3,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,3,2,3,3,1, + /* High bit codes are accepted (subject to utf-8->Unicode xlation) */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 +}; + + +apr_status_t filepath_root_test(char *path, apr_pool_t *p) +{ + apr_status_t rv; +#if APR_HAS_UNICODE_FS + if (apr_os_level >= APR_WIN_NT) + { + apr_wchar_t wpath[APR_PATH_MAX]; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) + return rv; + rv = GetDriveTypeW(wpath); + } + else +#endif + rv = GetDriveType(path); + + if (rv == DRIVE_UNKNOWN || rv == DRIVE_NO_ROOT_DIR) + return APR_EBADPATH; + return APR_SUCCESS; +} + + +apr_status_t filepath_drive_get(char **rootpath, char drive, + apr_int32_t flags, apr_pool_t *p) +{ + char path[APR_PATH_MAX]; +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t *ignored; + apr_wchar_t wdrive[8]; + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:" + * as if that is useful for anything. + */ + wcscpy(wdrive, L"D:."); + wdrive[0] = (apr_wchar_t)(unsigned char)drive; + if (!GetFullPathNameW(wdrive, sizeof(wpath) / sizeof(apr_wchar_t), wpath, &ignored)) + return apr_get_os_error(); + if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath))) + return rv; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *ignored; + char drivestr[4]; + drivestr[0] = drive; + drivestr[1] = ':'; + drivestr[2] = '.';; + drivestr[3] = '\0'; + if (!GetFullPathName(drivestr, sizeof(path), path, &ignored)) + return apr_get_os_error(); + } +#endif + if (!(flags & APR_FILEPATH_NATIVE)) { + for (*rootpath = path; **rootpath; ++*rootpath) { + if (**rootpath == '\\') + **rootpath = '/'; + } + } + *rootpath = apr_pstrdup(p, path); + return APR_SUCCESS; +} + + +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t *ignored; + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + apr_wchar_t wroot[APR_PATH_MAX]; + /* ???: This needs review, apparently "\\?\d:." returns "\\?\d:" + * as if that is useful for anything. + */ + if (rv = utf8_to_unicode_path(wroot, sizeof(wroot) + / sizeof(apr_wchar_t), root)) + return rv; + if (!GetFullPathNameW(wroot, sizeof(wpath) / sizeof(apr_wchar_t), wpath, &ignored)) + return apr_get_os_error(); + + /* Borrow wroot as a char buffer (twice as big as necessary) + */ + if ((rv = unicode_to_utf8_path((char*)wroot, sizeof(wroot), wpath))) + return rv; + *rootpath = apr_pstrdup(p, (char*)wroot); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char path[APR_PATH_MAX]; + char *ignored; + if (!GetFullPathName(root, sizeof(path), path, &ignored)) + return apr_get_os_error(); + *rootpath = apr_pstrdup(p, path); + } +#endif + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_filepath_get(char **rootpath, apr_int32_t flags, + apr_pool_t *p) +{ + char path[APR_PATH_MAX]; +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (!GetCurrentDirectoryW(sizeof(wpath) / sizeof(apr_wchar_t), wpath)) + return apr_get_os_error(); + if ((rv = unicode_to_utf8_path(path, sizeof(path), wpath))) + return rv; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + if (!GetCurrentDirectory(sizeof(path), path)) + return apr_get_os_error(); + } +#endif + if (!(flags & APR_FILEPATH_NATIVE)) { + for (*rootpath = path; **rootpath; ++*rootpath) { + if (**rootpath == '\\') + **rootpath = '/'; + } + } + *rootpath = apr_pstrdup(p, path); + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_filepath_set(const char *rootpath, + apr_pool_t *p) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), rootpath)) + return rv; + if (!SetCurrentDirectoryW(wpath)) + return apr_get_os_error(); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + if (!SetCurrentDirectory(rootpath)) + return apr_get_os_error(); + } +#endif + return APR_SUCCESS; +} diff --git a/srclib/apr/file_io/win32/flock.c b/srclib/apr/file_io/win32/flock.c new file mode 100644 index 0000000000..cdbd7e174c --- /dev/null +++ b/srclib/apr/file_io/win32/flock.c @@ -0,0 +1,68 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" + +APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type) +{ +#ifdef _WIN32_WCE + /* The File locking is unsuported on WCE */ + return APR_ENOTIMPL; +#else + const DWORD len = 0xffffffff; + DWORD flags; + + flags = ((type & APR_FLOCK_NONBLOCK) ? LOCKFILE_FAIL_IMMEDIATELY : 0) + + (((type & APR_FLOCK_TYPEMASK) == APR_FLOCK_SHARED) + ? 0 : LOCKFILE_EXCLUSIVE_LOCK); + if (apr_os_level >= APR_WIN_NT) { + /* Syntax is correct, len is passed for LengthLow and LengthHigh*/ + OVERLAPPED offset; + memset (&offset, 0, sizeof(offset)); + if (!LockFileEx(thefile->filehand, flags, 0, len, len, &offset)) + return apr_get_os_error(); + } + else { + if (!LockFile(thefile->filehand, 0, 0, len, 0)) + return apr_get_os_error(); + } + + return APR_SUCCESS; +#endif /* !defined(_WIN32_WCE) */ +} + +APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + DWORD len = 0xffffffff; + + if (apr_os_level >= APR_WIN_NT) { + /* Syntax is correct, len is passed for LengthLow and LengthHigh*/ + OVERLAPPED offset; + memset (&offset, 0, sizeof(offset)); + if (!UnlockFileEx(thefile->filehand, 0, len, len, &offset)) + return apr_get_os_error(); + } + else { + if (!UnlockFile(thefile->filehand, 0, 0, len, 0)) + return apr_get_os_error(); + } + + return APR_SUCCESS; +#endif /* !defined(_WIN32_WCE) */ +} diff --git a/srclib/apr/file_io/win32/open.c b/srclib/apr/file_io/win32/open.c new file mode 100644 index 0000000000..21b4ba7662 --- /dev/null +++ b/srclib/apr/file_io/win32/open.c @@ -0,0 +1,634 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_thread_mutex.h" +#if APR_HAVE_ERRNO_H +#include +#endif +#include +#include +#if APR_HAVE_SYS_STAT_H +#include +#endif +#include "apr_arch_misc.h" +#include "apr_arch_inherit.h" + +#if APR_HAS_UNICODE_FS +apr_status_t utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen, + const char* srcstr) +{ + /* TODO: The computations could preconvert the string to determine + * the true size of the retstr, but that's a memory over speed + * tradeoff that isn't appropriate this early in development. + * + * Allocate the maximum string length based on leading 4 + * characters of \\?\ (allowing nearly unlimited path lengths) + * plus the trailing null, then transform /'s into \\'s since + * the \\?\ form doesn't allow '/' path seperators. + * + * Note that the \\?\ form only works for local drive paths, and + * \\?\UNC\ is needed UNC paths. + */ + apr_size_t srcremains = strlen(srcstr) + 1; + apr_wchar_t *t = retstr; + apr_status_t rv; + + /* This is correct, we don't twist the filename if it is will + * definately be shorter than MAX_PATH. It merits some + * performance testing to see if this has any effect, but there + * seem to be applications that get confused by the resulting + * Unicode \\?\ style file names, especially if they use argv[0] + * or call the Win32 API functions such as GetModuleName, etc. + * Not every application is prepared to handle such names. + * + * Note that a utf-8 name can never result in more wide chars + * than the original number of utf-8 narrow chars. + */ + if (srcremains > MAX_PATH) { + if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) { + wcscpy (retstr, L"\\\\?\\"); + retlen -= 4; + t += 4; + } + else if ((srcstr[0] == '/' || srcstr[0] == '\\') + && (srcstr[1] == '/' || srcstr[1] == '\\') + && (srcstr[2] != '?')) { + /* Skip the slashes */ + srcstr += 2; + srcremains -= 2; + wcscpy (retstr, L"\\\\?\\UNC\\"); + retlen -= 8; + t += 8; + } + } + + if (rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen)) { + return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv; + } + if (srcremains) { + return APR_ENAMETOOLONG; + } + for (; *t; ++t) + if (*t == L'/') + *t = L'\\'; + return APR_SUCCESS; +} + +apr_status_t unicode_to_utf8_path(char* retstr, apr_size_t retlen, + const apr_wchar_t* srcstr) +{ + /* Skip the leading 4 characters if the path begins \\?\, or substitute + * // for the \\?\UNC\ path prefix, allocating the maximum string + * length based on the remaining string, plus the trailing null. + * then transform \\'s back into /'s since the \\?\ form never + * allows '/' path seperators, and APR always uses '/'s. + */ + apr_size_t srcremains = wcslen(srcstr) + 1; + apr_status_t rv; + char *t = retstr; + if (srcstr[0] == L'\\' && srcstr[1] == L'\\' && + srcstr[2] == L'?' && srcstr[3] == L'\\') { + if (srcstr[4] == L'U' && srcstr[5] == L'N' && + srcstr[6] == L'C' && srcstr[7] == L'\\') { + srcremains -= 8; + srcstr += 8; + retstr[0] = '\\'; + retstr[1] = '\\'; + retlen -= 2; + t += 2; + } + else { + srcremains -= 4; + srcstr += 4; + } + } + + if (rv = apr_conv_ucs2_to_utf8(srcstr, &srcremains, t, &retlen)) { + return rv; + } + if (srcremains) { + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} +#endif + +void *res_name_from_filename(const char *file, int global, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t *wpre, *wfile, *ch; + apr_size_t n = strlen(file) + 1; + apr_size_t r, d; + apr_status_t rv; + + if (apr_os_level >= APR_WIN_2000) { + if (global) + wpre = L"Global\\"; + else + wpre = L"Local\\"; + } + else + wpre = L""; + r = wcslen(wpre); + + if (n > 256 - r) { + file += n - 256 - r; + n = 256; + /* skip utf8 continuation bytes */ + while ((*file & 0xC0) == 0x80) { + ++file; + --n; + } + } + wfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t)); + wcscpy(wfile, wpre); + d = n; + if (rv = apr_conv_utf8_to_ucs2(file, &n, wfile + r, &d)) { + return NULL; + } + for (ch = wfile + r; *ch; ++ch) { + if (*ch == ':' || *ch == '/' || *ch == '\\') + *ch = '_'; + } + return wfile; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *nfile, *ch; + apr_size_t n = strlen(file) + 1; + +#if !APR_HAS_UNICODE_FS + apr_status_t rv; + apr_size_t r, d; + char *pre; + + if (apr_os_level >= APR_WIN_2000) { + if (global) + pre = "Global\\"; + else + pre = "Local\\"; + } + else + pre = ""; + r = strlen(pre); + + if (n > 256 - r) { + file += n - 256 - r; + n = 256; + } + nfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t)); + memcpy(nfile, pre, r); + memcpy(nfile + r, file, n); +#else + const apr_size_t r = 0; + if (n > 256) { + file += n - 256; + n = 256; + } + nfile = apr_pmemdup(pool, file, n); +#endif + for (ch = nfile + r; *ch; ++ch) { + if (*ch == ':' || *ch == '/' || *ch == '\\') + *ch = '_'; + } + return nfile; + } +#endif +} + + +apr_status_t file_cleanup(void *thefile) +{ + apr_file_t *file = thefile; + apr_status_t flush_rv = APR_SUCCESS; + + if (file->filehand != INVALID_HANDLE_VALUE) { + + /* In order to avoid later segfaults with handle 'reuse', + * we must protect against the case that a dup2'ed handle + * is being closed, and invalidate the corresponding StdHandle + */ + if (file->filehand == GetStdHandle(STD_ERROR_HANDLE)) { + SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE); + } + if (file->filehand == GetStdHandle(STD_OUTPUT_HANDLE)) { + SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE); + } + if (file->filehand == GetStdHandle(STD_INPUT_HANDLE)) { + SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE); + } + + if (file->buffered) { + flush_rv = apr_file_flush((apr_file_t *)thefile); + } + CloseHandle(file->filehand); + file->filehand = INVALID_HANDLE_VALUE; + } + if (file->pOverlapped && file->pOverlapped->hEvent) { + CloseHandle(file->pOverlapped->hEvent); + file->pOverlapped = NULL; + } + return flush_rv; +} + +APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, + apr_int32_t flag, apr_fileperms_t perm, + apr_pool_t *pool) +{ + HANDLE handle = INVALID_HANDLE_VALUE; + DWORD oflags = 0; + DWORD createflags = 0; + DWORD attributes = 0; + DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE; + apr_status_t rv; + + if (flag & APR_READ) { + oflags |= GENERIC_READ; + } + if (flag & APR_WRITE) { + oflags |= GENERIC_WRITE; + } + if (flag & APR_WRITEATTRS) { + oflags |= FILE_WRITE_ATTRIBUTES; + } + + if (apr_os_level >= APR_WIN_NT) + sharemode |= FILE_SHARE_DELETE; + + if (flag & APR_CREATE) { + if (flag & APR_EXCL) { + /* only create new if file does not already exist */ + createflags = CREATE_NEW; + } else if (flag & APR_TRUNCATE) { + /* truncate existing file or create new */ + createflags = CREATE_ALWAYS; + } else { + /* open existing but create if necessary */ + createflags = OPEN_ALWAYS; + } + } else if (flag & APR_TRUNCATE) { + /* only truncate if file already exists */ + createflags = TRUNCATE_EXISTING; + } else { + /* only open if file already exists */ + createflags = OPEN_EXISTING; + } + + if ((flag & APR_EXCL) && !(flag & APR_CREATE)) { + return APR_EACCES; + } + + if (flag & APR_DELONCLOSE) { + attributes |= FILE_FLAG_DELETE_ON_CLOSE; + } + + if (flag & APR_OPENLINK) { + attributes |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + /* Without READ or WRITE, we fail unless apr called apr_file_open + * internally with the private APR_OPENINFO flag. + * + * With the APR_OPENINFO flag on NT, use the option flag + * FILE_FLAG_BACKUP_SEMANTICS to allow us to open directories. + * See the static resolve_ident() fn in file_io/win32/filestat.c + */ + if (!(flag & (APR_READ | APR_WRITE))) { + if (flag & APR_OPENINFO) { + if (apr_os_level >= APR_WIN_NT) { + attributes |= FILE_FLAG_BACKUP_SEMANTICS; + } + } + else { + return APR_EACCES; + } + if (flag & APR_READCONTROL) + oflags |= READ_CONTROL; + } + + if (flag & APR_XTHREAD) { + /* This win32 specific feature is required + * to allow multiple threads to work with the file. + */ + attributes |= FILE_FLAG_OVERLAPPED; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wfname[APR_PATH_MAX]; + + if (flag & APR_SENDFILE_ENABLED) { + /* This feature is required to enable sendfile operations + * against the file on Win32. Also implies APR_XTHREAD. + */ + flag |= APR_XTHREAD; + attributes |= FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED; + } + + if (rv = utf8_to_unicode_path(wfname, sizeof(wfname) + / sizeof(apr_wchar_t), fname)) + return rv; + handle = CreateFileW(wfname, oflags, sharemode, + NULL, createflags, attributes, 0); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI { + handle = CreateFileA(fname, oflags, sharemode, + NULL, createflags, attributes, 0); + if (flag & APR_SENDFILE_ENABLED) { + /* This feature is not supported on this platform. + */ + flag &= ~APR_SENDFILE_ENABLED; + } + + } +#endif + if (handle == INVALID_HANDLE_VALUE) { + return apr_get_os_error(); + } + + (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*new)->pool = pool; + (*new)->filehand = handle; + (*new)->fname = apr_pstrdup(pool, fname); + (*new)->flags = flag; + (*new)->timeout = -1; + (*new)->ungetchar = -1; + + if (flag & APR_APPEND) { + (*new)->append = 1; + SetFilePointer((*new)->filehand, 0, NULL, FILE_END); + } + if (flag & APR_BUFFERED) { + (*new)->buffered = 1; + (*new)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + } + /* Need the mutex to handled buffered and O_APPEND style file i/o */ + if ((*new)->buffered || (*new)->append) { + rv = apr_thread_mutex_create(&(*new)->mutex, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + if (file_cleanup(*new) == APR_SUCCESS) { + apr_pool_cleanup_kill(pool, *new, file_cleanup); + } + return rv; + } + } + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new)->pollset, 1, pool, 0); + + if (!(flag & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup, + apr_pool_cleanup_null); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file) +{ + apr_status_t stat; + if ((stat = file_cleanup(file)) == APR_SUCCESS) { + apr_pool_cleanup_kill(file->pool, file, file_cleanup); + + if (file->mutex) { + apr_thread_mutex_destroy(file->mutex); + } + + return APR_SUCCESS; + } + return stat; +} + +APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) { + return rv; + } + if (DeleteFileW(wpath)) + return APR_SUCCESS; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + if (DeleteFile(path)) + return APR_SUCCESS; +#endif + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_file_rename(const char *frompath, + const char *topath, + apr_pool_t *pool) +{ + IF_WIN_OS_IS_UNICODE + { +#if APR_HAS_UNICODE_FS + apr_wchar_t wfrompath[APR_PATH_MAX], wtopath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wfrompath, sizeof(wfrompath) + / sizeof(apr_wchar_t), frompath)) { + return rv; + } + if (rv = utf8_to_unicode_path(wtopath, sizeof(wtopath) + / sizeof(apr_wchar_t), topath)) { + return rv; + } +#ifndef _WIN32_WCE + if (MoveFileExW(wfrompath, wtopath, MOVEFILE_REPLACE_EXISTING | + MOVEFILE_COPY_ALLOWED)) +#else + if (MoveFileW(wfrompath, wtopath)) +#endif + return APR_SUCCESS; +#else + if (MoveFileEx(frompath, topath, MOVEFILE_REPLACE_EXISTING | + MOVEFILE_COPY_ALLOWED)) + return APR_SUCCESS; +#endif + } +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Windows 95 and 98 do not support MoveFileEx, so we'll use + * the old MoveFile function. However, MoveFile requires that + * the new file not already exist...so we have to delete that + * file if it does. Perhaps we should back up the to-be-deleted + * file in case something happens? + */ + HANDLE handle = INVALID_HANDLE_VALUE; + + if ((handle = CreateFile(topath, GENERIC_WRITE, 0, 0, + OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE ) + { + CloseHandle(handle); + if (!DeleteFile(topath)) + return apr_get_os_error(); + } + if (MoveFile(frompath, topath)) + return APR_SUCCESS; + } +#endif + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file) +{ + *thefile = file->filehand; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, + apr_pool_t *pool) +{ + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->filehand = *thefile; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->timeout = -1; + (*file)->flags = flags; + + if (flags & APR_APPEND) { + (*file)->append = 1; + } + if (flags & APR_BUFFERED) { + (*file)->buffered = 1; + (*file)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + } + + if ((*file)->append || (*file)->buffered) { + apr_status_t rv; + rv = apr_thread_mutex_create(&(*file)->mutex, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + if (file_cleanup(*file) == APR_SUCCESS) { + apr_pool_cleanup_kill(pool, *file, file_cleanup); + } + return rv; + } + } + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0); + + /* XXX... we pcalloc above so all others are zeroed. + * Should we be testing if thefile is a handle to + * a PIPE and set up the mechanics appropriately? + * + * (*file)->pipe; + */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr) +{ + if (fptr->eof_hit == 1) { + return APR_EOF; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_ERROR_HANDLE); + if (!file_handle || (file_handle == INVALID_HANDLE_VALUE)) { + apr_status_t rv = apr_get_os_error(); + if (rv == APR_SUCCESS) { + return APR_EINVAL; + } + return rv; + } + + return apr_os_file_put(thefile, &file_handle, 0, pool); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (!file_handle || (file_handle == INVALID_HANDLE_VALUE)) { + apr_status_t rv = apr_get_os_error(); + if (rv == APR_SUCCESS) { + return APR_EINVAL; + } + return rv; + } + + return apr_os_file_put(thefile, &file_handle, 0, pool); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_INPUT_HANDLE); + if (!file_handle || (file_handle == INVALID_HANDLE_VALUE)) { + apr_status_t rv = apr_get_os_error(); + if (rv == APR_SUCCESS) { + return APR_EINVAL; + } + return rv; + } + + return apr_os_file_put(thefile, &file_handle, 0, pool); +#endif +} + +APR_POOL_IMPLEMENT_ACCESSOR(file); + +APR_IMPLEMENT_INHERIT_SET(file, flags, pool, file_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, file_cleanup) diff --git a/srclib/apr/file_io/win32/pipe.c b/srclib/apr/file_io/win32/pipe.c new file mode 100644 index 0000000000..f58b432408 --- /dev/null +++ b/srclib/apr/file_io/win32/pipe.c @@ -0,0 +1,182 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#if APR_HAVE_ERRNO_H +#include +#endif +#include +#include +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_STAT_H +#include +#endif +#include "apr_arch_misc.h" + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, apr_interval_time_t timeout) +{ + /* Always OK to unset timeouts */ + if (timeout == -1) { + thepipe->timeout = timeout; + return APR_SUCCESS; + } + if (!thepipe->pipe) { + return APR_ENOTIMPL; + } + if (timeout && !(thepipe->pOverlapped)) { + /* Cannot be nonzero if a pipe was opened blocking + */ + return APR_EINVAL; + } + thepipe->timeout = timeout; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, apr_interval_time_t *timeout) +{ + /* Always OK to get the timeout (even if it's unset ... -1) */ + *timeout = thepipe->timeout; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, apr_file_t **out, apr_pool_t *p) +{ + /* Unix creates full blocking pipes. */ + return apr_create_nt_pipe(in, out, APR_FULL_BLOCK, p); +} + +/* apr_create_nt_pipe() + * An internal (for now) APR function used by apr_proc_create() + * when setting up pipes to communicate with the child process. + * apr_create_nt_pipe() allows setting the blocking mode of each end of + * the pipe when the pipe is created (rather than after the pipe is created). + * A pipe handle must be opened in full async i/o mode in order to + * emulate Unix non-blocking pipes with timeouts. + * + * In general, we don't want to enable child side pipe handles for async i/o. + * This prevents us from enabling both ends of the pipe for async i/o in + * apr_file_pipe_create. + * + * Why not use NamedPipes on NT which support setting pipe state to + * non-blocking? On NT, even though you can set a pipe non-blocking, + * there is no clean way to set event driven non-zero timeouts (e.g select(), + * WaitForSinglelObject, et. al. will not detect pipe i/o). On NT, you + * have to poll the pipe to detect i/o on a non-blocking pipe. + */ +apr_status_t apr_create_nt_pipe(apr_file_t **in, apr_file_t **out, + apr_int32_t blocking_mode, + apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + SECURITY_ATTRIBUTES sa; + static unsigned long id = 0; + DWORD dwPipeMode; + DWORD dwOpenMode; + char name[50]; + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + (*in) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t)); + (*in)->pool = p; + (*in)->fname = NULL; + (*in)->pipe = 1; + (*in)->timeout = -1; + (*in)->ungetchar = -1; + (*in)->eof_hit = 0; + (*in)->filePtr = 0; + (*in)->bufpos = 0; + (*in)->dataRead = 0; + (*in)->direction = 0; + (*in)->pOverlapped = NULL; + (void) apr_pollset_create(&(*in)->pollset, 1, p, 0); + + (*out) = (apr_file_t *)apr_pcalloc(p, sizeof(apr_file_t)); + (*out)->pool = p; + (*out)->fname = NULL; + (*out)->pipe = 1; + (*out)->timeout = -1; + (*out)->ungetchar = -1; + (*out)->eof_hit = 0; + (*out)->filePtr = 0; + (*out)->bufpos = 0; + (*out)->dataRead = 0; + (*out)->direction = 0; + (*out)->pOverlapped = NULL; + (void) apr_pollset_create(&(*out)->pollset, 1, p, 0); + + if (apr_os_level >= APR_WIN_NT) { + /* Create the read end of the pipe */ + dwOpenMode = PIPE_ACCESS_INBOUND; + if (blocking_mode == APR_WRITE_BLOCK /* READ_NONBLOCK */ + || blocking_mode == APR_FULL_NONBLOCK) { + dwOpenMode |= FILE_FLAG_OVERLAPPED; + (*in)->pOverlapped = (OVERLAPPED*) apr_pcalloc(p, sizeof(OVERLAPPED)); + (*in)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + + dwPipeMode = 0; + + sprintf(name, "\\\\.\\pipe\\apr-pipe-%u.%lu", getpid(), id++); + + (*in)->filehand = CreateNamedPipe(name, + dwOpenMode, + dwPipeMode, + 1, //nMaxInstances, + 0, //nOutBufferSize, + 65536, //nInBufferSize, + 1, //nDefaultTimeOut, + &sa); + + /* Create the write end of the pipe */ + dwOpenMode = FILE_ATTRIBUTE_NORMAL; + if (blocking_mode == APR_READ_BLOCK /* WRITE_NONBLOCK */ + || blocking_mode == APR_FULL_NONBLOCK) { + dwOpenMode |= FILE_FLAG_OVERLAPPED; + (*out)->pOverlapped = (OVERLAPPED*) apr_pcalloc(p, sizeof(OVERLAPPED)); + (*out)->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + + (*out)->filehand = CreateFile(name, + GENERIC_WRITE, // access mode + 0, // share mode + &sa, // Security attributes + OPEN_EXISTING, // dwCreationDisposition + dwOpenMode, // Pipe attributes + NULL); // handle to template file + } + else { + /* Pipes on Win9* are blocking. Live with it. */ + if (!CreatePipe(&(*in)->filehand, &(*out)->filehand, &sa, 65536)) { + return apr_get_os_error(); + } + } + + apr_pool_cleanup_register((*in)->pool, (void *)(*in), file_cleanup, + apr_pool_cleanup_null); + apr_pool_cleanup_register((*out)->pool, (void *)(*out), file_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +#endif /* _WIN32_WCE */ +} diff --git a/srclib/apr/file_io/win32/readwrite.c b/srclib/apr/file_io/win32/readwrite.c new file mode 100644 index 0000000000..4e36f0eafd --- /dev/null +++ b/srclib/apr/file_io/win32/readwrite.c @@ -0,0 +1,505 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_errno.h" +#include +#include "apr_arch_atime.h" +#include "apr_arch_misc.h" + +/* + * read_with_timeout() + * Uses async i/o to emulate unix non-blocking i/o with timeouts. + */ +static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t len_in, apr_size_t *nbytes) +{ + apr_status_t rv; + DWORD len = (DWORD)len_in; + *nbytes = 0; + + /* Handle the zero timeout non-blocking case */ + if (file->timeout == 0) { + /* Peek at the pipe. If there is no data available, return APR_EAGAIN. + * If data is available, go ahead and read it. + */ + if (file->pipe) { + DWORD bytes; + if (!PeekNamedPipe(file->filehand, NULL, 0, NULL, &bytes, NULL)) { + rv = apr_get_os_error(); + if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) { + rv = APR_EOF; + } + return rv; + } + else { + if (bytes == 0) { + return APR_EAGAIN; + } + if (len > bytes) { + len = bytes; + } + } + } + else { + /* ToDo: Handle zero timeout non-blocking file i/o + * This is not needed until an APR application needs to + * timeout file i/o (which means setting file i/o non-blocking) + */ + } + } + + if (file->pOverlapped && !file->pipe) { + file->pOverlapped->Offset = (DWORD)file->filePtr; + file->pOverlapped->OffsetHigh = (DWORD)(file->filePtr >> 32); + } + + *nbytes = 0; + rv = ReadFile(file->filehand, buf, len, (LPDWORD)nbytes, file->pOverlapped); + + if (!rv) { + rv = apr_get_os_error(); + if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { + /* Wait for the pending i/o */ + if (file->timeout > 0) { + /* timeout in milliseconds... */ + rv = WaitForSingleObject(file->pOverlapped->hEvent, + (DWORD)(file->timeout/1000)); + } + else if (file->timeout == -1) { + rv = WaitForSingleObject(file->pOverlapped->hEvent, INFINITE); + } + switch (rv) { + case WAIT_OBJECT_0: + GetOverlappedResult(file->filehand, file->pOverlapped, + (LPDWORD)nbytes, TRUE); + rv = APR_SUCCESS; + break; + case WAIT_TIMEOUT: + rv = APR_TIMEUP; + break; + case WAIT_FAILED: + rv = apr_get_os_error(); + break; + default: + break; + } + if (rv != APR_SUCCESS) { + if (apr_os_level >= APR_WIN_98) + CancelIo(file->filehand); + } + } + else if (rv == APR_FROM_OS_ERROR(ERROR_BROKEN_PIPE)) { + /* Assume ERROR_BROKEN_PIPE signals an EOF reading from a pipe */ + rv = APR_EOF; + } + } else { + /* OK and 0 bytes read ==> end of file */ + if (*nbytes == 0) + rv = APR_EOF; + else + rv = APR_SUCCESS; + } + if (rv == APR_SUCCESS && file->pOverlapped && !file->pipe) { + file->filePtr += *nbytes; + } + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *len) +{ + apr_status_t rv; + DWORD bytes_read = 0; + + if (*len <= 0) { + *len = 0; + return APR_SUCCESS; + } + + /* If the file is open for xthread support, allocate and + * initialize the overlapped and io completion event (hEvent). + * Threads should NOT share an apr_file_t or its hEvent. + */ + if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) { + thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool, + sizeof(OVERLAPPED)); + thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!thefile->pOverlapped->hEvent) { + rv = apr_get_os_error(); + return rv; + } + } + + /* Handle the ungetchar if there is one */ + if (thefile->ungetchar != -1) { + bytes_read = 1; + *(char *)buf = (char)thefile->ungetchar; + buf = (char *)buf + 1; + (*len)--; + thefile->ungetchar = -1; + if (*len == 0) { + *len = bytes_read; + return APR_SUCCESS; + } + } + if (thefile->buffered) { + char *pos = (char *)buf; + apr_size_t blocksize; + apr_size_t size = *len; + + apr_thread_mutex_lock(thefile->mutex); + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = 0; + thefile->direction = 0; + thefile->dataRead = 0; + } + + rv = 0; + while (rv == 0 && size > 0) { + if (thefile->bufpos >= thefile->dataRead) { + apr_size_t read; + rv = read_with_timeout(thefile, thefile->buffer, + APR_FILE_BUFSIZE, &read); + if (read == 0) { + if (rv == APR_EOF) + thefile->eof_hit = TRUE; + break; + } + else { + thefile->dataRead = read; + thefile->filePtr += thefile->dataRead; + thefile->bufpos = 0; + } + } + + blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size; + memcpy(pos, thefile->buffer + thefile->bufpos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + *len = pos - (char *)buf; + if (*len) { + rv = APR_SUCCESS; + } + apr_thread_mutex_unlock(thefile->mutex); + } else { + /* Unbuffered i/o */ + apr_size_t nbytes; + rv = read_with_timeout(thefile, buf, *len, &nbytes); + *len = nbytes; + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) +{ + apr_status_t rv; + DWORD bwrote; + + /* If the file is open for xthread support, allocate and + * initialize the overlapped and io completion event (hEvent). + * Threads should NOT share an apr_file_t or its hEvent. + */ + if ((thefile->flags & APR_XTHREAD) && !thefile->pOverlapped ) { + thefile->pOverlapped = (OVERLAPPED*) apr_pcalloc(thefile->pool, + sizeof(OVERLAPPED)); + thefile->pOverlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!thefile->pOverlapped->hEvent) { + rv = apr_get_os_error(); + return rv; + } + } + + if (thefile->buffered) { + char *pos = (char *)buf; + apr_size_t blocksize; + apr_size_t size = *nbytes; + + apr_thread_mutex_lock(thefile->mutex); + + if (thefile->direction == 0) { + // Position file pointer for writing at the offset we are logically reading from + apr_off_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + DWORD offlo = (DWORD)offset; + DWORD offhi = (DWORD)(offset >> 32); + if (offset != thefile->filePtr) + SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 1; + } + + rv = 0; + while (rv == 0 && size > 0) { + if (thefile->bufpos == APR_FILE_BUFSIZE) // write buffer is full + rv = apr_file_flush(thefile); + + blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size; + memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + apr_thread_mutex_unlock(thefile->mutex); + return rv; + } else { + if (!thefile->pipe) { + apr_off_t offset = 0; + apr_status_t rc; + if (thefile->append) { + /* apr_file_lock will mutex the file across processes. + * The call to apr_thread_mutex_lock is added to avoid + * a race condition between LockFile and WriteFile + * that occasionally leads to deadlocked threads. + */ + apr_thread_mutex_lock(thefile->mutex); + rc = apr_file_lock(thefile, APR_FLOCK_EXCLUSIVE); + if (rc != APR_SUCCESS) { + apr_thread_mutex_unlock(thefile->mutex); + return rc; + } + rc = apr_file_seek(thefile, APR_END, &offset); + if (rc != APR_SUCCESS) { + apr_thread_mutex_unlock(thefile->mutex); + return rc; + } + } + if (thefile->pOverlapped) { + thefile->pOverlapped->Offset = (DWORD)thefile->filePtr; + thefile->pOverlapped->OffsetHigh = (DWORD)(thefile->filePtr >> 32); + } + rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, + thefile->pOverlapped); + if (thefile->append) { + apr_file_unlock(thefile); + apr_thread_mutex_unlock(thefile->mutex); + } + } + else { + rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, + thefile->pOverlapped); + } + if (rv) { + *nbytes = bwrote; + rv = APR_SUCCESS; + } + else { + (*nbytes) = 0; + rv = apr_get_os_error(); + if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) { + /* Wait for the pending i/o (put a timeout here?) */ + rv = WaitForSingleObject(thefile->pOverlapped->hEvent, INFINITE); + switch (rv) { + case WAIT_OBJECT_0: + GetOverlappedResult(thefile->filehand, thefile->pOverlapped, (LPDWORD)nbytes, TRUE); + rv = APR_SUCCESS; + break; + case WAIT_TIMEOUT: + rv = APR_TIMEUP; + break; + case WAIT_FAILED: + rv = apr_get_os_error(); + break; + default: + break; + } + if (rv != APR_SUCCESS) { + if (apr_os_level >= APR_WIN_98) + CancelIo(thefile->filehand); + } + } + } + if (rv == APR_SUCCESS && thefile->pOverlapped && !thefile->pipe) { + thefile->filePtr += *nbytes; + } + } + return rv; +} +/* ToDo: Write for it anyway and test the oslevel! + * Too bad WriteFileGather() is not supported on 95&98 (or NT prior to SP2) + */ +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, + apr_size_t *nbytes) +{ + apr_status_t rv = APR_SUCCESS; + apr_size_t i; + apr_size_t bwrote = 0; + char *buf; + + *nbytes = 0; + for (i = 0; i < nvec; i++) { + buf = vec[i].iov_base; + bwrote = vec[i].iov_len; + rv = apr_file_write(thefile, buf, &bwrote); + *nbytes += bwrote; + if (rv != APR_SUCCESS) { + break; + } + } + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) +{ + apr_size_t len = 1; + + return apr_file_write(thefile, &ch, &len); +} + +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) +{ + thefile->ungetchar = (unsigned char) ch; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) +{ + apr_status_t rc; + apr_size_t bread; + + bread = 1; + rc = apr_file_read(thefile, ch, &bread); + + if (rc) { + return rc; + } + + if (bread == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) +{ + apr_size_t len = strlen(str); + + return apr_file_write(thefile, str, &len); +} + +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) +{ + apr_size_t readlen; + apr_status_t rv = APR_SUCCESS; + int i; + + for (i = 0; i < len-1; i++) { + readlen = 1; + rv = apr_file_read(thefile, str+i, &readlen); + + if (readlen != 1) { + rv = APR_EOF; + break; + } + + if (str[i] == '\n') { + i++; /* don't clobber this char below */ + break; + } + } + str[i] = 0; + if (i > 0) { + /* we stored chars; don't report EOF or any other errors; + * the app will find out about that on the next call + */ + return APR_SUCCESS; + } + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) +{ + if (thefile->buffered) { + DWORD numbytes, written = 0; + apr_status_t rc = 0; + char *buffer; + apr_size_t bytesleft; + + if (thefile->direction == 1 && thefile->bufpos) { + buffer = thefile->buffer; + bytesleft = thefile->bufpos; + + do { + if (bytesleft > APR_DWORD_MAX) { + numbytes = APR_DWORD_MAX; + } + else { + numbytes = (DWORD)bytesleft; + } + + if (!WriteFile(thefile->filehand, buffer, numbytes, &written, NULL)) { + rc = apr_get_os_error(); + thefile->filePtr += written; + break; + } + + thefile->filePtr += written; + bytesleft -= written; + buffer += written; + + } while (bytesleft > 0); + + if (rc == 0) + thefile->bufpos = 0; + } + + return rc; + } else { + FlushFileBuffers(thefile->filehand); + return APR_SUCCESS; + } +} + +static int printf_flush(apr_vformatter_buff_t *vbuff) +{ + /* I would love to print this stuff out to the file, but I will + * get that working later. :) For now, just return. + */ + return -1; +} + +APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, + const char *format, ...) +{ + int cc; + va_list ap; + char *buf; + int len; + + buf = malloc(HUGE_STRING_LEN); + if (buf == NULL) { + return 0; + } + va_start(ap, format); + len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap); + cc = apr_file_puts(buf, fptr); + va_end(ap); + free(buf); + return (cc == APR_SUCCESS) ? len : -1; +} + + diff --git a/srclib/apr/file_io/win32/seek.c b/srclib/apr/file_io/win32/seek.c new file mode 100644 index 0000000000..bc075e3a84 --- /dev/null +++ b/srclib/apr/file_io/win32/seek.c @@ -0,0 +1,163 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_file_io.h" +#include "apr_file_io.h" +#include +#include + +static apr_status_t setptr(apr_file_t *thefile, apr_off_t pos ) +{ + apr_size_t newbufpos; + DWORD rc; + + if (thefile->direction == 1) { + apr_file_flush(thefile); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 0; + } + + newbufpos = pos - (thefile->filePtr - thefile->dataRead); + + if (newbufpos >= 0 && newbufpos <= thefile->dataRead) { + thefile->bufpos = (apr_size_t)newbufpos; + rc = 0; + } else { + DWORD offlo = (DWORD)pos; + DWORD offhi = (DWORD)(pos >> 32); + rc = SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN); + + if (rc == 0xFFFFFFFF) + rc = apr_get_os_error(); + else + rc = APR_SUCCESS; + if (rc == APR_SUCCESS) { + thefile->eof_hit = 0; + thefile->bufpos = thefile->dataRead = 0; + thefile->filePtr = pos; + } + } + + return rc; +} + + +APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, apr_seek_where_t where, apr_off_t *offset) +{ + apr_finfo_t finfo; + apr_status_t rc = APR_SUCCESS; + + thefile->eof_hit = 0; + + if (thefile->buffered) { + switch (where) { + case APR_SET: + rc = setptr(thefile, *offset); + break; + + case APR_CUR: + rc = setptr(thefile, thefile->filePtr - thefile->dataRead + + thefile->bufpos + *offset); + break; + + case APR_END: + rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile); + if (rc == APR_SUCCESS) + rc = setptr(thefile, finfo.size + *offset); + break; + + default: + return APR_EINVAL; + } + + *offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + return rc; + } + /* A file opened with APR_XTHREAD has been opened for overlapped i/o. + * APR must explicitly track the file pointer in this case. + */ + else if (thefile->pOverlapped || thefile->flags & APR_XTHREAD) { + switch(where) { + case APR_SET: + thefile->filePtr = *offset; + break; + + case APR_CUR: + thefile->filePtr += *offset; + break; + + case APR_END: + rc = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile); + if (rc == APR_SUCCESS && finfo.size - *offset < 0) + thefile->filePtr = finfo.size - *offset; + break; + + default: + return APR_EINVAL; + } + *offset = thefile->filePtr; + return rc; + } + else { + DWORD howmove; + DWORD offlo = (DWORD)*offset; + DWORD offhi = (DWORD)(*offset >> 32); + + switch(where) { + case APR_SET: + howmove = FILE_BEGIN; break; + case APR_CUR: + howmove = FILE_CURRENT; break; + case APR_END: + howmove = FILE_END; break; + default: + return APR_EINVAL; + } + offlo = SetFilePointer(thefile->filehand, (LONG)offlo, + (LONG*)&offhi, howmove); + if (offlo == 0xFFFFFFFF) + rc = apr_get_os_error(); + else + rc = APR_SUCCESS; + /* Since we can land at 0xffffffff we will measure our APR_SUCCESS */ + if (rc == APR_SUCCESS) + *offset = ((apr_off_t)offhi << 32) | offlo; + return rc; + } +} + + +APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *thefile, apr_off_t offset) +{ + apr_status_t rv; + DWORD offlo = (DWORD)offset; + DWORD offhi = (DWORD)(offset >> 32); + DWORD rc; + + rc = SetFilePointer(thefile->filehand, offlo, &offhi, FILE_BEGIN); + if (rc == 0xFFFFFFFF) + if ((rv = apr_get_os_error()) != APR_SUCCESS) + return rv; + + if (!SetEndOfFile(thefile->filehand)) + return apr_get_os_error(); + + if (thefile->buffered) { + return setptr(thefile, offset); + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/helpers/apr_rename.pl b/srclib/apr/helpers/apr_rename.pl new file mode 100755 index 0000000000..25b9d52d4c --- /dev/null +++ b/srclib/apr/helpers/apr_rename.pl @@ -0,0 +1,106 @@ +#!/usr/bin/perl -w +use strict; +use ExtUtils::MakeMaker qw(prompt); +use File::Find; + +my $just_check = @ARGV ? $ARGV[0] eq '-c' : 0; +shift if $just_check; +my $dir = shift || '.'; +my %names; + +my $prefix = 'apr_'; + +while () { + chomp; + my($old, $new) = grep { s/^$prefix//o } split; + next unless $old and $new; + $names{$old} = $new; +} + +my $pattern = join '|', keys %names; +#print "replacement pattern=$pattern\n"; + +find sub { + chomp; + return unless /\.[ch]$/; + my $file = "$File::Find::dir/$_"; + print "looking in $file\n"; + + replace($_, !$just_check); + +}, $dir; + +sub replace { + my($file, $replace) = @_; + local *IN, *OUT; + my @lines; + my $found = 0; + + open IN, $file or die "open $file: $!"; + + while () { + for (m/[^_\"]*$prefix($pattern)\b/og) { + $found++; + print " $file:$. apr_$_ -> apr_$names{$_}\n"; + } + push @lines, $_ if $replace; + } + + close IN; + + return unless $found and $replace; + +# my $ans = prompt("replace?", 'y'); +# return unless $ans =~ /^y/i; + + open OUT, ">$file" or die "open $file: $!"; + + for (@lines) { + unless (/^\#include/) { + s/([^_\"]*$prefix)($pattern)\b/$1$names{$2}/og; + } + print OUT $_; + } + + close OUT; +} + +__DATA__ +apr_time_t: +apr_implode_gmt apr_time_exp_gmt_get + +apr_socket_t: +apr_close_socket apr_socket_close +apr_create_socket apr_socket_create +apr_get_sockaddr apr_socket_addr_get +apr_get_socketdata apr_socket_data_get +apr_set_socketdata apr_socket_data_set +apr_shutdown apr_socket_shutdown +apr_bind apr_socket_bind +apr_listen apr_socket_listen +apr_accept apr_socket_accept +apr_connect apr_socket_connect +apr_send apr_socket_send +apr_sendv apr_socket_sendv +apr_sendto apr_socket_sendto +apr_recvfrom apr_socket_recvfrom +apr_sendfile apr_socket_sendfile +apr_recv apr_socket_recv + +apr_filepath_*: +apr_filename_of_pathname apr_filepath_name_get + +apr_gid_t: +apr_get_groupid apr_gid_get +apr_get_groupname apr_gid_name_get +apr_group_name_get apr_gid_name_get +apr_compare_groups apr_gid_compare + +apr_uid_t: +apr_get_home_directory apr_uid_homepath_get +apr_get_userid apr_uid_get +apr_current_userid apr_uid_current +apr_compare_users apr_uid_compare +apr_get_username apr_uid_name_get +apr_compare_users apr_uid_compare + diff --git a/srclib/apr/images/ScanDocBig.jpg b/srclib/apr/images/ScanDocBig.jpg new file mode 100644 index 0000000000000000000000000000000000000000..2c47fbc18a370e2e834c976beabbea29686a5efe GIT binary patch literal 5319 zcmb7IXHXMNw@&E26O`TpFCbE-h=6nw#7GH9LJ{dz0@AxQ=`|qIjPw$ajv|P3h|;7> z3mv2>yU{Q0o zv3zM`&F$^*(w^JU-iBKXqWk3fCqNBAL_kPLNI-Nm5#4~8oP_uWlw@Qi5))I9kWheVsc1p}Z(O$l z=*a-D0O^E4UH}0-kdPjD-3ed^009Jqf6wu6kdP7)lMxd9^{UYUfP_Q2lz~Trj8TPG&l1JNEE$@N0rBbQ*RtG_QB`|hT{FxtC2ipTDzyNAlZ5U6 zQ~(g)BqSjHTj3u4O$9qI?T%_X^E+3Vg~K0 zzOTjqzMck95#EH+6Vd~e0lS;}X*@#EC*g&{if>kB;(TkOX7>wzOFz z?C}gr>mwq%Aay?9p;LD-DArh~hVe6@LPt=C!B&+}wpy3fC%wZ^w?w0#{6W%ouYJnj zjPd5YQJ<^K$z$4L?Z*wuHLx#hPX-mZ<9e@vCiw;Fm9`yp zqt}4Ur|kNJ5g&ExO~#o85uW&|FCiymIy`F@zK=gIW+Mhh3pr9P?utH^Gpc76(z4Do zut2}As7NV2AH?^*G_Q7PP*DLbTbbKsLiN#l643v?D(pB{>P+ec}nSl!ey>-27P@bIh@Y)qn84593W!j(nL{YIsas7=X3kHt!Jy*suNpNU~8B4NLrBt z#lJ}S^X80C6S>0yCZ8&+G)HEwFz}1f#uCT+)08GlI+a1q^dBek>ZfRv7M)RF#Jioc z-NGdhY+yYS2x@l?-Zo4ZJPrtnWD`;5ituPqaSz(|4ho21XiSIo`ccfR8YxN5x!5wi z@L6{*5podr@d({$RfAtR$l^2~uiitesXN86(O`6|avFc~ht!D_b${h}$Y-Wu`$FpW zYbtsBOYA^@1DSW@;5Y9L*HWlHaU=A&u>*Y{YSodjG*DjiB_G??ob7INJx2z=lgTPHV+zFom z5#oW7@P@4~9%;?UB1wH9FLjWvYs^l^OeM74*nXqX2E;>g6(teY%d(I1Q$(~4iWAD# zO)h7>ua-+9oD;VZ5Bj*2J?({e7RMiLC%<-kUYIYid}bxJdYNFuL4CYo*lH5`TQXn_ z*NE%k6VkHza&IB^yfv+;b+i|T3l4>0{U2{c3Y#p-`HHa`)o8MG;Y>BY`DWeg6D26r ziUJ2YhFm7q@iXqtN+3H}nhiW|ZDB?^7tTx7lRk!l9fZmkO8GTCk@sulsFOi9l^x*V za_{NH+9~t=-LknFQTOaHlr2)2$GHhacEXyHf*IYHQMn@i-XC3`RuwUG5|{}7!Bl}{ zA2oHMFP8Djn5MkYurWFf-N}DPr81)5^m^ z;P69t36ur1kR$&U|LBBxq}@`=V#1E}J7tQ{J(^wWTd_XnyFAT>$vQUc{oG=>H9fTu zzk-5<{E6r3GXuOdD`;s_nqe!qMwv|XZ$ahmf``u)*kPu8K5afa{WiIQKLJ=c1R?iWC`RSXvUdRn9yOWVQmHrHz=!hCGNI1!@Pq^qR=ug_!sB zu8(t^*_yqs`*GSJepxAkBU69(>&3kRfBsU62gR82!!OX*rm<`>;vQ@UNVG4zIsRk|8RVg=uvN1 z%*WE=>N#+_?arwJnu>>!Vv#yc?=9zlfR>yw5DowYrS>L3vrC6QZ_TKCOpN>MN;P%$ zw_o2{e_SB~Ay6hbX47+|Rzl=RF>$YQd}92GtV>M|Apw*jf2Bq-=LKe?>^q)Dzv5>^ zI#rE2Q@i`2iz6~wEgO#(&!|K5_K(%Dertf?<3ulX>{ z&rr5ISArc>QG(I8OKGRD?gDkVf^fN_pZe_(j+fd8Wf`4xk6wVXl~7oIU3a;cw7-~? zu#Cqd7M>>`ttn3-Eufw(pY`z3bR=h{z-fRG#J&$n6hB>C>j;+X@;$M zWWZzk_5G5A#obHK@7M`(lOog1#a81OD;ZxF6Ri2FP}6W5u+F!*ESl#ZZDB&|(CJUc zAx>Pqt{g+bTKHffGu%hZrQRoO$-0XugFXq9mU2IQzg7Ff^8_w!7<>{mr--LaUCQ1~4L5nzDY<1k>5oB_Rbr%RqUasE4 zfd?#j?lx@VS`rRdyiUfIU(?mQ?SHpnACy8xHoV?RUBmDvo*QD0e;{-+N#s6=zvL>+ zD&;7j7h3cb9&%B!r-V%MJx50+poRNxRRwfaw_KDWm^FND_H~;%(4u_hy67PIzz;d+ zTwW>H@AR3oTeUf`Y+U*QhSGZL675}n4S2mRv?b$j&!%VjkoHsQ4#Q(nx6SeH0}~hB z68{*Zcfk@*x9ge*o$?c&CdlT5EyJYyryfm5Q)(};%mY09FLAuz_AVk9va*^2``$R4 zj`kzGtekA_x{MY>R*919LdYg`55;%s66*3;K6AYdAx!uv(a3xbfdaM9W5!NKqoSI= zc6(&wc+PMeT!r2wHida&8S8i|aI3!ewsQo>!MesnpHq3^-?Hr)G1mZm9(wR{&MmDt zSZd@$o%a#U6iMGZgZfRM51>`&)U-H+s62FhlA!QWuwtjh>hn7+bTeK(Hj0>@e3 z*4UqbOA_0=t0R`eP&65MSCsGJxd!*IA3-~Z#lQWfoAF;noU+Q3>C!GBo&btdm+2HU z7@;!i2ezYl6DWf;P;W|E>PZ~Jam}rNdd5TvQ7|>F1LMC; zDbh?+Le4&SGoMvvz{@Dc&CEMYrI&l?708YBC)F3;=Vt)&tqOU1jlq=83p1W^}`F=6;upqw%+=EESzw>GPmOVe+wQY4g;s{(ggV@{-8u++# ze&ct(*9he-?yc|KiyIti3tl>gZ>%?B;%8x>e*dNv$?IaF&Yqw2 zX=5K&IDdLEe2yMd=n)e3=rkhQy=Y{+5-(SXcFXHK@eSzV>r?l39ba4I zS$U;Dg(Burr&(})SJ8STfm}wldAR#G_8ypZJv7}2VW)kEoFg7wUZ~{Fxy+*CIS+^1 z;g#$%y62=tf?t4DF6K)cXgQu9vDkmeRMwVhqUscL|8ts)An>i9K#m{6#Uh;EaxF$N z*)~)?58M{3)3V9W*<(^7g`2Z26&7RBQKGK*c71yAu*(Opx|4gRo_c-EKi!(0nGc{5 z4n8)=dV>T!d~kT3taG}%*MP6OHtHW{SeGtl7FxfC3bNTwrXK|iZSu?E?~i}*Z8!6^-)AxD$_Gf z>g1f4N?})kv0t1My#fUViKKxG3Vi%FlS?yYV~D*e{s)n{(5re;8e}HY3Zf5Ws-m(1 zgKm`?yG>pLD2(eWMsR8UTnP=PY|!p_gDF|cKXNSO3=(YlcdB{XH{bU;eRC03?0>1k zcESP2LCa0lbdmItMdC*Xe8SpADJ(C#-HgRiB(q(=2yU5}E8X_h0C#qHJMgV;aG_P! z@Tpb$V?M1jGs#{@l#+A=N{RhmNt0Z5T2+Hs&z(SP-E-C;P*hf>SMX8?{jNNFJDT4IUyylJ!eZjA;%%FL>21s4(qvuY{HfksyVpx5s=q?>Cn*9C%6SK)f8Tdx zP0IAyPtM*1jT-wUUet49=LFGn5^Ktn1uiLGMW&l!$A0iPF5`CnW^m|)UG6=dyGC!L zYW)&aCumF)YYyt&`~|wElFuX$Ki~BTo#KMnI1-!ryO%1R?OR32e{)VTf7EeQg%#9r z6qy;G5&a`$Xn+}P*|r<6U=st0R=yKhAs=ViEV?YX24G!`J3pI#X3{l@Z97&(jh5NFtFp z&ddyc7fu>E-HS5!U!kEr*?|^2Q)eQDh~vER1Lo%|58#2zLRtJ4{G7QSE%0NSF|&bG zUhBf%v_G?+c8-XFzCu}H5ymC!JH<|oBqSq;GP|=QB|V^+APE#@Fb{=QS(qP6 z72b(SNWYasg_4$-(IlY_hLt2B^AHX>=j9F@8~CN~d3Bbz>i^u~L*bJa`#8uCm}iMAlT$-=DG_T9 zN%EXZ9B{`HhmCguBaW<6rB6|NL3d=ClLSr7!GO{iY93jBSHD7n;H{l2UTrh#A?C()e|iql*MR=9JshPSX95^U?&Tj=*22b#*FPJd z#&!dz`wqF<_XFRz#PoR4<%M``2BxGH-Z!x>6jEhKDV`IXM)0csB$%a-eDu^VQdsxH z>o~&?VWW-@z8vaFmm`eH7SUY!v!>byYcD(#a_Pmgu(R9&tYrejPicow$(y~>CpGlY>6qjk>^=|)8_?_b_T{zsgrJ7K_l;)hMp8NPPv|I?U%l<9&Nht z0m4hB`^kE6xI`~y$HLA%os|uUTaTfAPjh9wa{#G_(dzA3q(pCaGLkY-?J%*#A9@W? zL4F;w*U!`Y$z603S-EL+e=Vr2>crIBWXSLEhO#d3|7a`!LF2zvvHxZDKTM13ss92| C{__w3 literal 0 HcmV?d00001 diff --git a/srclib/apr/images/ScanDocSmall.jpg b/srclib/apr/images/ScanDocSmall.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a10964aa1331c65ee1e06e20a4eb8c1eede4cc87 GIT binary patch literal 2382 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 AqyPW_ literal 0 HcmV?d00001 diff --git a/srclib/apr/images/ball1.png b/srclib/apr/images/ball1.png new file mode 100644 index 0000000000000000000000000000000000000000..311d4b3fa7a38ff77d5b8d10adace33143acee99 GIT binary patch literal 499 zcmWNMO=#0l0LPyWjd)pzNI_Wd{wdwdq<*Xt(*qu^Dic90p5qVg|($ zoWqD9^E)VtMRCM~IAKEYAQY>$XmJ};DAOG(wyt`q)We?d$Nz)>@jo4l20g9YTLA!` z&{4m_dK+^)Y++e3+upNUi1oz-wrx|YQA+3>q7Dz1Li5TfQq!p27BY{UqgsK7M87SyLvVh2>0;~Wm z0zn0W3^)xS3=lu@R-Ir6H=GIw{YSj7n!ng6g#3r&=e|S=XVgqj+vXKtHF+{|sCvgC zzjONCwecr=zf&5T-QSsi+?(HFrmpXtilqkj)P|+xvMaYQb-|I2rF4GN>iG+?{y+Yn zEAtP6!KuLy+KYd6eDJh6e=iw$9o#xvl5STo?|ygf)|+N+`o^rUBe2X5k%x(6msTn> zoiE2)!atgcNaOhPualmOB{cT*)4s^r^!-&do@q?F>+6FBpF$+?am(n4_ffnbmBQH* nLswIu`+i0bbbsq^bX9t9rp*QK+Q7!zF7^wA0#W}nX*lyAUsB7^ literal 0 HcmV?d00001 diff --git a/srclib/apr/images/ball2.gif b/srclib/apr/images/ball2.gif new file mode 100644 index 0000000000000000000000000000000000000000..9adc11c6473fac16d23a998033587fcd15b834b3 GIT binary patch literal 1014 zcmYk*Pe>F|9KiA4%A!v<;;mUsq13<ryh=SXsN z8^oao;Qv=HEGu$F8DHl_j;~9OEFETtS=lV-x{@U`i))gbHv^_@$g3e^sVo&eL(t1> zoa-UBy1{v&LY@V3J`0#RCTKozHG)(hxQ)<~tpLbwVhAslc+s(=F!qafso5x^55x{w4CV3aTlCgTiO(z75j(2*)J8#qfa zfFU9PFaXUK4A25e&;lxG2rmGrcE|!18G;TfVuAu{fPhLsF$4t^gsVUekdi==7NS4} z!T{lGf1(k9D751Y{7(S+0*xdw^5OKOj#T}=OBZQr``(et=J30L(dCA-mDzY=JpN{? zZn_IfDX(>A{^QBzfluT?N4&r3`ok;VXQQ$C?!>{ldwT{CeJi9Bk@eEE<{S0ZT6^!{ z?UB;v`6tyMi({`Ry4otQWD7fZ|^+sd%87pUw?UGs-^i?Q~S}nhUxg&?pR;<iy*Kt(M9{=T8qBqft2a4{r%bBme*a literal 0 HcmV?d00001 diff --git a/srclib/apr/images/ball2.png b/srclib/apr/images/ball2.png new file mode 100644 index 0000000000000000000000000000000000000000..cac3c07ab113a627c1a7d471636a9833d6b15376 GIT binary patch literal 436 zcmV;l0ZaagP)?rLX6Ha*6%T`r7@iUF1lJ_s(OBMc^PWkY^$h{ayqd<4<5qodVAbu z9MrRka9Khc+EVVId`KJ(0OL*v2Sdpb+0l)e#} zzhI_jV#a3VQ3w{)f>>Y+W`c7_kuo zXhRxWXht>p9Df>uguo$?k42;!RDyC)atb6xgGdk#LJoym*1!^&0}~k08b||4AP$77 zpoSQrK?yA6Fc{j9h8CL17xEZSR9TgLKa52rqQWZV>w*GF7G+i@Y!4{ZDv1&+VLkW( zOmxEz><Ty|ZPDLh> zOb*2}Bahw{yuQAnV|4C!Ch;m2-*sZ^a2_2Vh_y`5cXg+eXD8b-TQ(MbO(m0UGc#S4 z@s{4n@yyZgx7)AXUK=Z^pUeJor0r8}-|Fzvo0nDXH~Z=e3hz`u$#0L}J(GU8bSrm? z4*XcHNDf^}Y`oERT_&|EOGvN(QxARaqk_aS|*erm_B_{ZdhlkX>X=5*vA8(nUl v7|gj+a<%_rnkqMykD{|pGs1VIo2f;1qU zX>1H6fUGnyPD?We!Zc%`D3Acr#>Na_Xv_el85sQe&u;@#j7i?^F5=wRX7mF&hdo^! zLn>~S23{9BWWZC*Fg0+hfaC4||AR%`9$HP>Z4+^=K*rF%r*|`J!0WGNi{np3*2`ot zl}M#0iD+iZOl|(-rr_ONB=2=GW2L{O=354)+LxhhN}tTl&-jLENv%=a=NfR|+1X>+ z7k-~@oGYeyy)bQcea*L7=G6A1`Jav{N~~Rc??j$`@0V9!ZhPLWJCd_!R;vwj48yte zwe7c0ZMT*xcstGh^`_%JKb_umm3VGsh;d->W`Dov)*1#gi@31wT>rk>GYbFUI-zNr y{t@UMu@cva66gHf+|;}h2H(V#RE6@)k_-iRPv3yLRN1LO6%3xPelF{r5}E)JCzlQY literal 0 HcmV?d00001 diff --git a/srclib/apr/images/caution.gif b/srclib/apr/images/caution.gif new file mode 100644 index 0000000000000000000000000000000000000000..39bac17027fb9519cadf8821790bcd5df31096c3 GIT binary patch literal 923 zcmchWv1`71uGqdf_ENR5WKUdxK$r<>L61bmgZ=Rz#*}TBc@7Wf2*k zVHuhsRrE;rbW7KCsa}gTPqQ>llN!}X^;ApMQ~@a^Qar^{G=&6gpuu98ZmB&L9$^t0 zA+?swJ>0@IT#5xn^Dqn3Fey^>s)t&rh6)@R4e<~Q(Ga%68Zb!15?a()3^veUF)Ssh za>CrzT}mHo$;{l;O-e2-D5|-ttDqiI^tzafx*!ifpvg3LpdS(_gf(E0h9#}=U@_Q0 zgC*r$mB|S;lQI&0tR+)56?{c5EGU|&2|nU92EdDUj7BY1;s-RD#tt|k7=^F~4AM+O z3mz;68)&H$RX1gFLbw=4qK~y?D)l(Z*LLqJwiA}k?JCvVj4s!kcQxAVs3SCmh15vb zO&X5^ZqPgju7r7LYOC5y{O>>We^0EBH#U3s@7%lH8w}U4$^4(0sber&;FJ27NXKNV zGk5Oy?7_p%>+#~&n{WHm$Io_0H*P-vG&#J~e{yAU@ALLay*o2`@nP%nnG3g;C*9qT zI}3vcqociztB=mFetq_K>HE-Ej{G`3T;4p`y|g_$_wM?SwWpW&*53E`Uw(NtIy5b- F{{RLp?QsAA literal 0 HcmV?d00001 diff --git a/srclib/apr/images/caution.png b/srclib/apr/images/caution.png new file mode 100644 index 0000000000000000000000000000000000000000..965fe7eb877a16fedbfd0f3d457d0d42632a6430 GIT binary patch literal 217 zcmeAS@N?(olHy`uVBq!ia0vp^f@~ literal 0 HcmV?d00001 diff --git a/srclib/apr/images/master.gif b/srclib/apr/images/master.gif new file mode 100644 index 0000000000000000000000000000000000000000..5751a4030bcc1ebba86ee205492f0ac5f5286077 GIT binary patch literal 3955 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 Be&_%I literal 0 HcmV?d00001 diff --git a/srclib/apr/images/tip.gif b/srclib/apr/images/tip.gif new file mode 100644 index 0000000000000000000000000000000000000000..2536791237e00566f0fd60f57c8ef684cba54134 GIT binary patch literal 1018 zcmchW%}dmA5XMIgTcQ$VH%JP0Nkywmj7nmJ+d(rhB3pYSP|(5EJZ021Bf?1V&>jXM zJOufYBtn-EBFIdbgV7s>hYm^*-J(MTP0#%Ph`xt~VP>BB%rn33=xjgQ(wC+*eIxRC z=C1DI&h8YEnVY(a8@o{?)m+t8T-lYPR?J0R#D!fbTG^b{S)AFKpyXsu>LgC=gaF!* zh8CJpO))2)nu!^kQH({TYAU8|N%k9Tq8oN# ze?VYEP(uvRphPJ+Fc{j9h8Bf$kw%QiA{0hqKa54hEKKkf>w*GFAr^vR8!hs`S94I z^zp{Q@6`=0*`J$b4R_x+b*G+A?A%+wzB>7-dB^g{@&2_8o%;M^bYyzA(7d(TP#CIR zE7X^_&39HEn0=gY%}Ce!fg|1X__NbZC>!b+)&yxywWjDQ4p O@{FgepUXO@geCy2gM|A4 literal 0 HcmV?d00001 diff --git a/srclib/apr/images/warning.gif b/srclib/apr/images/warning.gif new file mode 100644 index 0000000000000000000000000000000000000000..5d676d752903ccda75a93ca2d87f781edcd47455 GIT binary patch literal 923 zcmc(eu}ju*5Qp!z26G7CgjyOjDNG`iTQUd1s8=IFkeXUvcstTHp`lj6#V`l)8iF9m zt%#PksHNfB8luUqHQHRdp8Nh2eR-GT?mqY2=YDT*`PQ|$epk-OFOjSlnVxBxnkf}U zWO#;UXoghMBi++2UDKs%Ez&&A(lkw~RU_3?EmczmrIbkV6id+*0<@7vi)N~&=G5~D zi_i$Eu|)3S7Ovq^6eP{VEKI|spr}<3wNMQe7-BtqRr2Zu` zZ1VQh`K5P9pSr_i)Ay%#V^K!W?R`9Z^z+O1$mM&R2cs8cYwX1KhacU^#huByXTJ|- zUVnXlapC3D<3BHM?@q1n4VKp4+}OYRSNDdTRb0zGVRlsmkN3Q;NmG|hkvx3vK)>J7xNDR4&MP6eu9@O1Ta JS?83{1OOUTN-+Qc literal 0 HcmV?d00001 diff --git a/srclib/apr/include/apr.h.in b/srclib/apr/include/apr.h.in new file mode 100644 index 0000000000..d1332921dc --- /dev/null +++ b/srclib/apr/include/apr.h.in @@ -0,0 +1,397 @@ +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef APR_H +#define APR_H + +/* GENERATED FILE WARNING! DO NOT EDIT apr.h + * + * You must modify apr.h.in instead. + * + * And please, make an effort to stub apr.hw and apr.hnw in the process. + */ + +/** + * @file apr.h + * @brief APR Platform Definitions + * @remark This is a generated header generated from include/apr.h.in by + * ./configure, or copied from include/apr.hw or include/apr.hnw + * for Win32 or Netware by those build environments, respectively. + */ + +/** + * @defgroup APR Apache Portability Runtime library + * @{ + */ +/** + * @defgroup apr_platform Platform Definitions + * @{ + */ + +/* So that we can use inline on some critical functions, and use + * GNUC attributes (such as to get -Wall warnings for printf-like + * functions). Only do this in gcc 2.7 or later ... it may work + * on earlier stuff, but why chance it. + * + * We've since discovered that the gcc shipped with NeXT systems + * as "cc" is completely broken. It claims to be __GNUC__ and so + * on, but it doesn't implement half of the things that __GNUC__ + * means. In particular it's missing inline and the __attribute__ + * stuff. So we hack around it. PR#1613. -djg + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || \ + (__GNUC__ == 2 && __GNUC_MINOR__ < 7) ||\ + defined(NEXT) +#ifndef __attribute__ +#define __attribute__(__x) +#endif +#define APR_INLINE +#define APR_HAS_INLINE 0 +#else +#define APR_INLINE __inline__ +#define APR_HAS_INLINE 1 +#endif + +#define APR_HAVE_ARPA_INET_H @arpa_ineth@ +#define APR_HAVE_CONIO_H @conioh@ +#define APR_HAVE_CRYPT_H @crypth@ +#define APR_HAVE_CTYPE_H @ctypeh@ +#define APR_HAVE_DIRENT_H @direnth@ +#define APR_HAVE_ERRNO_H @errnoh@ +#define APR_HAVE_FCNTL_H @fcntlh@ +#define APR_HAVE_IO_H @ioh@ +#define APR_HAVE_LIMITS_H @limitsh@ +#define APR_HAVE_NETDB_H @netdbh@ +#define APR_HAVE_NETINET_IN_H @netinet_inh@ +#define APR_HAVE_NETINET_SCTP_H @netinet_sctph@ +#define APR_HAVE_NETINET_SCTP_UIO_H @netinet_sctp_uioh@ +#define APR_HAVE_NETINET_TCP_H @netinet_tcph@ +#define APR_HAVE_PTHREAD_H @pthreadh@ +#define APR_HAVE_SEMAPHORE_H @semaphoreh@ +#define APR_HAVE_SIGNAL_H @signalh@ +#define APR_HAVE_STDARG_H @stdargh@ +#define APR_HAVE_STDINT_H @stdint@ +#define APR_HAVE_STDIO_H @stdioh@ +#define APR_HAVE_STDLIB_H @stdlibh@ +#define APR_HAVE_STRING_H @stringh@ +#define APR_HAVE_STRINGS_H @stringsh@ +#define APR_HAVE_SYS_IOCTL_H @sys_ioctlh@ +#define APR_HAVE_SYS_SENDFILE_H @sys_sendfileh@ +#define APR_HAVE_SYS_SIGNAL_H @sys_signalh@ +#define APR_HAVE_SYS_SOCKET_H @sys_socketh@ +#define APR_HAVE_SYS_SOCKIO_H @sys_sockioh@ +#define APR_HAVE_SYS_SYSLIMITS_H @sys_syslimitsh@ +#define APR_HAVE_SYS_TIME_H @sys_timeh@ +#define APR_HAVE_SYS_TYPES_H @sys_typesh@ +#define APR_HAVE_SYS_UIO_H @sys_uioh@ +#define APR_HAVE_SYS_UN_H @sys_unh@ +#define APR_HAVE_SYS_WAIT_H @sys_waith@ +#define APR_HAVE_TIME_H @timeh@ +#define APR_HAVE_UNISTD_H @unistdh@ + +/** @} */ + +/* We don't include our conditional headers within the doxyblocks + * or the extern "C" namespace + */ + +#if APR_HAVE_SYS_TYPES_H +#include +#endif + +#if APR_HAVE_SYS_SOCKET_H +#include +#endif + +#if defined(__cplusplus) && !defined(__STDC_CONSTANT_MACROS) +/* C99 7.18.4 requires that stdint.h only exposes INT64_C + * and UINT64_C for C++ implementations if this is defined: */ +#define __STDC_CONSTANT_MACROS +#endif + +#if APR_HAVE_STDINT_H +#include +#endif + +#if APR_HAVE_SYS_WAIT_H +#include +#endif + +#ifdef OS2 +#define INCL_DOS +#define INCL_DOSERRORS +#include +#endif + +/* header files for PATH_MAX, _POSIX_PATH_MAX */ +#if APR_HAVE_LIMITS_H +#include +#else +#if APR_HAVE_SYS_SYSLIMITS_H +#include +#endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup apr_platform + * @ingroup APR + * @{ + */ + +#define APR_HAVE_SHMEM_MMAP_TMP @havemmaptmp@ +#define APR_HAVE_SHMEM_MMAP_SHM @havemmapshm@ +#define APR_HAVE_SHMEM_MMAP_ZERO @havemmapzero@ +#define APR_HAVE_SHMEM_SHMGET_ANON @haveshmgetanon@ +#define APR_HAVE_SHMEM_SHMGET @haveshmget@ +#define APR_HAVE_SHMEM_MMAP_ANON @havemmapanon@ +#define APR_HAVE_SHMEM_BEOS @havebeosarea@ + +#define APR_USE_SHMEM_MMAP_TMP @usemmaptmp@ +#define APR_USE_SHMEM_MMAP_SHM @usemmapshm@ +#define APR_USE_SHMEM_MMAP_ZERO @usemmapzero@ +#define APR_USE_SHMEM_SHMGET_ANON @useshmgetanon@ +#define APR_USE_SHMEM_SHMGET @useshmget@ +#define APR_USE_SHMEM_MMAP_ANON @usemmapanon@ +#define APR_USE_SHMEM_BEOS @usebeosarea@ + +#define APR_USE_FLOCK_SERIALIZE @flockser@ +#define APR_USE_SYSVSEM_SERIALIZE @sysvser@ +#define APR_USE_POSIXSEM_SERIALIZE @posixser@ +#define APR_USE_FCNTL_SERIALIZE @fcntlser@ +#define APR_USE_PROC_PTHREAD_SERIALIZE @procpthreadser@ +#define APR_USE_PTHREAD_SERIALIZE @pthreadser@ + +#define APR_HAS_FLOCK_SERIALIZE @hasflockser@ +#define APR_HAS_SYSVSEM_SERIALIZE @hassysvser@ +#define APR_HAS_POSIXSEM_SERIALIZE @hasposixser@ +#define APR_HAS_FCNTL_SERIALIZE @hasfcntlser@ +#define APR_HAS_PROC_PTHREAD_SERIALIZE @hasprocpthreadser@ + +#define APR_PROCESS_LOCK_IS_GLOBAL @proclockglobal@ + +#define APR_HAVE_CORKABLE_TCP @have_corkable_tcp@ +#define APR_HAVE_GETRLIMIT @have_getrlimit@ +#define APR_HAVE_IN_ADDR @have_in_addr@ +#define APR_HAVE_INET_ADDR @have_inet_addr@ +#define APR_HAVE_INET_NETWORK @have_inet_network@ +#define APR_HAVE_IPV6 @have_ipv6@ +#define APR_HAVE_MEMMOVE @have_memmove@ +#define APR_HAVE_SETRLIMIT @have_setrlimit@ +#define APR_HAVE_SIGACTION @have_sigaction@ +#define APR_HAVE_SIGSUSPEND @have_sigsuspend@ +#define APR_HAVE_SIGWAIT @have_sigwait@ +#define APR_HAVE_SA_STORAGE @have_sa_storage@ +#define APR_HAVE_STRCASECMP @have_strcasecmp@ +#define APR_HAVE_STRDUP @have_strdup@ +#define APR_HAVE_STRICMP @have_stricmp@ +#define APR_HAVE_STRNCASECMP @have_strncasecmp@ +#define APR_HAVE_STRNICMP @have_strnicmp@ +#define APR_HAVE_STRSTR @have_strstr@ +#define APR_HAVE_MEMCHR @have_memchr@ +#define APR_HAVE_STRUCT_RLIMIT @struct_rlimit@ +#define APR_HAVE_UNION_SEMUN @have_union_semun@ +#define APR_HAVE_SCTP @have_sctp@ + +/* APR Feature Macros */ +#define APR_HAS_SHARED_MEMORY @sharedmem@ +#define APR_HAS_THREADS @threads@ +#define APR_HAS_SENDFILE @sendfile@ +#define APR_HAS_MMAP @mmap@ +#define APR_HAS_FORK @fork@ +#define APR_HAS_RANDOM @rand@ +#define APR_HAS_OTHER_CHILD @oc@ +#define APR_HAS_DSO @aprdso@ +#define APR_HAS_SO_ACCEPTFILTER @acceptfilter@ +#define APR_HAS_UNICODE_FS 0 +#define APR_HAS_PROC_INVOKED 0 +#define APR_HAS_USER 1 +#define APR_HAS_LARGE_FILES @aprlfs@ +#define APR_HAS_XTHREAD_FILES 0 +#define APR_HAS_OS_UUID @osuuid@ + +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 + +/* APR sets APR_FILES_AS_SOCKETS to 1 on systems where it is possible + * to poll on files/pipes. + */ +#define APR_FILES_AS_SOCKETS @file_as_socket@ + +/* This macro indicates whether or not EBCDIC is the native character set. + */ +#define APR_CHARSET_EBCDIC @apr_charset_ebcdic@ + +/* If we have a TCP implementation that can be "corked", what flag + * do we use? + */ +#define APR_TCP_NOPUSH_FLAG @apr_tcp_nopush_flag@ + +/* Is the TCP_NODELAY socket option inherited from listening sockets? +*/ +#define APR_TCP_NODELAY_INHERITED @tcp_nodelay_inherited@ + +/* Is the O_NONBLOCK flag inherited from listening sockets? +*/ +#define APR_O_NONBLOCK_INHERITED @o_nonblock_inherited@ + +/* Typedefs that APR needs. */ + +typedef unsigned char apr_byte_t; + +typedef @short_value@ apr_int16_t; +typedef unsigned @short_value@ apr_uint16_t; + +typedef @int_value@ apr_int32_t; +typedef unsigned @int_value@ apr_uint32_t; + +typedef @long_value@ apr_int64_t; +typedef unsigned @long_value@ apr_uint64_t; + +typedef @size_t_value@ apr_size_t; +typedef @ssize_t_value@ apr_ssize_t; +typedef @off_t_value@ apr_off_t; +typedef @socklen_t_value@ apr_socklen_t; + +#define APR_SIZEOF_VOIDP @voidp_size@ + +/* Are we big endian? */ +#define APR_IS_BIGENDIAN @bigendian@ + +/* Mechanisms to properly type numeric literals */ +@int64_literal@ +@uint64_literal@ + +/* Definitions that APR programs need to work properly. */ + +/** + * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, + * so that they follow the platform's calling convention. + * @example + */ +/** void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data); + */ +#define APR_THREAD_FUNC + +/** + * The public APR functions are declared with APR_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APR_DECLARE_NONSTD(). + * + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE(rettype) apr_func(args) + * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA + * @remark Note that when APR compiles the library itself, it passes the + * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) + * to export public symbols from the dynamic library build.\n + * The user must define the APR_DECLARE_STATIC when compiling to target + * the static APR library on some platforms (e.g. Win32.) The public symbols + * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n + * By default, compiling an application and including the APR public + * headers, without defining APR_DECLARE_STATIC, will prepare the code to be + * linked to the dynamic library. + */ +#define APR_DECLARE(type) type + +/** + * The public APR functions using variable arguments are declared with + * APR_DECLARE_NONSTD(), as they must follow the C language calling convention. + * @see APR_DECLARE @see APR_DECLARE_DATA + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE_NONSTD(rettype) apr_func(args, ...); + */ +#define APR_DECLARE_NONSTD(type) type + +/** + * The public APR variables are declared with AP_MODULE_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * @see APR_DECLARE @see APR_DECLARE_NONSTD + * @remark Note that the declaration and implementations use different forms, + * but both must include the macro. + * @example + */ +/** extern APR_DECLARE_DATA type apr_variable;\n + * APR_DECLARE_DATA type apr_variable = value; + */ +#define APR_DECLARE_DATA + +/* Define APR_SSIZE_T_FMT. + * If ssize_t is an integer we define it to be "d", + * if ssize_t is a long int we define it to be "ld", + * if ssize_t is neither we declare an error here. + * I looked for a better way to define this here, but couldn't find one, so + * to find the logic for this definition search for "ssize_t_fmt" in + * configure.in. + */ +@ssize_t_fmt@ + +/* And APR_SIZE_T_FMT */ +@size_t_fmt@ + +/* And APR_OFF_T_FMT */ +@off_t_fmt@ + +/* And APR_PID_T_FMT */ +@pid_t_fmt@ + +/* And APR_INT64_T_FMT */ +@int64_t_fmt@ + +/* And APR_UINT64_T_FMT */ +@uint64_t_fmt@ + +/* And APR_UINT64_T_HEX_FMT */ +@uint64_t_hex_fmt@ + +/* Does the proc mutex lock threads too */ +#define APR_PROC_MUTEX_IS_GLOBAL @proc_mutex_is_global@ + +/* Local machine definition for console and log output. */ +#define APR_EOL_STR "@eolstr@" + + +#if APR_HAVE_SYS_WAIT_H +#ifdef WEXITSTATUS +#define apr_wait_t int +#else +#define apr_wait_t union wait +#define WEXITSTATUS(status) (int)((status).w_retcode) +#define WTERMSIG(status) (int)((status).w_termsig) +#endif /* !WEXITSTATUS */ +#endif /* HAVE_SYS_WAIT_H */ + +#if defined(PATH_MAX) +#define APR_PATH_MAX PATH_MAX +#elif defined(_POSIX_PATH_MAX) +#define APR_PATH_MAX _POSIX_PATH_MAX +#else +#error no decision has been made on APR_PATH_MAX for your platform +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APR_H */ diff --git a/srclib/apr/include/apr.hnw b/srclib/apr/include/apr.hnw new file mode 100644 index 0000000000..f1be62e1b8 --- /dev/null +++ b/srclib/apr/include/apr.hnw @@ -0,0 +1,364 @@ +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef APR_H +#define APR_H + +/* GENERATED FILE WARNING! DO NOT EDIT apr.h + * + * You must modify apr.hnw instead. + * + * And please, make an effort to stub apr.hw and apr.h.in in the process. + * + * This is the NetWare specific version of apr.h. It is copied from + * apr.hnw at the start of a NetWare build by prebuildNW.bat. + */ + +/** + * @file apr.h + * @brief APR Platform Definitions + * @remark This is a generated header generated from include/apr.h.in by + * ./configure, or copied from include/apr.hw or include/apr.hnw + * for Win32 or Netware by those build environments, respectively. + */ + +#if defined(NETWARE) || defined(DOXYGEN) + +#define FD_SETSIZE 1024 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_WINSOCK +#include +#else +#include +#endif +#include + +#ifdef NW_BUILD_IPV6 +#include +#endif + +#define _POSIX_THREAD_SAFE_FUNCTIONS 1 +#define READDIR_IS_THREAD_SAFE 1 + +/* Keep #include'd headers from within the __cplusplus or doxyblocks */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_platform Platform Definitions + * @ingroup APR + * @{ + */ + +#define APR_INLINE +#define APR_HAS_INLINE 0 +#ifndef __attribute__ +#define __attribute__(__x) +#endif +#define ENUM_BITFIELD(e,n,w) signed int n : w + +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 0 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 1 +#define APR_HAVE_DIRENT_H 1 +#define APR_HAVE_ERRNO_H 1 +#define APR_HAVE_FCNTL_H 1 +#define APR_HAVE_IO_H 0 +#define APR_HAVE_LIMITS_H 1 +#ifdef USE_WINSOCK +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#else +#define APR_HAVE_ARPA_INET_H 1 +#define APR_HAVE_NETDB_H 1 +#define APR_HAVE_NETINET_IN_H 1 +#endif +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SIGNAL_H 1 +#define APR_HAVE_STDARG_H 1 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_STRTOLL 1 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#ifdef USE_WINSOCK +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#else +#define APR_HAVE_SYS_SOCKET_H 1 +#define APR_HAVE_SYS_SOCKIO_H 1 +#define APR_HAVE_SYS_TIME_H 1 +#endif +#define APR_HAVE_SYS_SIGNAL_H 1 +#define APR_HAVE_SYS_TYPES_H 1 +#define APR_HAVE_SYS_UIO_H 1 +#define APR_HAVE_SYS_UN_H 1 +#define APR_HAVE_SYS_WAIT_H 1 +#define APR_HAVE_TIME_H 1 +#define APR_HAVE_UNISTD_H 1 + +#define APR_HAVE_SHMEM_MMAP_TMP 0 +#define APR_HAVE_SHMEM_MMAP_SHM 0 +#define APR_HAVE_SHMEM_MMAP_ZERO 0 +#define APR_HAVE_SHMEM_SHMGET_ANON 0 +#define APR_HAVE_SHMEM_SHMGET 0 +#define APR_HAVE_SHMEM_MMAP_ANON 0 +#define APR_HAVE_SHMEM_BEOS 0 + +#define APR_USE_SHMEM_MMAP_TMP 0 +#define APR_USE_SHMEM_MMAP_SHM 0 +#define APR_USE_SHMEM_MMAP_ZERO 0 +#define APR_USE_SHMEM_SHMGET_ANON 0 +#define APR_USE_SHMEM_SHMGET 0 +#define APR_USE_SHMEM_MMAP_ANON 0 +#define APR_USE_SHMEM_BEOS 0 + +#define APR_USE_FLOCK_SERIALIZE 0 +#define APR_USE_SYSVSEM_SERIALIZE 0 +#define APR_USE_FCNTL_SERIALIZE 0 +#define APR_USE_PROC_PTHREAD_SERIALIZE 0 +#define APR_USE_PTHREAD_SERIALIZE 0 + +#define APR_HAS_FLOCK_SERIALIZE 0 +#define APR_HAS_SYSVSEM_SERIALIZE 0 +#define APR_HAS_FCNTL_SERIALIZE 0 +#define APR_HAS_PROC_PTHREAD_SERIALIZE 0 +#define APR_HAS_RWLOCK_SERIALIZE 0 + +#define APR_HAS_LOCK_CREATE_NP 0 + +#define APR_PROCESS_LOCK_IS_GLOBAL 1 + +#define APR_FILE_BASED_SHM 0 + +#define APR_HAVE_CORKABLE_TCP 0 +#define APR_HAVE_GETRLIMIT 0 +#define APR_HAVE_ICONV 0 +#define APR_HAVE_IN_ADDR 1 +#define APR_HAVE_INET_ADDR 1 +#define APR_HAVE_INET_NETWORK 0 +#ifdef NW_BUILD_IPV6 +#define APR_HAVE_IPV6 1 +#else +#define APR_HAVE_IPV6 0 +#endif +#define APR_HAVE_MEMCHR 1 +#define APR_HAVE_MEMMOVE 1 +#define APR_HAVE_SETRLIMIT 0 +#define APR_HAVE_SIGACTION 0 +#define APR_HAVE_SIGSUSPEND 0 +#define APR_HAVE_SIGWAIT 0 +#define APR_HAVE_STRCASECMP 1 +#define APR_HAVE_STRDUP 1 +#define APR_HAVE_STRICMP 1 +#define APR_HAVE_STRNCASECMP 1 +#define APR_HAVE_STRNICMP 1 +#define APR_HAVE_STRSTR 1 +#define APR_HAVE_STRUCT_RLIMIT 0 +#define APR_HAVE_UNION_SEMUN 0 +#define APR_HAVE_SCTP 0 + +/* APR Feature Macros */ +#define APR_HAS_SHARED_MEMORY 0 +#define APR_HAS_THREADS 1 +#define APR_HAS_SENDFILE 0 +#define APR_HAS_MMAP 0 +#define APR_HAS_FORK 0 +#define APR_HAS_RANDOM 1 +#define APR_HAS_OTHER_CHILD 0 +#define APR_HAS_DSO 1 +#define APR_HAS_SO_ACCEPTFILTER 0 +#define APR_HAS_UNICODE_FS 0 +#define APR_HAS_PROC_INVOKED 0 +#define APR_HAS_USER 1 +#define APR_HAS_LARGE_FILES 1 +#define APR_HAS_XTHREAD_FILES 0 +#define APR_HAS_OS_UUID 0 + +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 + +/* Netware can poll on files/pipes. + */ +#define APR_FILES_AS_SOCKETS 1 + +/* This macro indicates whether or not EBCDIC is the native character set. + */ +#define APR_CHARSET_EBCDIC 0 + +/* Is the TCP_NODELAY socket option inherited from listening sockets? +*/ +#define APR_TCP_NODELAY_INHERITED 1 + +/* Is the O_NONBLOCK flag inherited from listening sockets? +*/ +#define APR_O_NONBLOCK_INHERITED 1 + +/* Typedefs that APR needs. */ + +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; + +typedef long long apr_int64_t; +typedef unsigned long long apr_uint64_t; + +typedef size_t apr_size_t; +typedef ssize_t apr_ssize_t; +#if APR_HAS_LARGE_FILES +typedef off64_t apr_off_t; +#else +typedef off_t apr_off_t; +#endif +#ifdef USE_WINSOCK +typedef int apr_socklen_t; +#else +typedef size_t apr_socklen_t; +#endif + +/* Are we big endian? */ +/* XXX: Fatal assumption on Alpha platforms */ +#define APR_IS_BIGENDIAN 0 + +#ifdef UNKNOWN_NETWARE_64BIT_FLAG_NEEDED +#define APR_SIZEOF_VOIDP 8 +#else +#define APR_SIZEOF_VOIDP 4 +#endif + +/* Mechanisms to properly type numeric literals */ +#define APR_INT64_C(val) (val##LL) +#define APR_UINT64_C(val) (val##ULL) + +/* PROC mutex is a GLOBAL mutex on Netware */ +#define APR_PROC_MUTEX_IS_GLOBAL 1 + +/* Definitions that APR programs need to work properly. */ + +/** + * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, + * so that they follow the platform's calling convention. + * @example + */ +/** void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data); + */ +#define APR_THREAD_FUNC + +/** + * The public APR functions are declared with APR_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APR_DECLARE_NONSTD(). + * + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE(rettype) apr_func(args) + * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA + * @remark Note that when APR compiles the library itself, it passes the + * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) + * to export public symbols from the dynamic library build.\n + * The user must define the APR_DECLARE_STATIC when compiling to target + * the static APR library on some platforms (e.g. Win32.) The public symbols + * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n + * By default, compiling an application and including the APR public + * headers, without defining APR_DECLARE_STATIC, will prepare the code to be + * linked to the dynamic library. + */ +#define APR_DECLARE(type) type + +/** + * The public APR functions using variable arguments are declared with + * APR_DECLARE_NONSTD(), as they must follow the C language calling convention. + * @see APR_DECLARE @see APR_DECLARE_DATA + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE_NONSTD(rettype) apr_func(args, ...); + */ +#define APR_DECLARE_NONSTD(type) type + +/** + * The public APR variables are declared with AP_MODULE_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * @see APR_DECLARE @see APR_DECLARE_NONSTD + * @remark Note that the declaration and implementations use different forms, + * but both must include the macro. + * @example + */ +/** extern APR_DECLARE_DATA type apr_variable;\n + * APR_DECLARE_DATA type apr_variable = value; + */ +#define APR_DECLARE_DATA + +#define APR_SSIZE_T_FMT "d" + +#define APR_SIZE_T_FMT "d" + +#if APR_HAS_LARGE_FILES +#define APR_OFF_T_FMT "lld" +#else +#define APR_OFF_T_FMT "ld" +#endif + +#define APR_PID_T_FMT "d" + +/* Local machine definition for console and log output. */ +#define APR_EOL_STR "\r\n" + +typedef int apr_wait_t; + +#define APR_PATH_MAX PATH_MAX + +#define APR_INT64_T_FMT "lld" +#define APR_UINT64_T_FMT "llu" +#define APR_UINT64_T_HEX_FMT "llx" +#define APR_TIME_T_FMT APR_INT64_T_FMT + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* NETWARE */ + +#endif /* APR_H */ diff --git a/srclib/apr/include/apr.hw b/srclib/apr/include/apr.hw new file mode 100644 index 0000000000..1174a190a5 --- /dev/null +++ b/srclib/apr/include/apr.hw @@ -0,0 +1,510 @@ +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#ifndef APR_H +#define APR_H + +/* GENERATED FILE WARNING! DO NOT EDIT apr.h + * + * You must modify apr.hw instead. + * + * And please, make an effort to stub apr.hnw and apr.h.in in the process. + * + * This is the Win32 specific version of apr.h. It is copied from + * apr.hw by the apr.dsp and libapr.dsp projects. + */ + +/** + * @file apr.h + * @brief APR Platform Definitions + * @remark This is a generated header generated from include/apr.h.in by + * ./configure, or copied from include/apr.hw or include/apr.hnw + * for Win32 or Netware by those build environments, respectively. + */ + +#if defined(WIN32) || defined(DOXYGEN) + +/* Ignore most warnings (back down to /W3) for poorly constructed headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(push, 3) +#endif + +/* disable or reduce the frequency of... + * C4057: indirection to slightly different base types + * C4075: slight indirection changes (unsigned short* vs short[]) + * C4100: unreferenced formal parameter + * C4127: conditional expression is constant + * C4163: '_rotl64' : not available as an intrinsic function + * C4201: nonstandard extension nameless struct/unions + * C4244: int to char/short - precision loss + * C4514: unreferenced inline function removed + */ +#pragma warning(disable: 4100 4127 4163 4201 4514; once: 4057 4075 4244) + +/* Has windows.h already been included? If so, our preferences don't matter, + * but we will still need the winsock things no matter what was included. + * If not, include a restricted set of windows headers to our tastes. + */ +#ifndef _WINDOWS_ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef _WIN32_WINNT + +/* Restrict the server to a subset of Windows NT 4.0 header files by default + */ +#define _WIN32_WINNT 0x0400 +#endif +#ifndef NOUSER +#define NOUSER +#endif +#ifndef NOMCX +#define NOMCX +#endif +#ifndef NOIME +#define NOIME +#endif +#include +/* + * Add a _very_few_ declarations missing from the restricted set of headers + * (If this list becomes extensive, re-enable the required headers above!) + * winsock headers were excluded by WIN32_LEAN_AND_MEAN, so include them now + */ +#define SW_HIDE 0 +#ifndef _WIN32_WCE +#include +#include +#include +#else +#include +#endif +#endif /* !_WINDOWS_ */ + +/** + * @defgroup apr_platform Platform Definitions + * @ingroup APR + * @{ + */ + +#define APR_INLINE __inline +#define APR_HAS_INLINE 1 +#ifndef __attribute__ +#define __attribute__(__x) +#endif + +#ifndef _WIN32_WCE +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 1 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 1 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 1 +#define APR_HAVE_FCNTL_H 1 +#define APR_HAVE_IO_H 1 +#define APR_HAVE_LIMITS_H 1 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_SCTP_H 0 +#define APR_HAVE_NETINET_SCTP_UIO_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SIGNAL_H 1 +#define APR_HAVE_STDARG_H 1 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SOCKIO_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 1 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 1 +#define APR_HAVE_PROCESS_H 1 +#define APR_HAVE_TIME_H 1 +#else +#define APR_HAVE_ARPA_INET_H 0 +#define APR_HAVE_CONIO_H 0 +#define APR_HAVE_CRYPT_H 0 +#define APR_HAVE_CTYPE_H 0 +#define APR_HAVE_DIRENT_H 0 +#define APR_HAVE_ERRNO_H 0 +#define APR_HAVE_FCNTL_H 0 +#define APR_HAVE_IO_H 0 +#define APR_HAVE_LIMITS_H 0 +#define APR_HAVE_NETDB_H 0 +#define APR_HAVE_NETINET_IN_H 0 +#define APR_HAVE_NETINET_TCP_H 0 +#define APR_HAVE_PTHREAD_H 0 +#define APR_HAVE_SIGNAL_H 0 +#define APR_HAVE_STDARG_H 0 +#define APR_HAVE_STDINT_H 0 +#define APR_HAVE_STDIO_H 1 +#define APR_HAVE_STDLIB_H 1 +#define APR_HAVE_STRING_H 1 +#define APR_HAVE_STRINGS_H 0 +#define APR_HAVE_SYS_SENDFILE_H 0 +#define APR_HAVE_SYS_SIGNAL_H 0 +#define APR_HAVE_SYS_SOCKET_H 0 +#define APR_HAVE_SYS_SYSLIMITS_H 0 +#define APR_HAVE_SYS_TIME_H 0 +#define APR_HAVE_SYS_TYPES_H 0 +#define APR_HAVE_SYS_UIO_H 0 +#define APR_HAVE_SYS_WAIT_H 0 +#define APR_HAVE_UNISTD_H 0 +#define APR_HAVE_STDDEF_H 0 +#define APR_HAVE_PROCESS_H 0 +#define APR_HAVE_TIME_H 0 +#endif + +#define APR_USE_FLOCK_SERIALIZE 0 +#define APR_USE_SYSVSEM_SERIALIZE 0 +#define APR_USE_FCNTL_SERIALIZE 0 +#define APR_USE_PROC_PTHREAD_SERIALIZE 0 +#define APR_USE_PTHREAD_SERIALIZE 0 + +#define APR_HAS_FLOCK_SERIALIZE 0 +#define APR_HAS_SYSVSEM_SERIALIZE 0 +#define APR_HAS_FCNTL_SERIALIZE 0 +#define APR_HAS_PROC_PTHREAD_SERIALIZE 0 +#define APR_HAS_RWLOCK_SERIALIZE 0 + +#define APR_HAS_LOCK_CREATE_NP 0 + +#define APR_PROCESS_LOCK_IS_GLOBAL 0 + +#define APR_USES_ANONYMOUS_SHM 0 +#define APR_USES_FILEBASED_SHM 0 +#define APR_USES_KEYBASED_SHM 0 + +#define APR_FILE_BASED_SHM 0 +#define APR_MEM_BASED_SHM 0 + +#define APR_HAVE_CORKABLE_TCP 0 +#define APR_HAVE_GETRLIMIT 0 +#define APR_HAVE_ICONV 0 +#define APR_HAVE_IN_ADDR 1 +#define APR_HAVE_INET_ADDR 1 +#define APR_HAVE_INET_NETWORK 0 +#define APR_HAVE_IPV6 0 +#define APR_HAVE_MEMMOVE 1 +#define APR_HAVE_SETRLIMIT 0 +#define APR_HAVE_SIGACTION 0 +#define APR_HAVE_SIGSUSPEND 0 +#define APR_HAVE_SIGWAIT 0 +#define APR_HAVE_STRCASECMP 0 +#define APR_HAVE_STRDUP 1 +#define APR_HAVE_STRNCASECMP 0 +#define APR_HAVE_STRSTR 1 +#define APR_HAVE_MEMCHR 1 +#define APR_HAVE_STRUCT_RLIMIT 0 +#define APR_HAVE_UNION_SEMUN 0 +#define APR_HAVE_SCTP 0 + +#ifndef _WIN32_WCE +#define APR_HAVE_STRICMP 1 +#define APR_HAVE_STRNICMP 1 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 1 +#else +#define APR_HAVE_STRICMP 0 +#define APR_HAVE_STRNICMP 0 +#define APR_PROCATTR_USER_SET_REQUIRES_PASSWORD 0 +#endif + +/** @} */ + +/* We don't include our conditional headers within the doxyblocks + * or the extern "C" namespace + */ + +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STDDEF_H +#include +#endif +#if APR_HAVE_TIME_H +#include +#endif +#if APR_HAVE_PROCESS_H +#include +#endif +#if APR_HAVE_IPV6 +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup apr_platform + * @ingroup APR + * @{ + */ + +/* APR Feature Macros */ +#define APR_HAS_SHARED_MEMORY 1 +#define APR_HAS_THREADS 1 +#define APR_HAS_MMAP 1 +#define APR_HAS_FORK 0 +#define APR_HAS_RANDOM 1 +#define APR_HAS_OTHER_CHILD 1 +#define APR_HAS_DSO 1 +#define APR_HAS_SO_ACCEPTFILTER 0 +#define APR_HAS_UNICODE_FS 1 +#define APR_HAS_PROC_INVOKED 1 +#ifndef _WIN32_WCE +#define APR_HAS_SENDFILE 1 +#define APR_HAS_USER 1 +#define APR_HAS_LARGE_FILES 1 +#define APR_HAS_XTHREAD_FILES 1 +#else +#define APR_HAS_SENDFILE 0 +#define APR_HAS_USER 0 +#define APR_HAS_LARGE_FILES 0 +#define APR_HAS_XTHREAD_FILES 0 +#endif +#define APR_HAS_OS_UUID 1 + +/* Win32 cannot poll [just yet] on files/pipes. + */ +#define APR_FILES_AS_SOCKETS 0 + +/* This macro indicates whether or not EBCDIC is the native character set. + */ +#define APR_CHARSET_EBCDIC 0 + +/* Is the TCP_NODELAY socket option inherited from listening sockets? + */ +#define APR_TCP_NODELAY_INHERITED 1 + +/* Is the O_NONBLOCK flag inherited from listening sockets? + */ +#define APR_O_NONBLOCK_INHERITED 1 + +/* Typedefs that APR needs. */ + +typedef unsigned char apr_byte_t; + +typedef short apr_int16_t; +typedef unsigned short apr_uint16_t; + +typedef int apr_int32_t; +typedef unsigned int apr_uint32_t; + +typedef __int64 apr_int64_t; +typedef unsigned __int64 apr_uint64_t; + +typedef size_t apr_size_t; +#if APR_HAVE_STDDEF_H +typedef ptrdiff_t apr_ssize_t; +#else +typedef int apr_ssize_t; +#endif +#if APR_HAS_LARGE_FILES +typedef __int64 apr_off_t; +#else +typedef int apr_off_t; +#endif +typedef int apr_socklen_t; + +/* Are we big endian? */ +/* XXX: Fatal assumption on Alpha platforms */ +#define APR_IS_BIGENDIAN 0 + +#ifdef WIN64 +#define APR_SIZEOF_VOIDP 8 +#else +#define APR_SIZEOF_VOIDP 4 +#endif + +/* XXX These simply don't belong here, perhaps in apr_portable.h + * based on some APR_HAVE_PID/GID/UID? + */ +typedef int pid_t; +typedef int uid_t; +typedef int gid_t; + +/* Mechanisms to properly type numeric literals */ + +#define APR_INT64_C(val) (val##i64) +#define APR_UINT64_C(val) (val##Ui64) + + +#if APR_HAVE_IPV6 + +/* Appears in later flavors, not the originals. */ +#ifndef in_addr6 +#define in6_addr in_addr6 +#endif + +#ifndef WS2TCPIP_INLINE +#define IN6_IS_ADDR_V4MAPPED(a) \ + ( (*(const apr_uint64_t *)(const void *)(&(a)->s6_addr[0]) == 0) \ + && (*(const apr_uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff))) +#endif + +#endif /* APR_HAS_IPV6 */ + +/* Definitions that APR programs need to work properly. */ + +/** + * Thread callbacks from APR functions must be declared with APR_THREAD_FUNC, + * so that they follow the platform's calling convention. + * @example + */ +/** void* APR_THREAD_FUNC my_thread_entry_fn(apr_thread_t *thd, void *data); + */ +#define APR_THREAD_FUNC __stdcall + + +#if defined(DOXYGEN) || !defined(WIN32) + +/** + * The public APR functions are declared with APR_DECLARE(), so they may + * use the most appropriate calling convention. Public APR functions with + * variable arguments must use APR_DECLARE_NONSTD(). + * + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE(rettype) apr_func(args) + * @see APR_DECLARE_NONSTD @see APR_DECLARE_DATA + * @remark Note that when APR compiles the library itself, it passes the + * symbol -DAPR_DECLARE_EXPORT to the compiler on some platforms (e.g. Win32) + * to export public symbols from the dynamic library build.\n + * The user must define the APR_DECLARE_STATIC when compiling to target + * the static APR library on some platforms (e.g. Win32.) The public symbols + * are neither exported nor imported when APR_DECLARE_STATIC is defined.\n + * By default, compiling an application and including the APR public + * headers, without defining APR_DECLARE_STATIC, will prepare the code to be + * linked to the dynamic library. + */ +#define APR_DECLARE(type) type + +/** + * The public APR functions using variable arguments are declared with + * APR_DECLARE_NONSTD(), as they must follow the C language calling convention. + * @see APR_DECLARE @see APR_DECLARE_DATA + * @remark Both the declaration and implementations must use the same macro. + * @example + */ +/** APR_DECLARE_NONSTD(rettype) apr_func(args, ...); + */ +#define APR_DECLARE_NONSTD(type) type + +/** + * The public APR variables are declared with AP_MODULE_DECLARE_DATA. + * This assures the appropriate indirection is invoked at compile time. + * @see APR_DECLARE @see APR_DECLARE_NONSTD + * @remark Note that the declaration and implementations use different forms, + * but both must include the macro. + * @example + */ +/** extern APR_DECLARE_DATA type apr_variable;\n + * APR_DECLARE_DATA type apr_variable = value; + */ +#define APR_DECLARE_DATA + +#elif defined(APR_DECLARE_STATIC) +#define APR_DECLARE(type) type __stdcall +#define APR_DECLARE_NONSTD(type) type __cdecl +#define APR_DECLARE_DATA +#elif defined(APR_DECLARE_EXPORT) +#define APR_DECLARE(type) __declspec(dllexport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllexport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllexport) +#else +#define APR_DECLARE(type) __declspec(dllimport) type __stdcall +#define APR_DECLARE_NONSTD(type) __declspec(dllimport) type __cdecl +#define APR_DECLARE_DATA __declspec(dllimport) +#endif + +#ifdef WIN64 +#define APR_SSIZE_T_FMT "I64d" +#define APR_SIZE_T_FMT "I64d" +#else +#define APR_SSIZE_T_FMT "d" +#define APR_SIZE_T_FMT "d" +#endif + +#if APR_HAS_LARGE_FILES +#define APR_OFF_T_FMT "I64d" +#else +#define APR_OFF_T_FMT "d" +#endif + +#define APR_PID_T_FMT "d" + +#define APR_INT64_T_FMT "I64d" +#define APR_UINT64_T_FMT "I64u" +#define APR_UINT64_T_HEX_FMT "I64x" + +/* Local machine definition for console and log output. */ +#define APR_EOL_STR "\r\n" + +/* No difference between PROC and GLOBAL mutex */ +#define APR_PROC_MUTEX_IS_GLOBAL 1 + +typedef int apr_wait_t; + +/* struct iovec is needed to emulate Unix writev */ +struct iovec { + char* iov_base; + apr_size_t iov_len; +}; + +/* Nasty Win32 .h ommissions we really need */ +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + +#if APR_HAS_UNICODE_FS +/* An arbitrary size that is digestable. True max is a bit less than 32000 */ +#define APR_PATH_MAX 8192 +#else /* !APR_HAS_UNICODE_FS */ +#define APR_PATH_MAX MAX_PATH +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +/* Done with badly written headers + */ +#if defined(_MSC_VER) && _MSC_VER >= 1200 +#pragma warning(pop) +#endif + +#endif /* WIN32 */ + +#endif /* APR_H */ diff --git a/srclib/apr/include/apr_allocator.h b/srclib/apr/include/apr_allocator.h new file mode 100644 index 0000000000..de29e911d5 --- /dev/null +++ b/srclib/apr/include/apr_allocator.h @@ -0,0 +1,160 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_ALLOCATOR_H +#define APR_ALLOCATOR_H + +/** + * @file apr_allocator.h + * @brief APR Internal Memory Allocation + */ + +#include "apr.h" +#include "apr_errno.h" +#define APR_WANT_MEMFUNC /**< For no good reason? */ +#include "apr_want.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_allocator Internal Memory Allocation + * @ingroup APR + * @{ + */ + +/** the allocator structure */ +typedef struct apr_allocator_t apr_allocator_t; +/** the structure which holds information about the allocation */ +typedef struct apr_memnode_t apr_memnode_t; + +/** basic memory node structure + * @note The next, ref and first_avail fields are available for use by the + * caller of apr_allocator_alloc(), the remaining fields are read-only. + * The next field has to be used with caution and sensibly set when the + * memnode is passed back to apr_allocator_free(). See apr_allocator_free() + * for details. + * The ref and first_avail fields will be properly restored by + * apr_allocator_free(). + */ +struct apr_memnode_t { + apr_memnode_t *next; /**< next memnode */ + apr_memnode_t **ref; /**< reference to self */ + apr_uint32_t index; /**< size */ + apr_uint32_t free_index; /**< how much free */ + char *first_avail; /**< pointer to first free memory */ + char *endp; /**< pointer to end of free memory */ +}; + +/** The base size of a memory node - aligned. */ +#define APR_MEMNODE_T_SIZE APR_ALIGN_DEFAULT(sizeof(apr_memnode_t)) + +/** Symbolic constants */ +#define APR_ALLOCATOR_MAX_FREE_UNLIMITED 0 + +/** + * Create a new allocator + * @param allocator The allocator we have just created. + * + */ +APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator); + +/** + * Destroy an allocator + * @param allocator The allocator to be destroyed + * @remark Any memnodes not given back to the allocator prior to destroying + * will _not_ be free()d. + */ +APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator); + +/** + * Allocate a block of mem from the allocator + * @param allocator The allocator to allocate from + * @param size The size of the mem to allocate (excluding the + * memnode structure) + */ +APR_DECLARE(apr_memnode_t *) apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size); + +/** + * Free a list of blocks of mem, giving them back to the allocator. + * The list is typically terminated by a memnode with its next field + * set to NULL. + * @param allocator The allocator to give the mem back to + * @param memnode The memory node to return + */ +APR_DECLARE(void) apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *memnode); + +#include "apr_pools.h" + +/** + * Set the owner of the allocator + * @param allocator The allocator to set the owner for + * @param pool The pool that is to own the allocator + * @remark Typically pool is the highest level pool using the allocator + */ +/* + * XXX: see if we can come up with something a bit better. Currently + * you can make a pool an owner, but if the pool doesn't use the allocator + * the allocator will never be destroyed. + */ +APR_DECLARE(void) apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool); + +/** + * Get the current owner of the allocator + * @param allocator The allocator to get the owner from + */ +APR_DECLARE(apr_pool_t *) apr_allocator_owner_get(apr_allocator_t *allocator); + +/** + * Set the current threshold at which the allocator should start + * giving blocks back to the system. + * @param allocator The allocator the set the threshold on + * @param size The threshold. 0 == unlimited. + */ +APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t size); + +#include "apr_thread_mutex.h" + +#if APR_HAS_THREADS +/** + * Set a mutex for the allocator to use + * @param allocator The allocator to set the mutex for + * @param mutex The mutex + */ +APR_DECLARE(void) apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex); + +/** + * Get the mutex currently set for the allocator + * @param allocator The allocator + */ +APR_DECLARE(apr_thread_mutex_t *) apr_allocator_mutex_get( + apr_allocator_t *allocator); + +#endif /* APR_HAS_THREADS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_ALLOCATOR_H */ diff --git a/srclib/apr/include/apr_atomic.h b/srclib/apr/include/apr_atomic.h new file mode 100644 index 0000000000..d70106980d --- /dev/null +++ b/srclib/apr/include/apr_atomic.h @@ -0,0 +1,129 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_ATOMIC_H +#define APR_ATOMIC_H + +/** + * @file apr_atomic.h + * @brief APR Atomic Operations + */ + +#include "apr.h" +#include "apr_pools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_atomic Atomic Operations + * @ingroup APR + * @{ + */ + +/** + * this function is required on some platforms to initialize the + * atomic operation's internal structures + * @param p pool + * @return APR_SUCCESS on successful completion + */ +APR_DECLARE(apr_status_t) apr_atomic_init(apr_pool_t *p); + +/* + * Atomic operations on 32-bit values + * Note: Each of these functions internally implements a memory barrier + * on platforms that require it + */ + +/** + * atomically read an apr_uint32_t from memory + * @param mem the pointer + */ +APR_DECLARE(apr_uint32_t) apr_atomic_read32(volatile apr_uint32_t *mem); + +/** + * atomically set an apr_uint32_t in memory + * @param mem pointer to the object + * @param val value that the object will assume + */ +APR_DECLARE(void) apr_atomic_set32(volatile apr_uint32_t *mem, apr_uint32_t val); + +/** + * atomically add 'val' to an apr_uint32_t + * @param mem pointer to the object + * @param val amount to add + * @return old value pointed to by mem + */ +APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val); + +/** + * atomically subtract 'val' from an apr_uint32_t + * @param mem pointer to the object + * @param val amount to subtract + */ +APR_DECLARE(void) apr_atomic_sub32(volatile apr_uint32_t *mem, apr_uint32_t val); + +/** + * atomically increment an apr_uint32_t by 1 + * @param mem pointer to the object + * @return old value pointed to by mem + */ +APR_DECLARE(apr_uint32_t) apr_atomic_inc32(volatile apr_uint32_t *mem); + +/** + * atomically decrement an apr_uint32_t by 1 + * @param mem pointer to the atomic value + * @return zero if the value becomes zero on decrement, otherwise non-zero + */ +APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem); + +/** + * compare an apr_uint32_t's value with 'cmp'. + * If they are the same swap the value with 'with' + * @param mem pointer to the value + * @param with what to swap it with + * @param cmp the value to compare it to + * @return the old value of *mem + */ +APR_DECLARE(apr_uint32_t) apr_atomic_cas32(volatile apr_uint32_t *mem, apr_uint32_t with, + apr_uint32_t cmp); + +/** + * exchange an apr_uint32_t's value with 'val'. + * @param mem pointer to the value + * @param val what to swap it with + * @return the old value of *mem + */ +APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint32_t val); + +/** + * compare the pointer's value with cmp. + * If they are the same swap the value with 'with' + * @param mem pointer to the pointer + * @param with what to swap it with + * @param cmp the value to compare it to + * @return the old value of the pointer + */ +APR_DECLARE(void*) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_ATOMIC_H */ diff --git a/srclib/apr/include/apr_dso.h b/srclib/apr/include/apr_dso.h new file mode 100644 index 0000000000..91c6d5befa --- /dev/null +++ b/srclib/apr/include/apr_dso.h @@ -0,0 +1,94 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_DSO_DOT_H +#define APR_DSO_DOT_H + +/** + * @file apr_dso.h + * @brief APR Dynamic Object Handling Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_dso Dynamic Object Handling + * @ingroup APR + * @{ + */ + +#if APR_HAS_DSO || defined(DOXYGEN) + +/** + * Structure for referencing dynamic objects + */ +typedef struct apr_dso_handle_t apr_dso_handle_t; + +/** + * Structure for referencing symbols from dynamic objects + */ +typedef void * apr_dso_handle_sym_t; + +/** + * Load a DSO library. + * @param res_handle Location to store new handle for the DSO. + * @param path Path to the DSO library + * @param ctx Pool to use. + * @bug We aught to provide an alternative to RTLD_GLOBAL, which + * is the only supported method of loading DSOs today. + */ +APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, + const char *path, apr_pool_t *ctx); + +/** + * Close a DSO library. + * @param handle handle to close. + */ +APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle); + +/** + * Load a symbol from a DSO handle. + * @param ressym Location to store the loaded symbol + * @param handle handle to load the symbol from. + * @param symname Name of the symbol to load. + */ +APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym, + apr_dso_handle_t *handle, + const char *symname); + +/** + * Report more information when a DSO function fails. + * @param dso The dso handle that has been opened + * @param buf Location to store the dso error + * @param bufsize The size of the provided buffer + */ +APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize); + +#endif /* APR_HAS_DSO */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/srclib/apr/include/apr_env.h b/srclib/apr/include/apr_env.h new file mode 100644 index 0000000000..9e3d2a72d8 --- /dev/null +++ b/srclib/apr/include/apr_env.h @@ -0,0 +1,67 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_ENV_H +#define APR_ENV_H +/** + * @file apr_env.h + * @brief APR Environment functions + */ +#include "apr_errno.h" +#include "apr_pools.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_env Functions for manupulating the environment + * @ingroup APR + * @{ + */ + +/** + * Get the value of an environment variable + * @param value the returned value, allocated from @a pool + * @param envvar the name of the environment variable + * @param pool where to allocate @a value and any temporary storage from + */ +APR_DECLARE(apr_status_t) apr_env_get(char **value, const char *envvar, + apr_pool_t *pool); + +/** + * Set the value of an environment variable + * @param envvar the name of the environment variable + * @param value the value to set + * @param pool where to allocate temporary storage from + */ +APR_DECLARE(apr_status_t) apr_env_set(const char *envvar, const char *value, + apr_pool_t *pool); + +/** + * Delete a variable from the environment + * @param envvar the name of the environment variable + * @param pool where to allocate temporary storage from + */ +APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_ENV_H */ diff --git a/srclib/apr/include/apr_errno.h b/srclib/apr/include/apr_errno.h new file mode 100644 index 0000000000..2046f3e2b2 --- /dev/null +++ b/srclib/apr/include/apr_errno.h @@ -0,0 +1,1224 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_ERRNO_H +#define APR_ERRNO_H + +/** + * @file apr_errno.h + * @brief APR Error Codes + */ + +#include "apr.h" + +#if APR_HAVE_ERRNO_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_errno Error Codes + * @ingroup APR + * @{ + */ + +/** + * Type for specifying an error or status code. + */ +typedef int apr_status_t; + +/** + * Return a human readable string describing the specified error. + * @param statcode The error code the get a string for. + * @param buf A buffer to hold the error string. + * @param bufsize Size of the buffer to hold the string. + */ +APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf, + apr_size_t bufsize); + +#if defined(DOXYGEN) +/** + * @def APR_FROM_OS_ERROR(os_err_type syserr) + * Fold a platform specific error into an apr_status_t code. + * @return apr_status_t + * @param e The platform os error code. + * @warning macro implementation; the syserr argument may be evaluated + * multiple times. + */ +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) + +/** + * @def APR_TO_OS_ERROR(apr_status_t statcode) + * @return os_err_type + * Fold an apr_status_t code back to the native platform defined error. + * @param e The apr_status_t folded platform os error code. + * @warning macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. + */ +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +/** @def apr_get_os_error() + * @return apr_status_t the last platform error, folded into apr_status_t, on most platforms + * @remark This retrieves errno, or calls a GetLastError() style function, and + * folds it with APR_FROM_OS_ERROR. Some platforms (such as OS2) have no + * such mechanism, so this call may be unsupported. Do NOT use this + * call for socket errors from socket, send, recv etc! + */ + +/** @def apr_set_os_error(e) + * Reset the last platform error, unfolded from an apr_status_t, on some platforms + * @param e The OS error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a SetLastError() style function, unfolding statcode + * with APR_TO_OS_ERROR. Some platforms (such as OS2) have no such + * mechanism, so this call may be unsupported. + */ + +/** @def apr_get_netos_error() + * Return the last socket error, folded into apr_status_t, on all platforms + * @remark This retrieves errno or calls a GetLastSocketError() style function, + * and folds it with APR_FROM_OS_ERROR. + */ + +/** @def apr_set_netos_error(e) + * Reset the last socket error, unfolded from an apr_status_t + * @param e The socket error folded in a prior call to APR_FROM_OS_ERROR() + * @warning This is a macro implementation; the statcode argument may be evaluated + * multiple times. If the statcode was not created by apr_get_os_error + * or APR_FROM_OS_ERROR, the results are undefined. This macro sets + * errno, or calls a WSASetLastError() style function, unfolding + * socketcode with APR_TO_OS_ERROR. + */ + +#endif /* defined(DOXYGEN) */ + +/** + * APR_OS_START_ERROR is where the APR specific error values start. + */ +#define APR_OS_START_ERROR 20000 +/** + * APR_OS_ERRSPACE_SIZE is the maximum number of errors you can fit + * into one of the error/status ranges below -- except for + * APR_OS_START_USERERR, which see. + */ +#define APR_OS_ERRSPACE_SIZE 50000 +/** + * APR_OS_START_STATUS is where the APR specific status codes start. + */ +#define APR_OS_START_STATUS (APR_OS_START_ERROR + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_USERERR are reserved for applications that use APR that + * layer their own error codes along with APR's. Note that the + * error immediately following this one is set ten times farther + * away than usual, so that users of apr have a lot of room in + * which to declare custom error codes. + */ +#define APR_OS_START_USERERR (APR_OS_START_STATUS + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_USEERR is obsolete, defined for compatibility only. + * Use APR_OS_START_USERERR instead. + */ +#define APR_OS_START_USEERR APR_OS_START_USERERR +/** + * APR_OS_START_CANONERR is where APR versions of errno values are defined + * on systems which don't have the corresponding errno. + */ +#define APR_OS_START_CANONERR (APR_OS_START_USERERR \ + + (APR_OS_ERRSPACE_SIZE * 10)) +/** + * APR_OS_START_EAIERR folds EAI_ error codes from getaddrinfo() into + * apr_status_t values. + */ +#define APR_OS_START_EAIERR (APR_OS_START_CANONERR + APR_OS_ERRSPACE_SIZE) +/** + * APR_OS_START_SYSERR folds platform-specific system error values into + * apr_status_t values. + */ +#define APR_OS_START_SYSERR (APR_OS_START_EAIERR + APR_OS_ERRSPACE_SIZE) + +/** no error. */ +#define APR_SUCCESS 0 + +/** + * @defgroup APR_Error APR Error Values + *
    + * APR ERROR VALUES
    + * APR_ENOSTAT      APR was unable to perform a stat on the file 
    + * APR_ENOPOOL      APR was not provided a pool with which to allocate memory
    + * APR_EBADDATE     APR was given an invalid date 
    + * APR_EINVALSOCK   APR was given an invalid socket
    + * APR_ENOPROC      APR was not given a process structure
    + * APR_ENOTIME      APR was not given a time structure
    + * APR_ENODIR       APR was not given a directory structure
    + * APR_ENOLOCK      APR was not given a lock structure
    + * APR_ENOPOLL      APR was not given a poll structure
    + * APR_ENOSOCKET    APR was not given a socket
    + * APR_ENOTHREAD    APR was not given a thread structure
    + * APR_ENOTHDKEY    APR was not given a thread key structure
    + * APR_ENOSHMAVAIL  There is no more shared memory available
    + * APR_EDSOOPEN     APR was unable to open the dso object.  For more 
    + *                  information call apr_dso_error().
    + * APR_EGENERAL     General failure (specific information not available)
    + * APR_EBADIP       The specified IP address is invalid
    + * APR_EBADMASK     The specified netmask is invalid
    + * APR_ESYMNOTFOUND Could not find the requested symbol
    + * 
    + * + *
    + * APR STATUS VALUES
    + * APR_INCHILD        Program is currently executing in the child
    + * APR_INPARENT       Program is currently executing in the parent
    + * APR_DETACH         The thread is detached
    + * APR_NOTDETACH      The thread is not detached
    + * APR_CHILD_DONE     The child has finished executing
    + * APR_CHILD_NOTDONE  The child has not finished executing
    + * APR_TIMEUP         The operation did not finish before the timeout
    + * APR_INCOMPLETE     The operation was incomplete although some processing
    + *                    was performed and the results are partially valid
    + * APR_BADCH          Getopt found an option not in the option string
    + * APR_BADARG         Getopt found an option that is missing an argument 
    + *                    and an argument was specified in the option string
    + * APR_EOF            APR has encountered the end of the file
    + * APR_NOTFOUND       APR was unable to find the socket in the poll structure
    + * APR_ANONYMOUS      APR is using anonymous shared memory
    + * APR_FILEBASED      APR is using a file name as the key to the shared memory
    + * APR_KEYBASED       APR is using a shared key as the key to the shared memory
    + * APR_EINIT          Ininitalizer value.  If no option has been found, but 
    + *                    the status variable requires a value, this should be used
    + * APR_ENOTIMPL       The APR function has not been implemented on this 
    + *                    platform, either because nobody has gotten to it yet, 
    + *                    or the function is impossible on this platform.
    + * APR_EMISMATCH      Two passwords do not match.
    + * APR_EABSOLUTE      The given path was absolute.
    + * APR_ERELATIVE      The given path was relative.
    + * APR_EINCOMPLETE    The given path was neither relative nor absolute.
    + * APR_EABOVEROOT     The given path was above the root path.
    + * APR_EBUSY          The given lock was busy.
    + * APR_EPROC_UNKNOWN  The given process wasn't recognized by APR
    + * 
    + * @{ + */ +/** @see APR_STATUS_IS_ENOSTAT */ +#define APR_ENOSTAT (APR_OS_START_ERROR + 1) +/** @see APR_STATUS_IS_ENOPOOL */ +#define APR_ENOPOOL (APR_OS_START_ERROR + 2) +/* empty slot: +3 */ +/** @see APR_STATUS_IS_EBADDATE */ +#define APR_EBADDATE (APR_OS_START_ERROR + 4) +/** @see APR_STATUS_IS_EINVALSOCK */ +#define APR_EINVALSOCK (APR_OS_START_ERROR + 5) +/** @see APR_STATUS_IS_ENOPROC */ +#define APR_ENOPROC (APR_OS_START_ERROR + 6) +/** @see APR_STATUS_IS_ENOTIME */ +#define APR_ENOTIME (APR_OS_START_ERROR + 7) +/** @see APR_STATUS_IS_ENODIR */ +#define APR_ENODIR (APR_OS_START_ERROR + 8) +/** @see APR_STATUS_IS_ENOLOCK */ +#define APR_ENOLOCK (APR_OS_START_ERROR + 9) +/** @see APR_STATUS_IS_ENOPOLL */ +#define APR_ENOPOLL (APR_OS_START_ERROR + 10) +/** @see APR_STATUS_IS_ENOSOCKET */ +#define APR_ENOSOCKET (APR_OS_START_ERROR + 11) +/** @see APR_STATUS_IS_ENOTHREAD */ +#define APR_ENOTHREAD (APR_OS_START_ERROR + 12) +/** @see APR_STATUS_IS_ENOTHDKEY */ +#define APR_ENOTHDKEY (APR_OS_START_ERROR + 13) +/** @see APR_STATUS_IS_EGENERAL */ +#define APR_EGENERAL (APR_OS_START_ERROR + 14) +/** @see APR_STATUS_IS_ENOSHMAVAIL */ +#define APR_ENOSHMAVAIL (APR_OS_START_ERROR + 15) +/** @see APR_STATUS_IS_EBADIP */ +#define APR_EBADIP (APR_OS_START_ERROR + 16) +/** @see APR_STATUS_IS_EBADMASK */ +#define APR_EBADMASK (APR_OS_START_ERROR + 17) +/* empty slot: +18 */ +/** @see APR_STATUS_IS_EDSOPEN */ +#define APR_EDSOOPEN (APR_OS_START_ERROR + 19) +/** @see APR_STATUS_IS_EABSOLUTE */ +#define APR_EABSOLUTE (APR_OS_START_ERROR + 20) +/** @see APR_STATUS_IS_ERELATIVE */ +#define APR_ERELATIVE (APR_OS_START_ERROR + 21) +/** @see APR_STATUS_IS_EINCOMPLETE */ +#define APR_EINCOMPLETE (APR_OS_START_ERROR + 22) +/** @see APR_STATUS_IS_EABOVEROOT */ +#define APR_EABOVEROOT (APR_OS_START_ERROR + 23) +/** @see APR_STATUS_IS_EBADPATH */ +#define APR_EBADPATH (APR_OS_START_ERROR + 24) +/** @see APR_STATUS_IS_EPATHWILD */ +#define APR_EPATHWILD (APR_OS_START_ERROR + 25) +/** @see APR_STATUS_IS_ESYMNOTFOUND */ +#define APR_ESYMNOTFOUND (APR_OS_START_ERROR + 26) +/** @see APR_STATUS_IS_EPROC_UNKNOWN */ +#define APR_EPROC_UNKNOWN (APR_OS_START_ERROR + 27) +/** @see APR_STATUS_IS_ENOTENOUGHENTROPY */ +#define APR_ENOTENOUGHENTROPY (APR_OS_START_ERROR + 28) +/** @} */ + +/** + * @defgroup APR_STATUS_IS Status Value Tests + * @warning For any particular error condition, more than one of these tests + * may match. This is because platform-specific error codes may not + * always match the semantics of the POSIX codes these tests (and the + * corresponding APR error codes) are named after. A notable example + * are the APR_STATUS_IS_ENOENT and APR_STATUS_IS_ENOTDIR tests on + * Win32 platforms. The programmer should always be aware of this and + * adjust the order of the tests accordingly. + * @{ + */ +/** + * APR was unable to perform a stat on the file + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOSTAT(s) ((s) == APR_ENOSTAT) +/** + * APR was not provided a pool with which to allocate memory + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOPOOL(s) ((s) == APR_ENOPOOL) +/** APR was given an invalid date */ +#define APR_STATUS_IS_EBADDATE(s) ((s) == APR_EBADDATE) +/** APR was given an invalid socket */ +#define APR_STATUS_IS_EINVALSOCK(s) ((s) == APR_EINVALSOCK) +/** APR was not given a process structure */ +#define APR_STATUS_IS_ENOPROC(s) ((s) == APR_ENOPROC) +/** APR was not given a time structure */ +#define APR_STATUS_IS_ENOTIME(s) ((s) == APR_ENOTIME) +/** APR was not given a directory structure */ +#define APR_STATUS_IS_ENODIR(s) ((s) == APR_ENODIR) +/** APR was not given a lock structure */ +#define APR_STATUS_IS_ENOLOCK(s) ((s) == APR_ENOLOCK) +/** APR was not given a poll structure */ +#define APR_STATUS_IS_ENOPOLL(s) ((s) == APR_ENOPOLL) +/** APR was not given a socket */ +#define APR_STATUS_IS_ENOSOCKET(s) ((s) == APR_ENOSOCKET) +/** APR was not given a thread structure */ +#define APR_STATUS_IS_ENOTHREAD(s) ((s) == APR_ENOTHREAD) +/** APR was not given a thread key structure */ +#define APR_STATUS_IS_ENOTHDKEY(s) ((s) == APR_ENOTHDKEY) +/** Generic Error which can not be put into another spot */ +#define APR_STATUS_IS_EGENERAL(s) ((s) == APR_EGENERAL) +/** There is no more shared memory available */ +#define APR_STATUS_IS_ENOSHMAVAIL(s) ((s) == APR_ENOSHMAVAIL) +/** The specified IP address is invalid */ +#define APR_STATUS_IS_EBADIP(s) ((s) == APR_EBADIP) +/** The specified netmask is invalid */ +#define APR_STATUS_IS_EBADMASK(s) ((s) == APR_EBADMASK) +/* empty slot: +18 */ +/** + * APR was unable to open the dso object. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN \ + || APR_TO_OS_ERROR(s) == ERROR_MOD_NOT_FOUND) +#else +#define APR_STATUS_IS_EDSOOPEN(s) ((s) == APR_EDSOOPEN) +#endif +/** The given path was absolute. */ +#define APR_STATUS_IS_EABSOLUTE(s) ((s) == APR_EABSOLUTE) +/** The given path was relative. */ +#define APR_STATUS_IS_ERELATIVE(s) ((s) == APR_ERELATIVE) +/** The given path was neither relative nor absolute. */ +#define APR_STATUS_IS_EINCOMPLETE(s) ((s) == APR_EINCOMPLETE) +/** The given path was above the root path. */ +#define APR_STATUS_IS_EABOVEROOT(s) ((s) == APR_EABOVEROOT) +/** The given path was bad. */ +#define APR_STATUS_IS_EBADPATH(s) ((s) == APR_EBADPATH) +/** The given path contained wildcards. */ +#define APR_STATUS_IS_EPATHWILD(s) ((s) == APR_EPATHWILD) +/** Could not find the requested symbol. + * For more information call apr_dso_error(). + */ +#if defined(WIN32) +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND \ + || APR_TO_OS_ERROR(s) == ERROR_PROC_NOT_FOUND) +#else +#define APR_STATUS_IS_ESYMNOTFOUND(s) ((s) == APR_ESYMNOTFOUND) +#endif +/** The given process was not recognized by APR. */ +#define APR_STATUS_IS_EPROC_UNKNOWN(s) ((s) == APR_EPROC_UNKNOWN) + +/** APR could not gather enough entropy to continue. */ +#define APR_STATUS_IS_ENOTENOUGHENTROPY(s) ((s) == APR_ENOTENOUGHENTROPY) + +/** @} */ + +/** + * @addtogroup APR_Error + * @{ + */ +/** @see APR_STATUS_IS_INCHILD */ +#define APR_INCHILD (APR_OS_START_STATUS + 1) +/** @see APR_STATUS_IS_INPARENT */ +#define APR_INPARENT (APR_OS_START_STATUS + 2) +/** @see APR_STATUS_IS_DETACH */ +#define APR_DETACH (APR_OS_START_STATUS + 3) +/** @see APR_STATUS_IS_NOTDETACH */ +#define APR_NOTDETACH (APR_OS_START_STATUS + 4) +/** @see APR_STATUS_IS_CHILD_DONE */ +#define APR_CHILD_DONE (APR_OS_START_STATUS + 5) +/** @see APR_STATUS_IS_CHILD_NOTDONE */ +#define APR_CHILD_NOTDONE (APR_OS_START_STATUS + 6) +/** @see APR_STATUS_IS_TIMEUP */ +#define APR_TIMEUP (APR_OS_START_STATUS + 7) +/** @see APR_STATUS_IS_INCOMPLETE */ +#define APR_INCOMPLETE (APR_OS_START_STATUS + 8) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** @see APR_STATUS_IS_BADCH */ +#define APR_BADCH (APR_OS_START_STATUS + 12) +/** @see APR_STATUS_IS_BADARG */ +#define APR_BADARG (APR_OS_START_STATUS + 13) +/** @see APR_STATUS_IS_EOF */ +#define APR_EOF (APR_OS_START_STATUS + 14) +/** @see APR_STATUS_IS_NOTFOUND */ +#define APR_NOTFOUND (APR_OS_START_STATUS + 15) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** @see APR_STATUS_IS_ANONYMOUS */ +#define APR_ANONYMOUS (APR_OS_START_STATUS + 19) +/** @see APR_STATUS_IS_FILEBASED */ +#define APR_FILEBASED (APR_OS_START_STATUS + 20) +/** @see APR_STATUS_IS_KEYBASED */ +#define APR_KEYBASED (APR_OS_START_STATUS + 21) +/** @see APR_STATUS_IS_EINIT */ +#define APR_EINIT (APR_OS_START_STATUS + 22) +/** @see APR_STATUS_IS_ENOTIMPL */ +#define APR_ENOTIMPL (APR_OS_START_STATUS + 23) +/** @see APR_STATUS_IS_EMISMATCH */ +#define APR_EMISMATCH (APR_OS_START_STATUS + 24) +/** @see APR_STATUS_IS_EBUSY */ +#define APR_EBUSY (APR_OS_START_STATUS + 25) +/** @} */ + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ +/** + * Program is currently executing in the child + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code */ +#define APR_STATUS_IS_INCHILD(s) ((s) == APR_INCHILD) +/** + * Program is currently executing in the parent + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INPARENT(s) ((s) == APR_INPARENT) +/** + * The thread is detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_DETACH(s) ((s) == APR_DETACH) +/** + * The thread is not detached + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTDETACH(s) ((s) == APR_NOTDETACH) +/** + * The child has finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_DONE(s) ((s) == APR_CHILD_DONE) +/** + * The child has not finished executing + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_CHILD_NOTDONE(s) ((s) == APR_CHILD_NOTDONE) +/** + * The operation did not finish before the timeout + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP) +/** + * The character conversion stopped because of an incomplete character or + * shift sequence at the end of the input buffer. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_INCOMPLETE(s) ((s) == APR_INCOMPLETE) +/* empty slot: +9 */ +/* empty slot: +10 */ +/* empty slot: +11 */ +/** + * Getopt found an option not in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADCH(s) ((s) == APR_BADCH) +/** + * Getopt found an option not in the option string and an argument was + * specified in the option string + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_BADARG(s) ((s) == APR_BADARG) +/** + * APR has encountered the end of the file + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EOF(s) ((s) == APR_EOF) +/** + * APR was unable to find the socket in the poll structure + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_NOTFOUND(s) ((s) == APR_NOTFOUND) +/* empty slot: +16 */ +/* empty slot: +17 */ +/* empty slot: +18 */ +/** + * APR is using anonymous shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ANONYMOUS(s) ((s) == APR_ANONYMOUS) +/** + * APR is using a file name as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_FILEBASED(s) ((s) == APR_FILEBASED) +/** + * APR is using a shared key as the key to the shared memory + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_KEYBASED(s) ((s) == APR_KEYBASED) +/** + * Ininitalizer value. If no option has been found, but + * the status variable requires a value, this should be used + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EINIT(s) ((s) == APR_EINIT) +/** + * The APR function has not been implemented on this + * platform, either because nobody has gotten to it yet, + * or the function is impossible on this platform. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_ENOTIMPL(s) ((s) == APR_ENOTIMPL) +/** + * Two passwords do not match. + * @warning + * always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EMISMATCH(s) ((s) == APR_EMISMATCH) +/** + * The given lock was busy + * @warning always use this test, as platform-specific variances may meet this + * more than one error code + */ +#define APR_STATUS_IS_EBUSY(s) ((s) == APR_EBUSY) + +/** @} */ + +/** + * @addtogroup APR_Error APR Error Values + * @{ + */ +/* APR CANONICAL ERROR VALUES */ +/** @see APR_STATUS_IS_EACCES */ +#ifdef EACCES +#define APR_EACCES EACCES +#else +#define APR_EACCES (APR_OS_START_CANONERR + 1) +#endif + +/** @see APR_STATUS_IS_EXIST */ +#ifdef EEXIST +#define APR_EEXIST EEXIST +#else +#define APR_EEXIST (APR_OS_START_CANONERR + 2) +#endif + +/** @see APR_STATUS_IS_ENAMETOOLONG */ +#ifdef ENAMETOOLONG +#define APR_ENAMETOOLONG ENAMETOOLONG +#else +#define APR_ENAMETOOLONG (APR_OS_START_CANONERR + 3) +#endif + +/** @see APR_STATUS_IS_ENOENT */ +#ifdef ENOENT +#define APR_ENOENT ENOENT +#else +#define APR_ENOENT (APR_OS_START_CANONERR + 4) +#endif + +/** @see APR_STATUS_IS_ENOTDIR */ +#ifdef ENOTDIR +#define APR_ENOTDIR ENOTDIR +#else +#define APR_ENOTDIR (APR_OS_START_CANONERR + 5) +#endif + +/** @see APR_STATUS_IS_ENOSPC */ +#ifdef ENOSPC +#define APR_ENOSPC ENOSPC +#else +#define APR_ENOSPC (APR_OS_START_CANONERR + 6) +#endif + +/** @see APR_STATUS_IS_ENOMEM */ +#ifdef ENOMEM +#define APR_ENOMEM ENOMEM +#else +#define APR_ENOMEM (APR_OS_START_CANONERR + 7) +#endif + +/** @see APR_STATUS_IS_EMFILE */ +#ifdef EMFILE +#define APR_EMFILE EMFILE +#else +#define APR_EMFILE (APR_OS_START_CANONERR + 8) +#endif + +/** @see APR_STATUS_IS_ENFILE */ +#ifdef ENFILE +#define APR_ENFILE ENFILE +#else +#define APR_ENFILE (APR_OS_START_CANONERR + 9) +#endif + +/** @see APR_STATUS_IS_EBADF */ +#ifdef EBADF +#define APR_EBADF EBADF +#else +#define APR_EBADF (APR_OS_START_CANONERR + 10) +#endif + +/** @see APR_STATUS_IS_EINVAL */ +#ifdef EINVAL +#define APR_EINVAL EINVAL +#else +#define APR_EINVAL (APR_OS_START_CANONERR + 11) +#endif + +/** @see APR_STATUS_IS_ESPIPE */ +#ifdef ESPIPE +#define APR_ESPIPE ESPIPE +#else +#define APR_ESPIPE (APR_OS_START_CANONERR + 12) +#endif + +/** + * @see APR_STATUS_IS_EAGAIN + * @warning use APR_STATUS_IS_EAGAIN instead of just testing this value + */ +#ifdef EAGAIN +#define APR_EAGAIN EAGAIN +#elif defined(EWOULDBLOCK) +#define APR_EAGAIN EWOULDBLOCK +#else +#define APR_EAGAIN (APR_OS_START_CANONERR + 13) +#endif + +/** @see APR_STATUS_IS_EINTR */ +#ifdef EINTR +#define APR_EINTR EINTR +#else +#define APR_EINTR (APR_OS_START_CANONERR + 14) +#endif + +/** @see APR_STATUS_IS_ENOTSOCK */ +#ifdef ENOTSOCK +#define APR_ENOTSOCK ENOTSOCK +#else +#define APR_ENOTSOCK (APR_OS_START_CANONERR + 15) +#endif + +/** @see APR_STATUS_IS_ECONNREFUSED */ +#ifdef ECONNREFUSED +#define APR_ECONNREFUSED ECONNREFUSED +#else +#define APR_ECONNREFUSED (APR_OS_START_CANONERR + 16) +#endif + +/** @see APR_STATUS_IS_EINPROGRESS */ +#ifdef EINPROGRESS +#define APR_EINPROGRESS EINPROGRESS +#else +#define APR_EINPROGRESS (APR_OS_START_CANONERR + 17) +#endif + +/** + * @see APR_STATUS_IS_ECONNABORTED + * @warning use APR_STATUS_IS_ECONNABORTED instead of just testing this value + */ + +#ifdef ECONNABORTED +#define APR_ECONNABORTED ECONNABORTED +#else +#define APR_ECONNABORTED (APR_OS_START_CANONERR + 18) +#endif + +/** @see APR_STATUS_IS_ECONNRESET */ +#ifdef ECONNRESET +#define APR_ECONNRESET ECONNRESET +#else +#define APR_ECONNRESET (APR_OS_START_CANONERR + 19) +#endif + +/** @see APR_STATUS_IS_ETIMEDOUT + * @deprecated */ +#ifdef ETIMEDOUT +#define APR_ETIMEDOUT ETIMEDOUT +#else +#define APR_ETIMEDOUT (APR_OS_START_CANONERR + 20) +#endif + +/** @see APR_STATUS_IS_EHOSTUNREACH */ +#ifdef EHOSTUNREACH +#define APR_EHOSTUNREACH EHOSTUNREACH +#else +#define APR_EHOSTUNREACH (APR_OS_START_CANONERR + 21) +#endif + +/** @see APR_STATUS_IS_ENETUNREACH */ +#ifdef ENETUNREACH +#define APR_ENETUNREACH ENETUNREACH +#else +#define APR_ENETUNREACH (APR_OS_START_CANONERR + 22) +#endif + +/** @see APR_STATUS_IS_EFTYPE */ +#ifdef EFTYPE +#define APR_EFTYPE EFTYPE +#else +#define APR_EFTYPE (APR_OS_START_CANONERR + 23) +#endif + +/** @see APR_STATUS_IS_EPIPE */ +#ifdef EPIPE +#define APR_EPIPE EPIPE +#else +#define APR_EPIPE (APR_OS_START_CANONERR + 24) +#endif + +/** @see APR_STATUS_IS_EXDEV */ +#ifdef EXDEV +#define APR_EXDEV EXDEV +#else +#define APR_EXDEV (APR_OS_START_CANONERR + 25) +#endif + +/** @see APR_STATUS_IS_ENOTEMPTY */ +#ifdef ENOTEMPTY +#define APR_ENOTEMPTY ENOTEMPTY +#else +#define APR_ENOTEMPTY (APR_OS_START_CANONERR + 26) +#endif + +/** @} */ + +#if defined(OS2) && !defined(DOXYGEN) + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define INCL_DOSERRORS +#define INCL_DOS + +/* Leave these undefined. + * OS2 doesn't rely on the errno concept. + * The API calls always return a result codes which + * should be filtered through APR_FROM_OS_ERROR(). + * + * #define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) + * #define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + */ + +/* A special case, only socket calls require this; + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(errno)) +#define apr_set_netos_error(e) (errno = APR_TO_OS_ERROR(e)) + +/* And this needs to be greped away for good: + */ +#define APR_OS2_STATUS(e) (APR_FROM_OS_ERROR(e)) + +/* These can't sit in a private header, so in spite of the extra size, + * they need to be made available here. + */ +#define SOCBASEERR 10000 +#define SOCEPERM (SOCBASEERR+1) /* Not owner */ +#define SOCESRCH (SOCBASEERR+3) /* No such process */ +#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ +#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ +#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ +#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ +#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ +#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ +#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ +#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ +#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ +#define SOCEWOULDBLOCK (SOCBASEERR+35) /* Operation would block */ +#define SOCEINPROGRESS (SOCBASEERR+36) /* Operation now in progress */ +#define SOCEALREADY (SOCBASEERR+37) /* Operation already in progress */ +#define SOCENOTSOCK (SOCBASEERR+38) /* Socket operation on non-socket */ +#define SOCEDESTADDRREQ (SOCBASEERR+39) /* Destination address required */ +#define SOCEMSGSIZE (SOCBASEERR+40) /* Message too long */ +#define SOCEPROTOTYPE (SOCBASEERR+41) /* Protocol wrong type for socket */ +#define SOCENOPROTOOPT (SOCBASEERR+42) /* Protocol not available */ +#define SOCEPROTONOSUPPORT (SOCBASEERR+43) /* Protocol not supported */ +#define SOCESOCKTNOSUPPORT (SOCBASEERR+44) /* Socket type not supported */ +#define SOCEOPNOTSUPP (SOCBASEERR+45) /* Operation not supported on socket */ +#define SOCEPFNOSUPPORT (SOCBASEERR+46) /* Protocol family not supported */ +#define SOCEAFNOSUPPORT (SOCBASEERR+47) /* Address family not supported by protocol family */ +#define SOCEADDRINUSE (SOCBASEERR+48) /* Address already in use */ +#define SOCEADDRNOTAVAIL (SOCBASEERR+49) /* Can't assign requested address */ +#define SOCENETDOWN (SOCBASEERR+50) /* Network is down */ +#define SOCENETUNREACH (SOCBASEERR+51) /* Network is unreachable */ +#define SOCENETRESET (SOCBASEERR+52) /* Network dropped connection on reset */ +#define SOCECONNABORTED (SOCBASEERR+53) /* Software caused connection abort */ +#define SOCECONNRESET (SOCBASEERR+54) /* Connection reset by peer */ +#define SOCENOBUFS (SOCBASEERR+55) /* No buffer space available */ +#define SOCEISCONN (SOCBASEERR+56) /* Socket is already connected */ +#define SOCENOTCONN (SOCBASEERR+57) /* Socket is not connected */ +#define SOCESHUTDOWN (SOCBASEERR+58) /* Can't send after socket shutdown */ +#define SOCETOOMANYREFS (SOCBASEERR+59) /* Too many references: can't splice */ +#define SOCETIMEDOUT (SOCBASEERR+60) /* Connection timed out */ +#define SOCECONNREFUSED (SOCBASEERR+61) /* Connection refused */ +#define SOCELOOP (SOCBASEERR+62) /* Too many levels of symbolic links */ +#define SOCENAMETOOLONG (SOCBASEERR+63) /* File name too long */ +#define SOCEHOSTDOWN (SOCBASEERR+64) /* Host is down */ +#define SOCEHOSTUNREACH (SOCBASEERR+65) /* No route to host */ +#define SOCENOTEMPTY (SOCBASEERR+66) /* Directory not empty */ + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + SOCENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + SOCEWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + SOCEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + SOCENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + SOCECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + SOCEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + SOCECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + SOCECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + SOCETIMEDOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + SOCENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE \ + || (s) == APR_OS_START_SYSERR + SOCEPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED) + +/* + Sorry, too tired to wrap this up for OS2... feel free to + fit the following into their best matches. + + { ERROR_NO_SIGNAL_SENT, ESRCH }, + { SOCEALREADY, EALREADY }, + { SOCEDESTADDRREQ, EDESTADDRREQ }, + { SOCEMSGSIZE, EMSGSIZE }, + { SOCEPROTOTYPE, EPROTOTYPE }, + { SOCENOPROTOOPT, ENOPROTOOPT }, + { SOCEPROTONOSUPPORT, EPROTONOSUPPORT }, + { SOCESOCKTNOSUPPORT, ESOCKTNOSUPPORT }, + { SOCEOPNOTSUPP, EOPNOTSUPP }, + { SOCEPFNOSUPPORT, EPFNOSUPPORT }, + { SOCEAFNOSUPPORT, EAFNOSUPPORT }, + { SOCEADDRINUSE, EADDRINUSE }, + { SOCEADDRNOTAVAIL, EADDRNOTAVAIL }, + { SOCENETDOWN, ENETDOWN }, + { SOCENETRESET, ENETRESET }, + { SOCENOBUFS, ENOBUFS }, + { SOCEISCONN, EISCONN }, + { SOCENOTCONN, ENOTCONN }, + { SOCESHUTDOWN, ESHUTDOWN }, + { SOCETOOMANYREFS, ETOOMANYREFS }, + { SOCELOOP, ELOOP }, + { SOCEHOSTDOWN, EHOSTDOWN }, + { SOCENOTEMPTY, ENOTEMPTY }, + { SOCEPIPE, EPIPE } +*/ + +#elif defined(WIN32) && !defined(DOXYGEN) /* !defined(OS2) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (APR_FROM_OS_ERROR(GetLastError())) +#define apr_set_os_error(e) (SetLastError(APR_TO_OS_ERROR(e))) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES \ + || (s) == APR_OS_START_SYSERR + ERROR_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_CANNOT_MAKE \ + || (s) == APR_OS_START_SYSERR + ERROR_CURRENT_DIRECTORY \ + || (s) == APR_OS_START_SYSERR + ERROR_DRIVE_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_FAIL_I24 \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_LOCKED \ + || (s) == APR_OS_START_SYSERR + ERROR_NETWORK_ACCESS_DENIED \ + || (s) == APR_OS_START_SYSERR + ERROR_SHARING_VIOLATION) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_EXISTS \ + || (s) == APR_OS_START_SYSERR + ERROR_ALREADY_EXISTS) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG \ + || (s) == APR_OS_START_SYSERR + ERROR_FILENAME_EXCED_RANGE \ + || (s) == APR_OS_START_SYSERR + WSAENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_OPEN_FAILED \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_MORE_FILES) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR \ + || (s) == APR_OS_START_SYSERR + ERROR_PATH_NOT_FOUND \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NETPATH \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_NET_NAME \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_PATHNAME \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DRIVE) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == APR_OS_START_SYSERR + ERROR_DISK_FULL) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM \ + || (s) == APR_OS_START_SYSERR + ERROR_ARENA_TRASHED \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_MEMORY \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_BLOCK \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_ENOUGH_QUOTA \ + || (s) == APR_OS_START_SYSERR + ERROR_OUTOFMEMORY) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE \ + || (s) == APR_OS_START_SYSERR + ERROR_TOO_MANY_OPEN_FILES) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_TARGET_HANDLE) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_ACCESS \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_FUNCTION \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_HANDLE \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_PARAMETER \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_SEEK_ON_DEVICE \ + || (s) == APR_OS_START_SYSERR + ERROR_NEGATIVE_SEEK) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_DATA \ + || (s) == APR_OS_START_SYSERR + ERROR_NO_PROC_SLOTS \ + || (s) == APR_OS_START_SYSERR + ERROR_NESTING_NOT_ALLOWED \ + || (s) == APR_OS_START_SYSERR + ERROR_MAX_THRDS_REACHED \ + || (s) == APR_OS_START_SYSERR + ERROR_LOCK_VIOLATION \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + ERROR_NETNAME_DELETED \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_EXE_MACHINE_TYPE_MISMATCH \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_DLL \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_MODULETYPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_EXE_FORMAT \ + || (s) == APR_OS_START_SYSERR + ERROR_INVALID_EXE_SIGNATURE \ + || (s) == APR_OS_START_SYSERR + ERROR_FILE_CORRUPT \ + || (s) == APR_OS_START_SYSERR + ERROR_BAD_FORMAT) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE \ + || (s) == APR_OS_START_SYSERR + ERROR_BROKEN_PIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV \ + || (s) == APR_OS_START_SYSERR + ERROR_NOT_SAME_DEVICE) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY \ + || (s) == APR_OS_START_SYSERR + ERROR_DIR_NOT_EMPTY) + +#elif defined(NETWARE) && defined(USE_WINSOCK) && !defined(DOXYGEN) /* !defined(OS2) && !defined(WIN32) */ + +#define APR_FROM_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e + APR_OS_START_SYSERR) +#define APR_TO_OS_ERROR(e) (e == 0 ? APR_SUCCESS : e - APR_OS_START_SYSERR) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: */ +#define apr_get_netos_error() (APR_FROM_OS_ERROR(WSAGetLastError())) +#define apr_set_netos_error(e) (WSASetLastError(APR_TO_OS_ERROR(e))) + +/* APR CANONICAL ERROR TESTS */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK \ + || (s) == APR_OS_START_SYSERR + WSAEWOULDBLOCK) +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR \ + || (s) == APR_OS_START_SYSERR + WSAEINTR) +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK \ + || (s) == APR_OS_START_SYSERR + WSAENOTSOCK) +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED \ + || (s) == APR_OS_START_SYSERR + WSAECONNREFUSED) +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS \ + || (s) == APR_OS_START_SYSERR + WSAEINPROGRESS) +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == APR_OS_START_SYSERR + WSAECONNABORTED) +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET \ + || (s) == APR_OS_START_SYSERR + WSAECONNRESET) +/* XXX deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#undef APR_STATUS_IS_TIMEUP +#define APR_STATUS_IS_TIMEUP(s) ((s) == APR_TIMEUP \ + || (s) == APR_OS_START_SYSERR + WSAETIMEDOUT \ + || (s) == APR_OS_START_SYSERR + WAIT_TIMEOUT) +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAEHOSTUNREACH) +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH \ + || (s) == APR_OS_START_SYSERR + WSAENETUNREACH) +#define APR_STATUS_IS_ENETDOWN(s) ((s) == APR_OS_START_SYSERR + WSAENETDOWN) +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY) + +#else /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/* + * os error codes are clib error codes + */ +#define APR_FROM_OS_ERROR(e) (e) +#define APR_TO_OS_ERROR(e) (e) + +#define apr_get_os_error() (errno) +#define apr_set_os_error(e) (errno = (e)) + +/* A special case, only socket calls require this: + */ +#define apr_get_netos_error() (errno) +#define apr_set_netos_error(e) (errno = (e)) + +/** + * @addtogroup APR_STATUS_IS + * @{ + */ + +/** permission denied */ +#define APR_STATUS_IS_EACCES(s) ((s) == APR_EACCES) +/** file exists */ +#define APR_STATUS_IS_EEXIST(s) ((s) == APR_EEXIST) +/** path name is too long */ +#define APR_STATUS_IS_ENAMETOOLONG(s) ((s) == APR_ENAMETOOLONG) +/** no such file or directory */ +#define APR_STATUS_IS_ENOENT(s) ((s) == APR_ENOENT) +/** not a directory */ +#define APR_STATUS_IS_ENOTDIR(s) ((s) == APR_ENOTDIR) +/** no space left on device */ +#ifdef EDQUOT +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC \ + || (s) == EDQUOT) +#else +#define APR_STATUS_IS_ENOSPC(s) ((s) == APR_ENOSPC) +#endif +/** not enough memory */ +#define APR_STATUS_IS_ENOMEM(s) ((s) == APR_ENOMEM) +/** too many open files */ +#define APR_STATUS_IS_EMFILE(s) ((s) == APR_EMFILE) +/** file table overflow */ +#define APR_STATUS_IS_ENFILE(s) ((s) == APR_ENFILE) +/** bad file # */ +#define APR_STATUS_IS_EBADF(s) ((s) == APR_EBADF) +/** invalid argument */ +#define APR_STATUS_IS_EINVAL(s) ((s) == APR_EINVAL) +/** illegal seek */ +#define APR_STATUS_IS_ESPIPE(s) ((s) == APR_ESPIPE) + +/** operation would block */ +#if !defined(EWOULDBLOCK) || !defined(EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#elif (EWOULDBLOCK == EAGAIN) +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN) +#else +#define APR_STATUS_IS_EAGAIN(s) ((s) == APR_EAGAIN \ + || (s) == EWOULDBLOCK) +#endif + +/** interrupted system call */ +#define APR_STATUS_IS_EINTR(s) ((s) == APR_EINTR) +/** socket operation on a non-socket */ +#define APR_STATUS_IS_ENOTSOCK(s) ((s) == APR_ENOTSOCK) +/** Connection Refused */ +#define APR_STATUS_IS_ECONNREFUSED(s) ((s) == APR_ECONNREFUSED) +/** operation now in progress */ +#define APR_STATUS_IS_EINPROGRESS(s) ((s) == APR_EINPROGRESS) + +/** + * Software caused connection abort + * @remark + * EPROTO on certain older kernels really means ECONNABORTED, so we need to + * ignore it for them. See discussion in new-httpd archives nh.9701 & nh.9603 + * + * There is potentially a bug in Solaris 2.x x<6, and other boxes that + * implement tcp sockets in userland (i.e. on top of STREAMS). On these + * systems, EPROTO can actually result in a fatal loop. See PR#981 for + * example. It's hard to handle both uses of EPROTO. + */ +#ifdef EPROTO +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED \ + || (s) == EPROTO) +#else +#define APR_STATUS_IS_ECONNABORTED(s) ((s) == APR_ECONNABORTED) +#endif + +/** Connection Reset by peer */ +#define APR_STATUS_IS_ECONNRESET(s) ((s) == APR_ECONNRESET) +/** Operation timed out + * @deprecated */ +#define APR_STATUS_IS_ETIMEDOUT(s) ((s) == APR_ETIMEDOUT) +/** no route to host */ +#define APR_STATUS_IS_EHOSTUNREACH(s) ((s) == APR_EHOSTUNREACH) +/** network is unreachable */ +#define APR_STATUS_IS_ENETUNREACH(s) ((s) == APR_ENETUNREACH) +/** inappropiate file type or format */ +#define APR_STATUS_IS_EFTYPE(s) ((s) == APR_EFTYPE) +/** broken pipe */ +#define APR_STATUS_IS_EPIPE(s) ((s) == APR_EPIPE) +/** cross device link */ +#define APR_STATUS_IS_EXDEV(s) ((s) == APR_EXDEV) +/** Directory Not Empty */ +#define APR_STATUS_IS_ENOTEMPTY(s) ((s) == APR_ENOTEMPTY || \ + (s) == APR_EEXIST) +/** @} */ + +#endif /* !defined(NETWARE) && !defined(OS2) && !defined(WIN32) */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_ERRNO_H */ diff --git a/srclib/apr/include/apr_file_info.h b/srclib/apr/include/apr_file_info.h new file mode 100644 index 0000000000..4680caba22 --- /dev/null +++ b/srclib/apr/include/apr_file_info.h @@ -0,0 +1,419 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_FILE_INFO_H +#define APR_FILE_INFO_H + +/** + * @file apr_file_info.h + * @brief APR File Information + */ + +#include "apr.h" +#include "apr_user.h" +#include "apr_pools.h" +#include "apr_tables.h" +#include "apr_time.h" +#include "apr_errno.h" + +#if APR_HAVE_SYS_UIO_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_file_info File Information + * @ingroup APR + * @{ + */ + +/* Many applications use the type member to determine the + * existance of a file or initialization of the file info, + * so the APR_NOFILE value must be distinct from APR_UNKFILE. + */ + +/** apr_filetype_e values for the filetype member of the + * apr_file_info_t structure + * @warning: Not all of the filetypes below can be determined. + * For example, a given platform might not correctly report + * a socket descriptor as APR_SOCK if that type isn't + * well-identified on that platform. In such cases where + * a filetype exists but cannot be described by the recognized + * flags below, the filetype will be APR_UNKFILE. If the + * filetype member is not determined, the type will be APR_NOFILE. + */ + +typedef enum { + APR_NOFILE = 0, /**< no file type determined */ + APR_REG, /**< a regular file */ + APR_DIR, /**< a directory */ + APR_CHR, /**< a character device */ + APR_BLK, /**< a block device */ + APR_PIPE, /**< a FIFO / pipe */ + APR_LNK, /**< a symbolic link */ + APR_SOCK, /**< a [unix domain] socket */ + APR_UNKFILE = 127 /**< a file of some other unknown type */ +} apr_filetype_e; + +/** + * @defgroup apr_file_permissions File Permissions flags + * @{ + */ + +#define APR_FPROT_USETID 0x8000 /**< Set user id */ +#define APR_FPROT_UREAD 0x0400 /**< Read by user */ +#define APR_FPROT_UWRITE 0x0200 /**< Write by user */ +#define APR_FPROT_UEXECUTE 0x0100 /**< Execute by user */ + +#define APR_FPROT_GSETID 0x4000 /**< Set group id */ +#define APR_FPROT_GREAD 0x0040 /**< Read by group */ +#define APR_FPROT_GWRITE 0x0020 /**< Write by group */ +#define APR_FPROT_GEXECUTE 0x0010 /**< Execute by group */ + +#define APR_FPROT_WSTICKY 0x2000 /**< Sticky bit */ +#define APR_FPROT_WREAD 0x0004 /**< Read by others */ +#define APR_FPROT_WWRITE 0x0002 /**< Write by others */ +#define APR_FPROT_WEXECUTE 0x0001 /**< Execute by others */ + +#define APR_FPROT_OS_DEFAULT 0x0FFF /**< use OS's default permissions */ + +/* additional permission flags for apr_file_copy and apr_file_append */ +#define APR_FPROT_FILE_SOURCE_PERMS 0x1000 /**< Copy source file's permissions */ + +/* backcompat */ +#define APR_USETID APR_FPROT_USETID /**< @deprecated @see APR_FPROT_USETID */ +#define APR_UREAD APR_FPROT_UREAD /**< @deprecated @see APR_FPROT_UREAD */ +#define APR_UWRITE APR_FPROT_UWRITE /**< @deprecated @see APR_FPROT_UWRITE */ +#define APR_UEXECUTE APR_FPROT_UEXECUTE /**< @deprecated @see APR_FPROT_UEXECUTE */ +#define APR_GSETID APR_FPROT_GSETID /**< @deprecated @see APR_FPROT_GSETID */ +#define APR_GREAD APR_FPROT_GREAD /**< @deprecated @see APR_FPROT_GREAD */ +#define APR_GWRITE APR_FPROT_GWRITE /**< @deprecated @see APR_FPROT_GWRITE */ +#define APR_GEXECUTE APR_FPROT_GEXECUTE /**< @deprecated @see APR_FPROT_GEXECUTE */ +#define APR_WSTICKY APR_FPROT_WSTICKY /**< @deprecated @see APR_FPROT_WSTICKY */ +#define APR_WREAD APR_FPROT_WREAD /**< @deprecated @see APR_FPROT_WREAD */ +#define APR_WWRITE APR_FPROT_WWRITE /**< @deprecated @see APR_FPROT_WWRITE */ +#define APR_WEXECUTE APR_FPROT_WEXECUTE /**< @deprecated @see APR_FPROT_WEXECUTE */ +#define APR_OS_DEFAULT APR_FPROT_OS_DEFAULT /**< @deprecated @see APR_FPROT_OS_DEFAULT */ +#define APR_FILE_SOURCE_PERMS APR_FPROT_FILE_SOURCE_PERMS /**< @deprecated @see APR_FPROT_FILE_SOURCE_PERMS */ + +/** @} */ + + +/** + * Structure for referencing directories. + */ +typedef struct apr_dir_t apr_dir_t; +/** + * Structure for determining file permissions. + */ +typedef apr_int32_t apr_fileperms_t; +#if (defined WIN32) || (defined NETWARE) +/** + * Structure for determining the inode of the file. + */ +typedef apr_uint64_t apr_ino_t; +/** + * Structure for determining the device the file is on. + */ +typedef apr_uint32_t apr_dev_t; +#else +/** The inode of the file. */ +typedef ino_t apr_ino_t; +/** + * Structure for determining the device the file is on. + */ +typedef dev_t apr_dev_t; +#endif + +/** + * @defgroup apr_file_stat Stat Functions + * @{ + */ +/** file info structure */ +typedef struct apr_finfo_t apr_finfo_t; + +#define APR_FINFO_LINK 0x00000001 /**< Stat the link not the file itself if it is a link */ +#define APR_FINFO_MTIME 0x00000010 /**< Modification Time */ +#define APR_FINFO_CTIME 0x00000020 /**< Creation or inode-changed time */ +#define APR_FINFO_ATIME 0x00000040 /**< Access Time */ +#define APR_FINFO_SIZE 0x00000100 /**< Size of the file */ +#define APR_FINFO_CSIZE 0x00000200 /**< Storage size consumed by the file */ +#define APR_FINFO_DEV 0x00001000 /**< Device */ +#define APR_FINFO_INODE 0x00002000 /**< Inode */ +#define APR_FINFO_NLINK 0x00004000 /**< Number of links */ +#define APR_FINFO_TYPE 0x00008000 /**< Type */ +#define APR_FINFO_USER 0x00010000 /**< User */ +#define APR_FINFO_GROUP 0x00020000 /**< Group */ +#define APR_FINFO_UPROT 0x00100000 /**< User protection bits */ +#define APR_FINFO_GPROT 0x00200000 /**< Group protection bits */ +#define APR_FINFO_WPROT 0x00400000 /**< World protection bits */ +#define APR_FINFO_ICASE 0x01000000 /**< if dev is case insensitive */ +#define APR_FINFO_NAME 0x02000000 /**< ->name in proper case */ + +#define APR_FINFO_MIN 0x00008170 /**< type, mtime, ctime, atime, size */ +#define APR_FINFO_IDENT 0x00003000 /**< dev and inode */ +#define APR_FINFO_OWNER 0x00030000 /**< user and group */ +#define APR_FINFO_PROT 0x00700000 /**< all protections */ +#define APR_FINFO_NORM 0x0073b170 /**< an atomic unix apr_stat() */ +#define APR_FINFO_DIRENT 0x02000000 /**< an atomic unix apr_dir_read() */ + +/** + * The file information structure. This is analogous to the POSIX + * stat structure. + */ +struct apr_finfo_t { + /** Allocates memory and closes lingering handles in the specified pool */ + apr_pool_t *pool; + /** The bitmask describing valid fields of this apr_finfo_t structure + * including all available 'wanted' fields and potentially more */ + apr_int32_t valid; + /** The access permissions of the file. Mimics Unix access rights. */ + apr_fileperms_t protection; + /** The type of file. One of APR_REG, APR_DIR, APR_CHR, APR_BLK, APR_PIPE, + * APR_LNK or APR_SOCK. If the type is undetermined, the value is APR_NOFILE. + * If the type cannot be determined, the value is APR_UNKFILE. + */ + apr_filetype_e filetype; + /** The user id that owns the file */ + apr_uid_t user; + /** The group id that owns the file */ + apr_gid_t group; + /** The inode of the file. */ + apr_ino_t inode; + /** The id of the device the file is on. */ + apr_dev_t device; + /** The number of hard links to the file. */ + apr_int32_t nlink; + /** The size of the file */ + apr_off_t size; + /** The storage size consumed by the file */ + apr_off_t csize; + /** The time the file was last accessed */ + apr_time_t atime; + /** The time the file was last modified */ + apr_time_t mtime; + /** The time the file was created, or the inode was last changed */ + apr_time_t ctime; + /** The pathname of the file (possibly unrooted) */ + const char *fname; + /** The file's name (no path) in filesystem case */ + const char *name; + /** The file's handle, if accessed (can be submitted to apr_duphandle) */ + struct apr_file_t *filehand; +}; + +/** + * get the specified file's stats. The file is specified by filename, + * instead of using a pre-opened file. + * @param finfo Where to store the information about the file, which is + * never touched if the call fails. + * @param fname The name of the file to stat. + * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_ values + * @param pool the pool to use to allocate the new file. + */ +APR_DECLARE(apr_status_t) apr_stat(apr_finfo_t *finfo, const char *fname, + apr_int32_t wanted, apr_pool_t *pool); + +/** @} */ +/** + * @defgroup apr_dir Directory Manipulation Functions + * @{ + */ + +/** + * Open the specified directory. + * @param new_dir The opened directory descriptor. + * @param dirname The full path to the directory (use / on all systems) + * @param pool The pool to use. + */ +APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new_dir, + const char *dirname, + apr_pool_t *pool); + +/** + * close the specified directory. + * @param thedir the directory descriptor to close. + */ +APR_DECLARE(apr_status_t) apr_dir_close(apr_dir_t *thedir); + +/** + * Read the next entry from the specified directory. + * @param finfo the file info structure and filled in by apr_dir_read + * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_ values + * @param thedir the directory descriptor returned from apr_dir_open + * @remark No ordering is guaranteed for the entries read. + */ +APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, + apr_dir_t *thedir); + +/** + * Rewind the directory to the first entry. + * @param thedir the directory descriptor to rewind. + */ +APR_DECLARE(apr_status_t) apr_dir_rewind(apr_dir_t *thedir); +/** @} */ + +/** + * @defgroup apr_filepath Filepath Manipulation Functions + * @{ + */ + +/** Cause apr_filepath_merge to fail if addpath is above rootpath */ +#define APR_FILEPATH_NOTABOVEROOT 0x01 + +/** internal: Only meaningful with APR_FILEPATH_NOTABOVEROOT */ +#define APR_FILEPATH_SECUREROOTTEST 0x02 + +/** Cause apr_filepath_merge to fail if addpath is above rootpath, + * even given a rootpath /foo/bar and an addpath ../bar/bash + */ +#define APR_FILEPATH_SECUREROOT 0x03 + +/** Fail apr_filepath_merge if the merged path is relative */ +#define APR_FILEPATH_NOTRELATIVE 0x04 + +/** Fail apr_filepath_merge if the merged path is absolute */ +#define APR_FILEPATH_NOTABSOLUTE 0x08 + +/** Return the file system's native path format (e.g. path delimiters + * of ':' on MacOS9, '\' on Win32, etc.) */ +#define APR_FILEPATH_NATIVE 0x10 + +/** Resolve the true case of existing directories and file elements + * of addpath, (resolving any aliases on Win32) and append a proper + * trailing slash if a directory + */ +#define APR_FILEPATH_TRUENAME 0x20 + +/** + * Extract the rootpath from the given filepath + * @param rootpath the root file path returned with APR_SUCCESS or APR_EINCOMPLETE + * @param filepath the pathname to parse for its root component + * @param flags the desired rules to apply, from + *
    + *      APR_FILEPATH_NATIVE    Use native path seperators (e.g. '\' on Win32)
    + *      APR_FILEPATH_TRUENAME  Tests that the root exists, and makes it proper
    + * 
    + * @param p the pool to allocate the new path string from + * @remark on return, filepath points to the first non-root character in the + * given filepath. In the simplest example, given a filepath of "/foo", + * returns the rootpath of "/" and filepath points at "foo". This is far + * more complex on other platforms, which will canonicalize the root form + * to a consistant format, given the APR_FILEPATH_TRUENAME flag, and also + * test for the validity of that root (e.g., that a drive d:/ or network + * share //machine/foovol/). + * The function returns APR_ERELATIVE if filepath isn't rooted (an + * error), APR_EINCOMPLETE if the root path is ambigious (but potentially + * legitimate, e.g. "/" on Windows is incomplete because it doesn't specify + * the drive letter), or APR_EBADPATH if the root is simply invalid. + * APR_SUCCESS is returned if filepath is an absolute path. + */ +APR_DECLARE(apr_status_t) apr_filepath_root(const char **rootpath, + const char **filepath, + apr_int32_t flags, + apr_pool_t *p); + +/** + * Merge additional file path onto the previously processed rootpath + * @param newpath the merged paths returned + * @param rootpath the root file path (NULL uses the current working path) + * @param addpath the path to add to the root path + * @param flags the desired APR_FILEPATH_ rules to apply when merging + * @param p the pool to allocate the new path string from + * @remark if the flag APR_FILEPATH_TRUENAME is given, and the addpath + * contains wildcard characters ('*', '?') on platforms that don't support + * such characters within filenames, the paths will be merged, but the + * result code will be APR_EPATHWILD, and all further segments will not + * reflect the true filenames including the wildcard and following segments. + */ +APR_DECLARE(apr_status_t) apr_filepath_merge(char **newpath, + const char *rootpath, + const char *addpath, + apr_int32_t flags, + apr_pool_t *p); + +/** + * Split a search path into separate components + * @param pathelts the returned components of the search path + * @param liststr the search path (e.g., getenv("PATH")) + * @param p the pool to allocate the array and path components from + * @remark empty path componenta do not become part of @a pathelts. + * @remark the path separator in @a liststr is system specific; + * e.g., ':' on Unix, ';' on Windows, etc. + */ +APR_DECLARE(apr_status_t) apr_filepath_list_split(apr_array_header_t **pathelts, + const char *liststr, + apr_pool_t *p); + +/** + * Merge a list of search path components into a single search path + * @param liststr the returned search path; may be NULL if @a pathelts is empty + * @param pathelts the components of the search path + * @param p the pool to allocate the search path from + * @remark emtpy strings in the source array are ignored. + * @remark the path separator in @a liststr is system specific; + * e.g., ':' on Unix, ';' on Windows, etc. + */ +APR_DECLARE(apr_status_t) apr_filepath_list_merge(char **liststr, + apr_array_header_t *pathelts, + apr_pool_t *p); + +/** + * Return the default file path (for relative file names) + * @param path the default path string returned + * @param flags optional flag APR_FILEPATH_NATIVE to retrieve the + * default file path in os-native format. + * @param p the pool to allocate the default path string from + */ +APR_DECLARE(apr_status_t) apr_filepath_get(char **path, apr_int32_t flags, + apr_pool_t *p); + +/** + * Set the default file path (for relative file names) + * @param path the default path returned + * @param p the pool to allocate any working storage + */ +APR_DECLARE(apr_status_t) apr_filepath_set(const char *path, apr_pool_t *p); + +/** The FilePath character encoding is unknown */ +#define APR_FILEPATH_ENCODING_UNKNOWN 0 + +/** The FilePath character encoding is locale-dependent */ +#define APR_FILEPATH_ENCODING_LOCALE 1 + +/** The FilePath character encoding is UTF-8 */ +#define APR_FILEPATH_ENCODING_UTF8 2 + +/** + * Determine the encoding used internally by the FilePath functions + * @param style points to a variable which receives the encoding style flag + * @param p the pool to allocate any working storage + * @remark Use @c apr_os_locale_encoding and/or @c apr_os_default_encoding + * to get the name of the path encoding if it's not UTF-8. + */ +APR_DECLARE(apr_status_t) apr_filepath_encoding(int *style, apr_pool_t *p); +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_FILE_INFO_H */ diff --git a/srclib/apr/include/apr_file_io.h b/srclib/apr/include/apr_file_io.h new file mode 100644 index 0000000000..847ecb044f --- /dev/null +++ b/srclib/apr/include/apr_file_io.h @@ -0,0 +1,806 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_FILE_IO_H +#define APR_FILE_IO_H + +/** + * @file apr_file_io.h + * @brief APR File I/O Handling + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_time.h" +#include "apr_errno.h" +#include "apr_file_info.h" +#include "apr_inherit.h" + +#define APR_WANT_STDIO /**< for SEEK_* */ +#define APR_WANT_IOVEC /**< for apr_file_writev */ +#include "apr_want.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_file_io File I/O Handling Functions + * @ingroup APR + * @{ + */ + +/** + * @defgroup apr_file_open_flags File Open Flags/Routines + * @{ + */ + +/* Note to implementors: Values in the range 0x00100000--0x80000000 + are reserved for platform-specific values. */ + +#define APR_FOPEN_READ 0x00001 /**< Open the file for reading */ +#define APR_FOPEN_WRITE 0x00002 /**< Open the file for writing */ +#define APR_FOPEN_CREATE 0x00004 /**< Create the file if not there */ +#define APR_FOPEN_APPEND 0x00008 /**< Append to the end of the file */ +#define APR_FOPEN_TRUNCATE 0x00010 /**< Open the file and truncate + to 0 length */ +#define APR_FOPEN_BINARY 0x00020 /**< Open the file in binary mode */ +#define APR_FOPEN_EXCL 0x00040 /**< Open should fail if APR_CREATE + and file exists. */ +#define APR_FOPEN_BUFFERED 0x00080 /**< Open the file for buffered I/O */ +#define APR_FOPEN_DELONCLOSE 0x00100 /**< Delete the file after close */ +#define APR_FOPEN_XTHREAD 0x00200 /**< Platform dependent tag to open + the file for use across multiple + threads */ +#define APR_FOPEN_SHARELOCK 0x00400 /**< Platform dependent support for + higher level locked read/write + access to support writes across + process/machines */ +#define APR_FOPEN_NOCLEANUP 0x00800 /**< Do not register a cleanup + when the file is opened */ +#define APR_FOPEN_SENDFILE_ENABLED 0x01000 /**< Advisory flag that this + file should support + apr_socket_sendfile operation */ +#define APR_FOPEN_LARGEFILE 0x04000 /**< Platform dependent flag to enable + large file support; WARNING see + below. */ +/* backcompat */ +#define APR_READ APR_FOPEN_READ /**< @deprecated @see APR_FOPEN_READ */ +#define APR_WRITE APR_FOPEN_WRITE /**< @deprecated @see APR_FOPEN_WRITE */ +#define APR_CREATE APR_FOPEN_CREATE /**< @deprecated @see APR_FOPEN_CREATE */ +#define APR_APPEND APR_FOPEN_APPEND /**< @deprecated @see APR_FOPEN_APPEND */ +#define APR_TRUNCATE APR_FOPEN_TRUNCATE /**< @deprecated @see APR_FOPEN_TRUNCATE */ +#define APR_BINARY APR_FOPEN_BINARY /**< @deprecated @see APR_FOPEN_BINARY */ +#define APR_EXCL APR_FOPEN_EXCL /**< @deprecated @see APR_FOPEN_EXCL */ +#define APR_BUFFERED APR_FOPEN_BUFFERED /**< @deprecated @see APR_FOPEN_BUFFERED */ +#define APR_DELONCLOSE APR_FOPEN_DELONCLOSE /**< @deprecated @see APR_FOPEN_DELONCLOSE */ +#define APR_XTHREAD APR_FOPEN_XTHREAD /**< @deprecated @see APR_FOPEN_XTHREAD */ +#define APR_SHARELOCK APR_FOPEN_SHARELOCK /**< @deprecated @see APR_FOPEN_SHARELOCK */ +#define APR_FILE_NOCLEANUP APR_FOPEN_NOCLEANUP /**< @deprecated @see APR_FOPEN_NOCLEANUP */ +#define APR_SENDFILE_ENABLED APR_FOPEN_SENDFILE_ENABLED /**< @deprecated @see APR_FOPEN_SENDFILE_ENABLED */ +#define APR_LARGEFILE APR_FOPEN_LARGEFILE /**< @deprecated @see APR_FOPEN_LARGEFILE */ + +/** @warning The APR_LARGEFILE flag only has effect on some platforms + * where sizeof(apr_off_t) == 4. Where implemented, it allows opening + * and writing to a file which exceeds the size which can be + * represented by apr_off_t (2 gigabytes). When a file's size does + * exceed 2Gb, apr_file_info_get() will fail with an error on the + * descriptor, likewise apr_stat()/apr_lstat() will fail on the + * filename. apr_dir_read() will fail with APR_INCOMPLETE on a + * directory entry for a large file depending on the particular + * APR_FINFO_* flags. Generally, it is not recommended to use this + * flag. */ + +/** @} */ + +/** + * @defgroup apr_file_seek_flags File Seek Flags + * @{ + */ + +/* flags for apr_file_seek */ +/** Set the file position */ +#define APR_SET SEEK_SET +/** Current */ +#define APR_CUR SEEK_CUR +/** Go to end of file */ +#define APR_END SEEK_END +/** @} */ + +/** + * @defgroup apr_file_attrs_set_flags File Attribute Flags + * @{ + */ + +/* flags for apr_file_attrs_set */ +#define APR_FILE_ATTR_READONLY 0x01 /**< File is read-only */ +#define APR_FILE_ATTR_EXECUTABLE 0x02 /**< File is executable */ +#define APR_FILE_ATTR_HIDDEN 0x04 /**< File is hidden */ +/** @} */ + +/** + * @defgroup apr_file_writev{_full} max iovec size + * @{ + */ +#if defined(DOXYGEN) +#define APR_MAX_IOVEC_SIZE 1024 /**< System dependent maximum + size of an iovec array */ +#elif defined(IOV_MAX) +#define APR_MAX_IOVEC_SIZE IOV_MAX +#elif defined(MAX_IOVEC) +#define APR_MAX_IOVEC_SIZE MAX_IOVEC +#else +#define APR_MAX_IOVEC_SIZE 1024 +#endif +/** @} */ + +/** File attributes */ +typedef apr_uint32_t apr_fileattrs_t; + +/** Type to pass as whence argument to apr_file_seek. */ +typedef int apr_seek_where_t; + +/** + * Structure for referencing files. + */ +typedef struct apr_file_t apr_file_t; + +/* File lock types/flags */ +/** + * @defgroup apr_file_lock_types File Lock Types + * @{ + */ + +#define APR_FLOCK_SHARED 1 /**< Shared lock. More than one process + or thread can hold a shared lock + at any given time. Essentially, + this is a "read lock", preventing + writers from establishing an + exclusive lock. */ +#define APR_FLOCK_EXCLUSIVE 2 /**< Exclusive lock. Only one process + may hold an exclusive lock at any + given time. This is analogous to + a "write lock". */ + +#define APR_FLOCK_TYPEMASK 0x000F /**< mask to extract lock type */ +#define APR_FLOCK_NONBLOCK 0x0010 /**< do not block while acquiring the + file lock */ +/** @} */ + +/** + * Open the specified file. + * @param newf The opened file descriptor. + * @param fname The full path to the file (using / on all systems) + * @param flag Or'ed value of: + *
    + *         APR_READ              open for reading
    + *         APR_WRITE             open for writing
    + *         APR_CREATE            create the file if not there
    + *         APR_APPEND            file ptr is set to end prior to all writes
    + *         APR_TRUNCATE          set length to zero if file exists
    + *         APR_BINARY            not a text file (This flag is ignored on 
    + *                               UNIX because it has no meaning)
    + *         APR_BUFFERED          buffer the data.  Default is non-buffered
    + *         APR_EXCL              return error if APR_CREATE and file exists
    + *         APR_DELONCLOSE        delete the file after closing.
    + *         APR_XTHREAD           Platform dependent tag to open the file
    + *                               for use across multiple threads
    + *         APR_SHARELOCK         Platform dependent support for higher
    + *                               level locked read/write access to support
    + *                               writes across process/machines
    + *         APR_FILE_NOCLEANUP    Do not register a cleanup with the pool 
    + *                               passed in on the pool argument (see below).
    + *                               The apr_os_file_t handle in apr_file_t will not
    + *                               be closed when the pool is destroyed.
    + *         APR_SENDFILE_ENABLED  Open with appropriate platform semantics
    + *                               for sendfile operations.  Advisory only,
    + *                               apr_socket_sendfile does not check this flag.
    + * 
    + * @param perm Access permissions for file. + * @param pool The pool to use. + * @remark If perm is APR_OS_DEFAULT and the file is being created, + * appropriate default permissions will be used. + */ +APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **newf, const char *fname, + apr_int32_t flag, apr_fileperms_t perm, + apr_pool_t *pool); + +/** + * Close the specified file. + * @param file The file descriptor to close. + */ +APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file); + +/** + * Delete the specified file. + * @param path The full path to the file (using / on all systems) + * @param pool The pool to use. + * @remark If the file is open, it won't be removed until all + * instances are closed. + */ +APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool); + +/** + * Rename the specified file. + * @param from_path The full path to the original file (using / on all systems) + * @param to_path The full path to the new file (using / on all systems) + * @param pool The pool to use. + * @warning If a file exists at the new location, then it will be + * overwritten. Moving files or directories across devices may not be + * possible. + */ +APR_DECLARE(apr_status_t) apr_file_rename(const char *from_path, + const char *to_path, + apr_pool_t *pool); + +/** + * Copy the specified file to another file. + * @param from_path The full path to the original file (using / on all systems) + * @param to_path The full path to the new file (using / on all systems) + * @param perms Access permissions for the new file if it is created. + * In place of the usual or'd combination of file permissions, the + * value APR_FILE_SOURCE_PERMS may be given, in which case the source + * file's permissions are copied. + * @param pool The pool to use. + * @remark The new file does not need to exist, it will be created if required. + * @warning If the new file already exists, its contents will be overwritten. + */ +APR_DECLARE(apr_status_t) apr_file_copy(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); + +/** + * Append the specified file to another file. + * @param from_path The full path to the source file (use / on all systems) + * @param to_path The full path to the destination file (use / on all systems) + * @param perms Access permissions for the destination file if it is created. + * In place of the usual or'd combination of file permissions, the + * value APR_FILE_SOURCE_PERMS may be given, in which case the source + * file's permissions are copied. + * @param pool The pool to use. + * @remark The new file does not need to exist, it will be created if required. + */ +APR_DECLARE(apr_status_t) apr_file_append(const char *from_path, + const char *to_path, + apr_fileperms_t perms, + apr_pool_t *pool); + +/** + * Are we at the end of the file + * @param fptr The apr file we are testing. + * @remark Returns APR_EOF if we are at the end of file, APR_SUCCESS otherwise. + */ +APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr); + +/** + * Open standard error as an apr file pointer. + * @param thefile The apr file to use as stderr. + * @param pool The pool to allocate the file out of. + * + * @remark The only reason that the apr_file_open_std* functions exist + * is that you may not always have a stderr/out/in on Windows. This + * is generally a problem with newer versions of Windows and services. + * + * @remark The other problem is that the C library functions generally work + * differently on Windows and Unix. So, by using apr_file_open_std* + * functions, you can get a handle to an APR struct that works with + * the APR functions which are supposed to work identically on all + * platforms. + */ +APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, + apr_pool_t *pool); + +/** + * open standard output as an apr file pointer. + * @param thefile The apr file to use as stdout. + * @param pool The pool to allocate the file out of. + * + * @remark See remarks for apr_file_open_stdout. + */ +APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, + apr_pool_t *pool); + +/** + * open standard input as an apr file pointer. + * @param thefile The apr file to use as stdin. + * @param pool The pool to allocate the file out of. + * + * @remark See remarks for apr_file_open_stdout. + */ +APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, + apr_pool_t *pool); + +/** + * Read data from the specified file. + * @param thefile The file descriptor to read from. + * @param buf The buffer to store the data to. + * @param nbytes On entry, the number of bytes to read; on exit, the number + * of bytes read. + * + * @remark apr_file_read will read up to the specified number of + * bytes, but never more. If there isn't enough data to fill that + * number of bytes, all of the available data is read. The third + * argument is modified to reflect the number of bytes read. If a + * char was put back into the stream via ungetc, it will be the first + * character returned. + * + * @remark It is not possible for both bytes to be read and an APR_EOF + * or other error to be returned. APR_EINTR is never returned. + */ +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, + apr_size_t *nbytes); + +/** + * Write data to the specified file. + * @param thefile The file descriptor to write to. + * @param buf The buffer which contains the data. + * @param nbytes On entry, the number of bytes to write; on exit, the number + * of bytes written. + * + * @remark apr_file_write will write up to the specified number of + * bytes, but never more. If the OS cannot write that many bytes, it + * will write as many as it can. The third argument is modified to + * reflect the * number of bytes written. + * + * @remark It is possible for both bytes to be written and an error to + * be returned. APR_EINTR is never returned. + */ +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, + apr_size_t *nbytes); + +/** + * Write data from iovec array to the specified file. + * @param thefile The file descriptor to write to. + * @param vec The array from which to get the data to write to the file. + * @param nvec The number of elements in the struct iovec array. This must + * be smaller than APR_MAX_IOVEC_SIZE. If it isn't, the function + * will fail with APR_EINVAL. + * @param nbytes The number of bytes written. + * + * @remark It is possible for both bytes to be written and an error to + * be returned. APR_EINTR is never returned. + * + * @remark apr_file_writev is available even if the underlying + * operating system doesn't provide writev(). + */ +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); + +/** + * Read data from the specified file, ensuring that the buffer is filled + * before returning. + * @param thefile The file descriptor to read from. + * @param buf The buffer to store the data to. + * @param nbytes The number of bytes to read. + * @param bytes_read If non-NULL, this will contain the number of bytes read. + * + * @remark apr_file_read will read up to the specified number of + * bytes, but never more. If there isn't enough data to fill that + * number of bytes, then the process/thread will block until it is + * available or EOF is reached. If a char was put back into the + * stream via ungetc, it will be the first character returned. + * + * @remark It is possible for both bytes to be read and an error to be + * returned. And if *bytes_read is less than nbytes, an accompanying + * error is _always_ returned. + * + * @remark APR_EINTR is never returned. + */ +APR_DECLARE(apr_status_t) apr_file_read_full(apr_file_t *thefile, void *buf, + apr_size_t nbytes, + apr_size_t *bytes_read); + +/** + * Write data to the specified file, ensuring that all of the data is + * written before returning. + * @param thefile The file descriptor to write to. + * @param buf The buffer which contains the data. + * @param nbytes The number of bytes to write. + * @param bytes_written If non-NULL, set to the number of bytes written. + * + * @remark apr_file_write will write up to the specified number of + * bytes, but never more. If the OS cannot write that many bytes, the + * process/thread will block until they can be written. Exceptional + * error such as "out of space" or "pipe closed" will terminate with + * an error. + * + * @remark It is possible for both bytes to be written and an error to + * be returned. And if *bytes_written is less than nbytes, an + * accompanying error is _always_ returned. + * + * @remark APR_EINTR is never returned. + */ +APR_DECLARE(apr_status_t) apr_file_write_full(apr_file_t *thefile, + const void *buf, + apr_size_t nbytes, + apr_size_t *bytes_written); + + +/** + * Write data from iovec array to the specified file, ensuring that all of the + * data is written before returning. + * @param thefile The file descriptor to write to. + * @param vec The array from which to get the data to write to the file. + * @param nvec The number of elements in the struct iovec array. This must + * be smaller than APR_MAX_IOVEC_SIZE. If it isn't, the function + * will fail with APR_EINVAL. + * @param nbytes The number of bytes written. + * + * @remark apr_file_writev_full is available even if the underlying + * operating system doesn't provide writev(). + */ +APR_DECLARE(apr_status_t) apr_file_writev_full(apr_file_t *thefile, + const struct iovec *vec, + apr_size_t nvec, + apr_size_t *nbytes); +/** + * Write a character into the specified file. + * @param ch The character to write. + * @param thefile The file descriptor to write to + */ +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile); + +/** + * Read a character from the specified file. + * @param ch The character to read into + * @param thefile The file descriptor to read from + */ +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile); + +/** + * Put a character back onto a specified stream. + * @param ch The character to write. + * @param thefile The file descriptor to write to + */ +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile); + +/** + * Read a string from the specified file. + * @param str The buffer to store the string in. + * @param len The length of the string + * @param thefile The file descriptor to read from + * @remark The buffer will be NUL-terminated if any characters are stored. + */ +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, + apr_file_t *thefile); + +/** + * Write the string into the specified file. + * @param str The string to write. + * @param thefile The file descriptor to write to + */ +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile); + +/** + * Flush the file's buffer. + * @param thefile The file descriptor to flush + */ +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile); + +/** + * Duplicate the specified file descriptor. + * @param new_file The structure to duplicate into. + * @param old_file The file to duplicate. + * @param p The pool to use for the new file. + * @remark *new_file must point to a valid apr_file_t, or point to NULL. + */ +APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); + +/** + * Duplicate the specified file descriptor and close the original + * @param new_file The old file that is to be closed and reused + * @param old_file The file to duplicate + * @param p The pool to use for the new file + * + * @remark new_file MUST point at a valid apr_file_t. It cannot be NULL. + */ +APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, + apr_file_t *old_file, + apr_pool_t *p); + +/** + * Move the specified file descriptor to a new pool + * @param new_file Pointer in which to return the new apr_file_t + * @param old_file The file to move + * @param p The pool to which the descriptor is to be moved + * @remark Unlike apr_file_dup2(), this function doesn't do an + * OS dup() operation on the underlying descriptor; it just + * moves the descriptor's apr_file_t wrapper to a new pool. + * @remark The new pool need not be an ancestor of old_file's pool. + * @remark After calling this function, old_file may not be used + */ +APR_DECLARE(apr_status_t) apr_file_setaside(apr_file_t **new_file, + apr_file_t *old_file, + apr_pool_t *p); + +/** + * Move the read/write file offset to a specified byte within a file. + * @param thefile The file descriptor + * @param where How to move the pointer, one of: + *
    + *            APR_SET  --  set the offset to offset
    + *            APR_CUR  --  add the offset to the current position 
    + *            APR_END  --  add the offset to the current file size 
    + * 
    + * @param offset The offset to move the pointer to. + * @remark The third argument is modified to be the offset the pointer + was actually moved to. + */ +APR_DECLARE(apr_status_t) apr_file_seek(apr_file_t *thefile, + apr_seek_where_t where, + apr_off_t *offset); + +/** + * Create an anonymous pipe. + * @param in The file descriptor to use as input to the pipe. + * @param out The file descriptor to use as output from the pipe. + * @param pool The pool to operate on. + */ +APR_DECLARE(apr_status_t) apr_file_pipe_create(apr_file_t **in, + apr_file_t **out, + apr_pool_t *pool); + +/** + * Create a named pipe. + * @param filename The filename of the named pipe + * @param perm The permissions for the newly created pipe. + * @param pool The pool to operate on. + */ +APR_DECLARE(apr_status_t) apr_file_namedpipe_create(const char *filename, + apr_fileperms_t perm, + apr_pool_t *pool); + +/** + * Get the timeout value for a pipe or manipulate the blocking state. + * @param thepipe The pipe we are getting a timeout for. + * @param timeout The current timeout value in microseconds. + */ +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_get(apr_file_t *thepipe, + apr_interval_time_t *timeout); + +/** + * Set the timeout value for a pipe or manipulate the blocking state. + * @param thepipe The pipe we are setting a timeout on. + * @param timeout The timeout value in microseconds. Values < 0 mean wait + * forever, 0 means do not wait at all. + */ +APR_DECLARE(apr_status_t) apr_file_pipe_timeout_set(apr_file_t *thepipe, + apr_interval_time_t timeout); + +/** file (un)locking functions. */ + +/** + * Establish a lock on the specified, open file. The lock may be advisory + * or mandatory, at the discretion of the platform. The lock applies to + * the file as a whole, rather than a specific range. Locks are established + * on a per-thread/process basis; a second lock by the same thread will not + * block. + * @param thefile The file to lock. + * @param type The type of lock to establish on the file. + */ +APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type); + +/** + * Remove any outstanding locks on the file. + * @param thefile The file to unlock. + */ +APR_DECLARE(apr_status_t) apr_file_unlock(apr_file_t *thefile); + +/**accessor and general file_io functions. */ + +/** + * return the file name of the current file. + * @param new_path The path of the file. + * @param thefile The currently open file. + */ +APR_DECLARE(apr_status_t) apr_file_name_get(const char **new_path, + apr_file_t *thefile); + +/** + * Return the data associated with the current file. + * @param data The user data associated with the file. + * @param key The key to use for retreiving data associated with this file. + * @param file The currently open file. + */ +APR_DECLARE(apr_status_t) apr_file_data_get(void **data, const char *key, + apr_file_t *file); + +/** + * Set the data associated with the current file. + * @param file The currently open file. + * @param data The user data to associate with the file. + * @param key The key to use for assocaiteing data with the file. + * @param cleanup The cleanup routine to use when the file is destroyed. + */ +APR_DECLARE(apr_status_t) apr_file_data_set(apr_file_t *file, void *data, + const char *key, + apr_status_t (*cleanup)(void *)); + +/** + * Write a string to a file using a printf format. + * @param fptr The file to write to. + * @param format The format string + * @param ... The values to substitute in the format string + * @return The number of bytes written + */ +APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, + const char *format, ...) + __attribute__((format(printf,2,3))); + +/** + * set the specified file's permission bits. + * @param fname The file (name) to apply the permissions to. + * @param perms The permission bits to apply to the file. + * + * @warning Some platforms may not be able to apply all of the + * available permission bits; APR_INCOMPLETE will be returned if some + * permissions are specified which could not be set. + * + * @warning Platforms which do not implement this feature will return + * APR_ENOTIMPL. + */ +APR_DECLARE(apr_status_t) apr_file_perms_set(const char *fname, + apr_fileperms_t perms); + +/** + * Set attributes of the specified file. + * @param fname The full path to the file (using / on all systems) + * @param attributes Or'd combination of + *
    + *            APR_FILE_ATTR_READONLY   - make the file readonly
    + *            APR_FILE_ATTR_EXECUTABLE - make the file executable
    + *            APR_FILE_ATTR_HIDDEN     - make the file hidden
    + * 
    + * @param attr_mask Mask of valid bits in attributes. + * @param pool the pool to use. + * @remark This function should be used in preference to explict manipulation + * of the file permissions, because the operations to provide these + * attributes are platform specific and may involve more than simply + * setting permission bits. + * @warning Platforms which do not implement this feature will return + * APR_ENOTIMPL. + */ +APR_DECLARE(apr_status_t) apr_file_attrs_set(const char *fname, + apr_fileattrs_t attributes, + apr_fileattrs_t attr_mask, + apr_pool_t *pool); + +/** + * Set the mtime of the specified file. + * @param fname The full path to the file (using / on all systems) + * @param mtime The mtime to apply to the file. + * @param pool The pool to use. + * @warning Platforms which do not implement this feature will return + * APR_ENOTIMPL. + */ +APR_DECLARE(apr_status_t) apr_file_mtime_set(const char *fname, + apr_time_t mtime, + apr_pool_t *pool); + +/** + * Create a new directory on the file system. + * @param path the path for the directory to be created. (use / on all systems) + * @param perm Permissions for the new direcoty. + * @param pool the pool to use. + */ +APR_DECLARE(apr_status_t) apr_dir_make(const char *path, apr_fileperms_t perm, + apr_pool_t *pool); + +/** Creates a new directory on the file system, but behaves like + * 'mkdir -p'. Creates intermediate directories as required. No error + * will be reported if PATH already exists. + * @param path the path for the directory to be created. (use / on all systems) + * @param perm Permissions for the new direcoty. + * @param pool the pool to use. + */ +APR_DECLARE(apr_status_t) apr_dir_make_recursive(const char *path, + apr_fileperms_t perm, + apr_pool_t *pool); + +/** + * Remove directory from the file system. + * @param path the path for the directory to be removed. (use / on all systems) + * @param pool the pool to use. + */ +APR_DECLARE(apr_status_t) apr_dir_remove(const char *path, apr_pool_t *pool); + +/** + * get the specified file's stats. + * @param finfo Where to store the information about the file. + * @param wanted The desired apr_finfo_t fields, as a bit flag of APR_FINFO_ values + * @param thefile The file to get information about. + */ +APR_DECLARE(apr_status_t) apr_file_info_get(apr_finfo_t *finfo, + apr_int32_t wanted, + apr_file_t *thefile); + + +/** + * Truncate the file's length to the specified offset + * @param fp The file to truncate + * @param offset The offset to truncate to. + */ +APR_DECLARE(apr_status_t) apr_file_trunc(apr_file_t *fp, apr_off_t offset); + +/** + * Retrieve the flags that were passed into apr_file_open() + * when the file was opened. + * @return apr_int32_t the flags + */ +APR_DECLARE(apr_int32_t) apr_file_flags_get(apr_file_t *f); + +/** + * Get the pool used by the file. + */ +APR_POOL_DECLARE_ACCESSOR(file); + +/** + * Set a file to be inherited by child processes. + * + */ +APR_DECLARE_INHERIT_SET(file); + +/** + * Unset a file from being inherited by child processes. + */ +APR_DECLARE_INHERIT_UNSET(file); + +/** + * Open a temporary file + * @param fp The apr file to use as a temporary file. + * @param templ The template to use when creating a temp file. + * @param flags The flags to open the file with. If this is zero, + * the file is opened with + * APR_CREATE | APR_READ | APR_WRITE | APR_EXCL | APR_DELONCLOSE + * @param p The pool to allocate the file out of. + * @remark + * This function generates a unique temporary file name from template. + * The last six characters of template must be XXXXXX and these are replaced + * with a string that makes the filename unique. Since it will be modified, + * template must not be a string constant, but should be declared as a character + * array. + * + */ +APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *templ, + apr_int32_t flags, apr_pool_t *p); + + +/** + * Find an existing directory suitable as a temporary storage location. + * @param temp_dir The temp directory. + * @param p The pool to use for any necessary allocations. + * @remark + * This function uses an algorithm to search for a directory that an + * an application can use for temporary storage. Once such a + * directory is found, that location is cached by the library. Thus, + * callers only pay the cost of this algorithm once if that one time + * is successful. + * + */ +APR_DECLARE(apr_status_t) apr_temp_dir_get(const char **temp_dir, + apr_pool_t *p); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_FILE_IO_H */ diff --git a/srclib/apr/include/apr_fnmatch.h b/srclib/apr/include/apr_fnmatch.h new file mode 100644 index 0000000000..7a2811aac8 --- /dev/null +++ b/srclib/apr/include/apr_fnmatch.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)fnmatch.h 8.1 (Berkeley) 6/2/93 + */ + +/* This file has been modified by the Apache Software Foundation. */ +#ifndef _APR_FNMATCH_H_ +#define _APR_FNMATCH_H_ + +/** + * @file apr_fnmatch.h + * @brief APR FNMatch Functions + */ + +#include "apr_errno.h" +#include "apr_tables.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_fnmatch Filename Matching Functions + * @ingroup APR + * @{ + */ + +#define APR_FNM_NOMATCH 1 /**< Match failed. */ + +#define APR_FNM_NOESCAPE 0x01 /**< Disable backslash escaping. */ +#define APR_FNM_PATHNAME 0x02 /**< Slash must be matched by slash. */ +#define APR_FNM_PERIOD 0x04 /**< Period must be matched by period. */ +#define APR_FNM_CASE_BLIND 0x08 /**< Compare characters case-insensitively. + * @remark This flag is an Apache addition + */ + +/** + * Try to match the string to the given pattern, return APR_SUCCESS if + * match, else return APR_FNM_NOMATCH. + * @param pattern The pattern to match to + * @param strings The string we are trying to match + * @param flags flags to use in the match. Bitwise OR of: + *
    + *              APR_FNM_NOESCAPE       Disable backslash escaping
    + *              APR_FNM_PATHNAME       Slash must be matched by slash
    + *              APR_FNM_PERIOD         Period must be matched by period
    + *              APR_FNM_CASE_BLIND     Compare characters case-insensitively.
    + * 
    + */ + +APR_DECLARE(apr_status_t) apr_fnmatch(const char *pattern, + const char *strings, int flags); + +/** + * Determine if the given pattern is a regular expression. + * @param pattern The pattern to search for glob characters. + * @return non-zero if pattern has any glob characters in it + */ +APR_DECLARE(int) apr_fnmatch_test(const char *pattern); + +/** + * Find all files that match a specified pattern. + * @param pattern The pattern to use for finding files. + * @param result Array to use when storing the results + * @param p The pool to use. + * @return non-zero if pattern has any glob characters in it + */ +APR_DECLARE(apr_status_t) apr_match_glob(const char *pattern, + apr_array_header_t **result, + apr_pool_t *p); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !_APR_FNMATCH_H_ */ diff --git a/srclib/apr/include/apr_general.h b/srclib/apr/include/apr_general.h new file mode 100644 index 0000000000..5973a986ea --- /dev/null +++ b/srclib/apr/include/apr_general.h @@ -0,0 +1,241 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_GENERAL_H +#define APR_GENERAL_H + +/** + * @file apr_general.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR Miscellaneous library routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#if APR_HAVE_SIGNAL_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_general Miscellaneous library routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** FALSE */ +#ifndef FALSE +#define FALSE 0 +#endif +/** TRUE */ +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +/** a space */ +#define APR_ASCII_BLANK '\040' +/** a carrige return */ +#define APR_ASCII_CR '\015' +/** a line feed */ +#define APR_ASCII_LF '\012' +/** a tab */ +#define APR_ASCII_TAB '\011' + +/** signal numbers typedef */ +typedef int apr_signum_t; + +/** + * Finding offsets of elements within structures. + * Taken from the X code... they've sweated portability of this stuff + * so we don't have to. Sigh... + * @param p_type pointer type name + * @param field data field within the structure pointed to + * @return offset + */ + +#if defined(CRAY) || (defined(__arm) && !defined(LINUX)) +#ifdef __STDC__ +#define APR_OFFSET(p_type,field) _Offsetof(p_type,field) +#else +#ifdef CRAY2 +#define APR_OFFSET(p_type,field) \ + (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) + +#else /* !CRAY2 */ + +#define APR_OFFSET(p_type,field) ((unsigned int)&(((p_type)NULL)->field)) + +#endif /* !CRAY2 */ +#endif /* __STDC__ */ +#else /* ! (CRAY || __arm) */ + +#define APR_OFFSET(p_type,field) \ + ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) + +#endif /* !CRAY */ + +/** + * Finding offsets of elements within structures. + * @param s_type structure type name + * @param field data field within the structure + * @return offset + */ +#if defined(offsetof) && !defined(__cplusplus) +#define APR_OFFSETOF(s_type,field) offsetof(s_type,field) +#else +#define APR_OFFSETOF(s_type,field) APR_OFFSET(s_type*,field) +#endif + +#ifndef DOXYGEN + +/* A couple of prototypes for functions in case some platform doesn't + * have it + */ +#if (!APR_HAVE_STRCASECMP) && (APR_HAVE_STRICMP) +#define strcasecmp(s1, s2) stricmp(s1, s2) +#elif (!APR_HAVE_STRCASECMP) +int strcasecmp(const char *a, const char *b); +#endif + +#if (!APR_HAVE_STRNCASECMP) && (APR_HAVE_STRNICMP) +#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n) +#elif (!APR_HAVE_STRNCASECMP) +int strncasecmp(const char *a, const char *b, size_t n); +#endif + +#endif + +/** + * Alignment macros + */ + +/* APR_ALIGN() is only to be used to align on a power of 2 boundary */ +#define APR_ALIGN(size, boundary) \ + (((size) + ((boundary) - 1)) & ~((boundary) - 1)) + +/** Default alignment */ +#define APR_ALIGN_DEFAULT(size) APR_ALIGN(size, 8) + + +/** + * String and memory functions + */ + +/* APR_STRINGIFY is defined here, and also in apr_release.h, so wrap it */ +#ifndef APR_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n) +/** Helper macro for APR_STRINGIFY */ +#define APR_STRINGIFY_HELPER(n) #n +#endif + +#if (!APR_HAVE_MEMMOVE) +#define memmove(a,b,c) bcopy(b,a,c) +#endif + +#if (!APR_HAVE_MEMCHR) +void *memchr(const void *s, int c, size_t n); +#endif + +/** @} */ + +/** + * @defgroup apr_library Library initialization and termination + * @{ + */ + +/** + * Setup any APR internal data structures. This MUST be the first function + * called for any APR library. + * @remark See apr_app_initialize if this is an application, rather than + * a library consumer of apr. + */ +APR_DECLARE(apr_status_t) apr_initialize(void); + +/** + * Set up an application with normalized argc, argv (and optionally env) in + * order to deal with platform-specific oddities, such as Win32 services, + * code pages and signals. This must be the first function called for any + * APR program. + * @param argc Pointer to the argc that may be corrected + * @param argv Pointer to the argv that may be corrected + * @param env Pointer to the env that may be corrected, may be NULL + * @remark See apr_initialize if this is a library consumer of apr. + * Otherwise, this call is identical to apr_initialize, and must be closed + * with a call to apr_terminate at the end of program execution. + */ +APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + char const * const * *argv, + char const * const * *env); + +/** + * Tear down any APR internal data structures which aren't torn down + * automatically. + * @remark An APR program must call this function at termination once it + * has stopped using APR services. The APR developers suggest using + * atexit to ensure this is called. When using APR from a language + * other than C that has problems with the calling convention, use + * apr_terminate2() instead. + */ +APR_DECLARE_NONSTD(void) apr_terminate(void); + +/** + * Tear down any APR internal data structures which aren't torn down + * automatically, same as apr_terminate + * @remark An APR program must call either the apr_terminate or apr_terminate2 + * function once it it has finished using APR services. The APR + * developers suggest using atexit(apr_terminate) to ensure this is done. + * apr_terminate2 exists to allow non-c language apps to tear down apr, + * while apr_terminate is recommended from c language applications. + */ +APR_DECLARE(void) apr_terminate2(void); + +/** @} */ + +/** + * @defgroup apr_random Random Functions + * @{ + */ + +#if APR_HAS_RANDOM || defined(DOXYGEN) + +/* TODO: I'm not sure this is the best place to put this prototype...*/ +/** + * Generate random bytes. + * @param buf Buffer to fill with random bytes + * @param length Length of buffer in bytes + */ +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, + apr_size_t length); + +#endif +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_GENERAL_H */ diff --git a/srclib/apr/include/apr_getopt.h b/srclib/apr/include/apr_getopt.h new file mode 100644 index 0000000000..972e14e3c7 --- /dev/null +++ b/srclib/apr/include/apr_getopt.h @@ -0,0 +1,158 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_GETOPT_H +#define APR_GETOPT_H + +/** + * @file apr_getopt.h + * @brief APR Command Arguments (getopt) + */ + +#include "apr_pools.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_getopt Command Argument Parsing + * @ingroup APR + * @{ + */ + +/** + * defintion of a error function + */ +typedef void (apr_getopt_err_fn_t)(void *arg, const char *err, ...); + +/** @see apr_getopt_t */ +typedef struct apr_getopt_t apr_getopt_t; + +/** + * Structure to store command line argument information. + */ +struct apr_getopt_t { + /** context for processing */ + apr_pool_t *cont; + /** function to print error message (NULL == no messages) */ + apr_getopt_err_fn_t *errfn; + /** user defined first arg to pass to error message */ + void *errarg; + /** index into parent argv vector */ + int ind; + /** character checked for validity */ + int opt; + /** reset getopt */ + int reset; + /** count of arguments */ + int argc; + /** array of pointers to arguments */ + const char **argv; + /** argument associated with option */ + char const* place; + /** set to nonzero to support interleaving options with regular args */ + int interleave; + /** start of non-option arguments skipped for interleaving */ + int skip_start; + /** end of non-option arguments skipped for interleaving */ + int skip_end; +}; + +/** @see apr_getopt_option_t */ +typedef struct apr_getopt_option_t apr_getopt_option_t; + +/** + * Structure used to describe options that getopt should search for. + */ +struct apr_getopt_option_t { + /** long option name, or NULL if option has no long name */ + const char *name; + /** option letter, or a value greater than 255 if option has no letter */ + int optch; + /** nonzero if option takes an argument */ + int has_arg; + /** a description of the option */ + const char *description; +}; + +/** + * Initialize the arguments for parsing by apr_getopt(). + * @param os The options structure created for apr_getopt() + * @param cont The pool to operate on + * @param argc The number of arguments to parse + * @param argv The array of arguments to parse + * @remark Arguments 2 and 3 are most commonly argc and argv from main(argc, argv) + * The errfn is initialized to fprintf(stderr... but may be overridden. + */ +APR_DECLARE(apr_status_t) apr_getopt_init(apr_getopt_t **os, apr_pool_t *cont, + int argc, const char * const *argv); + +/** + * Parse the options initialized by apr_getopt_init(). + * @param os The apr_opt_t structure returned by apr_getopt_init() + * @param opts A string of characters that are acceptable options to the + * program. Characters followed by ":" are required to have an + * option associated + * @param option_ch The next option character parsed + * @param option_arg The argument following the option character: + * @return There are four potential status values on exit. They are: + *
    + *             APR_EOF      --  No more options to parse
    + *             APR_BADCH    --  Found a bad option character
    + *             APR_BADARG   --  No argument followed the option flag
    + *             APR_SUCCESS  --  The next option was found.
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, + char *option_ch, const char **option_arg); + +/** + * Parse the options initialized by apr_getopt_init(), accepting long + * options beginning with "--" in addition to single-character + * options beginning with "-". + * @param os The apr_getopt_t structure created by apr_getopt_init() + * @param opts A pointer to a list of apr_getopt_option_t structures, which + * can be initialized with { "name", optch, has_args }. has_args + * is nonzero if the option requires an argument. A structure + * with an optch value of 0 terminates the list. + * @param option_ch Receives the value of "optch" from the apr_getopt_option_t + * structure corresponding to the next option matched. + * @param option_arg Receives the argument following the option, if any. + * @return There are four potential status values on exit. They are: + *
    + *             APR_EOF      --  No more options to parse
    + *             APR_BADCH    --  Found a bad option character
    + *             APR_BADARG   --  No argument followed the option flag
    + *             APR_SUCCESS  --  The next option was found.
    + * 
    + * When APR_SUCCESS is returned, os->ind gives the index of the first + * non-option argument. On error, a message will be printed to stdout unless + * os->err is set to 0. If os->interleave is set to nonzero, options can come + * after arguments, and os->argv will be permuted to leave non-option arguments + * at the end (the original argv is unaffected). + */ +APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os, + const apr_getopt_option_t *opts, + int *option_ch, + const char **option_arg); +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_GETOPT_H */ diff --git a/srclib/apr/include/apr_global_mutex.h b/srclib/apr/include/apr_global_mutex.h new file mode 100644 index 0000000000..7decb28250 --- /dev/null +++ b/srclib/apr/include/apr_global_mutex.h @@ -0,0 +1,153 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_GLOBAL_MUTEX_H +#define APR_GLOBAL_MUTEX_H + +/** + * @file apr_global_mutex.h + * @brief APR Global Locking Routines + */ + +#include "apr.h" +#include "apr_proc_mutex.h" /* only for apr_lockmech_e */ +#include "apr_pools.h" +#include "apr_errno.h" +#if APR_PROC_MUTEX_IS_GLOBAL +#include "apr_proc_mutex.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup APR_GlobalMutex Global Locking Routines + * @ingroup APR + * @{ + */ + +#if !APR_PROC_MUTEX_IS_GLOBAL || defined(DOXYGEN) + +/** Opaque global mutex structure. */ +typedef struct apr_global_mutex_t apr_global_mutex_t; + +/* Function definitions */ + +/** + * Create and initialize a mutex that can be used to synchronize both + * processes and threads. Note: There is considerable overhead in using + * this API if only cross-process or cross-thread mutual exclusion is + * required. See apr_proc_mutex.h and apr_thread_mutex.h for more + * specialized lock routines. + * @param mutex the memory address where the newly created mutex will be + * stored. + * @param fname A file name to use if the lock mechanism requires one. This + * argument should always be provided. The lock code itself will + * determine if it should be used. + * @param mech The mechanism to use for the interprocess lock, if any; one of + *
    + *            APR_LOCK_FCNTL
    + *            APR_LOCK_FLOCK
    + *            APR_LOCK_SYSVSEM
    + *            APR_LOCK_POSIXSEM
    + *            APR_LOCK_PROC_PTHREAD
    + *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
    + * 
    + * @param pool the pool from which to allocate the mutex. + * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports + * APR_LOCK_foo. Only APR_LOCK_DEFAULT is portable. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_create(apr_global_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); + +/** + * Re-open a mutex in a child process. + * @param mutex The newly re-opened mutex structure. + * @param fname A file name to use if the mutex mechanism requires one. This + * argument should always be provided. The mutex code itself will + * determine if it should be used. This filename should be the + * same one that was passed to apr_global_mutex_create(). + * @param pool The pool to operate on. + * @remark This function must be called to maintain portability, even + * if the underlying lock mechanism does not require it. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_child_init( + apr_global_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + +/** + * Acquire the lock for the given mutex. If the mutex is already locked, + * the current thread will be put to sleep until the lock becomes available. + * @param mutex the mutex on which to acquire the lock. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_lock(apr_global_mutex_t *mutex); + +/** + * Attempt to acquire the lock for the given mutex. If the mutex has already + * been acquired, the call returns immediately with APR_EBUSY. Note: it + * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine + * if the return value was APR_EBUSY, for portability reasons. + * @param mutex the mutex on which to attempt the lock acquiring. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex); + +/** + * Release the lock for the given mutex. + * @param mutex the mutex from which to release the lock. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_unlock(apr_global_mutex_t *mutex); + +/** + * Destroy the mutex and free the memory associated with the lock. + * @param mutex the mutex to destroy. + */ +APR_DECLARE(apr_status_t) apr_global_mutex_destroy(apr_global_mutex_t *mutex); + +/** + * Get the pool used by this global_mutex. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(global_mutex); + +#else /* APR_PROC_MUTEX_IS_GLOBAL */ + +/* Some platforms [e.g. Win32] have cross process locks that are truly + * global locks, since there isn't the concept of cross-process locks. + * Define these platforms in terms of an apr_proc_mutex_t. + */ + +#define apr_global_mutex_t apr_proc_mutex_t +#define apr_global_mutex_create apr_proc_mutex_create +#define apr_global_mutex_child_init apr_proc_mutex_child_init +#define apr_global_mutex_lock apr_proc_mutex_lock +#define apr_global_mutex_trylock apr_proc_mutex_trylock +#define apr_global_mutex_unlock apr_proc_mutex_unlock +#define apr_global_mutex_destroy apr_proc_mutex_destroy +#define apr_global_mutex_pool_get apr_proc_mutex_pool_get + +#endif + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ndef APR_GLOBAL_MUTEX_H */ diff --git a/srclib/apr/include/apr_hash.h b/srclib/apr/include/apr_hash.h new file mode 100644 index 0000000000..37f307c9fc --- /dev/null +++ b/srclib/apr/include/apr_hash.h @@ -0,0 +1,225 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_HASH_H +#define APR_HASH_H + +/** + * @file apr_hash.h + * @brief APR Hash Tables + */ + +#include "apr_pools.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_hash Hash Tables + * @ingroup APR + * @{ + */ + +/** + * When passing a key to apr_hash_set or apr_hash_get, this value can be + * passed to indicate a string-valued key, and have apr_hash compute the + * length automatically. + * + * @remark apr_hash will use strlen(key) for the length. The NUL terminator + * is not included in the hash value (why throw a constant in?). + * Since the hash table merely references the provided key (rather + * than copying it), apr_hash_this() will return the NUL-term'd key. + */ +#define APR_HASH_KEY_STRING (-1) + +/** + * Abstract type for hash tables. + */ +typedef struct apr_hash_t apr_hash_t; + +/** + * Abstract type for scanning hash tables. + */ +typedef struct apr_hash_index_t apr_hash_index_t; + +/** + * Callback functions for calculating hash values. + * @param key The key. + * @param klen The length of the key, or APR_HASH_KEY_STRING to use the string + * length. If APR_HASH_KEY_STRING then returns the actual key length. + */ +typedef unsigned int (*apr_hashfunc_t)(const char *key, apr_ssize_t *klen); + +/** + * The default hash function. + */ +unsigned int apr_hashfunc_default(const char *key, apr_ssize_t *klen); + +/** + * Create a hash table. + * @param pool The pool to allocate the hash table out of + * @return The hash table just created + */ +APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool); + +/** + * Create a hash table with a custom hash function + * @param pool The pool to allocate the hash table out of + * @param hash_func A custom hash function. + * @return The hash table just created + */ +APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool, + apr_hashfunc_t hash_func); + +/** + * Make a copy of a hash table + * @param pool The pool from which to allocate the new hash table + * @param h The hash table to clone + * @return The hash table just created + * @remark Makes a shallow copy + */ +APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool, + const apr_hash_t *h); + +/** + * Associate a value with a key in a hash table. + * @param ht The hash table + * @param key Pointer to the key + * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string length. + * @param val Value to associate with the key + * @remark If the value is NULL the hash entry is deleted. + */ +APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, const void *key, + apr_ssize_t klen, const void *val); + +/** + * Look up the value associated with a key in a hash table. + * @param ht The hash table + * @param key Pointer to the key + * @param klen Length of the key. Can be APR_HASH_KEY_STRING to use the string length. + * @return Returns NULL if the key is not present. + */ +APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, const void *key, + apr_ssize_t klen); + +/** + * Start iterating over the entries in a hash table. + * @param p The pool to allocate the apr_hash_index_t iterator. If this + * pool is NULL, then an internal, non-thread-safe iterator is used. + * @param ht The hash table + * @remark There is no restriction on adding or deleting hash entries during + * an iteration (although the results may be unpredictable unless all you do + * is delete the current entry) and multiple iterations can be in + * progress at the same time. + + * @example + */ +/** + *
    + * 
    + * int sum_values(apr_pool_t *p, apr_hash_t *ht)
    + * {
    + *     apr_hash_index_t *hi;
    + *     void *val;
    + *     int sum = 0;
    + *     for (hi = apr_hash_first(p, ht); hi; hi = apr_hash_next(hi)) {
    + *         apr_hash_this(hi, NULL, NULL, &val);
    + *         sum += *(int *)val;
    + *     }
    + *     return sum;
    + * }
    + * 
    + */ +APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht); + +/** + * Continue iterating over the entries in a hash table. + * @param hi The iteration state + * @return a pointer to the updated iteration state. NULL if there are no more + * entries. + */ +APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi); + +/** + * Get the current entry's details from the iteration state. + * @param hi The iteration state + * @param key Return pointer for the pointer to the key. + * @param klen Return pointer for the key length. + * @param val Return pointer for the associated value. + * @remark The return pointers should point to a variable that will be set to the + * corresponding data, or they may be NULL if the data isn't interesting. + */ +APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi, const void **key, + apr_ssize_t *klen, void **val); + +/** + * Get the number of key/value pairs in the hash table. + * @param ht The hash table + * @return The number of key/value pairs in the hash table. + */ +APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht); + +/** + * Merge two hash tables into one new hash table. The values of the overlay + * hash override the values of the base if both have the same key. Both + * hash tables must use the same hash function. + * @param p The pool to use for the new hash table + * @param overlay The table to add to the initial table + * @param base The table that represents the initial values of the new table + * @return A new hash table containing all of the data from the two passed in + */ +APR_DECLARE(apr_hash_t *) apr_hash_overlay(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base); + +/** + * Merge two hash tables into one new hash table. If the same key + * is present in both tables, call the supplied merge function to + * produce a merged value for the key in the new table. Both + * hash tables must use the same hash function. + * @param p The pool to use for the new hash table + * @param h1 The first of the tables to merge + * @param h2 The second of the tables to merge + * @param merger A callback function to merge values, or NULL to + * make values from h1 override values from h2 (same semantics as + * apr_hash_overlay()) + * @param data Client data to pass to the merger function + * @return A new hash table containing all of the data from the two passed in + */ +APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, + const apr_hash_t *h1, + const apr_hash_t *h2, + void * (*merger)(apr_pool_t *p, + const void *key, + apr_ssize_t klen, + const void *h1_val, + const void *h2_val, + const void *data), + const void *data); + +/** + * Get a pointer to the pool which the hash table was created in + */ +APR_POOL_DECLARE_ACCESSOR(hash); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_HASH_H */ diff --git a/srclib/apr/include/apr_inherit.h b/srclib/apr/include/apr_inherit.h new file mode 100644 index 0000000000..4042c90135 --- /dev/null +++ b/srclib/apr/include/apr_inherit.h @@ -0,0 +1,51 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_INHERIT_H +#define APR_INHERIT_H + +/** + * @file apr_inherit.h + * @brief APR File Handle Inheritance Helpers + * @remark This internal header includes internal declaration helpers + * for other headers to declare apr_foo_inherit_[un]set functions. + */ + +/** + * Prototype for type-specific declarations of apr_foo_inherit_set + * functions. + * @remark Doxygen unwraps this macro (via doxygen.conf) to provide + * actual help for each specific occurance of apr_foo_inherit_set. + * @remark the linkage is specified for APR. It would be possible to expand + * the macros to support other linkages. + */ +#define APR_DECLARE_INHERIT_SET(type) \ + APR_DECLARE(apr_status_t) apr_##type##_inherit_set( \ + apr_##type##_t *the##type) + +/** + * Prototype for type-specific declarations of apr_foo_inherit_unset + * functions. + * @remark Doxygen unwraps this macro (via doxygen.conf) to provide + * actual help for each specific occurance of apr_foo_inherit_unset. + * @remark the linkage is specified for APR. It would be possible to expand + * the macros to support other linkages. + */ +#define APR_DECLARE_INHERIT_UNSET(type) \ + APR_DECLARE(apr_status_t) apr_##type##_inherit_unset( \ + apr_##type##_t *the##type) + +#endif /* ! APR_INHERIT_H */ diff --git a/srclib/apr/include/apr_lib.h b/srclib/apr/include/apr_lib.h new file mode 100644 index 0000000000..c48782d5bb --- /dev/null +++ b/srclib/apr/include/apr_lib.h @@ -0,0 +1,230 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_LIB_H +#define APR_LIB_H + +/** + * @file apr_lib.h + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @brief APR general purpose library routines + */ + +#include "apr.h" +#include "apr_errno.h" + +#if APR_HAVE_CTYPE_H +#include +#endif +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_lib General Purpose Library Routines + * @ingroup APR + * This is collection of oddballs that didn't fit anywhere else, + * and might move to more appropriate headers with the release + * of APR 1.0. + * @{ + */ + +/** A constant representing a 'large' string. */ +#define HUGE_STRING_LEN 8192 + +/* + * Define the structures used by the APR general-purpose library. + */ + +/** @see apr_vformatter_buff_t */ +typedef struct apr_vformatter_buff_t apr_vformatter_buff_t; + +/** + * Structure used by the variable-formatter routines. + */ +struct apr_vformatter_buff_t { + /** The current position */ + char *curpos; + /** The end position of the format string */ + char *endpos; +}; + +/** + * return the final element of the pathname + * @param pathname The path to get the final element of + * @return the final element of the path + * @remark + *
    + * For example:
    + *                 "/foo/bar/gum"    -> "gum"
    + *                 "/foo/bar/gum/"   -> ""
    + *                 "gum"             -> "gum"
    + *                 "bs\\path\\stuff" -> "stuff"
    + * 
    + */ +APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname); + +/** + * apr_killpg + * Small utility macros to make things easier to read. Not usually a + * goal, to be sure.. + */ + +#ifdef WIN32 +#define apr_killpg(x, y) +#else /* WIN32 */ +#ifdef NO_KILLPG +#define apr_killpg(x, y) (kill (-(x), (y))) +#else /* NO_KILLPG */ +#define apr_killpg(x, y) (killpg ((x), (y))) +#endif /* NO_KILLPG */ +#endif /* WIN32 */ + +/** + * apr_vformatter() is a generic printf-style formatting routine + * with some extensions. + * @param flush_func The function to call when the buffer is full + * @param c The buffer to write to + * @param fmt The format string + * @param ap The arguments to use to fill out the format string. + * + * @remark + *
    + * The extensions are:
    + *
    + * %%pA	takes a struct in_addr *, and prints it as a.b.c.d
    + * %%pI	takes an apr_sockaddr_t * and prints it as a.b.c.d:port or
    + *      [ipv6-address]:port
    + * %%pT takes an apr_os_thread_t * and prints it in decimal
    + *      ('0' is printed if !APR_HAS_THREADS)
    + * %%pp takes a void * and outputs it in hex
    + *
    + * The %%p hacks are to force gcc's printf warning code to skip
    + * over a pointer argument without complaining.  This does
    + * mean that the ANSI-style %%p (output a void * in hex format) won't
    + * work as expected at all, but that seems to be a fair trade-off
    + * for the increased robustness of having printf-warnings work.
    + *
    + * Additionally, apr_vformatter allows for arbitrary output methods
    + * using the apr_vformatter_buff and flush_func.
    + *
    + * The apr_vformatter_buff has two elements curpos and endpos.
    + * curpos is where apr_vformatter will write the next byte of output.
    + * It proceeds writing output to curpos, and updating curpos, until
    + * either the end of output is reached, or curpos == endpos (i.e. the
    + * buffer is full).
    + *
    + * If the end of output is reached, apr_vformatter returns the
    + * number of bytes written.
    + *
    + * When the buffer is full, the flush_func is called.  The flush_func
    + * can return -1 to indicate that no further output should be attempted,
    + * and apr_vformatter will return immediately with -1.  Otherwise
    + * the flush_func should flush the buffer in whatever manner is
    + * appropriate, re apr_pool_t nitialize curpos and endpos, and return 0.
    + *
    + * Note that flush_func is only invoked as a result of attempting to
    + * write another byte at curpos when curpos >= endpos.  So for
    + * example, it's possible when the output exactly matches the buffer
    + * space available that curpos == endpos will be true when
    + * apr_vformatter returns.
    + *
    + * apr_vformatter does not call out to any other code, it is entirely
    + * self-contained.  This allows the callers to do things which are
    + * otherwise "unsafe".  For example, apr_psprintf uses the "scratch"
    + * space at the unallocated end of a block, and doesn't actually
    + * complete the allocation until apr_vformatter returns.  apr_psprintf
    + * would be completely broken if apr_vformatter were to call anything
    + * that used this same pool.  Similarly http_bprintf() uses the "scratch"
    + * space at the end of its output buffer, and doesn't actually note
    + * that the space is in use until it either has to flush the buffer
    + * or until apr_vformatter returns.
    + * 
    + */ +APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *b), + apr_vformatter_buff_t *c, const char *fmt, + va_list ap); + +/** + * Display a prompt and read in the password from stdin. + * @param prompt The prompt to display + * @param pwbuf Buffer to store the password + * @param bufsize The length of the password buffer. + * @remark If the password entered must be truncated to fit in + * the provided buffer, APR_ENAMETOOLONG will be returned. + * Note that the bufsize paramater is passed by reference for no + * reason; its value will never be modified by the apr_password_get() + * function. + */ +APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, + apr_size_t *bufsize); + +/** @} */ + +/** + * @defgroup apr_ctype ctype functions + * These macros allow correct support of 8-bit characters on systems which + * support 8-bit characters. Pretty dumb how the cast is required, but + * that's legacy libc for ya. These new macros do not support EOF like + * the standard macros do. Tough. + * @{ + */ +/** @see isalnum */ +#define apr_isalnum(c) (isalnum(((unsigned char)(c)))) +/** @see isalpha */ +#define apr_isalpha(c) (isalpha(((unsigned char)(c)))) +/** @see iscntrl */ +#define apr_iscntrl(c) (iscntrl(((unsigned char)(c)))) +/** @see isdigit */ +#define apr_isdigit(c) (isdigit(((unsigned char)(c)))) +/** @see isgraph */ +#define apr_isgraph(c) (isgraph(((unsigned char)(c)))) +/** @see islower*/ +#define apr_islower(c) (islower(((unsigned char)(c)))) +/** @see isascii */ +#ifdef isascii +#define apr_isascii(c) (isascii(((unsigned char)(c)))) +#else +#define apr_isascii(c) (((c) & ~0x7f)==0) +#endif +/** @see isprint */ +#define apr_isprint(c) (isprint(((unsigned char)(c)))) +/** @see ispunct */ +#define apr_ispunct(c) (ispunct(((unsigned char)(c)))) +/** @see isspace */ +#define apr_isspace(c) (isspace(((unsigned char)(c)))) +/** @see isupper */ +#define apr_isupper(c) (isupper(((unsigned char)(c)))) +/** @see isxdigit */ +#define apr_isxdigit(c) (isxdigit(((unsigned char)(c)))) +/** @see tolower */ +#define apr_tolower(c) (tolower(((unsigned char)(c)))) +/** @see toupper */ +#define apr_toupper(c) (toupper(((unsigned char)(c)))) + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_LIB_H */ diff --git a/srclib/apr/include/apr_mmap.h b/srclib/apr/include/apr_mmap.h new file mode 100644 index 0000000000..f1b45e3797 --- /dev/null +++ b/srclib/apr/include/apr_mmap.h @@ -0,0 +1,171 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_MMAP_H +#define APR_MMAP_H + +/** + * @file apr_mmap.h + * @brief APR MMAP routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_ring.h" +#include "apr_file_io.h" /* for apr_file_t */ + +#ifdef BEOS +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_mmap MMAP (Memory Map) Routines + * @ingroup APR + * @{ + */ + +/** MMap opened for reading */ +#define APR_MMAP_READ 1 +/** MMap opened for writing */ +#define APR_MMAP_WRITE 2 + +/** @see apr_mmap_t */ +typedef struct apr_mmap_t apr_mmap_t; + +/** + * @remark + * As far as I can tell the only really sane way to store an MMAP is as a + * void * and a length. BeOS requires this area_id, but that's just a little + * something extra. I am exposing this type, because it doesn't make much + * sense to keep it private, and opening it up makes some stuff easier in + * Apache. + */ +/** The MMAP structure */ +struct apr_mmap_t { + /** The pool the mmap structure was allocated out of. */ + apr_pool_t *cntxt; +#ifdef BEOS + /** An area ID. Only valid on BeOS */ + area_id area; +#endif +#ifdef WIN32 + /** The handle of the file mapping */ + HANDLE mhandle; + /** The start of the real memory page area (mapped view) */ + void *mv; + /** The physical start, size and offset */ + apr_off_t pstart; + apr_size_t psize; + apr_off_t poffset; +#endif + /** The start of the memory mapped area */ + void *mm; + /** The amount of data in the mmap */ + apr_size_t size; + /** ring of apr_mmap_t's that reference the same + * mmap'ed region; acts in place of a reference count */ + APR_RING_ENTRY(apr_mmap_t) link; +}; + +#if APR_HAS_MMAP || defined(DOXYGEN) + +/** @def APR_MMAP_THRESHOLD + * Files have to be at least this big before they're mmap()d. This is to deal + * with systems where the expense of doing an mmap() and an munmap() outweighs + * the benefit for small files. It shouldn't be set lower than 1. + */ +#ifdef MMAP_THRESHOLD +# define APR_MMAP_THRESHOLD MMAP_THRESHOLD +#else +# ifdef SUNOS4 +# define APR_MMAP_THRESHOLD (8*1024) +# else +# define APR_MMAP_THRESHOLD 1 +# endif /* SUNOS4 */ +#endif /* MMAP_THRESHOLD */ + +/** @def APR_MMAP_LIMIT + * Maximum size of MMap region + */ +#ifdef MMAP_LIMIT +# define APR_MMAP_LIMIT MMAP_LIMIT +#else +# define APR_MMAP_LIMIT (4*1024*1024) +#endif /* MMAP_LIMIT */ + +/** Can this file be MMaped */ +#define APR_MMAP_CANDIDATE(filelength) \ + ((filelength >= APR_MMAP_THRESHOLD) && (filelength < APR_MMAP_LIMIT)) + +/* Function definitions */ + +/** + * Create a new mmap'ed file out of an existing APR file. + * @param newmmap The newly created mmap'ed file. + * @param file The file turn into an mmap. + * @param offset The offset into the file to start the data pointer at. + * @param size The size of the file + * @param flag bit-wise or of: + *
    + *          APR_MMAP_READ       MMap opened for reading
    + *          APR_MMAP_WRITE      MMap opened for writing
    + * 
    + * @param cntxt The pool to use when creating the mmap. + */ +APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **newmmap, + apr_file_t *file, apr_off_t offset, + apr_size_t size, apr_int32_t flag, + apr_pool_t *cntxt); + +/** + * Duplicate the specified MMAP. + * @param new_mmap The structure to duplicate into. + * @param old_mmap The mmap to duplicate. + * @param p The pool to use for new_mmap. + */ +APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap, + apr_mmap_t *old_mmap, + apr_pool_t *p); + +/** + * Remove a mmap'ed. + * @param mm The mmap'ed file. + */ +APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm); + +/** + * Move the pointer into the mmap'ed file to the specified offset. + * @param addr The pointer to the offset specified. + * @param mm The mmap'ed file. + * @param offset The offset to move to. + */ +APR_DECLARE(apr_status_t) apr_mmap_offset(void **addr, apr_mmap_t *mm, + apr_off_t offset); + +#endif /* APR_HAS_MMAP */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_MMAP_H */ diff --git a/srclib/apr/include/apr_network_io.h b/srclib/apr/include/apr_network_io.h new file mode 100644 index 0000000000..68d8a7c49b --- /dev/null +++ b/srclib/apr/include/apr_network_io.h @@ -0,0 +1,821 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_NETWORK_IO_H +#define APR_NETWORK_IO_H +/** + * @file apr_network_io.h + * @brief APR Network library + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_inherit.h" + +#if APR_HAVE_NETINET_IN_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_network_io Network Routines + * @ingroup APR + * @{ + */ + +#ifndef APR_MAX_SECS_TO_LINGER +/** Maximum seconds to linger */ +#define APR_MAX_SECS_TO_LINGER 30 +#endif + +#ifndef APRMAXHOSTLEN +/** Maximum hostname length */ +#define APRMAXHOSTLEN 256 +#endif + +#ifndef APR_ANYADDR +/** Default 'any' address */ +#define APR_ANYADDR "0.0.0.0" +#endif + +/** + * @defgroup apr_sockopt Socket option definitions + * @{ + */ +#define APR_SO_LINGER 1 /**< Linger */ +#define APR_SO_KEEPALIVE 2 /**< Keepalive */ +#define APR_SO_DEBUG 4 /**< Debug */ +#define APR_SO_NONBLOCK 8 /**< Non-blocking IO */ +#define APR_SO_REUSEADDR 16 /**< Reuse addresses */ +#define APR_SO_SNDBUF 64 /**< Send buffer */ +#define APR_SO_RCVBUF 128 /**< Receive buffer */ +#define APR_SO_DISCONNECTED 256 /**< Disconnected */ +#define APR_TCP_NODELAY 512 /**< For SCTP sockets, this is mapped + * to STCP_NODELAY internally. + */ +#define APR_TCP_NOPUSH 1024 /**< No push */ +#define APR_RESET_NODELAY 2048 /**< This flag is ONLY set internally + * when we set APR_TCP_NOPUSH with + * APR_TCP_NODELAY set to tell us that + * APR_TCP_NODELAY should be turned on + * again when NOPUSH is turned off + */ +#define APR_INCOMPLETE_READ 4096 /**< Set on non-blocking sockets + * (timeout != 0) on which the + * previous read() did not fill a buffer + * completely. the next apr_socket_recv() + * will first call select()/poll() rather than + * going straight into read(). (Can also + * be set by an application to force a + * select()/poll() call before the next + * read, in cases where the app expects + * that an immediate read would fail.) + */ +#define APR_INCOMPLETE_WRITE 8192 /**< like APR_INCOMPLETE_READ, but for write + * @see APR_INCOMPLETE_READ + */ +#define APR_IPV6_V6ONLY 16384 /**< Don't accept IPv4 connections on an + * IPv6 listening socket. + */ +#define APR_TCP_DEFER_ACCEPT 32768 /**< Delay accepting of new connections + * until data is available. + * @see apr_socket_accept_filter + */ + +/** @} */ + +/** Define what type of socket shutdown should occur. */ +typedef enum { + APR_SHUTDOWN_READ, /**< no longer allow read request */ + APR_SHUTDOWN_WRITE, /**< no longer allow write requests */ + APR_SHUTDOWN_READWRITE /**< no longer allow read or write requests */ +} apr_shutdown_how_e; + +#define APR_IPV4_ADDR_OK 0x01 /**< @see apr_sockaddr_info_get() */ +#define APR_IPV6_ADDR_OK 0x02 /**< @see apr_sockaddr_info_get() */ + +#if (!APR_HAVE_IN_ADDR) +/** + * We need to make sure we always have an in_addr type, so APR will just + * define it ourselves, if the platform doesn't provide it. + */ +struct in_addr { + apr_uint32_t s_addr; /**< storage to hold the IP# */ +}; +#endif + +/** @def APR_INADDR_NONE + * Not all platforms have a real INADDR_NONE. This macro replaces + * INADDR_NONE on all platforms. + */ +#ifdef INADDR_NONE +#define APR_INADDR_NONE INADDR_NONE +#else +#define APR_INADDR_NONE ((unsigned int) 0xffffffff) +#endif + +/** + * @def APR_INET + * Not all platforms have these defined, so we'll define them here + * The default values come from FreeBSD 4.1.1 + */ +#define APR_INET AF_INET +/** @def APR_UNSPEC + * Let the system decide which address family to use + */ +#ifdef AF_UNSPEC +#define APR_UNSPEC AF_UNSPEC +#else +#define APR_UNSPEC 0 +#endif +#if APR_HAVE_IPV6 +/** @def APR_INET6 +* IPv6 Address Family. Not all platforms may have this defined. +*/ + +#define APR_INET6 AF_INET6 +#endif + +/** + * @defgroup IP_Proto IP Protocol Definitions for use when creating sockets + * @{ + */ +#define APR_PROTO_TCP 6 /**< TCP */ +#define APR_PROTO_UDP 17 /**< UDP */ +#define APR_PROTO_SCTP 132 /**< SCTP */ +/** @} */ + +/** + * Enum to tell us if we're interested in remote or local socket + */ +typedef enum { + APR_LOCAL, + APR_REMOTE +} apr_interface_e; + +/** + * The specific declaration of inet_addr's ... some platforms fall back + * inet_network (this is not good, but necessary) + */ + +#if APR_HAVE_INET_ADDR +#define apr_inet_addr inet_addr +#elif APR_HAVE_INET_NETWORK /* only DGUX, as far as I know */ +/** + * @warning + * not generally safe... inet_network() and inet_addr() perform + * different functions */ +#define apr_inet_addr inet_network +#endif + +/** A structure to represent sockets */ +typedef struct apr_socket_t apr_socket_t; +/** + * A structure to encapsulate headers and trailers for apr_socket_sendfile + */ +typedef struct apr_hdtr_t apr_hdtr_t; +/** A structure to represent in_addr */ +typedef struct in_addr apr_in_addr_t; +/** A structure to represent an IP subnet */ +typedef struct apr_ipsubnet_t apr_ipsubnet_t; + +/** @remark use apr_uint16_t just in case some system has a short that isn't 16 bits... */ +typedef apr_uint16_t apr_port_t; + +/** @remark It's defined here as I think it should all be platform safe... + * @see apr_sockaddr_t + */ +typedef struct apr_sockaddr_t apr_sockaddr_t; +/** + * APRs socket address type, used to ensure protocol independence + */ +struct apr_sockaddr_t { + /** The pool to use... */ + apr_pool_t *pool; + /** The hostname */ + char *hostname; + /** Either a string of the port number or the service name for the port */ + char *servname; + /** The numeric port */ + apr_port_t port; + /** The family */ + apr_int32_t family; + /** How big is the sockaddr we're using? */ + apr_socklen_t salen; + /** How big is the ip address structure we're using? */ + int ipaddr_len; + /** How big should the address buffer be? 16 for v4 or 46 for v6 + * used in inet_ntop... */ + int addr_str_len; + /** This points to the IP address structure within the appropriate + * sockaddr structure. */ + void *ipaddr_ptr; + /** If multiple addresses were found by apr_sockaddr_info_get(), this + * points to a representation of the next address. */ + apr_sockaddr_t *next; + /** Union of either IPv4 or IPv6 sockaddr. */ + union { + /** IPv4 sockaddr structure */ + struct sockaddr_in sin; +#if APR_HAVE_IPV6 + /** IPv6 sockaddr structure */ + struct sockaddr_in6 sin6; +#endif +#if APR_HAVE_SA_STORAGE + /** Placeholder to ensure that the size of this union is not + * dependent on whether APR_HAVE_IPV6 is defined. */ + struct sockaddr_storage sas; +#endif + } sa; +}; + +#if APR_HAS_SENDFILE +/** + * Support reusing the socket on platforms which support it (from disconnect, + * specifically Win32. + * @remark Optional flag passed into apr_socket_sendfile() + */ +#define APR_SENDFILE_DISCONNECT_SOCKET 1 +#endif + +/** A structure to encapsulate headers and trailers for apr_socket_sendfile */ +struct apr_hdtr_t { + /** An iovec to store the headers sent before the file. */ + struct iovec* headers; + /** number of headers in the iovec */ + int numheaders; + /** An iovec to store the trailers sent after the file. */ + struct iovec* trailers; + /** number of trailers in the iovec */ + int numtrailers; +}; + +/* function definitions */ + +/** + * Create a socket. + * @param new_sock The new socket that has been set up. + * @param family The address family of the socket (e.g., APR_INET). + * @param type The type of the socket (e.g., SOCK_STREAM). + * @param protocol The protocol of the socket (e.g., APR_PROTO_TCP). + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new_sock, + int family, int type, + int protocol, + apr_pool_t *cont); + +/** + * Shutdown either reading, writing, or both sides of a socket. + * @param thesocket The socket to close + * @param how How to shutdown the socket. One of: + *
    + *            APR_SHUTDOWN_READ         no longer allow read requests
    + *            APR_SHUTDOWN_WRITE        no longer allow write requests
    + *            APR_SHUTDOWN_READWRITE    no longer allow read or write requests 
    + * 
    + * @see apr_shutdown_how_e + * @remark This does not actually close the socket descriptor, it just + * controls which calls are still valid on the socket. + */ +APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how); + +/** + * Close a socket. + * @param thesocket The socket to close + */ +APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket); + +/** + * Bind the socket to its associated port + * @param sock The socket to bind + * @param sa The socket address to bind to + * @remark This may be where we will find out if there is any other process + * using the selected port. + */ +APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa); + +/** + * Listen to a bound socket for connections. + * @param sock The socket to listen on + * @param backlog The number of outstanding connections allowed in the sockets + * listen queue. If this value is less than zero, the listen + * queue size is set to zero. + */ +APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog); + +/** + * Accept a new connection request + * @param new_sock A copy of the socket that is connected to the socket that + * made the connection request. This is the socket which should + * be used for all future communication. + * @param sock The socket we are listening on. + * @param connection_pool The pool for the new socket. + */ +APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new_sock, + apr_socket_t *sock, + apr_pool_t *connection_pool); + +/** + * Issue a connection request to a socket either on the same machine + * or a different one. + * @param sock The socket we wish to use for our side of the connection + * @param sa The address of the machine we wish to connect to. + */ +APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa); + +/** + * Create apr_sockaddr_t from hostname, address family, and port. + * @param sa The new apr_sockaddr_t. + * @param hostname The hostname or numeric address string to resolve/parse, or + * NULL to build an address that corresponds to 0.0.0.0 or :: + * @param family The address family to use, or APR_UNSPEC if the system should + * decide. + * @param port The port number. + * @param flags Special processing flags: + *
    + *       APR_IPV4_ADDR_OK          first query for IPv4 addresses; only look
    + *                                 for IPv6 addresses if the first query failed;
    + *                                 only valid if family is APR_UNSPEC and hostname
    + *                                 isn't NULL; mutually exclusive with
    + *                                 APR_IPV6_ADDR_OK
    + *       APR_IPV6_ADDR_OK          first query for IPv6 addresses; only look
    + *                                 for IPv4 addresses if the first query failed;
    + *                                 only valid if family is APR_UNSPEC and hostname
    + *                                 isn't NULL and APR_HAVE_IPV6; mutually exclusive
    + *                                 with APR_IPV4_ADDR_OK
    + * 
    + * @param p The pool for the apr_sockaddr_t and associated storage. + */ +APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa, + const char *hostname, + apr_int32_t family, + apr_port_t port, + apr_int32_t flags, + apr_pool_t *p); + +/** + * Look up the host name from an apr_sockaddr_t. + * @param hostname The hostname. + * @param sa The apr_sockaddr_t. + * @param flags Special processing flags. + */ +APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname, + apr_sockaddr_t *sa, + apr_int32_t flags); + +/** + * Parse hostname/IP address with scope id and port. + * + * Any of the following strings are accepted: + * 8080 (just the port number) + * www.apache.org (just the hostname) + * www.apache.org:8080 (hostname and port number) + * [fe80::1]:80 (IPv6 numeric address string only) + * [fe80::1%eth0] (IPv6 numeric address string and scope id) + * + * Invalid strings: + * (empty string) + * [abc] (not valid IPv6 numeric address string) + * abc:65536 (invalid port number) + * + * @param addr The new buffer containing just the hostname. On output, *addr + * will be NULL if no hostname/IP address was specfied. + * @param scope_id The new buffer containing just the scope id. On output, + * *scope_id will be NULL if no scope id was specified. + * @param port The port number. On output, *port will be 0 if no port was + * specified. + * ### FIXME: 0 is a legal port (per RFC 1700). this should + * ### return something besides zero if the port is missing. + * @param str The input string to be parsed. + * @param p The pool from which *addr and *scope_id are allocated. + * @remark If scope id shouldn't be allowed, check for scope_id != NULL in + * addition to checking the return code. If addr/hostname should be + * required, check for addr == NULL in addition to checking the + * return code. + */ +APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr, + char **scope_id, + apr_port_t *port, + const char *str, + apr_pool_t *p); + +/** + * Get name of the current machine + * @param buf A buffer to store the hostname in. + * @param len The maximum length of the hostname that can be stored in the + * buffer provided. The suggested length is APRMAXHOSTLEN + 1. + * @param cont The pool to use. + * @remark If the buffer was not large enough, an error will be returned. + */ +APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len, apr_pool_t *cont); + +/** + * Return the data associated with the current socket + * @param data The user data associated with the socket. + * @param key The key to associate with the user data. + * @param sock The currently open socket. + */ +APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock); + +/** + * Set the data associated with the current socket. + * @param sock The currently open socket. + * @param data The user data to associate with the socket. + * @param key The key to associate with the data. + * @param cleanup The cleanup to call when the socket is destroyed. + */ +APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, + const char *key, + apr_status_t (*cleanup)(void*)); + +/** + * Send data over a network. + * @param sock The socket to send the data over. + * @param buf The buffer which contains the data to be sent. + * @param len On entry, the number of bytes to send; on exit, the number + * of bytes sent. + * @remark + *
    + * This functions acts like a blocking write by default.  To change 
    + * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
    + * socket option.
    + *
    + * It is possible for both bytes to be sent and an error to be returned.
    + *
    + * APR_EINTR is never returned.
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len); + +/** + * Send multiple packets of data over a network. + * @param sock The socket to send the data over. + * @param vec The array of iovec structs containing the data to send + * @param nvec The number of iovec structs in the array + * @param len Receives the number of bytes actually written + * @remark + *
    + * This functions acts like a blocking write by default.  To change 
    + * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
    + * socket option.
    + * The number of bytes actually sent is stored in argument 3.
    + *
    + * It is possible for both bytes to be sent and an error to be returned.
    + *
    + * APR_EINTR is never returned.
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len); + +/** + * @param sock The socket to send from + * @param where The apr_sockaddr_t describing where to send the data + * @param flags The flags to use + * @param buf The data to send + * @param len The length of the data to send + */ +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len); + +/** + * @param from The apr_sockaddr_t to fill in the recipient info + * @param sock The socket to use + * @param flags The flags to use + * @param buf The buffer to use + * @param len The length of the available buffer + */ + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len); + +#if APR_HAS_SENDFILE || defined(DOXYGEN) + +/** + * Send a file from an open file descriptor to a socket, along with + * optional headers and trailers + * @param sock The socket to which we're writing + * @param file The open file from which to read + * @param hdtr A structure containing the headers and trailers to send + * @param offset Offset into the file where we should begin writing + * @param len (input) - Number of bytes to send from the file + * (output) - Number of bytes actually sent, + * including headers, file, and trailers + * @param flags APR flags that are mapped to OS specific flags + * @remark This functions acts like a blocking write by default. To change + * this behavior, use apr_socket_timeout_set() or the + * APR_SO_NONBLOCK socket option. + * The number of bytes actually sent is stored in the len parameter. + * The offset parameter is passed by reference for no reason; its + * value will never be modified by the apr_socket_sendfile() function. + */ +APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, + apr_file_t *file, + apr_hdtr_t *hdtr, + apr_off_t *offset, + apr_size_t *len, + apr_int32_t flags); + +#endif /* APR_HAS_SENDFILE */ + +/** + * Read data from a network. + * @param sock The socket to read the data from. + * @param buf The buffer to store the data in. + * @param len On entry, the number of bytes to receive; on exit, the number + * of bytes received. + * @remark + *
    + * This functions acts like a blocking read by default.  To change 
    + * this behavior, use apr_socket_timeout_set() or the APR_SO_NONBLOCK
    + * socket option.
    + * The number of bytes actually received is stored in argument 3.
    + *
    + * It is possible for both bytes to be received and an APR_EOF or
    + * other error to be returned.
    + *
    + * APR_EINTR is never returned.
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, + char *buf, apr_size_t *len); + +/** + * Setup socket options for the specified socket + * @param sock The socket to set up. + * @param opt The option we would like to configure. One of: + *
    + *            APR_SO_DEBUG      --  turn on debugging information 
    + *            APR_SO_KEEPALIVE  --  keep connections active
    + *            APR_SO_LINGER     --  lingers on close if data is present
    + *            APR_SO_NONBLOCK   --  Turns blocking on/off for socket
    + *                                  When this option is enabled, use
    + *                                  the APR_STATUS_IS_EAGAIN() macro to
    + *                                  see if a send or receive function
    + *                                  could not transfer data without
    + *                                  blocking.
    + *            APR_SO_REUSEADDR  --  The rules used in validating addresses
    + *                                  supplied to bind should allow reuse
    + *                                  of local addresses.
    + *            APR_SO_SNDBUF     --  Set the SendBufferSize
    + *            APR_SO_RCVBUF     --  Set the ReceiveBufferSize
    + * 
    + * @param on Value for the option. + */ +APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on); + +/** + * Setup socket timeout for the specified socket + * @param sock The socket to set up. + * @param t Value for the timeout. + *
    + *   t > 0  -- read and write calls return APR_TIMEUP if specified time
    + *             elapsess with no data read or written
    + *   t == 0 -- read and write calls never block
    + *   t < 0  -- read and write calls block
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, + apr_interval_time_t t); + +/** + * Query socket options for the specified socket + * @param sock The socket to query + * @param opt The option we would like to query. One of: + *
    + *            APR_SO_DEBUG      --  turn on debugging information 
    + *            APR_SO_KEEPALIVE  --  keep connections active
    + *            APR_SO_LINGER     --  lingers on close if data is present
    + *            APR_SO_NONBLOCK   --  Turns blocking on/off for socket
    + *            APR_SO_REUSEADDR  --  The rules used in validating addresses
    + *                                  supplied to bind should allow reuse
    + *                                  of local addresses.
    + *            APR_SO_SNDBUF     --  Set the SendBufferSize
    + *            APR_SO_RCVBUF     --  Set the ReceiveBufferSize
    + *            APR_SO_DISCONNECTED -- Query the disconnected state of the socket.
    + *                                  (Currently only used on Windows)
    + * 
    + * @param on Socket option returned on the call. + */ +APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on); + +/** + * Query socket timeout for the specified socket + * @param sock The socket to query + * @param t Socket timeout returned from the query. + */ +APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, + apr_interval_time_t *t); + +/** + * Query the specified socket if at the OOB/Urgent data mark + * @param sock The socket to query + * @param atmark Is set to true if socket is at the OOB/urgent mark, + * otherwise is set to false. + */ +APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, + int *atmark); + +/** + * Return an apr_sockaddr_t from an apr_socket_t + * @param sa The returned apr_sockaddr_t. + * @param which Which interface do we want the apr_sockaddr_t for? + * @param sock The socket to use + */ +APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa, + apr_interface_e which, + apr_socket_t *sock); + +/** + * Return the IP address (in numeric address string format) in + * an APR socket address. APR will allocate storage for the IP address + * string from the pool of the apr_sockaddr_t. + * @param addr The IP address. + * @param sockaddr The socket address to reference. + */ +APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr); + +/** + * See if the IP addresses in two APR socket addresses are + * equivalent. Appropriate logic is present for comparing + * IPv4-mapped IPv6 addresses with IPv4 addresses. + * + * @param addr1 One of the APR socket addresses. + * @param addr2 The other APR socket address. + * @remark The return value will be non-zero if the addresses + * are equivalent. + */ +APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1, + const apr_sockaddr_t *addr2); + +/** +* Return the type of the socket. +* @param sock The socket to query. +* @param type The returned type (e.g., SOCK_STREAM). +*/ +APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, + int *type); + +/** + * Given an apr_sockaddr_t and a service name, set the port for the service + * @param sockaddr The apr_sockaddr_t that will have its port set + * @param servname The name of the service you wish to use + */ +APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr, + const char *servname); +/** + * Build an ip-subnet representation from an IP address and optional netmask or + * number-of-bits. + * @param ipsub The new ip-subnet representation + * @param ipstr The input IP address string + * @param mask_or_numbits The input netmask or number-of-bits string, or NULL + * @param p The pool to allocate from + */ +APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, + const char *ipstr, + const char *mask_or_numbits, + apr_pool_t *p); + +/** + * Test the IP address in an apr_sockaddr_t against a pre-built ip-subnet + * representation. + * @param ipsub The ip-subnet representation + * @param sa The socket address to test + * @return non-zero if the socket address is within the subnet, 0 otherwise + */ +APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa); + +#if APR_HAS_SO_ACCEPTFILTER || defined(DOXYGEN) +/** + * Set an OS level accept filter. + * @param sock The socket to put the accept filter on. + * @param name The accept filter + * @param args Any extra args to the accept filter. Passing NULL here removes + * the accept filter. + */ +apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *name, + char *args); +#endif + +/** + * Return the protocol of the socket. + * @param sock The socket to query. + * @param protocol The returned protocol (e.g., APR_PROTO_TCP). + */ +APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, + int *protocol); + +/** + * Set a socket to be inherited by child processes. + */ +APR_DECLARE_INHERIT_SET(socket); + +/** + * Unset a socket from being inherited by child processes. + */ +APR_DECLARE_INHERIT_UNSET(socket); + +/** + * @defgroup apr_mcast IP Multicast + * @{ + */ + +/** + * Join a Multicast Group + * @param sock The socket to join a multicast group + * @param join The address of the multicast group to join + * @param iface Address of the interface to use. If NULL is passed, the + * default multicast interface will be used. (OS Dependent) + * @param source Source Address to accept transmissions from (non-NULL + * implies Source-Specific Multicast) + */ +APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock, + apr_sockaddr_t *join, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); + +/** + * Leave a Multicast Group. All arguments must be the same as + * apr_mcast_join. + * @param sock The socket to leave a multicast group + * @param addr The address of the multicast group to leave + * @param iface Address of the interface to use. If NULL is passed, the + * default multicast interface will be used. (OS Dependent) + * @param source Source Address to accept transmissions from (non-NULL + * implies Source-Specific Multicast) + */ +APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock, + apr_sockaddr_t *addr, + apr_sockaddr_t *iface, + apr_sockaddr_t *source); + +/** + * Set the Multicast Time to Live (ttl) for a multicast transmission. + * @param sock The socket to set the multicast ttl + * @param ttl Time to live to Assign. 0-255, default=1 + * @remark If the TTL is 0, packets will only be seen by sockets on + * the local machine, and only when multicast loopback is enabled. + */ +APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock, + apr_byte_t ttl); + +/** + * Toggle IP Multicast Loopback + * @param sock The socket to set multicast loopback + * @param opt 0=disable, 1=enable + */ +APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock, + apr_byte_t opt); + + +/** + * Set the Interface to be used for outgoing Multicast Transmissions. + * @param sock The socket to set the multicast interface on + * @param iface Address of the interface to use for Multicast + */ +APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock, + apr_sockaddr_t *iface); + +/** @} */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_NETWORK_IO_H */ + diff --git a/srclib/apr/include/apr_poll.h b/srclib/apr/include/apr_poll.h new file mode 100644 index 0000000000..c9c5973041 --- /dev/null +++ b/srclib/apr/include/apr_poll.h @@ -0,0 +1,176 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_POLL_H +#define APR_POLL_H +/** + * @file apr_poll.h + * @brief APR Poll interface + */ +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_inherit.h" +#include "apr_file_io.h" +#include "apr_network_io.h" + +#if APR_HAVE_NETINET_IN_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_poll Poll Routines + * @ingroup APR + * @{ + */ + +/** + * Poll options + */ +#define APR_POLLIN 0x001 /**< Can read without blocking */ +#define APR_POLLPRI 0x002 /**< Priority data available */ +#define APR_POLLOUT 0x004 /**< Can write without blocking */ +#define APR_POLLERR 0x010 /**< Pending error */ +#define APR_POLLHUP 0x020 /**< Hangup occurred */ +#define APR_POLLNVAL 0x040 /**< Descriptior invalid */ + +/** + * Pollset Flags + */ +#define APR_POLLSET_THREADSAFE 0x001 /**< Adding or Removing a Descriptor is thread safe */ + +/** Used in apr_pollfd_t to determine what the apr_descriptor is */ +typedef enum { + APR_NO_DESC, /**< nothing here */ + APR_POLL_SOCKET, /**< descriptor refers to a socket */ + APR_POLL_FILE, /**< descriptor refers to a file */ + APR_POLL_LASTDESC /**< descriptor is the last one in the list */ +} apr_datatype_e ; + +/** Union of either an APR file or socket. */ +typedef union { + apr_file_t *f; /**< file */ + apr_socket_t *s; /**< socket */ +} apr_descriptor; + +/** @see apr_pollfd_t */ +typedef struct apr_pollfd_t apr_pollfd_t; + +/** Poll descriptor set. */ +struct apr_pollfd_t { + apr_pool_t *p; /**< associated pool */ + apr_datatype_e desc_type; /**< descriptor type */ + apr_int16_t reqevents; /**< requested events */ + apr_int16_t rtnevents; /**< returned events */ + apr_descriptor desc; /**< @see apr_descriptor */ + void *client_data; /**< allows app to associate context */ +}; + + +/* General-purpose poll API for arbitrarily large numbers of + * file descriptors + */ + +/** Opaque structure used for pollset API */ +typedef struct apr_pollset_t apr_pollset_t; + +/** + * Setup a pollset object + * @param pollset The pointer in which to return the newly created object + * @param size The maximum number of descriptors that this pollset can hold + * @param p The pool from which to allocate the pollset + * @param flags Optional flags to modify the operation of the pollset. + * + * @remark If flags equals APR_POLLSET_THREADSAFE, then a pollset is + * created on which it is safe to make concurrent calls to + * apr_pollset_add(), apr_pollset_remove() and apr_pollset_poll() from + * separate threads. This feature is only supported on some + * platforms; the apr_pollset_create() call will fail with + * APR_ENOTIMPL on platforms where it is not supported. + */ +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags); + +/** + * Destroy a pollset object + * @param pollset The pollset to destroy + */ +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset); + +/** + * Add a socket or file descriptor to a pollset + * @param pollset The pollset to which to add the descriptor + * @param descriptor The descriptor to add + * @remark If you set client_data in the descriptor, that value + * will be returned in the client_data field whenever this + * descriptor is signalled in apr_pollset_poll(). + */ +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor); + +/** + * Remove a descriptor from a pollset + * @param pollset The pollset from which to remove the descriptor + * @param descriptor The descriptor to remove + */ +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor); + +/** + * Block for activity on the descriptor(s) in a pollset + * @param pollset The pollset to use + * @param timeout Timeout in microseconds + * @param num Number of signalled descriptors (output parameter) + * @param descriptors Array of signalled descriptors (output parameter) + */ +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors); + + +/** + * Poll the sockets in the poll structure + * @param aprset The poll structure we will be using. + * @param numsock The number of sockets we are polling + * @param nsds The number of sockets signalled. + * @param timeout The amount of time in microseconds to wait. This is + * a maximum, not a minimum. If a socket is signalled, we + * will wake up before this time. A negative number means + * wait until a socket is signalled. + * @remark The number of sockets signalled is returned in the third argument. + * This is a blocking call, and it will not return until either a + * socket has been signalled, or the timeout has expired. + */ +APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t numsock, + apr_int32_t *nsds, + apr_interval_time_t timeout); + +/** @} */ + + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_POLL_H */ + diff --git a/srclib/apr/include/apr_pools.h b/srclib/apr/include/apr_pools.h new file mode 100644 index 0000000000..7b6daa351b --- /dev/null +++ b/srclib/apr/include/apr_pools.h @@ -0,0 +1,652 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_POOLS_H +#define APR_POOLS_H + +/** + * @file apr_pools.h + * @brief APR memory allocation + * + * Resource allocation routines... + * + * designed so that we don't have to keep track of EVERYTHING so that + * it can be explicitly freed later (a fundamentally unsound strategy --- + * particularly in the presence of die()). + * + * Instead, we maintain pools, and allocate items (both memory and I/O + * handlers) from the pools --- currently there are two, one for per + * transaction info, and one for config info. When a transaction is over, + * we can delete everything in the per-transaction apr_pool_t without fear, + * and without thinking too hard about it either. + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_general.h" /* for APR_STRINGIFY */ +#define APR_WANT_MEMFUNC /**< for no good reason? */ +#include "apr_want.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup apr_pools Memory Pool Functions + * @ingroup APR + * @{ + */ + +/** The fundamental pool type */ +typedef struct apr_pool_t apr_pool_t; + + +/** + * Declaration helper macro to construct apr_foo_pool_get()s. + * + * This standardized macro is used by opaque (APR) data types to return + * the apr_pool_t that is associated with the data type. + * + * APR_POOL_DECLARE_ACCESSOR() is used in a header file to declare the + * accessor function. A typical usage and result would be: + *
    + *    APR_POOL_DECLARE_ACCESSOR(file);
    + * becomes:
    + *    APR_DECLARE(apr_pool_t *) apr_file_pool_get(apr_file_t *ob);
    + * 
    + * @remark Doxygen unwraps this macro (via doxygen.conf) to provide + * actual help for each specific occurance of apr_foo_pool_get. + * @remark the linkage is specified for APR. It would be possible to expand + * the macros to support other linkages. + */ +#define APR_POOL_DECLARE_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) + +/** + * Implementation helper macro to provide apr_foo_pool_get()s. + * + * In the implementation, the APR_POOL_IMPLEMENT_ACCESSOR() is used to + * actually define the function. It assumes the field is named "pool". + */ +#define APR_POOL_IMPLEMENT_ACCESSOR(type) \ + APR_DECLARE(apr_pool_t *) apr_##type##_pool_get \ + (const apr_##type##_t *the##type) \ + { return the##type->pool; } + + +/** + * Pool debug levels + * + *
    + * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
    + * ---------------------------------
    + * |   |   |   |   |   |   |   | x |  General debug code enabled (useful in
    + *                                    combination with --with-efence).
    + *
    + * |   |   |   |   |   |   | x |   |  Verbose output on stderr (report
    + *                                    CREATE, CLEAR, DESTROY).
    + *
    + * |   |   |   | x |   |   |   |   |  Verbose output on stderr (report
    + *                                    PALLOC, PCALLOC).
    + *
    + * |   |   |   |   |   | x |   |   |  Lifetime checking. On each use of a
    + *                                    pool, check its lifetime.  If the pool
    + *                                    is out of scope, abort().
    + *                                    In combination with the verbose flag
    + *                                    above, it will output LIFE in such an
    + *                                    event prior to aborting.
    + *
    + * |   |   |   |   | x |   |   |   |  Pool owner checking.  On each use of a
    + *                                    pool, check if the current thread is the
    + *                                    pools owner.  If not, abort().  In
    + *                                    combination with the verbose flag above,
    + *                                    it will output OWNER in such an event
    + *                                    prior to aborting.  Use the debug
    + *                                    function apr_pool_owner_set() to switch
    + *                                    a pools ownership.
    + *
    + * When no debug level was specified, assume general debug mode.
    + * If level 0 was specified, debugging is switched off
    + * 
    + */ +#if defined(APR_POOL_DEBUG) +/* If APR_POOL_DEBUG is blank, we get 1; if it is a number, we get -1. */ +#if (APR_POOL_DEBUG - APR_POOL_DEBUG -1 == 1) +#undef APR_POOL_DEBUG +#define APR_POOL_DEBUG 1 +#endif +#else +#define APR_POOL_DEBUG 0 +#endif + +/** the place in the code where the particular function was called */ +#define APR_POOL__FILE_LINE__ __FILE__ ":" APR_STRINGIFY(__LINE__) + + + +/** A function that is called when allocation fails. */ +typedef int (*apr_abortfunc_t)(int retcode); + +/* + * APR memory structure manipulators (pools, tables, and arrays). + */ + +/* + * Initialization + */ + +/** + * Setup all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_initialize. + * @internal + */ +APR_DECLARE(apr_status_t) apr_pool_initialize(void); + +/** + * Tear down all of the internal structures required to use pools + * @remark Programs do NOT need to call this directly. APR will call this + * automatically from apr_terminate. + * @internal + */ +APR_DECLARE(void) apr_pool_terminate(void); + + +/* + * Pool creation/destruction + */ + +#include "apr_allocator.h" + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + * @param abort_fn A function to use if the pool cannot allocate more memory. + * @param allocator The allocator to use with the new pool. If NULL the + * allocator of the parent pool will be used. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); + +/** + * Debug version of apr_pool_create_ex. + * @param newpool @see apr_pool_create. + * @param parent @see apr_pool_create. + * @param abort_fn @see apr_pool_create. + * @param allocator @see apr_pool_create. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have you apr_pool_create_ex + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_create_ex in a wrapper, trust the macro + * and don't call apr_pool_create_ex_debug directly. + */ +APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line); + +#if APR_POOL_DEBUG +#define apr_pool_create_ex(newpool, parent, abort_fn, allocator) \ + apr_pool_create_ex_debug(newpool, parent, abort_fn, allocator, \ + APR_POOL__FILE_LINE__) +#endif + +/** + * Create a new pool. + * @param newpool The pool we have just created. + * @param parent The parent pool. If this is NULL, the new pool is a root + * pool. If it is non-NULL, the new pool will inherit all + * of its parent pool's attributes, except the apr_pool_t will + * be a sub-pool. + */ +#if defined(DOXYGEN) +APR_DECLARE(apr_status_t) apr_pool_create(apr_pool_t **newpool, + apr_pool_t *parent); +#else +#if APR_POOL_DEBUG +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex_debug(newpool, parent, NULL, NULL, \ + APR_POOL__FILE_LINE__) +#else +#define apr_pool_create(newpool, parent) \ + apr_pool_create_ex(newpool, parent, NULL, NULL) +#endif +#endif + +/** + * Find the pools allocator + * @param pool The pool to get the allocator from. + */ +APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool); + +/** + * Clear all memory in the pool and run all the cleanups. This also destroys all + * subpools. + * @param p The pool to clear + * @remark This does not actually free the memory, it just allows the pool + * to re-use this memory for the next allocation. + * @see apr_pool_destroy() + */ +APR_DECLARE(void) apr_pool_clear(apr_pool_t *p); + +/** + * Debug version of apr_pool_clear. + * @param p See: apr_pool_clear. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have you apr_pool_clear + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_clear in a wrapper, trust the macro + * and don't call apr_pool_destroy_clear directly. + */ +APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *p, + const char *file_line); + +#if APR_POOL_DEBUG +#define apr_pool_clear(p) \ + apr_pool_clear_debug(p, APR_POOL__FILE_LINE__) +#endif + +/** + * Destroy the pool. This takes similar action as apr_pool_clear() and then + * frees all the memory. + * @param p The pool to destroy + * @remark This will actually free the memory + */ +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *p); + +/** + * Debug version of apr_pool_destroy. + * @param p See: apr_pool_destroy. + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @remark Only available when APR_POOL_DEBUG is defined. + * Call this directly if you have you apr_pool_destroy + * calls in a wrapper function and wish to override + * the file_line argument to reflect the caller of + * your wrapper function. If you do not have + * apr_pool_destroy in a wrapper, trust the macro + * and don't call apr_pool_destroy_debug directly. + */ +APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *p, + const char *file_line); + +#if APR_POOL_DEBUG +#define apr_pool_destroy(p) \ + apr_pool_destroy_debug(p, APR_POOL__FILE_LINE__) +#endif + + +/* + * Memory allocation + */ + +/** + * Allocate a block of memory from a pool + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +APR_DECLARE(void *) apr_palloc(apr_pool_t *p, apr_size_t size); + +/** + * Debug version of apr_palloc + * @param p See: apr_palloc + * @param size See: apr_palloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_palloc + */ +APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line); + +#if APR_POOL_DEBUG +#define apr_palloc(p, size) \ + apr_palloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + +/** + * Allocate a block of memory from a pool and set all of the memory to 0 + * @param p The pool to allocate from + * @param size The amount of memory to allocate + * @return The allocated memory + */ +#if defined(DOXYGEN) +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *p, apr_size_t size); +#elif !APR_POOL_DEBUG +#define apr_pcalloc(p, size) memset(apr_palloc(p, size), 0, size) +#endif + +/** + * Debug version of apr_pcalloc + * @param p See: apr_pcalloc + * @param size See: apr_pcalloc + * @param file_line Where the function is called from. + * This is usually APR_POOL__FILE_LINE__. + * @return See: apr_pcalloc + */ +APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *p, apr_size_t size, + const char *file_line); + +#if APR_POOL_DEBUG +#define apr_pcalloc(p, size) \ + apr_pcalloc_debug(p, size, APR_POOL__FILE_LINE__) +#endif + + +/* + * Pool Properties + */ + +/** + * Set the function to be called when an allocation failure occurs. + * @remark If the program wants APR to exit on a memory allocation error, + * then this function can be called to set the callback to use (for + * performing cleanup and then exiting). If this function is not called, + * then APR will return an error and expect the calling program to + * deal with the error accordingly. + */ +APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abortfunc, + apr_pool_t *pool); + +/** + * Get the abort function associated with the specified pool. + * @param pool The pool for retrieving the abort function. + * @return The abort function for the given pool. + */ +APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool); + +/** + * Get the parent pool of the specified pool. + * @param pool The pool for retrieving the parent pool. + * @return The parent of the given pool. + */ +APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool); + +/** + * Determine if pool a is an ancestor of pool b. + * @param a The pool to search + * @param b The pool to search for + * @return True if a is an ancestor of b, NULL is considered an ancestor + * of all pools. + * @remark if compiled with APR_POOL_DEBUG, this function will also + * return true if A is a pool which has been guaranteed by the caller + * (using apr_pool_join) to have a lifetime at least as long as some + * ancestor of pool B. + */ +APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b); + +/** + * Tag a pool (give it a name) + * @param pool The pool to tag + * @param tag The tag + */ +APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag); + + +/* + * User data management + */ + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @warning The data to be attached to the pool should have a life span + * at least as long as the pool it is being attached to. + * + * Users of APR must take EXTREME care when choosing a key to + * use for their data. It is possible to accidentally overwrite + * data by choosing a key that another part of the program is using. + * Therefore it is advised that steps are taken to ensure that unique + * keys are used for all of the userdata objects in a particular pool + * (the same key in two different pools or a pool and one of its + * subpools is okay) at all times. Careful namespace prefixing of + * key names is a typical way to help ensure this uniqueness. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_set( + const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool); + +/** + * Set the data associated with the current pool + * @param data The user data associated with the pool. + * @param key The key to use for association + * @param cleanup The cleanup program to use to cleanup the data (NULL if none) + * @param pool The current pool + * @note same as apr_pool_userdata_set(), except that this version doesn't + * make a copy of the key (this function is useful, for example, when + * the key is a string literal) + * @warning This should NOT be used if the key could change addresses by + * any means between the apr_pool_userdata_setn() call and a + * subsequent apr_pool_userdata_get() on that key, such as if a + * static string is used as a userdata key in a DSO and the DSO could + * be unloaded and reloaded between the _setn() and the _get(). You + * MUST use apr_pool_userdata_set() in such cases. + * @warning More generally, the key and the data to be attached to the + * pool should have a life span at least as long as the pool itself. + * + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_setn( + const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool); + +/** + * Return the data associated with the current pool. + * @param data The user data associated with the pool. + * @param key The key for the data to retrieve + * @param pool The current pool. + */ +APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool); + + +/* + * Cleanup + * + * Cleanups are performed in the reverse order they were registered. That is: + * Last In, First Out. A cleanup function can safely allocate memory from + * the pool that is being cleaned up. It can also safely register additional + * cleanups which will be run LIFO, directly after the current cleanup + * terminates. Cleanups have to take caution in calling functions that + * create subpools. Subpools, created during cleanup will NOT automatically + * be cleaned up. In other words, cleanups are to clean up after themselves. + */ + +/** + * Register a function to be called when a pool is cleared or destroyed + * @param p The pool register the cleanup with + * @param data The data to pass to the cleanup function. + * @param plain_cleanup The function to call when the pool is cleared + * or destroyed + * @param child_cleanup The function to call when a child process is about + * to exec - this function is called in the child, obviously! + */ +APR_DECLARE(void) apr_pool_cleanup_register( + apr_pool_t *p, + const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)); + +/** + * Remove a previously registered cleanup function + * @param p The pool remove the cleanup from + * @param data The data to remove from cleanup + * @param cleanup The function to remove from cleanup + * @remarks For some strange reason only the plain_cleanup is handled by this + * function + */ +APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup)(void *)); + +/** + * Replace the child cleanup of a previously registered cleanup + * @param p The pool of the registered cleanup + * @param data The data of the registered cleanup + * @param plain_cleanup The plain cleanup function of the registered cleanup + * @param child_cleanup The function to register as the child cleanup + */ +APR_DECLARE(void) apr_pool_child_cleanup_set( + apr_pool_t *p, + const void *data, + apr_status_t (*plain_cleanup)(void *), + apr_status_t (*child_cleanup)(void *)); + +/** + * Run the specified cleanup function immediately and unregister it. Use + * @a data instead of the data that was registered with the cleanup. + * @param p The pool remove the cleanup from + * @param data The data to remove from cleanup + * @param cleanup The function to remove from cleanup + */ +APR_DECLARE(apr_status_t) apr_pool_cleanup_run( + apr_pool_t *p, + void *data, + apr_status_t (*cleanup)(void *)); + +/** + * An empty cleanup function + * @param data The data to cleanup + */ +APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data); + +/* Preparing for exec() --- close files, etc., but *don't* flush I/O + * buffers, *don't* wait for subprocesses, and *don't* free any memory. + */ +/** + * Run all of the child_cleanups, so that any unnecessary files are + * closed because we are about to exec a new program + */ +APR_DECLARE(void) apr_pool_cleanup_for_exec(void); + + +/** + * @defgroup PoolDebug Pool Debugging functions. + * + * pools have nested lifetimes -- sub_pools are destroyed when the + * parent pool is cleared. We allow certain liberties with operations + * on things such as tables (and on other structures in a more general + * sense) where we allow the caller to insert values into a table which + * were not allocated from the table's pool. The table's data will + * remain valid as long as all the pools from which its values are + * allocated remain valid. + * + * For example, if B is a sub pool of A, and you build a table T in + * pool B, then it's safe to insert data allocated in A or B into T + * (because B lives at most as long as A does, and T is destroyed when + * B is cleared/destroyed). On the other hand, if S is a table in + * pool A, it is safe to insert data allocated in A into S, but it + * is *not safe* to insert data allocated from B into S... because + * B can be cleared/destroyed before A is (which would leave dangling + * pointers in T's data structures). + * + * In general we say that it is safe to insert data into a table T + * if the data is allocated in any ancestor of T's pool. This is the + * basis on which the APR_POOL_DEBUG code works -- it tests these ancestor + * relationships for all data inserted into tables. APR_POOL_DEBUG also + * provides tools (apr_pool_find, and apr_pool_is_ancestor) for other + * folks to implement similar restrictions for their own data + * structures. + * + * However, sometimes this ancestor requirement is inconvenient -- + * sometimes it's necessary to create a sub pool where the sub pool is + * guaranteed to have the same lifetime as the parent pool. This is a + * guarantee implemented by the *caller*, not by the pool code. That + * is, the caller guarantees they won't destroy the sub pool + * individually prior to destroying the parent pool. + * + * In this case the caller must call apr_pool_join() to indicate this + * guarantee to the APR_POOL_DEBUG code. + * + * These functions are only implemented when #APR_POOL_DEBUG is set. + * + * @{ + */ +#if APR_POOL_DEBUG || defined(DOXYGEN) +/** + * Guarantee that a subpool has the same lifetime as the parent. + * @param p The parent pool + * @param sub The subpool + */ +APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub); + +/** + * Find a pool from something allocated in it. + * @param mem The thing allocated in the pool + * @return The pool it is allocated in + */ +APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem); + +/** + * Report the number of bytes currently in the pool + * @param p The pool to inspect + * @param recurse Recurse/include the subpools' sizes + * @return The number of bytes + */ +APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *p, int recurse); + +/** + * Lock a pool + * @param pool The pool to lock + * @param flag The flag + */ +APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag); + +/* @} */ + +#else /* APR_POOL_DEBUG or DOXYGEN */ + +#ifdef apr_pool_join +#undef apr_pool_join +#endif +#define apr_pool_join(a,b) + +#ifdef apr_pool_lock +#undef apr_pool_lock +#endif +#define apr_pool_lock(pool, lock) + +#endif /* APR_POOL_DEBUG or DOXYGEN */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_POOLS_H */ diff --git a/srclib/apr/include/apr_portable.h b/srclib/apr/include/apr_portable.h new file mode 100644 index 0000000000..b37263b787 --- /dev/null +++ b/srclib/apr/include/apr_portable.h @@ -0,0 +1,506 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header file is where you should put ANY platform specific information. + * This should be the only header file that programs need to include that + * actually has platform dependant code which refers to the . + */ +#ifndef APR_PORTABLE_H +#define APR_PORTABLE_H +/** + * @file apr_portable.h + * @brief APR Portability Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_global_mutex.h" +#include "apr_proc_mutex.h" +#include "apr_time.h" +#include "apr_dso.h" +#include "apr_shm.h" + +#if APR_HAVE_DIRENT_H +#include +#endif +#if APR_HAVE_FCNTL_H +#include +#endif +#if APR_HAVE_PTHREAD_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_portabile Portability Routines + * @ingroup APR + * @{ + */ + +#ifdef WIN32 +/* The primitives for Windows types */ +typedef HANDLE apr_os_file_t; +typedef HANDLE apr_os_dir_t; +typedef SOCKET apr_os_sock_t; +typedef HANDLE apr_os_proc_mutex_t; +typedef HANDLE apr_os_thread_t; +typedef HANDLE apr_os_proc_t; +typedef DWORD apr_os_threadkey_t; +typedef FILETIME apr_os_imp_time_t; +typedef SYSTEMTIME apr_os_exp_time_t; +typedef HANDLE apr_os_dso_handle_t; +typedef HANDLE apr_os_shm_t; + +#elif defined(OS2) +typedef HFILE apr_os_file_t; +typedef HDIR apr_os_dir_t; +typedef int apr_os_sock_t; +typedef HMTX apr_os_proc_mutex_t; +typedef TID apr_os_thread_t; +typedef PID apr_os_proc_t; +typedef PULONG apr_os_threadkey_t; +typedef struct timeval apr_os_imp_time_t; +typedef struct tm apr_os_exp_time_t; +typedef HMODULE apr_os_dso_handle_t; +typedef void* apr_os_shm_t; + +#elif defined(__BEOS__) +#include +#include + +struct apr_os_proc_mutex_t { + sem_id sem; + int32 ben; +}; + +typedef int apr_os_file_t; +typedef DIR apr_os_dir_t; +typedef int apr_os_sock_t; +typedef struct apr_os_proc_mutex_t apr_os_proc_mutex_t; +typedef thread_id apr_os_thread_t; +typedef thread_id apr_os_proc_t; +typedef int apr_os_threadkey_t; +typedef struct timeval apr_os_imp_time_t; +typedef struct tm apr_os_exp_time_t; +typedef image_id apr_os_dso_handle_t; +typedef void* apr_os_shm_t; + +#elif defined(NETWARE) +typedef int apr_os_file_t; +typedef DIR apr_os_dir_t; +typedef int apr_os_sock_t; +typedef NXMutex_t apr_os_proc_mutex_t; +typedef NXThreadId_t apr_os_thread_t; +typedef long apr_os_proc_t; +typedef NXKey_t apr_os_threadkey_t; +typedef struct timeval apr_os_imp_time_t; +typedef struct tm apr_os_exp_time_t; +typedef void * apr_os_dso_handle_t; +typedef void* apr_os_shm_t; + +#else +/* Any other OS should go above this one. This is the lowest common + * denominator typedefs for all UNIX-like systems. :) + */ + +/** Basic OS process mutex structure. */ +struct apr_os_proc_mutex_t { +#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE + /** Value used for SYS V Semaphore, FCNTL and FLOCK serialization */ + int crossproc; +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + /** Value used for PTHREAD serialization */ + pthread_mutex_t *pthread_interproc; +#endif +#if APR_HAS_THREADS + /* If no threads, no need for thread locks */ +#if APR_USE_PTHREAD_SERIALIZE + /** This value is currently unused within APR and Apache */ + pthread_mutex_t *intraproc; +#endif +#endif +}; + +typedef int apr_os_file_t; /**< native file */ +typedef DIR apr_os_dir_t; /**< native dir */ +typedef int apr_os_sock_t; /**< native dir */ +typedef struct apr_os_proc_mutex_t apr_os_proc_mutex_t; /**< native proces + * mutex + */ +#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H +typedef pthread_t apr_os_thread_t; /**< native thread */ +typedef pthread_key_t apr_os_threadkey_t; /**< native thread address + * space */ +#endif +typedef pid_t apr_os_proc_t; /**< native pid */ +typedef struct timeval apr_os_imp_time_t; /**< native timeval */ +typedef struct tm apr_os_exp_time_t; /**< native tm */ +/** @var apr_os_dso_handle_t + * native dso types + */ +#if defined(HPUX) || defined(HPUX10) || defined(HPUX11) +#include +typedef shl_t apr_os_dso_handle_t; +#elif defined(DARWIN) +#include +typedef NSModule apr_os_dso_handle_t; +#else +typedef void * apr_os_dso_handle_t; +#endif +typedef void* apr_os_shm_t; /**< native SHM */ + +#endif + +/** + * @typedef apr_os_sock_info_t + * @brief alias for local OS socket + */ +/** + * everything APR needs to know about an active socket to construct + * an APR socket from it; currently, this is platform-independent + */ +struct apr_os_sock_info_t { + apr_os_sock_t *os_sock; /**< always required */ + struct sockaddr *local; /**< NULL if not yet bound */ + struct sockaddr *remote; /**< NULL if not connected */ + int family; /**< always required (APR_INET, APR_INET6, etc.) */ + int type; /**< always required (SOCK_STREAM, SOCK_DGRAM, etc.) */ + int protocol; /**< 0 or actual protocol (APR_PROTO_SCTP, APR_PROTO_TCP, etc.) */ +}; + +typedef struct apr_os_sock_info_t apr_os_sock_info_t; + +#if APR_PROC_MUTEX_IS_GLOBAL || defined(DOXYGEN) +/** Opaque global mutex type */ +#define apr_os_global_mutex_t apr_os_proc_mutex_t +/** @return apr_os_global_mutex */ +#define apr_os_global_mutex_get apr_os_proc_mutex_get +#else + /** Thread and process mutex for those platforms where process mutexes + * are not held in threads. + */ + struct apr_os_global_mutex_t { + apr_pool_t *pool; + apr_proc_mutex_t *proc_mutex; +#if APR_HAS_THREADS + apr_thread_mutex_t *thread_mutex; +#endif /* APR_HAS_THREADS */ + }; + typedef struct apr_os_global_mutex_t apr_os_global_mutex_t; + +APR_DECLARE(apr_status_t) apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex, + apr_global_mutex_t *pmutex); +#endif + + +/** + * convert the file from apr type to os specific type. + * @param thefile The os specific file we are converting to + * @param file The apr file to convert. + * @remark On Unix, it is only possible to get a file descriptor from + * an apr file type. + */ +APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file); + +/** + * convert the dir from apr type to os specific type. + * @param thedir The os specific dir we are converting to + * @param dir The apr dir to convert. + */ +APR_DECLARE(apr_status_t) apr_os_dir_get(apr_os_dir_t **thedir, + apr_dir_t *dir); + +/** + * Convert the socket from an apr type to an OS specific socket + * @param thesock The socket to convert. + * @param sock The os specifc equivelant of the apr socket.. + */ +APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, + apr_socket_t *sock); + +/** + * Convert the proc mutex from os specific type to apr type + * @param ospmutex The os specific proc mutex we are converting to. + * @param pmutex The apr proc mutex to convert. + */ +APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex); + +/** + * Get the exploded time in the platforms native format. + * @param ostime the native time format + * @param aprtime the time to convert + */ +APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime); + +/** + * Get the imploded time in the platforms native format. + * @param ostime the native time format + * @param aprtime the time to convert + */ +APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime); + +/** + * convert the shm from apr type to os specific type. + * @param osshm The os specific shm representation + * @param shm The apr shm to convert. + */ +APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm); + +#if APR_HAS_THREADS || defined(DOXYGEN) +/** + * @defgroup apr_os_thread Thread portability Routines + * @{ + */ +/** + * convert the thread to os specific type from apr type. + * @param thethd The apr thread to convert + * @param thd The os specific thread we are converting to + */ +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd); + +/** + * convert the thread private memory key to os specific type from an apr type. + * @param thekey The apr handle we are converting from. + * @param key The os specific handle we are converting to. + */ +APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key); + +/** + * convert the thread from os specific type to apr type. + * @param thd The apr thread we are converting to. + * @param thethd The os specific thread to convert + * @param cont The pool to use if it is needed. + */ +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *cont); + +/** + * convert the thread private memory key from os specific type to apr type. + * @param key The apr handle we are converting to. + * @param thekey The os specific handle to convert + * @param cont The pool to use if it is needed. + */ +APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *cont); +/** + * Get the thread ID + */ +APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void); + +/** + * Compare two thread id's + * @param tid1 1st Thread ID to compare + * @param tid2 2nd Thread ID to compare + */ +APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2); + +/** @} */ +#endif /* APR_HAS_THREADS */ + +/** + * convert the file from os specific type to apr type. + * @param file The apr file we are converting to. + * @param thefile The os specific file to convert + * @param flags The flags that were used to open this file. + * @param cont The pool to use if it is needed. + * @remark On Unix, it is only possible to put a file descriptor into + * an apr file type. + */ +APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, apr_pool_t *cont); + +/** + * convert the file from os specific type to apr type. + * @param file The apr file we are converting to. + * @param thefile The os specific pipe to convert + * @param cont The pool to use if it is needed. + * @remark On Unix, it is only possible to put a file descriptor into + * an apr file type. + */ +APR_DECLARE(apr_status_t) apr_os_pipe_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_pool_t *cont); + +/** + * convert the file from os specific type to apr type. + * @param file The apr file we are converting to. + * @param thefile The os specific pipe to convert + * @param register_cleanup A cleanup will be registered on the apr_file_t + * to issue apr_file_close(). + * @param cont The pool to use if it is needed. + * @remark On Unix, it is only possible to put a file descriptor into + * an apr file type. + */ +APR_DECLARE(apr_status_t) apr_os_pipe_put_ex(apr_file_t **file, + apr_os_file_t *thefile, + int register_cleanup, + apr_pool_t *cont); + +/** + * convert the dir from os specific type to apr type. + * @param dir The apr dir we are converting to. + * @param thedir The os specific dir to convert + * @param cont The pool to use when creating to apr directory. + */ +APR_DECLARE(apr_status_t) apr_os_dir_put(apr_dir_t **dir, + apr_os_dir_t *thedir, + apr_pool_t *cont); + +/** + * Convert a socket from the os specific type to the apr type + * @param sock The pool to use. + * @param thesock The socket to convert to. + * @param cont The socket we are converting to an apr type. + * @remark If it is a true socket, it is best to call apr_os_sock_make() + * and provide APR with more information about the socket. + */ +APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, + apr_os_sock_t *thesock, + apr_pool_t *cont); + +/** + * Create a socket from an existing descriptor and local and remote + * socket addresses. + * @param apr_sock The new socket that has been set up + * @param os_sock_info The os representation of the socket handle and + * other characteristics of the socket + * @param cont The pool to use + * @remark If you only know the descriptor/handle or if it isn't really + * a true socket, use apr_os_sock_put() instead. + */ +APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont); + +/** + * Convert the proc mutex from os specific type to apr type + * @param pmutex The apr proc mutex we are converting to. + * @param ospmutex The os specific proc mutex to convert. + * @param cont The pool to use if it is needed. + */ +APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *cont); + +/** + * Put the imploded time in the APR format. + * @param aprtime the APR time format + * @param ostime the time to convert + * @param cont the pool to use if necessary + */ +APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont); + +/** + * Put the exploded time in the APR format. + * @param aprtime the APR time format + * @param ostime the time to convert + * @param cont the pool to use if necessary + */ +APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont); + +/** + * convert the shared memory from os specific type to apr type. + * @param shm The apr shm representation of osshm + * @param osshm The os specific shm identity + * @param cont The pool to use if it is needed. + * @remark On fork()ed architectures, this is typically nothing more than + * the memory block mapped. On non-fork architectures, this is typically + * some internal handle to pass the mapping from process to process. + */ +APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **shm, + apr_os_shm_t *osshm, + apr_pool_t *cont); + + +#if APR_HAS_DSO || defined(DOXYGEN) +/** + * @defgroup apr_os_dso DSO (Dynamic Loading) Portabiliity Routines + * @{ + */ +/** + * convert the dso handle from os specific to apr + * @param dso The apr handle we are converting to + * @param thedso the os specific handle to convert + * @param pool the pool to use if it is needed + */ +APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **dso, + apr_os_dso_handle_t thedso, + apr_pool_t *pool); + +/** + * convert the apr dso handle into an os specific one + * @param aprdso The apr dso handle to convert + * @param dso The os specific dso to return + */ +APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *dso, + apr_dso_handle_t *aprdso); + +#if APR_HAS_OS_UUID +/** + * Private: apr-util's apr_uuid module when supported by the platform + */ +APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data); +#endif + +/** @} */ +#endif /* APR_HAS_DSO */ + + +/** + * Get the name of the system default characer set. + * @param pool the pool to allocate the name from, if needed + */ +APR_DECLARE(const char*) apr_os_default_encoding(apr_pool_t *pool); + + +/** + * Get the name of the current locale character set. + * @param pool the pool to allocate the name from, if needed + * @remark Defers to apr_os_default_encoding if the current locale's + * data can't be retreved on this system. + */ +APR_DECLARE(const char*) apr_os_locale_encoding(apr_pool_t *pool); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_PORTABLE_H */ diff --git a/srclib/apr/include/apr_proc_mutex.h b/srclib/apr/include/apr_proc_mutex.h new file mode 100644 index 0000000000..05c9f19650 --- /dev/null +++ b/srclib/apr/include/apr_proc_mutex.h @@ -0,0 +1,166 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_PROC_MUTEX_H +#define APR_PROC_MUTEX_H + +/** + * @file apr_proc_mutex.h + * @brief APR Process Locking Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_proc_mutex Process Locking Routines + * @ingroup APR + * @{ + */ + +/** + * Enumerated potential types for APR process locking methods + * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports + * APR_LOCK_foo. Only APR_LOCK_DEFAULT is portable. + */ +typedef enum { + APR_LOCK_FCNTL, /**< fcntl() */ + APR_LOCK_FLOCK, /**< flock() */ + APR_LOCK_SYSVSEM, /**< System V Semaphores */ + APR_LOCK_PROC_PTHREAD, /**< POSIX pthread process-based locking */ + APR_LOCK_POSIXSEM, /**< POSIX semaphore process-based locking */ + APR_LOCK_DEFAULT /**< Use the default process lock */ +} apr_lockmech_e; + +/** Opaque structure representing a process mutex. */ +typedef struct apr_proc_mutex_t apr_proc_mutex_t; + +/* Function definitions */ + +/** + * Create and initialize a mutex that can be used to synchronize processes. + * @param mutex the memory address where the newly created mutex will be + * stored. + * @param fname A file name to use if the lock mechanism requires one. This + * argument should always be provided. The lock code itself will + * determine if it should be used. + * @param mech The mechanism to use for the interprocess lock, if any; one of + *
    + *            APR_LOCK_FCNTL
    + *            APR_LOCK_FLOCK
    + *            APR_LOCK_SYSVSEM
    + *            APR_LOCK_POSIXSEM
    + *            APR_LOCK_PROC_PTHREAD
    + *            APR_LOCK_DEFAULT     pick the default mechanism for the platform
    + * 
    + * @param pool the pool from which to allocate the mutex. + * @see apr_lockmech_e + * @warning Check APR_HAS_foo_SERIALIZE defines to see if the platform supports + * APR_LOCK_foo. Only APR_LOCK_DEFAULT is portable. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool); + +/** + * Re-open a mutex in a child process. + * @param mutex The newly re-opened mutex structure. + * @param fname A file name to use if the mutex mechanism requires one. This + * argument should always be provided. The mutex code itself will + * determine if it should be used. This filename should be the + * same one that was passed to apr_proc_mutex_create(). + * @param pool The pool to operate on. + * @remark This function must be called to maintain portability, even + * if the underlying lock mechanism does not require it. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool); + +/** + * Acquire the lock for the given mutex. If the mutex is already locked, + * the current thread will be put to sleep until the lock becomes available. + * @param mutex the mutex on which to acquire the lock. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex); + +/** + * Attempt to acquire the lock for the given mutex. If the mutex has already + * been acquired, the call returns immediately with APR_EBUSY. Note: it + * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine + * if the return value was APR_EBUSY, for portability reasons. + * @param mutex the mutex on which to attempt the lock acquiring. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex); + +/** + * Release the lock for the given mutex. + * @param mutex the mutex from which to release the lock. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex); + +/** + * Destroy the mutex and free the memory associated with the lock. + * @param mutex the mutex to destroy. + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex); + +/** + * Destroy the mutex and free the memory associated with the lock. + * @param mutex the mutex to destroy. + * @note This function is generally used to kill a cleanup on an already + * created mutex + */ +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex); + +/** + * Return the name of the lockfile for the mutex, or NULL + * if the mutex doesn't use a lock file + */ + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex); + +/** + * Display the name of the mutex, as it relates to the actual method used. + * This matches the valid options for Apache's AcceptMutex directive + * @param mutex the name of the mutex + */ +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex); + +/** + * Display the name of the default mutex: APR_LOCK_DEFAULT + */ +APR_DECLARE(const char *) apr_proc_mutex_defname(void); + +/** + * Get the pool used by this proc_mutex. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(proc_mutex); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_PROC_MUTEX_H */ diff --git a/srclib/apr/include/apr_random.h b/srclib/apr/include/apr_random.h new file mode 100644 index 0000000000..b5c2baaa5d --- /dev/null +++ b/srclib/apr/include/apr_random.h @@ -0,0 +1,74 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_RANDOM_H +#define APR_RANDOM_H + +#include + +typedef struct apr_crypto_hash_t apr_crypto_hash_t; + +typedef void apr_crypto_hash_init_t(apr_crypto_hash_t *hash); +typedef void apr_crypto_hash_add_t(apr_crypto_hash_t *hash,const void *data, + apr_size_t bytes); +typedef void apr_crypto_hash_finish_t(apr_crypto_hash_t *hash, + unsigned char *result); + +/* FIXME: make this opaque */ +struct apr_crypto_hash_t { + apr_crypto_hash_init_t *init; + apr_crypto_hash_add_t *add; + apr_crypto_hash_finish_t *finish; + apr_size_t size; + void *data; +}; + +APR_DECLARE(apr_crypto_hash_t *) apr_crypto_sha256_new(apr_pool_t *p); + +typedef struct apr_random_t apr_random_t; + +APR_DECLARE(void) apr_random_init(apr_random_t *g,apr_pool_t *p, + apr_crypto_hash_t *pool_hash, + apr_crypto_hash_t *key_hash, + apr_crypto_hash_t *prng_hash); +APR_DECLARE(apr_random_t *) apr_random_standard_new(apr_pool_t *p); +APR_DECLARE(void) apr_random_add_entropy(apr_random_t *g, + const void *entropy_, + apr_size_t bytes); +APR_DECLARE(apr_status_t) apr_random_insecure_bytes(apr_random_t *g, + void *random, + apr_size_t bytes); +APR_DECLARE(apr_status_t) apr_random_secure_bytes(apr_random_t *g, + void *random, + apr_size_t bytes); +APR_DECLARE(void) apr_random_barrier(apr_random_t *g); +APR_DECLARE(apr_status_t) apr_random_secure_ready(apr_random_t *r); +APR_DECLARE(apr_status_t) apr_random_insecure_ready(apr_random_t *r); + +/* Call this in the child after forking to mix the randomness + pools. Note that its generally a bad idea to fork a process with a + real PRNG in it - better to have the PRNG externally and get the + randomness from there. However, if you really must do it, then you + should supply all your entropy to all the PRNGs - don't worry, they + won't produce the same output. + + Note that apr_proc_fork() calls this for you, so only weird + applications need ever call it themselves. +*/ +struct apr_proc_t; +APR_DECLARE(void) apr_random_after_fork(struct apr_proc_t *proc); + +#endif /* ndef APR_RANDOM_H */ diff --git a/srclib/apr/include/apr_ring.h b/srclib/apr/include/apr_ring.h new file mode 100644 index 0000000000..ba1ac1f7a7 --- /dev/null +++ b/srclib/apr/include/apr_ring.h @@ -0,0 +1,489 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This code draws heavily from the 4.4BSD macros + * and Dean Gaudet's "splim/ring.h". + * + * + * + * We'd use Dean's code directly if we could guarantee the + * availability of inline functions. + */ + +#ifndef APR_RING_H +#define APR_RING_H + +/** + * @file apr_ring.h + * @brief APR Rings + */ + +/* + * for offsetof() + */ +#include "apr_general.h" + +/** + * @defgroup apr_ring Ring Macro Implementations + * @ingroup APR + * A ring is a kind of doubly-linked list that can be manipulated + * without knowing where its head is. + * @{ + */ + +/** + * The Ring Element + * + * A ring element struct is linked to the other elements in the ring + * through its ring entry field, e.g. + *
    + *      struct my_element_t {
    + *          APR_RING_ENTRY(my_element_t) link;
    + *          int foo;
    + *          char *bar;
    + *      };
    + * 
    + * + * An element struct may be put on more than one ring if it has more + * than one APR_RING_ENTRY field. Each APR_RING_ENTRY has a corresponding + * APR_RING_HEAD declaration. + * + * @warning For strict C standards compliance you should put the APR_RING_ENTRY + * first in the element struct unless the head is always part of a larger + * object with enough earlier fields to accommodate the offsetof() used + * to compute the ring sentinel below. You can usually ignore this caveat. + */ +#define APR_RING_ENTRY(elem) \ + struct { \ + struct elem *next; \ + struct elem *prev; \ + } + +/** + * The Ring Head + * + * Each ring is managed via its head, which is a struct declared like this: + *
    + *      APR_RING_HEAD(my_ring_t, my_element_t);
    + *      struct my_ring_t ring, *ringp;
    + * 
    + * + * This struct looks just like the element link struct so that we can + * be sure that the typecasting games will work as expected. + * + * The first element in the ring is next after the head, and the last + * element is just before the head. + */ +#define APR_RING_HEAD(head, elem) \ + struct head { \ + struct elem *next; \ + struct elem *prev; \ + } + +/** + * The Ring Sentinel + * + * This is the magic pointer value that occurs before the first and + * after the last elements in the ring, computed from the address of + * the ring's head. The head itself isn't an element, but in order to + * get rid of all the special cases when dealing with the ends of the + * ring, we play typecasting games to make it look like one. + * + * Here is a diagram to illustrate the arrangements of the next and + * prev pointers of each element in a single ring. Note that they point + * to the start of each element, not to the APR_RING_ENTRY structure. + * + *
    + *     +->+------+<-+  +->+------+<-+  +->+------+<-+
    + *     |  |struct|  |  |  |struct|  |  |  |struct|  |
    + *    /   | elem |   \/   | elem |   \/   | elem |  \
    + * ...    |      |   /\   |      |   /\   |      |   ...
    + *        +------+  |  |  +------+  |  |  +------+
    + *   ...--|prev  |  |  +--|ring  |  |  +--|prev  |
    + *        |  next|--+     | entry|--+     |  next|--...
    + *        +------+        +------+        +------+
    + *        | etc. |        | etc. |        | etc. |
    + *        :      :        :      :        :      :
    + * 
    + * + * The APR_RING_HEAD is nothing but a bare APR_RING_ENTRY. The prev + * and next pointers in the first and last elements don't actually + * point to the head, they point to a phantom place called the + * sentinel. Its value is such that last->next->next == first because + * the offset from the sentinel to the head's next pointer is the same + * as the offset from the start of an element to its next pointer. + * This also works in the opposite direction. + * + *
    + *        last                            first
    + *     +->+------+<-+  +->sentinel<-+  +->+------+<-+
    + *     |  |struct|  |  |            |  |  |struct|  |
    + *    /   | elem |   \/              \/   | elem |  \
    + * ...    |      |   /\              /\   |      |   ...
    + *        +------+  |  |  +------+  |  |  +------+
    + *   ...--|prev  |  |  +--|ring  |  |  +--|prev  |
    + *        |  next|--+     |  head|--+     |  next|--...
    + *        +------+        +------+        +------+
    + *        | etc. |                        | etc. |
    + *        :      :                        :      :
    + * 
    + * + * Note that the offset mentioned above is different for each kind of + * ring that the element may be on, and each kind of ring has a unique + * name for its APR_RING_ENTRY in each element, and has its own type + * for its APR_RING_HEAD. + * + * Note also that if the offset is non-zero (which is required if an + * element has more than one APR_RING_ENTRY), the unreality of the + * sentinel may have bad implications on very perverse implementations + * of C -- see the warning in APR_RING_ENTRY. + * + * @param hp The head of the ring + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_SENTINEL(hp, elem, link) \ + (struct elem *)((char *)(hp) - APR_OFFSETOF(struct elem, link)) + +/** + * The first element of the ring + * @param hp The head of the ring + */ +#define APR_RING_FIRST(hp) (hp)->next +/** + * The last element of the ring + * @param hp The head of the ring + */ +#define APR_RING_LAST(hp) (hp)->prev +/** + * The next element in the ring + * @param ep The current element + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_NEXT(ep, link) (ep)->link.next +/** + * The previous element in the ring + * @param ep The current element + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_PREV(ep, link) (ep)->link.prev + + +/** + * Initialize a ring + * @param hp The head of the ring + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_INIT(hp, elem, link) do { \ + APR_RING_FIRST((hp)) = APR_RING_SENTINEL((hp), elem, link); \ + APR_RING_LAST((hp)) = APR_RING_SENTINEL((hp), elem, link); \ + } while (0) + +/** + * Determine if a ring is empty + * @param hp The head of the ring + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + * @return true or false + */ +#define APR_RING_EMPTY(hp, elem, link) \ + (APR_RING_FIRST((hp)) == APR_RING_SENTINEL((hp), elem, link)) + +/** + * Initialize a singleton element + * @param ep The element + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_ELEM_INIT(ep, link) do { \ + APR_RING_NEXT((ep), link) = (ep); \ + APR_RING_PREV((ep), link) = (ep); \ + } while (0) + + +/** + * Splice the sequence ep1..epN into the ring before element lep + * (..lep.. becomes ..ep1..epN..lep..) + * @warning This doesn't work for splicing before the first element or on + * empty rings... see APR_RING_SPLICE_HEAD for one that does + * @param lep Element in the ring to splice before + * @param ep1 First element in the sequence to splice in + * @param epN Last element in the sequence to splice in + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_SPLICE_BEFORE(lep, ep1, epN, link) do { \ + APR_RING_NEXT((epN), link) = (lep); \ + APR_RING_PREV((ep1), link) = APR_RING_PREV((lep), link); \ + APR_RING_NEXT(APR_RING_PREV((lep), link), link) = (ep1); \ + APR_RING_PREV((lep), link) = (epN); \ + } while (0) + +/** + * Splice the sequence ep1..epN into the ring after element lep + * (..lep.. becomes ..lep..ep1..epN..) + * @warning This doesn't work for splicing after the last element or on + * empty rings... see APR_RING_SPLICE_TAIL for one that does + * @param lep Element in the ring to splice after + * @param ep1 First element in the sequence to splice in + * @param epN Last element in the sequence to splice in + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_SPLICE_AFTER(lep, ep1, epN, link) do { \ + APR_RING_PREV((ep1), link) = (lep); \ + APR_RING_NEXT((epN), link) = APR_RING_NEXT((lep), link); \ + APR_RING_PREV(APR_RING_NEXT((lep), link), link) = (epN); \ + APR_RING_NEXT((lep), link) = (ep1); \ + } while (0) + +/** + * Insert the element nep into the ring before element lep + * (..lep.. becomes ..nep..lep..) + * @warning This doesn't work for inserting before the first element or on + * empty rings... see APR_RING_INSERT_HEAD for one that does + * @param lep Element in the ring to insert before + * @param nep Element to insert + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_INSERT_BEFORE(lep, nep, link) \ + APR_RING_SPLICE_BEFORE((lep), (nep), (nep), link) + +/** + * Insert the element nep into the ring after element lep + * (..lep.. becomes ..lep..nep..) + * @warning This doesn't work for inserting after the last element or on + * empty rings... see APR_RING_INSERT_TAIL for one that does + * @param lep Element in the ring to insert after + * @param nep Element to insert + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_INSERT_AFTER(lep, nep, link) \ + APR_RING_SPLICE_AFTER((lep), (nep), (nep), link) + + +/** + * Splice the sequence ep1..epN into the ring before the first element + * (..hp.. becomes ..hp..ep1..epN..) + * @param hp Head of the ring + * @param ep1 First element in the sequence to splice in + * @param epN Last element in the sequence to splice in + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_SPLICE_HEAD(hp, ep1, epN, elem, link) \ + APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((hp), elem, link), \ + (ep1), (epN), link) + +/** + * Splice the sequence ep1..epN into the ring after the last element + * (..hp.. becomes ..ep1..epN..hp..) + * @param hp Head of the ring + * @param ep1 First element in the sequence to splice in + * @param epN Last element in the sequence to splice in + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_SPLICE_TAIL(hp, ep1, epN, elem, link) \ + APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((hp), elem, link), \ + (ep1), (epN), link) + +/** + * Insert the element nep into the ring before the first element + * (..hp.. becomes ..hp..nep..) + * @param hp Head of the ring + * @param nep Element to insert + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_INSERT_HEAD(hp, nep, elem, link) \ + APR_RING_SPLICE_HEAD((hp), (nep), (nep), elem, link) + +/** + * Insert the element nep into the ring after the last element + * (..hp.. becomes ..nep..hp..) + * @param hp Head of the ring + * @param nep Element to insert + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_INSERT_TAIL(hp, nep, elem, link) \ + APR_RING_SPLICE_TAIL((hp), (nep), (nep), elem, link) + +/** + * Concatenate ring h2 onto the end of ring h1, leaving h2 empty. + * @param h1 Head of the ring to concatenate onto + * @param h2 Head of the ring to concatenate + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_CONCAT(h1, h2, elem, link) do { \ + if (!APR_RING_EMPTY((h2), elem, link)) { \ + APR_RING_SPLICE_BEFORE(APR_RING_SENTINEL((h1), elem, link), \ + APR_RING_FIRST((h2)), \ + APR_RING_LAST((h2)), link); \ + APR_RING_INIT((h2), elem, link); \ + } \ + } while (0) + +/** + * Prepend ring h2 onto the beginning of ring h1, leaving h2 empty. + * @param h1 Head of the ring to prepend onto + * @param h2 Head of the ring to prepend + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_PREPEND(h1, h2, elem, link) do { \ + if (!APR_RING_EMPTY((h2), elem, link)) { \ + APR_RING_SPLICE_AFTER(APR_RING_SENTINEL((h1), elem, link), \ + APR_RING_FIRST((h2)), \ + APR_RING_LAST((h2)), link); \ + APR_RING_INIT((h2), elem, link); \ + } \ + } while (0) + +/** + * Unsplice a sequence of elements from a ring + * @warning The unspliced sequence is left with dangling pointers at either end + * @param ep1 First element in the sequence to unsplice + * @param epN Last element in the sequence to unsplice + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_UNSPLICE(ep1, epN, link) do { \ + APR_RING_NEXT(APR_RING_PREV((ep1), link), link) = \ + APR_RING_NEXT((epN), link); \ + APR_RING_PREV(APR_RING_NEXT((epN), link), link) = \ + APR_RING_PREV((ep1), link); \ + } while (0) + +/** + * Remove a single element from a ring + * @warning The unspliced element is left with dangling pointers at either end + * @param ep Element to remove + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_REMOVE(ep, link) \ + APR_RING_UNSPLICE((ep), (ep), link) + + +/* Debugging tools: */ + +#ifdef APR_RING_DEBUG +#include +#include + +#define APR_RING_CHECK_ONE(msg, ptr) \ + fprintf(stderr, "*** %s %p\n", msg, ptr) + +#define APR_RING_CHECK(hp, elem, link, msg) \ + APR_RING_CHECK_ELEM(APR_RING_SENTINEL(hp, elem, link), elem, link, msg) + +#define APR_RING_CHECK_ELEM(ep, elem, link, msg) do { \ + struct elem *start = (ep); \ + struct elem *here = start; \ + fprintf(stderr, "*** ring check start -- %s\n", msg); \ + do { \ + fprintf(stderr, "\telem %p\n", here); \ + fprintf(stderr, "\telem->next %p\n", \ + APR_RING_NEXT(here, link)); \ + fprintf(stderr, "\telem->prev %p\n", \ + APR_RING_PREV(here, link)); \ + fprintf(stderr, "\telem->next->prev %p\n", \ + APR_RING_PREV(APR_RING_NEXT(here, link), link)); \ + fprintf(stderr, "\telem->prev->next %p\n", \ + APR_RING_NEXT(APR_RING_PREV(here, link), link)); \ + if (APR_RING_PREV(APR_RING_NEXT(here, link), link) != here) { \ + fprintf(stderr, "\t*** elem->next->prev != elem\n"); \ + break; \ + } \ + if (APR_RING_NEXT(APR_RING_PREV(here, link), link) != here) { \ + fprintf(stderr, "\t*** elem->prev->next != elem\n"); \ + break; \ + } \ + here = APR_RING_NEXT(here, link); \ + } while (here != start); \ + fprintf(stderr, "*** ring check end\n"); \ + } while (0) + +#define APR_RING_CHECK_CONSISTENCY(hp, elem, link) \ + APR_RING_CHECK_ELEM_CONSISTENCY(APR_RING_SENTINEL(hp, elem, link),\ + elem, link) + +#define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) do { \ + struct elem *start = (ep); \ + struct elem *here = start; \ + do { \ + assert(APR_RING_PREV(APR_RING_NEXT(here, link), link) == here); \ + assert(APR_RING_NEXT(APR_RING_PREV(here, link), link) == here); \ + here = APR_RING_NEXT(here, link); \ + } while (here != start); \ + } while (0) + +#else +/** + * Print a single pointer value to STDERR + * (This is a no-op unless APR_RING_DEBUG is defined.) + * @param msg Descriptive message + * @param ptr Pointer value to print + */ +#define APR_RING_CHECK_ONE(msg, ptr) +/** + * Dump all ring pointers to STDERR, starting with the head and looping all + * the way around the ring back to the head. Aborts if an inconsistency + * is found. + * (This is a no-op unless APR_RING_DEBUG is defined.) + * @param hp Head of the ring + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + * @param msg Descriptive message + */ +#define APR_RING_CHECK(hp, elem, link, msg) +/** + * Loops around a ring and checks all the pointers for consistency. Pops + * an assertion if any inconsistency is found. Same idea as APR_RING_CHECK() + * except that it's silent if all is well. + * (This is a no-op unless APR_RING_DEBUG is defined.) + * @param hp Head of the ring + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_CHECK_CONSISTENCY(hp, elem, link) +/** + * Dump all ring pointers to STDERR, starting with the given element and + * looping all the way around the ring back to that element. Aborts if + * an inconsistency is found. + * (This is a no-op unless APR_RING_DEBUG is defined.) + * @param ep The element + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + * @param msg Descriptive message + */ +#define APR_RING_CHECK_ELEM(ep, elem, link, msg) +/** + * Loops around a ring, starting with the given element, and checks all + * the pointers for consistency. Pops an assertion if any inconsistency + * is found. Same idea as APR_RING_CHECK_ELEM() except that it's silent + * if all is well. + * (This is a no-op unless APR_RING_DEBUG is defined.) + * @param ep The element + * @param elem The name of the element struct + * @param link The name of the APR_RING_ENTRY in the element struct + */ +#define APR_RING_CHECK_ELEM_CONSISTENCY(ep, elem, link) +#endif + +/** @} */ + +#endif /* !APR_RING_H */ diff --git a/srclib/apr/include/apr_shm.h b/srclib/apr/include/apr_shm.h new file mode 100644 index 0000000000..2acb53e344 --- /dev/null +++ b/srclib/apr/include/apr_shm.h @@ -0,0 +1,140 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_SHM_H +#define APR_SHM_H + +/** + * @file apr_shm.h + * @brief APR Shared Memory Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_shm Shared Memory Routines + * @ingroup APR + * @{ + */ + +/** + * Private, platform-specific data struture representing a shared memory + * segment. + */ +typedef struct apr_shm_t apr_shm_t; + +/** + * Create and make accessable a shared memory segment. + * @param m The shared memory structure to create. + * @param reqsize The desired size of the segment. + * @param filename The file to use for shared memory on platforms that + * require it. + * @param pool the pool from which to allocate the shared memory + * structure. + * @remark A note about Anonymous vs. Named shared memory segments: + * Not all plaforms support anonymous shared memory segments, but in + * some cases it is prefered over other types of shared memory + * implementations. Passing a NULL 'file' parameter to this function + * will cause the subsystem to use anonymous shared memory segments. + * If such a system is not available, APR_ENOTIMPL is returned. + * @remark A note about allocation sizes: + * On some platforms it is necessary to store some metainformation + * about the segment within the actual segment. In order to supply + * the caller with the requested size it may be necessary for the + * implementation to request a slightly greater segment length + * from the subsystem. In all cases, the apr_shm_baseaddr_get() + * function will return the first usable byte of memory. + * + */ +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool); + +/** + * Remove shared memory segment associated with a filename. + * @param filename The filename associated with shared-memory segment which + * needs to be removed + * @param pool The pool used for file operations + * @remark This function is only supported on platforms which support + * name-based shared memory segments, and will return APR_ENOTIMPL on + * platforms without such support. + */ +APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, + apr_pool_t *pool); + +/** + * Destroy a shared memory segment and associated memory. + * @param m The shared memory segment structure to destroy. + */ +APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m); + +/** + * Attach to a shared memory segment that was created + * by another process. + * @param m The shared memory structure to create. + * @param filename The file used to create the original segment. + * (This MUST match the original filename.) + * @param pool the pool from which to allocate the shared memory + * structure for this process. + */ +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool); + +/** + * Detach from a shared memory segment without destroying it. + * @param m The shared memory structure representing the segment + * to detach from. + */ +APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m); + +/** + * Retrieve the base address of the shared memory segment. + * NOTE: This address is only usable within the callers address + * space, since this API does not guarantee that other attaching + * processes will maintain the same address mapping. + * @param m The shared memory segment from which to retrieve + * the base address. + * @return address, aligned by APR_ALIGN_DEFAULT. + */ +APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m); + +/** + * Retrieve the length of a shared memory segment in bytes. + * @param m The shared memory segment from which to retrieve + * the segment length. + */ +APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m); + +/** + * Get the pool used by this shared memory segment. + */ +APR_POOL_DECLARE_ACCESSOR(shm); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* APR_SHM_T */ diff --git a/srclib/apr/include/apr_signal.h b/srclib/apr/include/apr_signal.h new file mode 100644 index 0000000000..8cf65be8b0 --- /dev/null +++ b/srclib/apr/include/apr_signal.h @@ -0,0 +1,109 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_SIGNAL_H +#define APR_SIGNAL_H + +/** + * @file apr_signal.h + * @brief APR Signal Handling + */ + +#include "apr.h" +#include "apr_pools.h" + +#if APR_HAVE_SIGNAL_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_signal Handling + * @ingroup APR + * @{ + */ + +#if APR_HAVE_SIGACTION || defined(DOXYGEN) + +#if defined(DARWIN) && !defined(__cplusplus) && !defined(_ANSI_SOURCE) +/* work around Darwin header file bugs + * http://www.opensource.apple.com/bugs/X/BSD%20Kernel/2657228.html + */ +#undef SIG_DFL +#undef SIG_IGN +#undef SIG_ERR +#define SIG_DFL (void (*)(int))0 +#define SIG_IGN (void (*)(int))1 +#define SIG_ERR (void (*)(int))-1 +#endif + +/** Function prototype for signal handlers */ +typedef void apr_sigfunc_t(int); + +/** + * Set the signal handler function for a given signal + * @param signo The signal (eg... SIGWINCH) + * @param func the function to get called + */ +APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func); + +#if defined(SIG_IGN) && !defined(SIG_ERR) +#define SIG_ERR ((apr_sigfunc_t *) -1) +#endif + +#else /* !APR_HAVE_SIGACTION */ +#define apr_signal(a, b) signal(a, b) +#endif + + +/** + * Get the description for a specific signal number + * @param signum The signal number + * @return The description of the signal + */ +APR_DECLARE(const char *) apr_signal_description_get(int signum); + +/** + * APR-private function for initializing the signal package + * @internal + * @param pglobal The internal, global pool + */ +void apr_signal_init(apr_pool_t *pglobal); + +/** + * Block the delivery of a particular signal + * @param signum The signal number + * @return status + */ +APR_DECLARE(apr_status_t) apr_signal_block(int signum); + +/** + * Enable the delivery of a particular signal + * @param signum The signal number + * @return status + */ +APR_DECLARE(apr_status_t) apr_signal_unblock(int signum); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* APR_SIGNAL_H */ diff --git a/srclib/apr/include/apr_strings.h b/srclib/apr/include/apr_strings.h new file mode 100644 index 0000000000..94e99c3f10 --- /dev/null +++ b/srclib/apr/include/apr_strings.h @@ -0,0 +1,357 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Portions of this file are covered by */ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef APR_STRINGS_H +#define APR_STRINGS_H + +/** + * @file apr_strings.h + * @brief APR Strings library + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_pools.h" +#define APR_WANT_IOVEC +#include "apr_want.h" + +#if APR_HAVE_STDARG_H +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_strings String routines + * @ingroup APR + * @{ + */ + +/** + * Do a natural order comparison of two strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b); + +/** + * Do a natural order comparison of two strings ignoring the case of the + * strings. + * @param a The first string to compare + * @param b The second string to compare + * @return Either <0, 0, or >0. If the first string is less than the second + * this returns <0, if they are equivalent it returns 0, and if the + * first string is greater than second string it retuns >0. + */ +APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b); + +/** + * duplicate a string into memory allocated out of a pool + * @param p The pool to allocate out of + * @param s The string to duplicate + * @return The new string + */ +APR_DECLARE(char *) apr_pstrdup(apr_pool_t *p, const char *s); + +/** + * Create a null-terminated string by making a copy of a sequence + * of characters and appending a null byte + * @param p The pool to allocate out of + * @param s The block of characters to duplicate + * @param n The number of characters to duplicate + * @return The new string + * @remark This is a faster alternative to apr_pstrndup, for use + * when you know that the string being duplicated really + * has 'n' or more characters. If the string might contain + * fewer characters, use apr_pstrndup. + */ +APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *p, const char *s, apr_size_t n); + +/** + * duplicate the first n characters of a string into memory allocated + * out of a pool; the new string will be null-terminated + * @param p The pool to allocate out of + * @param s The string to duplicate + * @param n The number of characters to duplicate + * @return The new string + */ +APR_DECLARE(char *) apr_pstrndup(apr_pool_t *p, const char *s, apr_size_t n); + +/** + * Duplicate a block of memory. + * + * @param p The pool to allocate from + * @param m The memory to duplicate + * @param n The number of bytes to duplicate + * @return The new block of memory + */ +APR_DECLARE(void *) apr_pmemdup(apr_pool_t *p, const void *m, apr_size_t n); + +/** + * Concatenate multiple strings, allocating memory out a pool + * @param p The pool to allocate out of + * @param ... The strings to concatenate. The final string must be NULL + * @return The new string + */ +APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *p, ...); + +/** + * Concatenate multiple strings specified in a writev-style vector + * @param p The pool from which to allocate + * @param vec The strings to concatenate + * @param nvec The number of strings to concatenate + * @param nbytes (output) strlen of new string (pass in NULL to omit) + * @return The new string + */ +APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *p, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes); + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ap The arguments to use while printing the data + * @return The new string + */ +APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap); + +/** + * printf-style style printing routine. The data is output to a string + * allocated from a pool + * @param p The pool to allocate out of + * @param fmt The format of the string + * @param ... The arguments to use while printing the data + * @return The new string + */ +APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) + __attribute__((format(printf,2,3))); + +/** + * Copy up to dst_size characters from src to dst; does not copy + * past a NUL terminator in src, but always terminates dst with a NUL + * regardless. + * @param dst The destination string + * @param src The source string + * @param dst_size The space available in dst; dst always receives + * NUL termination, so if src is longer than + * dst_size, the actual number of characters copied is + * dst_size - 1. + * @return Pointer to the NUL terminator of the destination string, dst + * @remark + *
    + * Note the differences between this function and strncpy():
    + *  1) strncpy() doesn't always NUL terminate; apr_cpystrn() does.
    + *  2) strncpy() pads the destination string with NULs, which is often 
    + *     unnecessary; apr_cpystrn() does not.
    + *  3) strncpy() returns a pointer to the beginning of the dst string;
    + *     apr_cpystrn() returns a pointer to the NUL terminator of dst, 
    + *     to allow a check for truncation.
    + * 
    + */ +APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, + apr_size_t dst_size); + +/** + * Strip spaces from a string + * @param dest The destination string. It is okay to modify the string + * in place. Namely dest == src + * @param src The string to rid the spaces from. + * @return The destination string, dest. + */ +APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src); + +/** + * Convert the arguments to a program from one string to an array of + * strings terminated by a NULL pointer + * @param arg_str The arguments to convert + * @param argv_out Output location. This is a pointer to an array of strings. + * @param token_context Pool to use. + */ +APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context); + +/** + * Split a string into separate null-terminated tokens. The tokens are + * delimited in the string by one or more characters from the sep + * argument. + * @param str The string to separate; this should be specified on the + * first call to apr_strtok() for a given string, and NULL + * on subsequent calls. + * @param sep The set of delimiters + * @param last Internal state saved by apr_strtok() between calls. + * @return The next token from the string + */ +APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last); + +/** + * @defgroup APR_Strings_Snprintf snprintf implementations + * @warning + * These are snprintf implementations based on apr_vformatter(). + * + * Note that various standards and implementations disagree on the return + * value of snprintf, and side-effects due to %n in the formatting string. + * apr_snprintf (and apr_vsnprintf) behaves as follows: + * + * Process the format string until the entire string is exhausted, or + * the buffer fills. If the buffer fills then stop processing immediately + * (so no further %n arguments are processed), and return the buffer + * length. In all cases the buffer is NUL terminated. It will return the + * number of characters inserted into the buffer, not including the + * terminating NUL. As a special case, if len is 0, apr_snprintf will + * return the number of characters that would have been inserted if + * the buffer had been infinite (in this case, *buffer can be NULL) + * + * In no event does apr_snprintf return a negative number. + * @{ + */ + +/** + * snprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ... The arguments to use to fill out the format string. + */ +APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) + __attribute__((format(printf,3,4))); + +/** + * vsnprintf routine based on apr_vformatter. This means it understands the + * same extensions. + * @param buf The buffer to write to + * @param len The size of the buffer + * @param format The format string + * @param ap The arguments to use to fill out the format string. + */ +APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap); +/** @} */ + +/** + * create a string representation of an int, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n); + +/** + * create a string representation of a long, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n); + +/** + * create a string representation of an apr_off_t, allocated from a pool + * @param p The pool from which to allocate + * @param n The number to format + * @return The string representation of the number + */ +APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n); + +/** + * Convert a numeric string into an apr_off_t numeric value. + * @param offset The value of the parsed string. + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + */ +APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *buf, + char **end, int base); + +/** + * parse a numeric string into a 64-bit numeric value + * @param buf The string to parse. It may contain optional whitespace, + * followed by an optional '+' (positive, default) or '-' (negative) + * character, followed by an optional '0x' prefix if base is 0 or 16, + * followed by numeric digits appropriate for base. + * @param end A pointer to the end of the valid character in buf. If + * not NULL, it is set to the first invalid character in buf. + * @param base A numeric base in the range between 2 and 36 inclusive, + * or 0. If base is zero, buf will be treated as base ten unless its + * digits are prefixed with '0x', in which case it will be treated as + * base 16. + * @return The numeric value of the string. On overflow, errno is set + * to ERANGE. + */ +APR_DECLARE(apr_int64_t) apr_strtoi64(const char *buf, char **end, int base); + +/** + * parse a base-10 numeric string into a 64-bit numeric value. + * Equivalent to apr_strtoi64(buf, (char**)NULL, 10). + * @param buf The string to parse + * @return The numeric value of the string + */ +APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf); + +/** + * Format a binary size (magnitiudes are 2^10 rather than 10^3) from an apr_off_t, + * as bytes, K, M, T, etc, to a four character compacted human readable string. + * @param size The size to format + * @param buf The 5 byte text buffer (counting the trailing null) + * @return The buf passed to apr_strfsize() + * @remark All negative sizes report ' - ', apr_strfsize only formats positive values. + */ +APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* !APR_STRINGS_H */ diff --git a/srclib/apr/include/apr_support.h b/srclib/apr/include/apr_support.h new file mode 100644 index 0000000000..17a146a962 --- /dev/null +++ b/srclib/apr/include/apr_support.h @@ -0,0 +1,53 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_SUPPORT_H +#define APR_SUPPORT_H + +/** + * @file apr_support.h + * @brief APR Support functions + */ + +#include "apr.h" +#include "apr_network_io.h" +#include "apr_file_io.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_support Internal APR support functions + * @ingroup APR + * @{ + */ + +/** + * Wait for IO to occur or timeout. + * + * Uses POOL for temporary allocations. + */ +apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, + int for_read); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_SUPPORT_H */ diff --git a/srclib/apr/include/apr_tables.h b/srclib/apr/include/apr_tables.h new file mode 100644 index 0000000000..c30fdcb053 --- /dev/null +++ b/srclib/apr/include/apr_tables.h @@ -0,0 +1,422 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_TABLES_H +#define APR_TABLES_H + +/** + * @file apr_tables.h + * @brief APR Table library + */ + +#include "apr.h" +#include "apr_pools.h" + +#if APR_HAVE_STDARG_H +#include /* for va_list */ +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_tables Table and Array Functions + * @ingroup APR + * Tables are used to store entirely opaque structures + * for applications, while Arrays are usually used to + * deal with string lists. + * @{ + */ + +/** the table abstract data type */ +typedef struct apr_table_t apr_table_t; + +/** @see apr_array_header_t */ +typedef struct apr_array_header_t apr_array_header_t; + +/** An opaque array type */ +struct apr_array_header_t { + /** The pool the array is allocated out of */ + apr_pool_t *pool; + /** The amount of memory allocated for each element of the array */ + int elt_size; + /** The number of active elements in the array */ + int nelts; + /** The number of elements allocated in the array */ + int nalloc; + /** The elements in the array */ + char *elts; +}; + +/** + * The (opaque) structure for string-content tables. + */ +typedef struct apr_table_entry_t apr_table_entry_t; + +/** The type for each entry in a string-content table */ +struct apr_table_entry_t { + /** The key for the current table entry */ + char *key; /* maybe NULL in future; + * check when iterating thru table_elts + */ + /** The value for the current table entry */ + char *val; + + /** A checksum for the key, for use by the apr_table internals */ + apr_uint32_t key_checksum; +}; + +/** + * Get the elements from a table + * @param t The table + * @return An array containing the contents of the table + */ +APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t); + +/** + * Determine if the table is empty + * @param t The table to check + * @return True if empty, False otherwise + */ +APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t); + +/** + * Determine if the array is empty + * @param a The array to check + * @return True if empty, False otherwise + */ +APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a); + +/** + * Create an array + * @param p The pool to allocate the memory out of + * @param nelts the number of elements in the initial array + * @param elt_size The size of each element in the array. + * @return The new array + */ +APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, + int nelts, int elt_size); + +/** + * Add a new element to an array (as a first-in, last-out stack) + * @param arr The array to add an element to. + * @return Location for the new element in the array. + * @remark If there are no free spots in the array, then this function will + * allocate new space for the new element. + */ +APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr); + +/** + * Remove an element from an array (as a first-in, last-out stack) + * @param arr The array to remove an element from. + * @return Location of the element in the array. + * @remark If there are no elements in the array, NULL is returned. + */ +APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr); + +/** + * Concatenate two arrays together + * @param dst The destination array, and the one to go first in the combined + * array + * @param src The source array to add to the destination array + */ +APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst, + const apr_array_header_t *src); + +/** + * Copy the entire array + * @param p The pool to allocate the copy of the array out of + * @param arr The array to copy + * @return An exact copy of the array passed in + * @remark The alternate apr_array_copy_hdr copies only the header, and arranges + * for the elements to be copied if (and only if) the code subsequently + * does a push or arraycat. + */ +APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p, + const apr_array_header_t *arr); +/** + * Copy the headers of the array, and arrange for the elements to be copied if + * and only if the code subsequently does a push or arraycat. + * @param p The pool to allocate the copy of the array out of + * @param arr The array to copy + * @return An exact copy of the array passed in + * @remark The alternate apr_array_copy copies the *entire* array. + */ +APR_DECLARE(apr_array_header_t *) apr_array_copy_hdr(apr_pool_t *p, + const apr_array_header_t *arr); + +/** + * Append one array to the end of another, creating a new array in the process. + * @param p The pool to allocate the new array out of + * @param first The array to put first in the new array. + * @param second The array to put second in the new array. + * @return A new array containing the data from the two arrays passed in. +*/ +APR_DECLARE(apr_array_header_t *) apr_array_append(apr_pool_t *p, + const apr_array_header_t *first, + const apr_array_header_t *second); + +/** + * Generates a new string from the apr_pool_t containing the concatenated + * sequence of substrings referenced as elements within the array. The string + * will be empty if all substrings are empty or null, or if there are no + * elements in the array. If sep is non-NUL, it will be inserted between + * elements as a separator. + * @param p The pool to allocate the string out of + * @param arr The array to generate the string from + * @param sep The separator to use + * @return A string containing all of the data in the array. + */ +APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p, + const apr_array_header_t *arr, + const char sep); + +/** + * Make a new table + * @param p The pool to allocate the pool out of + * @param nelts The number of elements in the initial table. + * @return The new table. + * @warning This table can only store text data + */ +APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts); + +/** + * Create a new table and copy another table into it + * @param p The pool to allocate the new table out of + * @param t The table to copy + * @return A copy of the table passed in + */ +APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, + const apr_table_t *t); + +/** + * Delete all of the elements from a table + * @param t The table to clear + */ +APR_DECLARE(void) apr_table_clear(apr_table_t *t); + +/** + * Get the value associated with a given key from the table. After this call, + * The data is still in the table + * @param t The table to search for the key + * @param key The key to search for + * @return The value associated with the key, or NULL if the key does not exist. + */ +APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key); + +/** + * Add a key/value pair to a table, if another element already exists with the + * same key, this will over-write the old data. + * @param t The table to add the data to. + * @param key The key fo use + * @param val The value to add + * @remark When adding data, this function makes a copy of both the key and the + * value. + */ +APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key, + const char *val); + +/** + * Add a key/value pair to a table, if another element already exists with the + * same key, this will over-write the old data. + * @param t The table to add the data to. + * @param key The key to use + * @param val The value to add + * @warning When adding data, this function does not make a copy of the key or + * the value, so care should be taken to ensure that the values will + * not change after they have been added.. + */ +APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key, + const char *val); + +/** + * Remove data from the table + * @param t The table to remove data from + * @param key The key of the data being removed + */ +APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key); + +/** + * Add data to a table by merging the value with data that has already been + * stored + * @param t The table to search for the data + * @param key The key to merge data for + * @param val The data to add + * @remark If the key is not found, then this function acts like apr_table_add + */ +APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key, + const char *val); + +/** + * Add data to a table by merging the value with data that has already been + * stored + * @param t The table to search for the data + * @param key The key to merge data for + * @param val The data to add + * @remark If the key is not found, then this function acts like apr_table_addn + */ +APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key, + const char *val); + +/** + * Add data to a table, regardless of whether there is another element with the + * same key. + * @param t The table to add to + * @param key The key to use + * @param val The value to add. + * @remark When adding data, this function makes a copy of both the key and the + * value. + */ +APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key, + const char *val); + +/** + * Add data to a table, regardless of whether there is another element with the + * same key. + * @param t The table to add to + * @param key The key to use + * @param val The value to add. + * @remark When adding data, this function does not make a copy of the key or the + * value, so care should be taken to ensure that the values will not + * change after they have been added.. + */ +APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key, + const char *val); + +/** + * Merge two tables into one new table + * @param p The pool to use for the new table + * @param overlay The first table to put in the new table + * @param base The table to add at the end of the new table + * @return A new table containing all of the data from the two passed in + */ +APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p, + const apr_table_t *overlay, + const apr_table_t *base); + +/** + * Declaration prototype for the iterator callback function of apr_table_do() + * and apr_table_vdo(). + * @param rec The data passed as the first argument to apr_table_[v]do() + * @param key The key from this iteration of the table + * @param value The value from this iteration of the table + * @remark Iteration continues while this callback function returns non-zero. + * To export the callback function for apr_table_[v]do() it must be declared + * in the _NONSTD convention. + */ +typedef int (apr_table_do_callback_fn_t)(void *rec, const char *key, + const char *value); + +/** + * Iterate over a table running the provided function once for every + * element in the table. If there is data passed in as a vararg, then the + * function is only run on those elements whose key matches something in + * the vararg. If the vararg is NULL, then every element is run through the + * function. Iteration continues while the function returns non-zero. + * @param comp The function to run + * @param rec The data to pass as the first argument to the function + * @param t The table to iterate over + * @param ... The vararg. If this is NULL, then all elements in the table are + * run through the function, otherwise only those whose key matches + * are run. + * @return FALSE if one of the comp() iterations returned zero; TRUE if all + * iterations returned non-zero + * @see apr_table_do_callback_fn_t + */ +APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, ...); + +/** + * Iterate over a table running the provided function once for every + * element in the table. If there is data passed in as a vararg, then the + * function is only run on those element's whose key matches something in + * the vararg. If the vararg is NULL, then every element is run through the + * function. Iteration continues while the function returns non-zero. + * @param comp The function to run + * @param rec The data to pass as the first argument to the function + * @param t The table to iterate over + * @param vp The vararg table. If this is NULL, then all elements in the + * table are run through the function, otherwise only those + * whose key matches are run. + * @return FALSE if one of the comp() iterations returned zero; TRUE if all + * iterations returned non-zero + * @see apr_table_do_callback_fn_t + */ +APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, va_list vp); + +/** flag for overlap to use apr_table_setn */ +#define APR_OVERLAP_TABLES_SET (0) +/** flag for overlap to use apr_table_mergen */ +#define APR_OVERLAP_TABLES_MERGE (1) +/** + * For each element in table b, either use setn or mergen to add the data + * to table a. Which method is used is determined by the flags passed in. + * @param a The table to add the data to. + * @param b The table to iterate over, adding its data to table a + * @param flags How to add the table to table a. One of: + * APR_OVERLAP_TABLES_SET Use apr_table_setn + * APR_OVERLAP_TABLES_MERGE Use apr_table_mergen + * @remark This function is highly optimized, and uses less memory and CPU cycles + * than a function that just loops through table b calling other functions. + */ +/** + *
    + * Conceptually, apr_table_overlap does this:
    + *
    + *  apr_array_header_t *barr = apr_table_elts(b);
    + *  apr_table_entry_t *belt = (apr_table_entry_t *)barr->elts;
    + *  int i;
    + *
    + *  for (i = 0; i < barr->nelts; ++i) {
    + *      if (flags & APR_OVERLAP_TABLES_MERGE) {
    + *          apr_table_mergen(a, belt[i].key, belt[i].val);
    + *      }
    + *      else {
    + *          apr_table_setn(a, belt[i].key, belt[i].val);
    + *      }
    + *  }
    + *
    + *  Except that it is more efficient (less space and cpu-time) especially
    + *  when b has many elements.
    + *
    + *  Notice the assumptions on the keys and values in b -- they must be
    + *  in an ancestor of a's pool.  In practice b and a are usually from
    + *  the same pool.
    + * 
    + */ + +APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b, + unsigned flags); + +/** + * Eliminate redundant entries in a table by either overwriting + * or merging duplicates + * + * @param t Table. + * @param flags APR_OVERLAP_TABLES_MERGE to merge, or + * APR_OVERLAP_TABLES_SET to overwrite + */ +APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_TABLES_H */ diff --git a/srclib/apr/include/apr_thread_cond.h b/srclib/apr/include/apr_thread_cond.h new file mode 100644 index 0000000000..8b8a553235 --- /dev/null +++ b/srclib/apr/include/apr_thread_cond.h @@ -0,0 +1,134 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_THREAD_COND_H +#define APR_THREAD_COND_H + +/** + * @file apr_thread_cond.h + * @brief APR Condition Variable Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_time.h" +#include "apr_thread_mutex.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if APR_HAS_THREADS || defined(DOXYGEN) + +/** + * @defgroup apr_thread_cond Condition Variable Routines + * @ingroup APR + * @{ + */ + +/** Opaque structure for thread condition variables */ +typedef struct apr_thread_cond_t apr_thread_cond_t; + +/** + * Note: destroying a condition variable (or likewise, destroying or + * clearing the pool from which a condition variable was allocated) if + * any threads are blocked waiting on it gives undefined results. + */ + +/** + * Create and initialize a condition variable that can be used to signal + * and schedule threads in a single process. + * @param cond the memory address where the newly created condition variable + * will be stored. + * @param pool the pool from which to allocate the mutex. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool); + +/** + * Put the active calling thread to sleep until signaled to wake up. Each + * condition variable must be associated with a mutex, and that mutex must + * be locked before calling this function, or the behavior will be + * undefined. As the calling thread is put to sleep, the given mutex + * will be simultaneously released; and as this thread wakes up the lock + * is again simultaneously acquired. + * @param cond the condition variable on which to block. + * @param mutex the mutex that must be locked upon entering this function, + * is released while the thread is asleep, and is again acquired before + * returning from this function. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex); + +/** + * Put the active calling thread to sleep until signaled to wake up or + * the timeout is reached. Each condition variable must be associated + * with a mutex, and that mutex must be locked before calling this + * function, or the behavior will be undefined. As the calling thread + * is put to sleep, the given mutex will be simultaneously released; + * and as this thread wakes up the lock is again simultaneously acquired. + * @param cond the condition variable on which to block. + * @param mutex the mutex that must be locked upon entering this function, + * is released while the thread is asleep, and is again acquired before + * returning from this function. + * @param timeout The amount of time in microseconds to wait. This is + * a maximum, not a minimum. If the condition is signaled, we + * will wake up before this time, otherwise the error APR_TIMEUP + * is returned. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout); + +/** + * Signals a single thread, if one exists, that is blocking on the given + * condition variable. That thread is then scheduled to wake up and acquire + * the associated mutex. Although it is not required, if predictable scheduling + * is desired, that mutex must be locked while calling this function. + * @param cond the condition variable on which to produce the signal. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond); + +/** + * Signals all threads blocking on the given condition variable. + * Each thread that was signaled is then scheduled to wake up and acquire + * the associated mutex. This will happen in a serialized manner. + * @param cond the condition variable on which to produce the broadcast. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond); + +/** + * Destroy the condition variable and free the associated memory. + * @param cond the condition variable to destroy. + */ +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond); + +/** + * Get the pool used by this thread_cond. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(thread_cond); + +#endif /* APR_HAS_THREADS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_THREAD_COND_H */ diff --git a/srclib/apr/include/apr_thread_mutex.h b/srclib/apr/include/apr_thread_mutex.h new file mode 100644 index 0000000000..4d73164d41 --- /dev/null +++ b/srclib/apr/include/apr_thread_mutex.h @@ -0,0 +1,110 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_THREAD_MUTEX_H +#define APR_THREAD_MUTEX_H + +/** + * @file apr_thread_mutex.h + * @brief APR Thread Mutex Routines + */ + +#include "apr.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if APR_HAS_THREADS || defined(DOXYGEN) + +/** + * @defgroup apr_thread_mutex Thread Mutex Routines + * @ingroup APR + * @{ + */ + +/** Opaque thread-local mutex structure */ +typedef struct apr_thread_mutex_t apr_thread_mutex_t; + +#define APR_THREAD_MUTEX_DEFAULT 0x0 /**< platform-optimal lock behavior */ +#define APR_THREAD_MUTEX_NESTED 0x1 /**< enable nested (recursive) locks */ +#define APR_THREAD_MUTEX_UNNESTED 0x2 /**< disable nested locks */ + +/* Delayed the include to avoid a circular reference */ +#include "apr_pools.h" + +/** + * Create and initialize a mutex that can be used to synchronize threads. + * @param mutex the memory address where the newly created mutex will be + * stored. + * @param flags Or'ed value of: + *
    + *           APR_THREAD_MUTEX_DEFAULT   platform-optimal lock behavior.
    + *           APR_THREAD_MUTEX_NESTED    enable nested (recursive) locks.
    + *           APR_THREAD_MUTEX_UNNESTED  disable nested locks (non-recursive).
    + * 
    + * @param pool the pool from which to allocate the mutex. + * @warning Be cautious in using APR_THREAD_MUTEX_DEFAULT. While this is the + * most optimial mutex based on a given platform's performance charateristics, + * it will behave as either a nested or an unnested lock. + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool); +/** + * Acquire the lock for the given mutex. If the mutex is already locked, + * the current thread will be put to sleep until the lock becomes available. + * @param mutex the mutex on which to acquire the lock. + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex); + +/** + * Attempt to acquire the lock for the given mutex. If the mutex has already + * been acquired, the call returns immediately with APR_EBUSY. Note: it + * is important that the APR_STATUS_IS_EBUSY(s) macro be used to determine + * if the return value was APR_EBUSY, for portability reasons. + * @param mutex the mutex on which to attempt the lock acquiring. + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex); + +/** + * Release the lock for the given mutex. + * @param mutex the mutex from which to release the lock. + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex); + +/** + * Destroy the mutex and free the memory associated with the lock. + * @param mutex the mutex to destroy. + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex); + +/** + * Get the pool used by this thread_mutex. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(thread_mutex); + +#endif /* APR_HAS_THREADS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_THREAD_MUTEX_H */ diff --git a/srclib/apr/include/apr_thread_proc.h b/srclib/apr/include/apr_thread_proc.h new file mode 100644 index 0000000000..edfcad10c9 --- /dev/null +++ b/srclib/apr/include/apr_thread_proc.h @@ -0,0 +1,798 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_THREAD_PROC_H +#define APR_THREAD_PROC_H + +/** + * @file apr_thread_proc.h + * @brief APR Thread and Process Library + */ + +#include "apr.h" +#include "apr_file_io.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#if APR_HAVE_STRUCT_RLIMIT +#include +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_thread_proc Threads and Process Functions + * @ingroup APR + * @{ + */ + +typedef enum { + APR_SHELLCMD, /**< use the shell to invoke the program */ + APR_PROGRAM, /**< invoke the program directly, no copied env */ + APR_PROGRAM_ENV, /**< invoke the program, replicating our environment */ + APR_PROGRAM_PATH, /**< find program on PATH, use our environment */ + APR_SHELLCMD_ENV /**< use the shell to invoke the program, + * replicating our environment + */ +} apr_cmdtype_e; + +typedef enum { + APR_WAIT, /**< wait for the specified process to finish */ + APR_NOWAIT /**< do not wait -- just see if it has finished */ +} apr_wait_how_e; + +/* I am specifically calling out the values so that the macros below make + * more sense. Yes, I know I don't need to, but I am hoping this makes what + * I am doing more clear. If you want to add more reasons to exit, continue + * to use bitmasks. + */ +typedef enum { + APR_PROC_EXIT = 1, /**< process exited normally */ + APR_PROC_SIGNAL = 2, /**< process exited due to a signal */ + APR_PROC_SIGNAL_CORE = 4 /**< process exited and dumped a core file */ +} apr_exit_why_e; + +/** did we exit the process */ +#define APR_PROC_CHECK_EXIT(x) (x & APR_PROC_EXIT) +/** did we get a signal */ +#define APR_PROC_CHECK_SIGNALED(x) (x & APR_PROC_SIGNAL) +/** did we get core */ +#define APR_PROC_CHECK_CORE_DUMP(x) (x & APR_PROC_SIGNAL_CORE) + +/** @see apr_procattr_io_set */ +#define APR_NO_PIPE 0 + +/** @see apr_procattr_io_set */ +#define APR_FULL_BLOCK 1 +/** @see apr_procattr_io_set */ +#define APR_FULL_NONBLOCK 2 +/** @see apr_procattr_io_set */ +#define APR_PARENT_BLOCK 3 +/** @see apr_procattr_io_set */ +#define APR_CHILD_BLOCK 4 + +/** @see apr_procattr_limit_set */ +#define APR_LIMIT_CPU 0 +/** @see apr_procattr_limit_set */ +#define APR_LIMIT_MEM 1 +/** @see apr_procattr_limit_set */ +#define APR_LIMIT_NPROC 2 +/** @see apr_procattr_limit_set */ +#define APR_LIMIT_NOFILE 3 + +/** + * @defgroup APR_OC Other Child Flags + * @{ + */ +#define APR_OC_REASON_DEATH 0 /**< child has died, caller must call + * unregister still */ +#define APR_OC_REASON_UNWRITABLE 1 /**< write_fd is unwritable */ +#define APR_OC_REASON_RESTART 2 /**< a restart is occuring, perform + * any necessary cleanup (including + * sending a special signal to child) + */ +#define APR_OC_REASON_UNREGISTER 3 /**< unregister has been called, do + * whatever is necessary (including + * kill the child) */ +#define APR_OC_REASON_LOST 4 /**< somehow the child exited without + * us knowing ... buggy os? */ +#define APR_OC_REASON_RUNNING 5 /**< a health check is occuring, + * for most maintainence functions + * this is a no-op. + */ +/** @} */ + +/** The APR process type */ +typedef struct apr_proc_t { + /** The process ID */ + pid_t pid; + /** Parent's side of pipe to child's stdin */ + apr_file_t *in; + /** Parent's side of pipe to child's stdout */ + apr_file_t *out; + /** Parent's side of pipe to child's stdouterr */ + apr_file_t *err; +#if APR_HAS_PROC_INVOKED || defined(DOXYGEN) + /** Diagnositics/debugging string of the command invoked for + * this process [only present if APR_HAS_PROC_INVOKED is true] + * @remark Only enabled on Win32 by default. + * @bug This should either always or never be present in release + * builds - since it breaks binary compatibility. We may enable + * it always in APR 1.0 yet leave it undefined in most cases. + */ + char *invoked; +#endif +#if defined(WIN32) || defined(DOXYGEN) + /** (Win32 only) Creator's handle granting access to the process + * @remark This handle is closed and reset to NULL in every case + * corresponding to a waitpid() on Unix which returns the exit status. + * Therefore Win32 correspond's to Unix's zombie reaping characteristics + * and avoids potential handle leaks. + */ + HANDLE hproc; +#endif +} apr_proc_t; + +/** + * The prototype for APR child errfn functions. (See the description + * of apr_procattr_child_errfn_set() for more information.) + * It is passed the following parameters: + * @param pool Pool associated with the apr_proc_t. If your child + * error function needs user data, associate it with this + * pool. + * @param err APR error code describing the error + * @param description Text description of type of processing which failed + */ +typedef void (apr_child_errfn_t)(apr_pool_t *proc, apr_status_t err, + const char *description); + +/** Opaque Thread structure. */ +typedef struct apr_thread_t apr_thread_t; + +/** Opaque Thread attributes structure. */ +typedef struct apr_threadattr_t apr_threadattr_t; + +/** Opaque Process attributes structure. */ +typedef struct apr_procattr_t apr_procattr_t; + +/** Opaque control variable for one-time atomic variables. */ +typedef struct apr_thread_once_t apr_thread_once_t; + +/** Opaque thread private address space. */ +typedef struct apr_threadkey_t apr_threadkey_t; + +/** Opaque record of child process. */ +typedef struct apr_other_child_rec_t apr_other_child_rec_t; + +/** + * The prototype for any APR thread worker functions. + */ +typedef void *(APR_THREAD_FUNC *apr_thread_start_t)(apr_thread_t*, void*); + +typedef enum { + APR_KILL_NEVER, /**< process is never sent any signals */ + APR_KILL_ALWAYS, /**< process is sent SIGKILL on apr_pool_t cleanup */ + APR_KILL_AFTER_TIMEOUT, /**< SIGTERM, wait 3 seconds, SIGKILL */ + APR_JUST_WAIT, /**< wait forever for the process to complete */ + APR_KILL_ONLY_ONCE /**< send SIGTERM and then wait */ +} apr_kill_conditions_e; + +/* Thread Function definitions */ + +#if APR_HAS_THREADS + +/** + * Create and initialize a new threadattr variable + * @param new_attr The newly created threadattr. + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new_attr, + apr_pool_t *cont); + +/** + * Set if newly created threads should be created in detached state. + * @param attr The threadattr to affect + * @param on Non-zero if detached threads should be created. + */ +APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on); + +/** + * Get the detach state for this threadattr. + * @param attr The threadattr to reference + * @return APR_DETACH if threads are to be detached, or APR_NOTDETACH + * if threads are to be joinable. + */ +APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr); + +/** + * Set the stack size of newly created threads. + * @param attr The threadattr to affect + * @param stacksize The stack size in bytes + */ +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize); + +/** + * Set the stack guard area size of newly created threads. + * @param attr The threadattr to affect + * @param guardsize The stack guard area size in bytes + * @note Thread library implementations commonly use a "guard area" + * after each thread's stack which is not readable or writable such that + * stack overflows cause a segfault; this consumes e.g. 4K of memory + * and increases memory management overhead. Setting the guard area + * size to zero hence trades off reliable behaviour on stack overflow + * for performance. */ +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t guardsize); + +/** + * Create a new thread of execution + * @param new_thread The newly created thread handle. + * @param attr The threadattr to use to determine how to create the thread + * @param func The function to start the new thread in + * @param data Any data to be passed to the starting function + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new_thread, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, apr_pool_t *cont); + +/** + * stop the current thread + * @param thd The thread to stop + * @param retval The return value to pass back to any thread that cares + */ +APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, + apr_status_t retval); + +/** + * block until the desired thread stops executing. + * @param retval The return value from the dead thread. + * @param thd The thread to join + */ +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, + apr_thread_t *thd); + +/** + * force the current thread to yield the processor + */ +APR_DECLARE(void) apr_thread_yield(void); + +/** + * Initialize the control variable for apr_thread_once. If this isn't + * called, apr_initialize won't work. + * @param control The control variable to initialize + * @param p The pool to allocate data from. + */ +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p); + +/** + * Run the specified function one time, regardless of how many threads + * call it. + * @param control The control variable. The same variable should + * be passed in each time the function is tried to be + * called. This is how the underlying functions determine + * if the function has ever been called before. + * @param func The function to call. + */ +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)); + +/** + * detach a thread + * @param thd The thread to detach + */ +APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd); + +/** + * Return the pool associated with the current thread. + * @param data The user data associated with the thread. + * @param key The key to associate with the data + * @param thread The currently open thread. + */ +APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread); + +/** + * Return the pool associated with the current thread. + * @param data The user data to associate with the thread. + * @param key The key to use for associating the data with the thread + * @param cleanup The cleanup routine to use when the thread is destroyed. + * @param thread The currently open thread. + */ +APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread); + +/** + * Create and initialize a new thread private address space + * @param key The thread private handle. + * @param dest The destructor to use when freeing the private memory. + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *cont); + +/** + * Get a pointer to the thread private memory + * @param new_mem The data stored in private memory + * @param key The handle for the desired thread private memory + */ +APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new_mem, + apr_threadkey_t *key); + +/** + * Set the data to be stored in thread private memory + * @param priv The data to be stored in private memory + * @param key The handle for the desired thread private memory + */ +APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, + apr_threadkey_t *key); + +/** + * Free the thread private memory + * @param key The handle for the desired thread private memory + */ +APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key); + +/** + * Return the pool associated with the current threadkey. + * @param data The user data associated with the threadkey. + * @param key The key associated with the data + * @param threadkey The currently open threadkey. + */ +APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey); + +/** + * Return the pool associated with the current threadkey. + * @param data The data to set. + * @param key The key to associate with the data. + * @param cleanup The cleanup routine to use when the file is destroyed. + * @param threadkey The currently open threadkey. + */ +APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey); + +#endif + +/** + * Create and initialize a new procattr variable + * @param new_attr The newly created procattr. + * @param cont The pool to use + */ +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new_attr, + apr_pool_t *cont); + +/** + * Determine if any of stdin, stdout, or stderr should be linked to pipes + * when starting a child process. + * @param attr The procattr we care about. + * @param in Should stdin be a pipe back to the parent? + * @param out Should stdout be a pipe back to the parent? + * @param err Should stderr be a pipe back to the parent? + */ +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, apr_int32_t out, + apr_int32_t err); + +/** + * Set the child_in and/or parent_in values to existing apr_file_t values. + * @param attr The procattr we care about. + * @param child_in apr_file_t value to use as child_in. Must be a valid file. + * @param parent_in apr_file_t value to use as parent_in. Must be a valid file. + * @remark This is NOT a required initializer function. This is + * useful if you have already opened a pipe (or multiple files) + * that you wish to use, perhaps persistently across multiple + * process invocations - such as a log file. You can save some + * extra function calls by not creating your own pipe since this + * creates one in the process space for you. + */ +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(struct apr_procattr_t *attr, + apr_file_t *child_in, + apr_file_t *parent_in); + +/** + * Set the child_out and parent_out values to existing apr_file_t values. + * @param attr The procattr we care about. + * @param child_out apr_file_t value to use as child_out. Must be a valid file. + * @param parent_out apr_file_t value to use as parent_out. Must be a valid file. + * @remark This is NOT a required initializer function. This is + * useful if you have already opened a pipe (or multiple files) + * that you wish to use, perhaps persistently across multiple + * process invocations - such as a log file. + */ +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(struct apr_procattr_t *attr, + apr_file_t *child_out, + apr_file_t *parent_out); + +/** + * Set the child_err and parent_err values to existing apr_file_t values. + * @param attr The procattr we care about. + * @param child_err apr_file_t value to use as child_err. Must be a valid file. + * @param parent_err apr_file_t value to use as parent_err. Must be a valid file. + * @remark This is NOT a required initializer function. This is + * useful if you have already opened a pipe (or multiple files) + * that you wish to use, perhaps persistently across multiple + * process invocations - such as a log file. + */ +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(struct apr_procattr_t *attr, + apr_file_t *child_err, + apr_file_t *parent_err); + +/** + * Set which directory the child process should start executing in. + * @param attr The procattr we care about. + * @param dir Which dir to start in. By default, this is the same dir as + * the parent currently resides in, when the createprocess call + * is made. + */ +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir); + +/** + * Set what type of command the child process will call. + * @param attr The procattr we care about. + * @param cmd The type of command. One of: + *
    + *            APR_SHELLCMD     --  Anything that the shell can handle
    + *            APR_PROGRAM      --  Executable program   (default) 
    + *            APR_PROGRAM_ENV  --  Executable program, copy environment
    + *            APR_PROGRAM_PATH --  Executable program on PATH, copy env
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd); + +/** + * Determine if the child should start in detached state. + * @param attr The procattr we care about. + * @param detach Should the child start in detached state? Default is no. + */ +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, + apr_int32_t detach); + +#if APR_HAVE_STRUCT_RLIMIT +/** + * Set the Resource Utilization limits when starting a new process. + * @param attr The procattr we care about. + * @param what Which limit to set, one of: + *
    + *                 APR_LIMIT_CPU
    + *                 APR_LIMIT_MEM
    + *                 APR_LIMIT_NPROC
    + *                 APR_LIMIT_NOFILE
    + * 
    + * @param limit Value to set the limit to. + */ +APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, + apr_int32_t what, + struct rlimit *limit); +#endif + +/** + * Specify an error function to be called in the child process if APR + * encounters an error in the child prior to running the specified program. + * @param attr The procattr describing the child process to be created. + * @param errfn The function to call in the child process. + * @remark At the present time, it will only be called from apr_proc_create() + * on platforms where fork() is used. It will never be called on other + * platforms, on those platforms apr_proc_create() will return the error + * in the parent process rather than invoke the callback in the now-forked + * child process. + */ +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn); + +/** + * Specify that apr_proc_create() should do whatever it can to report + * failures to the caller of apr_proc_create(), rather than find out in + * the child. + * @param attr The procattr describing the child process to be created. + * @param chk Flag to indicate whether or not extra work should be done + * to try to report failures to the caller. + * @remark This flag only affects apr_proc_create() on platforms where + * fork() is used. This leads to extra overhead in the calling + * process, but that may help the application handle such + * errors more gracefully. + */ +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk); + +/** + * Determine if the child should start in its own address space or using the + * current one from its parent + * @param attr The procattr we care about. + * @param addrspace Should the child start in its own address space? Default + * is no on NetWare and yes on other platforms. + */ +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace); + +/** + * Set the username used for running process + * @param attr The procattr we care about. + * @param username The username used + * @param password User password if needed. Password is needed on WIN32 + * or any other platform having + * APR_PROCATTR_USER_SET_REQUIRES_PASSWORD set. + */ +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password); + +/** + * Set the group used for running process + * @param attr The procattr we care about. + * @param groupname The group name used + */ +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname); + + +#if APR_HAS_FORK +/** + * This is currently the only non-portable call in APR. This executes + * a standard unix fork. + * @param proc The resulting process handle. + * @param cont The pool to use. + * @remark returns APR_INCHILD for the child, and APR_INPARENT for the parent + * or an error. + */ +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *cont); +#endif + +/** + * Create a new process and execute a new program within that process. + * @param new_proc The resulting process handle. + * @param progname The program to run + * @param args the arguments to pass to the new program. The first + * one should be the program name. + * @param env The new environment table for the new process. This + * should be a list of NULL-terminated strings. This argument + * is ignored for APR_PROGRAM_ENV, APR_PROGRAM_PATH, and + * APR_SHELLCMD_ENV types of commands. + * @param attr the procattr we should use to determine how to create the new + * process + * @param pool The pool to use. + * @note This function returns without waiting for the new process to terminate; + * use apr_proc_wait for that. + */ +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new_proc, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool); + +/** + * Wait for a child process to die + * @param proc The process handle that corresponds to the desired child process + * @param exitcode The returned exit status of the child, if a child process + * dies, or the signal that caused the child to die. + * On platforms that don't support obtaining this information, + * the status parameter will be returned as APR_ENOTIMPL. + * @param exitwhy Why the child died, the bitwise or of: + *
    + *            APR_PROC_EXIT         -- process terminated normally
    + *            APR_PROC_SIGNAL       -- process was killed by a signal
    + *            APR_PROC_SIGNAL_CORE  -- process was killed by a signal, and
    + *                                     generated a core dump.
    + * 
    + * @param waithow How should we wait. One of: + *
    + *            APR_WAIT   -- block until the child process dies.
    + *            APR_NOWAIT -- return immediately regardless of if the 
    + *                          child is dead or not.
    + * 
    + * @remark The childs status is in the return code to this process. It is one of: + *
    + *            APR_CHILD_DONE     -- child is no longer running.
    + *            APR_CHILD_NOTDONE  -- child is still running.
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow); + +/** + * Wait for any current child process to die and return information + * about that child. + * @param proc Pointer to NULL on entry, will be filled out with child's + * information + * @param exitcode The returned exit status of the child, if a child process + * dies, or the signal that caused the child to die. + * On platforms that don't support obtaining this information, + * the status parameter will be returned as APR_ENOTIMPL. + * @param exitwhy Why the child died, the bitwise or of: + *
    + *            APR_PROC_EXIT         -- process terminated normally
    + *            APR_PROC_SIGNAL       -- process was killed by a signal
    + *            APR_PROC_SIGNAL_CORE  -- process was killed by a signal, and
    + *                                     generated a core dump.
    + * 
    + * @param waithow How should we wait. One of: + *
    + *            APR_WAIT   -- block until the child process dies.
    + *            APR_NOWAIT -- return immediately regardless of if the 
    + *                          child is dead or not.
    + * 
    + * @param p Pool to allocate child information out of. + * @bug Passing proc as a *proc rather than **proc was an odd choice + * for some platforms... this should be revisited in 1.0 + */ +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p); + +#define APR_PROC_DETACH_FOREGROUND 0 /**< Do not detach */ +#define APR_PROC_DETACH_DAEMONIZE 1 /**< Detach */ + +/** + * Detach the process from the controlling terminal. + * @param daemonize set to non-zero if the process should daemonize + * and become a background process, else it will + * stay in the foreground. + */ +APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize); + +/** + * Register an other_child -- a child associated to its registered + * maintence callback. This callback is invoked when the process + * dies, is disconnected or disappears. + * @param proc The child process to register. + * @param maintenance maintenance is a function that is invoked with a + * reason and the data pointer passed here. + * @param data Opaque context data passed to the maintenance function. + * @param write_fd An fd that is probed for writing. If it is ever unwritable + * then the maintenance is invoked with reason + * OC_REASON_UNWRITABLE. + * @param p The pool to use for allocating memory. + * @bug write_fd duplicates the proc->out stream, it's really redundant + * and should be replaced in the APR 1.0 API with a bitflag of which + * proc->in/out/err handles should be health checked. + * @bug no platform currently tests the pipes health. + */ +APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc, + void (*maintenance) (int reason, + void *, + int status), + void *data, apr_file_t *write_fd, + apr_pool_t *p); + +/** + * Stop watching the specified other child. + * @param data The data to pass to the maintenance function. This is + * used to find the process to unregister. + * @warning Since this can be called by a maintenance function while we're + * scanning the other_children list, all scanners should protect + * themself by loading ocr->next before calling any maintenance + * function. + */ +APR_DECLARE(void) apr_proc_other_child_unregister(void *data); + +/** + * Notify the maintenance callback of a registered other child process + * that application has detected an event, such as death. + * @param proc The process to check + * @param reason The reason code to pass to the maintenance function + * @param status The status to pass to the maintenance function + * @remark An example of code using this behavior; + *
    + * rv = apr_proc_wait_all_procs(&proc, &exitcode, &status, APR_WAIT, p);
    + * if (APR_STATUS_IS_CHILD_DONE(rv)) {
    + * #if APR_HAS_OTHER_CHILD
    + *     if (apr_proc_other_child_alert(&proc, APR_OC_REASON_DEATH, status)
    + *             == APR_SUCCESS) {
    + *         ;  (already handled)
    + *     }
    + *     else
    + * #endif
    + *         [... handling non-otherchild processes death ...]
    + * 
    + */ +APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc, + int reason, + int status); + +/** + * Test one specific other child processes and invoke the maintenance callback + * with the appropriate reason code, if still running, or the appropriate reason + * code if the process is no longer healthy. + * @param ocr The registered other child + * @param reason The reason code (e.g. APR_OC_REASON_RESTART) if still running + */ +APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr, + int reason); + +/** + * Test all registered other child processes and invoke the maintenance callback + * with the appropriate reason code, if still running, or the appropriate reason + * code if the process is no longer healthy. + * @param reason The reason code (e.g. APR_OC_REASON_RESTART) to running processes + */ +APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason); + +/** + * Terminate a process. + * @param proc The process to terminate. + * @param sig How to kill the process. + */ +APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int sig); + +/** + * Register a process to be killed when a pool dies. + * @param a The pool to use to define the processes lifetime + * @param proc The process to register + * @param how How to kill the process, one of: + *
    + *         APR_KILL_NEVER         -- process is never sent any signals
    + *         APR_KILL_ALWAYS        -- process is sent SIGKILL on apr_pool_t cleanup
    + *         APR_KILL_AFTER_TIMEOUT -- SIGTERM, wait 3 seconds, SIGKILL
    + *         APR_JUST_WAIT          -- wait forever for the process to complete
    + *         APR_KILL_ONLY_ONCE     -- send SIGTERM and then wait
    + * 
    + */ +APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *proc, + apr_kill_conditions_e how); + +#if APR_HAS_THREADS + +#if (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) && !defined(OS2) + +/** + * Setup the process for a single thread to be used for all signal handling. + * @warning This must be called before any threads are created + */ +APR_DECLARE(apr_status_t) apr_setup_signal_thread(void); + +/** + * Make the current thread listen for signals. This thread will loop + * forever, calling a provided function whenever it receives a signal. That + * functions should return 1 if the signal has been handled, 0 otherwise. + * @param signal_handler The function to call when a signal is received + * apr_status_t apr_signal_thread((int)(*signal_handler)(int signum)) + */ +APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum)); + +#endif /* (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) && !defined(OS2) */ + +/** + * Get the child-pool used by the thread from the thread info. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(thread); + +#endif /* APR_HAS_THREADS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_THREAD_PROC_H */ + diff --git a/srclib/apr/include/apr_thread_rwlock.h b/srclib/apr/include/apr_thread_rwlock.h new file mode 100644 index 0000000000..b8890b9d5c --- /dev/null +++ b/srclib/apr/include/apr_thread_rwlock.h @@ -0,0 +1,129 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_THREAD_RWLOCK_H +#define APR_THREAD_RWLOCK_H + +/** + * @file apr_thread_rwlock.h + * @brief APR Reader/Writer Lock Routines + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if APR_HAS_THREADS + +/** + * @defgroup apr_thread_rwlock Reader/Writer Lock Routines + * @ingroup APR + * @{ + */ + +/** Opaque read-write thread-safe lock. */ +typedef struct apr_thread_rwlock_t apr_thread_rwlock_t; + +/** + * Note: The following operations have undefined results: unlocking a + * read-write lock which is not locked in the calling thread; write + * locking a read-write lock which is already locked by the calling + * thread; destroying a read-write lock more than once; clearing or + * destroying the pool from which a locked read-write lock is + * allocated. + */ + +/** + * Create and initialize a read-write lock that can be used to synchronize + * threads. + * @param rwlock the memory address where the newly created readwrite lock + * will be stored. + * @param pool the pool from which to allocate the mutex. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool); +/** + * Acquire a shared-read lock on the given read-write lock. This will allow + * multiple threads to enter the same critical section while they have acquired + * the read lock. + * @param rwlock the read-write lock on which to acquire the shared read. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock); + +/** + * Attempt to acquire the shared-read lock on the given read-write lock. This + * is the same as apr_thread_rwlock_rdlock(), only that the function fails + * if there is another thread holding the write lock, or if there are any + * write threads blocking on the lock. If the function fails for this case, + * APR_EBUSY will be returned. Note: it is important that the + * APR_STATUS_IS_EBUSY(s) macro be used to determine if the return value was + * APR_EBUSY, for portability reasons. + * @param rwlock the rwlock on which to attempt the shared read. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock); + +/** + * Acquire an exclusive-write lock on the given read-write lock. This will + * allow only one single thread to enter the critical sections. If there + * are any threads currently holding the read-lock, this thread is put to + * sleep until it can have exclusive access to the lock. + * @param rwlock the read-write lock on which to acquire the exclusive write. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock); + +/** + * Attempt to acquire the exclusive-write lock on the given read-write lock. + * This is the same as apr_thread_rwlock_wrlock(), only that the function fails + * if there is any other thread holding the lock (for reading or writing), + * in which case the function will return APR_EBUSY. Note: it is important + * that the APR_STATUS_IS_EBUSY(s) macro be used to determine if the return + * value was APR_EBUSY, for portability reasons. + * @param rwlock the rwlock on which to attempt the exclusive write. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock); + +/** + * Release either the read or write lock currently held by the calling thread + * associated with the given read-write lock. + * @param rwlock the read-write lock to be released (unlocked). + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock); + +/** + * Destroy the read-write lock and free the associated memory. + * @param rwlock the rwlock to destroy. + */ +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock); + +/** + * Get the pool used by this thread_rwlock. + * @return apr_pool_t the pool + */ +APR_POOL_DECLARE_ACCESSOR(thread_rwlock); + +#endif /* APR_HAS_THREADS */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_THREAD_RWLOCK_H */ diff --git a/srclib/apr/include/apr_time.h b/srclib/apr/include/apr_time.h new file mode 100644 index 0000000000..1882b283e5 --- /dev/null +++ b/srclib/apr/include/apr_time.h @@ -0,0 +1,232 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_TIME_H +#define APR_TIME_H + +/** + * @file apr_time.h + * @brief APR Time Library + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_errno.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_time Time Routines + * @ingroup APR + * @{ + */ + +/** month names */ +APR_DECLARE_DATA extern const char apr_month_snames[12][4]; +/** day names */ +APR_DECLARE_DATA extern const char apr_day_snames[7][4]; + + +/** number of microseconds since 00:00:00 january 1, 1970 UTC */ +typedef apr_int64_t apr_time_t; + + +/** mechanism to properly type apr_time_t literals */ +#define APR_TIME_C(val) APR_INT64_C(val) + +/** mechanism to properly print apr_time_t values */ +#define APR_TIME_T_FMT APR_INT64_T_FMT + +/** intervals for I/O timeouts, in microseconds */ +typedef apr_int64_t apr_interval_time_t; +/** short interval for I/O timeouts, in microseconds */ +typedef apr_int32_t apr_short_interval_time_t; + +/** number of microseconds per second */ +#define APR_USEC_PER_SEC APR_TIME_C(1000000) + +/** @return apr_time_t as a second */ +#define apr_time_sec(time) ((time) / APR_USEC_PER_SEC) + +/** @return apr_time_t as a usec */ +#define apr_time_usec(time) ((time) % APR_USEC_PER_SEC) + +/** @return apr_time_t as a msec */ +#define apr_time_msec(time) (((time) / 1000) % 1000) + +/** @return apr_time_t as a msec */ +#define apr_time_as_msec(time) ((time) / 1000) + +/** @return a second as an apr_time_t */ +#define apr_time_from_sec(sec) ((apr_time_t)(sec) * APR_USEC_PER_SEC) + +/** @return a second and usec combination as an apr_time_t */ +#define apr_time_make(sec, usec) ((apr_time_t)(sec) * APR_USEC_PER_SEC \ + + (apr_time_t)(usec)) + +/** + * @return the current time + */ +APR_DECLARE(apr_time_t) apr_time_now(void); + +/** @see apr_time_exp_t */ +typedef struct apr_time_exp_t apr_time_exp_t; + +/** + * a structure similar to ANSI struct tm with the following differences: + * - tm_usec isn't an ANSI field + * - tm_gmtoff isn't an ANSI field (it's a bsdism) + */ +struct apr_time_exp_t { + /** microseconds past tm_sec */ + apr_int32_t tm_usec; + /** (0-61) seconds past tm_min */ + apr_int32_t tm_sec; + /** (0-59) minutes past tm_hour */ + apr_int32_t tm_min; + /** (0-23) hours past midnight */ + apr_int32_t tm_hour; + /** (1-31) day of the month */ + apr_int32_t tm_mday; + /** (0-11) month of the year */ + apr_int32_t tm_mon; + /** year since 1900 */ + apr_int32_t tm_year; + /** (0-6) days since sunday */ + apr_int32_t tm_wday; + /** (0-365) days since jan 1 */ + apr_int32_t tm_yday; + /** daylight saving time */ + apr_int32_t tm_isdst; + /** seconds east of UTC */ + apr_int32_t tm_gmtoff; +}; + +/** + * convert an ansi time_t to an apr_time_t + * @param result the resulting apr_time_t + * @param input the time_t to convert + */ +APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, + time_t input); + +/** + * convert a time to its human readable components using an offset + * from GMT + * @param result the exploded time + * @param input the time to explode + * @param offs the number of seconds offset to apply + */ +APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, + apr_int32_t offs); + +/** + * convert a time to its human readable components in GMT timezone + * @param result the exploded time + * @param input the time to explode + */ +APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input); + +/** + * convert a time to its human readable components in local timezone + * @param result the exploded time + * @param input the time to explode + */ +APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input); + +/** + * Convert time value from human readable format to a numeric apr_time_t + * e.g. elapsed usec since epoch + * @param result the resulting imploded time + * @param input the input exploded time + */ +APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *result, + apr_time_exp_t *input); + +/** + * Convert time value from human readable format to a numeric apr_time_t that + * always represents GMT + * @param result the resulting imploded time + * @param input the input exploded time + */ +APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *result, + apr_time_exp_t *input); + +/** + * Sleep for the specified number of micro-seconds. + * @param t desired amount of time to sleep. + * @warning May sleep for longer than the specified time. + */ +APR_DECLARE(void) apr_sleep(apr_interval_time_t t); + +/** length of a RFC822 Date */ +#define APR_RFC822_DATE_LEN (30) +/** + * apr_rfc822_date formats dates in the RFC822 + * format in an efficient manner. It is a fixed length + * format which requires the indicated amount of storage, + * including the trailing NUL terminator. + * @param date_str String to write to. + * @param t the time to convert + */ +APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t); + +/** length of a CTIME date */ +#define APR_CTIME_LEN (25) +/** + * apr_ctime formats dates in the ctime() format + * in an efficient manner. it is a fixed length format + * and requires the indicated amount of storage including + * the trailing NUL terminator. + * Unlike ANSI/ISO C ctime(), apr_ctime() does not include + * a \n at the end of the string. + * @param date_str String to write to. + * @param t the time to convert + */ +APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t); + +/** + * formats the exploded time according to the format specified + * @param s string to write to + * @param retsize The length of the returned string + * @param max The maximum length of the string + * @param format The format for the time string + * @param tm The time to convert + */ +APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize, + apr_size_t max, const char *format, + apr_time_exp_t *tm); + +/** + * Improve the clock resolution for the lifetime of the given pool. + * Generally this is only desireable on benchmarking and other very + * time-sensitive applications, and has no impact on most platforms. + * @param p The pool to associate the finer clock resolution + */ +APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p); + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_TIME_H */ diff --git a/srclib/apr/include/apr_user.h b/srclib/apr/include/apr_user.h new file mode 100644 index 0000000000..2529b79137 --- /dev/null +++ b/srclib/apr/include/apr_user.h @@ -0,0 +1,158 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_USER_H +#define APR_USER_H + +/** + * @file apr_user.h + * @brief APR User ID Services + */ + +#include "apr.h" +#include "apr_errno.h" +#include "apr_pools.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @defgroup apr_user User and Group ID Services + * @ingroup APR + * @{ + */ + +/** + * Structure for determining user ownership. + */ +#ifdef WIN32 +typedef PSID apr_uid_t; +#else +typedef uid_t apr_uid_t; +#endif + +/** + * Structure for determining group ownership. + */ +#ifdef WIN32 +typedef PSID apr_gid_t; +#else +typedef gid_t apr_gid_t; +#endif + +#if APR_HAS_USER + +/** + * Get the userid (and groupid) of the calling process + * @param userid Returns the user id + * @param groupid Returns the user's group id + * @param p The pool from which to allocate working space + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *userid, + apr_gid_t *groupid, + apr_pool_t *p); + +/** + * Get the user name for a specified userid + * @param username Pointer to new string containing user name (on output) + * @param userid The userid + * @param p The pool from which to allocate the string + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p); + +/** + * Get the userid (and groupid) for the specified username + * @param userid Returns the user id + * @param groupid Returns the user's group id + * @param username The username to lookup + * @param p The pool from which to allocate working space + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *userid, apr_gid_t *groupid, + const char *username, apr_pool_t *p); + +/** + * Get the home directory for the named user + * @param dirname Pointer to new string containing directory name (on output) + * @param username The named user + * @param p The pool from which to allocate the string + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p); + +/** + * Compare two user identifiers for equality. + * @param left One uid to test + * @param right Another uid to test + * @return APR_SUCCESS if the apr_uid_t strutures identify the same user, + * APR_EMISMATCH if not, APR_BADARG if an apr_uid_t is invalid. + * @remark This function is available only if APR_HAS_USER is defined. + */ +#if defined(WIN32) +APR_DECLARE(apr_status_t) apr_uid_compare(apr_uid_t left, apr_uid_t right); +#else +#define apr_uid_compare(left,right) (((left) == (right)) ? APR_SUCCESS : APR_EMISMATCH) +#endif + +/** + * Get the group name for a specified groupid + * @param groupname Pointer to new string containing group name (on output) + * @param groupid The groupid + * @param p The pool from which to allocate the string + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, + apr_gid_t groupid, apr_pool_t *p); + +/** + * Get the groupid for a specified group name + * @param groupid Pointer to the group id (on output) + * @param groupname The group name to look up + * @param p The pool from which to allocate the string + * @remark This function is available only if APR_HAS_USER is defined. + */ +APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, + const char *groupname, apr_pool_t *p); + +/** + * Compare two group identifiers for equality. + * @param left One gid to test + * @param right Another gid to test + * @return APR_SUCCESS if the apr_gid_t strutures identify the same group, + * APR_EMISMATCH if not, APR_BADARG if an apr_gid_t is invalid. + * @remark This function is available only if APR_HAS_USER is defined. + */ +#if defined(WIN32) +APR_DECLARE(apr_status_t) apr_gid_compare(apr_gid_t left, apr_gid_t right); +#else +#define apr_gid_compare(left,right) (((left) == (right)) ? APR_SUCCESS : APR_EMISMATCH) +#endif + +#endif /* ! APR_HAS_USER */ + +/** @} */ + +#ifdef __cplusplus +} +#endif + +#endif /* ! APR_USER_H */ diff --git a/srclib/apr/include/apr_version.h b/srclib/apr/include/apr_version.h new file mode 100644 index 0000000000..e309bf67c7 --- /dev/null +++ b/srclib/apr/include/apr_version.h @@ -0,0 +1,143 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_VERSION_H +#define APR_VERSION_H + +/** + * @file apr_version.h + * @brief APR Versioning Interface + * + * APR's Version + * + * There are several different mechanisms for accessing the version. There + * is a string form, and a set of numbers; in addition, there are constants + * which can be compiled into your application, and you can query the library + * being used for its actual version. + * + * Note that it is possible for an application to detect that it has been + * compiled against a different version of APR by use of the compile-time + * constants and the use of the run-time query function. + * + * APR version numbering follows the guidelines specified in: + * + * http://apr.apache.org/versioning.html + */ + + +/* The numeric compile-time version constants. These constants are the + * authoritative version numbers for APR. + */ + +/** major version + * Major API changes that could cause compatibility problems for older + * programs such as structure size changes. No binary compatibility is + * possible across a change in the major version. + */ +#define APR_MAJOR_VERSION 1 + +/** minor version + * Minor API changes that do not cause binary compatibility problems. + * Reset to 0 when upgrading APR_MAJOR_VERSION + */ +#define APR_MINOR_VERSION 2 + +/** patch level + * The Patch Level never includes API changes, simply bug fixes. + * Reset to 0 when upgrading APR_MINOR_VERSION + */ +#define APR_PATCH_VERSION 0 + +/** + * The symbol APR_IS_DEV_VERSION is only defined for internal, + * "development" copies of APR. It is undefined for released versions + * of APR. + */ +#define APR_IS_DEV_VERSION + + +#if defined(APR_IS_DEV_VERSION) || defined(DOXYGEN) +/** Internal: string form of the "is dev" flag */ +#define APR_IS_DEV_STRING "-dev" +#else +#define APR_IS_DEV_STRING "" +#endif + +/* APR_STRINGIFY is defined here, and also in apr_general.h, so wrap it */ +#ifndef APR_STRINGIFY +/** Properly quote a value as a string in the C preprocessor */ +#define APR_STRINGIFY(n) APR_STRINGIFY_HELPER(n) +/** Helper macro for APR_STRINGIFY */ +#define APR_STRINGIFY_HELPER(n) #n +#endif + +/** The formatted string of APR's version */ +#define APR_VERSION_STRING \ + APR_STRINGIFY(APR_MAJOR_VERSION) "." \ + APR_STRINGIFY(APR_MINOR_VERSION) "." \ + APR_STRINGIFY(APR_PATCH_VERSION) \ + APR_IS_DEV_STRING + +/** An alternative formatted string of APR's version */ +/* macro for Win32 .rc files using numeric csv representation */ +#define APR_VERSION_STRING_CSV APR_MAJOR_VERSION ##, \ + ##APR_MINOR_VERSION ##, \ + ##APR_PATCH_VERSION + + +#ifndef APR_VERSION_ONLY + +/* The C language API to access the version at run time, + * as opposed to compile time. APR_VERSION_ONLY may be defined + * externally when preprocessing apr_version.h to obtain strictly + * the C Preprocessor macro declarations. + */ + +#include "apr.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * The numeric version information is broken out into fields within this + * structure. + */ +typedef struct { + int major; /**< major number */ + int minor; /**< minor number */ + int patch; /**< patch number */ + int is_dev; /**< is development (1 or 0) */ +} apr_version_t; + +/** + * Return APR's version information information in a numeric form. + * + * @param pvsn Pointer to a version structure for returning the version + * information. + */ +APR_DECLARE(void) apr_version(apr_version_t *pvsn); + +/** Return APR's version information as a string. */ +APR_DECLARE(const char *) apr_version_string(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ndef APR_VERSION_ONLY */ + +#endif /* ndef APR_VERSION_H */ diff --git a/srclib/apr/include/apr_want.h b/srclib/apr/include/apr_want.h new file mode 100644 index 0000000000..c7556a7926 --- /dev/null +++ b/srclib/apr/include/apr_want.h @@ -0,0 +1,109 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" /* configuration data */ +/** + * @file apr_want.h + * @brief APR Standard Headers Support + * + *
    + * Features:
    + *
    + *   APR_WANT_STRFUNC:  strcmp, strcat, strcpy, etc
    + *   APR_WANT_MEMFUNC:  memcmp, memcpy, etc
    + *   APR_WANT_STDIO:     and related bits
    + *   APR_WANT_IOVEC:    struct iovec
    + *   APR_WANT_BYTEFUNC: htons, htonl, ntohl, ntohs
    + *
    + * Typical usage:
    + *
    + *   #define APR_WANT_STRFUNC
    + *   #define APR_WANT_MEMFUNC
    + *   #include "apr_want.h"
    + *
    + * The appropriate headers will be included.
    + *
    + * Note: it is safe to use this in a header (it won't interfere with other
    + *       headers' or source files' use of apr_want.h)
    + * 
    + */ + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STRFUNC + +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif + +#undef APR_WANT_STRFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_MEMFUNC + +#if APR_HAVE_STRING_H +#include +#endif + +#undef APR_WANT_MEMFUNC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_STDIO + +#if APR_HAVE_STDIO_H +#include +#endif + +#undef APR_WANT_STDIO +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_IOVEC + +#if APR_HAVE_SYS_UIO_H +#include +#endif + +#undef APR_WANT_IOVEC +#endif + +/* --------------------------------------------------------------------- */ + +#ifdef APR_WANT_BYTEFUNC + +/* Single Unix says they are in arpa/inet.h. Linux has them in + * netinet/in.h. FreeBSD has them in arpa/inet.h but requires that + * netinet/in.h be included first. + */ +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif + +#undef APR_WANT_BYTEFUNC +#endif + +/* --------------------------------------------------------------------- */ diff --git a/srclib/apr/include/arch/aix/apr_arch_dso.h b/srclib/apr/include/arch/aix/apr_arch_dso.h new file mode 100644 index 0000000000..cc9c026639 --- /dev/null +++ b/srclib/apr/include/arch/aix/apr_arch_dso.h @@ -0,0 +1,41 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#if APR_HAS_DSO + +void *dlopen(const char *path, int mode); +void *dlsym(void *handle, const char *symbol); +const char *dlerror(void); +int dlclose(void *handle); + +struct apr_dso_handle_t { + apr_pool_t *pool; + void *handle; + const char *errormsg; +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/apr_private_common.h b/srclib/apr/include/arch/apr_private_common.h new file mode 100644 index 0000000000..c5fbbaa9fa --- /dev/null +++ b/srclib/apr/include/arch/apr_private_common.h @@ -0,0 +1,42 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * This file contains private declarations common to all architectures. + */ + +#ifndef APR_PRIVATE_COMMON_H +#define APR_PRIVATE_COMMON_H + +#include "apr_pools.h" +#include "apr_tables.h" + +apr_status_t apr_filepath_list_split_impl(apr_array_header_t **pathelts, + const char *liststr, + char separator, + apr_pool_t *p); + +apr_status_t apr_filepath_list_merge_impl(char **liststr, + apr_array_header_t *pathelts, + char separator, + apr_pool_t *p); + +/* temporary defines to handle 64bit compile mismatches */ +#define APR_INT_TRUNC_CAST int +#define APR_UINT32_TRUNC_CAST apr_uint32_t +#define APR_UINT32_MAX 0xFFFFFFFFUL + +#endif /*APR_PRIVATE_COMMON_H*/ diff --git a/srclib/apr/include/arch/beos/apr_arch_dso.h b/srclib/apr/include/arch/beos/apr_arch_dso.h new file mode 100644 index 0000000000..1bf3395c06 --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_dso.h @@ -0,0 +1,41 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_dso.h" +#include "apr.h" +#include +#include + +#if APR_HAS_DSO + +struct apr_dso_handle_t { + image_id handle; /* Handle to the DSO loaded */ + apr_pool_t *pool; + const char *errormsg; /* if the load fails, we have an error + * message here :) + */ +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/beos/apr_arch_proc_mutex.h b/srclib/apr/include/arch/beos/apr_arch_proc_mutex.h new file mode 100644 index 0000000000..1325e00ed0 --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_proc_mutex.h @@ -0,0 +1,36 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_MUTEX_H +#define PROC_MUTEX_H + +#include "apr_pools.h" +#include "apr_proc_mutex.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" + +struct apr_proc_mutex_t { + apr_pool_t *pool; + + /* Our lock :) */ + sem_id Lock; + int32 LockCount; +}; + +#endif /* PROC_MUTEX_H */ + diff --git a/srclib/apr/include/arch/beos/apr_arch_thread_cond.h b/srclib/apr/include/arch/beos/apr_arch_thread_cond.h new file mode 100644 index 0000000000..b4584b47ca --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_thread_cond.h @@ -0,0 +1,46 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_COND_H +#define THREAD_COND_H + +#include +#include "apr_pools.h" +#include "apr_thread_cond.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "apr_ring.h" + +struct waiter_t { + APR_RING_ENTRY(waiter_t) link; + sem_id sem; +}; + +struct apr_thread_cond_t { + apr_pool_t *pool; + sem_id lock; + apr_thread_mutex_t *condlock; + thread_id owner; + /* active list */ + APR_RING_HEAD(active_list, waiter_t) alist; + /* free list */ + APR_RING_HEAD(free_list, waiter_t) flist; +}; + +#endif /* THREAD_COND_H */ + diff --git a/srclib/apr/include/arch/beos/apr_arch_thread_mutex.h b/srclib/apr/include/arch/beos/apr_arch_thread_mutex.h new file mode 100644 index 0000000000..af9c96f87b --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_thread_mutex.h @@ -0,0 +1,42 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MUTEX_H +#define THREAD_MUTEX_H + +#include +#include "apr_pools.h" +#include "apr_thread_mutex.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" + +struct apr_thread_mutex_t { + apr_pool_t *pool; + + /* Our lock :) */ + sem_id Lock; + int32 LockCount; + + /* If we nest locks we need these... */ + int nested; + apr_os_thread_t owner; + int owner_ref; +}; + +#endif /* THREAD_MUTEX_H */ + diff --git a/srclib/apr/include/arch/beos/apr_arch_thread_rwlock.h b/srclib/apr/include/arch/beos/apr_arch_thread_rwlock.h new file mode 100644 index 0000000000..7f911816d5 --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_thread_rwlock.h @@ -0,0 +1,45 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_RWLOCK_H +#define THREAD_RWLOCK_H + +#include +#include "apr_pools.h" +#include "apr_thread_rwlock.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" + +struct apr_thread_rwlock_t { + apr_pool_t *pool; + + /* Our lock :) */ + sem_id Lock; + int32 LockCount; + /* Read/Write lock stuff */ + sem_id Read; + int32 ReadCount; + sem_id Write; + int32 WriteCount; + int32 Nested; + + thread_id writer; +}; + +#endif /* THREAD_RWLOCK_H */ + diff --git a/srclib/apr/include/arch/beos/apr_arch_threadproc.h b/srclib/apr/include/arch/beos/apr_arch_threadproc.h new file mode 100644 index 0000000000..c11fe4e39e --- /dev/null +++ b/srclib/apr/include/arch/beos/apr_arch_threadproc.h @@ -0,0 +1,95 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_thread_proc.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_thread_proc.h" +#include "apr_general.h" +#include "apr_portable.h" +#include +#include +#include +#include +#include + +#ifndef THREAD_PROC_H +#define THREAD_PROC_H + +#define SHELL_PATH "/bin/sh" + +#define PTHREAD_CANCEL_AYNCHRONOUS CANCEL_ASYNCH; +#define PTHREAD_CANCEL_DEFERRED CANCEL_DEFER; + +#define PTHREAD_CANCEL_ENABLE CANCEL_ENABLE; +#define PTHREAD_CANCEL_DISABLE CANCEL_DISABLE; + +#define BEOS_MAX_DATAKEYS 128 + +struct apr_thread_t { + apr_pool_t *pool; + thread_id td; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + int32 attr; + int detached; + int joinable; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + int32 key; +}; + +struct beos_private_data { + const void ** data; + int count; + volatile thread_id td; +}; + +struct beos_key { + int assigned; + int count; + sem_id lock; + int32 ben_lock; + void (* destructor) (void *); +}; + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; +}; + +struct apr_thread_once_t { + sem_id sem; + int hit; +}; + +#endif /* ! THREAD_PROC_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_dso.h b/srclib/apr/include/arch/netware/apr_arch_dso.h new file mode 100644 index 0000000000..18d2403626 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_dso.h @@ -0,0 +1,43 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#include + +typedef struct sym_list sym_list; + +struct sym_list { + sym_list *next; + char *symbol; +}; + +struct apr_dso_handle_t { + apr_pool_t *pool; + void *handle; + const char *errormsg; + sym_list *symbols; + char *path; +}; + +#endif diff --git a/srclib/apr/include/arch/netware/apr_arch_file_io.h b/srclib/apr/include/arch/netware/apr_arch_file_io.h new file mode 100644 index 0000000000..bcef9add98 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_file_io.h @@ -0,0 +1,151 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILE_IO_H +#define FILE_IO_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_tables.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_lib.h" +#include "apr_poll.h" + +/* System headers the file I/O library needs */ +#if APR_HAVE_FCNTL_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_ERRNO_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif +#if APR_HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_SYS_UIO_H +#include +#endif +#if APR_HAVE_SYS_TIME_H +#include +#endif + +#include + +/* End System headers */ + +#define APR_FILE_BUFSIZE 4096 + +#if APR_HAS_LARGE_FILES +#define lseek(f,o,w) lseek64(f,o,w) +#define ftruncate(f,l) ftruncate64(f,l) +#endif + +typedef struct stat struct_stat; + +struct apr_file_t { + apr_pool_t *pool; + int filedes; + char *fname; + apr_int32_t flags; + int eof_hit; + int is_pipe; + apr_interval_time_t timeout; + int buffered; + enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking; + int ungetchar; /* Last char provided by an unget op. (-1 = no char)*/ + + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; + + /* Stuff for buffered mode */ + char *buffer; + int bufpos; /* Read/Write position in buffer */ + apr_off_t dataRead; /* amount of valid data read into buffer */ + int direction; /* buffer being used for 0 = read, 1 = write */ + apr_off_t filePtr; /* position in file of handle */ +#if APR_HAS_THREADS + struct apr_thread_mutex_t *thlock; +#endif +}; + +struct apr_dir_t { + apr_pool_t *pool; + char *dirname; + DIR *dirstruct; + struct dirent *entry; +}; + +typedef struct apr_stat_entry_t apr_stat_entry_t; + +struct apr_stat_entry_t { + struct stat info; + char *casedName; + apr_time_t expire; + NXPathCtx_t pathCtx; +}; + +#define MAX_SERVER_NAME 64 +#define MAX_VOLUME_NAME 64 +#define MAX_PATH_NAME 256 +#define MAX_FILE_NAME 256 + +#define DRIVE_ONLY 1 + +/* If the user passes d: vs. D: (or //mach/share vs. //MACH/SHARE), + * we need to fold the case to canonical form. This function is + * supposed to do so. + */ +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p); + +/* This function check to see of the given path includes a drive/volume + * specifier. If the _only_ parameter is set to DRIVE_ONLY then it + * check to see of the path only contains a drive/volume specifier and + * nothing else. + */ +apr_status_t filepath_has_drive(const char *rootpath, int only, apr_pool_t *p); + +/* This function compares the drive/volume specifiers for each given path. + * It returns zero if they match or non-zero if not. + */ +apr_status_t filepath_compare_drive(const char *path1, const char *path2, apr_pool_t *p); + +apr_status_t apr_unix_file_cleanup(void *); + +#endif /* ! FILE_IO_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_global_mutex.h b/srclib/apr/include/arch/netware/apr_arch_global_mutex.h new file mode 100644 index 0000000000..f8f534fef2 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_global_mutex.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GLOBAL_MUTEX_H +#define GLOBAL_MUTEX_H + +#include "apr_global_mutex.h" +#include "apr_thread_mutex.h" + +struct apr_global_mutex_t { + apr_pool_t *pool; + apr_thread_mutex_t *mutex; +}; + +#endif /* GLOBAL_MUTEX_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_internal_time.h b/srclib/apr/include/arch/netware/apr_arch_internal_time.h new file mode 100644 index 0000000000..399ac72e79 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_internal_time.h @@ -0,0 +1,26 @@ +/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIME_INTERNAL_H +#define TIME_INTERNAL_H + +#include "apr.h" + +#define TZONE (*___timezone()) + +void apr_netware_setup_time(void); + +#endif /* TIME_INTERNAL_H */ diff --git a/srclib/apr/include/arch/netware/apr_arch_networkio.h b/srclib/apr/include/arch/netware/apr_arch_networkio.h new file mode 100644 index 0000000000..a15afc586e --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_networkio.h @@ -0,0 +1,31 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_IO_H + +#ifdef USE_WINSOCK +/* Making sure that we include the correct networkio.h since the + the project file is configured to first look for headers in + arch/netware and then arch/unix. But in this specific case we + want arch/win32. +*/ +#include <../win32/apr_arch_networkio.h> +#else +#include <../unix/apr_arch_networkio.h> +#endif + +#endif /* ! NETWORK_IO_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_pre_nw.h b/srclib/apr/include/arch/netware/apr_arch_pre_nw.h new file mode 100644 index 0000000000..6c0026c6b7 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_pre_nw.h @@ -0,0 +1,67 @@ +#ifndef __pre_nw__ +#define __pre_nw__ + +#include + +#ifndef __GNUC__ +#pragma precompile_target "precomp.mch" +#endif + +#define NETWARE + +#define N_PLAT_NLM + +/* Copyright 2004-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#define FAR +#define far + +/* no-op for Codewarrior C compiler; a functions are cdecl + by default */ +#define cdecl + +/* if we have wchar_t enabled in C++, predefine this type to avoid + a conflict in Novell's header files */ +#ifndef __GNUC__ +#ifndef DOXYGEN +#if (__option(cplusplus) && __option(wchar_type)) +#define _WCHAR_T +#endif +#endif +#endif + +/* C9X defintion used by MSL C++ library */ +#define DECIMAL_DIG 17 + +/* some code may want to use the MS convention for long long */ +#ifndef __int64 +#define __int64 long long +#endif + +/* expat version */ +#define VERSION "expat_1.95.1" +#define EXPAT_MAJOR_VERSION 1 +#define EXPAT_MINOR_VERSION 95 +#define EXPAT_EDIT 2 + +#define XML_MAJOR_VERSION EXPAT_MAJOR_VERSION +#define XML_MINOR_VERSION EXPAT_MINOR_VERSION +#define XML_MICRO_VERSION EXPAT_EDIT + +#endif + + + diff --git a/srclib/apr/include/arch/netware/apr_arch_proc_mutex.h b/srclib/apr/include/arch/netware/apr_arch_proc_mutex.h new file mode 100644 index 0000000000..09c325e4fe --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_proc_mutex.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_MUTEX_H +#define PROC_MUTEX_H + +#include "apr_proc_mutex.h" +#include "apr_thread_mutex.h" + +struct apr_proc_mutex_t { + apr_pool_t *pool; + apr_thread_mutex_t *mutex; +}; + +#endif /* PROC_MUTEX_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_thread_cond.h b/srclib/apr/include/arch/netware/apr_arch_thread_cond.h new file mode 100644 index 0000000000..bfb5ece393 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_thread_cond.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_COND_H +#define THREAD_COND_H + +#include "apr_thread_cond.h" +#include + +struct apr_thread_cond_t { + apr_pool_t *pool; + NXCond_t *cond; +}; + +#endif /* THREAD_COND_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_thread_mutex.h b/srclib/apr/include/arch/netware/apr_arch_thread_mutex.h new file mode 100644 index 0000000000..d9b599a0e3 --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_thread_mutex.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MUTEX_H +#define THREAD_MUTEX_H + +#include "apr_thread_mutex.h" +#include + +struct apr_thread_mutex_t { + apr_pool_t *pool; + NXMutex_t *mutex; +}; + +#endif /* THREAD_MUTEX_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_thread_rwlock.h b/srclib/apr/include/arch/netware/apr_arch_thread_rwlock.h new file mode 100644 index 0000000000..b87e2d5dbf --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_thread_rwlock.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_RWLOCK_H +#define THREAD_RWLOCK_H + +#include "apr_thread_rwlock.h" +#include + +struct apr_thread_rwlock_t { + apr_pool_t *pool; + NXRwLock_t *rwlock; +}; + +#endif /* THREAD_RWLOCK_H */ + diff --git a/srclib/apr/include/arch/netware/apr_arch_threadproc.h b/srclib/apr/include/arch/netware/apr_arch_threadproc.h new file mode 100644 index 0000000000..b30d6f6e3e --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_arch_threadproc.h @@ -0,0 +1,78 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" + +#include + +#ifndef THREAD_PROC_H +#define THREAD_PROC_H + +#define SHELL_PATH "" +#define APR_DEFAULT_STACK_SIZE 65536 + +struct apr_thread_t { + apr_pool_t *pool; + NXContext_t ctx; + NXThreadId_t td; + char *thread_name; + apr_int32_t cancel; + apr_int32_t cancel_how; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + apr_size_t stack_size; + apr_int32_t detach; + char *thread_name; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + NXKey_t key; +}; + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; + apr_int32_t addrspace; +}; + +struct apr_thread_once_t { + unsigned long value; +}; + +//struct apr_proc_t { +// apr_pool_t *pool; +// pid_t pid; +// apr_procattr_t *attr; +//}; + +#endif /* ! THREAD_PROC_H */ + diff --git a/srclib/apr/include/arch/netware/apr_private.h b/srclib/apr/include/arch/netware/apr_private.h new file mode 100644 index 0000000000..04a3b0b91c --- /dev/null +++ b/srclib/apr/include/arch/netware/apr_private.h @@ -0,0 +1,191 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Note: + * This is the windows specific autoconf-like config file + * which unix would create at build time. + */ + +#ifdef NETWARE + +#ifndef APR_PRIVATE_H +#define APR_PRIVATE_H + +/* Include the public APR symbols, include our idea of the 'right' + * subset of the Windows.h header. This saves us repetition. + */ +#include "apr.h" + +#include +#include +#include +#include +#include +#include +#include + +/* Use this section to define all of the HAVE_FOO_H + * that are required to build properly. + */ +#define HAVE_DLFCN_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_SIGNAL_H 1 +#define HAVE_STDDEF_H 1 +#define HAVE_STDLIB_H 1 +#ifndef USE_WINSOCK +#define HAVE_SYS_SELECT_H 1 +#define HAVE_WRITEV 1 +#endif +#define HAVE_SYS_STAT_H 1 +#define HAVE_SYS_MMAN_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_ICONV_H 1 +#define HAVE_UTIME_H 1 + +#define HAVE_STRICMP 1 +#define HAVE_STRNICMP 1 +#define HAVE_STRDUP 1 +#define HAVE_STRSTR 1 +#define HAVE_MEMCHR 1 +#define HAVE_CALLOC 1 +#define HAVE_UTIME 1 + +#define HAVE_GETENV 1 +#define HAVE_SETENV 1 +#define HAVE_UNSETENV 1 + +#define HAVE_WRITEV 1 + +/* 64-bit integer conversion function */ +#define APR_INT64_STRFN strtoll + +/*#define DSO_USE_DLFCN */ + +#ifdef NW_BUILD_IPV6 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETNAMEINFO 1 +#endif + +/* 1 is used for SIGABRT on netware */ +/* 2 is used for SIGFPE on netware */ +/* 3 is used for SIGILL on netware */ +/* 4 is used for SIGINT on netware */ +/* 5 is used for SIGSEGV on netware */ +/* 6 is used for SIGTERM on netware */ +/* 7 is used for SIGPOLL on netware */ + +#define SIGKILL 11 +#define SA_NOCLDSTOP 12 +#define SIGALRM 13 +#define SIGCHLD 14 +#define SIGCONT 15 +#define SIGHUP 16 +#define SIGPIPE 17 +#define SIGQUIT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGUSR1 23 +#define SIGUSR2 24 + +#define SIGTRAP 25 +#define SIGIOT 26 +#define SIGBUS 27 +#define SIGSTKFLT 28 +#define SIGURG 29 +#define SIGXCPU 30 +#define SIGXFSZ 31 +#define SIGVTALRM 32 +#define SIGPROF 33 +#define SIGWINCH 34 +#define SIGIO 35 + +#if 0 +#define __attribute__(__x) + +/* APR COMPATABILITY FUNCTIONS + * This section should be used to define functions and + * macros which are need to make Windows features look + * like POSIX features. + */ +typedef void (Sigfunc)(int); +#endif + +#define strcasecmp(s1, s2) stricmp(s1, s2) +#define Sleep(t) delay(t) +#define lstat(a,b) stat(a,b) +#define _getch() getcharacter() + +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONGLONG 8 +#define SIZEOF_CHAR 1 +#define SIZEOF_SSIZE_T SIZEOF_INT + +void netware_pool_proc_cleanup (); + +/* NLM registration routines for managing which NLMs + are using the library. */ +int register_NLM(void *NLMHandle); +int unregister_NLM(void *NLMHandle); + +/* Application global data management */ +extern int gLibId; +extern void *gLibHandle; + +typedef struct app_data { + int initialized; + void* gPool; + void* gs_aHooksToSort; + void* gs_phOptionalHooks; + void* gs_phOptionalFunctions; + void* gs_nlmhandle; + rtag_t gs_startup_rtag; + rtag_t gs_socket_rtag; + rtag_t gs_lookup_rtag; + rtag_t gs_event_rtag; + rtag_t gs_pcp_rtag; +} APP_DATA; + +int setGlobalPool(void *data); +void* getGlobalPool(); +int setStatCache(void *data); +void* getStatCache(); + +/* Redefine malloc to use the library malloc call so + that all of the memory resources will be owned + and can be shared by the library. */ +#undef malloc +#define malloc(x) library_malloc(gLibHandle,x) + +#if APR_HAS_LARGE_FILES +#define APR_OFF_T_STRFN strtoll +#else +#define APR_OFF_T_STRFN strtol +#endif + +/* used to check DWORD overflow for 64bit compiles */ +#define APR_DWORD_MAX 0xFFFFFFFFUL + +/* + * Include common private declarations. + */ +#include "../apr_private_common.h" + +#endif /*APR_PRIVATE_H*/ +#endif /*NETWARE*/ diff --git a/srclib/apr/include/arch/os2/apr_arch_dso.h b/srclib/apr/include/arch/os2/apr_arch_dso.h new file mode 100644 index 0000000000..9a202a3fa2 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_dso.h @@ -0,0 +1,37 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#if APR_HAS_DSO + +struct apr_dso_handle_t { + apr_pool_t *cont; /* Context for returning error strings */ + HMODULE handle; /* Handle to the DSO loaded */ + apr_status_t load_error; + char *failed_module; +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/os2/apr_arch_file_io.h b/srclib/apr/include/arch/os2/apr_arch_file_io.h new file mode 100644 index 0000000000..26045c1f65 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_file_io.h @@ -0,0 +1,81 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILE_IO_H +#define FILE_IO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_thread_mutex.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_poll.h" + +/* We have an implementation of mkstemp but it's not very multi-threading + * friendly & is part of the POSIX emulation rather than native so don't + * use it. + */ +#undef HAVE_MKSTEMP + +#define APR_FILE_BUFSIZE 4096 + +struct apr_file_t { + apr_pool_t *pool; + HFILE filedes; + char * fname; + int isopen; + int buffered; + int eof_hit; + apr_int32_t flags; + int timeout; + int pipe; + HEV pipeSem; + enum { BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking; + + /* Stuff for buffered mode */ + char *buffer; + int bufpos; // Read/Write position in buffer + unsigned long dataRead; // amount of valid data read into buffer + int direction; // buffer being used for 0 = read, 1 = write + unsigned long filePtr; // position in file of handle + apr_thread_mutex_t *mutex;// mutex semaphore, must be owned to access the above fields +}; + +struct apr_dir_t { + apr_pool_t *pool; + char *dirname; + ULONG handle; + FILEFINDBUF3 entry; + int validentry; +}; + +apr_status_t apr_file_cleanup(void *); +apr_status_t apr_os2_time_to_apr_time(apr_time_t *result, FDATE os2date, + FTIME os2time); + +/* see win32/fileio.h for description of these */ +extern const char c_is_fnchar[256]; + +#define IS_FNCHAR(c) c_is_fnchar[(unsigned char)c] + +apr_status_t filepath_root_test(char *path, apr_pool_t *p); +apr_status_t filepath_drive_get(char **rootpath, char drive, + apr_int32_t flags, apr_pool_t *p); +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p); + +#endif /* ! FILE_IO_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_networkio.h b/srclib/apr/include/arch/os2/apr_arch_networkio.h new file mode 100644 index 0000000000..43151ed2a0 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_networkio.h @@ -0,0 +1,76 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_IO_H +#define NETWORK_IO_H + +#include "apr_private.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_arch_os2calls.h" +#include "apr_poll.h" + +#if APR_HAVE_NETDB_H +#include +#endif + +typedef struct sock_userdata_t sock_userdata_t; +struct sock_userdata_t { + sock_userdata_t *next; + const char *key; + void *data; +}; + +struct apr_socket_t { + apr_pool_t *cntxt; + int socketdes; + int type; + int protocol; + apr_sockaddr_t *local_addr; + apr_sockaddr_t *remote_addr; + apr_interval_time_t timeout; + int nonblock; + int local_port_unknown; + int local_interface_unknown; + int remote_addr_unknown; + apr_int32_t options; + apr_int32_t inherit; + sock_userdata_t *userdata; + + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; +}; + +/* Error codes returned from sock_errno() */ +#define SOCBASEERR 10000 +#define SOCEPERM (SOCBASEERR+1) /* Not owner */ +#define SOCESRCH (SOCBASEERR+3) /* No such process */ +#define SOCEINTR (SOCBASEERR+4) /* Interrupted system call */ +#define SOCENXIO (SOCBASEERR+6) /* No such device or address */ +#define SOCEBADF (SOCBASEERR+9) /* Bad file number */ +#define SOCEACCES (SOCBASEERR+13) /* Permission denied */ +#define SOCEFAULT (SOCBASEERR+14) /* Bad address */ +#define SOCEINVAL (SOCBASEERR+22) /* Invalid argument */ +#define SOCEMFILE (SOCBASEERR+24) /* Too many open files */ +#define SOCEPIPE (SOCBASEERR+32) /* Broken pipe */ +#define SOCEOS2ERR (SOCBASEERR+100) /* OS/2 Error */ + +const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size); +int apr_inet_pton(int af, const char *src, void *dst); +void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t); + +#endif /* ! NETWORK_IO_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_os2calls.h b/srclib/apr/include/arch/os2/apr_arch_os2calls.h new file mode 100644 index 0000000000..3705ee94a5 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_os2calls.h @@ -0,0 +1,59 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_errno.h" +#include +#include + +extern int (*apr_os2_socket)(int, int, int); +extern int (*apr_os2_select)(int *, int, int, int, long); +extern int (*apr_os2_sock_errno)(); +extern int (*apr_os2_accept)(int, struct sockaddr *, int *); +extern int (*apr_os2_bind)(int, struct sockaddr *, int); +extern int (*apr_os2_connect)(int, struct sockaddr *, int); +extern int (*apr_os2_getpeername)(int, struct sockaddr *, int *); +extern int (*apr_os2_getsockname)(int, struct sockaddr *, int *); +extern int (*apr_os2_getsockopt)(int, int, int, char *, int *); +extern int (*apr_os2_ioctl)(int, int, caddr_t, int); +extern int (*apr_os2_listen)(int, int); +extern int (*apr_os2_recv)(int, char *, int, int); +extern int (*apr_os2_send)(int, const char *, int, int); +extern int (*apr_os2_setsockopt)(int, int, int, char *, int); +extern int (*apr_os2_shutdown)(int, int); +extern int (*apr_os2_soclose)(int); +extern int (*apr_os2_writev)(int, struct iovec *, int); +extern int (*apr_os2_sendto)(int, const char *, int, int, const struct sockaddr *, int); +extern int (*apr_os2_recvfrom)(int, char *, int, int, struct sockaddr *, int *); + +#define socket apr_os2_socket +#define select apr_os2_select +#define sock_errno apr_os2_sock_errno +#define accept apr_os2_accept +#define bind apr_os2_bind +#define connect apr_os2_connect +#define getpeername apr_os2_getpeername +#define getsockname apr_os2_getsockname +#define getsockopt apr_os2_getsockopt +#define ioctl apr_os2_ioctl +#define listen apr_os2_listen +#define recv apr_os2_recv +#define send apr_os2_send +#define setsockopt apr_os2_setsockopt +#define shutdown apr_os2_shutdown +#define soclose apr_os2_soclose +#define writev apr_os2_writev +#define sendto apr_os2_sendto +#define recvfrom apr_os2_recvfrom diff --git a/srclib/apr/include/arch/os2/apr_arch_proc_mutex.h b/srclib/apr/include/arch/os2/apr_arch_proc_mutex.h new file mode 100644 index 0000000000..737a162da1 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_proc_mutex.h @@ -0,0 +1,31 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_MUTEX_H +#define PROC_MUTEX_H + +#include "apr_proc_mutex.h" +#include "apr_file_io.h" + +struct apr_proc_mutex_t { + apr_pool_t *pool; + HMTX hMutex; + TID owner; + int lock_count; +}; + +#endif /* PROC_MUTEX_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_thread_cond.h b/srclib/apr/include/arch/os2/apr_arch_thread_cond.h new file mode 100644 index 0000000000..05d56b6e21 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_thread_cond.h @@ -0,0 +1,28 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_COND_H +#define THREAD_COND_H + +#include "apr_thread_cond.h" +#include "apr_file_io.h" + +struct apr_thread_cond_t { + apr_pool_t *pool; +}; + +#endif /* THREAD_COND_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_thread_mutex.h b/srclib/apr/include/arch/os2/apr_arch_thread_mutex.h new file mode 100644 index 0000000000..b445429435 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_thread_mutex.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MUTEX_H +#define THREAD_MUTEX_H + +#include "apr_thread_mutex.h" +#include "apr_file_io.h" + +struct apr_thread_mutex_t { + apr_pool_t *pool; + HMTX hMutex; +}; + +#endif /* THREAD_MUTEX_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_thread_rwlock.h b/srclib/apr/include/arch/os2/apr_arch_thread_rwlock.h new file mode 100644 index 0000000000..b942d595e3 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_thread_rwlock.h @@ -0,0 +1,31 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_RWLOCK_H +#define THREAD_RWLOCK_H + +#include "apr_thread_rwlock.h" +#include "apr_file_io.h" + +struct apr_thread_rwlock_t { + apr_pool_t *pool; + int readers; + HMTX write_lock; + HEV read_done; +}; + +#endif /* THREAD_RWLOCK_H */ + diff --git a/srclib/apr/include/arch/os2/apr_arch_threadproc.h b/srclib/apr/include/arch/os2/apr_arch_threadproc.h new file mode 100644 index 0000000000..91ed2e3f93 --- /dev/null +++ b/srclib/apr/include/arch/os2/apr_arch_threadproc.h @@ -0,0 +1,67 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_thread_proc.h" +#include "apr_file_io.h" + +#ifndef THREAD_PROC_H +#define THREAD_PROC_H + +#define APR_THREADATTR_DETACHED 1 + +#define SHELL_PATH "cmd.exe" +#define APR_THREAD_STACKSIZE 65536 + +struct apr_threadattr_t { + apr_pool_t *pool; + unsigned long attr; + apr_size_t stacksize; +}; + +struct apr_thread_t { + apr_pool_t *pool; + struct apr_threadattr_t *attr; + unsigned long tid; + apr_thread_start_t func; + void *data; + apr_status_t exitval; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + unsigned long *key; +}; + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; +}; + +struct apr_thread_once_t { + unsigned long sem; + char hit; +}; + +#endif /* ! THREAD_PROC_H */ + diff --git a/srclib/apr/include/arch/os390/apr_arch_dso.h b/srclib/apr/include/arch/os390/apr_arch_dso.h new file mode 100644 index 0000000000..2cd2112a21 --- /dev/null +++ b/srclib/apr/include/arch/os390/apr_arch_dso.h @@ -0,0 +1,39 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#if APR_HAS_DSO + +#include + +struct apr_dso_handle_t { + dllhandle *handle; /* Handle to the DSO loaded */ + int failing_errno; /* Don't save the buffer returned by + strerror(); it gets reused */ + apr_pool_t *pool; +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/unix/apr_arch_dso.h b/srclib/apr/include/arch/unix/apr_arch_dso.h new file mode 100644 index 0000000000..e5d9d8305f --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_dso.h @@ -0,0 +1,63 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#if APR_HAS_DSO + +#ifdef HAVE_MACH_O_DYLD_H +#include +#endif + +#ifdef HAVE_DLFCN_H +#include +#endif + +#ifdef HAVE_DL_H +#include +#endif + +#ifndef RTLD_NOW +#define RTLD_NOW 1 +#endif + +#ifndef RTLD_GLOBAL +#define RTLD_GLOBAL 0 +#endif + +#if (defined(__DragonFly__) ||\ + defined(__FreeBSD__) ||\ + defined(__OpenBSD__) ||\ + defined(__NetBSD__) ) && !defined(__ELF__) +#define DLSYM_NEEDS_UNDERSCORE +#endif + +struct apr_dso_handle_t { + apr_pool_t *pool; + void *handle; + const char *errormsg; +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/unix/apr_arch_file_io.h b/srclib/apr/include/arch/unix/apr_arch_file_io.h new file mode 100644 index 0000000000..1d10b04903 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_file_io.h @@ -0,0 +1,138 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILE_IO_H +#define FILE_IO_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_tables.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_lib.h" +#include "apr_thread_mutex.h" +#ifndef WAITIO_USES_POLL +#include "apr_poll.h" +#endif + +/* System headers the file I/O library needs */ +#if APR_HAVE_FCNTL_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_ERRNO_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif +#if APR_HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_SYS_UIO_H +#include +#endif +#if APR_HAVE_SYS_TIME_H +#include +#endif +#ifdef BEOS +#include +#endif + +#if BEOS_BONE +# ifndef BONE7 + /* prior to BONE/7 fd_set & select were defined in sys/socket.h */ +# include +# else + /* Be moved the fd_set stuff and also the FIONBIO definition... */ +# include +# endif +#endif +/* End System headers */ + +#define APR_FILE_BUFSIZE 4096 + +struct apr_file_t { + apr_pool_t *pool; + int filedes; + char *fname; + apr_int32_t flags; + int eof_hit; + int is_pipe; + apr_interval_time_t timeout; + int buffered; + enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking; + int ungetchar; /* Last char provided by an unget op. (-1 = no char)*/ +#ifndef WAITIO_USES_POLL + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; +#endif + /* Stuff for buffered mode */ + char *buffer; + int bufpos; /* Read/Write position in buffer */ + unsigned long dataRead; /* amount of valid data read into buffer */ + int direction; /* buffer being used for 0 = read, 1 = write */ + unsigned long filePtr; /* position in file of handle */ +#if APR_HAS_THREADS + struct apr_thread_mutex_t *thlock; +#endif +}; + +#if APR_HAS_LARGE_FILES && defined(_LARGEFILE64_SOURCE) +#define stat(f,b) stat64(f,b) +#define lstat(f,b) lstat64(f,b) +#define fstat(f,b) fstat64(f,b) +#define lseek(f,o,w) lseek64(f,o,w) +#define ftruncate(f,l) ftruncate64(f,l) +typedef struct stat64 struct_stat; +#else +typedef struct stat struct_stat; +#endif + +struct apr_dir_t { + apr_pool_t *pool; + char *dirname; + DIR *dirstruct; + struct dirent *entry; +}; + +apr_status_t apr_unix_file_cleanup(void *); + +mode_t apr_unix_perms2mode(apr_fileperms_t perms); +apr_fileperms_t apr_unix_mode2perms(mode_t mode); + + +#endif /* ! FILE_IO_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_global_mutex.h b/srclib/apr/include/arch/unix/apr_arch_global_mutex.h new file mode 100644 index 0000000000..e5724dc7b0 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_global_mutex.h @@ -0,0 +1,37 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef GLOBAL_MUTEX_H +#define GLOBAL_MUTEX_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_global_mutex.h" +#include "apr_arch_proc_mutex.h" +#include "apr_arch_thread_mutex.h" + +struct apr_global_mutex_t { + apr_pool_t *pool; + apr_proc_mutex_t *proc_mutex; +#if APR_HAS_THREADS + apr_thread_mutex_t *thread_mutex; +#endif /* APR_HAS_THREADS */ +}; + +#endif /* GLOBAL_MUTEX_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_inherit.h b/srclib/apr/include/arch/unix/apr_arch_inherit.h new file mode 100644 index 0000000000..22914e2ef6 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_inherit.h @@ -0,0 +1,52 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INHERIT_H +#define INHERIT_H + +#include "apr_inherit.h" + +#define APR_INHERIT (1 << 24) /* Must not conflict with other bits */ + +#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup) \ +apr_status_t apr_##name##_inherit_set(apr_##name##_t *the##name) \ +{ \ + if (the##name->flag & APR_FILE_NOCLEANUP) \ + return APR_EINVAL; \ + if (!(the##name->flag & APR_INHERIT)) { \ + the##name->flag |= APR_INHERIT; \ + apr_pool_child_cleanup_set(the##name->pool, \ + (void *)the##name, \ + cleanup, apr_pool_cleanup_null); \ + } \ + return APR_SUCCESS; \ +} + +#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup) \ +apr_status_t apr_##name##_inherit_unset(apr_##name##_t *the##name) \ +{ \ + if (the##name->flag & APR_FILE_NOCLEANUP) \ + return APR_EINVAL; \ + if (the##name->flag & APR_INHERIT) { \ + the##name->flag &= ~APR_INHERIT; \ + apr_pool_child_cleanup_set(the##name->pool, \ + (void *)the##name, \ + cleanup, cleanup); \ + } \ + return APR_SUCCESS; \ +} + +#endif /* ! INHERIT_H */ diff --git a/srclib/apr/include/arch/unix/apr_arch_internal_time.h b/srclib/apr/include/arch/unix/apr_arch_internal_time.h new file mode 100644 index 0000000000..321921e9fc --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_internal_time.h @@ -0,0 +1,24 @@ +/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIME_INTERNAL_H +#define TIME_INTERNAL_H + +#include "apr.h" + +void apr_unix_setup_time(void); + +#endif /* TIME_INTERNAL_H */ diff --git a/srclib/apr/include/arch/unix/apr_arch_misc.h b/srclib/apr/include/arch/unix/apr_arch_misc.h new file mode 100644 index 0000000000..4168a2b5cc --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_misc.h @@ -0,0 +1,67 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISC_H +#define MISC_H + +#include "apr.h" +#include "apr_portable.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_getopt.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_getopt.h" + +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_SIGNAL_H +#include +#endif +#if APR_HAVE_PTHREAD_H +#include +#endif + +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif + +#ifdef BEOS +#include +#endif + +struct apr_other_child_rec_t { + apr_pool_t *p; + struct apr_other_child_rec_t *next; + apr_proc_t *proc; + void (*maintenance) (int, void *, int); + void *data; + apr_os_file_t write_fd; +}; + +#if defined(WIN32) || defined(NETWARE) +#define WSAHighByte 2 +#define WSALowByte 0 +#endif + +#endif /* ! MISC_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_networkio.h b/srclib/apr/include/arch/unix/apr_arch_networkio.h new file mode 100644 index 0000000000..c55616ddbf --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_networkio.h @@ -0,0 +1,142 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_IO_H +#define NETWORK_IO_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#ifndef WAITIO_USES_POLL +#include "apr_poll.h" +#endif + +/* System headers the network I/O library needs */ +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_UIO_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#if APR_HAVE_ERRNO_H +#include +#endif +#if APR_HAVE_SYS_TIME_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_NETINET_TCP_H +#include +#endif +#if APR_HAVE_NETINET_SCTP_UIO_H +#include +#endif +#if APR_HAVE_NETINET_SCTP_H +#include +#endif +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif +#if APR_HAVE_SYS_SOCKET_H +#include +#endif +#if APR_HAVE_SYS_SOCKIO_H +#include +#endif +#if APR_HAVE_NETDB_H +#include +#endif +#if APR_HAVE_FCNTL_H +#include +#endif +#if APR_HAVE_SYS_SENDFILE_H +#include +#endif +#if APR_HAVE_SYS_IOCTL_H +#include +#endif +/* End System Headers */ + +#ifndef HAVE_POLLIN +#define POLLIN 1 +#define POLLPRI 2 +#define POLLOUT 4 +#define POLLERR 8 +#define POLLHUP 16 +#define POLLNVAL 32 +#endif + +typedef struct sock_userdata_t sock_userdata_t; +struct sock_userdata_t { + sock_userdata_t *next; + const char *key; + void *data; +}; + +struct apr_socket_t { + apr_pool_t *cntxt; + int socketdes; + int type; + int protocol; + apr_sockaddr_t *local_addr; + apr_sockaddr_t *remote_addr; + apr_interval_time_t timeout; +#ifndef HAVE_POLL + int connected; +#endif + int local_port_unknown; + int local_interface_unknown; + int remote_addr_unknown; + apr_int32_t options; + apr_int32_t inherit; + sock_userdata_t *userdata; +#ifndef WAITIO_USES_POLL + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; +#endif +}; + +const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size); +int apr_inet_pton(int af, const char *src, void *dst); +void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t); + +#define apr_is_option_set(skt, option) \ + (((skt)->options & (option)) == (option)) + +#define apr_set_option(skt, option, on) \ + do { \ + if (on) \ + (skt)->options |= (option); \ + else \ + (skt)->options &= ~(option); \ + } while (0) + +#endif /* ! NETWORK_IO_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_poll_private.h b/srclib/apr/include/arch/unix/apr_arch_poll_private.h new file mode 100644 index 0000000000..c653a8084a --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_poll_private.h @@ -0,0 +1,100 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_ARCH_POLL_PRIVATE_H +#define APR_ARCH_POLL_PRIVATE_H + +#include "apr.h" +#include "apr_poll.h" +#include "apr_time.h" +#include "apr_portable.h" +#include "apr_arch_networkio.h" +#include "apr_arch_file_io.h" + +#if HAVE_POLL_H +#include +#endif + +#if HAVE_SYS_POLL_H +#include +#endif + +#ifdef HAVE_PORT_CREATE +#include +#include +#endif + +#ifdef HAVE_KQUEUE +#include +#include +#include +#endif + +#ifdef HAVE_EPOLL +#include +#endif + +#ifdef NETWARE +#define HAS_SOCKETS(dt) (dt == APR_POLL_SOCKET) ? 1 : 0 +#define HAS_PIPES(dt) (dt == APR_POLL_FILE) ? 1 : 0 +#endif + +/* Choose the best method platform specific to use in apr_pollset */ +#ifdef HAVE_KQUEUE +#define POLLSET_USES_KQUEUE +#elif defined(HAVE_PORT_CREATE) +#define POLLSET_USES_PORT +#elif defined(HAVE_EPOLL) +#define POLLSET_USES_EPOLL +#elif defined(HAVE_POLL) +#define POLLSET_USES_POLL +#else +#define POLLSET_USES_SELECT +#endif + +#ifdef HAVE_POLL +#define POLL_USES_POLL +#else +#define POLL_USES_SELECT +#endif + +#if defined(POLLSET_USES_KQUEUE) || defined(POLLSET_USES_EPOLL) || defined(POLLSET_USES_PORT) + +#include "apr_ring.h" + +#if APR_HAS_THREADS +#include "apr_thread_mutex.h" +#define pollset_lock_rings() \ + if (pollset->flags & APR_POLLSET_THREADSAFE) \ + apr_thread_mutex_lock(pollset->ring_lock); +#define pollset_unlock_rings() \ + if (pollset->flags & APR_POLLSET_THREADSAFE) \ + apr_thread_mutex_unlock(pollset->ring_lock); +#else +#define pollset_lock_rings() +#define pollset_unlock_rings() +#endif + +typedef struct pfd_elem_t pfd_elem_t; + +struct pfd_elem_t { + APR_RING_ENTRY(pfd_elem_t) link; + apr_pollfd_t pfd; +}; + +#endif + +#endif /* APR_ARCH_POLL_PRIVATE_H */ diff --git a/srclib/apr/include/arch/unix/apr_arch_proc_mutex.h b/srclib/apr/include/arch/unix/apr_arch_proc_mutex.h new file mode 100644 index 0000000000..3ed046cb11 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_proc_mutex.h @@ -0,0 +1,113 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_MUTEX_H +#define PROC_MUTEX_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_proc_mutex.h" +#include "apr_pools.h" +#include "apr_portable.h" +#include "apr_file_io.h" +#include "apr_arch_file_io.h" + +/* System headers required by Locks library */ +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_SYS_IPC_H +#include +#endif +#ifdef HAVE_SYS_SEM_H +#include +#endif +#ifdef HAVE_SYS_FILE_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#if APR_HAVE_PTHREAD_H +#include +#endif +#if APR_HAVE_SEMAPHORE_H +#include +#endif +/* End System Headers */ + +struct apr_proc_mutex_unix_lock_methods_t { + unsigned int flags; + apr_status_t (*create)(apr_proc_mutex_t *, const char *); + apr_status_t (*acquire)(apr_proc_mutex_t *); + apr_status_t (*tryacquire)(apr_proc_mutex_t *); + apr_status_t (*release)(apr_proc_mutex_t *); + apr_status_t (*cleanup)(void *); + apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *); + const char *name; +}; +typedef struct apr_proc_mutex_unix_lock_methods_t apr_proc_mutex_unix_lock_methods_t; + +/* bit values for flags field in apr_unix_lock_methods_t */ +#define APR_PROCESS_LOCK_MECH_IS_GLOBAL 1 + +#if !APR_HAVE_UNION_SEMUN && defined(APR_HAS_SYSVSEM_SERIALIZE) +union semun { + int val; + struct semid_ds *buf; + unsigned short *array; +}; +#endif + +struct apr_proc_mutex_t { + apr_pool_t *pool; + const apr_proc_mutex_unix_lock_methods_t *meth; + const apr_proc_mutex_unix_lock_methods_t *inter_meth; + int curr_locked; + char *fname; +#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE + apr_file_t *interproc; +#endif +#if APR_HAS_POSIXSEM_SERIALIZE + sem_t *psem_interproc; +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + pthread_mutex_t *pthread_interproc; +#endif +}; + +void apr_proc_mutex_unix_setup_lock(void); + +#endif /* PROC_MUTEX_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_shm.h b/srclib/apr/include/arch/unix/apr_arch_shm.h new file mode 100644 index 0000000000..b57df765fa --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_shm.h @@ -0,0 +1,70 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SHM_H +#define SHM_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_shm.h" +#include "apr_pools.h" +#include "apr_file_io.h" +#include "apr_network_io.h" +#include "apr_portable.h" + +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#ifdef HAVE_SYS_IPC_H +#include +#endif +#ifdef HAVE_SYS_MUTEX_H +#include +#endif +#ifdef HAVE_SYS_SHM_H +#include +#endif +#if !defined(SHM_R) +#define SHM_R 0400 +#endif +#if !defined(SHM_W) +#define SHM_W 0200 +#endif +#ifdef HAVE_SYS_FILE_H +#include +#endif + +/* Not all systems seem to have MAP_FAILED defined, but it should always + * just be (void *)-1. */ +#ifndef MAP_FAILED +#define MAP_FAILED ((void *)-1) +#endif + +struct apr_shm_t { + apr_pool_t *pool; + void *base; /* base real address */ + void *usable; /* base usable address */ + apr_size_t reqsize; /* requested segment size */ + apr_size_t realsize; /* actual segment size */ + const char *filename; /* NULL if anonymous */ +#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON + int shmid; /* shmem ID returned from shmget() */ +#endif +}; + +#endif /* SHM_H */ diff --git a/srclib/apr/include/arch/unix/apr_arch_thread_cond.h b/srclib/apr/include/arch/unix/apr_arch_thread_cond.h new file mode 100644 index 0000000000..643b01d59e --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_thread_cond.h @@ -0,0 +1,42 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_COND_H +#define THREAD_COND_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_thread_mutex.h" +#include "apr_thread_cond.h" +#include "apr_pools.h" + +#if APR_HAVE_PTHREAD_H +#include +#endif + +/* XXX: Should we have a better autoconf search, something like + * APR_HAS_PTHREAD_COND? -aaron */ +#if APR_HAS_THREADS +struct apr_thread_cond_t { + apr_pool_t *pool; + pthread_cond_t cond; +}; +#endif + +#endif /* THREAD_COND_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_thread_mutex.h b/srclib/apr/include/arch/unix/apr_arch_thread_mutex.h new file mode 100644 index 0000000000..6b1b6717b5 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_thread_mutex.h @@ -0,0 +1,39 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MUTEX_H +#define THREAD_MUTEX_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_thread_mutex.h" +#include "apr_portable.h" +#include "apr_atomic.h" + +#if APR_HAVE_PTHREAD_H +#include +#endif + +#if APR_HAS_THREADS +struct apr_thread_mutex_t { + apr_pool_t *pool; + pthread_mutex_t mutex; +}; +#endif + +#endif /* THREAD_MUTEX_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_thread_rwlock.h b/srclib/apr/include/arch/unix/apr_arch_thread_rwlock.h new file mode 100644 index 0000000000..c4631897c2 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_thread_rwlock.h @@ -0,0 +1,49 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_RWLOCK_H +#define THREAD_RWLOCK_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_thread_rwlock.h" +#include "apr_pools.h" + +#if APR_HAVE_PTHREAD_H +/* this gives us pthread_rwlock_t */ +#include +#endif + +#if APR_HAS_THREADS +#ifdef HAVE_PTHREAD_RWLOCKS + +struct apr_thread_rwlock_t { + apr_pool_t *pool; + pthread_rwlock_t rwlock; +}; + +#else + +struct apr_thread_rwlock_t { + apr_pool_t *pool; +}; +#endif + +#endif + +#endif /* THREAD_RWLOCK_H */ + diff --git a/srclib/apr/include/arch/unix/apr_arch_threadproc.h b/srclib/apr/include/arch/unix/apr_arch_threadproc.h new file mode 100644 index 0000000000..bb91ef7f75 --- /dev/null +++ b/srclib/apr/include/arch/unix/apr_arch_threadproc.h @@ -0,0 +1,106 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_arch_file_io.h" + +/* System headers required for thread/process library */ +#if APR_HAVE_PTHREAD_H +#include +#endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#if APR_HAVE_SIGNAL_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_SYS_WAIT_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +/* End System Headers */ + + +#ifndef THREAD_PROC_H +#define THREAD_PROC_H + +#define SHELL_PATH "/bin/sh" + +#if APR_HAS_THREADS + +struct apr_thread_t { + apr_pool_t *pool; + pthread_t *td; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + pthread_attr_t attr; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + pthread_key_t key; +}; + +struct apr_thread_once_t { + pthread_once_t once; +}; + +#endif + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; +#ifdef RLIMIT_CPU + struct rlimit *limit_cpu; +#endif +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) + struct rlimit *limit_mem; +#endif +#ifdef RLIMIT_NPROC + struct rlimit *limit_nproc; +#endif +#ifdef RLIMIT_NOFILE + struct rlimit *limit_nofile; +#endif + apr_child_errfn_t *errfn; + apr_int32_t errchk; + apr_uid_t uid; + apr_gid_t gid; +}; + +#endif /* ! THREAD_PROC_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_atime.h b/srclib/apr/include/arch/win32/apr_arch_atime.h new file mode 100644 index 0000000000..bf09a3289c --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_atime.h @@ -0,0 +1,63 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ATIME_H +#define ATIME_H + +#include "apr_private.h" +#include "apr_time.h" +#if APR_HAVE_TIME_H +#include +#endif + +struct atime_t { + apr_pool_t *cntxt; + apr_time_t currtime; + SYSTEMTIME *explodedtime; +}; + + +/* Number of micro-seconds between the beginning of the Windows epoch + * (Jan. 1, 1601) and the Unix epoch (Jan. 1, 1970) + */ +#define APR_DELTA_EPOCH_IN_USEC APR_TIME_C(11644473600000000); + + +__inline void FileTimeToAprTime(apr_time_t *result, FILETIME *input) +{ + /* Convert FILETIME one 64 bit number so we can work with it. */ + *result = input->dwHighDateTime; + *result = (*result) << 32; + *result |= input->dwLowDateTime; + *result /= 10; /* Convert from 100 nano-sec periods to micro-seconds. */ + *result -= APR_DELTA_EPOCH_IN_USEC; /* Convert from Windows epoch to Unix epoch */ + return; +} + + +__inline void AprTimeToFileTime(LPFILETIME pft, apr_time_t t) +{ + LONGLONG ll; + t += APR_DELTA_EPOCH_IN_USEC; + ll = t * 10; + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = (DWORD) (ll >> 32); + return; +} + + +#endif /* ! ATIME_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_dso.h b/srclib/apr/include/arch/win32/apr_arch_dso.h new file mode 100644 index 0000000000..e26f4ecc71 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_dso.h @@ -0,0 +1,36 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DSO_H +#define DSO_H + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_dso.h" +#include "apr.h" + +#if APR_HAS_DSO + +struct apr_dso_handle_t { + apr_pool_t *cont; + void *handle; + apr_status_t load_error; +}; + +#endif + +#endif diff --git a/srclib/apr/include/arch/win32/apr_arch_file_io.h b/srclib/apr/include/arch/win32/apr_arch_file_io.h new file mode 100644 index 0000000000..3af8720b9f --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_file_io.h @@ -0,0 +1,278 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FILE_IO_H +#define FILE_IO_H + +#include "apr.h" +#include "apr_private.h" +#include "apr_pools.h" +#include "apr_general.h" +#include "apr_tables.h" +#include "apr_thread_mutex.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_arch_misc.h" +#include "apr_poll.h" + +#ifdef HAVE_SYS_STAT_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_FCNTL_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#if APR_HAVE_DIRENT_H +#include +#endif +#ifdef HAVE_MALLOC_H +#include +#endif + +#if APR_HAS_UNICODE_FS +#include "arch/win32/apr_arch_utf8.h" +#include + +typedef apr_uint16_t apr_wchar_t; + +/* Helper functions for the WinNT ApiW() functions. APR treats all + * resource identifiers (files, etc) by their UTF-8 name, to provide + * access to all named identifiers. [UTF-8 completely maps Unicode + * into char type strings.] + * + * The _path flavors below provide us fast mappings of the + * Unicode filename //?/D:/path and //?/UNC/mach/share/path mappings, + * which allow unlimited (well, 32000 wide character) length names. + * These prefixes may appear in Unicode, but must not appear in the + * Ascii API calls. So we tack them on in utf8_to_unicode_path, and + * strip them right back off in unicode_to_utf8_path. + */ +apr_status_t utf8_to_unicode_path(apr_wchar_t* dststr, apr_size_t dstchars, + const char* srcstr); +apr_status_t unicode_to_utf8_path(char* dststr, apr_size_t dstchars, + const apr_wchar_t* srcstr); + +#endif /* APR_HAS_UNICODE_FS */ + +/* Another Helper functions for the WinNT ApiW() functions. We need to + * derive some 'resource' names (max length 255 characters, prefixed with + * Global/ or Local/ on WinNT) from something that looks like a filename. + * Since 'resource' names never contain slashes, convert these to '_'s + * and return the appropriate char* or wchar* for ApiA or ApiW calls. + */ + +void *res_name_from_filename(const char *file, int global, apr_pool_t *pool); + +#define APR_FILE_MAX MAX_PATH + +#define APR_FILE_BUFSIZE 4096 + +/* obscure ommissions from msvc's sys/stat.h */ +#ifdef _MSC_VER +#define S_IFIFO _S_IFIFO /* pipe */ +#define S_IFBLK 0060000 /* Block Special */ +#define S_IFLNK 0120000 /* Symbolic Link */ +#define S_IFSOCK 0140000 /* Socket */ +#define S_IFWHT 0160000 /* Whiteout */ +#endif + +/* Internal Flags for apr_file_open */ +#define APR_OPENINFO 0x00100000 /* Open without READ or WRITE access */ +#define APR_OPENLINK 0x00200000 /* Open a link itself, if supported */ +#define APR_READCONTROL 0x00400000 /* Read the file's owner/perms */ +#define APR_WRITECONTROL 0x00800000 /* Modifythe file's owner/perms */ +#define APR_WRITEATTRS 0x01000000 /* Modify the file's attributes */ + +/* Entries missing from the MSVC 5.0 Win32 SDK: + */ +#ifndef FILE_ATTRIBUTE_DEVICE +#define FILE_ATTRIBUTE_DEVICE 0x00000040 +#endif +#ifndef FILE_ATTRIBUTE_REPARSE_POINT +#define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400 +#endif +#ifndef FILE_FLAG_OPEN_NO_RECALL +#define FILE_FLAG_OPEN_NO_RECALL 0x00100000 +#endif +#ifndef FILE_FLAG_OPEN_REPARSE_POINT +#define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000 +#endif +#ifndef TRUSTEE_IS_WELL_KNOWN_GROUP +#define TRUSTEE_IS_WELL_KNOWN_GROUP 5 +#endif + +/* Information bits available from the WIN32 FindFirstFile function */ +#define APR_FINFO_WIN32_DIR (APR_FINFO_NAME | APR_FINFO_TYPE \ + | APR_FINFO_CTIME | APR_FINFO_ATIME \ + | APR_FINFO_MTIME | APR_FINFO_SIZE) + +/* Sneak the Readonly bit through finfo->protection for internal use _only_ */ +#define APR_FREADONLY 0x10000000 + +/* Private function for apr_stat/lstat/getfileinfo/dir_read */ +int fillin_fileinfo(apr_finfo_t *finfo, WIN32_FILE_ATTRIBUTE_DATA *wininfo, + int byhandle, apr_int32_t wanted); + +/* Private function that extends apr_stat/lstat/getfileinfo/dir_read */ +apr_status_t more_finfo(apr_finfo_t *finfo, const void *ufile, + apr_int32_t wanted, int whatfile); + +/* whatfile types for the ufile arg */ +#define MORE_OF_HANDLE 0 +#define MORE_OF_FSPEC 1 +#define MORE_OF_WFSPEC 2 + +/* quick run-down of fields in windows' apr_file_t structure that may have + * obvious uses. + * fname -- the filename as passed to the open call. + * dwFileAttricutes -- Attributes used to open the file. + * append -- Windows doesn't support the append concept when opening files. + * APR needs to keep track of this, and always make sure we append + * correctly when writing to a file with this flag set TRUE. + */ + +// for apr_poll.c; +#define filedes filehand + +struct apr_file_t { + apr_pool_t *pool; + HANDLE filehand; + BOOLEAN pipe; // Is this a pipe of a file? + OVERLAPPED *pOverlapped; + apr_interval_time_t timeout; + apr_int32_t flags; + + /* File specific info */ + apr_finfo_t *finfo; + char *fname; + DWORD dwFileAttributes; + int eof_hit; + BOOLEAN buffered; // Use buffered I/O? + int ungetchar; // Last char provided by an unget op. (-1 = no char) + int append; + + /* Stuff for buffered mode */ + char *buffer; + apr_size_t bufpos; // Read/Write position in buffer + apr_size_t dataRead; // amount of valid data read into buffer + int direction; // buffer being used for 0 = read, 1 = write + apr_off_t filePtr; // position in file of handle + apr_thread_mutex_t *mutex; // mutex semaphore, must be owned to access the above fields + + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; + + /* Pipe specific info */ +}; + +struct apr_dir_t { + apr_pool_t *pool; + HANDLE dirhand; + apr_size_t rootlen; + char *dirname; + char *name; + union { +#if APR_HAS_UNICODE_FS + struct { + WIN32_FIND_DATAW *entry; + } w; +#endif +#if APR_HAS_ANSI_FS + struct { + WIN32_FIND_DATAA *entry; + } n; +#endif + }; + int bof; +}; + +/* There are many goofy characters the filesystem can't accept + * or can confound the cmd.exe shell. Here's the list + * [declared in filesys.c] + */ +extern const char apr_c_is_fnchar[256]; + +#define IS_FNCHAR(c) (apr_c_is_fnchar[(unsigned char)(c)] & 1) +#define IS_SHCHAR(c) ((apr_c_is_fnchar[(unsigned char)(c)] & 2) == 2) + + +/* If the user passes APR_FILEPATH_TRUENAME to either + * apr_filepath_root or apr_filepath_merge, this fn determines + * that the root really exists. It's expensive, wouldn't want + * to do this too frequenly. + */ +apr_status_t filepath_root_test(char *path, apr_pool_t *p); + + +/* The apr_filepath_merge wants to canonicalize the cwd to the + * addpath if the user passes NULL as the old root path (this + * isn't true of an empty string "", which won't be concatenated. + * + * But we need to figure out what the cwd of a given volume is, + * when the user passes D:foo. This fn will determine D:'s cwd. + * + * If flags includes the bit APR_FILEPATH_NATIVE, the path returned + * is in the os-native format. + */ +apr_status_t filepath_drive_get(char **rootpath, char drive, + apr_int32_t flags, apr_pool_t *p); + + +/* If the user passes d: vs. D: (or //mach/share vs. //MACH/SHARE), + * we need to fold the case to canonical form. This function is + * supposed to do so. + */ +apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p); + + +apr_status_t file_cleanup(void *); + +/** + * Internal function to create a Win32/NT pipe that respects some async + * timeout options. + * @param in new read end of the created pipe + * @param out new write end of the created pipe + * @param blocking_mode one of + *
    + *       APR_FULL_BLOCK
    + *       APR_READ_BLOCK
    + *       APR_WRITE_BLOCK
    + *       APR_FULL_NONBLOCK
    + * 
    + * @remark It so happens that APR_FULL_BLOCK and APR_FULL_NONBLOCK + * are common to apr_procattr_io_set() in, out and err modes. + * Because APR_CHILD_BLOCK and APR_WRITE_BLOCK share the same value, + * as do APR_PARENT_BLOCK and APR_READ_BLOCK, it's possible to use + * that value directly for creating the stdout/stderr pipes. When + * creating the stdin pipe, the values must be transposed. + * @see apr_procattr_io_set + */ +apr_status_t apr_create_nt_pipe(apr_file_t **in, apr_file_t **out, + apr_int32_t blocking_mode, + apr_pool_t *p); + +/** @see apr_create_nt_pipe */ +#define APR_READ_BLOCK 3 +/** @see apr_create_nt_pipe */ +#define APR_WRITE_BLOCK 4 + +#endif /* ! FILE_IO_H */ diff --git a/srclib/apr/include/arch/win32/apr_arch_inherit.h b/srclib/apr/include/arch/win32/apr_arch_inherit.h new file mode 100644 index 0000000000..b7eb1e673f --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_inherit.h @@ -0,0 +1,69 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef INHERIT_H +#define INHERIT_H + +#include "apr_inherit.h" + +#define APR_INHERIT (1 << 24) /* Must not conflict with other bits */ + +#define APR_IMPLEMENT_INHERIT_SET(name, flag, pool, cleanup) \ +APR_DECLARE(apr_status_t) apr_##name##_inherit_set(apr_##name##_t *the##name) \ +{ \ + IF_WIN_OS_IS_UNICODE \ + { \ + if (!SetHandleInformation(the##name->filehand, \ + HANDLE_FLAG_INHERIT, \ + HANDLE_FLAG_INHERIT)) \ + return apr_get_os_error(); \ + } \ + ELSE_WIN_OS_IS_ANSI \ + { \ + HANDLE temp, hproc = GetCurrentProcess(); \ + if (!DuplicateHandle(hproc, the##name->filehand, \ + hproc, &temp, 0, TRUE, \ + DUPLICATE_SAME_ACCESS)) \ + return apr_get_os_error(); \ + CloseHandle(the##name->filehand); \ + the##name->filehand = temp; \ + } \ + return APR_SUCCESS; \ +} + +#define APR_IMPLEMENT_INHERIT_UNSET(name, flag, pool, cleanup) \ +APR_DECLARE(apr_status_t) apr_##name##_inherit_unset(apr_##name##_t *the##name)\ +{ \ + IF_WIN_OS_IS_UNICODE \ + { \ + if (!SetHandleInformation(the##name->filehand, \ + HANDLE_FLAG_INHERIT, 0)) \ + return apr_get_os_error(); \ + } \ + ELSE_WIN_OS_IS_ANSI \ + { \ + HANDLE temp, hproc = GetCurrentProcess(); \ + if (!DuplicateHandle(hproc, the##name->filehand, \ + hproc, &temp, 0, FALSE, \ + DUPLICATE_SAME_ACCESS)) \ + return apr_get_os_error(); \ + CloseHandle(the##name->filehand); \ + the##name->filehand = temp; \ + } \ + return APR_SUCCESS; \ +} + +#endif /* ! INHERIT_H */ diff --git a/srclib/apr/include/arch/win32/apr_arch_misc.h b/srclib/apr/include/arch/win32/apr_arch_misc.h new file mode 100644 index 0000000000..fc86fe22f8 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_misc.h @@ -0,0 +1,327 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MISC_H +#define MISC_H + +#include "apr.h" +#include "apr_portable.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_getopt.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_getopt.h" + +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_SIGNAL_H +#include +#endif +#if APR_HAVE_PTHREAD_H +#include +#endif + +/* ### create APR_HAVE_* macros for these? */ +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif + +struct apr_other_child_rec_t { + apr_pool_t *p; + struct apr_other_child_rec_t *next; + apr_proc_t *proc; + void (*maintenance) (int, void *, int); + void *data; + apr_os_file_t write_fd; +}; + +#define WSAHighByte 2 +#define WSALowByte 0 + +/* start.c and apr_app.c helpers and communication within misc.c + * + * They are not for public consumption, although apr_app_init_complete + * must be an exported symbol to avoid reinitialization. + */ +extern int APR_DECLARE_DATA apr_app_init_complete; + +int apr_wastrtoastr(char const * const * *retarr, + wchar_t const * const *arr, int args); + +/* Platform specific designation of run time os version. + * Gaps allow for specific service pack levels that + * export new kernel or winsock functions or behavior. + */ +typedef enum { + APR_WIN_UNK = 0, + APR_WIN_UNSUP = 1, + APR_WIN_95 = 10, + APR_WIN_95_B = 11, + APR_WIN_95_OSR2 = 12, + APR_WIN_98 = 14, + APR_WIN_98_SE = 16, + APR_WIN_ME = 18, + + APR_WIN_UNICODE = 20, /* Prior versions support only narrow chars */ + + APR_WIN_CE_3 = 23, /* CE is an odd beast, not supporting */ + /* some pre-NT features, such as the */ + APR_WIN_NT = 30, /* narrow charset APIs (fooA fns), while */ + APR_WIN_NT_3_5 = 35, /* not supporting some NT-family features. */ + APR_WIN_NT_3_51 = 36, + + APR_WIN_NT_4 = 40, + APR_WIN_NT_4_SP2 = 42, + APR_WIN_NT_4_SP3 = 43, + APR_WIN_NT_4_SP4 = 44, + APR_WIN_NT_4_SP5 = 45, + APR_WIN_NT_4_SP6 = 46, + + APR_WIN_2000 = 50, + APR_WIN_2000_SP1 = 51, + APR_WIN_2000_SP2 = 52, + APR_WIN_XP = 60, + APR_WIN_XP_SP1 = 61, + APR_WIN_XP_SP2 = 62, + APR_WIN_2003 = 70 +} apr_oslevel_e; + +extern APR_DECLARE_DATA apr_oslevel_e apr_os_level; + +apr_status_t apr_get_oslevel(apr_oslevel_e *); + +/* The APR_HAS_ANSI_FS symbol is PRIVATE, and internal to APR. + * APR only supports char data for filenames. Like most applications, + * characters >127 are essentially undefined. APR_HAS_UNICODE_FS lets + * the application know that utf-8 is the encoding method of APR, and + * only incidently hints that we have Wide OS calls. + * + * APR_HAS_ANSI_FS is simply an OS flag to tell us all calls must be + * the unicode eqivilant. + */ + +#if defined(_WIN32_WCE) || defined(WINNT) +#define APR_HAS_ANSI_FS 0 +#else +#define APR_HAS_ANSI_FS 1 +#endif + +/* IF_WIN_OS_IS_UNICODE / ELSE_WIN_OS_IS_ANSI help us keep the code trivial + * where have runtime tests for unicode-ness, that aren't needed in any + * build which supports only WINNT or WCE. + */ +#if APR_HAS_ANSI_FS && APR_HAS_UNICODE_FS +#define IF_WIN_OS_IS_UNICODE if (apr_os_level >= APR_WIN_UNICODE) +#define ELSE_WIN_OS_IS_ANSI else +#else APR_HAS_UNICODE_FS +#define IF_WIN_OS_IS_UNICODE +#define ELSE_WIN_OS_IS_ANSI +#endif /* WINNT */ + +typedef enum { + DLL_WINBASEAPI = 0, // kernel32 From WinBase.h + DLL_WINADVAPI = 1, // advapi32 From WinBase.h + DLL_WINSOCKAPI = 2, // mswsock From WinSock.h + DLL_WINSOCK2API = 3, // ws2_32 From WinSock2.h + DLL_SHSTDAPI = 4, // shell32 From ShellAPI.h + DLL_NTDLL = 5, // shell32 From our real kernel + DLL_defined = 6 // must define as last idx_ + 1 +} apr_dlltoken_e; + +FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char *fnName, int ordinal); + +/* The apr_load_dll_func call WILL fault if the function cannot be loaded */ + +#define APR_DECLARE_LATE_DLL_FUNC(lib, rettype, calltype, fn, ord, args, names) \ + typedef rettype (calltype *apr_winapi_fpt_##fn) args; \ + static apr_winapi_fpt_##fn apr_winapi_pfn_##fn = NULL; \ + __inline rettype apr_winapi_##fn args \ + { if (!apr_winapi_pfn_##fn) \ + apr_winapi_pfn_##fn = (apr_winapi_fpt_##fn) \ + apr_load_dll_func(lib, #fn, ord); \ + return (*(apr_winapi_pfn_##fn)) names; }; \ + +/* Provide late bound declarations of every API function missing from + * one or more supported releases of the Win32 API + * + * lib is the enumerated token from apr_dlltoken_e, and must correspond + * to the string table entry in start.c used by the apr_load_dll_func(). + * Token names (attempt to) follow Windows.h declarations prefixed by DLL_ + * in order to facilitate comparison. Use the exact declaration syntax + * and names from Windows.h to prevent ambigutity and bugs. + * + * rettype and calltype follow the original declaration in Windows.h + * fn is the true function name - beware Ansi/Unicode #defined macros + * ord is the ordinal within the library, use 0 if it varies between versions + * args is the parameter list following the original declaration, in parens + * names is the parameter list sans data types, enclosed in parens + * + * #undef/re#define the Ansi/Unicode generic name to abate confusion + * In the case of non-text functions, simply #define the original name + */ + +#if !defined(_WIN32_WCE) && !defined(WINNT) + +#ifdef GetFileAttributesExA +#undef GetFileAttributesExA +#endif +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, GetFileAttributesExA, 0, ( + IN LPCSTR lpFileName, + IN GET_FILEEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFileInformation), + (lpFileName, fInfoLevelId, lpFileInformation)); +#define GetFileAttributesExA apr_winapi_GetFileAttributesExA +#undef GetFileAttributesEx +#define GetFileAttributesEx apr_winapi_GetFileAttributesExA + +#ifdef GetFileAttributesExW +#undef GetFileAttributesExW +#endif +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, GetFileAttributesExW, 0, ( + IN LPCWSTR lpFileName, + IN GET_FILEEX_INFO_LEVELS fInfoLevelId, + OUT LPVOID lpFileInformation), + (lpFileName, fInfoLevelId, lpFileInformation)); +#define GetFileAttributesExW apr_winapi_GetFileAttributesExW + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, CancelIo, 0, ( + IN HANDLE hFile), + (hFile)); +#define CancelIo apr_winapi_CancelIo + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, TryEnterCriticalSection, 0, ( + LPCRITICAL_SECTION lpCriticalSection), + (lpCriticalSection)); +#define TryEnterCriticalSection apr_winapi_TryEnterCriticalSection + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINBASEAPI, BOOL, WINAPI, SwitchToThread, 0, ( + void), + ()); +#define SwitchToThread apr_winapi_SwitchToThread + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINADVAPI, BOOL, WINAPI, GetEffectiveRightsFromAclW, 0, ( + IN PACL pacl, + IN PTRUSTEE_W pTrustee, + OUT PACCESS_MASK pAccessRights), + (pacl, pTrustee, pAccessRights)); +#define GetEffectiveRightsFromAclW apr_winapi_GetEffectiveRightsFromAclW + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINADVAPI, BOOL, WINAPI, GetNamedSecurityInfoW, 0, ( + IN LPWSTR pObjectName, + IN SE_OBJECT_TYPE ObjectType, + IN SECURITY_INFORMATION SecurityInfo, + OUT PSID *ppsidOwner, + OUT PSID *ppsidGroup, + OUT PACL *ppDacl, + OUT PACL *ppSacl, + OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor), + (pObjectName, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, + ppDacl, ppSacl, ppSecurityDescriptor)); +#define GetNamedSecurityInfoW apr_winapi_GetNamedSecurityInfoW + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINADVAPI, BOOL, WINAPI, GetNamedSecurityInfoA, 0, ( + IN LPSTR pObjectName, + IN SE_OBJECT_TYPE ObjectType, + IN SECURITY_INFORMATION SecurityInfo, + OUT PSID *ppsidOwner, + OUT PSID *ppsidGroup, + OUT PACL *ppDacl, + OUT PACL *ppSacl, + OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor), + (pObjectName, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, + ppDacl, ppSacl, ppSecurityDescriptor)); +#define GetNamedSecurityInfoA apr_winapi_GetNamedSecurityInfoA +#undef GetNamedSecurityInfo +#define GetNamedSecurityInfo apr_winapi_GetNamedSecurityInfoA + +APR_DECLARE_LATE_DLL_FUNC(DLL_WINADVAPI, BOOL, WINAPI, GetSecurityInfo, 0, ( + IN HANDLE handle, + IN SE_OBJECT_TYPE ObjectType, + IN SECURITY_INFORMATION SecurityInfo, + OUT PSID *ppsidOwner, + OUT PSID *ppsidGroup, + OUT PACL *ppDacl, + OUT PACL *ppSacl, + OUT PSECURITY_DESCRIPTOR *ppSecurityDescriptor), + (handle, ObjectType, SecurityInfo, ppsidOwner, ppsidGroup, + ppDacl, ppSacl, ppSecurityDescriptor)); +#define GetSecurityInfo apr_winapi_GetSecurityInfo + +APR_DECLARE_LATE_DLL_FUNC(DLL_SHSTDAPI, LPWSTR *, WINAPI, CommandLineToArgvW, 0, ( + LPCWSTR lpCmdLine, + int *pNumArgs), + (lpCmdLine, pNumArgs)); +#define CommandLineToArgvW apr_winapi_CommandLineToArgvW + +#endif /* !defined(_WIN32_WCE) && !defined(WINNT) */ + +#if !defined(_WIN32_WCE) + +APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, DWORD, WINAPI, NtQueryTimerResolution, 0, ( + ULONG *pMaxRes, /* Minimum NS Resolution */ + ULONG *pMinRes, /* Maximum NS Resolution */ + ULONG *pCurRes), /* Current NS Resolution */ + (pMaxRes, pMinRes, pCurRes)); +#define QueryTimerResolution apr_winapi_NtQueryTimerResolution + +APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, DWORD, WINAPI, NtSetTimerResolution, 0, ( + ULONG ReqRes, /* Requested NS Clock Resolution */ + BOOL Acquire, /* Aquire (1) or Release (0) our interest */ + ULONG *pNewRes), /* The NS Clock Resolution granted */ + (ReqRes, Acquire, pNewRes)); +#define SetTimerResolution apr_winapi_NtSetTimerResolution + +/* ### These are ULONG_PTR values, but that's int32 for all we care + * until the Win64 port is prepared. + */ +typedef struct PBI { + DWORD ExitStatus; + PVOID PebBaseAddress; + ULONG AffinityMask; + LONG BasePriority; + ULONG UniqueProcessId; + ULONG InheritedFromUniqueProcessId; +} PBI, *PPBI; + +APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, DWORD, WINAPI, NtQueryInformationProcess, 0, ( + HANDLE hProcess, /* Obvious */ + INT info, /* Use 0 for PBI documented above */ + PVOID pPI, /* The PIB buffer */ + ULONG LenPI, /* Use sizeof(PBI) */ + ULONG *pSizePI), /* returns pPI buffer used (may pass NULL) */ + (hProcess, info, pPI, LenPI, pSizePI)); +#define QueryInformationProcess apr_winapi_NtQueryInformationProcess + +APR_DECLARE_LATE_DLL_FUNC(DLL_NTDLL, DWORD, WINAPI, NtQueryObject, 0, ( + HANDLE hObject, /* Obvious */ + INT info, /* Use 0 for PBI documented above */ + PVOID pOI, /* The PIB buffer */ + ULONG LenOI, /* Use sizeof(PBI) */ + ULONG *pSizeOI), /* returns pPI buffer used (may pass NULL) */ + (hObject, info, pOI, LenOI, pSizeOI)); +#define QueryObject apr_winapi_NtQueryObject + +#endif /* !defined(_WIN32_WCE) */ + +#endif /* ! MISC_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_networkio.h b/srclib/apr/include/arch/win32/apr_arch_networkio.h new file mode 100644 index 0000000000..d07e4485ab --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_networkio.h @@ -0,0 +1,86 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETWORK_IO_H +#define NETWORK_IO_H + +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_poll.h" + +typedef struct sock_userdata_t sock_userdata_t; +struct sock_userdata_t { + sock_userdata_t *next; + const char *key; + void *data; +}; + +struct apr_socket_t { + apr_pool_t *cntxt; + SOCKET socketdes; + int type; /* SOCK_STREAM, SOCK_DGRAM */ + int protocol; + apr_sockaddr_t *local_addr; + apr_sockaddr_t *remote_addr; + int timeout_ms; /* MUST MATCH if timeout > 0 */ + apr_interval_time_t timeout; + apr_int32_t disconnected; + int local_port_unknown; + int local_interface_unknown; + int remote_addr_unknown; + apr_int32_t options; + apr_int32_t inherit; +#if APR_HAS_SENDFILE + /* As of 07.20.04, the overlapped structure is only used by + * apr_socket_sendfile and that's where it will be allocated + * and initialized. + */ + OVERLAPPED *overlapped; +#endif + sock_userdata_t *userdata; + + /* if there is a timeout set, then this pollset is used */ + apr_pollset_t *pollset; +}; + +#ifdef _WIN32_WCE +#ifndef WSABUF +typedef struct _WSABUF { + u_long len; /* the length of the buffer */ + char FAR * buf; /* the pointer to the buffer */ +} WSABUF, FAR * LPWSABUF; +#endif +#endif + +apr_status_t status_from_res_error(int); + +const char *apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size); +int apr_inet_pton(int af, const char *src, void *dst); +void apr_sockaddr_vars_set(apr_sockaddr_t *, int, apr_port_t); + +#define apr_is_option_set(skt, option) \ + (((skt)->options & (option)) == (option)) + +#define apr_set_option(skt, option, on) \ + do { \ + if (on) \ + (skt)->options |= (option); \ + else \ + (skt)->options &= ~(option); \ + } while (0) + +#endif /* ! NETWORK_IO_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_proc_mutex.h b/srclib/apr/include/arch/win32/apr_arch_proc_mutex.h new file mode 100644 index 0000000000..aaac5a30c7 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_proc_mutex.h @@ -0,0 +1,29 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROC_MUTEX_H +#define PROC_MUTEX_H + +#include "apr_proc_mutex.h" + +struct apr_proc_mutex_t { + apr_pool_t *pool; + HANDLE handle; + const char *fname; +}; + +#endif /* PROC_MUTEX_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_thread_cond.h b/srclib/apr/include/arch/win32/apr_arch_thread_cond.h new file mode 100644 index 0000000000..5520ef26b0 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_thread_cond.h @@ -0,0 +1,32 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_COND_H +#define THREAD_COND_H + +#include "apr_thread_cond.h" + +struct apr_thread_cond_t { + apr_pool_t *pool; + HANDLE event; + HANDLE mutex; + int signal_all; + int num_waiting; + int signalled; +}; + +#endif /* THREAD_COND_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_thread_mutex.h b/srclib/apr/include/arch/win32/apr_arch_thread_mutex.h new file mode 100644 index 0000000000..e180b7d42d --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_thread_mutex.h @@ -0,0 +1,40 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_MUTEX_H +#define THREAD_MUTEX_H + +#include "apr_pools.h" + +typedef enum thread_mutex_type { + thread_mutex_critical_section, + thread_mutex_unnested_event, + thread_mutex_nested_mutex +} thread_mutex_type; + +/* handle applies only to unnested_event on all platforms + * and nested_mutex on Win9x only. Otherwise critical_section + * is used for NT nexted mutexes providing optimal performance. + */ +struct apr_thread_mutex_t { + apr_pool_t *pool; + thread_mutex_type type; + HANDLE handle; + CRITICAL_SECTION section; +}; + +#endif /* THREAD_MUTEX_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_thread_rwlock.h b/srclib/apr/include/arch/win32/apr_arch_thread_rwlock.h new file mode 100644 index 0000000000..5a41fb97d0 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_thread_rwlock.h @@ -0,0 +1,30 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef THREAD_RWLOCK_H +#define THREAD_RWLOCK_H + +#include "apr_thread_rwlock.h" + +struct apr_thread_rwlock_t { + apr_pool_t *pool; + HANDLE write_mutex; + HANDLE read_event; + LONG readers; +}; + +#endif /* THREAD_RWLOCK_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_threadproc.h b/srclib/apr/include/arch/win32/apr_arch_threadproc.h new file mode 100644 index 0000000000..3fb64a0e9d --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_threadproc.h @@ -0,0 +1,72 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" + +#ifndef THREAD_PROC_H +#define THREAD_PROC_H + +#define SHELL_PATH "cmd.exe" + +struct apr_thread_t { + apr_pool_t *pool; + HANDLE td; + apr_int32_t cancel; + apr_int32_t cancel_how; + void *data; + apr_thread_start_t func; + apr_status_t exitval; +}; + +struct apr_threadattr_t { + apr_pool_t *pool; + apr_int32_t detach; + apr_size_t stacksize; +}; + +struct apr_threadkey_t { + apr_pool_t *pool; + DWORD key; +}; + +struct apr_procattr_t { + apr_pool_t *pool; + apr_file_t *parent_in; + apr_file_t *child_in; + apr_file_t *parent_out; + apr_file_t *child_out; + apr_file_t *parent_err; + apr_file_t *child_err; + char *currdir; + apr_int32_t cmdtype; + apr_int32_t detached; + apr_child_errfn_t *errfn; + apr_int32_t errchk; +#ifndef _WIN32_WCE + HANDLE user_token; + LPSECURITY_ATTRIBUTES sa; + LPVOID sd; +#endif +}; + +struct apr_thread_once_t { + long value; +}; + +#endif /* ! THREAD_PROC_H */ + diff --git a/srclib/apr/include/arch/win32/apr_arch_utf8.h b/srclib/apr/include/arch/win32/apr_arch_utf8.h new file mode 100644 index 0000000000..c3ca62745f --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_arch_utf8.h @@ -0,0 +1,56 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UTF8_H +#define UTF8_H + +#include "apr.h" +#include "apr_lib.h" +#include "apr_errno.h" + +/* If we ever support anything more exciting than char... this could move. + */ +typedef apr_uint16_t apr_wchar_t; + +/** + * An APR internal function for fast utf-8 octet-encoded Unicode conversion + * to the ucs-2 wide Unicode format. This function is used for filename and + * other resource conversions for platforms providing native Unicode support. + * + * @tip Only the errors APR_EINVAL and APR_INCOMPLETE may occur, the former + * when the character code is invalid (in or out of context) and the later + * when more characters were expected, but insufficient characters remain. + */ +APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in, + apr_size_t *inbytes, + apr_wchar_t *out, + apr_size_t *outwords); + +/** + * An APR internal function for fast ucs-2 wide Unicode format conversion to + * the utf-8 octet-encoded Unicode. This function is used for filename and + * other resource conversions for platforms providing native Unicode support. + * + * @tip Only the errors APR_EINVAL and APR_INCOMPLETE may occur, the former + * when the character code is invalid (in or out of context) and the later + * when more words were expected, but insufficient words remain. + */ +APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in, + apr_size_t *inwords, + char *out, + apr_size_t *outbytes); + +#endif /* def UTF8_H */ diff --git a/srclib/apr/include/arch/win32/apr_dbg_win32_handles.h b/srclib/apr/include/arch/win32/apr_dbg_win32_handles.h new file mode 100644 index 0000000000..291d77db07 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_dbg_win32_handles.h @@ -0,0 +1,217 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_DBG_WIN32_HANDLES_H +#define APR_DBG_WIN32_HANDLES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* USAGE: + * + * Add the following include to apr_private.h for internal debugging, + * or copy this header into apr/include add the include below to apr.h + * for really global debugging; + * + * #include "apr_dbg_win32_handles.h" + * + * apr_dbg_log is the crux of this function ... it uses Win32 API and + * no apr calls itself to log all activity to a file named for the + * executing application with a .pid suffix. Ergo several instances + * may be executing and logged at once. + * + * HANDLE apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, int nh + * [, HANDLE *hv, char *dsc...]) + * + * returns: the handle passed in ha, which is cast back to the real return type. + * + * formats one line into the debug log file if nh is zero; + * ha (hex) seq(hex) tid(hex) fn fl ln + * xxxxxxxx xxxxxxxx xxxxxxxx func() sourcefile:lineno + * The macro apr_dbg_rv makes this simple to implement for many APIs + * that simply take args that don't interest us, and return a handle. + * + * formats multiple lines (nh) into the debug log file for each hv/dsc pair + * (nh must correspond to the number of pairs); + * hv (hex) seq(hex) tid(hex) fn dsc fl ln + * xxxxxxxx xxxxxxxx xxxxxxxx func(arg) sourcefile:lineno + * In this later usage, hv is the still the return value but is not + * treated as a handle. + */ + +APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, + int nh,/* HANDLE *hv, char *dsc */...); + +#define apr_dbg_rv(fn, args) (apr_dbg_log(#fn,(fn) args,__FILE__,__LINE__,0)) + +#define CloseHandle(h) \ + ((BOOL)apr_dbg_log("CloseHandle", \ + (HANDLE)(CloseHandle)(h), \ + __FILE__,__LINE__,1, \ + &(h),"")) + +#define CreateEventA(sd,b1,b2,nm) apr_dbg_rv(CreateEventA,(sd,b1,b2,nm)) +#define CreateEventW(sd,b1,b2,nm) apr_dbg_rv(CreateEventW,(sd,b1,b2,nm)) + +#define CreateFileA(nm,d1,d2,sd,d3,d4,h) apr_dbg_rv(CreateFileA,(nm,d1,d2,sd,d3,d4,h)) +#define CreateFileW(nm,d1,d2,sd,d3,d4,h) apr_dbg_rv(CreateFileW,(nm,d1,d2,sd,d3,d4,h)) + +#define CreateFileMappingA(fh,sd,d1,d2,d3,nm) apr_dbg_rv(CreateFileMappingA,(fh,sd,d1,d2,d3,nm)) +#define CreateFileMappingW(fh,sd,d1,d2,d3,nm) apr_dbg_rv(CreateFileMappingW,(fh,sd,d1,d2,d3,nm)) + +#define CreateMutexA(sd,b,nm) apr_dbg_rv(CreateMutexA,(sd,b,nm)) +#define CreateMutexW(sd,b,nm) apr_dbg_rv(CreateMutexW,(sd,b,nm)) + +#define CreateIoCompletionPort(h1,h2,pd1,d2) apr_dbg_rv(CreateIoCompletionPort,(h1,h2,pd1,d2)) + +#define CreateNamedPipeA(nm,d1,d2,d3,d4,d5,d6,sd) apr_dbg_rv(CreateNamedPipeA,(nm,d1,d2,d3,d4,d5,d6,sd)) +#define CreateNamedPipeW(nm,d1,d2,d3,d4,d5,d6,sd) apr_dbg_rv(CreateNamedPipeW,(nm,d1,d2,d3,d4,d5,d6,sd)) + +#define CreatePipe(ph1,ph2,sd,d) \ + ((BOOL)apr_dbg_log("CreatePipe", \ + (HANDLE)(CreatePipe)(ph1,ph2,sd,d), \ + __FILE__,__LINE__,2, \ + (ph1),"hRead", \ + (ph2),"hWrite")) + +#define CreateProcessA(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr) \ + ((BOOL)apr_dbg_log("CreateProcessA", \ + (HANDLE)(CreateProcessA)(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr), \ + __FILE__,__LINE__,2, \ + &((hr)->hProcess),"hProcess", \ + &((hr)->hThread),"hThread")) +#define CreateProcessW(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr) \ + ((BOOL)apr_dbg_log("CreateProcessW", \ + (HANDLE)(CreateProcessW)(s1,s2,sd1,sd2,b,d1,s3,s4,pd2,hr), \ + __FILE__,__LINE__,2, \ + &((hr)->hProcess),"hProcess", \ + &((hr)->hThread),"hThread")) + +#define CreateSemaphoreA(sd,d1,d2,nm) apr_dbg_rv(CreateSemaphoreA,(sd,d1,d2,nm)) +#define CreateSemaphoreW(sd,d1,d2,nm) apr_dbg_rv(CreateSemaphoreW,(sd,d1,d2,nm)) + +#define CreateThread(sd,d1,fn,pv,d2,pd3) apr_dbg_rv(CreateThread,(sd,d1,fn,pv,d2,pd3)) + +#define DeregisterEventSource(h) \ + ((BOOL)apr_dbg_log("DeregisterEventSource", \ + (HANDLE)(DeregisterEventSource)(h), \ + __FILE__,__LINE__,1, \ + &(h),"")) + +#define DuplicateHandle(h1,h2,h3,ph4,d1,b,d2) \ + ((BOOL)apr_dbg_log("DuplicateHandle", \ + (HANDLE)(DuplicateHandle)(h1,h2,h3,ph4,d1,b,d2), \ + __FILE__,__LINE__,2, \ + (ph4),((h3)==GetCurrentProcess()) \ + ? "Target" : "EXTERN Target", \ + &(h2),((h1)==GetCurrentProcess()) \ + ? "Source" : "EXTERN Source")) + +#define GetCurrentProcess() \ + (apr_dbg_log("GetCurrentProcess", \ + (GetCurrentProcess)(),__FILE__,__LINE__,0)) + +#define GetCurrentThread() \ + (apr_dbg_log("GetCurrentThread", \ + (GetCurrentThread)(),__FILE__,__LINE__,0)) + +#define GetModuleHandleA(nm) apr_dbg_rv(GetModuleHandleA,(nm)) +#define GetModuleHandleW(nm) apr_dbg_rv(GetModuleHandleW,(nm)) + +#define GetStdHandle(d) apr_dbg_rv(GetStdHandle,(d)) + +#define LoadLibraryA(nm) apr_dbg_rv(LoadLibraryA,(nm)) +#define LoadLibraryW(nm) apr_dbg_rv(LoadLibraryW,(nm)) + +#define LoadLibraryExA(nm,h,d) apr_dbg_rv(LoadLibraryExA,(nm,h,d)) +#define LoadLibraryExW(nm,h,d) apr_dbg_rv(LoadLibraryExW,(nm,h,d)) + +#define OpenEventA(d,b,nm) apr_dbg_rv(OpenEventA,(d,b,nm)) +#define OpenEventW(d,b,nm) apr_dbg_rv(OpenEventW,(d,b,nm)) + +#define OpenFileMappingA(d,b,nm) apr_dbg_rv(OpenFileMappingA,(d,b,nm)) +#define OpenFileMappingW(d,b,nm) apr_dbg_rv(OpenFileMappingW,(d,b,nm)) + +#define RegisterEventSourceA(s1,s2) apr_dbg_rv(RegisterEventSourceA,(s1,s2)) +#define RegisterEventSourceW(s1,s2) apr_dbg_rv(RegisterEventSourceW,(s1,s2)) + +#define SetEvent(h) \ + ((BOOL)apr_dbg_log("SetEvent", \ + (HANDLE)(SetEvent)(h), \ + __FILE__,__LINE__,1, \ + &(h),"")) + +#define SetStdHandle(d,h) \ + ((BOOL)apr_dbg_log("SetStdHandle", \ + (HANDLE)(SetStdHandle)(d,h), \ + __FILE__,__LINE__,1,&(h),"")) + +#define socket(i1,i2,i3) \ + ((SOCKET)apr_dbg_log("socket", \ + (HANDLE)(socket)(i1,i2,i3), \ + __FILE__,__LINE__,0)) + +#define WaitForSingleObject(h,d) \ + ((DWORD)apr_dbg_log("WaitForSingleObject", \ + (HANDLE)(WaitForSingleObject)(h,d), \ + __FILE__,__LINE__,1,&(h),"Signaled")) + +#define WaitForSingleObjectEx(h,d,b) \ + ((DWORD)apr_dbg_log("WaitForSingleObjectEx", \ + (HANDLE)(WaitForSingleObjectEx)(h,d,b), \ + __FILE__,__LINE__,1,&(h),"Signaled")) + +#define WaitForMultipleObjects(d1,ah,b,d2) \ + ((DWORD)apr_dbg_log("WaitForMultipleObjects", \ + (HANDLE)(WaitForMultipleObjects)(d1,ah,b,d2), \ + __FILE__,__LINE__,1,ah,"Signaled")) + +#define WaitForMultipleObjectsEx(d1,ah,b1,d2,b2) \ + ((DWORD)apr_dbg_log("WaitForMultipleObjectsEx", \ + (HANDLE)(WaitForMultipleObjectsEx)(d1,ah,b1,d2,b2), \ + __FILE__,__LINE__,1,ah,"Signaled")) + +#define WSASocketA(i1,i2,i3,pi,g,dw) \ + ((SOCKET)apr_dbg_log("WSASocketA", \ + (HANDLE)(WSASocketA)(i1,i2,i3,pi,g,dw), \ + __FILE__,__LINE__,0)) + +#define WSASocketW(i1,i2,i3,pi,g,dw) \ + ((SOCKET)apr_dbg_log("WSASocketW", \ + (HANDLE)(WSASocketW)(i1,i2,i3,pi,g,dw), \ + __FILE__,__LINE__,0)) + +#define closesocket(sh) \ + ((int)apr_dbg_log("closesocket", \ + (HANDLE)(closesocket)(sh), \ + __FILE__,__LINE__,1,&(sh),"")) + +#define _beginthread(fn,d,pv) \ + ((unsigned long)apr_dbg_log("_beginthread", \ + (HANDLE)(_beginthread)(fn,d,pv), \ + __FILE__,__LINE__,0)) + +#define _beginthreadex(sd,d1,fn,pv,d2,pd3) \ + ((unsigned long)apr_dbg_log("_beginthreadex", \ + (HANDLE)(_beginthreadex)(sd,d1,fn,pv,d2,pd3), \ + __FILE__,__LINE__,0)) + +#ifdef __cplusplus +} +#endif + +#endif /* !defined(APR_DBG_WIN32_HANDLES_H) */ diff --git a/srclib/apr/include/arch/win32/apr_private.h b/srclib/apr/include/arch/win32/apr_private.h new file mode 100644 index 0000000000..ac93d1ed87 --- /dev/null +++ b/srclib/apr/include/arch/win32/apr_private.h @@ -0,0 +1,171 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Note: + * This is the windows specific autoconf-like config file + * which unix would create at build time. + */ + +#ifdef WIN32 + +#ifndef APR_PRIVATE_H +#define APR_PRIVATE_H + +/* Include the public APR symbols, include our idea of the 'right' + * subset of the Windows.h header. This saves us repetition. + */ +#include "apr.h" + +/* + * Add a _very_few_ declarations missing from the restricted set of headers + * (If this list becomes extensive, re-enable the required headers above!) + * winsock headers were excluded by WIN32_LEAN_AND_MEAN, so include them now + */ +#ifndef SW_HIDE +#define SW_HIDE 0 +#endif + +/* For the misc.h late-loaded dynamic symbols, we need some obscure types + * Avoid dragging in wtypes.h unless it's absolutely necessary [generally + * not with APR itself, until some GUI-related security is introduced.] + */ +#ifndef _WIN32_WCE +#define HAVE_ACLAPI 1 +#ifdef __wtypes_h__ +#include +#else +#define __wtypes_h__ +#include +#undef __wtypes_h__ +#endif +#else +#define HAVE_ACLAPI 0 +#endif + +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STDDEF_H +#include +#endif +#include +#if APR_HAVE_TIME_H +#include +#endif + +/* Use this section to define all of the HAVE_FOO_H + * that are required to build properly. + */ +#define HAVE_LIMITS_H 1 +#define HAVE_MALLOC_H 1 +#define HAVE_SIGNAL_H 1 +/* #define HAVE_STDDEF_H 1 why not? */ +#define HAVE_STDLIB_H 1 + +#define HAVE_STRICMP 1 +#define HAVE_STRNICMP 1 +#define HAVE_STRDUP 1 +#define HAVE_STRSTR 1 +#define HAVE_MEMCHR 1 + +#define SIGHUP 1 +/* 2 is used for SIGINT on windows */ +#define SIGQUIT 3 +/* 4 is used for SIGILL on windows */ +#define SIGTRAP 5 +#define SIGIOT 6 +#define SIGBUS 7 +/* 8 is used for SIGFPE on windows */ +#define SIGKILL 9 +#define SIGUSR1 10 +/* 11 is used for SIGSEGV on windows */ +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +/* 15 is used for SIGTERM on windows */ +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +/* 21 is used for SIGBREAK on windows */ +/* 22 is used for SIGABRT on windows */ +#define SIGTTIN 23 +#define SIGTTOU 24 +#define SIGURG 25 +#define SIGXCPU 26 +#define SIGXFSZ 27 +#define SIGVTALRM 28 +#define SIGPROF 29 +#define SIGWINCH 30 +#define SIGIO 31 + +#define __attribute__(__x) + +/* APR COMPATABILITY FUNCTIONS + * This section should be used to define functions and + * macros which are need to make Windows features look + * like POSIX features. + */ +typedef void (Sigfunc)(int); + +#define sleep(t) Sleep((t) * 1000) + +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 +#define SIZEOF_LONGLONG 8 +#define SIZEOF_CHAR 1 +#define SIZEOF_SSIZE_T SIZEOF_INT + +unsigned __stdcall SignalHandling(void *); +int thread_ready(void); + +#if !APR_HAVE_ERRNO_H +APR_DECLARE_DATA int errno; +#define ENOSPC 1 +#endif + +#if APR_HAVE_IPV6 +#define HAVE_GETADDRINFO 1 +#define HAVE_GETNAMEINFO 1 +#endif + +/* MSVC 7.0 introduced _strtoi64 */ +#if _MSC_VER >= 1300 && _INTEGRAL_MAX_BITS >= 64 +#define APR_INT64_STRFN _strtoi64 +#endif + +#if APR_HAS_LARGE_FILES +#ifdef APR_INT64_STRFN +#define APR_OFF_T_STRFN APR_INT64_STRFN +#else +#define APR_OFF_T_STRFN apr_strtoi64 +#endif +#else +#define APR_OFF_T_STRFN strtoi +#endif + +/* used to check for DWORD overflow in 64bit compiles */ +#define APR_DWORD_MAX 0xFFFFFFFFUL + +/* + * Include common private declarations. + */ +#include "../apr_private_common.h" + +#endif /*APR_PRIVATE_H*/ +#endif /*WIN32*/ diff --git a/srclib/apr/libapr.dsp b/srclib/apr/libapr.dsp new file mode 100644 index 0000000000..dd399a7e5e --- /dev/null +++ b/srclib/apr/libapr.dsp @@ -0,0 +1,645 @@ +# Microsoft Developer Studio Project File - Name="libapr" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libapr - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libapr.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libapr.mak" CFG="libapr - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libapr - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libapr - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libapr - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /Oy- /Zi /I "./include" /I "./include/arch" /I "./include/arch/win32" /I "./include/arch/unix" /D "NDEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "_WINDOWS" /Fd"Release\libapr_src" /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" /d "APR_VERSION_ONLY" /I "./include" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /opt:ref +# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Release/libapr-1.dll" /opt:ref + +!ELSEIF "$(CFG)" == "libapr - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "./include" /I "./include/arch" /I "./include/arch/win32" /I "./include/arch/unix" /D "_DEBUG" /D "APR_DECLARE_EXPORT" /D "WIN32" /D "_WINDOWS" /Fd"Debug\libapr_src" /FD /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /o /win32 "NUL" +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" /d "APR_VERSION_ONLY" /I "./include" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /machine:I386 +# ADD LINK32 kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib /nologo /base:"0x6EEC0000" /subsystem:windows /dll /incremental:no /debug /machine:I386 /out:"Debug/libapr-1.dll" + +!ENDIF + +# Begin Target + +# Name "libapr - Win32 Release" +# Name "libapr - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter ".c" +# Begin Group "atomic" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\atomic\win32\apr_atomic.c +# End Source File +# End Group +# Begin Group "dso" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\dso\win32\dso.c +# End Source File +# End Group +# Begin Group "file_io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\file_io\unix\copy.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\dir.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\fileacc.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filedup.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filepath.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\filepath_util.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filestat.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\filesys.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\flock.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\fullrw.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\mktemp.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\open.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\pipe.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\readwrite.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\win32\seek.c +# End Source File +# Begin Source File + +SOURCE=.\file_io\unix\tempdir.c +# End Source File +# End Group +# Begin Group "locks" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\locks\win32\proc_mutex.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_cond.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_mutex.c +# End Source File +# Begin Source File + +SOURCE=.\locks\win32\thread_rwlock.c +# End Source File +# End Group +# Begin Group "memory" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\memory\unix\apr_pools.c +# End Source File +# End Group +# Begin Group "misc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\misc\win32\apr_app.c +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\charset.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\env.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\errorcodes.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\getopt.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\internal.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\misc.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\otherchild.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\rand.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\start.c +# End Source File +# Begin Source File + +SOURCE=.\misc\win32\utf8.c +# End Source File +# Begin Source File + +SOURCE=.\misc\unix\version.c +# End Source File +# End Group +# Begin Group "mmap" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\mmap\unix\common.c +# End Source File +# Begin Source File + +SOURCE=.\mmap\win32\mmap.c +# End Source File +# End Group +# Begin Group "network_io" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\network_io\unix\inet_ntop.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\inet_pton.c +# End Source File +# Begin Source File + +SOURCE=.\poll\unix\select.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\multicast.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sendrecv.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\unix\sockaddr.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sockets.c +# End Source File +# Begin Source File + +SOURCE=.\network_io\win32\sockopt.c +# End Source File +# End Group +# Begin Group "passwd" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\passwd\apr_getpass.c +# End Source File +# End Group +# Begin Group "shmem" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\shmem\win32\shm.c +# End Source File +# End Group +# Begin Group "strings" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\strings\apr_cpystrn.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_fnmatch.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_snprintf.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strings.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strnatcmp.c +# End Source File +# Begin Source File + +SOURCE=.\strings\apr_strtok.c +# End Source File +# End Group +# Begin Group "tables" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\tables\apr_hash.c +# End Source File +# Begin Source File + +SOURCE=.\tables\apr_tables.c +# End Source File +# End Group +# Begin Group "threadproc" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\threadproc\win32\proc.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\signals.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\thread.c +# End Source File +# Begin Source File + +SOURCE=.\threadproc\win32\threadpriv.c +# End Source File +# End Group +# Begin Group "time" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\time\win32\access.c +# End Source File +# Begin Source File + +SOURCE=.\time\win32\time.c +# End Source File +# Begin Source File + +SOURCE=.\time\win32\timestr.c +# End Source File +# End Group +# Begin Group "user" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\user\win32\groupinfo.c +# End Source File +# Begin Source File + +SOURCE=.\user\win32\userinfo.c +# End Source File +# End Group +# End Group +# Begin Group "Private Header Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_atime.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_dso.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_file_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_inherit.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_misc.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_networkio.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_thread_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_thread_rwlock.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_threadproc.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_arch_utf8.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\win32\apr_private.h +# End Source File +# Begin Source File + +SOURCE=.\include\arch\apr_private_common.h +# End Source File +# End Group +# Begin Group "Public Header Files" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\include\apr.h.in +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\include\apr.hnw +# PROP Exclude_From_Build 1 +# End Source File +# Begin Source File + +SOURCE=.\include\apr.hw + +!IF "$(CFG)" == "libapr - Win32 Release" + +# Begin Custom Build - Creating apr.h from apr.hw +InputPath=.\include\apr.hw + +".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + type .\include\apr.hw > .\include\apr.h + +# End Custom Build + +!ELSEIF "$(CFG)" == "libapr - Win32 Debug" + +# Begin Custom Build - Creating apr.h from apr.hw +InputPath=.\include\apr.hw + +".\include\apr.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + type .\include\apr.hw > .\include\apr.h + +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\include\apr_allocator.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_atomic.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_dso.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_env.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_errno.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_file_info.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_file_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_fnmatch.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_general.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_getopt.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_global_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_hash.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_inherit.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_lib.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_mmap.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_network_io.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_poll.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_pools.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_portable.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_proc_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_ring.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_shm.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_signal.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_strings.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_support.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_tables.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_cond.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_mutex.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_proc.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_thread_rwlock.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_time.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_user.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_version.h +# End Source File +# Begin Source File + +SOURCE=.\include\apr_want.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\libapr.rc +# End Source File +# End Target +# End Project diff --git a/srclib/apr/libapr.rc b/srclib/apr/libapr.rc new file mode 100644 index 0000000000..8dc3cedfa9 --- /dev/null +++ b/srclib/apr/libapr.rc @@ -0,0 +1,54 @@ +#include "apr_version.h" + +#define APR_COPYRIGHT "Copyright 2000-2005 The Apache Software " \ + "Foundation or its licensors, as applicable." + +#define APR_LICENSE "Licensed under the Apache License, Version 2.0 " \ + "(the ""License""); you may not use this file except " \ + "in compliance with the License. You may obtain a " \ + "copy of the License at\r\n\r\n" \ + "http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n" \ + "Unless required by applicable law or agreed to in " \ + "writing, software distributed under the License is " \ + "distributed on an ""AS IS"" BASIS, WITHOUT " \ + "WARRANTIES OR CONDITIONS OF ANY KIND, either " \ + "express or implied. See the License for the " \ + "specific language governing permissions and " \ + "limitations under the License." + +#define APR_DLL_BASENAME "libapr-" APR_STRINGIFY(APR_MAJOR_VERSION) + + +1 VERSIONINFO + FILEVERSION APR_VERSION_STRING_CSV,0 + PRODUCTVERSION APR_VERSION_STRING_CSV,0 + FILEFLAGSMASK 0x3fL +#if defined(_DEBUG) + FILEFLAGS 0x01L +#else + FILEFLAGS 0x00L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", APR_LICENSE "\0" + VALUE "CompanyName", "Apache Software Foundation\0" + VALUE "FileDescription", "Apache Portable Runtime Library\0" + VALUE "FileVersion", APR_VERSION_STRING "\0" + VALUE "InternalName", APR_DLL_BASENAME "\0" + VALUE "LegalCopyright", APR_COPYRIGHT "\0" + VALUE "OriginalFilename", APR_DLL_BASENAME ".dll\0" + VALUE "ProductName", "Apache Portable Runtime Project\0" + VALUE "ProductVersion", APR_VERSION_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff --git a/srclib/apr/libaprnw.mcp.zip b/srclib/apr/libaprnw.mcp.zip new file mode 100644 index 0000000000000000000000000000000000000000..f9d5c14e61f378e50b8ba31b2f05ad83090221b7 GIT binary patch literal 171800 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

    s+gFY6)Rc)w!+6-Y;IZ_n>Ekhro@< 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 z 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 + */ + +#include "apr_arch_proc_mutex.h" +#include "apr_strings.h" +#include "apr_portable.h" + +static apr_status_t _proc_mutex_cleanup(void * data) +{ + apr_proc_mutex_t *lock = (apr_proc_mutex_t*)data; + if (lock->LockCount != 0) { + /* we're still locked... */ + while (atomic_add(&lock->LockCount , -1) > 1){ + /* OK we had more than one person waiting on the lock so + * the sem is also locked. Release it until we have no more + * locks left. + */ + release_sem (lock->Lock); + } + } + delete_sem(lock->Lock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new; + apr_status_t stat = APR_SUCCESS; + + if (mech != APR_LOCK_DEFAULT) { + return APR_ENOTIMPL; + } + + new = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); + if (new == NULL){ + return APR_ENOMEM; + } + + if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) { + _proc_mutex_cleanup(new); + return stat; + } + new->LockCount = 0; + new->Lock = stat; + new->pool = pool; + + apr_pool_cleanup_register(new->pool, (void *)new, _proc_mutex_cleanup, + apr_pool_cleanup_null); + + (*mutex) = new; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + int32 stat; + + if (atomic_add(&mutex->LockCount, 1) > 0) { + if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) { + atomic_add(&mutex->LockCount, -1); + return stat; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + int32 stat; + + if (atomic_add(&mutex->LockCount, -1) > 1) { + if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) { + atomic_add(&mutex->LockCount, 1); + return stat; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + apr_status_t stat; + if ((stat = _proc_mutex_cleanup(mutex)) == APR_SUCCESS) { + apr_pool_cleanup_kill(mutex->pool, mutex, _proc_mutex_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) +{ + return _proc_mutex_cleanup(mutex); +} + + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + return NULL; +} + +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return "beossem"; +} + +APR_DECLARE(const char *) apr_proc_mutex_defname(void) +{ + return "beossem"; +} + +APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) + +/* Implement OS-specific accessors defined in apr_portable.h */ + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ + ospmutex->sem = pmutex->Lock; + ospmutex->ben = pmutex->LockCount; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*pmutex) == NULL) { + (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); + (*pmutex)->pool = pool; + } + (*pmutex)->Lock = ospmutex->sem; + (*pmutex)->LockCount = ospmutex->ben; + return APR_SUCCESS; +} + diff --git a/srclib/apr/locks/beos/thread_cond.c b/srclib/apr/locks/beos/thread_cond.c new file mode 100644 index 0000000000..dc9ba618c3 --- /dev/null +++ b/srclib/apr/locks/beos/thread_cond.c @@ -0,0 +1,185 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_thread_mutex.h" +#include "apr_arch_thread_cond.h" +#include "apr_strings.h" +#include "apr_portable.h" + +static apr_status_t thread_cond_cleanup(void *data) +{ + struct waiter *w; + apr_thread_cond_t *cond = (apr_thread_cond_t *)data; + + acquire_sem(cond->lock); + delete_sem(cond->lock); + + return APR_SUCCESS; +} + +static struct waiter_t *make_waiter(apr_pool_t *pool) +{ + struct waiter_t *w = (struct waiter_t*) + apr_palloc(pool, sizeof(struct waiter_t)); + if (w == NULL) + return NULL; + + w->sem = create_sem(0, "apr conditional waiter"); + if (w->sem < 0) + return NULL; + + APR_RING_ELEM_INIT(w, link); + + return w; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool) +{ + apr_thread_cond_t *new_cond; + sem_id rv; + int i; + + new_cond = (apr_thread_cond_t *)apr_palloc(pool, sizeof(apr_thread_cond_t)); + + if (new_cond == NULL) + return APR_ENOMEM; + + if ((rv = create_sem(1, "apr conditional lock")) < B_OK) + return rv; + + new_cond->lock = rv; + new_cond->pool = pool; + APR_RING_INIT(&new_cond->alist, waiter_t, link); + APR_RING_INIT(&new_cond->flist, waiter_t, link); + + for (i=0;i < 10 ;i++) { + struct waiter_t *nw = make_waiter(pool); + APR_RING_INSERT_TAIL(&new_cond->flist, nw, waiter_t, link); + } + + apr_pool_cleanup_register(new_cond->pool, + (void *)new_cond, thread_cond_cleanup, + apr_pool_cleanup_null); + + *cond = new_cond; + return APR_SUCCESS; +} + + +static apr_status_t do_wait(apr_thread_cond_t *cond, apr_thread_mutex_t *mutex, + int timeout) +{ + struct waiter_t *wait; + thread_id cth = find_thread(NULL); + apr_status_t rv; + int flags = B_RELATIVE_TIMEOUT; + + /* We must be the owner of the mutex or we can't do this... */ + if (mutex->owner != cth) { + /* What should we return??? */ + return APR_EINVAL; + } + + acquire_sem(cond->lock); + wait = APR_RING_FIRST(&cond->flist); + if (wait) + APR_RING_REMOVE(wait, link); + else + wait = make_waiter(cond->pool); + APR_RING_INSERT_TAIL(&cond->alist, wait, waiter_t, link); + cond->condlock = mutex; + release_sem(cond->lock); + + apr_thread_mutex_unlock(cond->condlock); + + if (timeout == 0) + flags = 0; + + rv = acquire_sem_etc(wait->sem, 1, flags, timeout); + + apr_thread_mutex_lock(cond->condlock); + + if (rv != B_OK) + if (rv == B_TIMED_OUT) + return APR_TIMEUP; + return rv; + + acquire_sem(cond->lock); + APR_RING_REMOVE(wait, link); + APR_RING_INSERT_TAIL(&cond->flist, wait, waiter_t, link); + release_sem(cond->lock); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex) +{ + return do_wait(cond, mutex, 0); +} + +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout) +{ + return do_wait(cond, mutex, timeout); +} + +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) +{ + struct waiter_t *wake; + + acquire_sem(cond->lock); + if (!APR_RING_EMPTY(&cond->alist, waiter_t, link)) { + wake = APR_RING_FIRST(&cond->alist); + APR_RING_REMOVE(wake, link); + release_sem(wake->sem); + APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link); + } + release_sem(cond->lock); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) +{ + struct waiter_t *wake; + + acquire_sem(cond->lock); + while (! APR_RING_EMPTY(&cond->alist, waiter_t, link)) { + wake = APR_RING_FIRST(&cond->alist); + APR_RING_REMOVE(wake, link); + release_sem(wake->sem); + APR_RING_INSERT_TAIL(&cond->flist, wake, waiter_t, link); + } + release_sem(cond->lock); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + apr_status_t stat; + if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) { + apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) + diff --git a/srclib/apr/locks/beos/thread_mutex.c b/srclib/apr/locks/beos/thread_mutex.c new file mode 100644 index 0000000000..5f488f16fb --- /dev/null +++ b/srclib/apr/locks/beos/thread_mutex.c @@ -0,0 +1,147 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*Read/Write locking implementation based on the MultiLock code from + * Stephen Beaulieu + */ + +#include "apr_arch_thread_mutex.h" +#include "apr_strings.h" +#include "apr_portable.h" + +static apr_status_t _thread_mutex_cleanup(void * data) +{ + apr_thread_mutex_t *lock = (apr_thread_mutex_t*)data; + if (lock->LockCount != 0) { + /* we're still locked... */ + while (atomic_add(&lock->LockCount , -1) > 1){ + /* OK we had more than one person waiting on the lock so + * the sem is also locked. Release it until we have no more + * locks left. + */ + release_sem (lock->Lock); + } + } + delete_sem(lock->Lock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_m; + apr_status_t stat = APR_SUCCESS; + + new_m = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t)); + if (new_m == NULL){ + return APR_ENOMEM; + } + + if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) { + _thread_mutex_cleanup(new_m); + return stat; + } + new_m->LockCount = 0; + new_m->Lock = stat; + new_m->pool = pool; + + /* Optimal default is APR_THREAD_MUTEX_UNNESTED, + * no additional checks required for either flag. + */ + new_m->nested = flags & APR_THREAD_MUTEX_NESTED; + + apr_pool_cleanup_register(new_m->pool, (void *)new_m, _thread_mutex_cleanup, + apr_pool_cleanup_null); + + (*mutex) = new_m; + return APR_SUCCESS; +} + +#if APR_HAS_CREATE_LOCKS_NP +APR_DECLARE(apr_status_t) apr_thread_mutex_create_np(apr_thread_mutex_t **mutex, + const char *fname, + apr_lockmech_e_np mech, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} +#endif + +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + int32 stat; + thread_id me = find_thread(NULL); + + if (mutex->nested && mutex->owner == me) { + mutex->owner_ref++; + return APR_SUCCESS; + } + + if (atomic_add(&mutex->LockCount, 1) > 0) { + if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) { + /* Oh dear, acquire_sem failed!! */ + atomic_add(&mutex->LockCount, -1); + return stat; + } + } + + mutex->owner = me; + mutex->owner_ref = 1; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + int32 stat; + + if (mutex->nested && mutex->owner == find_thread(NULL)) { + mutex->owner_ref--; + if (mutex->owner_ref > 0) + return APR_SUCCESS; + } + + if (atomic_add(&mutex->LockCount, -1) > 1) { + if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) { + atomic_add(&mutex->LockCount, 1); + return stat; + } + } + + mutex->owner = -1; + mutex->owner_ref = 0; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + apr_status_t stat; + if ((stat = _thread_mutex_cleanup(mutex)) == APR_SUCCESS) { + apr_pool_cleanup_kill(mutex->pool, mutex, _thread_mutex_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) + diff --git a/srclib/apr/locks/beos/thread_rwlock.c b/srclib/apr/locks/beos/thread_rwlock.c new file mode 100644 index 0000000000..be11017a25 --- /dev/null +++ b/srclib/apr/locks/beos/thread_rwlock.c @@ -0,0 +1,190 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*Read/Write locking implementation based on the MultiLock code from + * Stephen Beaulieu + */ + +#include "apr_arch_thread_rwlock.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#define BIG_NUM 100000 + +static apr_status_t _thread_rw_cleanup(void * data) +{ + apr_thread_rwlock_t *mutex = (apr_thread_rwlock_t*)data; + + if (mutex->ReadCount != 0) { + while (atomic_add(&mutex->ReadCount , -1) > 1){ + release_sem (mutex->Read); + } + } + if (mutex->WriteCount != 0) { + while (atomic_add(&mutex->WriteCount , -1) > 1){ + release_sem (mutex->Write); + } + } + if (mutex->LockCount != 0) { + while (atomic_add(&mutex->LockCount , -1) > 1){ + release_sem (mutex->Lock); + } + } + + delete_sem(mutex->Read); + delete_sem(mutex->Write); + delete_sem(mutex->Lock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + apr_thread_rwlock_t *new; + + new = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t)); + if (new == NULL){ + return APR_ENOMEM; + } + + new->pool = pool; + /* we need to make 3 locks... */ + new->ReadCount = 0; + new->WriteCount = 0; + new->LockCount = 0; + new->Read = create_sem(0, "APR_ReadLock"); + new->Write = create_sem(0, "APR_WriteLock"); + new->Lock = create_sem(0, "APR_Lock"); + + if (new->Lock < 0 || new->Read < 0 || new->Write < 0) { + _thread_rw_cleanup(new); + return -1; + } + + apr_pool_cleanup_register(new->pool, (void *)new, _thread_rw_cleanup, + apr_pool_cleanup_null); + (*rwlock) = new; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + int32 rv = APR_SUCCESS; + + if (find_thread(NULL) == rwlock->writer) { + /* we're the writer - no problem */ + rwlock->Nested++; + } else { + /* we're not the writer */ + int32 r = atomic_add(&rwlock->ReadCount, 1); + if (r < 0) { + /* Oh dear, writer holds lock, wait for sem */ + rv = acquire_sem_etc(rwlock->Read, 1, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT); + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + int rv = APR_SUCCESS; + + if (find_thread(NULL) == rwlock->writer) { + rwlock->Nested++; + } else { + /* we're not the writer... */ + if (atomic_add(&rwlock->LockCount, 1) >= 1) { + /* we're locked - acquire the sem */ + rv = acquire_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT); + } + if (rv == APR_SUCCESS) { + /* decrement the ReadCount to a large -ve number so that + * we block on new readers... + */ + int32 readers = atomic_add(&rwlock->ReadCount, -BIG_NUM); + if (readers > 0) { + /* readers are holding the lock */ + rv = acquire_sem_etc(rwlock->Write, readers, B_DO_NOT_RESCHEDULE, + B_INFINITE_TIMEOUT); + } + if (rv == APR_SUCCESS) + rwlock->writer = find_thread(NULL); + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t rv = APR_SUCCESS; + int32 readers; + + /* we know we hold the lock, so don't check it :) */ + if (find_thread(NULL) == rwlock->writer) { + /* we know we hold the lock, so don't check it :) */ + if (rwlock->Nested > 1) { + /* we're recursively locked */ + rwlock->Nested--; + return APR_SUCCESS; + } + /* OK so we need to release the sem if we have it :) */ + readers = atomic_add(&rwlock->ReadCount, BIG_NUM) + BIG_NUM; + if (readers > 0) { + rv = release_sem_etc(rwlock->Read, readers, B_DO_NOT_RESCHEDULE); + } + if (rv == APR_SUCCESS) { + rwlock->writer = -1; + if (atomic_add(&rwlock->LockCount, -1) > 1) { + rv = release_sem_etc(rwlock->Lock, 1, B_DO_NOT_RESCHEDULE); + } + } + } else { + /* We weren't the Writer, so just release the ReadCount... */ + if (atomic_add(&rwlock->ReadCount, -1) < 0) { + /* we have a writer waiting for the lock, so release it */ + rv = release_sem_etc(rwlock->Write, 1, B_DO_NOT_RESCHEDULE); + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + if ((stat = _thread_rw_cleanup(rwlock)) == APR_SUCCESS) { + apr_pool_cleanup_kill(rwlock->pool, rwlock, _thread_rw_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock) + diff --git a/srclib/apr/locks/netware/proc_mutex.c b/srclib/apr/locks/netware/proc_mutex.c new file mode 100644 index 0000000000..72a8bfcddc --- /dev/null +++ b/srclib/apr/locks/netware/proc_mutex.c @@ -0,0 +1,118 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_portable.h" +#include "apr_arch_proc_mutex.h" +#include "apr_arch_thread_mutex.h" + +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_status_t ret; + apr_proc_mutex_t *new_mutex = NULL; + new_mutex = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); + + if(new_mutex ==NULL) { + return APR_ENOMEM; + } + + new_mutex->pool = pool; + ret = apr_thread_mutex_create(&(new_mutex->mutex), APR_THREAD_MUTEX_DEFAULT, pool); + + if (ret == APR_SUCCESS) + *mutex = new_mutex; + + return ret; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + if (mutex) + return apr_thread_mutex_lock(mutex->mutex); + return APR_ENOLOCK; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + if (mutex) + return apr_thread_mutex_trylock(mutex->mutex); + return APR_ENOLOCK; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + if (mutex) + return apr_thread_mutex_unlock(mutex->mutex); + return APR_ENOLOCK; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) +{ + return apr_proc_mutex_destroy(mutex); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + if (mutex) + return apr_thread_mutex_destroy(mutex->mutex); + return APR_ENOLOCK; +} + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + return NULL; +} + +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return "netwarethread"; +} + +APR_DECLARE(const char *) apr_proc_mutex_defname(void) +{ + return "netwarethread"; +} + +APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) + +/* Implement OS-specific accessors defined in apr_portable.h */ + +apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ + if (pmutex) + ospmutex = pmutex->mutex->mutex; + return APR_ENOLOCK; +} + +apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + diff --git a/srclib/apr/locks/netware/thread_cond.c b/srclib/apr/locks/netware/thread_cond.c new file mode 100644 index 0000000000..fdaa958732 --- /dev/null +++ b/srclib/apr/locks/netware/thread_cond.c @@ -0,0 +1,100 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_arch_thread_mutex.h" +#include "apr_arch_thread_cond.h" +#include "apr_portable.h" + +static apr_status_t thread_cond_cleanup(void *data) +{ + apr_thread_cond_t *cond = (apr_thread_cond_t *)data; + + NXCondFree(cond->cond); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool) +{ + apr_thread_cond_t *new_cond = NULL; + + new_cond = (apr_thread_cond_t *)apr_pcalloc(pool, sizeof(apr_thread_cond_t)); + + if(new_cond ==NULL) { + return APR_ENOMEM; + } + new_cond->pool = pool; + + new_cond->cond = NXCondAlloc(NULL); + + if(new_cond->cond == NULL) + return APR_ENOMEM; + + apr_pool_cleanup_register(new_cond->pool, new_cond, + (void*)thread_cond_cleanup, + apr_pool_cleanup_null); + *cond = new_cond; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex) +{ + if (NXCondWait(cond->cond, mutex->mutex) != 0) + return APR_EINTR; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout){ + if (NXCondTimedWait(cond->cond, mutex->mutex, + (timeout*1000)/NXGetSystemTick()) == NX_ETIMEDOUT) { + return APR_TIMEUP; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) +{ + NXCondSignal(cond->cond); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) +{ + NXCondBroadcast(cond->cond); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + apr_status_t stat; + if ((stat = thread_cond_cleanup(cond)) == APR_SUCCESS) { + apr_pool_cleanup_kill(cond->pool, cond, thread_cond_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) + diff --git a/srclib/apr/locks/netware/thread_mutex.c b/srclib/apr/locks/netware/thread_mutex.c new file mode 100644 index 0000000000..0d41b30e06 --- /dev/null +++ b/srclib/apr/locks/netware/thread_mutex.c @@ -0,0 +1,92 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_arch_thread_mutex.h" +#include "apr_portable.h" + +static apr_status_t thread_mutex_cleanup(void *data) +{ + apr_thread_mutex_t *mutex = (apr_thread_mutex_t *)data; + + NXMutexFree(mutex->mutex); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_mutex = NULL; + + /* XXX: Implement _UNNESTED flavor and favor _DEFAULT for performance + */ + if (flags & APR_THREAD_MUTEX_UNNESTED) { + return APR_ENOTIMPL; + } + new_mutex = (apr_thread_mutex_t *)apr_pcalloc(pool, sizeof(apr_thread_mutex_t)); + + if(new_mutex ==NULL) { + return APR_ENOMEM; + } + new_mutex->pool = pool; + + new_mutex->mutex = NXMutexAlloc(NX_MUTEX_RECURSIVE, 0, NULL); + + if(new_mutex->mutex == NULL) + return APR_ENOMEM; + + apr_pool_cleanup_register(new_mutex->pool, new_mutex, + (void*)thread_mutex_cleanup, + apr_pool_cleanup_null); + *mutex = new_mutex; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + NXLock(mutex->mutex); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + if (!NXTryLock(mutex->mutex)) + return APR_EBUSY; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + NXUnlock(mutex->mutex); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + apr_status_t stat; + if ((stat = thread_mutex_cleanup(mutex)) == APR_SUCCESS) { + apr_pool_cleanup_kill(mutex->pool, mutex, thread_mutex_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) + diff --git a/srclib/apr/locks/netware/thread_rwlock.c b/srclib/apr/locks/netware/thread_rwlock.c new file mode 100644 index 0000000000..1631012a2d --- /dev/null +++ b/srclib/apr/locks/netware/thread_rwlock.c @@ -0,0 +1,102 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_arch_thread_rwlock.h" +#include "apr_portable.h" + +static apr_status_t thread_rwlock_cleanup(void *data) +{ + apr_thread_rwlock_t *rwlock = (apr_thread_rwlock_t *)data; + + NXRwLockFree (rwlock->rwlock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + apr_thread_rwlock_t *new_rwlock = NULL; + + NXHierarchy_t hierarchy = 1; //for libc NKS NXRwLockAlloc + NXLockInfo_t *info; //for libc NKS NXRwLockAlloc + + new_rwlock = (apr_thread_rwlock_t *)apr_pcalloc(pool, sizeof(apr_thread_rwlock_t)); + + if(new_rwlock ==NULL) { + return APR_ENOMEM; + } + new_rwlock->pool = pool; + + info = (NXLockInfo_t *)apr_pcalloc(pool, sizeof(NXLockInfo_t)); + new_rwlock->rwlock = NXRwLockAlloc(hierarchy, info); + if(new_rwlock->rwlock == NULL) + return APR_ENOMEM; + + apr_pool_cleanup_register(new_rwlock->pool, new_rwlock, thread_rwlock_cleanup, + apr_pool_cleanup_null); + *rwlock = new_rwlock; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + NXRdLock(rwlock->rwlock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + if (!NXTryRdLock(rwlock->rwlock)) + return APR_EBUSY; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + NXWrLock(rwlock->rwlock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + if (!NXTryWrLock(rwlock->rwlock)) + return APR_EBUSY; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + NXRwUnlock(rwlock->rwlock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + if ((stat = thread_rwlock_cleanup(rwlock)) == APR_SUCCESS) { + apr_pool_cleanup_kill(rwlock->pool, rwlock, thread_rwlock_cleanup); + return APR_SUCCESS; + } + return stat; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock) + diff --git a/srclib/apr/locks/os2/proc_mutex.c b/srclib/apr/locks/os2/proc_mutex.c new file mode 100644 index 0000000000..8527e3f550 --- /dev/null +++ b/srclib/apr/locks/os2/proc_mutex.c @@ -0,0 +1,234 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_proc_mutex.h" +#include "apr_arch_file_io.h" +#include +#include + +#define CurrentTid (*_threadid) + +static char *fixed_name(const char *fname, apr_pool_t *pool) +{ + char *semname; + + if (fname == NULL) + semname = NULL; + else { + // Semaphores don't live in the file system, fix up the name + while (*fname == '/' || *fname == '\\') { + fname++; + } + + semname = apr_pstrcat(pool, "/SEM32/", fname, NULL); + + if (semname[8] == ':') { + semname[8] = '$'; + } + } + + return semname; +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *vmutex) +{ + apr_proc_mutex_t *mutex = vmutex; + return apr_proc_mutex_destroy(mutex); +} + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + return NULL; +} + +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return "os2sem"; +} + +APR_DECLARE(const char *) apr_proc_mutex_defname(void) +{ + return "os2sem"; +} + + +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new; + ULONG rc; + char *semname; + + if (mech != APR_LOCK_DEFAULT) { + return APR_ENOTIMPL; + } + + new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + new->pool = pool; + new->owner = 0; + new->lock_count = 0; + *mutex = new; + + semname = fixed_name(fname, pool); + rc = DosCreateMutexSem(semname, &(new->hMutex), DC_SEM_SHARED, FALSE); + + if (!rc) { + apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null); + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new; + ULONG rc; + char *semname; + + new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + new->pool = pool; + new->owner = 0; + new->lock_count = 0; + + semname = fixed_name(fname, pool); + rc = DosOpenMutexSem(semname, &(new->hMutex)); + *mutex = new; + + if (!rc) { + apr_pool_cleanup_register(pool, new, apr_proc_mutex_cleanup, apr_pool_cleanup_null); + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT); + + if (rc == 0) { + mutex->owner = CurrentTid; + mutex->lock_count++; + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN); + + if (rc == 0) { + mutex->owner = CurrentTid; + mutex->lock_count++; + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + ULONG rc; + + if (mutex->owner == CurrentTid && mutex->lock_count > 0) { + mutex->lock_count--; + rc = DosReleaseMutexSem(mutex->hMutex); + return APR_FROM_OS_ERROR(rc); + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + ULONG rc; + apr_status_t status = APR_SUCCESS; + + if (mutex->owner == CurrentTid) { + while (mutex->lock_count > 0 && status == APR_SUCCESS) { + status = apr_proc_mutex_unlock(mutex); + } + } + + if (status != APR_SUCCESS) { + return status; + } + + if (mutex->hMutex == 0) { + return APR_SUCCESS; + } + + rc = DosCloseMutexSem(mutex->hMutex); + + if (!rc) { + mutex->hMutex = 0; + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) + + + +/* Implement OS-specific accessors defined in apr_portable.h */ + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ + *ospmutex = pmutex->hMutex; + return APR_ENOTIMPL; +} + + + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new; + + new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + new->pool = pool; + new->owner = 0; + new->lock_count = 0; + new->hMutex = *ospmutex; + *pmutex = new; + + return APR_SUCCESS; +} + diff --git a/srclib/apr/locks/os2/thread_cond.c b/srclib/apr/locks/os2/thread_cond.c new file mode 100644 index 0000000000..575d91a8da --- /dev/null +++ b/srclib/apr/locks/os2/thread_cond.c @@ -0,0 +1,60 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_thread_mutex.h" +#include "apr_arch_thread_cond.h" +#include "apr_arch_file_io.h" +#include + +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout){ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + return APR_ENOTIMPL; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) + diff --git a/srclib/apr/locks/os2/thread_mutex.c b/srclib/apr/locks/os2/thread_mutex.c new file mode 100644 index 0000000000..0b21ea4e4a --- /dev/null +++ b/srclib/apr/locks/os2/thread_mutex.c @@ -0,0 +1,102 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_thread_mutex.h" +#include "apr_arch_file_io.h" +#include +#include + +static apr_status_t thread_mutex_cleanup(void *themutex) +{ + apr_thread_mutex_t *mutex = themutex; + return apr_thread_mutex_destroy(mutex); +} + + + +/* XXX: Need to respect APR_THREAD_MUTEX_[UN]NESTED flags argument + * or return APR_ENOTIMPL!!! + */ +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_mutex; + ULONG rc; + + new_mutex = (apr_thread_mutex_t *)apr_palloc(pool, sizeof(apr_thread_mutex_t)); + new_mutex->pool = pool; + + rc = DosCreateMutexSem(NULL, &(new_mutex->hMutex), 0, FALSE); + *mutex = new_mutex; + + if (!rc) + apr_pool_cleanup_register(pool, new_mutex, thread_mutex_cleanup, apr_pool_cleanup_null); + + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_INDEFINITE_WAIT); + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + ULONG rc = DosRequestMutexSem(mutex->hMutex, SEM_IMMEDIATE_RETURN); + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + ULONG rc = DosReleaseMutexSem(mutex->hMutex); + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + ULONG rc; + + if (mutex->hMutex == 0) + return APR_SUCCESS; + + while (DosReleaseMutexSem(mutex->hMutex) == 0); + + rc = DosCloseMutexSem(mutex->hMutex); + + if (!rc) { + mutex->hMutex = 0; + return APR_SUCCESS; + } + + return APR_FROM_OS_ERROR(rc); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) + diff --git a/srclib/apr/locks/os2/thread_rwlock.c b/srclib/apr/locks/os2/thread_rwlock.c new file mode 100644 index 0000000000..653112dab6 --- /dev/null +++ b/srclib/apr/locks/os2/thread_rwlock.c @@ -0,0 +1,200 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_thread_rwlock.h" +#include "apr_arch_file_io.h" +#include + +static apr_status_t thread_rwlock_cleanup(void *therwlock) +{ + apr_thread_rwlock_t *rwlock = therwlock; + return apr_thread_rwlock_destroy(rwlock); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + apr_thread_rwlock_t *new_rwlock; + ULONG rc; + + new_rwlock = (apr_thread_rwlock_t *)apr_palloc(pool, sizeof(apr_thread_rwlock_t)); + new_rwlock->pool = pool; + new_rwlock->readers = 0; + + rc = DosCreateMutexSem(NULL, &(new_rwlock->write_lock), 0, FALSE); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + rc = DosCreateEventSem(NULL, &(new_rwlock->read_done), 0, FALSE); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + *rwlock = new_rwlock; + + if (!rc) + apr_pool_cleanup_register(pool, new_rwlock, thread_rwlock_cleanup, + apr_pool_cleanup_null); + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + ULONG rc, posts; + + rc = DosRequestMutexSem(rwlock->write_lock, SEM_INDEFINITE_WAIT); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + /* We've successfully acquired the writer mutex so we can't be locked + * for write which means it's ok to add a reader lock. The writer mutex + * doubles as race condition protection for the readers counter. + */ + rwlock->readers++; + DosResetEventSem(rwlock->read_done, &posts); + rc = DosReleaseMutexSem(rwlock->write_lock); + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + /* As above but with different wait time */ + ULONG rc, posts; + + rc = DosRequestMutexSem(rwlock->write_lock, SEM_IMMEDIATE_RETURN); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + rwlock->readers++; + DosResetEventSem(rwlock->read_done, &posts); + rc = DosReleaseMutexSem(rwlock->write_lock); + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + ULONG rc; + + rc = DosRequestMutexSem(rwlock->write_lock, SEM_INDEFINITE_WAIT); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + /* We've got the writer lock but we have to wait for all readers to + * unlock before it's ok to use it + */ + + if (rwlock->readers) { + rc = DosWaitEventSem(rwlock->read_done, SEM_INDEFINITE_WAIT); + + if (rc) + DosReleaseMutexSem(rwlock->write_lock); + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + ULONG rc; + + rc = DosRequestMutexSem(rwlock->write_lock, SEM_IMMEDIATE_RETURN); + + if (rc) + return APR_FROM_OS_ERROR(rc); + + /* We've got the writer lock but we have to wait for all readers to + * unlock before it's ok to use it + */ + + if (rwlock->readers) { + /* There are readers active, give up */ + DosReleaseMutexSem(rwlock->write_lock); + rc = ERROR_TIMEOUT; + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + ULONG rc; + + /* First, guess that we're unlocking a writer */ + rc = DosReleaseMutexSem(rwlock->write_lock); + + if (rc == ERROR_NOT_OWNER) { + /* Nope, we must have a read lock */ + if (rwlock->readers) { + DosEnterCritSec(); + rwlock->readers--; + + if (rwlock->readers == 0) { + DosPostEventSem(rwlock->read_done); + } + + DosExitCritSec(); + rc = 0; + } + } + + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + ULONG rc; + + if (rwlock->write_lock == 0) + return APR_SUCCESS; + + while (DosReleaseMutexSem(rwlock->write_lock) == 0); + + rc = DosCloseMutexSem(rwlock->write_lock); + + if (!rc) { + rwlock->write_lock = 0; + DosCloseEventSem(rwlock->read_done); + return APR_SUCCESS; + } + + return APR_FROM_OS_ERROR(rc); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock) + diff --git a/srclib/apr/locks/unix/global_mutex.c b/srclib/apr/locks/unix/global_mutex.c new file mode 100644 index 0000000000..9a72d1438c --- /dev/null +++ b/srclib/apr/locks/unix/global_mutex.c @@ -0,0 +1,178 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_strings.h" +#include "apr_arch_global_mutex.h" +#include "apr_proc_mutex.h" +#include "apr_thread_mutex.h" +#include "apr_portable.h" + +static apr_status_t global_mutex_cleanup(void *data) +{ + apr_global_mutex_t *m = (apr_global_mutex_t *)data; + apr_status_t rv; + + rv = apr_proc_mutex_destroy(m->proc_mutex); + +#if APR_HAS_THREADS + if (m->thread_mutex) { + if (rv != APR_SUCCESS) { + (void)apr_thread_mutex_destroy(m->thread_mutex); + } + else { + rv = apr_thread_mutex_destroy(m->thread_mutex); + } + } +#endif /* APR_HAS_THREADS */ + + return rv; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_create(apr_global_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_status_t rv; + apr_global_mutex_t *m; + + m = (apr_global_mutex_t *)apr_palloc(pool, sizeof(*m)); + m->pool = pool; + + rv = apr_proc_mutex_create(&m->proc_mutex, fname, mech, m->pool); + if (rv != APR_SUCCESS) { + return rv; + } + +#if APR_HAS_THREADS + if (m->proc_mutex->inter_meth->flags & APR_PROCESS_LOCK_MECH_IS_GLOBAL) { + m->thread_mutex = NULL; /* We don't need a thread lock. */ + } + else { + rv = apr_thread_mutex_create(&m->thread_mutex, + APR_THREAD_MUTEX_DEFAULT, m->pool); + if (rv != APR_SUCCESS) { + rv = apr_proc_mutex_destroy(m->proc_mutex); + return rv; + } + } +#endif /* APR_HAS_THREADS */ + + apr_pool_cleanup_register(m->pool, (void *)m, + global_mutex_cleanup, apr_pool_cleanup_null); + *mutex = m; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_child_init( + apr_global_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + apr_status_t rv; + + rv = apr_proc_mutex_child_init(&((*mutex)->proc_mutex), fname, pool); + return rv; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_lock(apr_global_mutex_t *mutex) +{ + apr_status_t rv; + +#if APR_HAS_THREADS + if (mutex->thread_mutex) { + rv = apr_thread_mutex_lock(mutex->thread_mutex); + if (rv != APR_SUCCESS) { + return rv; + } + } +#endif /* APR_HAS_THREADS */ + + rv = apr_proc_mutex_lock(mutex->proc_mutex); + +#if APR_HAS_THREADS + if (rv != APR_SUCCESS) { + if (mutex->thread_mutex) { + (void)apr_thread_mutex_unlock(mutex->thread_mutex); + } + } +#endif /* APR_HAS_THREADS */ + + return rv; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_trylock(apr_global_mutex_t *mutex) +{ + apr_status_t rv; + +#if APR_HAS_THREADS + if (mutex->thread_mutex) { + rv = apr_thread_mutex_trylock(mutex->thread_mutex); + if (rv != APR_SUCCESS) { + return rv; + } + } +#endif /* APR_HAS_THREADS */ + + rv = apr_proc_mutex_trylock(mutex->proc_mutex); + +#if APR_HAS_THREADS + if (rv != APR_SUCCESS) { + if (mutex->thread_mutex) { + (void)apr_thread_mutex_unlock(mutex->thread_mutex); + } + } +#endif /* APR_HAS_THREADS */ + + return rv; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_unlock(apr_global_mutex_t *mutex) +{ + apr_status_t rv; + + rv = apr_proc_mutex_unlock(mutex->proc_mutex); +#if APR_HAS_THREADS + if (mutex->thread_mutex) { + if (rv != APR_SUCCESS) { + (void)apr_thread_mutex_unlock(mutex->thread_mutex); + } + else { + rv = apr_thread_mutex_unlock(mutex->thread_mutex); + } + } +#endif /* APR_HAS_THREADS */ + return rv; +} + +APR_DECLARE(apr_status_t) apr_os_global_mutex_get(apr_os_global_mutex_t *ospmutex, + apr_global_mutex_t *pmutex) +{ + ospmutex->pool = pmutex->pool; + ospmutex->proc_mutex = pmutex->proc_mutex; +#if APR_HAS_THREADS + ospmutex->thread_mutex = pmutex->thread_mutex; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_global_mutex_destroy(apr_global_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, global_mutex_cleanup); +} + +APR_POOL_IMPLEMENT_ACCESSOR(global_mutex) diff --git a/srclib/apr/locks/unix/proc_mutex.c b/srclib/apr/locks/unix/proc_mutex.c new file mode 100644 index 0000000000..98fb2eb1e6 --- /dev/null +++ b/srclib/apr/locks/unix/proc_mutex.c @@ -0,0 +1,864 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_strings.h" +#include "apr_arch_proc_mutex.h" +#include "apr_arch_file_io.h" /* for apr_mkstemp() */ + +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, apr_proc_mutex_cleanup); +} + +static apr_status_t proc_mutex_no_tryacquire(apr_proc_mutex_t *new_mutex) +{ + return APR_ENOTIMPL; +} + +#if APR_HAS_POSIXSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || \ + APR_HAS_PROC_PTHREAD_SERIALIZE || APR_HAS_SYSVSEM_SERIALIZE +static apr_status_t proc_mutex_no_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *cont, + const char *fname) +{ + return APR_SUCCESS; +} +#endif + +#if APR_HAS_POSIXSEM_SERIALIZE + +#ifndef SEM_FAILED +#define SEM_FAILED (-1) +#endif + +static apr_status_t proc_mutex_posix_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex = mutex_; + + if (sem_close(mutex->psem_interproc) < 0) { + return errno; + } + + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_posix_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + sem_t *psem; + char semname[31]; + apr_time_t now; + unsigned long sec; + unsigned long usec; + + new_mutex->interproc = apr_palloc(new_mutex->pool, + sizeof(*new_mutex->interproc)); + /* + * This bogusness is to follow what appears to be the + * lowest common denominator in Posix semaphore naming: + * - start with '/' + * - be at most 14 chars + * - be unique and not match anything on the filesystem + * + * Because of this, we ignore fname, and try our + * own naming system. We tuck the name away, since it might + * be useful for debugging. to make this as robust as possible, + * we initially try something larger (and hopefully more unique) + * and gracefully fail down to the LCD above. + * + * NOTE: Darwin (Mac OS X) seems to be the most restrictive + * implementation. Versions previous to Darwin 6.2 had the 14 + * char limit, but later rev's allow up to 31 characters. + * + * FIXME: There is a small window of opportunity where + * instead of getting a new semaphore descriptor, we get + * a previously obtained one. This can happen if the requests + * are made at the "same time" and in the small span of time between + * the sem_open and the sem_unlink. Use of O_EXCL does not + * help here however... + * + */ + now = apr_time_now(); + sec = apr_time_sec(now); + usec = apr_time_usec(now); + apr_snprintf(semname, sizeof(semname), "/ApR.%lxZ%lx", sec, usec); + psem = sem_open(semname, O_CREAT, 0644, 1); + if ((psem == (sem_t *)SEM_FAILED) && (errno == ENAMETOOLONG)) { + /* Oh well, good try */ + semname[13] = '\0'; + psem = sem_open(semname, O_CREAT, 0644, 1); + } + + if (psem == (sem_t *)SEM_FAILED) { + return errno; + } + /* Ahhh. The joys of Posix sems. Predelete it... */ + sem_unlink(semname); + new_mutex->psem_interproc = psem; + new_mutex->fname = apr_pstrdup(new_mutex->pool, semname); + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_posix_acquire(apr_proc_mutex_t *mutex) +{ + if (sem_wait(mutex->psem_interproc) < 0) { + return errno; + } + mutex->curr_locked = 1; + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex) +{ + mutex->curr_locked = 0; + if (sem_post(mutex->psem_interproc) < 0) { + /* any failure is probably fatal, so no big deal to leave + * ->curr_locked at 0. */ + return errno; + } + return APR_SUCCESS; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_posixsem_methods = +{ +#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(POSIXSEM_IS_GLOBAL) + APR_PROCESS_LOCK_MECH_IS_GLOBAL, +#else + 0, +#endif + proc_mutex_posix_create, + proc_mutex_posix_acquire, + proc_mutex_no_tryacquire, + proc_mutex_posix_release, + proc_mutex_posix_cleanup, + proc_mutex_no_child_init, + "posixsem" +}; + +#endif /* Posix sem implementation */ + +#if APR_HAS_SYSVSEM_SERIALIZE + +static struct sembuf proc_mutex_op_on; +static struct sembuf proc_mutex_op_off; + +static void proc_mutex_sysv_setup(void) +{ + proc_mutex_op_on.sem_num = 0; + proc_mutex_op_on.sem_op = -1; + proc_mutex_op_on.sem_flg = SEM_UNDO; + proc_mutex_op_off.sem_num = 0; + proc_mutex_op_off.sem_op = 1; + proc_mutex_op_off.sem_flg = SEM_UNDO; +} + +static apr_status_t proc_mutex_sysv_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + union semun ick; + + if (mutex->interproc->filedes != -1) { + ick.val = 0; + semctl(mutex->interproc->filedes, 0, IPC_RMID, ick); + } + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_sysv_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + union semun ick; + apr_status_t rv; + + new_mutex->interproc = apr_palloc(new_mutex->pool, sizeof(*new_mutex->interproc)); + new_mutex->interproc->filedes = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600); + + if (new_mutex->interproc->filedes < 0) { + rv = errno; + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + ick.val = 1; + if (semctl(new_mutex->interproc->filedes, 0, SETVAL, ick) < 0) { + rv = errno; + proc_mutex_sysv_cleanup(new_mutex); + return rv; + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_sysv_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_on, 1); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + mutex->curr_locked = 1; + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_sysv_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = semop(mutex->interproc->filedes, &proc_mutex_op_off, 1); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + return APR_SUCCESS; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_sysv_methods = +{ +#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(SYSVSEM_IS_GLOBAL) + APR_PROCESS_LOCK_MECH_IS_GLOBAL, +#else + 0, +#endif + proc_mutex_sysv_create, + proc_mutex_sysv_acquire, + proc_mutex_no_tryacquire, + proc_mutex_sysv_release, + proc_mutex_sysv_cleanup, + proc_mutex_no_child_init, + "sysvsem" +}; + +#endif /* SysV sem implementation */ + +#if APR_HAS_PROC_PTHREAD_SERIALIZE + +static apr_status_t proc_mutex_proc_pthread_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex=mutex_; + apr_status_t rv; + + if (mutex->curr_locked == 1) { + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; + } + } + /* curr_locked is set to -1 until the mutex has been created */ + if (mutex->curr_locked != -1) { + if ((rv = pthread_mutex_destroy(mutex->pthread_interproc))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; + } + } + if (munmap((caddr_t)mutex->pthread_interproc, sizeof(pthread_mutex_t))) { + return errno; + } + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_proc_pthread_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + apr_status_t rv; + int fd; + pthread_mutexattr_t mattr; + + fd = open("/dev/zero", O_RDWR); + if (fd < 0) { + return errno; + } + + new_mutex->pthread_interproc = (pthread_mutex_t *)mmap( + (caddr_t) 0, + sizeof(pthread_mutex_t), + PROT_READ | PROT_WRITE, MAP_SHARED, + fd, 0); + if (new_mutex->pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) { + close(fd); + return errno; + } + close(fd); + + new_mutex->curr_locked = -1; /* until the mutex has been created */ + + if ((rv = pthread_mutexattr_init(&mattr))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + if ((rv = pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + +#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP + if ((rv = pthread_mutexattr_setrobust_np(&mattr, + PTHREAD_MUTEX_ROBUST_NP))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + if ((rv = pthread_mutexattr_setprotocol(&mattr, PTHREAD_PRIO_INHERIT))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } +#endif + + if ((rv = pthread_mutex_init(new_mutex->pthread_interproc, &mattr))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + pthread_mutexattr_destroy(&mattr); + return rv; + } + + new_mutex->curr_locked = 0; /* mutex created now */ + + if ((rv = pthread_mutexattr_destroy(&mattr))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + proc_mutex_proc_pthread_cleanup(new_mutex); + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_proc_pthread_acquire(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + if ((rv = pthread_mutex_lock(mutex->pthread_interproc))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif +#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP + /* Okay, our owner died. Let's try to make it consistent again. */ + if (rv == EOWNERDEAD) { + pthread_mutex_consistent_np(mutex->pthread_interproc); + } + else + return rv; +#else + return rv; +#endif + } + mutex->curr_locked = 1; + return APR_SUCCESS; +} + +/* TODO: Add proc_mutex_proc_pthread_tryacquire(apr_proc_mutex_t *mutex) */ + +static apr_status_t proc_mutex_proc_pthread_release(apr_proc_mutex_t *mutex) +{ + apr_status_t rv; + + mutex->curr_locked = 0; + if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; + } + return APR_SUCCESS; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_proc_pthread_methods = +{ + APR_PROCESS_LOCK_MECH_IS_GLOBAL, + proc_mutex_proc_pthread_create, + proc_mutex_proc_pthread_acquire, + proc_mutex_no_tryacquire, + proc_mutex_proc_pthread_release, + proc_mutex_proc_pthread_cleanup, + proc_mutex_no_child_init, + "pthread" +}; + +#endif + +#if APR_HAS_FCNTL_SERIALIZE + +static struct flock proc_mutex_lock_it; +static struct flock proc_mutex_unlock_it; + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *); + +static void proc_mutex_fcntl_setup(void) +{ + proc_mutex_lock_it.l_whence = SEEK_SET; /* from current point */ + proc_mutex_lock_it.l_start = 0; /* -"- */ + proc_mutex_lock_it.l_len = 0; /* until end of file */ + proc_mutex_lock_it.l_type = F_WRLCK; /* set exclusive/write lock */ + proc_mutex_lock_it.l_pid = 0; /* pid not actually interesting */ + proc_mutex_unlock_it.l_whence = SEEK_SET; /* from current point */ + proc_mutex_unlock_it.l_start = 0; /* -"- */ + proc_mutex_unlock_it.l_len = 0; /* until end of file */ + proc_mutex_unlock_it.l_type = F_UNLCK; /* set exclusive/write lock */ + proc_mutex_unlock_it.l_pid = 0; /* pid not actually interesting */ +} + +static apr_status_t proc_mutex_fcntl_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_fcntl_release(mutex); + if (status != APR_SUCCESS) + return status; + } + + return apr_file_close(mutex->interproc); +} + +static apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + APR_CREATE | APR_WRITE | APR_EXCL, + APR_UREAD | APR_UWRITE | APR_GREAD | APR_WREAD, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + APR_CREATE | APR_WRITE | APR_EXCL, + new_mutex->pool); + } + + if (rv != APR_SUCCESS) { + return rv; + } + + new_mutex->curr_locked = 0; + unlink(new_mutex->fname); + apr_pool_cleanup_register(new_mutex->pool, + (void*)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_fcntl_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = fcntl(mutex->interproc->filedes, F_SETLKW, &proc_mutex_lock_it); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + mutex->curr_locked=1; + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_fcntl_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked=0; + do { + rc = fcntl(mutex->interproc->filedes, F_SETLKW, &proc_mutex_unlock_it); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + return APR_SUCCESS; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_fcntl_methods = +{ +#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FCNTL_IS_GLOBAL) + APR_PROCESS_LOCK_MECH_IS_GLOBAL, +#else + 0, +#endif + proc_mutex_fcntl_create, + proc_mutex_fcntl_acquire, + proc_mutex_no_tryacquire, + proc_mutex_fcntl_release, + proc_mutex_fcntl_cleanup, + proc_mutex_no_child_init, + "fcntl" +}; + +#endif /* fcntl implementation */ + +#if APR_HAS_FLOCK_SERIALIZE + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *); + +static apr_status_t proc_mutex_flock_cleanup(void *mutex_) +{ + apr_status_t status; + apr_proc_mutex_t *mutex=mutex_; + + if (mutex->curr_locked == 1) { + status = proc_mutex_flock_release(mutex); + if (status != APR_SUCCESS) + return status; + } + if (mutex->interproc) { /* if it was opened properly */ + apr_file_close(mutex->interproc); + } + unlink(mutex->fname); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex, + const char *fname) +{ + int rv; + + if (fname) { + new_mutex->fname = apr_pstrdup(new_mutex->pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + APR_CREATE | APR_WRITE | APR_EXCL, + APR_UREAD | APR_UWRITE, + new_mutex->pool); + } + else { + new_mutex->fname = apr_pstrdup(new_mutex->pool, "/tmp/aprXXXXXX"); + rv = apr_file_mktemp(&new_mutex->interproc, new_mutex->fname, + APR_CREATE | APR_WRITE | APR_EXCL, + new_mutex->pool); + } + + if (rv != APR_SUCCESS) { + proc_mutex_flock_cleanup(new_mutex); + return errno; + } + new_mutex->curr_locked = 0; + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_flock_acquire(apr_proc_mutex_t *mutex) +{ + int rc; + + do { + rc = flock(mutex->interproc->filedes, LOCK_EX); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + mutex->curr_locked = 1; + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_flock_release(apr_proc_mutex_t *mutex) +{ + int rc; + + mutex->curr_locked = 0; + do { + rc = flock(mutex->interproc->filedes, LOCK_UN); + } while (rc < 0 && errno == EINTR); + if (rc < 0) { + return errno; + } + return APR_SUCCESS; +} + +static apr_status_t proc_mutex_flock_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *pool, + const char *fname) +{ + apr_proc_mutex_t *new_mutex; + int rv; + + new_mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + + memcpy(new_mutex, *mutex, sizeof *new_mutex); + new_mutex->pool = pool; + if (!fname) { + fname = (*mutex)->fname; + } + new_mutex->fname = apr_pstrdup(pool, fname); + rv = apr_file_open(&new_mutex->interproc, new_mutex->fname, + APR_WRITE, 0, new_mutex->pool); + if (rv != APR_SUCCESS) { + return rv; + } + *mutex = new_mutex; + return APR_SUCCESS; +} + +static const apr_proc_mutex_unix_lock_methods_t mutex_flock_methods = +{ +#if APR_PROCESS_LOCK_IS_GLOBAL || !APR_HAS_THREADS || defined(FLOCK_IS_GLOBAL) + APR_PROCESS_LOCK_MECH_IS_GLOBAL, +#else + 0, +#endif + proc_mutex_flock_create, + proc_mutex_flock_acquire, + proc_mutex_no_tryacquire, + proc_mutex_flock_release, + proc_mutex_flock_cleanup, + proc_mutex_flock_child_init, + "flock" +}; + +#endif /* flock implementation */ + +void apr_proc_mutex_unix_setup_lock(void) +{ + /* setup only needed for sysvsem and fnctl */ +#if APR_HAS_SYSVSEM_SERIALIZE + proc_mutex_sysv_setup(); +#endif +#if APR_HAS_FCNTL_SERIALIZE + proc_mutex_fcntl_setup(); +#endif +} + +static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech) +{ + switch (mech) { + case APR_LOCK_FCNTL: +#if APR_HAS_FCNTL_SERIALIZE + new_mutex->inter_meth = &mutex_fcntl_methods; +#else + return APR_ENOTIMPL; +#endif + break; + case APR_LOCK_FLOCK: +#if APR_HAS_FLOCK_SERIALIZE + new_mutex->inter_meth = &mutex_flock_methods; +#else + return APR_ENOTIMPL; +#endif + break; + case APR_LOCK_SYSVSEM: +#if APR_HAS_SYSVSEM_SERIALIZE + new_mutex->inter_meth = &mutex_sysv_methods; +#else + return APR_ENOTIMPL; +#endif + break; + case APR_LOCK_POSIXSEM: +#if APR_HAS_POSIXSEM_SERIALIZE + new_mutex->inter_meth = &mutex_posixsem_methods; +#else + return APR_ENOTIMPL; +#endif + break; + case APR_LOCK_PROC_PTHREAD: +#if APR_HAS_PROC_PTHREAD_SERIALIZE + new_mutex->inter_meth = &mutex_proc_pthread_methods; +#else + return APR_ENOTIMPL; +#endif + break; + case APR_LOCK_DEFAULT: +#if APR_USE_FLOCK_SERIALIZE + new_mutex->inter_meth = &mutex_flock_methods; +#elif APR_USE_SYSVSEM_SERIALIZE + new_mutex->inter_meth = &mutex_sysv_methods; +#elif APR_USE_FCNTL_SERIALIZE + new_mutex->inter_meth = &mutex_fcntl_methods; +#elif APR_USE_PROC_PTHREAD_SERIALIZE + new_mutex->inter_meth = &mutex_proc_pthread_methods; +#elif APR_USE_POSIXSEM_SERIALIZE + new_mutex->inter_meth = &mutex_posixsem_methods; +#else + return APR_ENOTIMPL; +#endif + break; + default: + return APR_ENOTIMPL; + } + return APR_SUCCESS; +} + +APR_DECLARE(const char *) apr_proc_mutex_defname(void) +{ + apr_status_t rv; + apr_proc_mutex_t mutex; + + if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT)) != APR_SUCCESS) { + return "unknown"; + } + mutex.meth = mutex.inter_meth; + + return apr_proc_mutex_name(&mutex); +} + +static apr_status_t proc_mutex_create(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech, const char *fname) +{ + apr_status_t rv; + + if ((rv = proc_mutex_choose_method(new_mutex, mech)) != APR_SUCCESS) { + return rv; + } + + new_mutex->meth = new_mutex->inter_meth; + + if ((rv = new_mutex->meth->create(new_mutex, fname)) != APR_SUCCESS) { + return rv; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + apr_proc_mutex_t *new_mutex; + apr_status_t rv; + + new_mutex = apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); + new_mutex->pool = pool; + + if ((rv = proc_mutex_create(new_mutex, mech, fname)) != APR_SUCCESS) + return rv; + + *mutex = new_mutex; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + return (*mutex)->meth->child_init(mutex, pool, fname); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->acquire(mutex); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->tryacquire(mutex); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + return mutex->meth->release(mutex); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) +{ + return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex); +} + +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return mutex->meth->name; +} + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + /* POSIX sems use the fname field but don't use a file, + * so be careful. */ +#if APR_HAS_FLOCK_SERIALIZE + if (mutex->meth == &mutex_flock_methods) { + return mutex->fname; + } +#endif +#if APR_HAS_FCNTL_SERIALIZE + if (mutex->meth == &mutex_fcntl_methods) { + return mutex->fname; + } +#endif + return NULL; +} + +APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) + +/* Implement OS-specific accessors defined in apr_portable.h */ + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *pmutex) +{ +#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE || APR_HAS_POSIXSEM_SERIALIZE + ospmutex->crossproc = pmutex->interproc->filedes; +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + ospmutex->pthread_interproc = pmutex->pthread_interproc; +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*pmutex) == NULL) { + (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, + sizeof(apr_proc_mutex_t)); + (*pmutex)->pool = pool; + } +#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE || APR_HAS_POSIXSEM_SERIALIZE + apr_os_file_put(&(*pmutex)->interproc, &ospmutex->crossproc, 0, pool); +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + (*pmutex)->pthread_interproc = ospmutex->pthread_interproc; +#endif + return APR_SUCCESS; +} + diff --git a/srclib/apr/locks/unix/thread_cond.c b/srclib/apr/locks/unix/thread_cond.c new file mode 100644 index 0000000000..c1ebb895c0 --- /dev/null +++ b/srclib/apr/locks/unix/thread_cond.c @@ -0,0 +1,135 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" + +#if APR_HAS_THREADS + +#include "apr_arch_thread_mutex.h" +#include "apr_arch_thread_cond.h" + +static apr_status_t thread_cond_cleanup(void *data) +{ + apr_thread_cond_t *cond = (apr_thread_cond_t *)data; + apr_status_t rv; + + rv = pthread_cond_destroy(&cond->cond); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool) +{ + apr_thread_cond_t *new_cond; + apr_status_t rv; + + new_cond = apr_palloc(pool, sizeof(apr_thread_cond_t)); + + new_cond->pool = pool; + + if ((rv = pthread_cond_init(&new_cond->cond, NULL))) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; + } + + apr_pool_cleanup_register(new_cond->pool, + (void *)new_cond, thread_cond_cleanup, + apr_pool_cleanup_null); + + *cond = new_cond; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_cond_wait(&cond->cond, &mutex->mutex); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout) +{ + apr_status_t rv; + apr_time_t then; + struct timespec abstime; + + then = apr_time_now() + timeout; + abstime.tv_sec = apr_time_sec(then); + abstime.tv_nsec = apr_time_usec(then) * 1000; /* nanoseconds */ + + rv = pthread_cond_timedwait(&cond->cond, &mutex->mutex, &abstime); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + if (ETIMEDOUT == rv) { + return APR_TIMEUP; + } + return rv; +} + + +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) +{ + apr_status_t rv; + + rv = pthread_cond_signal(&cond->cond); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) +{ + apr_status_t rv; + + rv = pthread_cond_broadcast(&cond->cond); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) + +#endif /* APR_HAS_THREADS */ diff --git a/srclib/apr/locks/unix/thread_mutex.c b/srclib/apr/locks/unix/thread_mutex.c new file mode 100644 index 0000000000..31a566f6e9 --- /dev/null +++ b/srclib/apr/locks/unix/thread_mutex.c @@ -0,0 +1,138 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_thread_mutex.h" +#define APR_WANT_MEMFUNC +#include "apr_want.h" + +#if APR_HAS_THREADS + +static apr_status_t thread_mutex_cleanup(void *data) +{ + apr_thread_mutex_t *mutex = data; + apr_status_t rv; + + rv = pthread_mutex_destroy(&mutex->mutex); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + apr_thread_mutex_t *new_mutex; + apr_status_t rv; + +#ifndef HAVE_PTHREAD_MUTEX_RECURSIVE + if (flags & APR_THREAD_MUTEX_NESTED) { + return APR_ENOTIMPL; + } +#endif + + new_mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t)); + new_mutex->pool = pool; + +#ifdef HAVE_PTHREAD_MUTEX_RECURSIVE + if (flags & APR_THREAD_MUTEX_NESTED) { + pthread_mutexattr_t mattr; + + rv = pthread_mutexattr_init(&mattr); + if (rv) return rv; + + rv = pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE); + if (rv) { + pthread_mutexattr_destroy(&mattr); + return rv; + } + + rv = pthread_mutex_init(&new_mutex->mutex, &mattr); + + pthread_mutexattr_destroy(&mattr); + } else +#endif + rv = pthread_mutex_init(&new_mutex->mutex, NULL); + + if (rv) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; + } + + apr_pool_cleanup_register(new_mutex->pool, + new_mutex, thread_mutex_cleanup, + apr_pool_cleanup_null); + + *mutex = new_mutex; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_lock(&mutex->mutex); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + apr_status_t rv; + + rv = pthread_mutex_trylock(&mutex->mutex); + if (rv) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return (rv == EBUSY) ? APR_EBUSY : rv; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + apr_status_t status; + + status = pthread_mutex_unlock(&mutex->mutex); +#ifdef PTHREAD_SETS_ERRNO + if (status) { + status = errno; + } +#endif + + return status; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) + +#endif /* APR_HAS_THREADS */ diff --git a/srclib/apr/locks/unix/thread_rwlock.c b/srclib/apr/locks/unix/thread_rwlock.c new file mode 100644 index 0000000000..18f374794a --- /dev/null +++ b/srclib/apr/locks/unix/thread_rwlock.c @@ -0,0 +1,181 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_thread_rwlock.h" +#include "apr_private.h" + +#if APR_HAS_THREADS + +#ifdef HAVE_PTHREAD_RWLOCKS + +/* The rwlock must be initialized but not locked by any thread when + * cleanup is called. */ +static apr_status_t thread_rwlock_cleanup(void *data) +{ + apr_thread_rwlock_t *rwlock = (apr_thread_rwlock_t *)data; + apr_status_t stat; + + stat = pthread_rwlock_destroy(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + apr_thread_rwlock_t *new_rwlock; + apr_status_t stat; + + new_rwlock = apr_palloc(pool, sizeof(apr_thread_rwlock_t)); + new_rwlock->pool = pool; + + if ((stat = pthread_rwlock_init(&new_rwlock->rwlock, NULL))) { +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + return stat; + } + + apr_pool_cleanup_register(new_rwlock->pool, + (void *)new_rwlock, thread_rwlock_cleanup, + apr_pool_cleanup_null); + + *rwlock = new_rwlock; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + + stat = pthread_rwlock_rdlock(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + + stat = pthread_rwlock_tryrdlock(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + /* Normalize the return code. */ + if (stat == EBUSY) + stat = APR_EBUSY; + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + + stat = pthread_rwlock_wrlock(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + + stat = pthread_rwlock_trywrlock(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + /* Normalize the return code. */ + if (stat == EBUSY) + stat = APR_EBUSY; + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t stat; + + stat = pthread_rwlock_unlock(&rwlock->rwlock); +#ifdef PTHREAD_SETS_ERRNO + if (stat) { + stat = errno; + } +#endif + return stat; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + return apr_pool_cleanup_run(rwlock->pool, rwlock, thread_rwlock_cleanup); +} + +#else /* HAVE_PTHREAD_RWLOCKS */ + +APR_DECLARE(apr_status_t) apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + return APR_ENOTIMPL; +} + +#endif /* HAVE_PTHREAD_RWLOCKS */ +APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock) + +#endif /* APR_HAS_THREADS */ diff --git a/srclib/apr/locks/win32/proc_mutex.c b/srclib/apr/locks/win32/proc_mutex.c new file mode 100644 index 0000000000..9e316506a9 --- /dev/null +++ b/srclib/apr/locks/win32/proc_mutex.c @@ -0,0 +1,216 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_arch_file_io.h" +#include "apr_arch_proc_mutex.h" +#include "apr_arch_misc.h" + +static apr_status_t proc_mutex_cleanup(void *mutex_) +{ + apr_proc_mutex_t *mutex = mutex_; + + if (mutex->handle) { + if (CloseHandle(mutex->handle) == 0) { + return apr_get_os_error(); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, + const char *fname, + apr_lockmech_e mech, + apr_pool_t *pool) +{ + HANDLE hMutex; + void *mutexkey; + + /* res_name_from_filename turns fname into a pseduo-name + * without slashes or backslashes, and prepends the \global + * prefix on Win2K and later + */ + if (fname) { + mutexkey = res_name_from_filename(fname, 1, pool); + } + else { + mutexkey = NULL; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + hMutex = CreateMutexW(NULL, FALSE, mutexkey); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + hMutex = CreateMutexA(NULL, FALSE, mutexkey); + } +#endif + + if (!hMutex) { + return apr_get_os_error(); + } + + *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + (*mutex)->pool = pool; + (*mutex)->handle = hMutex; + (*mutex)->fname = fname; + apr_pool_cleanup_register((*mutex)->pool, *mutex, + proc_mutex_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, + const char *fname, + apr_pool_t *pool) +{ + HANDLE hMutex; + void *mutexkey; + + if (!fname) { + /* Reinitializing unnamed mutexes is a noop in the Unix code. */ + return APR_SUCCESS; + } + + /* res_name_from_filename turns file into a pseudo-name + * without slashes or backslashes, and prepends the \global + * prefix on Win2K and later + */ + mutexkey = res_name_from_filename(fname, 1, pool); + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + hMutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, mutexkey); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + hMutex = OpenMutexA(MUTEX_ALL_ACCESS, FALSE, mutexkey); + } +#endif + + if (!hMutex) { + return apr_get_os_error(); + } + + *mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t)); + (*mutex)->pool = pool; + (*mutex)->handle = hMutex; + (*mutex)->fname = fname; + apr_pool_cleanup_register((*mutex)->pool, *mutex, + proc_mutex_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) +{ + DWORD rv; + + rv = WaitForSingleObject(mutex->handle, INFINITE); + + if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) +{ + DWORD rv; + + rv = WaitForSingleObject(mutex->handle, 0); + + if (rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +{ + if (ReleaseMutex(mutex->handle) == 0) { + return apr_get_os_error(); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) +{ + apr_status_t stat; + + stat = proc_mutex_cleanup(mutex); + if (stat == APR_SUCCESS) { + apr_pool_cleanup_kill(mutex->pool, mutex, proc_mutex_cleanup); + } + return stat; +} + +APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) +{ + return apr_proc_mutex_destroy((apr_proc_mutex_t *)mutex); +} + +APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +{ + return NULL; +} + +APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +{ + return mutex->fname; +} + +APR_DECLARE(const char *) apr_proc_mutex_defname(void) +{ + return "win32mutex"; +} + +APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) + +/* Implement OS-specific accessors defined in apr_portable.h */ + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, + apr_proc_mutex_t *mutex) +{ + *ospmutex = mutex->handle; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, + apr_os_proc_mutex_t *ospmutex, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*pmutex) == NULL) { + (*pmutex) = (apr_proc_mutex_t *)apr_palloc(pool, + sizeof(apr_proc_mutex_t)); + (*pmutex)->pool = pool; + } + (*pmutex)->handle = *ospmutex; + return APR_SUCCESS; +} + diff --git a/srclib/apr/locks/win32/thread_cond.c b/srclib/apr/locks/win32/thread_cond.c new file mode 100644 index 0000000000..dca1e8fb65 --- /dev/null +++ b/srclib/apr/locks/win32/thread_cond.c @@ -0,0 +1,173 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "win32/apr_arch_thread_mutex.h" +#include "win32/apr_arch_thread_cond.h" +#include "apr_portable.h" + +static apr_status_t thread_cond_cleanup(void *data) +{ + apr_thread_cond_t *cond = data; + CloseHandle(cond->mutex); + CloseHandle(cond->event); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond, + apr_pool_t *pool) +{ + *cond = apr_palloc(pool, sizeof(**cond)); + (*cond)->pool = pool; + (*cond)->event = CreateEvent(NULL, TRUE, FALSE, NULL); + (*cond)->mutex = CreateMutex(NULL, FALSE, NULL); + (*cond)->signal_all = 0; + (*cond)->num_waiting = 0; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex) +{ + DWORD res; + + while (1) { + res = WaitForSingleObject(cond->mutex, INFINITE); + if (res != WAIT_OBJECT_0) { + return apr_get_os_error(); + } + cond->num_waiting++; + ReleaseMutex(cond->mutex); + + apr_thread_mutex_unlock(mutex); + res = WaitForSingleObject(cond->event, INFINITE); + cond->num_waiting--; + if (res != WAIT_OBJECT_0) { + apr_status_t rv = apr_get_os_error(); + ReleaseMutex(cond->mutex); + return rv; + } + if (cond->signal_all) { + if (cond->num_waiting == 0) { + ResetEvent(cond->event); + } + break; + } + if (cond->signalled) { + cond->signalled = 0; + ResetEvent(cond->event); + break; + } + ReleaseMutex(cond->mutex); + } + apr_thread_mutex_lock(mutex); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_timedwait(apr_thread_cond_t *cond, + apr_thread_mutex_t *mutex, + apr_interval_time_t timeout) +{ + DWORD res; + DWORD timeout_ms = (DWORD) apr_time_as_msec(timeout); + + while (1) { + res = WaitForSingleObject(cond->mutex, timeout_ms); + if (res != WAIT_OBJECT_0) { + if (res == WAIT_TIMEOUT) { + return APR_TIMEUP; + } + return apr_get_os_error(); + } + cond->num_waiting++; + ReleaseMutex(cond->mutex); + + apr_thread_mutex_unlock(mutex); + res = WaitForSingleObject(cond->event, timeout_ms); + cond->num_waiting--; + if (res != WAIT_OBJECT_0) { + apr_status_t rv = apr_get_os_error(); + ReleaseMutex(cond->mutex); + apr_thread_mutex_lock(mutex); + if (res == WAIT_TIMEOUT) { + return APR_TIMEUP; + } + return apr_get_os_error(); + } + if (cond->signal_all) { + if (cond->num_waiting == 0) { + ResetEvent(cond->event); + } + break; + } + if (cond->signalled) { + cond->signalled = 0; + ResetEvent(cond->event); + break; + } + ReleaseMutex(cond->mutex); + } + apr_thread_mutex_lock(mutex); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_signal(apr_thread_cond_t *cond) +{ + apr_status_t rv = APR_SUCCESS; + DWORD res; + + res = WaitForSingleObject(cond->mutex, INFINITE); + if (res != WAIT_OBJECT_0) { + return apr_get_os_error(); + } + cond->signalled = 1; + res = SetEvent(cond->event); + if (res == 0) { + rv = apr_get_os_error(); + } + ReleaseMutex(cond->mutex); + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_broadcast(apr_thread_cond_t *cond) +{ + apr_status_t rv = APR_SUCCESS; + DWORD res; + + res = WaitForSingleObject(cond->mutex, INFINITE); + if (res != WAIT_OBJECT_0) { + return apr_get_os_error(); + } + cond->signalled = 1; + cond->signal_all = 1; + res = SetEvent(cond->event); + if (res == 0) { + rv = apr_get_os_error(); + } + ReleaseMutex(cond->mutex); + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_cond_destroy(apr_thread_cond_t *cond) +{ + return apr_pool_cleanup_run(cond->pool, cond, thread_cond_cleanup); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_cond) + diff --git a/srclib/apr/locks/win32/thread_mutex.c b/srclib/apr/locks/win32/thread_mutex.c new file mode 100644 index 0000000000..0a848fbcf5 --- /dev/null +++ b/srclib/apr/locks/win32/thread_mutex.c @@ -0,0 +1,135 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_arch_thread_mutex.h" +#include "apr_thread_mutex.h" +#include "apr_portable.h" +#include "apr_arch_misc.h" + +static apr_status_t thread_mutex_cleanup(void *data) +{ + apr_thread_mutex_t *lock = data; + + if (lock->type == thread_mutex_critical_section) { + DeleteCriticalSection(&lock->section); + } + else { + if (!CloseHandle(lock->handle)) { + return apr_get_os_error(); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, + unsigned int flags, + apr_pool_t *pool) +{ + (*mutex) = (apr_thread_mutex_t *)apr_palloc(pool, sizeof(**mutex)); + + (*mutex)->pool = pool; + + if (flags & APR_THREAD_MUTEX_UNNESTED) { + /* Use an auto-reset signaled event, ready to accept one + * waiting thread. + */ + (*mutex)->type = thread_mutex_unnested_event; + (*mutex)->handle = CreateEvent(NULL, FALSE, TRUE, NULL); + } + else { +#if APR_HAS_UNICODE_FS + /* Critical Sections are terrific, performance-wise, on NT. + * On Win9x, we cannot 'try' on a critical section, so we + * use a [slower] mutex object, instead. + */ + IF_WIN_OS_IS_UNICODE { + (*mutex)->type = thread_mutex_critical_section; + InitializeCriticalSection(&(*mutex)->section); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI { + (*mutex)->type = thread_mutex_nested_mutex; + (*mutex)->handle = CreateMutex(NULL, FALSE, NULL); + + } +#endif + } + + apr_pool_cleanup_register((*mutex)->pool, (*mutex), thread_mutex_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_lock(apr_thread_mutex_t *mutex) +{ + if (mutex->type == thread_mutex_critical_section) { + EnterCriticalSection(&mutex->section); + } + else { + DWORD rv = WaitForSingleObject(mutex->handle, INFINITE); + if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) { + return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error(); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_trylock(apr_thread_mutex_t *mutex) +{ + if (mutex->type == thread_mutex_critical_section) { + if (!TryEnterCriticalSection(&mutex->section)) { + return APR_EBUSY; + } + } + else { + DWORD rv = WaitForSingleObject(mutex->handle, 0); + if ((rv != WAIT_OBJECT_0) && (rv != WAIT_ABANDONED)) { + return (rv == WAIT_TIMEOUT) ? APR_EBUSY : apr_get_os_error(); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_unlock(apr_thread_mutex_t *mutex) +{ + if (mutex->type == thread_mutex_critical_section) { + LeaveCriticalSection(&mutex->section); + } + else if (mutex->type == thread_mutex_unnested_event) { + if (!SetEvent(mutex->handle)) { + return apr_get_os_error(); + } + } + else if (mutex->type == thread_mutex_nested_mutex) { + if (!ReleaseMutex(mutex->handle)) { + return apr_get_os_error(); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_mutex_destroy(apr_thread_mutex_t *mutex) +{ + return apr_pool_cleanup_run(mutex->pool, mutex, thread_mutex_cleanup); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_mutex) + diff --git a/srclib/apr/locks/win32/thread_rwlock.c b/srclib/apr/locks/win32/thread_rwlock.c new file mode 100644 index 0000000000..75d79bcbee --- /dev/null +++ b/srclib/apr/locks/win32/thread_rwlock.c @@ -0,0 +1,163 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "win32/apr_arch_thread_rwlock.h" +#include "apr_portable.h" + +static apr_status_t thread_rwlock_cleanup(void *data) +{ + return apr_thread_rwlock_destroy((apr_thread_rwlock_t *) data); +} + +APR_DECLARE(apr_status_t)apr_thread_rwlock_create(apr_thread_rwlock_t **rwlock, + apr_pool_t *pool) +{ + *rwlock = apr_palloc(pool, sizeof(**rwlock)); + + (*rwlock)->pool = pool; + (*rwlock)->readers = 0; + + if (! ((*rwlock)->read_event = CreateEvent(NULL, TRUE, FALSE, NULL))) { + *rwlock = NULL; + return apr_get_os_error(); + } + + if (! ((*rwlock)->write_mutex = CreateMutex(NULL, FALSE, NULL))) { + CloseHandle((*rwlock)->read_event); + *rwlock = NULL; + return apr_get_os_error(); + } + + apr_pool_cleanup_register(pool, *rwlock, thread_rwlock_cleanup, + apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +static apr_status_t apr_thread_rwlock_rdlock_core(apr_thread_rwlock_t *rwlock, + DWORD milliseconds) +{ + DWORD code = WaitForSingleObject(rwlock->write_mutex, milliseconds); + + if (code == WAIT_FAILED || code == WAIT_TIMEOUT) + return APR_FROM_OS_ERROR(code); + + /* We've successfully acquired the writer mutex, we can't be locked + * for write, so it's OK to add the reader lock. The writer mutex + * doubles as race condition protection for the readers counter. + */ + InterlockedIncrement(&rwlock->readers); + + if (! ResetEvent(rwlock->read_event)) + return apr_get_os_error(); + + if (! ReleaseMutex(rwlock->write_mutex)) + return apr_get_os_error(); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_rdlock(apr_thread_rwlock_t *rwlock) +{ + return apr_thread_rwlock_rdlock_core(rwlock, INFINITE); +} + +APR_DECLARE(apr_status_t) +apr_thread_rwlock_tryrdlock(apr_thread_rwlock_t *rwlock) +{ + return apr_thread_rwlock_rdlock_core(rwlock, 0); +} + +static apr_status_t +apr_thread_rwlock_wrlock_core(apr_thread_rwlock_t *rwlock, DWORD milliseconds) +{ + DWORD code = WaitForSingleObject(rwlock->write_mutex, milliseconds); + + if (code == WAIT_FAILED || code == WAIT_TIMEOUT) + return APR_FROM_OS_ERROR(code); + + /* We've got the writer lock but we have to wait for all readers to + * unlock before it's ok to use it. + */ + if (rwlock->readers) { + /* Must wait for readers to finish before returning, unless this + * is an trywrlock (milliseconds == 0): + */ + code = milliseconds + ? WaitForSingleObject(rwlock->read_event, milliseconds) + : WAIT_TIMEOUT; + + if (code == WAIT_FAILED || code == WAIT_TIMEOUT) { + /* Unable to wait for readers to finish, release write lock: */ + if (! ReleaseMutex(rwlock->write_mutex)) + return apr_get_os_error(); + + return APR_FROM_OS_ERROR(code); + } + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_wrlock(apr_thread_rwlock_t *rwlock) +{ + return apr_thread_rwlock_wrlock_core(rwlock, INFINITE); +} + +APR_DECLARE(apr_status_t)apr_thread_rwlock_trywrlock(apr_thread_rwlock_t *rwlock) +{ + return apr_thread_rwlock_wrlock_core(rwlock, 0); +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_unlock(apr_thread_rwlock_t *rwlock) +{ + apr_status_t rv = 0; + + /* First, guess that we're unlocking a writer */ + if (! ReleaseMutex(rwlock->write_mutex)) + rv = apr_get_os_error(); + + if (rv == APR_FROM_OS_ERROR(ERROR_NOT_OWNER)) { + /* Nope, we must have a read lock */ + if (rwlock->readers && + ! InterlockedDecrement(&rwlock->readers) && + ! SetEvent(rwlock->read_event)) { + rv = apr_get_os_error(); + } + else { + rv = 0; + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_rwlock_destroy(apr_thread_rwlock_t *rwlock) +{ + if (! CloseHandle(rwlock->read_event)) + return apr_get_os_error(); + + if (! CloseHandle(rwlock->write_mutex)) + return apr_get_os_error(); + + return APR_SUCCESS; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread_rwlock) diff --git a/srclib/apr/memory/unix/apr_pools.c b/srclib/apr/memory/unix/apr_pools.c new file mode 100644 index 0000000000..335516fd56 --- /dev/null +++ b/srclib/apr/memory/unix/apr_pools.c @@ -0,0 +1,2278 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" + +#include "apr_atomic.h" +#include "apr_portable.h" /* for get_os_proc */ +#include "apr_strings.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_allocator.h" +#include "apr_lib.h" +#include "apr_thread_mutex.h" +#include "apr_hash.h" +#include "apr_time.h" +#define APR_WANT_MEMFUNC +#include "apr_want.h" +#include "apr_env.h" + +#if APR_HAVE_STDLIB_H +#include /* for malloc, free and abort */ +#endif + +#if APR_HAVE_UNISTD_H +#include /* for getpid */ +#endif + + +/* + * Magic numbers + */ + +#define MIN_ALLOC 8192 +#define MAX_INDEX 20 + +#define BOUNDARY_INDEX 12 +#define BOUNDARY_SIZE (1 << BOUNDARY_INDEX) + +/* + * Timing constants for killing subprocesses + * There is a total 3-second delay between sending a SIGINT + * and sending of the final SIGKILL. + * TIMEOUT_INTERVAL should be set to TIMEOUT_USECS / 64 + * for the exponetial timeout alogrithm. + */ +#define TIMEOUT_USECS 3000000 +#define TIMEOUT_INTERVAL 46875 + +/* + * Allocator + */ + +struct apr_allocator_t { + apr_uint32_t max_index; + apr_uint32_t max_free_index; + apr_uint32_t current_free_index; +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; +#endif /* APR_HAS_THREADS */ + apr_pool_t *owner; + apr_memnode_t *free[MAX_INDEX]; +}; + +#define SIZEOF_ALLOCATOR_T APR_ALIGN_DEFAULT(sizeof(apr_allocator_t)) + + +/* + * Allocator + */ + +APR_DECLARE(apr_status_t) apr_allocator_create(apr_allocator_t **allocator) +{ + apr_allocator_t *new_allocator; + + *allocator = NULL; + + if ((new_allocator = malloc(SIZEOF_ALLOCATOR_T)) == NULL) + return APR_ENOMEM; + + memset(new_allocator, 0, SIZEOF_ALLOCATOR_T); + new_allocator->max_free_index = APR_ALLOCATOR_MAX_FREE_UNLIMITED; + + *allocator = new_allocator; + + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_allocator_destroy(apr_allocator_t *allocator) +{ + apr_uint32_t index; + apr_memnode_t *node, **ref; + + for (index = 0; index < MAX_INDEX; index++) { + ref = &allocator->free[index]; + while ((node = *ref) != NULL) { + *ref = node->next; + free(node); + } + } + + free(allocator); +} + +#if APR_HAS_THREADS +APR_DECLARE(void) apr_allocator_mutex_set(apr_allocator_t *allocator, + apr_thread_mutex_t *mutex) +{ + allocator->mutex = mutex; +} + +APR_DECLARE(apr_thread_mutex_t *) apr_allocator_mutex_get( + apr_allocator_t *allocator) +{ + return allocator->mutex; +} +#endif /* APR_HAS_THREADS */ + +APR_DECLARE(void) apr_allocator_owner_set(apr_allocator_t *allocator, + apr_pool_t *pool) +{ + allocator->owner = pool; +} + +APR_DECLARE(apr_pool_t *) apr_allocator_owner_get(apr_allocator_t *allocator) +{ + return allocator->owner; +} + +APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator, + apr_size_t in_size) +{ + apr_uint32_t max_free_index; + apr_uint32_t size = (APR_UINT32_TRUNC_CAST)in_size; + +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; + + mutex = apr_allocator_mutex_get(allocator); + if (mutex != NULL) + apr_thread_mutex_lock(mutex); +#endif /* APR_HAS_THREADS */ + + max_free_index = APR_ALIGN(size, BOUNDARY_SIZE) >> BOUNDARY_INDEX; + allocator->current_free_index += max_free_index; + allocator->current_free_index -= allocator->max_free_index; + allocator->max_free_index = max_free_index; + if (allocator->current_free_index > max_free_index) + allocator->current_free_index = max_free_index; + +#if APR_HAS_THREADS + if (mutex != NULL) + apr_thread_mutex_unlock(mutex); +#endif +} + +static APR_INLINE +apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) +{ + apr_memnode_t *node, **ref; + apr_uint32_t max_index; + apr_size_t i, index; + + /* Round up the block size to the next boundary, but always + * allocate at least a certain size (MIN_ALLOC). + */ + size = APR_ALIGN(size + APR_MEMNODE_T_SIZE, BOUNDARY_SIZE); + if (size < MIN_ALLOC) + size = MIN_ALLOC; + + /* Find the index for this node size by + * dividing its size by the boundary size + */ + index = (size >> BOUNDARY_INDEX) - 1; + + if (index > APR_UINT32_MAX) { + return NULL; + } + + /* First see if there are any nodes in the area we know + * our node will fit into. + */ + if (index <= allocator->max_index) { +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + /* Walk the free list to see if there are + * any nodes on it of the requested size + * + * NOTE: an optimization would be to check + * allocator->free[index] first and if no + * node is present, directly use + * allocator->free[max_index]. This seems + * like overkill though and could cause + * memory waste. + */ + max_index = allocator->max_index; + ref = &allocator->free[index]; + i = index; + while (*ref == NULL && i < max_index) { + ref++; + i++; + } + + if ((node = *ref) != NULL) { + /* If we have found a node and it doesn't have any + * nodes waiting in line behind it _and_ we are on + * the highest available index, find the new highest + * available index + */ + if ((*ref = node->next) == NULL && i >= max_index) { + do { + ref--; + max_index--; + } + while (*ref == NULL && max_index > 0); + + allocator->max_index = max_index; + } + + allocator->current_free_index += node->index; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + node->next = NULL; + node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; + + return node; + } + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + } + + /* If we found nothing, seek the sink (at index 0), if + * it is not empty. + */ + else if (allocator->free[0]) { +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + /* Walk the free list to see if there are + * any nodes on it of the requested size + */ + ref = &allocator->free[0]; + while ((node = *ref) != NULL && index > node->index) + ref = &node->next; + + if (node) { + *ref = node->next; + + allocator->current_free_index += node->index; + if (allocator->current_free_index > allocator->max_free_index) + allocator->current_free_index = allocator->max_free_index; + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + node->next = NULL; + node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; + + return node; + } + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + } + + /* If we haven't got a suitable node, malloc a new one + * and initialize it. + */ + if ((node = malloc(size)) == NULL) + return NULL; + + node->next = NULL; + node->index = (APR_UINT32_TRUNC_CAST)index; + node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; + node->endp = (char *)node + size; + + return node; +} + +static APR_INLINE +void allocator_free(apr_allocator_t *allocator, apr_memnode_t *node) +{ + apr_memnode_t *next, *freelist = NULL; + apr_uint32_t index, max_index; + apr_uint32_t max_free_index, current_free_index; + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_lock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + max_index = allocator->max_index; + max_free_index = allocator->max_free_index; + current_free_index = allocator->current_free_index; + + /* Walk the list of submitted nodes and free them one by one, + * shoving them in the right 'size' buckets as we go. + */ + do { + next = node->next; + index = node->index; + + if (max_free_index != APR_ALLOCATOR_MAX_FREE_UNLIMITED + && index > current_free_index) { + node->next = freelist; + freelist = node; + } + else if (index < MAX_INDEX) { + /* Add the node to the appropiate 'size' bucket. Adjust + * the max_index when appropiate. + */ + if ((node->next = allocator->free[index]) == NULL + && index > max_index) { + max_index = index; + } + allocator->free[index] = node; + current_free_index -= index; + } + else { + /* This node is too large to keep in a specific size bucket, + * just add it to the sink (at index 0). + */ + node->next = allocator->free[0]; + allocator->free[0] = node; + current_free_index -= index; + } + } while ((node = next) != NULL); + + allocator->max_index = max_index; + allocator->current_free_index = current_free_index; + +#if APR_HAS_THREADS + if (allocator->mutex) + apr_thread_mutex_unlock(allocator->mutex); +#endif /* APR_HAS_THREADS */ + + while (freelist != NULL) { + node = freelist; + freelist = node->next; + free(node); + } +} + +APR_DECLARE(apr_memnode_t *) apr_allocator_alloc(apr_allocator_t *allocator, + apr_size_t size) +{ + return allocator_alloc(allocator, size); +} + +APR_DECLARE(void) apr_allocator_free(apr_allocator_t *allocator, + apr_memnode_t *node) +{ + allocator_free(allocator, node); +} + + + +/* + * Debug level + */ + +#define APR_POOL_DEBUG_GENERAL 0x01 +#define APR_POOL_DEBUG_VERBOSE 0x02 +#define APR_POOL_DEBUG_LIFETIME 0x04 +#define APR_POOL_DEBUG_OWNER 0x08 +#define APR_POOL_DEBUG_VERBOSE_ALLOC 0x10 + +#define APR_POOL_DEBUG_VERBOSE_ALL (APR_POOL_DEBUG_VERBOSE \ + | APR_POOL_DEBUG_VERBOSE_ALLOC) + + +/* + * Structures + */ + +typedef struct cleanup_t cleanup_t; + +/** A list of processes */ +struct process_chain { + /** The process ID */ + apr_proc_t *proc; + apr_kill_conditions_e kill_how; + /** The next process in the list */ + struct process_chain *next; +}; + + +#if APR_POOL_DEBUG + +typedef struct debug_node_t debug_node_t; + +struct debug_node_t { + debug_node_t *next; + apr_uint32_t index; + void *beginp[64]; + void *endp[64]; +}; + +#define SIZEOF_DEBUG_NODE_T APR_ALIGN_DEFAULT(sizeof(debug_node_t)) + +#endif /* APR_POOL_DEBUG */ + +/* The ref field in the apr_pool_t struct holds a + * pointer to the pointer referencing this pool. + * It is used for parent, child, sibling management. + * Look at apr_pool_create_ex() and apr_pool_destroy() + * to see how it is used. + */ +struct apr_pool_t { + apr_pool_t *parent; + apr_pool_t *child; + apr_pool_t *sibling; + apr_pool_t **ref; + cleanup_t *cleanups; + cleanup_t *free_cleanups; + apr_allocator_t *allocator; + struct process_chain *subprocesses; + apr_abortfunc_t abort_fn; + apr_hash_t *user_data; + const char *tag; + +#if !APR_POOL_DEBUG + apr_memnode_t *active; + apr_memnode_t *self; /* The node containing the pool itself */ + char *self_first_avail; + +#else /* APR_POOL_DEBUG */ + apr_pool_t *joined; /* the caller has guaranteed that this pool + * will survive as long as ->joined */ + debug_node_t *nodes; + const char *file_line; + apr_uint32_t creation_flags; + unsigned int stat_alloc; + unsigned int stat_total_alloc; + unsigned int stat_clear; +#if APR_HAS_THREADS + apr_os_thread_t owner; + apr_thread_mutex_t *mutex; +#endif /* APR_HAS_THREADS */ +#endif /* APR_POOL_DEBUG */ +#ifdef NETWARE + apr_os_proc_t owner_proc; +#endif /* defined(NETWARE) */ +}; + +#define SIZEOF_POOL_T APR_ALIGN_DEFAULT(sizeof(apr_pool_t)) + + +/* + * Variables + */ + +static apr_byte_t apr_pools_initialized = 0; +static apr_pool_t *global_pool = NULL; + +#if !APR_POOL_DEBUG +static apr_allocator_t *global_allocator = NULL; +#endif /* !APR_POOL_DEBUG */ + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) +static apr_file_t *file_stderr = NULL; +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + +/* + * Local functions + */ + +static void run_cleanups(cleanup_t **c); +static void run_child_cleanups(cleanup_t **c); +static void free_proc_chain(struct process_chain *procs); + +#if APR_POOL_DEBUG +static void pool_destroy_debug(apr_pool_t *pool, const char *file_line); +#endif + +#if !APR_POOL_DEBUG +/* + * Initialization + */ + +APR_DECLARE(apr_status_t) apr_pool_initialize(void) +{ + apr_status_t rv; + + if (apr_pools_initialized++) + return APR_SUCCESS; + + if ((rv = apr_allocator_create(&global_allocator)) != APR_SUCCESS) { + apr_pools_initialized = 0; + return rv; + } + + if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL, + global_allocator)) != APR_SUCCESS) { + apr_allocator_destroy(global_allocator); + global_allocator = NULL; + apr_pools_initialized = 0; + return rv; + } + + apr_pool_tag(global_pool, "apr_global_pool"); + + /* This has to happen here because mutexes might be backed by + * atomics. It used to be snug and safe in apr_initialize(). + */ + if ((rv = apr_atomic_init(global_pool)) != APR_SUCCESS) { + return rv; + } + +#if APR_HAS_THREADS + { + apr_thread_mutex_t *mutex; + + if ((rv = apr_thread_mutex_create(&mutex, + APR_THREAD_MUTEX_DEFAULT, + global_pool)) != APR_SUCCESS) { + return rv; + } + + apr_allocator_mutex_set(global_allocator, mutex); + } +#endif /* APR_HAS_THREADS */ + + apr_allocator_owner_set(global_allocator, global_pool); + + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_pool_terminate(void) +{ + if (!apr_pools_initialized) + return; + + if (--apr_pools_initialized) + return; + + apr_pool_destroy(global_pool); /* This will also destroy the mutex */ + global_pool = NULL; + + global_allocator = NULL; +} + + +/* Node list management helper macros; list_insert() inserts 'node' + * before 'point'. */ +#define list_insert(node, point) do { \ + node->ref = point->ref; \ + *node->ref = node; \ + node->next = point; \ + point->ref = &node->next; \ +} while (0) + +/* list_remove() removes 'node' from its list. */ +#define list_remove(node) do { \ + *node->ref = node->next; \ + node->next->ref = node->ref; \ +} while (0) + +/* + * Memory allocation + */ + +APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size) +{ + apr_memnode_t *active, *node; + void *mem; + apr_size_t free_index; + + size = APR_ALIGN_DEFAULT(size); + active = pool->active; + + /* If the active node has enough bytes left, use it. */ + if (size < (apr_size_t)(active->endp - active->first_avail)) { + mem = active->first_avail; + active->first_avail += size; + + return mem; + } + + node = active->next; + if (size < (apr_size_t)(node->endp - node->first_avail)) { + list_remove(node); + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == NULL) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + } + + node->free_index = 0; + + mem = node->first_avail; + node->first_avail += size; + + list_insert(node, active); + + pool->active = node; + + free_index = (APR_ALIGN(active->endp - active->first_avail + 1, + BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; + + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; + node = active->next; + if (free_index >= node->free_index) + return mem; + + do { + node = node->next; + } + while (free_index < node->free_index); + + list_remove(active); + list_insert(active, node); + + return mem; +} + +/* Provide an implementation of apr_pcalloc for backward compatibility + * with code built before apr_pcalloc was a macro + */ + +#ifdef apr_pcalloc +#undef apr_pcalloc +#endif + +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size); +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size) +{ + void *mem; + + size = APR_ALIGN_DEFAULT(size); + if ((mem = apr_palloc(pool, size)) != NULL) { + memset(mem, 0, size); + } + + return mem; +} + + +/* + * Pool creation/destruction + */ + +APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) +{ + apr_memnode_t *active; + + /* Destroy the subpools. The subpools will detach themselves from + * this pool thus this loop is safe and easy. + */ + while (pool->child) + apr_pool_destroy(pool->child); + + /* Run cleanups */ + run_cleanups(&pool->cleanups); + pool->cleanups = NULL; + pool->free_cleanups = NULL; + + /* Free subprocesses */ + free_proc_chain(pool->subprocesses); + pool->subprocesses = NULL; + + /* Clear the user data. */ + pool->user_data = NULL; + + /* Find the node attached to the pool structure, reset it, make + * it the active node and free the rest of the nodes. + */ + active = pool->active = pool->self; + active->first_avail = pool->self_first_avail; + + if (active->next == active) + return; + + *active->ref = NULL; + allocator_free(pool->allocator, active->next); + active->next = active; + active->ref = &active->next; +} + +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) +{ + apr_memnode_t *active; + apr_allocator_t *allocator; + + /* Destroy the subpools. The subpools will detach themselve from + * this pool thus this loop is safe and easy. + */ + while (pool->child) + apr_pool_destroy(pool->child); + + /* Run cleanups */ + run_cleanups(&pool->cleanups); + + /* Free subprocesses */ + free_proc_chain(pool->subprocesses); + + /* Remove the pool from the parents child list */ + if (pool->parent) { +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(pool->parent->allocator)) != NULL) + apr_thread_mutex_lock(mutex); +#endif /* APR_HAS_THREADS */ + + if ((*pool->ref = pool->sibling) != NULL) + pool->sibling->ref = pool->ref; + +#if APR_HAS_THREADS + if (mutex) + apr_thread_mutex_unlock(mutex); +#endif /* APR_HAS_THREADS */ + } + + /* Find the block attached to the pool structure. Save a copy of the + * allocator pointer, because the pool struct soon will be no more. + */ + allocator = pool->allocator; + active = pool->self; + *active->ref = NULL; + +#if APR_HAS_THREADS + if (apr_allocator_owner_get(allocator) == pool) { + /* Make sure to remove the lock, since it is highly likely to + * be invalid now. + */ + apr_allocator_mutex_set(allocator, NULL); + } +#endif /* APR_HAS_THREADS */ + + /* Free all the nodes in the pool (including the node holding the + * pool struct), by giving them back to the allocator. + */ + allocator_free(allocator, active); + + /* If this pool happens to be the owner of the allocator, free + * everything in the allocator (that includes the pool struct + * and the allocator). Don't worry about destroying the optional mutex + * in the allocator, it will have been destroyed by the cleanup function. + */ + if (apr_allocator_owner_get(allocator) == pool) { + apr_allocator_destroy(allocator); + } +} + +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + apr_pool_t *pool; + apr_memnode_t *node; + + *newpool = NULL; + + if (!parent) + parent = global_pool; + + if (!abort_fn && parent) + abort_fn = parent->abort_fn; + + if (allocator == NULL) + allocator = parent->allocator; + + if ((node = allocator_alloc(allocator, + MIN_ALLOC - APR_MEMNODE_T_SIZE)) == NULL) { + if (abort_fn) + abort_fn(APR_ENOMEM); + + return APR_ENOMEM; + } + + node->next = node; + node->ref = &node->next; + + pool = (apr_pool_t *)node->first_avail; + node->first_avail = pool->self_first_avail = (char *)pool + SIZEOF_POOL_T; + + pool->allocator = allocator; + pool->active = pool->self = node; + pool->abort_fn = abort_fn; + pool->child = NULL; + pool->cleanups = NULL; + pool->free_cleanups = NULL; + pool->subprocesses = NULL; + pool->user_data = NULL; + pool->tag = NULL; + +#ifdef NETWARE + pool->owner_proc = (apr_os_proc_t)getnlmhandle(); +#endif /* defined(NETWARE) */ + + if ((pool->parent = parent) != NULL) { +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; + + if ((mutex = apr_allocator_mutex_get(parent->allocator)) != NULL) + apr_thread_mutex_lock(mutex); +#endif /* APR_HAS_THREADS */ + + if ((pool->sibling = parent->child) != NULL) + pool->sibling->ref = &pool->sibling; + + parent->child = pool; + pool->ref = &parent->child; + +#if APR_HAS_THREADS + if (mutex) + apr_thread_mutex_unlock(mutex); +#endif /* APR_HAS_THREADS */ + } + else { + pool->sibling = NULL; + pool->ref = NULL; + } + + *newpool = pool; + + return APR_SUCCESS; +} + + +/* + * "Print" functions + */ + +/* + * apr_psprintf is implemented by writing directly into the current + * block of the pool, starting right at first_avail. If there's + * insufficient room, then a new block is allocated and the earlier + * output is copied over. The new block isn't linked into the pool + * until all the output is done. + * + * Note that this is completely safe because nothing else can + * allocate in this apr_pool_t while apr_psprintf is running. alarms are + * blocked, and the only thing outside of apr_pools.c that's invoked + * is apr_vformatter -- which was purposefully written to be + * self-contained with no callouts. + */ + +struct psprintf_data { + apr_vformatter_buff_t vbuff; + apr_memnode_t *node; + apr_pool_t *pool; + apr_byte_t got_a_new_node; + apr_memnode_t *free; +}; + +#define APR_PSPRINTF_MIN_STRINGSIZE 32 + +static int psprintf_flush(apr_vformatter_buff_t *vbuff) +{ + struct psprintf_data *ps = (struct psprintf_data *)vbuff; + apr_memnode_t *node, *active; + apr_size_t cur_len, size; + char *strp; + apr_pool_t *pool; + apr_size_t free_index; + + pool = ps->pool; + active = ps->node; + strp = ps->vbuff.curpos; + cur_len = strp - active->first_avail; + size = cur_len << 1; + + /* Make sure that we don't try to use a block that has less + * than APR_PSPRINTF_MIN_STRINGSIZE bytes left in it. This + * also catches the case where size == 0, which would result + * in reusing a block that can't even hold the NUL byte. + */ + if (size < APR_PSPRINTF_MIN_STRINGSIZE) + size = APR_PSPRINTF_MIN_STRINGSIZE; + + node = active->next; + if (!ps->got_a_new_node + && size < (apr_size_t)(node->endp - node->first_avail)) { + + list_remove(node); + list_insert(node, active); + + node->free_index = 0; + + pool->active = node; + + free_index = (APR_ALIGN(active->endp - active->first_avail + 1, + BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; + + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; + node = active->next; + if (free_index < node->free_index) { + do { + node = node->next; + } + while (free_index < node->free_index); + + list_remove(active); + list_insert(active, node); + } + + node = pool->active; + } + else { + if ((node = allocator_alloc(pool->allocator, size)) == NULL) + return -1; + + if (ps->got_a_new_node) { + active->next = ps->free; + ps->free = active; + } + + ps->got_a_new_node = 1; + } + + memcpy(node->first_avail, active->first_avail, cur_len); + + ps->node = node; + ps->vbuff.curpos = node->first_avail + cur_len; + ps->vbuff.endpos = node->endp - 1; /* Save a byte for NUL terminator */ + + return 0; +} + +APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) +{ + struct psprintf_data ps; + char *strp; + apr_size_t size; + apr_memnode_t *active, *node; + apr_size_t free_index; + + ps.node = active = pool->active; + ps.pool = pool; + ps.vbuff.curpos = ps.node->first_avail; + + /* Save a byte for the NUL terminator */ + ps.vbuff.endpos = ps.node->endp - 1; + ps.got_a_new_node = 0; + ps.free = NULL; + + /* Make sure that the first node passed to apr_vformatter has at least + * room to hold the NUL terminator. + */ + if (ps.node->first_avail == ps.node->endp) { + if (psprintf_flush(&ps.vbuff) == -1) { + if (pool->abort_fn) { + pool->abort_fn(APR_ENOMEM); + } + + return NULL; + } + } + + if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + + strp = ps.vbuff.curpos; + *strp++ = '\0'; + + size = strp - ps.node->first_avail; + size = APR_ALIGN_DEFAULT(size); + strp = ps.node->first_avail; + ps.node->first_avail += size; + + if (ps.free) + allocator_free(pool->allocator, ps.free); + + /* + * Link the node in if it's a new one + */ + if (!ps.got_a_new_node) + return strp; + + active = pool->active; + node = ps.node; + + node->free_index = 0; + + list_insert(node, active); + + pool->active = node; + + free_index = (APR_ALIGN(active->endp - active->first_avail + 1, + BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; + + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; + node = active->next; + + if (free_index >= node->free_index) + return strp; + + do { + node = node->next; + } + while (free_index < node->free_index); + + list_remove(active); + list_insert(active, node); + + return strp; +} + + +#else /* APR_POOL_DEBUG */ +/* + * Debug helper functions + */ + + +/* + * Walk the pool tree rooted at pool, depth first. When fn returns + * anything other than 0, abort the traversal and return the value + * returned by fn. + */ +static int apr_pool_walk_tree(apr_pool_t *pool, + int (*fn)(apr_pool_t *pool, void *data), + void *data) +{ + int rv; + apr_pool_t *child; + + rv = fn(pool, data); + if (rv) + return rv; + +#if APR_HAS_THREADS + if (pool->mutex) { + apr_thread_mutex_lock(pool->mutex); + } +#endif /* APR_HAS_THREADS */ + + child = pool->child; + while (child) { + rv = apr_pool_walk_tree(child, fn, data); + if (rv) + break; + + child = child->sibling; + } + +#if APR_HAS_THREADS + if (pool->mutex) { + apr_thread_mutex_unlock(pool->mutex); + } +#endif /* APR_HAS_THREADS */ + + return rv; +} + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) +static void apr_pool_log_event(apr_pool_t *pool, const char *event, + const char *file_line, int deref) +{ + if (file_stderr) { + if (deref) { + apr_file_printf(file_stderr, + "POOL DEBUG: " + "[%lu" +#if APR_HAS_THREADS + "/%lu" +#endif /* APR_HAS_THREADS */ + "] " + "%7s " + "(%10lu/%10lu/%10lu) " + "0x%08X \"%s\" " + "<%s> " + "(%u/%u/%u) " + "\n", + (unsigned long)getpid(), +#if APR_HAS_THREADS + (unsigned long)apr_os_thread_current(), +#endif /* APR_HAS_THREADS */ + event, + (unsigned long)apr_pool_num_bytes(pool, 0), + (unsigned long)apr_pool_num_bytes(pool, 1), + (unsigned long)apr_pool_num_bytes(global_pool, 1), + (unsigned int)pool, pool->tag, + file_line, + pool->stat_alloc, pool->stat_total_alloc, pool->stat_clear); + } + else { + apr_file_printf(file_stderr, + "POOL DEBUG: " + "[%lu" +#if APR_HAS_THREADS + "/%lu" +#endif /* APR_HAS_THREADS */ + "] " + "%7s " + " " + "0x%08X " + "<%s> " + "\n", + (unsigned long)getpid(), +#if APR_HAS_THREADS + (unsigned long)apr_os_thread_current(), +#endif /* APR_HAS_THREADS */ + event, + (unsigned int)pool, + file_line); + } + } +} +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) +static int pool_is_child_of(apr_pool_t *parent, void *data) +{ + apr_pool_t *pool = (apr_pool_t *)data; + + return (pool == parent); +} + +static int apr_pool_is_child_of(apr_pool_t *pool, apr_pool_t *parent) +{ + if (parent == NULL) + return 0; + + return apr_pool_walk_tree(parent, pool_is_child_of, pool); +} +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */ + +static void apr_pool_check_integrity(apr_pool_t *pool) +{ + /* Rule of thumb: use of the global pool is always + * ok, since the only user is apr_pools.c. Unless + * people have searched for the top level parent and + * started to use that... + */ + if (pool == global_pool || global_pool == NULL) + return; + + /* Lifetime + * This basically checks to see if the pool being used is still + * a relative to the global pool. If not it was previously + * destroyed, in which case we abort(). + */ +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) + if (!apr_pool_is_child_of(pool, global_pool)) { +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + apr_pool_log_event(pool, "LIFE", + __FILE__ ":apr_pool_integrity check", 0); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + abort(); + } +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_LIFETIME) */ + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER) +#if APR_HAS_THREADS + if (!apr_os_thread_equal(pool->owner, apr_os_thread_current())) { +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + apr_pool_log_event(pool, "THREAD", + __FILE__ ":apr_pool_integrity check", 0); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + abort(); + } +#endif /* APR_HAS_THREADS */ +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_OWNER) */ +} + + +/* + * Initialization (debug) + */ + +APR_DECLARE(apr_status_t) apr_pool_initialize(void) +{ + apr_status_t rv; +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + char *logpath; +#endif + + if (apr_pools_initialized++) + return APR_SUCCESS; + + /* Since the debug code works a bit differently then the + * regular pools code, we ask for a lock here. The regular + * pools code has got this lock embedded in the global + * allocator, a concept unknown to debug mode. + */ + if ((rv = apr_pool_create_ex(&global_pool, NULL, NULL, + NULL)) != APR_SUCCESS) { + return rv; + } + + apr_pool_tag(global_pool, "APR global pool"); + + apr_pools_initialized = 1; + + /* This has to happen here because mutexes might be backed by + * atomics. It used to be snug and safe in apr_initialize(). + */ + if ((rv = apr_atomic_init(global_pool)) != APR_SUCCESS) { + return rv; + } + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + rv = apr_env_get(&logpath, "APR_POOL_DEBUG_LOG", global_pool); + + if (rv == APR_SUCCESS) { + apr_file_open(&file_stderr, logpath, APR_APPEND|APR_WRITE|APR_CREATE, + APR_OS_DEFAULT, global_pool); + } + else { + apr_file_open_stderr(&file_stderr, global_pool); + } + + if (file_stderr) { + apr_file_printf(file_stderr, + "POOL DEBUG: [PID" +#if APR_HAS_THREADS + "/TID" +#endif /* APR_HAS_THREADS */ + "] ACTION (SIZE /POOL SIZE /TOTAL SIZE) " + "POOL \"TAG\" <__FILE__:__LINE__> (ALLOCS/TOTAL ALLOCS/CLEARS)\n"); + + apr_pool_log_event(global_pool, "GLOBAL", __FILE__ ":apr_pool_initialize", 0); + } +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_pool_terminate(void) +{ + if (!apr_pools_initialized) + return; + + apr_pools_initialized = 0; + + apr_pool_destroy(global_pool); /* This will also destroy the mutex */ + global_pool = NULL; + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + file_stderr = NULL; +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ +} + + +/* + * Memory allocation (debug) + */ + +static void *pool_alloc(apr_pool_t *pool, apr_size_t size) +{ + debug_node_t *node; + void *mem; + + if ((mem = malloc(size)) == NULL) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + + node = pool->nodes; + if (node == NULL || node->index == 64) { + if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + + memset(node, 0, SIZEOF_DEBUG_NODE_T); + + node->next = pool->nodes; + pool->nodes = node; + node->index = 0; + } + + node->beginp[node->index] = mem; + node->endp[node->index] = (char *)mem + size; + node->index++; + + pool->stat_alloc++; + pool->stat_total_alloc++; + + return mem; +} + +APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + void *mem; + + apr_pool_check_integrity(pool); + + mem = pool_alloc(pool, size); + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) + apr_pool_log_event(pool, "PALLOC", file_line, 1); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) */ + + return mem; +} + +APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + void *mem; + + apr_pool_check_integrity(pool); + + mem = pool_alloc(pool, size); + memset(mem, 0, size); + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) + apr_pool_log_event(pool, "PCALLOC", file_line, 1); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALLOC) */ + + return mem; +} + + +/* + * Pool creation/destruction (debug) + */ + +static void pool_clear_debug(apr_pool_t *pool, const char *file_line) +{ + debug_node_t *node; + apr_uint32_t index; + + /* Destroy the subpools. The subpools will detach themselves from + * this pool thus this loop is safe and easy. + */ + while (pool->child) + pool_destroy_debug(pool->child, file_line); + + /* Run cleanups */ + run_cleanups(&pool->cleanups); + pool->free_cleanups = NULL; + pool->cleanups = NULL; + + /* If new child pools showed up, this is a reason to raise a flag */ + if (pool->child) + abort(); + + /* Free subprocesses */ + free_proc_chain(pool->subprocesses); + pool->subprocesses = NULL; + + /* Clear the user data. */ + pool->user_data = NULL; + + /* Free the blocks */ + while ((node = pool->nodes) != NULL) { + pool->nodes = node->next; + + for (index = 0; index < node->index; index++) + free(node->beginp[index]); + + free(node); + } + + pool->stat_alloc = 0; + pool->stat_clear++; +} + +APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *pool, + const char *file_line) +{ +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex = NULL; +#endif + + apr_pool_check_integrity(pool); + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) + apr_pool_log_event(pool, "CLEAR", file_line, 1); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */ + +#if APR_HAS_THREADS + if (pool->parent != NULL) + mutex = pool->parent->mutex; + + /* Lock the parent mutex before clearing so that if we have our + * own mutex it won't be accessed by apr_pool_walk_tree after + * it has been destroyed. + */ + if (mutex != NULL && mutex != pool->mutex) { + apr_thread_mutex_lock(mutex); + } +#endif + + pool_clear_debug(pool, file_line); + +#if APR_HAS_THREADS + /* If we had our own mutex, it will have been destroyed by + * the registered cleanups. Recreate the mutex. Unlock + * the mutex we obtained above. + */ + if (mutex != pool->mutex) { + (void)apr_thread_mutex_create(&pool->mutex, + APR_THREAD_MUTEX_NESTED, pool); + + if (mutex != NULL) + (void)apr_thread_mutex_unlock(mutex); + } +#endif /* APR_HAS_THREADS */ +} + +static void pool_destroy_debug(apr_pool_t *pool, const char *file_line) +{ + apr_pool_check_integrity(pool); + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) + apr_pool_log_event(pool, "DESTROY", file_line, 1); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */ + + pool_clear_debug(pool, file_line); + + /* Remove the pool from the parents child list */ + if (pool->parent) { +#if APR_HAS_THREADS + apr_thread_mutex_t *mutex; + + if ((mutex = pool->parent->mutex) != NULL) + apr_thread_mutex_lock(mutex); +#endif /* APR_HAS_THREADS */ + + if ((*pool->ref = pool->sibling) != NULL) + pool->sibling->ref = pool->ref; + +#if APR_HAS_THREADS + if (mutex) + apr_thread_mutex_unlock(mutex); +#endif /* APR_HAS_THREADS */ + } + + if (pool->allocator != NULL + && apr_allocator_owner_get(pool->allocator) == pool) { + apr_allocator_destroy(pool->allocator); + } + + /* Free the pool itself */ + free(pool); +} + +APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *pool, + const char *file_line) +{ + if (pool->joined) { + /* Joined pools must not be explicitly destroyed; the caller + * has broken the guarantee. */ +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) + apr_pool_log_event(pool, "LIFE", + __FILE__ ":apr_pool_destroy abort on joined", 0); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE_ALL) */ + + abort(); + } + pool_destroy_debug(pool, file_line); +} + +APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + apr_pool_t *pool; + + *newpool = NULL; + + if (!parent) { + parent = global_pool; + } + else { + apr_pool_check_integrity(parent); + + if (!allocator) + allocator = parent->allocator; + } + + if (!abort_fn && parent) + abort_fn = parent->abort_fn; + + if ((pool = malloc(SIZEOF_POOL_T)) == NULL) { + if (abort_fn) + abort_fn(APR_ENOMEM); + + return APR_ENOMEM; + } + + memset(pool, 0, SIZEOF_POOL_T); + + pool->allocator = allocator; + pool->abort_fn = abort_fn; + pool->tag = file_line; + pool->file_line = file_line; + + if ((pool->parent = parent) != NULL) { +#if APR_HAS_THREADS + if (parent->mutex) + apr_thread_mutex_lock(parent->mutex); +#endif /* APR_HAS_THREADS */ + if ((pool->sibling = parent->child) != NULL) + pool->sibling->ref = &pool->sibling; + + parent->child = pool; + pool->ref = &parent->child; + +#if APR_HAS_THREADS + if (parent->mutex) + apr_thread_mutex_unlock(parent->mutex); +#endif /* APR_HAS_THREADS */ + } + else { + pool->sibling = NULL; + pool->ref = NULL; + } + +#if APR_HAS_THREADS + pool->owner = apr_os_thread_current(); +#endif /* APR_HAS_THREADS */ +#ifdef NETWARE + pool->owner_proc = (apr_os_proc_t)getnlmhandle(); +#endif /* defined(NETWARE) */ + + + if (parent == NULL || parent->allocator != allocator) { +#if APR_HAS_THREADS + apr_status_t rv; + + /* No matter what the creation flags say, always create + * a lock. Without it integrity_check and apr_pool_num_bytes + * blow up (because they traverse pools child lists that + * possibly belong to another thread, in combination with + * the pool having no lock). However, this might actually + * hide problems like creating a child pool of a pool + * belonging to another thread. + */ + if ((rv = apr_thread_mutex_create(&pool->mutex, + APR_THREAD_MUTEX_NESTED, pool)) != APR_SUCCESS) { + free(pool); + return rv; + } +#endif /* APR_HAS_THREADS */ + } + else { +#if APR_HAS_THREADS + if (parent) + pool->mutex = parent->mutex; +#endif /* APR_HAS_THREADS */ + } + + *newpool = pool; + +#if (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) + apr_pool_log_event(pool, "CREATE", file_line, 1); +#endif /* (APR_POOL_DEBUG & APR_POOL_DEBUG_VERBOSE) */ + + return APR_SUCCESS; +} + + +/* + * "Print" functions (debug) + */ + +struct psprintf_data { + apr_vformatter_buff_t vbuff; + char *mem; + apr_size_t size; +}; + +static int psprintf_flush(apr_vformatter_buff_t *vbuff) +{ + struct psprintf_data *ps = (struct psprintf_data *)vbuff; + apr_size_t size; + + size = ps->vbuff.curpos - ps->mem; + + ps->size <<= 1; + if ((ps->mem = realloc(ps->mem, ps->size)) == NULL) + return -1; + + ps->vbuff.curpos = ps->mem + size; + ps->vbuff.endpos = ps->mem + ps->size - 1; + + return 0; +} + +APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) +{ + struct psprintf_data ps; + debug_node_t *node; + + apr_pool_check_integrity(pool); + + ps.size = 64; + ps.mem = malloc(ps.size); + ps.vbuff.curpos = ps.mem; + + /* Save a byte for the NUL terminator */ + ps.vbuff.endpos = ps.mem + ps.size - 1; + + if (apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap) == -1) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + + *ps.vbuff.curpos++ = '\0'; + + /* + * Link the node in + */ + node = pool->nodes; + if (node == NULL || node->index == 64) { + if ((node = malloc(SIZEOF_DEBUG_NODE_T)) == NULL) { + if (pool->abort_fn) + pool->abort_fn(APR_ENOMEM); + + return NULL; + } + + node->next = pool->nodes; + pool->nodes = node; + node->index = 0; + } + + node->beginp[node->index] = ps.mem; + node->endp[node->index] = ps.mem + ps.size; + node->index++; + + return ps.mem; +} + + +/* + * Debug functions + */ + +APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub) +{ +#if APR_POOL_DEBUG + if (sub->parent != p) { + abort(); + } + sub->joined = p; +#endif +} + +static int pool_find(apr_pool_t *pool, void *data) +{ + void **pmem = (void **)data; + debug_node_t *node; + apr_uint32_t index; + + node = pool->nodes; + + while (node) { + for (index = 0; index < node->index; index++) { + if (node->beginp[index] <= *pmem + && node->endp[index] > *pmem) { + *pmem = pool; + return 1; + } + } + + node = node->next; + } + + return 0; +} + +APR_DECLARE(apr_pool_t *) apr_pool_find(const void *mem) +{ + void *pool = (void *)mem; + + if (apr_pool_walk_tree(global_pool, pool_find, &pool)) + return pool; + + return NULL; +} + +static int pool_num_bytes(apr_pool_t *pool, void *data) +{ + apr_size_t *psize = (apr_size_t *)data; + debug_node_t *node; + apr_uint32_t index; + + node = pool->nodes; + + while (node) { + for (index = 0; index < node->index; index++) { + *psize += (char *)node->endp[index] - (char *)node->beginp[index]; + } + + node = node->next; + } + + return 0; +} + +APR_DECLARE(apr_size_t) apr_pool_num_bytes(apr_pool_t *pool, int recurse) +{ + apr_size_t size = 0; + + if (!recurse) { + pool_num_bytes(pool, &size); + + return size; + } + + apr_pool_walk_tree(pool, pool_num_bytes, &size); + + return size; +} + +APR_DECLARE(void) apr_pool_lock(apr_pool_t *pool, int flag) +{ +} + +#endif /* !APR_POOL_DEBUG */ + +#ifdef NETWARE +void netware_pool_proc_cleanup () +{ + apr_pool_t *pool = global_pool->child; + apr_os_proc_t owner_proc = (apr_os_proc_t)getnlmhandle(); + + while (pool) { + if (pool->owner_proc == owner_proc) { + apr_pool_destroy (pool); + pool = global_pool->child; + } + else { + pool = pool->sibling; + } + } + return; +} +#endif /* defined(NETWARE) */ + + +/* + * "Print" functions (common) + */ + +APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...) +{ + va_list ap; + char *res; + + va_start(ap, fmt); + res = apr_pvsprintf(p, fmt, ap); + va_end(ap); + return res; +} + +/* + * Pool Properties + */ + +APR_DECLARE(void) apr_pool_abort_set(apr_abortfunc_t abort_fn, + apr_pool_t *pool) +{ + pool->abort_fn = abort_fn; +} + +APR_DECLARE(apr_abortfunc_t) apr_pool_abort_get(apr_pool_t *pool) +{ + return pool->abort_fn; +} + +APR_DECLARE(apr_pool_t *) apr_pool_parent_get(apr_pool_t *pool) +{ +#ifdef NETWARE + /* On NetWare, don't return the global_pool, return the application pool + as the top most pool */ + if (pool->parent == global_pool) + return NULL; + else +#endif + return pool->parent; +} + +APR_DECLARE(apr_allocator_t *) apr_pool_allocator_get(apr_pool_t *pool) +{ + return pool->allocator; +} + +/* return TRUE if a is an ancestor of b + * NULL is considered an ancestor of all pools + */ +APR_DECLARE(int) apr_pool_is_ancestor(apr_pool_t *a, apr_pool_t *b) +{ + if (a == NULL) + return 1; + +#if APR_POOL_DEBUG + /* Find the pool with the longest lifetime guaranteed by the + * caller: */ + while (a->joined) { + a = a->joined; + } +#endif + + while (b) { + if (a == b) + return 1; + + b = b->parent; + } + + return 0; +} + +APR_DECLARE(void) apr_pool_tag(apr_pool_t *pool, const char *tag) +{ + pool->tag = tag; +} + + +/* + * User data management + */ + +APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_pool_t *pool) +{ +#if APR_POOL_DEBUG + apr_pool_check_integrity(pool); +#endif /* APR_POOL_DEBUG */ + + if (pool->user_data == NULL) + pool->user_data = apr_hash_make(pool); + + if (apr_hash_get(pool->user_data, key, APR_HASH_KEY_STRING) == NULL) { + char *new_key = apr_pstrdup(pool, key); + apr_hash_set(pool->user_data, new_key, APR_HASH_KEY_STRING, data); + } + else { + apr_hash_set(pool->user_data, key, APR_HASH_KEY_STRING, data); + } + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pool_userdata_setn(const void *data, + const char *key, + apr_status_t (*cleanup)(void *), + apr_pool_t *pool) +{ +#if APR_POOL_DEBUG + apr_pool_check_integrity(pool); +#endif /* APR_POOL_DEBUG */ + + if (pool->user_data == NULL) + pool->user_data = apr_hash_make(pool); + + apr_hash_set(pool->user_data, key, APR_HASH_KEY_STRING, data); + + if (cleanup) + apr_pool_cleanup_register(pool, data, cleanup, cleanup); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key, + apr_pool_t *pool) +{ +#if APR_POOL_DEBUG + apr_pool_check_integrity(pool); +#endif /* APR_POOL_DEBUG */ + + if (pool->user_data == NULL) { + *data = NULL; + } + else { + *data = apr_hash_get(pool->user_data, key, APR_HASH_KEY_STRING); + } + + return APR_SUCCESS; +} + + +/* + * Cleanup + */ + +struct cleanup_t { + struct cleanup_t *next; + const void *data; + apr_status_t (*plain_cleanup_fn)(void *data); + apr_status_t (*child_cleanup_fn)(void *data); +}; + +APR_DECLARE(void) apr_pool_cleanup_register(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *data), + apr_status_t (*child_cleanup_fn)(void *data)) +{ + cleanup_t *c; + +#if APR_POOL_DEBUG + apr_pool_check_integrity(p); +#endif /* APR_POOL_DEBUG */ + + if (p != NULL) { + if (p->free_cleanups) { + /* reuse a cleanup structure */ + c = p->free_cleanups; + p->free_cleanups = c->next; + } else { + c = apr_palloc(p, sizeof(cleanup_t)); + } + c->data = data; + c->plain_cleanup_fn = plain_cleanup_fn; + c->child_cleanup_fn = child_cleanup_fn; + c->next = p->cleanups; + p->cleanups = c; + } +} + +APR_DECLARE(void) apr_pool_cleanup_kill(apr_pool_t *p, const void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + cleanup_t *c, **lastp; + +#if APR_POOL_DEBUG + apr_pool_check_integrity(p); +#endif /* APR_POOL_DEBUG */ + + if (p == NULL) + return; + + c = p->cleanups; + lastp = &p->cleanups; + while (c) { + if (c->data == data && c->plain_cleanup_fn == cleanup_fn) { + *lastp = c->next; + /* move to freelist */ + c->next = p->free_cleanups; + p->free_cleanups = c; + break; + } + + lastp = &c->next; + c = c->next; + } +} + +APR_DECLARE(void) apr_pool_child_cleanup_set(apr_pool_t *p, const void *data, + apr_status_t (*plain_cleanup_fn)(void *), + apr_status_t (*child_cleanup_fn)(void *)) +{ + cleanup_t *c; + +#if APR_POOL_DEBUG + apr_pool_check_integrity(p); +#endif /* APR_POOL_DEBUG */ + + if (p == NULL) + return; + + c = p->cleanups; + while (c) { + if (c->data == data && c->plain_cleanup_fn == plain_cleanup_fn) { + c->child_cleanup_fn = child_cleanup_fn; + break; + } + + c = c->next; + } +} + +APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data, + apr_status_t (*cleanup_fn)(void *)) +{ + apr_pool_cleanup_kill(p, data, cleanup_fn); + return (*cleanup_fn)(data); +} + +static void run_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->plain_cleanup_fn)((void *)c->data); + c = *cref; + } +} + +static void run_child_cleanups(cleanup_t **cref) +{ + cleanup_t *c = *cref; + + while (c) { + *cref = c->next; + (*c->child_cleanup_fn)((void *)c->data); + c = *cref; + } +} + +static void cleanup_pool_for_exec(apr_pool_t *p) +{ + run_child_cleanups(&p->cleanups); + + for (p = p->child; p; p = p->sibling) + cleanup_pool_for_exec(p); +} + +APR_DECLARE(void) apr_pool_cleanup_for_exec(void) +{ +#if !defined(WIN32) && !defined(OS2) + /* + * Don't need to do anything on NT or OS/2, because I + * am actually going to spawn the new process - not + * exec it. All handles that are not inheritable, will + * be automajically closed. The only problem is with + * file handles that are open, but there isn't much + * I can do about that (except if the child decides + * to go out and close them + */ + cleanup_pool_for_exec(global_pool); +#endif /* !defined(WIN32) && !defined(OS2) */ +} + +APR_DECLARE_NONSTD(apr_status_t) apr_pool_cleanup_null(void *data) +{ + /* do nothing cleanup routine */ + return APR_SUCCESS; +} + +/* Subprocesses don't use the generic cleanup interface because + * we don't want multiple subprocesses to result in multiple + * three-second pauses; the subprocesses have to be "freed" all + * at once. If other resources are introduced with the same property, + * we might want to fold support for that into the generic interface. + * For now, it's a special case. + */ +APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *pool, apr_proc_t *proc, + apr_kill_conditions_e how) +{ + struct process_chain *pc = apr_palloc(pool, sizeof(struct process_chain)); + + pc->proc = proc; + pc->kill_how = how; + pc->next = pool->subprocesses; + pool->subprocesses = pc; +} + +static void free_proc_chain(struct process_chain *procs) +{ + /* Dispose of the subprocesses we've spawned off in the course of + * whatever it was we're cleaning up now. This may involve killing + * some of them off... + */ + struct process_chain *pc; + int need_timeout = 0; + apr_time_t timeout_interval; + + if (!procs) + return; /* No work. Whew! */ + + /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL + * dance with any of the processes we're cleaning up. If we've got + * any kill-on-sight subprocesses, ditch them now as well, so they + * don't waste any more cycles doing whatever it is that they shouldn't + * be doing anymore. + */ + +#ifndef NEED_WAITPID + /* Pick up all defunct processes */ + for (pc = procs; pc; pc = pc->next) { + if (apr_proc_wait(pc->proc, NULL, NULL, APR_NOWAIT) != APR_CHILD_NOTDONE) + pc->kill_how = APR_KILL_NEVER; + } +#endif /* !defined(NEED_WAITPID) */ + + for (pc = procs; pc; pc = pc->next) { +#ifndef WIN32 + if ((pc->kill_how == APR_KILL_AFTER_TIMEOUT) + || (pc->kill_how == APR_KILL_ONLY_ONCE)) { + /* + * Subprocess may be dead already. Only need the timeout if not. + * Note: apr_proc_kill on Windows is TerminateProcess(), which is + * similar to a SIGKILL, so always give the process a timeout + * under Windows before killing it. + */ + if (apr_proc_kill(pc->proc, SIGTERM) == APR_SUCCESS) + need_timeout = 1; + } + else if (pc->kill_how == APR_KILL_ALWAYS) { +#else /* WIN32 knows only one fast, clean method of killing processes today */ + if (pc->kill_how != APR_KILL_NEVER) { + need_timeout = 1; + pc->kill_how = APR_KILL_ALWAYS; +#endif + apr_proc_kill(pc->proc, SIGKILL); + } + } + + /* Sleep only if we have to. The sleep algorithm grows + * by a factor of two on each iteration. TIMEOUT_INTERVAL + * is equal to TIMEOUT_USECS / 64. + */ + if (need_timeout) { + timeout_interval = TIMEOUT_INTERVAL; + apr_sleep(timeout_interval); + + do { + /* check the status of the subprocesses */ + need_timeout = 0; + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) { + if (apr_proc_wait(pc->proc, NULL, NULL, APR_NOWAIT) + == APR_CHILD_NOTDONE) + need_timeout = 1; /* subprocess is still active */ + else + pc->kill_how = APR_KILL_NEVER; /* subprocess has exited */ + } + } + if (need_timeout) { + if (timeout_interval >= TIMEOUT_USECS) { + break; + } + apr_sleep(timeout_interval); + timeout_interval *= 2; + } + } while (need_timeout); + } + + /* OK, the scripts we just timed out for have had a chance to clean up + * --- now, just get rid of them, and also clean up the system accounting + * goop... + */ + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how == APR_KILL_AFTER_TIMEOUT) + apr_proc_kill(pc->proc, SIGKILL); + } + + /* Now wait for all the signaled processes to die */ + for (pc = procs; pc; pc = pc->next) { + if (pc->kill_how != APR_KILL_NEVER) + (void)apr_proc_wait(pc->proc, NULL, NULL, APR_WAIT); + } +} + + +/* + * Pool creation/destruction stubs, for people who are running + * mixed release/debug enviroments. + */ + +#if !APR_POOL_DEBUG +APR_DECLARE(void *) apr_palloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_palloc(pool, size); +} + +APR_DECLARE(void *) apr_pcalloc_debug(apr_pool_t *pool, apr_size_t size, + const char *file_line) +{ + return apr_pcalloc(pool, size); +} + +APR_DECLARE(void) apr_pool_clear_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_clear(pool); +} + +APR_DECLARE(void) apr_pool_destroy_debug(apr_pool_t *pool, + const char *file_line) +{ + apr_pool_destroy(pool); +} + +APR_DECLARE(apr_status_t) apr_pool_create_ex_debug(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator, + const char *file_line) +{ + return apr_pool_create_ex(newpool, parent, abort_fn, allocator); +} + +#else /* APR_POOL_DEBUG */ + +#undef apr_palloc +APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size); + +APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size) +{ + return apr_palloc_debug(pool, size, "undefined"); +} + +#undef apr_pcalloc +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size); + +APR_DECLARE(void *) apr_pcalloc(apr_pool_t *pool, apr_size_t size) +{ + return apr_pcalloc_debug(pool, size, "undefined"); +} + +#undef apr_pool_clear +APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool); + +APR_DECLARE(void) apr_pool_clear(apr_pool_t *pool) +{ + apr_pool_clear_debug(pool, "undefined"); +} + +#undef apr_pool_destroy +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool); + +APR_DECLARE(void) apr_pool_destroy(apr_pool_t *pool) +{ + apr_pool_destroy_debug(pool, "undefined"); +} + +#undef apr_pool_create_ex +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator); + +APR_DECLARE(apr_status_t) apr_pool_create_ex(apr_pool_t **newpool, + apr_pool_t *parent, + apr_abortfunc_t abort_fn, + apr_allocator_t *allocator) +{ + return apr_pool_create_ex_debug(newpool, parent, + abort_fn, allocator, + "undefined"); +} + +#endif /* APR_POOL_DEBUG */ diff --git a/srclib/apr/misc/netware/apr.xdc b/srclib/apr/misc/netware/apr.xdc new file mode 100644 index 0000000000000000000000000000000000000000..12a7f6ba2df41eccb047c2884088c022f9395540 GIT binary patch literal 128 zcmZ>Aba!K7U|?VbVr&2;2Lb{>% +#include +#include +#ifdef USE_WINSOCK +#include "novsock2.h" +#endif + +#include "apr_pools.h" +#include "apr_private.h" + + +/* library-private data...*/ +int gLibId = -1; +void *gLibHandle = (void *) NULL; +NXMutex_t *gLibLock = (NXMutex_t *) NULL; + +/* internal library function prototypes...*/ +int DisposeLibraryData(void *); + +int _NonAppStart +( + void *NLMHandle, + void *errorScreen, + const char *cmdLine, + const char *loadDirPath, + size_t uninitializedDataLength, + void *NLMFileHandle, + int (*readRoutineP)( int conn, void *fileHandle, size_t offset, + size_t nbytes, size_t *bytesRead, void *buffer ), + size_t customDataOffset, + size_t customDataSize, + int messageCount, + const char **messages +) +{ +#ifdef USE_WINSOCK + WSADATA wsaData; +#endif + apr_status_t status; + + NX_LOCK_INFO_ALLOC(liblock, "Per-Application Data Lock", 0); + +#pragma unused(cmdLine) +#pragma unused(loadDirPath) +#pragma unused(uninitializedDataLength) +#pragma unused(NLMFileHandle) +#pragma unused(readRoutineP) +#pragma unused(customDataOffset) +#pragma unused(customDataSize) +#pragma unused(messageCount) +#pragma unused(messages) + + gLibId = register_library(DisposeLibraryData); + + if (gLibId < -1) + { + OutputToScreen(errorScreen, "Unable to register library with kernel.\n"); + return -1; + } + + gLibHandle = NLMHandle; + + gLibLock = NXMutexAlloc(0, 0, &liblock); + + if (!gLibLock) + { + OutputToScreen(errorScreen, "Unable to allocate library data lock.\n"); + return -1; + } + + apr_netware_setup_time(); + + if ((status = apr_pool_initialize()) != APR_SUCCESS) + return status; + +#ifdef USE_WINSOCK + return WSAStartup((WORD) MAKEWORD(2, 0), &wsaData); +#else + return 0; +#endif +} + +void _NonAppStop( void ) +{ + apr_pool_terminate(); + +#ifdef USE_WINSOCK + WSACleanup(); +#endif + + unregister_library(gLibId); + NXMutexFree(gLibLock); +} + +int _NonAppCheckUnload( void ) +{ + return 0; +} + +int register_NLM(void *NLMHandle) +{ + APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId); + + NXLock(gLibLock); + if (!app_data) { + app_data = (APP_DATA*)library_malloc(gLibHandle, sizeof(APP_DATA)); + + if (app_data) { + memset (app_data, 0, sizeof(APP_DATA)); + set_app_data(gLibId, app_data); + app_data->gs_nlmhandle = NLMHandle; + } + } + + if (app_data && (!app_data->initialized)) { + app_data->initialized = 1; + NXUnlock(gLibLock); + return 0; + } + + NXUnlock(gLibLock); + return 1; +} + +int unregister_NLM(void *NLMHandle) +{ + APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId); + + NXLock(gLibLock); + if (app_data) { + app_data->initialized = 0; + NXUnlock(gLibLock); + return 0; + } + NXUnlock(gLibLock); + return 1; +} + +int DisposeLibraryData(void *data) +{ + if (data) + { + library_free(data); + } + + return 0; +} + +int setGlobalPool(void *data) +{ + APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId); + + NXLock(gLibLock); + + if (app_data && !app_data->gPool) { + app_data->gPool = data; + } + + NXUnlock(gLibLock); + return 1; +} + +void* getGlobalPool() +{ + APP_DATA *app_data = (APP_DATA*) get_app_data(gLibId); + + if (app_data) { + return app_data->gPool; + } + + return NULL; +} + diff --git a/srclib/apr/misc/netware/rand.c b/srclib/apr/misc/netware/rand.c new file mode 100644 index 0000000000..8dd89dace2 --- /dev/null +++ b/srclib/apr/misc/netware/rand.c @@ -0,0 +1,70 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define APR_WANT_MEMFUNC +#include "apr_want.h" +#include "apr_general.h" +#include "apr_private.h" + +#if APR_HAS_RANDOM + +#include + +static int NXSeedRandomInternal( size_t width, void *seed ) +{ + static int init = 0; + int *s = (int *) seed; + union { int x; char y[4]; } u; + + if (!init) { + srand(NXGetSystemTick()); + init = 1; + } + + if (width > 3) + { + do + { + *s++ = rand(); + } + while ((width -= 4) > 3); + } + + if (width > 0) + { + char *p = (char *) s; + + u.x = rand(); + + while (width > 0) + *p++ = u.y[width--]; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, + apr_size_t length) +{ + if (NXSeedRandom(length, buf) != 0) { + return NXSeedRandomInternal (length, buf); + } + return APR_SUCCESS; +} + + + +#endif /* APR_HAS_RANDOM */ diff --git a/srclib/apr/misc/netware/start.c b/srclib/apr/misc/netware/start.c new file mode 100644 index 0000000000..2cbfe9bfce --- /dev/null +++ b/srclib/apr/misc/netware/start.c @@ -0,0 +1,188 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_signal.h" + +#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */ +#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */ +#include "apr_arch_internal_time.h" + +#ifdef USE_WINSOCK +/* +** Resource tag signatures for using NetWare WinSock 2. These will no longer +** be needed by anyone once the new WSAStartupWithNlmHandle() is available +** since WinSock will make the calls to AllocateResourceTag(). +*/ +#define WS_LOAD_ENTRY_SIGNATURE (*(unsigned long *) "WLDE") +#define WS_SKT_SIGNATURE (*(unsigned long *) "WSKT") +#define WS_LOOKUP_SERVICE_SIGNATURE (*(unsigned long *) "WLUP") +#define WS_WSAEVENT_SIGNATURE (*(unsigned long *) "WEVT") +#define WS_CPORT_SIGNATURE (*(unsigned long *) "WCPT") + + +int (*WSAStartupWithNLMHandle)( WORD version, LPWSADATA data, void *handle ) = NULL; +int (*WSACleanupWithNLMHandle)( void *handle ) = NULL; + +static int wsa_startup_with_handle (WORD wVersionRequested, LPWSADATA data, void *handle) +{ + APP_DATA *app_data; + + if (!(app_data = (APP_DATA*) get_app_data(gLibId))) + return APR_EGENERAL; + + app_data->gs_startup_rtag = AllocateResourceTag(handle, "WinSock Start-up", WS_LOAD_ENTRY_SIGNATURE); + app_data->gs_socket_rtag = AllocateResourceTag(handle, "WinSock socket()", WS_SKT_SIGNATURE); + app_data->gs_lookup_rtag = AllocateResourceTag(handle, "WinSock Look-up", WS_LOOKUP_SERVICE_SIGNATURE); + app_data->gs_event_rtag = AllocateResourceTag(handle, "WinSock Event", WS_WSAEVENT_SIGNATURE); + app_data->gs_pcp_rtag = AllocateResourceTag(handle, "WinSock C-Port", WS_CPORT_SIGNATURE); + + return WSAStartupRTags(wVersionRequested, data, + app_data->gs_startup_rtag, + app_data->gs_socket_rtag, + app_data->gs_lookup_rtag, + app_data->gs_event_rtag, + app_data->gs_pcp_rtag); +} + +static int wsa_cleanup_with_handle (void *handle) +{ + APP_DATA *app_data; + + if (!(app_data = (APP_DATA*) get_app_data(gLibId))) + return APR_EGENERAL; + + return WSACleanupRTag(app_data->gs_startup_rtag); +} + +static int UnregisterAppWithWinSock (void *nlm_handle) +{ + if (!WSACleanupWithNLMHandle) + { + if (!(WSACleanupWithNLMHandle = ImportPublicObject(gLibHandle, "WSACleanupWithNLMHandle"))) + WSACleanupWithNLMHandle = wsa_cleanup_with_handle; + } + + return (*WSACleanupWithNLMHandle)(nlm_handle); +} + +static int RegisterAppWithWinSock (void *nlm_handle) +{ + int err; + WSADATA wsaData; + WORD wVersionRequested = MAKEWORD(WSAHighByte, WSALowByte); + + if (!WSAStartupWithNLMHandle) + { + if (!(WSAStartupWithNLMHandle = ImportPublicObject(gLibHandle, "WSAStartupWithNLMHandle"))) + WSAStartupWithNLMHandle = wsa_startup_with_handle; + } + + err = (*WSAStartupWithNLMHandle)(wVersionRequested, &wsaData, nlm_handle); + + if (LOBYTE(wsaData.wVersion) != WSAHighByte || + HIBYTE(wsaData.wVersion) != WSALowByte) { + + UnregisterAppWithWinSock (nlm_handle); + return APR_EEXIST; + } + + return err; +} +#endif + + + +APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + const char * const * *argv, + const char * const * *env) +{ + /* An absolute noop. At present, only Win32 requires this stub, but it's + * required in order to move command arguments passed through the service + * control manager into the process, and it's required to fix the char* + * data passed in from win32 unicode into utf-8, win32's apr internal fmt. + */ + return apr_initialize(); +} + +APR_DECLARE(apr_status_t) apr_initialize(void) +{ + apr_pool_t *pool; + int err; + void *nlmhandle = getnlmhandle(); + + /* Register the NLM as using APR. If it is already + registered then just return. */ + if (register_NLM(nlmhandle) != 0) { + return APR_SUCCESS; + } + + /* apr_pool_initialize() is being called from the library + startup code since all of the memory resources belong + to the library rather than the application. */ + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { + return APR_ENOPOOL; + } + + apr_pool_tag(pool, "apr_initilialize"); + +#ifdef USE_WINSOCK + err = RegisterAppWithWinSock (nlmhandle); + + if (err) { + return err; + } +#endif + + apr_signal_init(pool); + + return APR_SUCCESS; +} + +APR_DECLARE_NONSTD(void) apr_terminate(void) +{ + APP_DATA *app_data; + + /* Get our instance data for shutting down. */ + if (!(app_data = (APP_DATA*) get_app_data(gLibId))) + return; + + /* Unregister the NLM. If it is not registered + then just return. */ + if (unregister_NLM(app_data->gs_nlmhandle) != 0) { + return; + } + + /* apr_pool_terminate() is being called from the + library shutdown code since the memory resources + belong to the library rather than the application */ + + /* Just clean up the memory for the app that is going + away. */ + netware_pool_proc_cleanup (); + +#ifdef USE_WINSOCK + UnregisterAppWithWinSock (app_data->gs_nlmhandle); +#endif +} + +APR_DECLARE(void) apr_terminate2(void) +{ + apr_terminate(); +} diff --git a/srclib/apr/misc/unix/charset.c b/srclib/apr/misc/unix/charset.c new file mode 100644 index 0000000000..8a4b897413 --- /dev/null +++ b/srclib/apr/misc/unix/charset.c @@ -0,0 +1,83 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#ifdef HAVE_LANGINFO_H +#include +#endif + +/* + * simple heuristic to determine codepage of source code so that + * literal strings (e.g., "GET /\r\n") in source code can be translated + * properly + * + * If appropriate, a symbol can be set at configure time to determine + * this. On EBCDIC platforms, it will be important how the code was + * unpacked. + */ + +APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool) +{ +#ifdef __MVS__ +# ifdef __CODESET__ + return __CODESET__; +# else + return "IBM-1047"; +# endif +#endif + + if ('}' == 0xD0) { + return "IBM-1047"; + } + + if ('{' == 0xFB) { + return "EDF04"; + } + + if ('A' == 0xC1) { + return "EBCDIC"; /* not useful */ + } + + if ('A' == 0x41) { + return "ISO-8859-1"; /* not necessarily true */ + } + + return "unknown"; +} + + +APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool) +{ +#if defined(HAVE_NL_LANGINFO) && defined(CODESET) + const char *charset; + + charset = nl_langinfo(CODESET); + if (charset && *charset) { +#ifdef _OSD_POSIX /* Bug workaround - delete as soon as fixed in OSD_POSIX */ + /* Some versions of OSD_POSIX return nl_langinfo(CODESET)="^[nN]" */ + /* Ignore the bogus information and use apr_os_default_encoding() */ + if (charset[0] != '^') +#endif + return charset; + } +#endif + + return apr_os_default_encoding(pool); +} diff --git a/srclib/apr/misc/unix/env.c b/srclib/apr/misc/unix/env.c new file mode 100644 index 0000000000..4b95c5d9be --- /dev/null +++ b/srclib/apr/misc/unix/env.c @@ -0,0 +1,97 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr.h" +#include "apr_private.h" +#include "apr_env.h" + +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include +#endif + +APR_DECLARE(apr_status_t) apr_env_get(char **value, + const char *envvar, + apr_pool_t *pool) +{ +#ifdef HAVE_GETENV + + char *val = getenv(envvar); + if (!val) + return APR_ENOENT; + *value = val; + return APR_SUCCESS; + +#else + return APR_ENOTIMPL; +#endif +} + + +APR_DECLARE(apr_status_t) apr_env_set(const char *envvar, + const char *value, + apr_pool_t *pool) +{ +#if defined(HAVE_SETENV) + + if (0 > setenv(envvar, value, 1)) + return APR_ENOMEM; + return APR_SUCCESS; + +#elif defined(HAVE_PUTENV) + + apr_size_t elen = strlen(envvar); + apr_size_t vlen = strlen(value); + char *env = apr_palloc(pool, elen + vlen + 2); + char *p = env + elen; + + memcpy(env, envvar, elen); + *p++ = '='; + memcpy(p, value, vlen); + p[vlen] = '\0'; + + if (0 > putenv(env)) + return APR_ENOMEM; + return APR_SUCCESS; + +#else + return APR_ENOTIMPL; +#endif +} + + +APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool) +{ +#ifdef HAVE_UNSETENV + + unsetenv(envvar); + return APR_SUCCESS; + +#else + /* hint: some platforms allow envvars to be unset via + * putenv("varname")... that isn't Single Unix spec, + * but if your platform doesn't have unsetenv() it is + * worth investigating and potentially adding a + * configure check to decide when to use that form of + * putenv() here + */ + return APR_ENOTIMPL; +#endif +} diff --git a/srclib/apr/misc/unix/errorcodes.c b/srclib/apr/misc/unix/errorcodes.c new file mode 100644 index 0000000000..45b8e21eca --- /dev/null +++ b/srclib/apr/misc/unix/errorcodes.c @@ -0,0 +1,416 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_misc.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_dso.h" + +#if APR_HAVE_NETDB_H +#include +#endif +#ifdef HAVE_DLFCN_H +#include +#endif + +/* + * stuffbuffer - like apr_cpystrn() but returns the address of the + * dest buffer instead of the address of the terminating '\0' + */ +static char *stuffbuffer(char *buf, apr_size_t bufsize, const char *s) +{ + apr_cpystrn(buf,s,bufsize); + return buf; +} + +static char *apr_error_string(apr_status_t statcode) +{ + switch (statcode) { + case APR_ENOPOOL: + return "A new pool could not be created."; + case APR_EBADDATE: + return "An invalid date has been provided"; + case APR_EINVALSOCK: + return "An invalid socket was returned"; + case APR_ENOPROC: + return "No process was provided and one was required."; + case APR_ENOTIME: + return "No time was provided and one was required."; + case APR_ENODIR: + return "No directory was provided and one was required."; + case APR_ENOLOCK: + return "No lock was provided and one was required."; + case APR_ENOPOLL: + return "No poll structure was provided and one was required."; + case APR_ENOSOCKET: + return "No socket was provided and one was required."; + case APR_ENOTHREAD: + return "No thread was provided and one was required."; + case APR_ENOTHDKEY: + return "No thread key structure was provided and one was required."; + case APR_ENOSHMAVAIL: + return "No shared memory is currently available"; + case APR_EDSOOPEN: +#if APR_HAS_DSO && defined(HAVE_LIBDL) + return dlerror(); +#else + return "DSO load failed"; +#endif /* HAVE_LIBDL */ + case APR_EBADIP: + return "The specified IP address is invalid."; + case APR_EBADMASK: + return "The specified network mask is invalid."; + + case APR_INCHILD: + return + "Your code just forked, and you are currently executing in the " + "child process"; + case APR_INPARENT: + return + "Your code just forked, and you are currently executing in the " + "parent process"; + case APR_DETACH: + return "The specified thread is detached"; + case APR_NOTDETACH: + return "The specified thread is not detached"; + case APR_CHILD_DONE: + return "The specified child process is done executing"; + case APR_CHILD_NOTDONE: + return "The specified child process is not done executing"; + case APR_TIMEUP: + return "The timeout specified has expired"; + case APR_INCOMPLETE: + return "Partial results are valid but processing is incomplete"; + case APR_BADCH: + return "Bad character specified on command line"; + case APR_BADARG: + return "Missing parameter for the specified command line option"; + case APR_EOF: + return "End of file found"; + case APR_NOTFOUND: + return "Could not find specified socket in poll list."; + case APR_ANONYMOUS: + return "Shared memory is implemented anonymously"; + case APR_FILEBASED: + return "Shared memory is implemented using files"; + case APR_KEYBASED: + return "Shared memory is implemented using a key system"; + case APR_EINIT: + return + "There is no error, this value signifies an initialized " + "error code"; + case APR_ENOTIMPL: + return "This function has not been implemented on this platform"; + case APR_EMISMATCH: + return "passwords do not match"; + case APR_EABSOLUTE: + return "The given path is absolute"; + case APR_ERELATIVE: + return "The given path is relative"; + case APR_EINCOMPLETE: + return "The given path is incomplete"; + case APR_EABOVEROOT: + return "The given path was above the root path"; + case APR_EBADPATH: + return "The given path misformatted or contained invalid characters"; + case APR_EPATHWILD: + return "The given path contained wildcard characters"; + case APR_EPROC_UNKNOWN: + return "The process is not recognized."; + case APR_EGENERAL: + return "Internal error"; + default: + return "Error string not specified yet"; + } +} + + +#ifdef OS2 +#include + +int apr_canonical_error(apr_status_t err); + +static char *apr_os_strerror(char* buf, apr_size_t bufsize, int err) +{ + char result[200]; + unsigned char message[HUGE_STRING_LEN]; + ULONG len; + char *pos; + int c; + + if (err >= 10000 && err < 12000) { /* socket error codes */ + return stuffbuffer(buf, bufsize, + strerror(apr_canonical_error(err+APR_OS_START_SYSERR))); + } + else if (DosGetMessage(NULL, 0, message, HUGE_STRING_LEN, err, + "OSO001.MSG", &len) == 0) { + len--; + message[len] = 0; + pos = result; + + if (len >= sizeof(result)) + len = sizeof(result-1); + + for (c=0; ccont = cont; + (*os)->reset = 0; + (*os)->errfn = (apr_getopt_err_fn_t*)(fprintf); + (*os)->errarg = (void*)(stderr); + + (*os)->place = EMSG; + (*os)->argc = argc; + + /* The argv parameter must be compatible with main()'s argv, since + that's the primary purpose of this function. But people might + want to use this function with arrays other than the main argv, + and we shouldn't touch the caller's data. So we copy. */ + argv_buff = apr_palloc(cont, (argc + 1) * sizeof(const char *)); + memcpy(argv_buff, argv, argc * sizeof(const char *)); + (*os)->argv = argv_buff; + (*os)->argv[argc] = NULL; + + (*os)->interleave = 0; + (*os)->ind = 1; + (*os)->skip_start = 1; + (*os)->skip_end = 1; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_getopt(apr_getopt_t *os, const char *opts, + char *optch, const char **optarg) +{ + const char *oli; /* option letter list index */ + + if (os->reset || !*os->place) { /* update scanning pointer */ + os->reset = 0; + if (os->ind >= os->argc || *(os->place = os->argv[os->ind]) != '-') { + os->place = EMSG; + *optch = os->opt; + return (APR_EOF); + } + if (os->place[1] && *++os->place == '-') { /* found "--" */ + ++os->ind; + os->place = EMSG; + *optch = os->opt; + return (APR_EOF); + } + } /* option letter okay? */ + if ((os->opt = (int) *os->place++) == (int) ':' || + !(oli = strchr(opts, os->opt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means -1. + */ + if (os->opt == (int) '-') { + *optch = os->opt; + return (APR_EOF); + } + if (!*os->place) + ++os->ind; + if (os->errfn && *opts != ':') { + (os->errfn)(os->errarg, "%s: illegal option -- %c\n", + apr_filepath_name_get(*os->argv), os->opt); + } + *optch = os->opt; + return (APR_BADCH); + } + if (*++oli != ':') { /* don't need argument */ + *optarg = NULL; + if (!*os->place) + ++os->ind; + } + else { /* need an argument */ + if (*os->place) /* no white space */ + *optarg = os->place; + else if (os->argc <= ++os->ind) { /* no arg */ + os->place = EMSG; + if (*opts == ':') { + *optch = os->opt; + return (APR_BADARG); + } + if (os->errfn) { + (os->errfn)(os->errarg, + "%s: option requires an argument -- %c\n", + apr_filepath_name_get(*os->argv), os->opt); + } + *optch = os->opt; + return (APR_BADCH); + } + else /* white space */ + *optarg = os->argv[os->ind]; + os->place = EMSG; + ++os->ind; + } + *optch = os->opt; + return APR_SUCCESS; +} + +/* Reverse the sequence argv[start..start+len-1]. */ +static void reverse(const char **argv, int start, int len) +{ + const char *temp; + + for (; len >= 2; start++, len -= 2) { + temp = argv[start]; + argv[start] = argv[start + len - 1]; + argv[start + len - 1] = temp; + } +} + +/* + * Permute os->argv with the goal that non-option arguments will all + * appear at the end. os->skip_start is where we started skipping + * non-option arguments, os->skip_end is where we stopped, and os->ind + * is where we are now. + */ +static void permute(apr_getopt_t *os) +{ + int len1 = os->skip_end - os->skip_start; + int len2 = os->ind - os->skip_end; + + if (os->interleave) { + /* + * Exchange the sequences argv[os->skip_start..os->skip_end-1] and + * argv[os->skip_end..os->ind-1]. The easiest way to do that is + * to reverse the entire range and then reverse the two + * sub-ranges. + */ + reverse(os->argv, os->skip_start, len1 + len2); + reverse(os->argv, os->skip_start, len2); + reverse(os->argv, os->skip_start + len2, len1); + } + + /* Reset skip range to the new location of the non-option sequence. */ + os->skip_start += len2; + os->skip_end += len2; +} + +/* Helper function to print out an error involving a long option */ +static apr_status_t serr(apr_getopt_t *os, const char *err, const char *str, + apr_status_t status) +{ + if (os->errfn) + (os->errfn)(os->errarg, "%s: %s: %s\n", + apr_filepath_name_get(*os->argv), err, str); + return status; +} + +/* Helper function to print out an error involving a short option */ +static apr_status_t cerr(apr_getopt_t *os, const char *err, int ch, + apr_status_t status) +{ + if (os->errfn) + (os->errfn)(os->errarg, "%s: %s: %c\n", + apr_filepath_name_get(*os->argv), err, ch); + return status; +} + +APR_DECLARE(apr_status_t) apr_getopt_long(apr_getopt_t *os, + const apr_getopt_option_t *opts, + int *optch, const char **optarg) +{ + const char *p; + int i; + + /* Let the calling program reset option processing. */ + if (os->reset) { + os->place = EMSG; + os->ind = 1; + os->reset = 0; + } + + /* + * We can be in one of two states: in the middle of processing a + * run of short options, or about to process a new argument. + * Since the second case can lead to the first one, handle that + * one first. */ + p = os->place; + if (*p == '\0') { + /* If we are interleaving, skip non-option arguments. */ + if (os->interleave) { + while (os->ind < os->argc && *os->argv[os->ind] != '-') + os->ind++; + os->skip_end = os->ind; + } + if (os->ind >= os->argc || *os->argv[os->ind] != '-') { + os->ind = os->skip_start; + return APR_EOF; + } + + p = os->argv[os->ind++] + 1; + if (*p == '-' && p[1] != '\0') { /* Long option */ + /* Search for the long option name in the caller's table. */ + apr_size_t len = 0; + + p++; + for (i = 0; ; i++) { + if (opts[i].optch == 0) /* No match */ + return serr(os, "invalid option", p - 2, APR_BADCH); + + if (opts[i].name) { + len = strlen(opts[i].name); + if (strncmp(p, opts[i].name, len) == 0 + && (p[len] == '\0' || p[len] == '=')) + break; + } + } + *optch = opts[i].optch; + + if (opts[i].has_arg) { + if (p[len] == '=') /* Argument inline */ + *optarg = p + len + 1; + else { + if (os->ind >= os->argc) /* Argument missing */ + return serr(os, "missing argument", p - 2, APR_BADARG); + else /* Argument in next arg */ + *optarg = os->argv[os->ind++]; + } + } else { + *optarg = NULL; + if (p[len] == '=') + return serr(os, "erroneous argument", p - 2, APR_BADARG); + } + permute(os); + return APR_SUCCESS; + } else { + if (*p == '-') { /* Bare "--"; we're done */ + permute(os); + os->ind = os->skip_start; + return APR_EOF; + } + else + if (*p == '\0') /* Bare "-" is illegal */ + return serr(os, "invalid option", p, APR_BADCH); + } + } + + /* + * Now we're in a run of short options, and *p is the next one. + * Look for it in the caller's table. + */ + for (i = 0; ; i++) { + if (opts[i].optch == 0) /* No match */ + return cerr(os, "invalid option character", *p, APR_BADCH); + + if (*p == opts[i].optch) + break; + } + *optch = *p++; + + if (opts[i].has_arg) { + if (*p != '\0') /* Argument inline */ + *optarg = p; + else { + if (os->ind >= os->argc) /* Argument missing */ + return cerr(os, "missing argument", *optch, APR_BADARG); + else /* Argument in next arg */ + *optarg = os->argv[os->ind++]; + } + os->place = EMSG; + } else { + *optarg = NULL; + os->place = p; + } + + permute(os); + return APR_SUCCESS; +} diff --git a/srclib/apr/misc/unix/otherchild.c b/srclib/apr/misc/unix/otherchild.c new file mode 100644 index 0000000000..8ae41410c4 --- /dev/null +++ b/srclib/apr/misc/unix/otherchild.c @@ -0,0 +1,221 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_arch_misc.h" +#include "apr_arch_threadproc.h" +#include "apr_arch_file_io.h" + +#if APR_HAS_OTHER_CHILD + +#ifdef HAVE_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#if APR_HAVE_SYS_WAIT_H +#include +#endif +#ifdef BEOS +#include /* for fd_set definition! */ +#endif + +static apr_other_child_rec_t *other_children = NULL; + +static apr_status_t other_child_cleanup(void *data) +{ + apr_other_child_rec_t **pocr, *nocr; + + for (pocr = &other_children; *pocr; pocr = &(*pocr)->next) { + if ((*pocr)->data == data) { + nocr = (*pocr)->next; + (*(*pocr)->maintenance) (APR_OC_REASON_UNREGISTER, (*pocr)->data, -1); + *pocr = nocr; + /* XXX: um, well we've just wasted some space in pconf ? */ + return APR_SUCCESS; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc, + void (*maintenance) (int reason, void *, int status), + void *data, apr_file_t *write_fd, apr_pool_t *p) +{ + apr_other_child_rec_t *ocr; + + ocr = apr_palloc(p, sizeof(*ocr)); + ocr->p = p; + ocr->proc = proc; + ocr->maintenance = maintenance; + ocr->data = data; + if (write_fd == NULL) { + ocr->write_fd = (apr_os_file_t) -1; + } + else { +#ifdef WIN32 + /* This should either go away as part of eliminating apr_proc_probe_writable_fds + * or write_fd should point to an apr_file_t + */ + ocr->write_fd = write_fd->filehand; +#else + ocr->write_fd = write_fd->filedes; +#endif + + } + ocr->next = other_children; + other_children = ocr; + apr_pool_cleanup_register(p, ocr->data, other_child_cleanup, + apr_pool_cleanup_null); +} + +APR_DECLARE(void) apr_proc_other_child_unregister(void *data) +{ + apr_other_child_rec_t *cur; + + cur = other_children; + while (cur) { + if (cur->data == data) { + break; + } + cur = cur->next; + } + + /* segfault if this function called with invalid parm */ + apr_pool_cleanup_kill(cur->p, cur->data, other_child_cleanup); + other_child_cleanup(data); +} + +APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc, + int reason, + int status) +{ + apr_other_child_rec_t *ocr, *nocr; + + for (ocr = other_children; ocr; ocr = nocr) { + nocr = ocr->next; + if (ocr->proc->pid != proc->pid) + continue; + + ocr->proc = NULL; + (*ocr->maintenance) (reason, ocr->data, status); + return APR_SUCCESS; + } + return APR_EPROC_UNKNOWN; +} + +APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr, + int reason) +{ + /* Todo: + * Implement code to detect if pipes are still alive. + */ +#ifdef WIN32 + DWORD status; + + if (ocr->proc == NULL) + return; + + if (!ocr->proc->hproc) { + /* Already mopped up, perhaps we apr_proc_kill'ed it, + * they should have already unregistered! + */ + ocr->proc = NULL; + (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1); + } + else if (!GetExitCodeProcess(ocr->proc->hproc, &status)) { + CloseHandle(ocr->proc->hproc); + ocr->proc->hproc = NULL; + ocr->proc = NULL; + (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1); + } + else if (status == STILL_ACTIVE) { + (*ocr->maintenance) (reason, ocr->data, -1); + } + else { + CloseHandle(ocr->proc->hproc); + ocr->proc->hproc = NULL; + ocr->proc = NULL; + (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status); + } + +#else /* ndef Win32 */ + pid_t waitret; + int status; + + if (ocr->proc == NULL) + return; + + waitret = waitpid(ocr->proc->pid, &status, WNOHANG); + if (waitret == ocr->proc->pid) { + ocr->proc = NULL; + (*ocr->maintenance) (APR_OC_REASON_DEATH, ocr->data, status); + } + else if (waitret == 0) { + (*ocr->maintenance) (reason, ocr->data, -1); + } + else if (waitret == -1) { + /* uh what the heck? they didn't call unregister? */ + ocr->proc = NULL; + (*ocr->maintenance) (APR_OC_REASON_LOST, ocr->data, -1); + } +#endif +} + +APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason) +{ + apr_other_child_rec_t *ocr, *next_ocr; + + for (ocr = other_children; ocr; ocr = next_ocr) { + next_ocr = ocr->next; + apr_proc_other_child_refresh(ocr, reason); + } +} + +#else /* !APR_HAS_OTHER_CHILD */ + +APR_DECLARE(void) apr_proc_other_child_register(apr_proc_t *proc, + void (*maintenance) (int reason, void *, int status), + void *data, apr_file_t *write_fd, apr_pool_t *p) +{ + return; +} + +APR_DECLARE(void) apr_proc_other_child_unregister(void *data) +{ + return; +} + +APR_DECLARE(apr_status_t) apr_proc_other_child_alert(apr_proc_t *proc, + int reason, + int status) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(void) apr_proc_other_child_refresh(apr_other_child_rec_t *ocr, + int reason) +{ + return; +} + +APR_DECLARE(void) apr_proc_other_child_refresh_all(int reason) +{ + return; +} + +#endif /* APR_HAS_OTHER_CHILD */ diff --git a/srclib/apr/misc/unix/rand.c b/srclib/apr/misc/unix/rand.c new file mode 100644 index 0000000000..4691f08a19 --- /dev/null +++ b/srclib/apr/misc/unix/rand.c @@ -0,0 +1,238 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define APR_WANT_MEMFUNC +#include "apr_want.h" +#include "apr_general.h" + +#include "apr_arch_misc.h" +#include +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_SOCKET_H +#include +#endif +#if APR_HAVE_FCNTL_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_SYS_UN_H +#include +#endif +#ifdef HAVE_UUID_UUID_H +#include +#endif +#ifdef HAVE_UUID_H +#include +#endif + +#ifndef SHUT_RDWR +#define SHUT_RDWR 2 +#endif + +#if defined(HAVE_UUID_CREATE) + +APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data) +{ + uuid_t g; + + uuid_create(&g, NULL); + + memcpy(uuid_data, &g, sizeof(uuid_t)); + + return APR_SUCCESS; +} + +#elif defined(HAVE_UUID_GENERATE) + +APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data) +{ + uuid_t g; + + uuid_generate(g); + + memcpy(uuid_data, g, sizeof(uuid_t)); + + return APR_SUCCESS; +} +#endif + +#if APR_HAS_RANDOM + +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char *buf, + apr_size_t length) +{ +#ifdef DEV_RANDOM + + int fd = -1; + + /* On BSD/OS 4.1, /dev/random gives out 8 bytes at a time, then + * gives EOF, so reading 'length' bytes may require opening the + * device several times. */ + do { + apr_ssize_t rc; + + if (fd == -1) + if ((fd = open(DEV_RANDOM, O_RDONLY)) == -1) + return errno; + + rc = read(fd, buf, length); + if (rc < 0) { + int errnum = errno; + close(fd); + return errnum; + } + else if (rc == 0) { + close(fd); + fd = -1; /* force open() again */ + } + else { + buf += rc; + length -= rc; + } + } while (length > 0); + + close(fd); +#elif defined(OS2) + static UCHAR randbyte(); + unsigned int idx; + + for (idx=0; idx 0; egdsockname++) { + egd_path_len = strlen(*egdsockname); + + if (egd_path_len > sizeof(addr.sun_path)) { + return APR_EINVAL; + } + + memset(&addr, 0, sizeof(struct sockaddr_un)); + addr.sun_family = AF_UNIX; + memcpy(addr.sun_path, *egdsockname, egd_path_len); + egd_addr_len = APR_OFFSETOF(struct sockaddr_un, sun_path) + + egd_path_len; + + egd_socket = socket(PF_UNIX, SOCK_STREAM, 0); + + if (egd_socket == -1) { + return errno; + } + + rv = connect(egd_socket, (struct sockaddr*)&addr, egd_addr_len); + + if (rv == -1) { + bad_errno = errno; + continue; + } + + /* EGD can only return 255 bytes of data at a time. Silly. */ + while (length > 0) { + apr_ssize_t srv; + req[0] = 2; /* We'll block for now. */ + req[1] = length > 255 ? 255: length; + + srv = write(egd_socket, req, 2); + if (srv == -1) { + bad_errno = errno; + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + break; + } + + if (srv != 2) { + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + return APR_EGENERAL; + } + + resp_expected = req[1]; + srv = read(egd_socket, resp, resp_expected); + if (srv == -1) { + bad_errno = errno; + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + return bad_errno; + } + + memcpy(curbuf, resp, srv); + curbuf += srv; + length -= srv; + } + + shutdown(egd_socket, SHUT_RDWR); + close(egd_socket); + } + + if (length > 0) { + /* We must have iterated through the list of sockets, + * and no go. Return the errno. + */ + return bad_errno; + } + +#elif defined(HAVE_TRUERAND) /* use truerand */ + + extern int randbyte(void); /* from the truerand library */ + unsigned int idx; + + /* this will increase the startup time of the server, unfortunately... + * (generating 20 bytes takes about 8 seconds) + */ + for (idx=0; idx> 8; + return byte; +} + + + +/* A bunch of system information like memory & process stats. + * Not highly random but every bit helps.... + */ +static UCHAR randbyte_sysinfo() +{ + UCHAR byte = 0; + UCHAR SysVars[100]; + int b; + + DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars)); + + for (b = 0; b < 100; b++) { + byte ^= SysVars[b]; + } + + return byte; +} + + + +/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal + * counters which run at the CPU's MHz speed. We get separate + * idle / busy / interrupt cycle counts which should provide very good + * randomness due to interference of hardware events. + * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions + * which is why it's run-time linked. + */ + +static APIRET APIENTRY(*DosPerfSysCall) (ULONG ulCommand, ULONG ulParm1, + ULONG ulParm2, ULONG ulParm3) = NULL; +static HMODULE hDoscalls = 0; +#define CMD_KI_RDCNT (0x63) + +typedef struct _CPUUTIL { + ULONG ulTimeLow; /* Low 32 bits of time stamp */ + ULONG ulTimeHigh; /* High 32 bits of time stamp */ + ULONG ulIdleLow; /* Low 32 bits of idle time */ + ULONG ulIdleHigh; /* High 32 bits of idle time */ + ULONG ulBusyLow; /* Low 32 bits of busy time */ + ULONG ulBusyHigh; /* High 32 bits of busy time */ + ULONG ulIntrLow; /* Low 32 bits of interrupt time */ + ULONG ulIntrHigh; /* High 32 bits of interrupt time */ +} CPUUTIL; + + +static UCHAR randbyte_perf() +{ + UCHAR byte = 0; + CPUUTIL util; + int c; + + if (hDoscalls == 0) { + char failed_module[20]; + ULONG rc; + + rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS", + &hDoscalls); + + if (rc == 0) { + rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall); + + if (rc) { + DosPerfSysCall = NULL; + } + } + } + + if (DosPerfSysCall) { + if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) { + for (c = 0; c < sizeof(util); c++) { + byte ^= ((UCHAR *)&util)[c]; + } + } + else { + DosPerfSysCall = NULL; + } + } + + return byte; +} + + + +static UCHAR randbyte() +{ + return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf(); +} diff --git a/srclib/apr/misc/unix/start.c b/srclib/apr/misc/unix/start.c new file mode 100644 index 0000000000..c1176bdea1 --- /dev/null +++ b/srclib/apr/misc/unix/start.c @@ -0,0 +1,89 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_signal.h" +#include "apr_atomic.h" + +#include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */ +#include "apr_arch_internal_time.h" + + +APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + const char * const * *argv, + const char * const * *env) +{ + /* An absolute noop. At present, only Win32 requires this stub, but it's + * required in order to move command arguments passed through the service + * control manager into the process, and it's required to fix the char* + * data passed in from win32 unicode into utf-8, win32's apr internal fmt. + */ + return apr_initialize(); +} + +static int initialized = 0; + +APR_DECLARE(apr_status_t) apr_initialize(void) +{ + apr_pool_t *pool; + apr_status_t status; + + if (initialized++) { + return APR_SUCCESS; + } + +#if !defined(BEOS) && !defined(OS2) + apr_proc_mutex_unix_setup_lock(); + apr_unix_setup_time(); +#endif + + if ((status = apr_pool_initialize()) != APR_SUCCESS) + return status; + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { + return APR_ENOPOOL; + } + + apr_pool_tag(pool, "apr_initialize"); + + /* apr_atomic_init() used to be called from here aswell. + * Pools rely on mutexes though, which can be backed by + * atomics. Due to this circular dependency + * apr_pool_initialize() is taking care of calling + * apr_atomic_init() at the correct time. + */ + + apr_signal_init(pool); + + return APR_SUCCESS; +} + +APR_DECLARE_NONSTD(void) apr_terminate(void) +{ + initialized--; + if (initialized) { + return; + } + apr_pool_terminate(); + +} + +APR_DECLARE(void) apr_terminate2(void) +{ + apr_terminate(); +} diff --git a/srclib/apr/misc/unix/version.c b/srclib/apr/misc/unix/version.c new file mode 100644 index 0000000000..a46cf6c2c5 --- /dev/null +++ b/srclib/apr/misc/unix/version.c @@ -0,0 +1,35 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_version.h" +#include "apr_general.h" /* for APR_STRINGIFY */ + +APR_DECLARE(void) apr_version(apr_version_t *pvsn) +{ + pvsn->major = APR_MAJOR_VERSION; + pvsn->minor = APR_MINOR_VERSION; + pvsn->patch = APR_PATCH_VERSION; +#ifdef APR_IS_DEV_VERSION + pvsn->is_dev = 1; +#else + pvsn->is_dev = 0; +#endif +} + +APR_DECLARE(const char *) apr_version_string(void) +{ + return APR_VERSION_STRING; +} diff --git a/srclib/apr/misc/win32/apr_app.c b/srclib/apr/misc/win32/apr_app.c new file mode 100644 index 0000000000..eb76df35a3 --- /dev/null +++ b/srclib/apr/misc/win32/apr_app.c @@ -0,0 +1,80 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* Usage Notes: + * + * this module, and the misc/win32/utf8.c modules must be + * compiled APR_EXPORT_STATIC and linked to an application with + * the /entry:wmainCRTStartup flag. This module becomes the true + * wmain entry point, and passes utf-8 reformatted argv and env + * arrays to the application's main function. + * + * This module is only compatible with Unicode-only executables. + * Mixed (Win9x backwards compatible) binaries should refer instead + * to the apr_startup.c module. + * + * _dbg_malloc/realloc is used in place of the usual API, in order + * to convince the MSVCRT that they created these entities. If we + * do not create them as _CRT_BLOCK entities, the crt will fault + * on an assert. We are not worrying about the crt's locks here, + * since we are single threaded [so far]. + */ + +#include "apr_general.h" +#include "ShellAPI.h" +#include "crtdbg.h" +#include "wchar.h" +#include "apr_arch_file_io.h" +#include "assert.h" +#include "apr_private.h" +#include "apr_arch_misc.h" + +/* This symbol is _private_, although it must be exported. + */ + +extern int main(int argc, const char **argv, const char **env); + +int wmain(int argc, const wchar_t **wargv, const wchar_t **wenv) +{ + char **argv; + char **env; + int dupenv; + + (void)apr_wastrtoastr(&argv, wargv, argc); + + dupenv = apr_wastrtoastr(&env, wenv, -1); + + _environ = _malloc_dbg((dupenv + 1) * sizeof (char *), + _CRT_BLOCK, __FILE__, __LINE__ ); + memcpy(_environ, env, (dupenv + 1) * sizeof (char *)); + + /* MSVCRT will attempt to maintain the wide environment calls + * on _putenv(), which is bogus if we've passed a non-ascii + * string to _putenv(), since they use MultiByteToWideChar + * and breaking the implicit utf-8 assumption we've built. + * + * Reset _wenviron for good measure. + */ + if (_wenviron) { + wenv = _wenviron; + _wenviron = NULL; + free((wchar_t **)wenv); + } + + apr_app_init_complete = 1; + + return main(argc, argv, env); +} diff --git a/srclib/apr/misc/win32/charset.c b/srclib/apr/misc/win32/charset.c new file mode 100644 index 0000000000..c0db771840 --- /dev/null +++ b/srclib/apr/misc/win32/charset.c @@ -0,0 +1,43 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_strings.h" +#include "apr_portable.h" + + +APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool) +{ + return apr_psprintf(pool, "CP%u", (unsigned) GetACP()); +} + + +APR_DECLARE(const char*) apr_os_locale_encoding (apr_pool_t *pool) +{ + LCID locale = GetThreadLocale(); + int len = GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, NULL, 0); + char *cp = apr_palloc(pool, len + 2); + if (0 < GetLocaleInfo(locale, LOCALE_IDEFAULTANSICODEPAGE, cp + 2, len)) + { + /* Fix up the returned number to make a valid codepage name of + the form "CPnnnn". */ + cp[0] = 'C'; + cp[1] = 'P'; + return cp; + } + + return apr_os_default_encoding(pool); +} diff --git a/srclib/apr/misc/win32/env.c b/srclib/apr/misc/win32/env.c new file mode 100644 index 0000000000..d8edc400bf --- /dev/null +++ b/srclib/apr/misc/win32/env.c @@ -0,0 +1,169 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define APR_WANT_STRFUNC +#include "apr_want.h" +#include "apr.h" +#include "apr_arch_misc.h" +#include "apr_arch_utf8.h" +#include "apr_env.h" +#include "apr_errno.h" +#include "apr_pools.h" + + +#if APR_HAS_UNICODE_FS +static apr_status_t widen_envvar_name (apr_wchar_t *buffer, + apr_size_t bufflen, + const char *envvar) +{ + apr_size_t inchars; + apr_status_t status; + + inchars = strlen(envvar) + 1; + status = apr_conv_utf8_to_ucs2(envvar, &inchars, buffer, &bufflen); + if (status == APR_INCOMPLETE) + status = APR_ENAMETOOLONG; + + return status; +} +#endif + + +APR_DECLARE(apr_status_t) apr_env_get(char **value, + const char *envvar, + apr_pool_t *pool) +{ + char *val = NULL; + DWORD size; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wenvvar[APR_PATH_MAX]; + apr_size_t inchars, outchars; + apr_wchar_t *wvalue, dummy; + apr_status_t status; + + status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar); + if (status) + return status; + + size = GetEnvironmentVariableW(wenvvar, &dummy, 0); + if (size == 0) + /* The environment variable doesn't exist. */ + return APR_ENOENT; + + wvalue = apr_palloc(pool, size * sizeof(*wvalue)); + size = GetEnvironmentVariableW(wenvvar, wvalue, size); + if (size == 0) + /* Mid-air collision?. Somebody must've changed the env. var. */ + return APR_INCOMPLETE; + + inchars = wcslen(wvalue) + 1; + outchars = 3 * inchars; /* Enougn for any UTF-8 representation */ + val = apr_palloc(pool, outchars); + status = apr_conv_ucs2_to_utf8(wvalue, &inchars, val, &outchars); + if (status) + return status; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char dummy; + + size = GetEnvironmentVariableA(envvar, &dummy, 0); + if (size == 0) + /* The environment variable doesn't exist. */ + return APR_ENOENT; + + val = apr_palloc(pool, size); + size = GetEnvironmentVariableA(envvar, val, size); + if (size == 0) + /* Mid-air collision?. Somebody must've changed the env. var. */ + return APR_INCOMPLETE; + } +#endif + + *value = val; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_env_set(const char *envvar, + const char *value, + apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wenvvar[APR_PATH_MAX]; + apr_wchar_t *wvalue; + apr_size_t inchars, outchars; + apr_status_t status; + + status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar); + if (status) + return status; + + outchars = inchars = strlen(value) + 1; + wvalue = apr_palloc(pool, outchars * sizeof(*wvalue)); + status = apr_conv_utf8_to_ucs2(value, &inchars, wvalue, &outchars); + if (status) + return status; + + if (!SetEnvironmentVariableW(wenvvar, wvalue)) + return apr_get_os_error(); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + if (!SetEnvironmentVariableA(envvar, value)) + return apr_get_os_error(); + } +#endif + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_env_delete(const char *envvar, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wenvvar[APR_PATH_MAX]; + apr_status_t status; + + status = widen_envvar_name(wenvvar, APR_PATH_MAX, envvar); + if (status) + return status; + + if (!SetEnvironmentVariableW(wenvvar, NULL)) + return apr_get_os_error(); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + if (!SetEnvironmentVariableA(envvar, NULL)) + return apr_get_os_error(); + } +#endif + + return APR_SUCCESS; +} diff --git a/srclib/apr/misc/win32/internal.c b/srclib/apr/misc/win32/internal.c new file mode 100644 index 0000000000..239011264d --- /dev/null +++ b/srclib/apr/misc/win32/internal.c @@ -0,0 +1,102 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" + +#include "apr_arch_misc.h" +#include "apr_arch_file_io.h" +#include +#include + +/* This module is the source of -static- helper functions that are + * entirely internal to apr. If the fn is exported - it does not + * belong here. + * + * Namespace decoration is still required to protect us from symbol + * clashes in static linkages. + */ + + +/* Shared by apr_app.c and start.c + * + * An internal apr function to convert an array of strings (either + * a counted or NULL terminated list, such as an argv[argc] or env[] + * list respectively) from wide Unicode strings to narrow utf-8 strings. + * These are allocated from the MSVCRT's _CRT_BLOCK to trick the system + * into trusting our store. + */ +int apr_wastrtoastr(char const * const * *retarr, + wchar_t const * const *arr, int args) +{ + apr_size_t elesize = 0; + char **newarr; + char *elements; + char *ele; + int arg; + + if (args < 0) { + for (args = 0; arr[args]; ++args) + ; + } + + newarr = _malloc_dbg((args + 1) * sizeof(char *), + _CRT_BLOCK, __FILE__, __LINE__); + + for (arg = 0; arg < args; ++arg) { + newarr[arg] = (void*)(wcslen(arr[arg]) + 1); + elesize += (apr_size_t)newarr[arg]; + } + + /* This is a safe max allocation, we will realloc after + * processing and return the excess to the free store. + * 3 ucs bytes hold any single wchar_t value (16 bits) + * 4 ucs bytes will hold a wchar_t pair value (20 bits) + */ + elesize = elesize * 3 + 1; + ele = elements = _malloc_dbg(elesize * sizeof(char), + _CRT_BLOCK, __FILE__, __LINE__); + + for (arg = 0; arg < args; ++arg) { + apr_size_t len = (apr_size_t)newarr[arg]; + apr_size_t newlen = elesize; + + newarr[arg] = ele; + (void)apr_conv_ucs2_to_utf8(arr[arg], &len, + newarr[arg], &elesize); + + newlen -= elesize; + ele += newlen; + assert(elesize && (len == 0)); + } + + newarr[arg] = NULL; + *(ele++) = '\0'; + + /* Return to the free store if the heap realloc is the least bit optimized + */ + ele = _realloc_dbg(elements, ele - elements, + _CRT_BLOCK, __FILE__, __LINE__); + + if (ele != elements) { + apr_size_t diff = ele - elements; + for (arg = 0; arg < args; ++arg) { + newarr[arg] += diff; + } + } + + *retarr = newarr; + return args; +} diff --git a/srclib/apr/misc/win32/misc.c b/srclib/apr/misc/win32/misc.c new file mode 100644 index 0000000000..eaf896a285 --- /dev/null +++ b/srclib/apr/misc/win32/misc.c @@ -0,0 +1,245 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_arch_misc.h" +#include "crtdbg.h" +#include "apr_arch_file_io.h" +#include "assert.h" +#include "apr_lib.h" + +APR_DECLARE_DATA apr_oslevel_e apr_os_level = APR_WIN_UNK; + +apr_status_t apr_get_oslevel(apr_oslevel_e *level) +{ + if (apr_os_level == APR_WIN_UNK) + { + static OSVERSIONINFO oslev; + oslev.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&oslev); + + if (oslev.dwPlatformId == VER_PLATFORM_WIN32_NT) + { + static unsigned int servpack = 0; + char *pservpack; + if (pservpack = oslev.szCSDVersion) { + while (*pservpack && !apr_isdigit(*pservpack)) { + pservpack++; + } + if (*pservpack) + servpack = atoi(pservpack); + } + + if (oslev.dwMajorVersion < 3) { + apr_os_level = APR_WIN_UNSUP; + } + else if (oslev.dwMajorVersion == 3) { + if (oslev.dwMajorVersion < 50) { + apr_os_level = APR_WIN_UNSUP; + } + else if (oslev.dwMajorVersion == 50) { + apr_os_level = APR_WIN_NT_3_5; + } + else { + apr_os_level = APR_WIN_NT_3_51; + } + } + else if (oslev.dwMajorVersion == 4) { + if (servpack < 2) + apr_os_level = APR_WIN_NT_4; + else if (servpack <= 2) + apr_os_level = APR_WIN_NT_4_SP2; + else if (servpack <= 3) + apr_os_level = APR_WIN_NT_4_SP3; + else if (servpack <= 4) + apr_os_level = APR_WIN_NT_4_SP4; + else if (servpack <= 5) + apr_os_level = APR_WIN_NT_4_SP5; + else + apr_os_level = APR_WIN_NT_4_SP6; + } + else if (oslev.dwMajorVersion == 5) { + if (oslev.dwMinorVersion == 0) { + if (servpack == 0) + apr_os_level = APR_WIN_2000; + else if (servpack == 1) + apr_os_level = APR_WIN_2000_SP1; + else + apr_os_level = APR_WIN_2000_SP2; + } + else if (oslev.dwMinorVersion == 2) { + apr_os_level = APR_WIN_2003; + } + else { + if (servpack < 1) + apr_os_level = APR_WIN_XP; + else if (servpack == 1) + apr_os_level = APR_WIN_XP_SP1; + else + apr_os_level = APR_WIN_XP_SP2; + } + } + else { + apr_os_level = APR_WIN_XP; + } + } +#ifndef WINNT + else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) { + char *prevision; + if (prevision = oslev.szCSDVersion) { + while (*prevision && !apr_isupper(*prevision)) { + prevision++; + } + } + else prevision = ""; + + if (oslev.dwMinorVersion < 10) { + if (*prevision < 'C') + apr_os_level = APR_WIN_95; + else + apr_os_level = APR_WIN_95_OSR2; + } + else if (oslev.dwMinorVersion < 90) { + if (*prevision < 'A') + apr_os_level = APR_WIN_98; + else + apr_os_level = APR_WIN_98_SE; + } + else { + apr_os_level = APR_WIN_ME; + } + } +#endif +#ifdef _WIN32_WCE + else if (oslev.dwPlatformId == VER_PLATFORM_WIN32_CE) + { + if (oslev.dwMajorVersion < 3) { + apr_os_level = APR_WIN_UNSUP; + } + else { + apr_os_level = APR_WIN_CE_3; + } + } +#endif + else { + apr_os_level = APR_WIN_UNSUP; + } + } + + *level = apr_os_level; + + if (apr_os_level < APR_WIN_UNSUP) { + return APR_EGENERAL; + } + + return APR_SUCCESS; +} + + +/* This is the helper code to resolve late bound entry points + * missing from one or more releases of the Win32 API + */ + +static const char* const lateDllName[DLL_defined] = { + "kernel32", "advapi32", "mswsock", "ws2_32", "shell32", "ntdll.dll" }; +static HMODULE lateDllHandle[DLL_defined] = { + NULL, NULL, NULL, NULL, NULL, NULL }; + +FARPROC apr_load_dll_func(apr_dlltoken_e fnLib, char* fnName, int ordinal) +{ + if (!lateDllHandle[fnLib]) { + lateDllHandle[fnLib] = LoadLibrary(lateDllName[fnLib]); + if (!lateDllHandle[fnLib]) + return NULL; + } + if (ordinal) + return GetProcAddress(lateDllHandle[fnLib], (char *) ordinal); + else + return GetProcAddress(lateDllHandle[fnLib], fnName); +} + +/* Declared in include/arch/win32/apr_dbg_win32_handles.h + */ +APR_DECLARE_NONSTD(HANDLE) apr_dbg_log(char* fn, HANDLE ha, char* fl, int ln, + int nh, /* HANDLE hv, char *dsc */...) +{ + static DWORD tlsid = 0xFFFFFFFF; + static HANDLE fh = NULL; + static long ctr = 0; + static CRITICAL_SECTION cs; + long seq; + DWORD wrote; + char *sbuf; + + seq = (InterlockedIncrement)(&ctr); + + if (tlsid == 0xFFFFFFFF) { + tlsid = (TlsAlloc)(); + } + + sbuf = (TlsGetValue)(tlsid); + if (!fh || !sbuf) { + sbuf = (malloc)(1024); + (TlsSetValue)(tlsid, sbuf); + sbuf[1023] = '\0'; + if (!fh) { + (GetModuleFileName)(NULL, sbuf, 250); + sprintf(strchr(sbuf, '\0'), ".%d", + (GetCurrentProcessId)()); + fh = (CreateFile)(sbuf, GENERIC_WRITE, 0, NULL, + CREATE_ALWAYS, 0, NULL); + (InitializeCriticalSection)(&cs); + } + } + + if (!nh) { + (sprintf)(sbuf, "%08x %08x %08x %s() %s:%d\n", + (DWORD)ha, seq, GetCurrentThreadId(), fn, fl, ln); + (EnterCriticalSection)(&cs); + (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL); + (LeaveCriticalSection)(&cs); + } + else { + va_list a; + va_start(a,nh); + (EnterCriticalSection)(&cs); + do { + HANDLE *hv = va_arg(a, HANDLE*); + char *dsc = va_arg(a, char*); + if (strcmp(dsc, "Signaled") == 0) { + if ((DWORD)ha >= STATUS_WAIT_0 + && (DWORD)ha < STATUS_ABANDONED_WAIT_0) { + hv += (DWORD)ha; + } + else if ((DWORD)ha >= STATUS_ABANDONED_WAIT_0 + && (DWORD)ha < STATUS_USER_APC) { + hv += (DWORD)ha - STATUS_ABANDONED_WAIT_0; + dsc = "Abandoned"; + } + else if ((DWORD)ha == WAIT_TIMEOUT) { + dsc = "Timed Out"; + } + } + (sprintf)(sbuf, "%08x %08x %08x %s(%s) %s:%d\n", + (DWORD*)*hv, seq, GetCurrentThreadId(), + fn, dsc, fl, ln); + (WriteFile)(fh, sbuf, (DWORD)strlen(sbuf), &wrote, NULL); + } while (--nh); + (LeaveCriticalSection)(&cs); + va_end(a); + } + return ha; +} diff --git a/srclib/apr/misc/win32/rand.c b/srclib/apr/misc/win32/rand.c new file mode 100644 index 0000000000..1dd5d4f841 --- /dev/null +++ b/srclib/apr/misc/win32/rand.c @@ -0,0 +1,68 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_portable.h" +#include "apr_arch_misc.h" +#include + + +APR_DECLARE(apr_status_t) apr_generate_random_bytes(unsigned char * buf, + apr_size_t length) +{ + HCRYPTPROV hProv; + apr_status_t res = APR_SUCCESS; + + /* 0x40 bit = CRYPT_SILENT, only introduced in more recent PSDKs + * and will only work for Win2K and later. + */ + DWORD flags = CRYPT_VERIFYCONTEXT + | ((apr_os_level >= APR_WIN_2000) ? 0x40 : 0); + + if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, flags)) { + return apr_get_os_error(); + } + /* XXX: An ugly hack for Win64, randomness is such that noone should + * ever expect > 2^31 bytes of data at once without the prng + * coming to a complete halt. + */ + if (!CryptGenRandom(hProv, (DWORD)length, buf)) { + res = apr_get_os_error(); + } + CryptReleaseContext(hProv, 0); + return res; +} + + +APR_DECLARE(apr_status_t) apr_os_uuid_get(unsigned char *uuid_data) +{ + /* Note: this call doesn't actually require CoInitialize() first + * + * XXX: we should scramble the bytes or some such to eliminate the + * possible misuse/abuse since uuid is based on the NIC address, and + * is therefore not only a uniqifier, but an identity (which might not + * be appropriate in all cases. + * + * Note that Win2000, XP and later no longer suffer from this problem, + * a scrambling fix is only needed for (apr_os_level < APR_WIN_2000) + */ + if (FAILED(UuidCreate((UUID *)uuid_data))) { + return APR_EGENERAL; + } + return APR_SUCCESS; +} diff --git a/srclib/apr/misc/win32/start.c b/srclib/apr/misc/win32/start.c new file mode 100644 index 0000000000..be43f54e3c --- /dev/null +++ b/srclib/apr/misc/win32/start.c @@ -0,0 +1,223 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_signal.h" +#include "ShellAPI.h" + +#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */ +#include "wchar.h" +#include "apr_arch_file_io.h" +#include "crtdbg.h" +#include "assert.h" + +/* This symbol is _private_, although it must be exported. + */ +int APR_DECLARE_DATA apr_app_init_complete = 0; + +/* Used by apr_app_initialize to reprocess the environment + * + * An internal apr function to convert a double-null terminated set + * of single-null terminated strings from wide Unicode to narrow utf-8 + * as a list of strings. These are allocated from the MSVCRT's + * _CRT_BLOCK to trick the system into trusting our store. + */ +static int warrsztoastr(const char * const * *retarr, + const wchar_t * arrsz, int args) +{ + const apr_wchar_t *wch; + apr_size_t totlen; + apr_size_t newlen; + apr_size_t wsize; + char **newarr; + int arg; + + if (args < 0) { + for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch) + if (!*wch) + ++args; + } + wsize = 1 + wch - arrsz; + + newarr = _malloc_dbg((args + 1) * sizeof(char *), + _CRT_BLOCK, __FILE__, __LINE__); + + /* This is a safe max allocation, we will realloc after + * processing and return the excess to the free store. + * 3 ucs bytes hold any single wchar_t value (16 bits) + * 4 ucs bytes will hold a wchar_t pair value (20 bits) + */ + newlen = totlen = wsize * 3 + 1; + newarr[0] = _malloc_dbg(newlen * sizeof(char), + _CRT_BLOCK, __FILE__, __LINE__); + + (void)apr_conv_ucs2_to_utf8(arrsz, &wsize, + newarr[0], &newlen); + + assert(newlen && !wsize); + /* Return to the free store if the heap realloc is the least bit optimized + */ + newarr[0] = _realloc_dbg(newarr[0], totlen - newlen, + _CRT_BLOCK, __FILE__, __LINE__); + + for (arg = 1; arg < args; ++arg) { + newarr[arg] = newarr[arg - 1] + 2; + while (*(newarr[arg]++)) { + /* continue */; + } + } + + newarr[arg] = NULL; + + *retarr = newarr; + return args; +} + +/* Reprocess the arguments to main() for a completely apr-ized application + */ + +APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, + const char * const * *argv, + const char * const * *env) +{ + apr_status_t rv = apr_initialize(); + + if (rv != APR_SUCCESS) { + return rv; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t **wstrs; + apr_wchar_t *sysstr; + int wstrc; + int dupenv; + + if (apr_app_init_complete) { + return rv; + } + + apr_app_init_complete = 1; + + sysstr = GetCommandLineW(); + if (sysstr) { + wstrs = CommandLineToArgvW(sysstr, &wstrc); + if (wstrs) { + *argc = apr_wastrtoastr(argv, wstrs, wstrc); + GlobalFree(wstrs); + } + } + + sysstr = GetEnvironmentStringsW(); + dupenv = warrsztoastr(&_environ, sysstr, -1); + + if (env) { + *env = _malloc_dbg((dupenv + 1) * sizeof (char *), + _CRT_BLOCK, __FILE__, __LINE__ ); + memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *)); + } + else { + } + + FreeEnvironmentStringsW(sysstr); + + /* MSVCRT will attempt to maintain the wide environment calls + * on _putenv(), which is bogus if we've passed a non-ascii + * string to _putenv(), since they use MultiByteToWideChar + * and breaking the implicit utf-8 assumption we've built. + * + * Reset _wenviron for good measure. + */ + if (_wenviron) { + apr_wchar_t **wenv = _wenviron; + _wenviron = NULL; + free(wenv); + } + + } +#endif + return rv; +} + +static int initialized = 0; + +/* Provide to win32/thread.c */ +extern DWORD tls_apr_thread; + +APR_DECLARE(apr_status_t) apr_initialize(void) +{ + apr_pool_t *pool; + apr_status_t status; + int iVersionRequested; + WSADATA wsaData; + int err; + apr_oslevel_e osver; + + if (initialized++) { + return APR_SUCCESS; + } + + /* Initialize apr_os_level global */ + if (apr_get_oslevel(&osver) != APR_SUCCESS) { + return APR_EEXIST; + } + + tls_apr_thread = TlsAlloc(); + if ((status = apr_pool_initialize()) != APR_SUCCESS) + return status; + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { + return APR_ENOPOOL; + } + + apr_pool_tag(pool, "apr_initialize"); + + iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte); + err = WSAStartup((WORD) iVersionRequested, &wsaData); + if (err) { + return err; + } + if (LOBYTE(wsaData.wVersion) != WSAHighByte || + HIBYTE(wsaData.wVersion) != WSALowByte) { + WSACleanup(); + return APR_EEXIST; + } + + apr_signal_init(pool); + + return APR_SUCCESS; +} + +APR_DECLARE_NONSTD(void) apr_terminate(void) +{ + initialized--; + if (initialized) { + return; + } + apr_pool_terminate(); + + WSACleanup(); + + TlsFree(tls_apr_thread); +} + +APR_DECLARE(void) apr_terminate2(void) +{ + apr_terminate(); +} diff --git a/srclib/apr/misc/win32/utf8.c b/srclib/apr/misc/win32/utf8.c new file mode 100644 index 0000000000..d77e656d36 --- /dev/null +++ b/srclib/apr/misc/win32/utf8.c @@ -0,0 +1,254 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_errno.h" +#include "apr_arch_utf8.h" + +/* Implement the design principal specified by RFC 2718 2.2.5 + * Guidelines for new URL Schemes - within the APR. + * + * Since many architectures support unicode, and UCS2 is the most + * efficient storage used by those archictures, these functions + * exist to validate a UCS string. It is up to the operating system + * to determine the validitity of the string in the context of it's + * native language support. File systems that support filename + * characters of 0x80-0xff but have no support of Unicode will find + * this function useful only for validating the character sequences + * and rejecting poorly encoded strings, if RFC 2718 2.2.5 naming is + * desired. + * + * from RFC 2279 UTF-8, a transformation format of ISO 10646 + * + * UCS-4 range (hex.) UTF-8 octet sequence (binary) + * 1:2 0000 0000-0000 007F 0xxxxxxx + * 2:2 0000 0080-0000 07FF 110XXXXx 10xxxxxx + * 3:2 0000 0800-0000 FFFF 1110XXXX 10Xxxxxx 10xxxxxx + * 4:4 0001 0000-001F FFFF 11110zXX 10XXxxxx 10xxxxxx 10xxxxxx + * inv 0020 0000-03FF FFFF 111110XX 10XXXxxx 10xxxxxx 10xxxxxx 10xxxxxx + * inv 0400 0000-7FFF FFFF 1111110X 10XXXXxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx + * + * One of the X values must be one for the encoding length to be legit. + * Neither the z bit, nor the final two forms, are used for ucs-2 + * + * "Pairs of UCS-2 values between D800 and DFFF (surrogate pairs in + * Unicode parlance), being actually UCS-4 characters transformed + * through UTF-16, need special treatment: the UTF-16 transformation + * must be undone, yielding a UCS-4 character that is then transformed + * as above." + * + * from RFC2781 UTF-16: the compressed ISO 10646 encoding bitmask + * + * U' = U - 0x10000 + * U' = 000000000000yyyyyyyyyyxxxxxxxxxx + * W1 = 110110yyyyyyyyyy + * W2 = 110111xxxxxxxxxx + * + * apr_conv_utf8_to_ucs2 out bytes:sizeof(in) * 1 <= Req <= sizeof(in) * 2 + * + * apr_conv_ucs2_to_utf8 out words:sizeof(in) / 2 <= Req <= sizeof(in) * 3 / 2 + */ + +APR_DECLARE(apr_status_t) apr_conv_utf8_to_ucs2(const char *in, + apr_size_t *inbytes, + apr_wchar_t *out, + apr_size_t *outwords) +{ + apr_int64_t newch, mask; + apr_size_t expect, eating; + int ch; + + while (*inbytes && *outwords) + { + ch = (unsigned char)(*in++); + if (!(ch & 0200)) { + /* US-ASCII-7 plain text + */ + --*inbytes; + --*outwords; + *(out++) = ch; + } + else + { + if ((ch & 0300) != 0300) { + /* Multibyte Continuation is out of place + */ + return APR_EINVAL; + } + else + { + /* Multibyte Sequence Lead Character + * + * Compute the expected bytes while adjusting + * or lead byte and leading zeros mask. + */ + mask = 0340; + expect = 1; + while ((ch & mask) == mask) { + mask |= mask >> 1; + if (++expect > 3) /* (truly 5 for ucs-4) */ + return APR_EINVAL; + } + newch = ch & ~mask; + eating = expect + 1; + if (*inbytes <= expect) + return APR_INCOMPLETE; + /* Reject values of excessive leading 0 bits + * utf-8 _demands_ the shortest possible byte length + */ + if (expect == 1) { + if (!(newch & 0036)) + return APR_EINVAL; + } + else { + /* Reject values of excessive leading 0 bits + */ + if (!newch && !((unsigned char)*in & 0077 & (mask << 1))) + return APR_EINVAL; + if (expect == 2) { + /* Reject values D800-DFFF when not utf16 encoded + * (may not be an appropriate restriction for ucs-4) + */ + if (newch == 0015 && ((unsigned char)*in & 0040)) + return APR_EINVAL; + } + else if (expect == 3) { + /* Short circuit values > 110000 + */ + if (newch > 4) + return APR_EINVAL; + if (newch == 4 && ((unsigned char)*in & 0060)) + return APR_EINVAL; + } + } + /* Where the boolean (expect > 2) is true, we will need + * an extra word for the output. + */ + if (*outwords < (apr_size_t)(expect > 2) + 1) + break; /* buffer full */ + while (expect--) + { + /* Multibyte Continuation must be legal */ + if (((ch = (unsigned char)*(in++)) & 0300) != 0200) + return APR_EINVAL; + newch <<= 6; + newch |= (ch & 0077); + } + *inbytes -= eating; + /* newch is now a true ucs-4 character + * + * now we need to fold to ucs-2 + */ + if (newch < 0x10000) + { + --*outwords; + *(out++) = (apr_wchar_t) newch; + } + else + { + *outwords -= 2; + newch -= 0x10000; + *(out++) = (apr_wchar_t) (0xD800 | (newch >> 10)); + *(out++) = (apr_wchar_t) (0xDC00 | (newch & 0x03FF)); + } + } + } + } + /* Buffer full 'errors' aren't errors, the client must inspect both + * the inbytes and outwords values + */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_conv_ucs2_to_utf8(const apr_wchar_t *in, + apr_size_t *inwords, + char *out, + apr_size_t *outbytes) +{ + apr_int64_t newch, require; + apr_size_t need; + char *invout; + int ch; + + while (*inwords && *outbytes) + { + ch = (unsigned short)(*in++); + if (ch < 0x80) + { + --*inwords; + --*outbytes; + *(out++) = (unsigned char) ch; + } + else + { + if ((ch & 0xFC00) == 0xDC00) { + /* Invalid Leading ucs-2 Multiword Continuation Character + */ + return APR_EINVAL; + } + if ((ch & 0xFC00) == 0xD800) { + /* Leading ucs-2 Multiword Character + */ + if (*inwords < 2) { + /* Missing ucs-2 Multiword Continuation Character + */ + return APR_INCOMPLETE; + } + if (((unsigned short)(*in) & 0xFC00) != 0xDC00) { + /* Invalid ucs-2 Multiword Continuation Character + */ + return APR_EINVAL; + } + newch = (ch & 0x03FF) << 10 | ((unsigned short)(*in++) & 0x03FF); + newch += 0x10000; + } + else { + /* ucs-2 Single Word Character + */ + newch = ch; + } + /* Determine the absolute minimum utf-8 bytes required + */ + require = newch >> 11; + need = 1; + while (require) + require >>= 5, ++need; + if (need >= *outbytes) + break; /* Insufficient buffer */ + *inwords -= (need > 2) + 1; + *outbytes -= need + 1; + /* Compute the utf-8 characters in last to first order, + * calculating the lead character length bits along the way. + */ + ch = 0200; + out += need + 1; + invout = out; + while (need--) { + ch |= ch >> 1; + *(--invout) = (unsigned char)(0200 | (newch & 0077)); + newch >>= 6; + } + /* Compute the lead utf-8 character and move the dest offset + */ + *(--invout) = (unsigned char)(ch | newch); + } + } + /* Buffer full 'errors' aren't errors, the client must inspect both + * the inwords and outbytes values + */ + return APR_SUCCESS; +} diff --git a/srclib/apr/mmap/unix/common.c b/srclib/apr/mmap/unix/common.c new file mode 100644 index 0000000000..b300a993d9 --- /dev/null +++ b/srclib/apr/mmap/unix/common.c @@ -0,0 +1,43 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* common .c + * This file has any function that is truly common and platform + * neutral. Or at least that's the theory. + * + * The header files are a problem so there are a few #ifdef's to take + * care of those. + * + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_mmap.h" +#include "apr_errno.h" + +#if APR_HAS_MMAP || defined(BEOS) + +APR_DECLARE(apr_status_t) apr_mmap_offset(void **addr, apr_mmap_t *mmap, + apr_off_t offset) +{ + if (offset < 0 || offset > mmap->size) + return APR_EINVAL; + + (*addr) = (char *) mmap->mm + offset; + return APR_SUCCESS; +} + +#endif diff --git a/srclib/apr/mmap/unix/mmap.c b/srclib/apr/mmap/unix/mmap.c new file mode 100644 index 0000000000..fdce7fa7f0 --- /dev/null +++ b/srclib/apr/mmap/unix/mmap.c @@ -0,0 +1,172 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_mmap.h" +#include "apr_errno.h" +#include "apr_arch_file_io.h" +#include "apr_portable.h" + +/* System headers required for the mmap library */ +#ifdef BEOS +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STDIO_H +#include +#endif +#ifdef HAVE_SYS_STAT_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif + +#if APR_HAS_MMAP || defined(BEOS) + +static apr_status_t mmap_cleanup(void *themmap) +{ + apr_mmap_t *mm = themmap; + apr_mmap_t *next = APR_RING_NEXT(mm,link); + int rv = 0; + + /* we no longer refer to the mmaped region */ + APR_RING_REMOVE(mm,link); + APR_RING_NEXT(mm,link) = NULL; + APR_RING_PREV(mm,link) = NULL; + + if (next != mm) { + /* more references exist, so we're done */ + return APR_SUCCESS; + } + +#ifdef BEOS + rv = delete_area(mm->area); +#else + rv = munmap(mm->mm, mm->size); +#endif + mm->mm = (void *)-1; + + if (rv == 0) { + return APR_SUCCESS; + } + return errno; +} + +APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, + apr_file_t *file, apr_off_t offset, + apr_size_t size, apr_int32_t flag, + apr_pool_t *cont) +{ + void *mm; +#ifdef BEOS + area_id aid = -1; + uint32 pages = 0; +#else + apr_int32_t native_flags = 0; +#endif + +#if APR_HAS_LARGE_FILES && defined(HAVE_MMAP64) +#define mmap mmap64 +#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4 + /* LFS but no mmap64: check for overflow */ + if ((apr_int64_t)offset + size > INT_MAX) + return APR_EINVAL; +#endif + + if (size == 0) + return APR_EINVAL; + + if (file == NULL || file->filedes == -1 || file->buffered) + return APR_EBADF; + (*new) = (apr_mmap_t *)apr_pcalloc(cont, sizeof(apr_mmap_t)); + +#ifdef BEOS + /* XXX: mmap shouldn't really change the seek offset */ + apr_file_seek(file, APR_SET, &offset); + + /* There seems to be some strange interactions that mean our area must + * be set as READ & WRITE or writev will fail! Go figure... + * So we ignore the value in flags and always ask for both READ and WRITE + */ + pages = (size + B_PAGE_SIZE -1) / B_PAGE_SIZE; + aid = create_area("apr_mmap", &mm , B_ANY_ADDRESS, pages * B_PAGE_SIZE, + B_NO_LOCK, B_WRITE_AREA|B_READ_AREA); + + if (aid < B_NO_ERROR) { + /* we failed to get an area we can use... */ + *new = NULL; + return APR_ENOMEM; + } + + if (aid >= B_NO_ERROR) + read(file->filedes, mm, size); + + (*new)->area = aid; +#else + + if (flag & APR_MMAP_WRITE) { + native_flags |= PROT_WRITE; + } + if (flag & APR_MMAP_READ) { + native_flags |= PROT_READ; + } + + mm = mmap(NULL, size, native_flags, MAP_SHARED, file->filedes, offset); + + if (mm == (void *)-1) { + /* we failed to get an mmap'd file... */ + *new = NULL; + return errno; + } +#endif + + (*new)->mm = mm; + (*new)->size = size; + (*new)->cntxt = cont; + APR_RING_ELEM_INIT(*new, link); + + /* register the cleanup... */ + apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap, + apr_mmap_t *old_mmap, + apr_pool_t *p) +{ + *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t)); + (*new_mmap)->cntxt = p; + + APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link); + + apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm) +{ + return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup); +} + +#endif diff --git a/srclib/apr/mmap/win32/mmap.c b/srclib/apr/mmap/win32/mmap.c new file mode 100644 index 0000000000..4db585281b --- /dev/null +++ b/srclib/apr/mmap/win32/mmap.c @@ -0,0 +1,162 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" +#include "apr_general.h" +#include "apr_mmap.h" +#include "apr_errno.h" +#include "apr_arch_file_io.h" +#include "apr_portable.h" +#include "apr_strings.h" + +#if APR_HAS_MMAP + +static apr_status_t mmap_cleanup(void *themmap) +{ + apr_mmap_t *mm = themmap; + apr_mmap_t *next = APR_RING_NEXT(mm,link); + apr_status_t rv = 0; + + /* we no longer refer to the mmaped region */ + APR_RING_REMOVE(mm,link); + APR_RING_NEXT(mm,link) = NULL; + APR_RING_PREV(mm,link) = NULL; + + if (next != mm) { + /* more references exist, so we're done */ + return APR_SUCCESS; + } + + if (mm->mv) { + if (!UnmapViewOfFile(mm->mv)) + { + apr_status_t rv = apr_get_os_error(); + CloseHandle(mm->mhandle); + mm->mv = NULL; + mm->mhandle = NULL; + return rv; + } + mm->mv = NULL; + } + if (mm->mhandle) + { + if (!CloseHandle(mm->mhandle)) + { + apr_status_t rv = apr_get_os_error(); + CloseHandle(mm->mhandle); + mm->mhandle = NULL; + return rv; + } + mm->mhandle = NULL; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_mmap_create(apr_mmap_t **new, apr_file_t *file, + apr_off_t offset, apr_size_t size, + apr_int32_t flag, apr_pool_t *cont) +{ + static DWORD memblock = 0; + DWORD fmaccess = 0; + DWORD mvaccess = 0; + DWORD offlo; + DWORD offhi; + + if (size == 0) + return APR_EINVAL; + + if (flag & APR_MMAP_WRITE) + fmaccess |= PAGE_READWRITE; + else if (flag & APR_MMAP_READ) + fmaccess |= PAGE_READONLY; + + if (flag & APR_MMAP_READ) + mvaccess |= FILE_MAP_READ; + if (flag & APR_MMAP_WRITE) + mvaccess |= FILE_MAP_WRITE; + + if (!file || !file->filehand || file->filehand == INVALID_HANDLE_VALUE + || file->buffered) + return APR_EBADF; + + if (!memblock) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + memblock = si.dwAllocationGranularity; + } + + *new = apr_pcalloc(cont, sizeof(apr_mmap_t)); + (*new)->pstart = (offset / memblock) * memblock; + (*new)->poffset = offset - (*new)->pstart; + (*new)->psize = (apr_size_t)((*new)->poffset) + size; + /* The size of the CreateFileMapping object is the current size + * of the size of the mmap object (e.g. file size), not the size + * of the mapped region! + */ + + (*new)->mhandle = CreateFileMapping(file->filehand, NULL, fmaccess, + 0, 0, NULL); + if (!(*new)->mhandle || (*new)->mhandle == INVALID_HANDLE_VALUE) + { + *new = NULL; + return apr_get_os_error(); + } + + offlo = (DWORD)(*new)->pstart; + offhi = (DWORD)((*new)->pstart >> 32); + (*new)->mv = MapViewOfFile((*new)->mhandle, mvaccess, offhi, + offlo, (*new)->psize); + if (!(*new)->mv) + { + apr_status_t rv = apr_get_os_error(); + CloseHandle((*new)->mhandle); + *new = NULL; + return rv; + } + + (*new)->mm = (char*)((*new)->mv) + (*new)->poffset; + (*new)->size = size; + (*new)->cntxt = cont; + APR_RING_ELEM_INIT(*new, link); + + /* register the cleanup... */ + apr_pool_cleanup_register((*new)->cntxt, (void*)(*new), mmap_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_mmap_dup(apr_mmap_t **new_mmap, + apr_mmap_t *old_mmap, + apr_pool_t *p) +{ + *new_mmap = (apr_mmap_t *)apr_pmemdup(p, old_mmap, sizeof(apr_mmap_t)); + (*new_mmap)->cntxt = p; + + APR_RING_INSERT_AFTER(old_mmap, *new_mmap, link); + + apr_pool_cleanup_register(p, *new_mmap, mmap_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_mmap_delete(apr_mmap_t *mm) +{ + return apr_pool_cleanup_run(mm->cntxt, mm, mmap_cleanup); +} + +#endif diff --git a/srclib/apr/network_io/beos/sendrecv.c b/srclib/apr/network_io/beos/sendrecv.c new file mode 100644 index 0000000000..6378a3aaa9 --- /dev/null +++ b/srclib/apr/network_io/beos/sendrecv.c @@ -0,0 +1,214 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#if BEOS_BONE /* BONE uses the unix code - woohoo */ +#include "../unix/sendrecv.c" +#else +#include "apr_arch_networkio.h" +#include "apr_time.h" + +static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read) +{ + struct timeval tv, *tvptr; + fd_set fdset; + int srv; + + do { + FD_ZERO(&fdset); + FD_SET(sock->socketdes, &fdset); + if (sock->timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = sock->timeout / APR_USEC_PER_SEC; + tv.tv_usec = sock->timeout % APR_USEC_PER_SEC; + tvptr = &tv; + } + srv = select(sock->socketdes + 1, + for_read ? &fdset : NULL, + for_read ? NULL : &fdset, + NULL, + tvptr); + /* TODO - timeout should be smaller on repeats of this loop */ + } while (srv == -1 && errno == EINTR); + + if (srv == 0) { + return APR_TIMEUP; + } + else if (srv < 0) { + return errno; + } + return APR_SUCCESS; +} + +#define SEND_WAIT APR_USEC_PER_SEC / 10 + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = send(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + apr_int32_t snooze_val = SEND_WAIT; + apr_int32_t zzz = 0; + + do { + rv = send(sock->socketdes, buf, (*len), 0); + if (rv == -1 && errno == EWOULDBLOCK){ + apr_sleep (snooze_val); + zzz += snooze_val; + snooze_val += SEND_WAIT; + /* have we passed our timeout value */ + if (zzz > (sock->timeout * APR_USEC_PER_SEC)) + break; + } + } while (rv == -1 && (errno == EINTR || errno == EWOULDBLOCK)); + } + if (rv == -1) { + *len = 0; + return errno; + } + (*len) = rv; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = recv(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + apr_status_t arv = wait_for_io_or_timeout(sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = recv(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + (*len) = rv; + if (rv == 0) + return APR_EOF; + return APR_SUCCESS; +} + +/* BeOS doesn't have writev for sockets so we use the following instead... + */ +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t * sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + *len = vec[0].iov_len; + return apr_socket_send(sock, vec[0].iov_base, len); +} + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) + && sock->timeout != 0) { + apr_status_t arv = wait_for_io_or_timeout(sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + *len = rv; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + if (from == NULL){ + return APR_ENOMEM; + /* Not sure if this is correct. Maybe we should just allocate + the memory?? + */ + } + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + + if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && + sock->timeout != 0) { + apr_status_t arv = wait_for_io_or_timeout(sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + + (*len) = rv; + if (rv == 0) + return APR_EOF; + + return APR_SUCCESS; +} + +#endif /* ! BEOS_BONE */ diff --git a/srclib/apr/network_io/beos/socketcommon.c b/srclib/apr/network_io/beos/socketcommon.c new file mode 100644 index 0000000000..cdadc8561a --- /dev/null +++ b/srclib/apr/network_io/beos/socketcommon.c @@ -0,0 +1,5 @@ +#include "../unix/inet_ntop.c" +#include "../unix/inet_pton.c" +#include "../unix/sockets.c" +#include "../unix/sockaddr.c" +#include "../unix/sockopt.c" diff --git a/srclib/apr/network_io/os2/inet_ntop.c b/srclib/apr/network_io/os2/inet_ntop.c new file mode 100644 index 0000000000..f1f79d4948 --- /dev/null +++ b/srclib/apr/network_io/os2/inet_ntop.c @@ -0,0 +1 @@ +#include "../unix/inet_ntop.c" diff --git a/srclib/apr/network_io/os2/inet_pton.c b/srclib/apr/network_io/os2/inet_pton.c new file mode 100644 index 0000000000..dbd3ac454b --- /dev/null +++ b/srclib/apr/network_io/os2/inet_pton.c @@ -0,0 +1 @@ +#include "../unix/inet_pton.c" diff --git a/srclib/apr/network_io/os2/os2calls.c b/srclib/apr/network_io/os2/os2calls.c new file mode 100644 index 0000000000..ef204ca7a8 --- /dev/null +++ b/srclib/apr/network_io/os2/os2calls.c @@ -0,0 +1,132 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_portable.h" +#include "apr_general.h" +#include "apr_lib.h" + +static int os2_socket_init(int, int ,int); + +int (*apr_os2_socket)(int, int, int) = os2_socket_init; +int (*apr_os2_select)(int *, int, int, int, long) = NULL; +int (*apr_os2_sock_errno)() = NULL; +int (*apr_os2_accept)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_bind)(int, struct sockaddr *, int) = NULL; +int (*apr_os2_connect)(int, struct sockaddr *, int) = NULL; +int (*apr_os2_getpeername)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_getsockname)(int, struct sockaddr *, int *) = NULL; +int (*apr_os2_getsockopt)(int, int, int, char *, int *) = NULL; +int (*apr_os2_ioctl)(int, int, caddr_t, int) = NULL; +int (*apr_os2_listen)(int, int) = NULL; +int (*apr_os2_recv)(int, char *, int, int) = NULL; +int (*apr_os2_send)(int, const char *, int, int) = NULL; +int (*apr_os2_setsockopt)(int, int, int, char *, int) = NULL; +int (*apr_os2_shutdown)(int, int) = NULL; +int (*apr_os2_soclose)(int) = NULL; +int (*apr_os2_writev)(int, struct iovec *, int) = NULL; +int (*apr_os2_sendto)(int, const char *, int, int, const struct sockaddr *, int); +int (*apr_os2_recvfrom)(int, char *, int, int, struct sockaddr *, int *); + +static HMODULE hSO32DLL; + +static int os2_fn_link() +{ + DosEnterCritSec(); /* Stop two threads doing this at the same time */ + + if (apr_os2_socket == os2_socket_init) { + ULONG rc; + char errorstr[200]; + + rc = DosLoadModule(errorstr, sizeof(errorstr), "SO32DLL", &hSO32DLL); + + if (rc) + return APR_OS2_STATUS(rc); + + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCKET", &apr_os2_socket); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SELECT", &apr_os2_select); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCK_ERRNO", &apr_os2_sock_errno); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "ACCEPT", &apr_os2_accept); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "BIND", &apr_os2_bind); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "CONNECT", &apr_os2_connect); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETPEERNAME", &apr_os2_getpeername); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETSOCKNAME", &apr_os2_getsockname); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "GETSOCKOPT", &apr_os2_getsockopt); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "IOCTL", &apr_os2_ioctl); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "LISTEN", &apr_os2_listen); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "RECV", &apr_os2_recv); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SEND", &apr_os2_send); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SETSOCKOPT", &apr_os2_setsockopt); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SHUTDOWN", &apr_os2_shutdown); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SOCLOSE", &apr_os2_soclose); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "WRITEV", &apr_os2_writev); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "SENDTO", &apr_os2_sendto); + + if (!rc) + rc = DosQueryProcAddr(hSO32DLL, 0, "RECVFROM", &apr_os2_recvfrom); + + if (rc) + return APR_OS2_STATUS(rc); + } + + DosExitCritSec(); + return APR_SUCCESS; +} + + + +static int os2_socket_init(int domain, int type, int protocol) +{ + int rc = os2_fn_link(); + if (rc == APR_SUCCESS) + return apr_os2_socket(domain, type, protocol); + return rc; +} diff --git a/srclib/apr/network_io/os2/sendrecv.c b/srclib/apr/network_io/os2/sendrecv.c new file mode 100644 index 0000000000..a762b7dc31 --- /dev/null +++ b/srclib/apr/network_io/os2/sendrecv.c @@ -0,0 +1,151 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_lib.h" +#include + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int fds, err = 0; + + do { + if (!sock->nonblock || err == SOCEWOULDBLOCK) { + fds = sock->socketdes; + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = send(sock->socketdes, buf, (*len), 0); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || err == SOCEWOULDBLOCK); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + (*len) = rv; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int fds, err = 0; + + do { + if (!sock->nonblock || (err == SOCEWOULDBLOCK && sock->timeout != 0)) { + fds = sock->socketdes; + rv = select(&fds, 1, 0, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = recv(sock->socketdes, buf, (*len), 0); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || (err == SOCEWOULDBLOCK && sock->timeout != 0)); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + (*len) = rv; + return rv == 0 ? APR_EOF : APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + apr_status_t rv; + struct iovec *tmpvec; + int fds, err = 0; + int nv_tosend, total = 0; + + /* Make sure writev() only gets fed 64k at a time */ + for ( nv_tosend = 0; nv_tosend < nvec && total + vec[nv_tosend].iov_len < 65536; nv_tosend++ ) { + total += vec[nv_tosend].iov_len; + } + + tmpvec = alloca(sizeof(struct iovec) * nv_tosend); + memcpy(tmpvec, vec, sizeof(struct iovec) * nv_tosend); + + do { + if (!sock->nonblock || err == SOCEWOULDBLOCK) { + fds = sock->socketdes; + rv = select(&fds, 0, 1, 0, sock->timeout >= 0 ? sock->timeout/1000 : -1); + + if (rv != 1) { + *len = 0; + err = sock_errno(); + + if (rv == 0) + return APR_TIMEUP; + + if (err == SOCEINTR) + continue; + + return APR_OS2_STATUS(err); + } + } + + rv = writev(sock->socketdes, tmpvec, nv_tosend); + err = rv < 0 ? sock_errno() : 0; + } while (err == SOCEINTR || err == SOCEWOULDBLOCK); + + if (err) { + *len = 0; + return APR_OS2_STATUS(err); + } + + *len = rv; + return APR_SUCCESS; +} diff --git a/srclib/apr/network_io/os2/sendrecv_udp.c b/srclib/apr/network_io/os2/sendrecv_udp.c new file mode 100644 index 0000000000..7a79e715dc --- /dev/null +++ b/srclib/apr/network_io/os2/sendrecv_udp.c @@ -0,0 +1,104 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_support.h" +#include "apr_lib.h" +#include + + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int serrno; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + + if (rv == -1 && serrno == SOCEWOULDBLOCK && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, *len, flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && (serrno = sock_errno()) == SOCEINTR); + } + } + + if (rv == -1) { + *len = 0; + return APR_FROM_OS_ERROR(serrno); + } + + *len = rv; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + int serrno; + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + + if (rv == -1 && serrno == SOCEWOULDBLOCK && sock->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, *len, flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && (serrno = sock_errno()) == EINTR); + } + } + + if (rv == -1) { + (*len) = 0; + return APR_FROM_OS_ERROR(serrno); + } + + (*len) = rv; + + if (rv == 0 && sock->type == SOCK_STREAM) + return APR_EOF; + + return APR_SUCCESS; +} diff --git a/srclib/apr/network_io/os2/sockaddr.c b/srclib/apr/network_io/os2/sockaddr.c new file mode 100644 index 0000000000..2afe4b77c0 --- /dev/null +++ b/srclib/apr/network_io/os2/sockaddr.c @@ -0,0 +1 @@ +#include "../unix/sockaddr.c" diff --git a/srclib/apr/network_io/os2/sockets.c b/srclib/apr/network_io/os2/sockets.c new file mode 100644 index 0000000000..aeaef0db01 --- /dev/null +++ b/srclib/apr/network_io/os2/sockets.c @@ -0,0 +1,309 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_arch_inherit.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_portable.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include +#include +#include +#include +#include +#include +#include +#include "apr_arch_os2calls.h" + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (thesocket->socketdes < 0) { + return APR_EINVALSOCK; + } + + if (soclose(thesocket->socketdes) == 0) { + thesocket->socketdes = -1; + return APR_SUCCESS; + } + else { + return APR_OS2_STATUS(sock_errno()); + } +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); +} + +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); +} + +APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, int type, + int protocol, apr_pool_t *cont) +{ + int downgrade = (family == AF_UNSPEC); + apr_pollfd_t pfd; + + if (family == AF_UNSPEC) { +#if APR_HAVE_IPV6 + family = AF_INET6; +#else + family = AF_INET; +#endif + } + + alloc_socket(new, cont); + + (*new)->socketdes = socket(family, type, protocol); +#if APR_HAVE_IPV6 + if ((*new)->socketdes < 0 && downgrade) { + family = AF_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes < 0) { + return APR_OS2_STATUS(sock_errno()); + } + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->nonblock = FALSE; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + if (shutdown(thesocket->socketdes, how) == 0) { + return APR_SUCCESS; + } + else { + return APR_OS2_STATUS(sock_errno()); + } +} + +APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket) +{ + apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup); + return socket_cleanup(thesocket); +} + +APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, + sa->salen) == -1) + return APR_OS2_STATUS(sock_errno()); + else { + sock->local_addr = sa; + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == -1) + return APR_OS2_STATUS(sock_errno()); + else + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, + apr_socket_t *sock, + apr_pool_t *connection_context) +{ + alloc_socket(new, connection_context); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol); + + (*new)->timeout = -1; + (*new)->nonblock = FALSE; + + (*new)->socketdes = accept(sock->socketdes, + (struct sockaddr *)&(*new)->remote_addr->sa, + &(*new)->remote_addr->salen); + + if ((*new)->socketdes < 0) { + return APR_OS2_STATUS(sock_errno()); + } + + *(*new)->local_addr = *sock->local_addr; + (*new)->local_addr->pool = connection_context; + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if ((connect(sock->socketdes, (struct sockaddr *)&sa->sa.sin, + sa->salen) < 0) && + (sock_errno() != SOCEINPROGRESS)) { + return APR_OS2_STATUS(sock_errno()); + } + else { + int namelen = sizeof(sock->local_addr->sa.sin); + getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa.sin, + &namelen); + sock->remote_addr = sa; + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type) +{ + *type = sock->type; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, + apr_status_t (*cleanup) (void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); + (*apr_sock)->timeout = -1; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, apr_pool_t *cont) +{ + if (cont == NULL) { + return APR_ENOPOOL; + } + if ((*sock) == NULL) { + alloc_socket(sock, cont); + set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + } + + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + +APR_IMPLEMENT_INHERIT_SET(socket, inherit, cntxt, socket_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, cntxt, socket_cleanup) + diff --git a/srclib/apr/network_io/os2/sockopt.c b/srclib/apr/network_io/os2/sockopt.c new file mode 100644 index 0000000000..5f8a70371c --- /dev/null +++ b/srclib/apr/network_io/os2/sockopt.c @@ -0,0 +1,139 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, + apr_interval_time_t t) +{ + sock->timeout = t; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + struct linger li; + + if (on) + one = 1; + else + one = 0; + + if (opt & APR_SO_KEEPALIVE) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_DEBUG) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_REUSEADDR) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_SNDBUF) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_SO_NONBLOCK) { + if (ioctl(sock->socketdes, FIONBIO, (caddr_t)&one, sizeof(one)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } else { + sock->nonblock = one; + } + } + if (opt & APR_SO_LINGER) { + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + if (opt & APR_TCP_NODELAY) { + if (setsockopt(sock->socketdes, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(int)) == -1) { + return APR_OS2_STATUS(sock_errno()); + } + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, + apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch(opt) { + default: + return APR_EINVAL; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ + int oobmark; + + if (ioctl(sock->socketdes, SIOCATMARK, (void*)&oobmark, sizeof(oobmark)) < 0) { + return APR_OS2_STATUS(sock_errno()); + } + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_gethostname(char *buf, apr_int32_t len, + apr_pool_t *cont) +{ + if (gethostname(buf, len) == -1) { + buf[0] = '\0'; + return APR_OS2_STATUS(sock_errno()); + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} diff --git a/srclib/apr/network_io/unix/inet_ntop.c b/srclib/apr/network_io/unix/inet_ntop.c new file mode 100644 index 0000000000..451e9a0fb7 --- /dev/null +++ b/srclib/apr/network_io/unix/inet_ntop.c @@ -0,0 +1,245 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "apr_private.h" +#include "apr_arch_networkio.h" +#include "apr_strings.h" + +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_SOCKET_H +#include +#endif +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif +#include +#if APR_HAVE_ERRNO_H +#include +#endif +#include + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif + +#ifndef INT16SZ +#define INT16SZ sizeof(apr_int16_t) +#endif + +#ifndef __P +#define __P(x) x +#endif + +#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT) +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __P((const unsigned char *src, char *dst, apr_size_t size)); +#if APR_HAVE_IPV6 +static const char *inet_ntop6 __P((const unsigned char *src, char *dst, apr_size_t size)); +#endif + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +apr_inet_ntop(int af, const void *src, char *dst, apr_size_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#if APR_HAVE_IPV6 + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(const unsigned char *src, char *dst, apr_size_t size) +{ + const apr_size_t MIN_SIZE = 16; /* space for 255.255.255.255\0 */ + int n = 0; + char *next = dst; + + if (size < MIN_SIZE) { + errno = ENOSPC; + return NULL; + } + do { + unsigned char u = *src++; + if (u > 99) { + *next++ = '0' + u/100; + u %= 100; + *next++ = '0' + u/10; + u %= 10; + } + else if (u > 9) { + *next++ = '0' + u/10; + u %= 10; + } + *next++ = '0' + u; + *next++ = '.'; + n++; + } while (n < 4); + *--next = 0; + return dst; +} + +#if APR_HAVE_IPV6 +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(const unsigned char *src, char *dst, apr_size_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + unsigned int words[IN6ADDRSZ / INT16SZ]; + int i; + const unsigned char *next_src, *src_end; + unsigned int *next_dest; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + next_src = src; + src_end = src + IN6ADDRSZ; + next_dest = words; + best.base = -1; + cur.base = -1; + i = 0; + do { + unsigned int next_word = (unsigned int)*next_src++; + next_word <<= 8; + next_word |= (unsigned int)*next_src++; + *next_dest++ = next_word; + + if (next_word == 0) { + if (cur.base == -1) { + cur.base = i; + cur.len = 1; + } + else { + cur.len++; + } + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) { + best = cur; + } + cur.base = -1; + } + } + + i++; + } while (next_src < src_end); + + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) { + best = cur; + } + } + if (best.base != -1 && best.len < 2) { + best.base = -1; + } + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ);) { + /* Are we inside the best run of 0x00's? */ + if (i == best.base) { + *tp++ = ':'; + i += best.len; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) { + *tp++ = ':'; + } + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) { + return (NULL); + } + tp += strlen(tp); + break; + } + tp += apr_snprintf(tp, sizeof tmp - (tp - tmp), "%x", words[i]); + i++; + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) { + *tp++ = ':'; + } + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((apr_size_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif diff --git a/srclib/apr/network_io/unix/inet_pton.c b/srclib/apr/network_io/unix/inet_pton.c new file mode 100644 index 0000000000..22b15390fc --- /dev/null +++ b/srclib/apr/network_io/unix/inet_pton.c @@ -0,0 +1,240 @@ +/* Copyright (c) 1996 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include "apr_private.h" +#include "apr_arch_networkio.h" + +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_SYS_SOCKET_H +#include +#endif +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif +#include +#if APR_HAVE_ERRNO_H +#include +#endif + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif + +#ifndef INT16SZ +#define INT16SZ sizeof(apr_int16_t) +#endif + +#ifndef INADDRSZ +#define INADDRSZ 4 +#endif + +#ifndef __P +#define __P(x) x +#endif + +#if !defined(EAFNOSUPPORT) && defined(WSAEAFNOSUPPORT) +#define EAFNOSUPPORT WSAEAFNOSUPPORT +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __P((const char *src, unsigned char *dst)); +#if APR_HAVE_IPV6 +static int inet_pton6 __P((const char *src, unsigned char *dst)); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ +int +apr_inet_pton(int af, const char *src, void *dst) +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#if APR_HAVE_IPV6 + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(const char *src, unsigned char *dst) +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + unsigned char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + unsigned int new = *tp * 10 + (unsigned int)(pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#if APR_HAVE_IPV6 +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(const char *src, unsigned char *dst) +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + unsigned char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + unsigned int val; + + memset((tp = tmp), '\0', IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + INT16SZ > endp) + return (0); + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif diff --git a/srclib/apr/network_io/unix/multicast.c b/srclib/apr/network_io/unix/multicast.c new file mode 100644 index 0000000000..eb4304f07c --- /dev/null +++ b/srclib/apr/network_io/unix/multicast.c @@ -0,0 +1,332 @@ +/* Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_support.h" +#include "apr_portable.h" +#include "apr_arch_inherit.h" + +#ifdef HAVE_GETIFADDRS +#include +#include +#endif + +#ifdef HAVE_STRUCT_IPMREQ +/* Only UDP and Raw Sockets can be used for Multicast */ +static apr_status_t mcast_check_type(apr_socket_t *sock) +{ + int type; + apr_status_t rv; + + rv = apr_socket_type_get(sock, &type); + + if (rv != APR_SUCCESS) { + return rv; + } + else if (type == SOCK_DGRAM || type == SOCK_RAW) { + return APR_SUCCESS; + } + else { + return APR_ENOTIMPL; + } +} + +static void fill_mip_v4(struct ip_mreq *mip, apr_sockaddr_t *mcast, + apr_sockaddr_t *iface) +{ + mip->imr_multiaddr = mcast->sa.sin.sin_addr; + if (iface == NULL) { + mip->imr_interface.s_addr = INADDR_ANY; + } + else { + mip->imr_interface = iface->sa.sin.sin_addr; + } +} + +#if APR_HAVE_IPV6 +static unsigned int find_if_index(const apr_sockaddr_t *iface) +{ + unsigned int index = 0; +#ifdef HAVE_GETIFADDRS + struct ifaddrs *ifp, *ifs; + + /** + * TODO: getifaddrs is only portable to *BSD and OS X. Using ioctl + * and SIOCGIFCONF is needed for Linux/Solaris support. + * + * There is a wrapper that takes the messy ioctl interface into + * getifaddrs. The license is acceptable, but, It is a fairly large + * chunk of code. + */ + if (getifaddrs(&ifs) != 0) { + return 0; + } + + for (ifp = ifs; ifp; ifp = ifp->ifa_next) { + if (ifp->ifa_addr != NULL && ifp->ifa_addr->sa_family == AF_INET6) { + if (memcmp(&iface->sa.sin6.sin6_addr, + &ifp->ifa_addr->sa_data[0], + sizeof(iface->sa.sin6.sin6_addr)) == 0) { + index = if_nametoindex(ifp->ifa_name); + break; + } + } + } + + freeifaddrs(ifs); +#endif + return index; +} + +static void fill_mip_v6(struct ipv6_mreq *mip, const apr_sockaddr_t *mcast, + const apr_sockaddr_t *iface) +{ + memcpy(&mip->ipv6mr_multiaddr, mcast->ipaddr_ptr, + sizeof(mip->ipv6mr_multiaddr)); + + if (iface == NULL) { + mip->ipv6mr_interface = 0; + } + else { + mip->ipv6mr_interface = find_if_index(iface); + } +} + +#endif + +static int sock_is_ipv4(apr_socket_t *sock) +{ + if (sock->local_addr->family == APR_INET) + return 1; + return 0; +} + +#if APR_HAVE_IPV6 +static int sock_is_ipv6(apr_socket_t *sock) +{ + if (sock->local_addr->family == APR_INET6) + return 1; + return 0; +} +#endif + +static apr_status_t do_mcast(int type, apr_socket_t *sock, + apr_sockaddr_t *mcast, apr_sockaddr_t *iface, + apr_sockaddr_t *source) +{ + struct ip_mreq mip4; + apr_status_t rv = APR_SUCCESS; +#if APR_HAVE_IPV6 + struct ipv6_mreq mip6; +#endif +#if MCAST_JOIN_SOURCE_GROUP + struct group_source_req mip; + int ip_proto; +#endif + + rv = mcast_check_type(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + + if (source != NULL) { +#if MCAST_JOIN_SOURCE_GROUP + if (sock_is_ipv6(sock)) + ip_proto = IPPROTO_IP; + else if (sock_is_ipv6(sock)) + ip_proto = IPPROTO_IPV6; + else + return APR_ENOTIMPL; + + if (type == IP_ADD_MEMBERSHIP) + type = MCAST_JOIN_SOURCE_GROUP; + else if (type == IP_DROP_MEMBERSHIP) + type = MCAST_LEAVE_SOURCE_GROUP; + else + return APR_ENOTIMPL; + + mip.gsr_interface = find_if_index(iface); + memcpy(&mip.gsr_group, mcast->ipaddr_ptr, sizeof(mip.gsr_group)); + memcpy(&mip.gsr_source, source->ipaddr_ptr, sizeof(mip.gsr_source)); + + if (setsockopt(sock->socketdes, ip_proto, type, (const void *) &mip, + sizeof(mip)) == -1) { + rv = errno; + } +#else + /* We do not support Source-Specific Multicast. */ + return APR_ENOTIMPL; +#endif + } + else { + if (sock_is_ipv4(sock)) { + + fill_mip_v4(&mip4, mcast, iface); + + if (setsockopt(sock->socketdes, IPPROTO_IP, type, + (const void *) &mip4, sizeof(mip4)) == -1) { + rv = errno; + } + } +#if APR_HAVE_IPV6 + else if (sock_is_ipv6(sock)) { + if (type == IP_ADD_MEMBERSHIP) { + type = IPV6_JOIN_GROUP; + } + else if (type == IP_DROP_MEMBERSHIP) { + type = IPV6_LEAVE_GROUP; + } + else { + return APR_ENOTIMPL; + } + + fill_mip_v6(&mip6, mcast, iface); + + if (setsockopt(sock->socketdes, IPPROTO_IPV6, type, + &mip6, sizeof(mip6)) == -1) { + rv = errno; + } + } +#endif + else { + rv = APR_ENOTIMPL; + } + } + return rv; +} + +static apr_status_t do_mcast_opt(int type, apr_socket_t *sock, + apr_byte_t value) +{ + apr_status_t rv = APR_SUCCESS; + + rv = mcast_check_type(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + + if (sock_is_ipv4(sock)) { + if (setsockopt(sock->socketdes, IPPROTO_IP, type, + (const void *) &value, sizeof(value)) == -1) { + rv = errno; + } + } +#if APR_HAVE_IPV6 + else if (sock_is_ipv6(sock) && type == IP_MULTICAST_LOOP) { + unsigned int loopopt = value; + type = IPV6_MULTICAST_LOOP; + if (setsockopt(sock->socketdes, IPPROTO_IPV6, type, + &loopopt, sizeof(loopopt)) == -1) { + rv = errno; + } + } + else if (sock_is_ipv6(sock)) { + if (type == IP_MULTICAST_TTL) { + type = IPV6_MULTICAST_HOPS; + } + else { + return APR_ENOTIMPL; + } + + if (setsockopt(sock->socketdes, IPPROTO_IPV6, type, + &value, sizeof(value)) == -1) { + rv = errno; + } + } +#endif + else { + rv = APR_ENOTIMPL; + } + + return rv; +} +#endif + +APR_DECLARE(apr_status_t) apr_mcast_join(apr_socket_t *sock, + apr_sockaddr_t *join, + apr_sockaddr_t *iface, + apr_sockaddr_t *source) +{ +#if defined(IP_ADD_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ) + return do_mcast(IP_ADD_MEMBERSHIP, sock, join, iface, source); +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_mcast_leave(apr_socket_t *sock, + apr_sockaddr_t *addr, + apr_sockaddr_t *iface, + apr_sockaddr_t *source) +{ +#if defined(IP_DROP_MEMBERSHIP) && defined(HAVE_STRUCT_IPMREQ) + return do_mcast(IP_DROP_MEMBERSHIP, sock, addr, iface, source); +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_mcast_hops(apr_socket_t *sock, apr_byte_t ttl) +{ +#if defined(IP_MULTICAST_TTL) && defined(HAVE_STRUCT_IPMREQ) + return do_mcast_opt(IP_MULTICAST_TTL, sock, ttl); +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_mcast_loopback(apr_socket_t *sock, + apr_byte_t opt) +{ +#if defined(IP_MULTICAST_LOOP) && defined(HAVE_STRUCT_IPMREQ) + return do_mcast_opt(IP_MULTICAST_LOOP, sock, opt); +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_mcast_interface(apr_socket_t *sock, + apr_sockaddr_t *iface) +{ +#if defined(IP_MULTICAST_IF) && defined(HAVE_STRUCT_IPMREQ) + apr_status_t rv = APR_SUCCESS; + + if (sock_is_ipv4(sock)) { + if (setsockopt(sock->socketdes, IPPROTO_IP, IP_MULTICAST_IF, + (const void *) &iface->sa.sin.sin_addr, + sizeof(iface->sa.sin.sin_addr)) == -1) { + rv = errno; + } + } +#if APR_HAVE_IPV6 + else if (sock_is_ipv6(sock)) { + unsigned int idx = find_if_index(iface); + if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_MULTICAST_IF, + &idx, sizeof(idx)) == -1) { + rv = errno; + } + } +#endif + else { + rv = APR_ENOTIMPL; + } + return rv; +#else + return APR_ENOTIMPL; +#endif +} diff --git a/srclib/apr/network_io/unix/sendrecv.c b/srclib/apr/network_io/unix/sendrecv.c new file mode 100644 index 0000000000..46853a39b8 --- /dev/null +++ b/srclib/apr/network_io/unix/sendrecv.c @@ -0,0 +1,960 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_support.h" + +#if APR_HAS_SENDFILE +/* This file is needed to allow us access to the apr_file_t internals. */ +#include "apr_arch_file_io.h" +#endif /* APR_HAS_SENDFILE */ + +/* osreldate.h is only needed on FreeBSD for sendfile detection */ +#if defined(__FreeBSD__) +#include +#endif + +apr_status_t apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + if (sock->options & APR_INCOMPLETE_WRITE) { + sock->options &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = write(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + + while (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { + apr_status_t arv; +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = write(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + if ((sock->timeout > 0) && (rv < *len)) { + sock->options |= APR_INCOMPLETE_WRITE; + } + (*len) = rv; + return APR_SUCCESS; +} + +apr_status_t apr_socket_recv(apr_socket_t *sock, char *buf, apr_size_t *len) +{ + apr_ssize_t rv; + apr_status_t arv; + + if (sock->options & APR_INCOMPLETE_READ) { + sock->options &= ~APR_INCOMPLETE_READ; + goto do_select; + } + + do { + rv = read(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = read(sock->socketdes, buf, (*len)); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + if ((sock->timeout > 0) && (rv < *len)) { + sock->options |= APR_INCOMPLETE_READ; + } + (*len) = rv; + if (rv == 0) { + return APR_EOF; + } + return APR_SUCCESS; +} + +apr_status_t apr_socket_sendto(apr_socket_t *sock, apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = sendto(sock->socketdes, buf, (*len), flags, + (const struct sockaddr*)&where->sa, + where->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + *len = rv; + return APR_SUCCESS; +} + +apr_status_t apr_socket_recvfrom(apr_sockaddr_t *from, apr_socket_t *sock, + apr_int32_t flags, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 1); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } else { + do { + rv = recvfrom(sock->socketdes, buf, (*len), flags, + (struct sockaddr*)&from->sa, &from->salen); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + (*len) = 0; + return errno; + } + + (*len) = rv; + if (rv == 0 && sock->type == SOCK_STREAM) { + return APR_EOF; + } + + return APR_SUCCESS; +} + +#ifdef HAVE_WRITEV +apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec, + apr_int32_t nvec, apr_size_t *len) +{ + apr_ssize_t rv; + apr_size_t requested_len = 0; + apr_int32_t i; + + for (i = 0; i < nvec; i++) { + requested_len += vec[i].iov_len; + } + + if (sock->options & APR_INCOMPLETE_WRITE) { + sock->options &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = writev(sock->socketdes, vec, nvec); + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { + apr_status_t arv; +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = writev(sock->socketdes, vec, nvec); + } while (rv == -1 && errno == EINTR); + } + } + if (rv == -1) { + *len = 0; + return errno; + } + if ((sock->timeout > 0) && (rv < requested_len)) { + sock->options |= APR_INCOMPLETE_WRITE; + } + (*len) = rv; + return APR_SUCCESS; +} +#endif + +#if APR_HAS_SENDFILE + +/* TODO: Verify that all platforms handle the fd the same way, + * i.e. that they don't move the file pointer. + */ +/* TODO: what should flags be? int_32? */ + +/* Define a structure to pass in when we have a NULL header value */ +static apr_hdtr_t no_hdtr; + +#if defined(__linux__) && defined(HAVE_WRITEV) + +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + int rv, nbytes = 0, total_hdrbytes, i; + apr_status_t arv; + +#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64) + apr_off_t off = *offset; +#define sendfile sendfile64 + +#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4 + /* 64-bit apr_off_t but no sendfile64(): fail if trying to send + * past the 2Gb limit. */ + off_t off; + + if ((apr_int64_t)*offset + *len > INT_MAX) { + return EINVAL; + } + + off = *offset; + +#else + off_t off = *offset; +#endif + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + if (hdtr->numheaders > 0) { + apr_size_t hdrbytes; + + /* cork before writing headers */ + rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1); + if (rv != APR_SUCCESS) { + return rv; + } + + /* Now write the headers */ + arv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, + &hdrbytes); + if (arv != APR_SUCCESS) { + *len = 0; + return errno; + } + nbytes += hdrbytes; + + /* If this was a partial write and we aren't doing timeouts, + * return now with the partial byte count; this is a non-blocking + * socket. + */ + total_hdrbytes = 0; + for (i = 0; i < hdtr->numheaders; i++) { + total_hdrbytes += hdtr->headers[i].iov_len; + } + if (hdrbytes < total_hdrbytes) { + *len = hdrbytes; + return apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + } + } + + if (sock->options & APR_INCOMPLETE_WRITE) { + sock->options &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = sendfile(sock->socketdes, /* socket */ + file->filedes, /* open file descriptor of the file to be sent */ + &off, /* where in the file to start */ + *len); /* number of bytes to send */ + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = sendfile(sock->socketdes, /* socket */ + file->filedes, /* open file descriptor of the file to be sent */ + &off, /* where in the file to start */ + *len); /* number of bytes to send */ + } while (rv == -1 && errno == EINTR); + } + } + + if (rv == -1) { + *len = nbytes; + rv = errno; + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + return rv; + } + + nbytes += rv; + + if (rv < *len) { + *len = nbytes; + arv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + if (rv > 0) { + + /* If this was a partial write, return now with the + * partial byte count; this is a non-blocking socket. + */ + + if (sock->timeout > 0) { + sock->options |= APR_INCOMPLETE_WRITE; + } + return arv; + } + else { + /* If the file got smaller mid-request, eventually the offset + * becomes equal to the new file size and the kernel returns 0. + * Make this an error so the caller knows to log something and + * exit. + */ + return APR_EOF; + } + } + + /* Now write the footers */ + if (hdtr->numtrailers > 0) { + apr_size_t trbytes; + arv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, + &trbytes); + nbytes += trbytes; + if (arv != APR_SUCCESS) { + *len = nbytes; + rv = errno; + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + return rv; + } + } + + apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + + (*len) = nbytes; + return rv < 0 ? errno : APR_SUCCESS; +} + +#elif defined(__FreeBSD__) || defined(__DragonFly__) + +/* Release 3.1 or greater */ +apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, + apr_hdtr_t * hdtr, apr_off_t * offset, + apr_size_t * len, apr_int32_t flags) +{ + off_t nbytes = 0; + int rv, i; + struct sf_hdtr headerstruct; + apr_size_t bytes_to_send = *len; + + /* Ignore flags for now. */ + flags = 0; + + if (!hdtr) { + hdtr = &no_hdtr; + } + +#if defined(__FreeBSD_version) && __FreeBSD_version < 460001 + else if (hdtr->numheaders) { + + /* On early versions of FreeBSD sendfile, the number of bytes to send + * must include the length of the headers. Don't look at the man page + * for this :( Instead, look at the the logic in + * src/sys/kern/uipc_syscalls::sendfile(). + * + * This was fixed in the middle of 4.6-STABLE + */ + for (i = 0; i < hdtr->numheaders; i++) { + bytes_to_send += hdtr->headers[i].iov_len; + } + } +#endif + + headerstruct.headers = hdtr->headers; + headerstruct.hdr_cnt = hdtr->numheaders; + headerstruct.trailers = hdtr->trailers; + headerstruct.trl_cnt = hdtr->numtrailers; + + /* FreeBSD can send the headers/footers as part of the system call */ + do { + if (sock->options & APR_INCOMPLETE_WRITE) { + apr_status_t arv; + sock->options &= ~APR_INCOMPLETE_WRITE; + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + if (bytes_to_send) { + /* We won't dare call sendfile() if we don't have + * header or file bytes to send because bytes_to_send == 0 + * means send the whole file. + */ + rv = sendfile(file->filedes, /* file to be sent */ + sock->socketdes, /* socket */ + *offset, /* where in the file to start */ + bytes_to_send, /* number of bytes to send */ + &headerstruct, /* Headers/footers */ + &nbytes, /* number of bytes written */ + flags); /* undefined, set to 0 */ + + if (rv == -1) { + if (errno == EAGAIN) { + if (sock->timeout > 0) { + sock->options |= APR_INCOMPLETE_WRITE; + } + /* FreeBSD's sendfile can return -1/EAGAIN even if it + * sent bytes. Sanitize the result so we get normal EAGAIN + * semantics w.r.t. bytes sent. + */ + if (nbytes) { + /* normal exit for a big file & non-blocking io */ + (*len) = nbytes; + return APR_SUCCESS; + } + } + } + else { /* rv == 0 (or the kernel is broken) */ + if (nbytes == 0) { + /* Most likely the file got smaller after the stat. + * Return an error so the caller can do the Right Thing. + */ + (*len) = nbytes; + return APR_EOF; + } + } + } + else { + /* just trailer bytes... use writev() + */ + rv = writev(sock->socketdes, + hdtr->trailers, + hdtr->numtrailers); + if (rv > 0) { + nbytes = rv; + rv = 0; + } + else { + nbytes = 0; + } + } + if ((rv == -1) && (errno == EAGAIN) + && (sock->timeout > 0)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + } while (rv == -1 && (errno == EINTR || errno == EAGAIN)); + + (*len) = nbytes; + if (rv == -1) { + return errno; + } + return APR_SUCCESS; +} + +#elif defined(__hpux) || defined(__hpux__) + +/* HP cc in ANSI mode defines __hpux; gcc defines __hpux__ */ + +/* HP-UX Version 10.30 or greater + * (no worries, because we only get here if autoconfiguration found sendfile) + */ + +/* ssize_t sendfile(int s, int fd, off_t offset, size_t nbytes, + * const struct iovec *hdtrl, int flags); + * + * nbytes is the number of bytes to send just from the file; as with FreeBSD, + * if nbytes == 0, the rest of the file (from offset) is sent + */ + +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + int i; + apr_ssize_t rc; + apr_size_t nbytes = *len, headerlen, trailerlen; + struct iovec hdtrarray[2]; + char *headerbuf, *trailerbuf; + +#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILE64) + /* later HP-UXes have a sendfile64() */ +#define sendfile sendfile64 + apr_off_t off = *offset; + +#elif APR_HAS_LARGE_FILES && SIZEOF_OFF_T == 4 + /* HP-UX 11.00 doesn't have a sendfile64(): fail if trying to send + * past the 2Gb limit */ + off_t off; + + if ((apr_int64_t)*offset + *len > INT_MAX) { + return EINVAL; + } + off = *offset; +#else + apr_off_t off = *offset; +#endif + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* HP-UX can only send one header iovec and one footer iovec; try to + * only allocate storage to combine input iovecs when we really have to + */ + + switch(hdtr->numheaders) { + case 0: + hdtrarray[0].iov_base = NULL; + hdtrarray[0].iov_len = 0; + break; + case 1: + hdtrarray[0] = hdtr->headers[0]; + break; + default: + headerlen = 0; + for (i = 0; i < hdtr->numheaders; i++) { + headerlen += hdtr->headers[i].iov_len; + } + + /* XXX: BUHHH? wow, what a memory leak! */ + headerbuf = hdtrarray[0].iov_base = apr_palloc(sock->cntxt, headerlen); + hdtrarray[0].iov_len = headerlen; + + for (i = 0; i < hdtr->numheaders; i++) { + memcpy(headerbuf, hdtr->headers[i].iov_base, + hdtr->headers[i].iov_len); + headerbuf += hdtr->headers[i].iov_len; + } + } + + switch(hdtr->numtrailers) { + case 0: + hdtrarray[1].iov_base = NULL; + hdtrarray[1].iov_len = 0; + break; + case 1: + hdtrarray[1] = hdtr->trailers[0]; + break; + default: + trailerlen = 0; + for (i = 0; i < hdtr->numtrailers; i++) { + trailerlen += hdtr->trailers[i].iov_len; + } + + /* XXX: BUHHH? wow, what a memory leak! */ + trailerbuf = hdtrarray[1].iov_base = apr_palloc(sock->cntxt, trailerlen); + hdtrarray[1].iov_len = trailerlen; + + for (i = 0; i < hdtr->numtrailers; i++) { + memcpy(trailerbuf, hdtr->trailers[i].iov_base, + hdtr->trailers[i].iov_len); + trailerbuf += hdtr->trailers[i].iov_len; + } + } + + do { + if (nbytes) { /* any bytes to send from the file? */ + rc = sendfile(sock->socketdes, /* socket */ + file->filedes, /* file descriptor to send */ + off, /* where in the file to start */ + nbytes, /* number of bytes to send from file */ + hdtrarray, /* Headers/footers */ + flags); /* undefined, set to 0 */ + } + else { /* we can't call sendfile() with no bytes to send from the file */ + rc = writev(sock->socketdes, hdtrarray, 2); + } + } while (rc == -1 && errno == EINTR); + + while ((rc == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { + apr_status_t arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + if (nbytes) { + rc = sendfile(sock->socketdes, /* socket */ + file->filedes, /* file descriptor to send */ + off, /* where in the file to start */ + nbytes, /* number of bytes to send from file */ + hdtrarray, /* Headers/footers */ + flags); /* undefined, set to 0 */ + } + else { /* we can't call sendfile() with no bytes to send from the file */ + rc = writev(sock->socketdes, hdtrarray, 2); + } + } while (rc == -1 && errno == EINTR); + } + } + + if (rc == -1) { + *len = 0; + return errno; + } + + /* Set len to the number of bytes written */ + *len = rc; + return APR_SUCCESS; +} +#elif defined(_AIX) || defined(__MVS__) +/* AIX and OS/390 have the same send_file() interface. + * + * subtle differences: + * AIX doesn't update the file ptr but OS/390 does + * + * availability (correctly determined by autoconf): + * + * AIX - version 4.3.2 with APAR IX85388, or version 4.3.3 and above + * OS/390 - V2R7 and above + */ +apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file, + apr_hdtr_t * hdtr, apr_off_t * offset, + apr_size_t * len, apr_int32_t flags) +{ + int i, ptr, rv = 0; + void * hbuf=NULL, * tbuf=NULL; + apr_status_t arv; + struct sf_parms parms; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* word to the wise: by default, AIX stores files sent by send_file() + * in the network buffer cache... there are supposedly scenarios + * where the most recent copy of the file won't be sent, but I can't + * recreate the potential problem, perhaps because of the way we + * use send_file()... if you suspect such a problem, try turning + * on the SF_SYNC_CACHE flag + */ + + /* AIX can also send the headers/footers as part of the system call */ + parms.header_length = 0; + if (hdtr && hdtr->numheaders) { + if (hdtr->numheaders == 1) { + parms.header_data = hdtr->headers[0].iov_base; + parms.header_length = hdtr->headers[0].iov_len; + } + else { + for (i = 0; i < hdtr->numheaders; i++) { + parms.header_length += hdtr->headers[i].iov_len; + } +#if 0 + /* Keepalives make apr_palloc a bad idea */ + hbuf = malloc(parms.header_length); +#else + /* but headers are small, so maybe we can hold on to the + * memory for the life of the socket... + */ + hbuf = apr_palloc(sock->cntxt, parms.header_length); +#endif + ptr = 0; + for (i = 0; i < hdtr->numheaders; i++) { + memcpy((char *)hbuf + ptr, hdtr->headers[i].iov_base, + hdtr->headers[i].iov_len); + ptr += hdtr->headers[i].iov_len; + } + parms.header_data = hbuf; + } + } + else parms.header_data = NULL; + parms.trailer_length = 0; + if (hdtr && hdtr->numtrailers) { + if (hdtr->numtrailers == 1) { + parms.trailer_data = hdtr->trailers[0].iov_base; + parms.trailer_length = hdtr->trailers[0].iov_len; + } + else { + for (i = 0; i < hdtr->numtrailers; i++) { + parms.trailer_length += hdtr->trailers[i].iov_len; + } +#if 0 + /* Keepalives make apr_palloc a bad idea */ + tbuf = malloc(parms.trailer_length); +#else + tbuf = apr_palloc(sock->cntxt, parms.trailer_length); +#endif + ptr = 0; + for (i = 0; i < hdtr->numtrailers; i++) { + memcpy((char *)tbuf + ptr, hdtr->trailers[i].iov_base, + hdtr->trailers[i].iov_len); + ptr += hdtr->trailers[i].iov_len; + } + parms.trailer_data = tbuf; + } + } + else { + parms.trailer_data = NULL; + } + + /* Whew! Headers and trailers set up. Now for the file data */ + + parms.file_descriptor = file->filedes; + parms.file_offset = *offset; + parms.file_bytes = *len; + + /* O.K. All set up now. Let's go to town */ + + if (sock->options & APR_INCOMPLETE_WRITE) { + sock->options &= ~APR_INCOMPLETE_WRITE; + goto do_select; + } + + do { + rv = send_file(&(sock->socketdes), /* socket */ + &(parms), /* all data */ + flags); /* flags */ + } while (rv == -1 && errno == EINTR); + + while ((rv == -1) && (errno == EAGAIN || errno == EWOULDBLOCK) + && (sock->timeout > 0)) { +do_select: + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + else { + do { + rv = send_file(&(sock->socketdes), /* socket */ + &(parms), /* all data */ + flags); /* flags */ + } while (rv == -1 && errno == EINTR); + } + } + + (*len) = parms.bytes_sent; + +#if 0 + /* Clean up after ourselves */ + if(hbuf) free(hbuf); + if(tbuf) free(tbuf); +#endif + + if (rv == -1) { + return errno; + } + + if ((sock->timeout > 0) + && (parms.bytes_sent + < (parms.file_bytes + parms.header_length + parms.trailer_length))) { + sock->options |= APR_INCOMPLETE_WRITE; + } + + return APR_SUCCESS; +} +#elif defined(__osf__) && defined (__alpha) +/* Tru64's sendfile implementation doesn't work, and we need to make sure that + * we don't use it until it is fixed. If it is used as it is now, it will + * hang the machine and the only way to fix it is a reboot. + */ +#elif defined(HAVE_SENDFILEV) +/* Solaris 8's sendfilev() interface + * + * SFV_FD_SELF refers to our memory space. + * + * Required Sparc patches (or newer): + * 111297-01, 108528-09, 109472-06, 109234-03, 108995-02, 111295-01, 109025-03, + * 108991-13 + * Required x86 patches (or newer): + * 111298-01, 108529-09, 109473-06, 109235-04, 108996-02, 111296-01, 109026-04, + * 108992-13 + */ + +#if APR_HAS_LARGE_FILES && defined(HAVE_SENDFILEV64) +#define sendfilevec_t sendfilevec64_t +#define sendfilev sendfilev64 +#endif + +apr_status_t apr_socket_sendfile(apr_socket_t *sock, apr_file_t *file, + apr_hdtr_t *hdtr, apr_off_t *offset, + apr_size_t *len, apr_int32_t flags) +{ + apr_status_t rv, arv; + apr_size_t nbytes; + sendfilevec_t *sfv; + int vecs, curvec, i, repeat; + apr_size_t requested_len = 0; + + if (!hdtr) { + hdtr = &no_hdtr; + } + + /* Ignore flags for now. */ + flags = 0; + + /* Calculate how much space we need. */ + vecs = hdtr->numheaders + hdtr->numtrailers + 1; + sfv = apr_palloc(sock->cntxt, sizeof(sendfilevec_t) * vecs); + + curvec = 0; + + /* Add the headers */ + for (i = 0; i < hdtr->numheaders; i++, curvec++) { + sfv[curvec].sfv_fd = SFV_FD_SELF; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = (apr_off_t)hdtr->headers[i].iov_base; + sfv[curvec].sfv_len = hdtr->headers[i].iov_len; + requested_len += sfv[curvec].sfv_len; + } + + /* If the len is 0, we skip the file. */ + if (*len) + { + sfv[curvec].sfv_fd = file->filedes; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = *offset; + sfv[curvec].sfv_len = *len; + requested_len += sfv[curvec].sfv_len; + + curvec++; + } + else { + vecs--; + } + + /* Add the footers */ + for (i = 0; i < hdtr->numtrailers; i++, curvec++) { + sfv[curvec].sfv_fd = SFV_FD_SELF; + sfv[curvec].sfv_flag = 0; + sfv[curvec].sfv_off = (apr_off_t)hdtr->trailers[i].iov_base; + sfv[curvec].sfv_len = hdtr->trailers[i].iov_len; + requested_len += sfv[curvec].sfv_len; + } + + /* If the last write couldn't send all the requested data, + * wait for the socket to become writable before proceeding + */ + if (sock->options & APR_INCOMPLETE_WRITE) { + sock->options &= ~APR_INCOMPLETE_WRITE; + arv = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } + + /* Actually do the sendfilev + * + * Solaris may return -1/EAGAIN even if it sent bytes on a non-block sock. + * + * If no bytes were originally sent (nbytes == 0) and we are on a TIMEOUT + * socket (which as far as the OS is concerned is a non-blocking socket), + * we want to retry after waiting for the other side to read the data (as + * determined by poll). Once it is clear to send, we want to retry + * sending the sendfilevec_t once more. + */ + arv = 0; + do { + /* Clear out the repeat */ + repeat = 0; + + /* socket, vecs, number of vecs, bytes written */ + rv = sendfilev(sock->socketdes, sfv, vecs, &nbytes); + + if (rv == -1 && errno == EAGAIN) { + if (nbytes) { + rv = 0; + } + else if (!arv && (sock->timeout > 0)) { + apr_status_t t = apr_wait_for_io_or_timeout(NULL, sock, 0); + + if (t != APR_SUCCESS) { + *len = 0; + return t; + } + + arv = 1; + repeat = 1; + } + } + } while ((rv == -1 && errno == EINTR) || repeat); + + if (rv == -1) { + *len = 0; + return errno; + } + + /* Update how much we sent */ + *len = nbytes; + if ((sock->timeout > 0) && (*len < requested_len)) { + sock->options |= APR_INCOMPLETE_WRITE; + } + return APR_SUCCESS; +} +#else +#error APR has detected sendfile on your system, but nobody has written a +#error version of it for APR yet. To get past this, either write +#error apr_socket_sendfile or change APR_HAS_SENDFILE in apr.h to 0. +#endif /* __linux__, __FreeBSD__, __DragonFly__, __HPUX__, _AIX, __MVS__, + Tru64/OSF1 */ + +#endif /* APR_HAS_SENDFILE */ diff --git a/srclib/apr/network_io/unix/sockaddr.c b/srclib/apr/network_io/unix/sockaddr.c new file mode 100644 index 0000000000..f27e97fb98 --- /dev/null +++ b/srclib/apr/network_io/unix/sockaddr.c @@ -0,0 +1,968 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_strings.h" +#include "apr.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_private.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + +#define APR_WANT_STRFUNC +#include "apr_want.h" + +struct apr_ipsubnet_t { + int family; +#if APR_HAVE_IPV6 + apr_uint32_t sub[4]; /* big enough for IPv4 and IPv6 addresses */ + apr_uint32_t mask[4]; +#else + apr_uint32_t sub[1]; + apr_uint32_t mask[1]; +#endif +}; + +#if !defined(NETWARE) && !defined(WIN32) +#ifdef HAVE_SET_H_ERRNO +#define SET_H_ERRNO(newval) set_h_errno(newval) +#else +#define SET_H_ERRNO(newval) h_errno = (newval) +#endif +#else +#define SET_H_ERRNO(newval) +#endif + +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) +/* This is the maximum size that may be returned from the reentrant + * gethostbyname_r function. If the system tries to use more, it + * should return ERANGE. + */ +#define GETHOSTBYNAME_BUFLEN 512 +#endif + +#ifdef _WIN32_WCE +/* XXX: BS solution. Need an HAVE_GETSERVBYNAME and actually + * do something here, to provide the obvious proto mappings. + */ +static void *getservbyname(const char *name, const char *proto) +{ + return NULL; +} +#endif + +static apr_status_t get_local_addr(apr_socket_t *sock) +{ + sock->local_addr->salen = sizeof(sock->local_addr->sa); + if (getsockname(sock->socketdes, (struct sockaddr *)&sock->local_addr->sa, + &sock->local_addr->salen) < 0) { + return apr_get_netos_error(); + } + else { + sock->local_port_unknown = sock->local_interface_unknown = 0; + /* XXX assumes sin_port and sin6_port at same offset */ + sock->local_addr->port = ntohs(sock->local_addr->sa.sin.sin_port); + return APR_SUCCESS; + } +} + +static apr_status_t get_remote_addr(apr_socket_t *sock) +{ + sock->remote_addr->salen = sizeof(sock->remote_addr->sa); + if (getpeername(sock->socketdes, (struct sockaddr *)&sock->remote_addr->sa, + &sock->remote_addr->salen) < 0) { + return apr_get_netos_error(); + } + else { + sock->remote_addr_unknown = 0; + /* XXX assumes sin_port and sin6_port at same offset */ + sock->remote_addr->port = ntohs(sock->remote_addr->sa.sin.sin_port); + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_sockaddr_ip_get(char **addr, + apr_sockaddr_t *sockaddr) +{ + *addr = apr_palloc(sockaddr->pool, sockaddr->addr_str_len); + apr_inet_ntop(sockaddr->family, + sockaddr->ipaddr_ptr, + *addr, + sockaddr->addr_str_len); +#if APR_HAVE_IPV6 + if (sockaddr->family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sockaddr->ipaddr_ptr)) { + /* This is an IPv4-mapped IPv6 address; drop the leading + * part of the address string so we're left with the familiar + * IPv4 format. + */ + *addr += strlen("::ffff:"); + } +#endif + return APR_SUCCESS; +} + +void apr_sockaddr_vars_set(apr_sockaddr_t *addr, int family, apr_port_t port) +{ + addr->family = family; + addr->sa.sin.sin_family = family; + if (port) { + /* XXX IPv6: assumes sin_port and sin6_port at same offset */ + addr->sa.sin.sin_port = htons(port); + addr->port = port; + } + + if (family == APR_INET) { + addr->salen = sizeof(struct sockaddr_in); + addr->addr_str_len = 16; + addr->ipaddr_ptr = &(addr->sa.sin.sin_addr); + addr->ipaddr_len = sizeof(struct in_addr); + } +#if APR_HAVE_IPV6 + else if (family == APR_INET6) { + addr->salen = sizeof(struct sockaddr_in6); + addr->addr_str_len = 46; + addr->ipaddr_ptr = &(addr->sa.sin6.sin6_addr); + addr->ipaddr_len = sizeof(struct in6_addr); + } +#endif +} + +APR_DECLARE(apr_status_t) apr_socket_addr_get(apr_sockaddr_t **sa, + apr_interface_e which, + apr_socket_t *sock) +{ + if (which == APR_LOCAL) { + if (sock->local_interface_unknown || sock->local_port_unknown) { + apr_status_t rv = get_local_addr(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + } + *sa = sock->local_addr; + } + else if (which == APR_REMOTE) { + if (sock->remote_addr_unknown) { + apr_status_t rv = get_remote_addr(sock); + + if (rv != APR_SUCCESS) { + return rv; + } + } + *sa = sock->remote_addr; + } + else { + *sa = NULL; + return APR_EINVAL; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_parse_addr_port(char **addr, + char **scope_id, + apr_port_t *port, + const char *str, + apr_pool_t *p) +{ + const char *ch, *lastchar; + int big_port; + apr_size_t addrlen; + + *addr = NULL; /* assume not specified */ + *scope_id = NULL; /* assume not specified */ + *port = 0; /* assume not specified */ + + /* First handle the optional port number. That may be all that + * is specified in the string. + */ + ch = lastchar = str + strlen(str) - 1; + while (ch >= str && apr_isdigit(*ch)) { + --ch; + } + + if (ch < str) { /* Entire string is the port. */ + big_port = atoi(str); + if (big_port < 1 || big_port > 65535) { + return APR_EINVAL; + } + *port = big_port; + return APR_SUCCESS; + } + + if (*ch == ':' && ch < lastchar) { /* host and port number specified */ + if (ch == str) { /* string starts with ':' -- bad */ + return APR_EINVAL; + } + big_port = atoi(ch + 1); + if (big_port < 1 || big_port > 65535) { + return APR_EINVAL; + } + *port = big_port; + lastchar = ch - 1; + } + + /* now handle the hostname */ + addrlen = lastchar - str + 1; + +/* XXX we don't really have to require APR_HAVE_IPV6 for this; + * just pass char[] for ipaddr (so we don't depend on struct in6_addr) + * and always define APR_INET6 + */ +#if APR_HAVE_IPV6 + if (*str == '[') { + const char *end_bracket = memchr(str, ']', addrlen); + struct in6_addr ipaddr; + const char *scope_delim; + + if (!end_bracket || end_bracket != lastchar) { + *port = 0; + return APR_EINVAL; + } + + /* handle scope id; this is the only context where it is allowed */ + scope_delim = memchr(str, '%', addrlen); + if (scope_delim) { + if (scope_delim == end_bracket - 1) { /* '%' without scope id */ + *port = 0; + return APR_EINVAL; + } + addrlen = scope_delim - str - 1; + *scope_id = apr_palloc(p, end_bracket - scope_delim); + memcpy(*scope_id, scope_delim + 1, end_bracket - scope_delim - 1); + (*scope_id)[end_bracket - scope_delim - 1] = '\0'; + } + else { + addrlen = addrlen - 2; /* minus 2 for '[' and ']' */ + } + + *addr = apr_palloc(p, addrlen + 1); + memcpy(*addr, + str + 1, + addrlen); + (*addr)[addrlen] = '\0'; + if (apr_inet_pton(AF_INET6, *addr, &ipaddr) != 1) { + *addr = NULL; + *scope_id = NULL; + *port = 0; + return APR_EINVAL; + } + } + else +#endif + { + /* XXX If '%' is not a valid char in a DNS name, we *could* check + * for bogus scope ids first. + */ + *addr = apr_palloc(p, addrlen + 1); + memcpy(*addr, str, addrlen); + (*addr)[addrlen] = '\0'; + } + return APR_SUCCESS; +} + +#if defined(HAVE_GETADDRINFO) + +static apr_status_t call_resolver(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + struct addrinfo hints, *ai, *ai_list; + apr_sockaddr_t *prev_sa; + int error; + char *servname = NULL; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = family; + hints.ai_socktype = SOCK_STREAM; +#ifdef HAVE_GAI_ADDRCONFIG + if (family == APR_UNSPEC) { + /* By default, only look up addresses using address types for + * which a local interface is configured, i.e. no IPv6 if no + * IPv6 interfaces configured. */ + hints.ai_flags = AI_ADDRCONFIG; + } +#endif + if(hostname == NULL) { +#ifdef AI_PASSIVE + /* If hostname is NULL, assume we are trying to bind to all + * interfaces. */ + hints.ai_flags |= AI_PASSIVE; +#endif + /* getaddrinfo according to RFC 2553 must have either hostname + * or servname non-NULL. + */ +#ifdef OSF1 + /* The Tru64 5.0 getaddrinfo() can only resolve services given + * by the name listed in /etc/services; a numeric or unknown + * servname gets an EAI_SERVICE error. So just resolve the + * appropriate anyaddr and fill in the port later. */ + hostname = family == AF_INET6 ? "::" : "0.0.0.0"; + servname = NULL; +#ifdef AI_NUMERICHOST + hints.ai_flags |= AI_NUMERICHOST; +#endif +#else +#ifdef _AIX + /* But current AIX getaddrinfo() doesn't like servname = "0"; + * the "1" won't hurt since we use the port parameter to fill + * in the returned socket addresses later + */ + if (!port) { + servname = "1"; + } + else +#endif /* _AIX */ + servname = apr_itoa(p, port); +#endif /* OSF1 */ + } + error = getaddrinfo(hostname, servname, &hints, &ai_list); +#ifdef HAVE_GAI_ADDRCONFIG + if (error == EAI_BADFLAGS && family == APR_UNSPEC) { + /* Retry with no flags if AI_ADDRCONFIG was rejected. */ + hints.ai_flags = 0; + error = getaddrinfo(hostname, servname, &hints, &ai_list); + } +#endif + if (error) { +#ifndef WIN32 + if (error == EAI_SYSTEM) { + return errno; + } + else +#endif + { + /* issues with representing this with APR's error scheme: + * glibc uses negative values for these numbers, perhaps so + * they don't conflict with h_errno values... Tru64 uses + * positive values which conflict with h_errno values + */ +#if defined(NEGATIVE_EAI) + error = -error; +#endif + return error + APR_OS_START_EAIERR; + } + } + + prev_sa = NULL; + ai = ai_list; + while (ai) { /* while more addresses to report */ + apr_sockaddr_t *new_sa; + + /* Ignore anything bogus: getaddrinfo in some old versions of + * glibc will return AF_UNIX entries for APR_UNSPEC+AI_PASSIVE + * lookups. */ + if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6) { + ai = ai->ai_next; + continue; + } + + new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); + + new_sa->pool = p; + memcpy(&new_sa->sa, ai->ai_addr, ai->ai_addrlen); + apr_sockaddr_vars_set(new_sa, ai->ai_family, port); + + if (!prev_sa) { /* first element in new list */ + if (hostname) { + new_sa->hostname = apr_pstrdup(p, hostname); + } + *sa = new_sa; + } + else { + new_sa->hostname = prev_sa->hostname; + prev_sa->next = new_sa; + } + + prev_sa = new_sa; + ai = ai->ai_next; + } + freeaddrinfo(ai_list); + return APR_SUCCESS; +} + +static apr_status_t find_addresses(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + if (flags & APR_IPV4_ADDR_OK) { + apr_status_t error = call_resolver(sa, hostname, AF_INET, port, flags, p); + +#if APR_HAVE_IPV6 + if (error) { + family = AF_INET6; /* try again */ + } + else +#endif + return error; + } +#if APR_HAVE_IPV6 + else if (flags & APR_IPV6_ADDR_OK) { + apr_status_t error = call_resolver(sa, hostname, AF_INET6, port, flags, p); + + if (error) { + family = AF_INET; /* try again */ + } + else { + return APR_SUCCESS; + } + } +#endif + + return call_resolver(sa, hostname, family, port, flags, p); +} + +#else /* end of HAVE_GETADDRINFO code */ + +static apr_status_t find_addresses(apr_sockaddr_t **sa, + const char *hostname, apr_int32_t family, + apr_port_t port, apr_int32_t flags, + apr_pool_t *p) +{ + struct hostent *hp; + apr_sockaddr_t *prev_sa; + int curaddr; +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) +#ifdef GETHOSTBYNAME_R_HOSTENT_DATA + struct hostent_data hd; +#else + /* If you see ERANGE, that means GETHOSBYNAME_BUFLEN needs to be + * bumped. */ + char tmp[GETHOSTBYNAME_BUFLEN]; +#endif + int hosterror; +#endif + struct hostent hs; + struct in_addr ipaddr; + char *addr_list[2]; + const char *orig_hostname = hostname; + + if (hostname == NULL) { + /* if we are given a NULL hostname, assume '0.0.0.0' */ + hostname = "0.0.0.0"; + } + + if (*hostname >= '0' && *hostname <= '9' && + strspn(hostname, "0123456789.") == strlen(hostname)) { + + ipaddr.s_addr = inet_addr(hostname); + addr_list[0] = (char *)&ipaddr; + addr_list[1] = NULL; /* just one IP in list */ + hs.h_addr_list = (char **)addr_list; + hp = &hs; + } + else { +#if APR_HAS_THREADS && !defined(GETHOSTBYNAME_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYNAME_R) && !defined(BEOS) +#if defined(GETHOSTBYNAME_R_HOSTENT_DATA) + /* AIX, HP/UX, D/UX et alia */ + gethostbyname_r(hostname, &hs, &hd); + hp = &hs; +#else +#if defined(GETHOSTBYNAME_R_GLIBC2) + /* Linux glibc2+ */ + gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, + &hp, &hosterror); +#else + /* Solaris, Irix et alia */ + hp = gethostbyname_r(hostname, &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, + &hosterror); +#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */ + if (!hp) { + return (hosterror + APR_OS_START_SYSERR); + } +#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */ +#else + hp = gethostbyname(hostname); +#endif + + if (!hp) { +#ifdef WIN32 + return apr_get_netos_error(); +#else + return (h_errno + APR_OS_START_SYSERR); +#endif + } + } + + prev_sa = NULL; + curaddr = 0; + while (hp->h_addr_list[curaddr]) { + apr_sockaddr_t *new_sa = apr_pcalloc(p, sizeof(apr_sockaddr_t)); + + new_sa->pool = p; + new_sa->sa.sin.sin_addr = *(struct in_addr *)hp->h_addr_list[curaddr]; + apr_sockaddr_vars_set(new_sa, AF_INET, port); + + if (!prev_sa) { /* first element in new list */ + if (orig_hostname) { + new_sa->hostname = apr_pstrdup(p, orig_hostname); + } + *sa = new_sa; + } + else { + new_sa->hostname = prev_sa->hostname; + prev_sa->next = new_sa; + } + + prev_sa = new_sa; + ++curaddr; + } + + return APR_SUCCESS; +} + +#endif /* end of !HAVE_GETADDRINFO code */ + +APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa, + const char *hostname, + apr_int32_t family, apr_port_t port, + apr_int32_t flags, apr_pool_t *p) +{ + apr_int32_t masked; + *sa = NULL; + + if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { + if (!hostname || + family != APR_UNSPEC || + masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) { + return APR_EINVAL; + } +#if !APR_HAVE_IPV6 + if (flags & APR_IPV6_ADDR_OK) { + return APR_ENOTIMPL; + } +#endif + } +#if !APR_HAVE_IPV6 + /* What may happen is that APR is not IPv6-enabled, but we're still + * going to call getaddrinfo(), so we have to tell the OS we only + * want IPv4 addresses back since we won't know what to do with + * IPv6 addresses. + */ + if (family == APR_UNSPEC) { + family = APR_INET; + } +#endif + + return find_addresses(sa, hostname, family, port, flags, p); +} + +APR_DECLARE(apr_status_t) apr_getnameinfo(char **hostname, + apr_sockaddr_t *sockaddr, + apr_int32_t flags) +{ +#if defined(HAVE_GETNAMEINFO) + int rc; +#if defined(NI_MAXHOST) + char tmphostname[NI_MAXHOST]; +#else + char tmphostname[256]; +#endif + + /* don't know if it is portable for getnameinfo() to set h_errno; + * clear it then see if it was set */ + SET_H_ERRNO(0); + + /* default flags are NI_NAMREQD; otherwise, getnameinfo() will return + * a numeric address string if it fails to resolve the host name; + * that is *not* what we want here + * + * For IPv4-mapped IPv6 addresses, drop down to IPv4 before calling + * getnameinfo() to avoid getnameinfo bugs (MacOS X, glibc). + */ +#if APR_HAVE_IPV6 + if (sockaddr->family == AF_INET6 && + IN6_IS_ADDR_V4MAPPED(&sockaddr->sa.sin6.sin6_addr)) { + struct sockaddr_in tmpsa; + tmpsa.sin_family = AF_INET; + tmpsa.sin_addr.s_addr = ((apr_uint32_t *)sockaddr->ipaddr_ptr)[3]; +#ifdef SIN6_LEN + tmpsa.sin_len = sizeof(tmpsa); +#endif + + rc = getnameinfo((const struct sockaddr *)&tmpsa, sizeof(tmpsa), + tmphostname, sizeof(tmphostname), NULL, 0, + flags != 0 ? flags : NI_NAMEREQD); + } + else +#endif + rc = getnameinfo((const struct sockaddr *)&sockaddr->sa, sockaddr->salen, + tmphostname, sizeof(tmphostname), NULL, 0, + flags != 0 ? flags : NI_NAMEREQD); + if (rc != 0) { + *hostname = NULL; + +#ifndef WIN32 + /* something went wrong. Look at the EAI_ error code */ + if (rc == EAI_SYSTEM) { + /* EAI_SYSTEM System error returned in errno. */ + /* IMHO, Implementations that set h_errno a simply broken. */ + if (h_errno) { /* for broken implementations which set h_errno */ + return h_errno + APR_OS_START_SYSERR; + } + else { /* "normal" case */ + return errno + APR_OS_START_SYSERR; + } + } + else +#endif + { +#if defined(NEGATIVE_EAI) + if (rc < 0) rc = -rc; +#endif + return rc + APR_OS_START_EAIERR; /* return the EAI_ error */ + } + } + *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, + tmphostname); + return APR_SUCCESS; +#else +#if APR_HAS_THREADS && !defined(GETHOSTBYADDR_IS_THREAD_SAFE) && \ + defined(HAVE_GETHOSTBYADDR_R) && !defined(BEOS) +#ifdef GETHOSTBYNAME_R_HOSTENT_DATA + struct hostent_data hd; +#else + char tmp[GETHOSTBYNAME_BUFLEN]; +#endif + int hosterror; + struct hostent hs, *hptr; + +#if defined(GETHOSTBYNAME_R_HOSTENT_DATA) + /* AIX, HP/UX, D/UX et alia */ + gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, &hs, &hd); + hptr = &hs; +#else +#if defined(GETHOSTBYNAME_R_GLIBC2) + /* Linux glibc2+ */ + gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, + &hs, tmp, GETHOSTBYNAME_BUFLEN - 1, &hptr, &hosterror); +#else + /* Solaris, Irix et alia */ + hptr = gethostbyaddr_r((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET, + &hs, tmp, GETHOSTBYNAME_BUFLEN, &hosterror); +#endif /* !defined(GETHOSTBYNAME_R_GLIBC2) */ + if (!hptr) { + *hostname = NULL; + return hosterror + APR_OS_START_SYSERR; + } +#endif /* !defined(GETHOSTBYNAME_R_HOSTENT_DATA) */ +#else + struct hostent *hptr; + hptr = gethostbyaddr((char *)&sockaddr->sa.sin.sin_addr, + sizeof(struct in_addr), AF_INET); +#endif + + if (hptr) { + *hostname = sockaddr->hostname = apr_pstrdup(sockaddr->pool, hptr->h_name); + return APR_SUCCESS; + } + *hostname = NULL; +#if defined(WIN32) + return apr_get_netos_error(); +#elif defined(OS2) + return h_errno; +#else + return h_errno + APR_OS_START_SYSERR; +#endif +#endif +} + +APR_DECLARE(apr_status_t) apr_getservbyname(apr_sockaddr_t *sockaddr, + const char *servname) +{ + struct servent *se; + + if (servname == NULL) + return APR_EINVAL; + + if ((se = getservbyname(servname, NULL)) != NULL){ + sockaddr->port = htons(se->s_port); + sockaddr->servname = apr_pstrdup(sockaddr->pool, servname); + sockaddr->sa.sin.sin_port = se->s_port; + return APR_SUCCESS; + } + return errno; +} + +#define V4MAPPED_EQUAL(a,b) \ +((a)->sa.sin.sin_family == AF_INET && \ + (b)->sa.sin.sin_family == AF_INET6 && \ + IN6_IS_ADDR_V4MAPPED((struct in6_addr *)(b)->ipaddr_ptr) && \ + !memcmp((a)->ipaddr_ptr, \ + &((struct in6_addr *)(b)->ipaddr_ptr)->s6_addr[12], \ + (a)->ipaddr_len)) + +APR_DECLARE(int) apr_sockaddr_equal(const apr_sockaddr_t *addr1, + const apr_sockaddr_t *addr2) +{ + if (addr1->ipaddr_len == addr2->ipaddr_len && + !memcmp(addr1->ipaddr_ptr, addr2->ipaddr_ptr, addr1->ipaddr_len)) { + return 1; + } +#if APR_HAVE_IPV6 + if (V4MAPPED_EQUAL(addr1, addr2)) { + return 1; + } + if (V4MAPPED_EQUAL(addr2, addr1)) { + return 1; + } +#endif + return 0; /* not equal */ +} + +static apr_status_t parse_network(apr_ipsubnet_t *ipsub, const char *network) +{ + /* legacy syntax for ip addrs: a.b.c. ==> a.b.c.0/24 for example */ + int shift; + char *s, *t; + int octet; + char buf[sizeof "255.255.255.255"]; + + if (strlen(network) < sizeof buf) { + strcpy(buf, network); + } + else { + return APR_EBADIP; + } + + /* parse components */ + s = buf; + ipsub->sub[0] = 0; + ipsub->mask[0] = 0; + shift = 24; + while (*s) { + t = s; + if (!apr_isdigit(*t)) { + return APR_EBADIP; + } + while (apr_isdigit(*t)) { + ++t; + } + if (*t == '.') { + *t++ = 0; + } + else if (*t) { + return APR_EBADIP; + } + if (shift < 0) { + return APR_EBADIP; + } + octet = atoi(s); + if (octet < 0 || octet > 255) { + return APR_EBADIP; + } + ipsub->sub[0] |= octet << shift; + ipsub->mask[0] |= 0xFFUL << shift; + s = t; + shift -= 8; + } + ipsub->sub[0] = ntohl(ipsub->sub[0]); + ipsub->mask[0] = ntohl(ipsub->mask[0]); + ipsub->family = AF_INET; + return APR_SUCCESS; +} + +/* return values: + * APR_EINVAL not an IP address; caller should see if it is something else + * APR_BADIP IP address portion is is not valid + * APR_BADMASK mask portion is not valid + */ + +static apr_status_t parse_ip(apr_ipsubnet_t *ipsub, const char *ipstr, int network_allowed) +{ + /* supported flavors of IP: + * + * . IPv6 numeric address string (e.g., "fe80::1") + * + * IMPORTANT: Don't store IPv4-mapped IPv6 address as an IPv6 address. + * + * . IPv4 numeric address string (e.g., "127.0.0.1") + * + * . IPv4 network string (e.g., "9.67") + * + * IMPORTANT: This network form is only allowed if network_allowed is on. + */ + int rc; + +#if APR_HAVE_IPV6 + rc = apr_inet_pton(AF_INET6, ipstr, ipsub->sub); + if (rc == 1) { + if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ipsub->sub)) { + /* apr_ipsubnet_test() assumes that we don't create IPv4-mapped IPv6 + * addresses; this of course forces the user to specify IPv4 addresses + * in a.b.c.d style instead of ::ffff:a.b.c.d style. + */ + return APR_EBADIP; + } + ipsub->family = AF_INET6; + } + else +#endif + { + rc = apr_inet_pton(AF_INET, ipstr, ipsub->sub); + if (rc == 1) { + ipsub->family = AF_INET; + } + } + if (rc != 1) { + if (network_allowed) { + return parse_network(ipsub, ipstr); + } + else { + return APR_EBADIP; + } + } + return APR_SUCCESS; +} + +static int looks_like_ip(const char *ipstr) +{ + if (strchr(ipstr, ':')) { + /* definitely not a hostname; assume it is intended to be an IPv6 address */ + return 1; + } + + /* simple IPv4 address string check */ + while ((*ipstr == '.') || apr_isdigit(*ipstr)) + ipstr++; + return (*ipstr == '\0'); +} + +static void fix_subnet(apr_ipsubnet_t *ipsub) +{ + /* in case caller specified more bits in network address than are + * valid according to the mask, turn off the extra bits + */ + int i; + + for (i = 0; i < sizeof ipsub->mask / sizeof(apr_int32_t); i++) { + ipsub->sub[i] &= ipsub->mask[i]; + } +} + +/* be sure not to store any IPv4 address as a v4-mapped IPv6 address */ +APR_DECLARE(apr_status_t) apr_ipsubnet_create(apr_ipsubnet_t **ipsub, const char *ipstr, + const char *mask_or_numbits, apr_pool_t *p) +{ + apr_status_t rv; + char *endptr; + long bits, maxbits = 32; + + /* filter out stuff which doesn't look remotely like an IP address; this helps + * callers like mod_access which have a syntax allowing hostname or IP address; + * APR_EINVAL tells the caller that it was probably not intended to be an IP + * address + */ + if (!looks_like_ip(ipstr)) { + return APR_EINVAL; + } + + *ipsub = apr_pcalloc(p, sizeof(apr_ipsubnet_t)); + + /* assume ipstr is an individual IP address, not a subnet */ + memset((*ipsub)->mask, 0xFF, sizeof (*ipsub)->mask); + + rv = parse_ip(*ipsub, ipstr, mask_or_numbits == NULL); + if (rv != APR_SUCCESS) { + return rv; + } + + if (mask_or_numbits) { +#if APR_HAVE_IPV6 + if ((*ipsub)->family == AF_INET6) { + maxbits = 128; + } +#endif + bits = strtol(mask_or_numbits, &endptr, 10); + if (*endptr == '\0' && bits > 0 && bits <= maxbits) { + /* valid num-bits string; fill in mask appropriately */ + int cur_entry = 0; + apr_int32_t cur_bit_value; + + memset((*ipsub)->mask, 0, sizeof (*ipsub)->mask); + while (bits > 32) { + (*ipsub)->mask[cur_entry] = 0xFFFFFFFF; /* all 32 bits */ + bits -= 32; + ++cur_entry; + } + cur_bit_value = 0x80000000; + while (bits) { + (*ipsub)->mask[cur_entry] |= cur_bit_value; + --bits; + cur_bit_value /= 2; + } + (*ipsub)->mask[cur_entry] = htonl((*ipsub)->mask[cur_entry]); + } + else if (apr_inet_pton(AF_INET, mask_or_numbits, (*ipsub)->mask) == 1 && + (*ipsub)->family == AF_INET) { + /* valid IPv4 netmask */ + } + else { + return APR_EBADMASK; + } + } + + fix_subnet(*ipsub); + + return APR_SUCCESS; +} + +APR_DECLARE(int) apr_ipsubnet_test(apr_ipsubnet_t *ipsub, apr_sockaddr_t *sa) +{ +#if APR_HAVE_IPV6 + /* XXX This line will segv on Win32 build with APR_HAVE_IPV6, + * but without the IPV6 drivers installed. + */ + if (sa->sa.sin.sin_family == AF_INET) { + if (ipsub->family == AF_INET && + ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0])) { + return 1; + } + } + else if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)sa->ipaddr_ptr)) { + if (ipsub->family == AF_INET && + (((apr_uint32_t *)sa->ipaddr_ptr)[3] & ipsub->mask[0]) == ipsub->sub[0]) { + return 1; + } + } + else { + apr_uint32_t *addr = (apr_uint32_t *)sa->ipaddr_ptr; + + if ((addr[0] & ipsub->mask[0]) == ipsub->sub[0] && + (addr[1] & ipsub->mask[1]) == ipsub->sub[1] && + (addr[2] & ipsub->mask[2]) == ipsub->sub[2] && + (addr[3] & ipsub->mask[3]) == ipsub->sub[3]) { + return 1; + } + } +#else + if ((sa->sa.sin.sin_addr.s_addr & ipsub->mask[0]) == ipsub->sub[0]) { + return 1; + } +#endif /* APR_HAVE_IPV6 */ + return 0; /* no match */ +} diff --git a/srclib/apr/network_io/unix/sockets.c b/srclib/apr/network_io/unix/sockets.c new file mode 100644 index 0000000000..05ae6cce3c --- /dev/null +++ b/srclib/apr/network_io/unix/sockets.c @@ -0,0 +1,415 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_strings.h" +#include "apr_support.h" +#include "apr_portable.h" +#include "apr_arch_inherit.h" + +#ifdef BEOS_R5 +#undef close +#define close closesocket +#endif /* BEOS_R5 */ + +static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (close(thesocket->socketdes) == 0) { + thesocket->socketdes = -1; + return APR_SUCCESS; + } + else { + return errno; + } +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); + sock->options = 0; +#if defined(BEOS) && !defined(BEOS_BONE) + /* BeOS pre-BONE has TCP_NODELAY on by default and it can't be + * switched off! + */ + sock->options |= APR_TCP_NODELAY; +#endif +} + +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; +#ifndef WAITIO_USES_POLL + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); +#endif +} + +apr_status_t apr_socket_protocol_get(apr_socket_t *sock, int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +apr_status_t apr_socket_create(apr_socket_t **new, int ofamily, int type, + int protocol, apr_pool_t *cont) +{ + int family = ofamily; + + if (family == APR_UNSPEC) { +#if APR_HAVE_IPV6 + family = APR_INET6; +#else + family = APR_INET; +#endif + } + + alloc_socket(new, cont); + +#ifndef BEOS_R5 + (*new)->socketdes = socket(family, type, protocol); +#else + /* For some reason BeOS R5 has an unconventional protocol numbering, + * so we need to translate here. */ + switch (protocol) { + case 0: + (*new)->socketdes = socket(family, type, 0); + break; + case APR_PROTO_TCP: + (*new)->socketdes = socket(family, type, IPPROTO_TCP); + break; + case APR_PROTO_UDP: + (*new)->socketdes = socket(family, type, IPPROTO_UDP); + break; + case APR_PROTO_SCTP: + default: + errno = EPROTONOSUPPORT; + (*new)->socketdes = -1; + break; + } +#endif /* BEOS_R5 */ + +#if APR_HAVE_IPV6 + if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) { + family = APR_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes < 0) { + return errno; + } + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->inherit = 0; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), socket_cleanup, + socket_cleanup); + + return APR_SUCCESS; +} + +apr_status_t apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + return (shutdown(thesocket->socketdes, how) == -1) ? errno : APR_SUCCESS; +} + +apr_status_t apr_socket_close(apr_socket_t *thesocket) +{ + return apr_pool_cleanup_run(thesocket->cntxt, thesocket, socket_cleanup); +} + +apr_status_t apr_socket_bind(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, sa->salen) == -1) { + return errno; + } + else { + sock->local_addr = sa; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + if (sock->local_addr->sa.sin.sin_port == 0) { /* no need for ntohs() when comparing w/ 0 */ + sock->local_port_unknown = 1; /* kernel got us an ephemeral port */ + } + return APR_SUCCESS; + } +} + +apr_status_t apr_socket_listen(apr_socket_t *sock, apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == -1) + return errno; + else + return APR_SUCCESS; +} + +apr_status_t apr_socket_accept(apr_socket_t **new, apr_socket_t *sock, + apr_pool_t *connection_context) +{ + alloc_socket(new, connection_context); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, sock->protocol); + +#ifndef HAVE_POLL + (*new)->connected = 1; +#endif + (*new)->timeout = -1; + + (*new)->socketdes = accept(sock->socketdes, + (struct sockaddr *)&(*new)->remote_addr->sa, + &(*new)->remote_addr->salen); + + if ((*new)->socketdes < 0) { + return errno; + } +#ifdef TPF + if ((*new)->socketdes == 0) { + /* 0 is an invalid socket for TPF */ + return APR_EINTR; + } +#endif + + *(*new)->local_addr = *sock->local_addr; + + /* The above assignment just overwrote the pool entry. Setting the local_addr + pool for the accepted socket back to what it should be. Otherwise all + allocations for this socket will come from a server pool that is not + freed until the process goes down.*/ + (*new)->local_addr->pool = connection_context; + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } +#if APR_HAVE_IPV6 + else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; + } +#endif + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + if (sock->local_port_unknown) { + /* not likely for a listening socket, but theoretically possible :) */ + (*new)->local_port_unknown = 1; + } + +#if APR_TCP_NODELAY_INHERITED + if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) { + apr_set_option(*new, APR_TCP_NODELAY, 1); + } +#endif /* TCP_NODELAY_INHERITED */ +#if APR_O_NONBLOCK_INHERITED + if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { + apr_set_option(*new, APR_SO_NONBLOCK, 1); + } +#endif /* APR_O_NONBLOCK_INHERITED */ + + if (sock->local_interface_unknown || + !memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* If the interface address inside the listening socket's local_addr wasn't + * up-to-date, we don't know local interface of the connected socket either. + * + * If the listening socket was not bound to a specific interface, we + * don't know the local_addr of the connected socket. + */ + (*new)->local_interface_unknown = 1; + } + + (*new)->inherit = 0; + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), socket_cleanup, + socket_cleanup); + return APR_SUCCESS; +} + +apr_status_t apr_socket_connect(apr_socket_t *sock, apr_sockaddr_t *sa) +{ + int rc; + + do { + rc = connect(sock->socketdes, + (const struct sockaddr *)&sa->sa.sin, + sa->salen); + } while (rc == -1 && errno == EINTR); + + /* we can see EINPROGRESS the first time connect is called on a non-blocking + * socket; if called again, we can see EALREADY + */ + if ((rc == -1) && (errno == EINPROGRESS || errno == EALREADY) + && (sock->timeout > 0)) { + rc = apr_wait_for_io_or_timeout(NULL, sock, 0); + if (rc != APR_SUCCESS) { + return rc; + } + +#ifdef SO_ERROR + { + int error; + apr_socklen_t len = sizeof(error); + if ((rc = getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, + (char *)&error, &len)) < 0) { + return errno; + } + if (error) { + return error; + } + } +#endif /* SO_ERROR */ + } + + if (rc == -1 && errno != EISCONN) { + return errno; + } + + sock->remote_addr = sa; + if (sock->local_addr->port == 0) { + /* connect() got us an ephemeral port */ + sock->local_port_unknown = 1; + } + if (!memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* not bound to specific local interface; connect() had to assign + * one for the socket + */ + sock->local_interface_unknown = 1; + } +#ifndef HAVE_POLL + sock->connected=1; +#endif + return APR_SUCCESS; +} + +apr_status_t apr_socket_type_get(apr_socket_t *sock, int *type) +{ + *type = sock->type; + return APR_SUCCESS; +} + +apr_status_t apr_socket_data_get(void **data, const char *key, apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + +apr_status_t apr_socket_data_set(apr_socket_t *sock, void *data, const char *key, + apr_status_t (*cleanup) (void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_get(apr_os_sock_t *thesock, apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); + (*apr_sock)->timeout = -1; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { +#ifndef HAVE_POLL + (*apr_sock)->connected = 1; +#endif + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + (*apr_sock)->inherit = 0; + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, socket_cleanup); + return APR_SUCCESS; +} + +apr_status_t apr_os_sock_put(apr_socket_t **sock, apr_os_sock_t *thesock, + apr_pool_t *cont) +{ + /* XXX Bogus assumption that *sock points at anything legit */ + if ((*sock) == NULL) { + alloc_socket(sock, cont); + /* XXX IPv6 figure out the family here! */ + /* XXX figure out the actual socket type here */ + /* *or* just decide that apr_os_sock_put() has to be told the family and type */ + set_socket_vars(*sock, APR_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + } + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + +APR_IMPLEMENT_INHERIT_SET(socket, inherit, cntxt, socket_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(socket, inherit, cntxt, socket_cleanup) diff --git a/srclib/apr/network_io/unix/sockopt.c b/srclib/apr/network_io/unix/sockopt.c new file mode 100644 index 0000000000..4c45db1563 --- /dev/null +++ b/srclib/apr/network_io/unix/sockopt.c @@ -0,0 +1,391 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_strings.h" + + +static apr_status_t soblock(int sd) +{ +/* BeOS uses setsockopt at present for non blocking... */ +#ifndef BEOS + int fd_flags; + + fd_flags = fcntl(sd, F_GETFL, 0); +#if defined(O_NONBLOCK) + fd_flags &= ~O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags &= ~O_NDELAY; +#elif defined(FNDELAY) + fd_flags &= ~FNDELAY; +#else +#error Please teach APR how to make sockets blocking on your platform. +#endif + if (fcntl(sd, F_SETFL, fd_flags) == -1) { + return errno; + } +#else + int on = 0; + if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0) + return errno; +#endif /* BEOS */ + return APR_SUCCESS; +} + +static apr_status_t sononblock(int sd) +{ +#ifndef BEOS + int fd_flags; + + fd_flags = fcntl(sd, F_GETFL, 0); +#if defined(O_NONBLOCK) + fd_flags |= O_NONBLOCK; +#elif defined(O_NDELAY) + fd_flags |= O_NDELAY; +#elif defined(FNDELAY) + fd_flags |= FNDELAY; +#else +#error Please teach APR how to make sockets non-blocking on your platform. +#endif + if (fcntl(sd, F_SETFL, fd_flags) == -1) { + return errno; + } +#else + int on = 1; + if (setsockopt(sd, SOL_SOCKET, SO_NONBLOCK, &on, sizeof(int)) < 0) + return errno; +#endif /* BEOS */ + return APR_SUCCESS; +} + + +apr_status_t apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) +{ + apr_status_t stat; + + /* If our new timeout is non-negative and our old timeout was + * negative, then we need to ensure that we are non-blocking. + * Conversely, if our new timeout is negative and we had + * non-negative timeout, we must make sure our socket is blocking. + * We want to avoid calling fcntl more than necessary on the + * socket. + */ + if (t >= 0 && sock->timeout < 0) { + if (apr_is_option_set(sock, APR_SO_NONBLOCK) != 1) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) { + return stat; + } + apr_set_option(sock, APR_SO_NONBLOCK, 1); + } + } + else if (t < 0 && sock->timeout >= 0) { + if (apr_is_option_set(sock, APR_SO_NONBLOCK) != 0) { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) { + return stat; + } + apr_set_option(sock, APR_SO_NONBLOCK, 0); + } + } + /* must disable the incomplete read support if we disable + * a timeout + */ + if (t <= 0) { + sock->options &= ~APR_INCOMPLETE_READ; + } + sock->timeout = t; + return APR_SUCCESS; +} + + +apr_status_t apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + apr_status_t rv; + + if (on) + one = 1; + else + one = 0; + switch(opt) { + case APR_SO_KEEPALIVE: +#ifdef SO_KEEPALIVE + if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_KEEPALIVE, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_DEBUG: + if (on != apr_is_option_set(sock, APR_SO_DEBUG)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_DEBUG, on); + } + break; + case APR_SO_REUSEADDR: + if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, (void *)&one, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_REUSEADDR, on); + } + break; + case APR_SO_SNDBUF: +#ifdef SO_SNDBUF + if (apr_is_option_set(sock, APR_SO_SNDBUF) != on) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF, (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_SNDBUF, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_RCVBUF: +#ifdef SO_RCVBUF + if (apr_is_option_set(sock, APR_SO_RCVBUF) != on) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF, (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_RCVBUF, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_SO_NONBLOCK: + if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) { + if (on) { + if ((rv = sononblock(sock->socketdes)) != APR_SUCCESS) + return rv; + } + else { + if ((rv = soblock(sock->socketdes)) != APR_SUCCESS) + return rv; + } + apr_set_option(sock, APR_SO_NONBLOCK, on); + } + break; + case APR_SO_LINGER: +#ifdef SO_LINGER + if (apr_is_option_set(sock, APR_SO_LINGER) != on) { + struct linger li; + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, (char *) &li, sizeof(struct linger)) == -1) { + return errno; + } + apr_set_option(sock, APR_SO_LINGER, on); + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_TCP_DEFER_ACCEPT: +#if defined(TCP_DEFER_ACCEPT) + if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_DEFER_ACCEPT; + + if (setsockopt(sock->socketdes, optlevel, optname, + (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on); + } +#else + return APR_ENOTIMPL; +#endif + case APR_TCP_NODELAY: +#if defined(TCP_NODELAY) + if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + if (setsockopt(sock->socketdes, optlevel, optname, (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_TCP_NODELAY, on); + } +#else + /* BeOS pre-BONE has TCP_NODELAY set by default. + * As it can't be turned off we might as well check if they're asking + * for it to be turned on! + */ +#ifdef BEOS + if (on == 1) + return APR_SUCCESS; + else +#endif + return APR_ENOTIMPL; +#endif + break; + case APR_TCP_NOPUSH: +#if APR_TCP_NOPUSH_FLAG + if (apr_is_option_set(sock, APR_TCP_NOPUSH) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + /* OK we're going to change some settings here... */ + /* TCP_NODELAY is mutually exclusive, so do we have it set? */ + if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1 && on) { + /* If we want to set NOPUSH then if we have the TCP_NODELAY + * flag set we need to switch it off... + */ + int tmpflag = 0; + if (setsockopt(sock->socketdes, optlevel, optname, + (void*)&tmpflag, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_RESET_NODELAY, 1); + apr_set_option(sock, APR_TCP_NODELAY, 0); + } else if (on) { + apr_set_option(sock, APR_RESET_NODELAY, 0); + } + /* OK, now we can just set the TCP_NOPUSH flag accordingly...*/ + if (setsockopt(sock->socketdes, IPPROTO_TCP, APR_TCP_NOPUSH_FLAG, + (void*)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_TCP_NOPUSH, on); + if (!on && apr_is_option_set(sock, APR_RESET_NODELAY)) { + int tmpflag = 1; + if (setsockopt(sock->socketdes, optlevel, optname, + (void*)&tmpflag, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_RESET_NODELAY,0); + apr_set_option(sock, APR_TCP_NODELAY, 1); + } + } +#else + return APR_ENOTIMPL; +#endif + break; + case APR_INCOMPLETE_READ: + apr_set_option(sock, APR_INCOMPLETE_READ, on); + break; + case APR_IPV6_V6ONLY: +#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY) + /* we don't know the initial setting of this option, + * so don't check sock->options since that optimization + * won't work + */ + if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_IPV6_V6ONLY, on); +#else + return APR_ENOTIMPL; +#endif + break; + default: + return APR_EINVAL; + } + + return APR_SUCCESS; +} + + +apr_status_t apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +apr_status_t apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch(opt) { + default: + *on = apr_is_option_set(sock, opt); + } + return APR_SUCCESS; +} + + +apr_status_t apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ +#ifndef BEOS_R5 + int oobmark; + + if (ioctl(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0) + return apr_get_netos_error(); + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +#else /* BEOS_R5 */ + return APR_ENOTIMPL; +#endif +} + +apr_status_t apr_gethostname(char *buf, apr_int32_t len, apr_pool_t *cont) +{ +#ifdef BEOS_R5 + if (gethostname(buf, len) == 0) { +#else + if (gethostname(buf, len) != 0) { +#endif + buf[0] = '\0'; + return errno; + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + /* note... most platforms just truncate in this condition + * linux+glibc return an error + */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} + +#if APR_HAS_SO_ACCEPTFILTER +apr_status_t apr_socket_accept_filter(apr_socket_t *sock, char *name, + char *args) +{ + struct accept_filter_arg af; + strncpy(af.af_name, name, 16); + strncpy(af.af_arg, args, 256 - 16); + + if ((setsockopt(sock->socketdes, SOL_SOCKET, SO_ACCEPTFILTER, + &af, sizeof(af))) < 0) { + return errno; + } + return APR_SUCCESS; +} +#endif diff --git a/srclib/apr/network_io/win32/sendrecv.c b/srclib/apr/network_io/win32/sendrecv.c new file mode 100644 index 0000000000..5f5df4802f --- /dev/null +++ b/srclib/apr/network_io/win32/sendrecv.c @@ -0,0 +1,451 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_lib.h" +#include "apr_arch_file_io.h" +#if APR_HAVE_TIME_H +#include +#endif + +/* MAX_SEGMENT_SIZE is the maximum amount of data that will be sent to a client + * in one call of TransmitFile. This number must be small enough to give the + * slowest client time to receive the data before the socket timeout triggers. + * The same problem can exist with apr_socket_send(). In that case, we rely on + * the application to adjust socket timeouts and max send segment + * sizes appropriately. + * For example, Apache will in most cases call apr_socket_send() with less + * than 8193 bytes. + */ +#define MAX_SEGMENT_SIZE 65536 +#define WSABUF_ON_STACK 50 + +APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + WSABUF wsaData; + int lasterror; + DWORD dwBytes = 0; + + wsaData.len = (u_long)*len; + wsaData.buf = (char*) buf; + +#ifndef _WIN32_WCE + rv = WSASend(sock->socketdes, &wsaData, 1, &dwBytes, 0, NULL, NULL); +#else + rv = send(sock->socketdes, wsaData.buf, wsaData.len, 0); + dwBytes = rv; +#endif + if (rv == SOCKET_ERROR) { + lasterror = apr_get_netos_error(); + return lasterror; + } + + *len = dwBytes; + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + WSABUF wsaData; + int lasterror; + DWORD dwBytes = 0; + DWORD flags = 0; + + wsaData.len = (u_long)*len; + wsaData.buf = (char*) buf; + +#ifndef _WIN32_WCE + rv = WSARecv(sock->socketdes, &wsaData, 1, &dwBytes, &flags, NULL, NULL); +#else + rv = recv(sock->socketdes, wsaData.buf, wsaData.len, 0); + dwBytes = rv; +#endif + if (rv == SOCKET_ERROR) { + lasterror = apr_get_netos_error(); + *len = 0; + return lasterror; + } + + *len = dwBytes; + return dwBytes == 0 ? APR_EOF : APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, + const struct iovec *vec, + apr_int32_t in_vec, apr_size_t *nbytes) +{ + apr_status_t rc = APR_SUCCESS; + apr_ssize_t rv; + apr_size_t cur_len; + apr_int32_t nvec = 0; + int i, j = 0; + DWORD dwBytes = 0; + WSABUF *pWsaBuf; + + for (i = 0; i < in_vec; i++) { + cur_len = vec[i].iov_len; + nvec++; + while (cur_len > APR_DWORD_MAX) { + nvec++; + cur_len -= APR_DWORD_MAX; + } + } + + pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec)) + : malloc(sizeof(WSABUF) * (nvec)); + if (!pWsaBuf) + return APR_ENOMEM; + + for (i = 0; i < in_vec; i++) { + char * base = vec[i].iov_base; + cur_len = vec[i].iov_len; + + do { + if (cur_len > APR_DWORD_MAX) { + pWsaBuf[j].buf = base; + pWsaBuf[j].len = APR_DWORD_MAX; + cur_len -= APR_DWORD_MAX; + base += APR_DWORD_MAX; + } + else { + pWsaBuf[j].buf = base; + pWsaBuf[j].len = (DWORD)cur_len; + cur_len = 0; + } + j++; + + } while (cur_len > 0); + } +#ifndef _WIN32_WCE + rv = WSASend(sock->socketdes, pWsaBuf, nvec, &dwBytes, 0, NULL, NULL); + if (rv == SOCKET_ERROR) { + rc = apr_get_netos_error(); + } +#else + for (i = 0; i < nvec; i++) { + rv = send(sock->socketdes, pWsaBuf[i].buf, pWsaBuf[i].len, 0); + if (rv == SOCKET_ERROR) { + rc = apr_get_netos_error(); + break; + } + dwBytes += rv; + } +#endif + if (nvec > WSABUF_ON_STACK) + free(pWsaBuf); + + *nbytes = dwBytes; + return rc; +} + + +APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, + apr_sockaddr_t *where, + apr_int32_t flags, const char *buf, + apr_size_t *len) +{ + apr_ssize_t rv; + + rv = sendto(sock->socketdes, buf, (int)*len, flags, + (const struct sockaddr*)&where->sa, + where->salen); + if (rv == SOCKET_ERROR) { + *len = 0; + return apr_get_netos_error(); + } + + *len = rv; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, + apr_socket_t *sock, + apr_int32_t flags, + char *buf, apr_size_t *len) +{ + apr_ssize_t rv; + + rv = recvfrom(sock->socketdes, buf, (int)*len, flags, + (struct sockaddr*)&from->sa, &from->salen); + if (rv == SOCKET_ERROR) { + (*len) = 0; + return apr_get_netos_error(); + } + (*len) = rv; + if (rv == 0 && sock->type == SOCK_STREAM) + return APR_EOF; + + return APR_SUCCESS; +} + + +static apr_status_t collapse_iovec(char **off, apr_size_t *len, + struct iovec *iovec, int numvec, + char *buf, apr_size_t buflen) +{ + if (numvec == 1) { + *off = iovec[0].iov_base; + *len = iovec[0].iov_len; + } + else { + int i; + for (i = 0; i < numvec; i++) { + *len += iovec[i].iov_len; + } + + if (*len > buflen) { + *len = 0; + return APR_INCOMPLETE; + } + + *off = buf; + + for (i = 0; i < numvec; i++) { + memcpy(buf, iovec[i].iov_base, iovec[i].iov_len); + buf += iovec[i].iov_len; + } + } + return APR_SUCCESS; +} + + +#if APR_HAS_SENDFILE +/* + * apr_status_t apr_socket_sendfile(apr_socket_t *, apr_file_t *, apr_hdtr_t *, + * apr_off_t *, apr_size_t *, apr_int32_t flags) + * Send a file from an open file descriptor to a socket, along with + * optional headers and trailers + * arg 1) The socket to which we're writing + * arg 2) The open file from which to read + * arg 3) A structure containing the headers and trailers to send + * arg 4) Offset into the file where we should begin writing + * arg 5) Number of bytes to send out of the file + * arg 6) APR flags that are mapped to OS specific flags + */ +APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, + apr_file_t *file, + apr_hdtr_t *hdtr, + apr_off_t *offset, + apr_size_t *len, + apr_int32_t flags) +{ + apr_status_t status = APR_SUCCESS; + apr_status_t rv; + apr_off_t curoff = *offset; + DWORD dwFlags = 0; + apr_size_t nbytes; + TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL; + int ptr = 0; + apr_size_t bytes_to_send; /* Bytes to send out of the file (not including headers) */ + int disconnected = 0; + int sendv_trailers = 0; + char hdtrbuf[4096]; + + if (apr_os_level < APR_WIN_NT) { + return APR_ENOTIMPL; + } + + /* Use len to keep track of number of total bytes sent (including headers) */ + bytes_to_send = *len; + *len = 0; + + /* Handle the goofy case of sending headers/trailers and a zero byte file */ + if (!bytes_to_send && hdtr) { + if (hdtr->numheaders) { + rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, + &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + if (hdtr->numtrailers) { + rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, + &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + return APR_SUCCESS; + } + + memset(&tfb, '\0', sizeof (tfb)); + + /* Collapse the headers into a single buffer */ + if (hdtr && hdtr->numheaders) { + apr_size_t head_length = tfb.HeadLength; + ptfb = &tfb; + nbytes = 0; + rv = collapse_iovec((char **)&ptfb->Head, &head_length, + hdtr->headers, hdtr->numheaders, + hdtrbuf, sizeof(hdtrbuf)); + + tfb.HeadLength = (DWORD)head_length; + + /* If not enough buffer, punt to sendv */ + if (rv == APR_INCOMPLETE) { + rv = apr_socket_sendv(sock, hdtr->headers, hdtr->numheaders, &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + ptfb = NULL; + } + } + + /* Initialize the overlapped structure used on TransmitFile + */ + if (!sock->overlapped) { + sock->overlapped = apr_pcalloc(sock->cntxt, sizeof(OVERLAPPED)); + sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + } + while (bytes_to_send) { + DWORD xmitbytes; + + if (bytes_to_send > MAX_SEGMENT_SIZE) { + xmitbytes = MAX_SEGMENT_SIZE; + } + else { + /* Last call to TransmitFile() */ + xmitbytes = (DWORD)bytes_to_send; + /* Collapse the trailers into a single buffer */ + if (hdtr && hdtr->numtrailers) { + apr_size_t tail_length = tfb.TailLength; + ptfb = &tfb; + rv = collapse_iovec((char**) &ptfb->Tail, &tail_length, + hdtr->trailers, hdtr->numtrailers, + hdtrbuf + ptfb->HeadLength, + sizeof(hdtrbuf) - ptfb->HeadLength); + + tfb.TailLength = (DWORD)tail_length; + + if (rv == APR_INCOMPLETE) { + /* If not enough buffer, punt to sendv, later */ + sendv_trailers = 1; + } + } + /* Disconnect the socket after last send */ + if ((flags & APR_SENDFILE_DISCONNECT_SOCKET) + && !sendv_trailers) { + dwFlags |= TF_REUSE_SOCKET; + dwFlags |= TF_DISCONNECT; + disconnected = 1; + } + } + + sock->overlapped->Offset = (DWORD)(curoff); +#if APR_HAS_LARGE_FILES + sock->overlapped->OffsetHigh = (DWORD)(curoff >> 32); +#endif + /* XXX BoundsChecker claims dwFlags must not be zero. */ + rv = TransmitFile(sock->socketdes, /* socket */ + file->filehand, /* open file descriptor of the file to be sent */ + xmitbytes, /* number of bytes to send. 0=send all */ + 0, /* Number of bytes per send. 0=use default */ + sock->overlapped, /* OVERLAPPED structure */ + ptfb, /* header and trailer buffers */ + dwFlags); /* flags to control various aspects of TransmitFile */ + if (!rv) { + status = apr_get_netos_error(); + if ((status == APR_FROM_OS_ERROR(ERROR_IO_PENDING)) || + (status == APR_FROM_OS_ERROR(WSA_IO_PENDING))) + { + rv = WaitForSingleObject(sock->overlapped->hEvent, + (DWORD)(sock->timeout >= 0 + ? sock->timeout_ms : INFINITE)); + if (rv == WAIT_OBJECT_0) { + status = APR_SUCCESS; + if (!disconnected) { + if (!WSAGetOverlappedResult(sock->socketdes, + sock->overlapped, + &xmitbytes, + FALSE, + &dwFlags)) { + status = apr_get_netos_error(); + } + /* Ugly code alert: WSAGetOverlappedResult returns + * a count of all bytes sent. This loop only + * tracks bytes sent out of the file. + */ + else if (ptfb) { + xmitbytes -= (ptfb->HeadLength + ptfb->TailLength); + } + } + } + else if (rv == WAIT_TIMEOUT) { + status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); + } + else if (rv == WAIT_ABANDONED) { + /* Hummm... WAIT_ABANDONDED is not an error code. It is + * a return specific to the Win32 WAIT functions that + * indicates that a thread exited while holding a + * mutex. Should consider triggering an assert + * to detect the condition... + */ + status = APR_FROM_OS_ERROR(WAIT_TIMEOUT); + } + else + status = apr_get_os_error(); + } + } + if (status != APR_SUCCESS) + break; + + bytes_to_send -= xmitbytes; + curoff += xmitbytes; + *len += xmitbytes; + /* Adjust len for any headers/trailers sent */ + if (ptfb) { + *len += (ptfb->HeadLength + ptfb->TailLength); + memset(&tfb, '\0', sizeof (tfb)); + ptfb = NULL; + } + } + + if (status == APR_SUCCESS) { + if (sendv_trailers) { + rv = apr_socket_sendv(sock, hdtr->trailers, hdtr->numtrailers, &nbytes); + if (rv != APR_SUCCESS) + return rv; + *len += nbytes; + } + + + /* Mark the socket as disconnected, but do not close it. + * Note: The application must have stored the socket prior to making + * the call to apr_socket_sendfile in order to either reuse it + * or close it. + */ + if (disconnected) { + sock->disconnected = 1; + sock->socketdes = INVALID_SOCKET; + } + } + + return status; +} + +#endif + diff --git a/srclib/apr/network_io/win32/sockets.c b/srclib/apr/network_io/win32/sockets.c new file mode 100644 index 0000000000..d095f4bacd --- /dev/null +++ b/srclib/apr/network_io/win32/sockets.c @@ -0,0 +1,497 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "apr_strings.h" +#include +#include "apr_arch_inherit.h" +#include "apr_arch_misc.h" + +static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ + +static apr_status_t socket_cleanup(void *sock) +{ + apr_socket_t *thesocket = sock; + + if (thesocket->socketdes != INVALID_SOCKET) { + if (closesocket(thesocket->socketdes) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + thesocket->socketdes = INVALID_SOCKET; + } +#if APR_HAS_SENDFILE + if (thesocket->overlapped) { + CloseHandle(thesocket->overlapped->hEvent); + thesocket->overlapped = NULL; + } +#endif + return APR_SUCCESS; +} + +static void set_socket_vars(apr_socket_t *sock, int family, int type, int protocol) +{ + sock->type = type; + sock->protocol = protocol; + apr_sockaddr_vars_set(sock->local_addr, family, 0); + apr_sockaddr_vars_set(sock->remote_addr, family, 0); +} +static void alloc_socket(apr_socket_t **new, apr_pool_t *p) +{ + *new = (apr_socket_t *)apr_pcalloc(p, sizeof(apr_socket_t)); + (*new)->cntxt = p; + (*new)->local_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->local_addr->pool = p; + (*new)->remote_addr = (apr_sockaddr_t *)apr_pcalloc((*new)->cntxt, + sizeof(apr_sockaddr_t)); + (*new)->remote_addr->pool = p; + + /* Create a pollset with room for one descriptor. */ + /* ### check return codes */ + (void) apr_pollset_create(&(*new)->pollset, 1, p, 0); +} + +APR_DECLARE(apr_status_t) apr_socket_protocol_get(apr_socket_t *sock, + int *protocol) +{ + *protocol = sock->protocol; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new, int family, + int type, int protocol, + apr_pool_t *cont) +{ + int downgrade = (family == AF_UNSPEC); + + if (family == AF_UNSPEC) { +#if APR_HAVE_IPV6 + family = AF_INET6; +#else + family = AF_INET; +#endif + } + + alloc_socket(new, cont); + + /* For right now, we are not using socket groups. We may later. + * No flags to use when creating a socket, so use 0 for that parameter as well. + */ + (*new)->socketdes = socket(family, type, protocol); +#if APR_HAVE_IPV6 + if ((*new)->socketdes == INVALID_SOCKET && downgrade) { + family = AF_INET; + (*new)->socketdes = socket(family, type, protocol); + } +#endif + + if ((*new)->socketdes == INVALID_SOCKET) { + return apr_get_netos_error(); + } + +#ifdef WIN32 + /* Socket handles are never truly inheritable, there are too many + * bugs associated. WSADuplicateSocket will copy them, but for our + * purposes, always transform the socket() created as a non-inherited + * handle + */ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE { + /* A different approach. Many users report errors such as + * (32538)An operation was attempted on something that is not + * a socket. : Parent: WSADuplicateSocket failed... + * + * This appears that the duplicated handle is no longer recognized + * as a socket handle. SetHandleInformation should overcome that + * problem by not altering the handle identifier. But this won't + * work on 9x - it's unsupported. + */ + SetHandleInformation((HANDLE) (*new)->socketdes, + HANDLE_FLAG_INHERIT, 0); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI { + HANDLE hProcess = GetCurrentProcess(); + HANDLE dup; + if (DuplicateHandle(hProcess, (HANDLE) (*new)->socketdes, hProcess, + &dup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { + closesocket((*new)->socketdes); + (*new)->socketdes = (SOCKET) dup; + } + } +#endif + +#endif /* def WIN32 */ + + set_socket_vars(*new, family, type, protocol); + + (*new)->timeout = -1; + (*new)->disconnected = 0; + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_shutdown(apr_socket_t *thesocket, + apr_shutdown_how_e how) +{ + int winhow = 0; + +#ifdef SD_RECEIVE + switch (how) { + case APR_SHUTDOWN_READ: { + winhow = SD_RECEIVE; + break; + } + case APR_SHUTDOWN_WRITE: { + winhow = SD_SEND; + break; + } + case APR_SHUTDOWN_READWRITE: { + winhow = SD_BOTH; + break; + } + default: + return APR_BADARG; + } +#endif + if (shutdown(thesocket->socketdes, winhow) == 0) { + return APR_SUCCESS; + } + else { + return apr_get_netos_error(); + } +} + +APR_DECLARE(apr_status_t) apr_socket_close(apr_socket_t *thesocket) +{ + apr_pool_cleanup_kill(thesocket->cntxt, thesocket, socket_cleanup); + return socket_cleanup(thesocket); +} + +APR_DECLARE(apr_status_t) apr_socket_bind(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + if (bind(sock->socketdes, + (struct sockaddr *)&sa->sa, + sa->salen) == -1) { + return apr_get_netos_error(); + } + else { + sock->local_addr = sa; + if (sock->local_addr->sa.sin.sin_port == 0) { + sock->local_port_unknown = 1; /* ephemeral port */ + } + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_socket_listen(apr_socket_t *sock, + apr_int32_t backlog) +{ + if (listen(sock->socketdes, backlog) == SOCKET_ERROR) + return apr_get_netos_error(); + else + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_accept(apr_socket_t **new, + apr_socket_t *sock, apr_pool_t *p) +{ + SOCKET s; +#if APR_HAVE_IPV6 + struct sockaddr_storage sa; +#else + struct sockaddr sa; +#endif + int salen = sizeof(sock->remote_addr->sa); + + /* Don't allocate the memory until after we call accept. This allows + us to work with nonblocking sockets. */ + s = accept(sock->socketdes, (struct sockaddr *)&sa, &salen); + if (s == INVALID_SOCKET) { + return apr_get_netos_error(); + } + + alloc_socket(new, p); + set_socket_vars(*new, sock->local_addr->sa.sin.sin_family, SOCK_STREAM, + sock->protocol); + + (*new)->timeout = -1; + (*new)->disconnected = 0; + + (*new)->socketdes = s; + /* XXX next line looks bogus w.r.t. AF_INET6 support */ + (*new)->remote_addr->salen = sizeof((*new)->remote_addr->sa); + memcpy (&(*new)->remote_addr->sa, &sa, salen); + *(*new)->local_addr = *sock->local_addr; + + /* The above assignment just overwrote the pool entry. Setting the local_addr + pool for the accepted socket back to what it should be. Otherwise all + allocations for this socket will come from a server pool that is not + freed until the process goes down.*/ + (*new)->local_addr->pool = p; + + /* fix up any pointers which are no longer valid */ + if (sock->local_addr->sa.sin.sin_family == AF_INET) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin.sin_addr; + } +#if APR_HAVE_IPV6 + else if (sock->local_addr->sa.sin.sin_family == AF_INET6) { + (*new)->local_addr->ipaddr_ptr = &(*new)->local_addr->sa.sin6.sin6_addr; + } +#endif + (*new)->remote_addr->port = ntohs((*new)->remote_addr->sa.sin.sin_port); + if (sock->local_port_unknown) { + /* not likely for a listening socket, but theoretically possible :) */ + (*new)->local_port_unknown = 1; + } + +#if APR_TCP_NODELAY_INHERITED + if (apr_is_option_set(sock, APR_TCP_NODELAY) == 1) { + apr_set_option(*new, APR_TCP_NODELAY, 1); + } +#endif /* TCP_NODELAY_INHERITED */ +#if APR_O_NONBLOCK_INHERITED + if (apr_is_option_set(sock, APR_SO_NONBLOCK) == 1) { + apr_set_option(*new, APR_SO_NONBLOCK, 1); + } +#endif /* APR_O_NONBLOCK_INHERITED */ + + if (sock->local_interface_unknown || + !memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* If the interface address inside the listening socket's local_addr wasn't + * up-to-date, we don't know local interface of the connected socket either. + * + * If the listening socket was not bound to a specific interface, we + * don't know the local_addr of the connected socket. + */ + (*new)->local_interface_unknown = 1; + } + + apr_pool_cleanup_register((*new)->cntxt, (void *)(*new), + socket_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_connect(apr_socket_t *sock, + apr_sockaddr_t *sa) +{ + apr_status_t rv; + + if ((sock->socketdes == INVALID_SOCKET) || (!sock->local_addr)) { + return APR_ENOTSOCK; + } + + if (connect(sock->socketdes, (const struct sockaddr *)&sa->sa.sin, + sa->salen) == SOCKET_ERROR) { + int rc; + struct timeval tv, *tvptr; + fd_set wfdset, efdset; + + rv = apr_get_netos_error(); + if (rv != APR_FROM_OS_ERROR(WSAEWOULDBLOCK)) { + return rv; + } + + if (sock->timeout == 0) { + /* Tell the app that the connect is in progress... + * Gotta play some games here. connect on Unix will return + * EINPROGRESS under the same circumstances that Windows + * returns WSAEWOULDBLOCK. Do some adhoc canonicalization... + */ + return APR_FROM_OS_ERROR(WSAEINPROGRESS); + } + + /* wait for the connect to complete or timeout */ + FD_ZERO(&wfdset); + FD_SET(sock->socketdes, &wfdset); + FD_ZERO(&efdset); + FD_SET(sock->socketdes, &efdset); + + if (sock->timeout < 0) { + tvptr = NULL; + } + else { + /* casts for winsock/timeval definition */ + tv.tv_sec = (long)apr_time_sec(sock->timeout); + tv.tv_usec = (int)apr_time_usec(sock->timeout); + tvptr = &tv; + } + rc = select(FD_SETSIZE+1, NULL, &wfdset, &efdset, tvptr); + if (rc == SOCKET_ERROR) { + return apr_get_netos_error(); + } + else if (!rc) { + return APR_FROM_OS_ERROR(WSAETIMEDOUT); + } + /* Evaluate the efdset */ + if (FD_ISSET(sock->socketdes, &efdset)) { + /* The connect failed. */ + int rclen = sizeof(rc); + if (getsockopt(sock->socketdes, SOL_SOCKET, SO_ERROR, (char*) &rc, &rclen)) { + return apr_get_netos_error(); + } + return APR_FROM_OS_ERROR(rc); + } + } + /* connect was OK .. amazing */ + sock->remote_addr = sa; + if (sock->local_addr->sa.sin.sin_port == 0) { + sock->local_port_unknown = 1; + } + if (!memcmp(sock->local_addr->ipaddr_ptr, + generic_inaddr_any, + sock->local_addr->ipaddr_len)) { + /* not bound to specific local interface; connect() had to assign + * one for the socket + */ + sock->local_interface_unknown = 1; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_type_get(apr_socket_t *sock, int *type) +{ + *type = sock->type; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_data_get(void **data, const char *key, + apr_socket_t *sock) +{ + sock_userdata_t *cur = sock->userdata; + + *data = NULL; + + while (cur) { + if (!strcmp(cur->key, key)) { + *data = cur->data; + break; + } + cur = cur->next; + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, + const char *key, + apr_status_t (*cleanup)(void *)) +{ + sock_userdata_t *new = apr_palloc(sock->cntxt, sizeof(sock_userdata_t)); + + new->key = apr_pstrdup(sock->cntxt, key); + new->data = data; + new->next = sock->userdata; + sock->userdata = new; + + if (cleanup) { + apr_pool_cleanup_register(sock->cntxt, data, cleanup, cleanup); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_sock_t *thesock, + apr_socket_t *sock) +{ + *thesock = sock->socketdes; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_make(apr_socket_t **apr_sock, + apr_os_sock_info_t *os_sock_info, + apr_pool_t *cont) +{ + alloc_socket(apr_sock, cont); + set_socket_vars(*apr_sock, os_sock_info->family, os_sock_info->type, os_sock_info->protocol); + (*apr_sock)->timeout = -1; + (*apr_sock)->disconnected = 0; + (*apr_sock)->socketdes = *os_sock_info->os_sock; + if (os_sock_info->local) { + memcpy(&(*apr_sock)->local_addr->sa.sin, + os_sock_info->local, + (*apr_sock)->local_addr->salen); + (*apr_sock)->local_addr->pool = cont; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->local_addr->port = ntohs((*apr_sock)->local_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->local_port_unknown = (*apr_sock)->local_interface_unknown = 1; + } + if (os_sock_info->remote) { + memcpy(&(*apr_sock)->remote_addr->sa.sin, + os_sock_info->remote, + (*apr_sock)->remote_addr->salen); + (*apr_sock)->remote_addr->pool = cont; + /* XXX IPv6 - this assumes sin_port and sin6_port at same offset */ + (*apr_sock)->remote_addr->port = ntohs((*apr_sock)->remote_addr->sa.sin.sin_port); + } + else { + (*apr_sock)->remote_addr_unknown = 1; + } + + apr_pool_cleanup_register((*apr_sock)->cntxt, (void *)(*apr_sock), + socket_cleanup, apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_sock_put(apr_socket_t **sock, + apr_os_sock_t *thesock, + apr_pool_t *cont) +{ + if ((*sock) == NULL) { + alloc_socket(sock, cont); + /* XXX figure out the actual socket type here */ + /* *or* just decide that apr_os_sock_put() has to be told the family and type */ + set_socket_vars(*sock, AF_INET, SOCK_STREAM, 0); + (*sock)->timeout = -1; + (*sock)->disconnected = 0; + } + (*sock)->local_port_unknown = (*sock)->local_interface_unknown = 1; + (*sock)->remote_addr_unknown = 1; + (*sock)->socketdes = *thesock; + return APR_SUCCESS; +} + + +/* Sockets cannot be inherited through the standard sockets + * inheritence. WSADuplicateSocket must be used. + * This is not trivial to implement. + */ + +APR_DECLARE(apr_status_t) apr_socket_inherit_set(apr_socket_t *socket) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_socket_inherit_unset(apr_socket_t *socket) +{ + return APR_ENOTIMPL; +} + + diff --git a/srclib/apr/network_io/win32/sockopt.c b/srclib/apr/network_io/win32/sockopt.c new file mode 100644 index 0000000000..7f38aa7036 --- /dev/null +++ b/srclib/apr/network_io/win32/sockopt.c @@ -0,0 +1,261 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_networkio.h" +#include "apr_network_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include + +apr_status_t soblock(SOCKET sd) +{ + u_long zero = 0; + + if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + return APR_SUCCESS; +} + +apr_status_t sononblock(SOCKET sd) +{ + u_long one = 1; + + if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) { + return apr_get_netos_error(); + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t) +{ + apr_status_t stat; + + if (t == 0) { + /* Set the socket non-blocking if it was previously blocking */ + if (sock->timeout != 0) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + } + else if (t > 0) { + /* Set the socket to blocking if it was previously non-blocking */ + if (sock->timeout == 0) { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + /* Reset socket timeouts if the new timeout differs from the old timeout */ + if (sock->timeout != t) + { + /* Win32 timeouts are in msec, represented as int */ + sock->timeout_ms = (int)apr_time_as_msec(t); + setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, + (char *) &sock->timeout_ms, + sizeof(sock->timeout_ms)); + setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, + (char *) &sock->timeout_ms, + sizeof(sock->timeout_ms)); + } + } + else if (t < 0) { + int zero = 0; + /* Set the socket to blocking with infinite timeouts */ + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, + (char *) &zero, sizeof(zero)); + setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, + (char *) &zero, sizeof(zero)); + } + sock->timeout = t; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t on) +{ + int one; + apr_status_t stat; + + one = on ? 1 : 0; + + switch (opt) { + case APR_SO_KEEPALIVE: + if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_SO_KEEPALIVE, on); + } + break; + case APR_SO_DEBUG: + if (on != apr_is_option_set(sock, APR_SO_DEBUG)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_SO_DEBUG, on); + } + break; + case APR_SO_REUSEADDR: + if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) { + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, + (void *)&one, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_SO_REUSEADDR, on); + } + break; + case APR_SO_NONBLOCK: + if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) { + if (on) { + if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + else { + if ((stat = soblock(sock->socketdes)) != APR_SUCCESS) + return stat; + } + apr_set_option(sock, APR_SO_NONBLOCK, on); + } + break; + case APR_SO_LINGER: + { + if (apr_is_option_set(sock, APR_SO_LINGER) != on) { + struct linger li; + li.l_onoff = on; + li.l_linger = APR_MAX_SECS_TO_LINGER; + if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, + (char *) &li, sizeof(struct linger)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_SO_LINGER, on); + } + break; + } + case APR_TCP_DEFER_ACCEPT: +#if defined(TCP_DEFER_ACCEPT) + if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_DEFER_ACCEPT; + + if (setsockopt(sock->socketdes, optlevel, optname, + (void *)&on, sizeof(int)) == -1) { + return errno; + } + apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on); + } +#else + return APR_ENOTIMPL; +#endif + case APR_TCP_NODELAY: + if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) { + int optlevel = IPPROTO_TCP; + int optname = TCP_NODELAY; + +#if APR_HAVE_SCTP + if (sock->protocol == IPPROTO_SCTP) { + optlevel = IPPROTO_SCTP; + optname = SCTP_NODELAY; + } +#endif + if (setsockopt(sock->socketdes, optlevel, optname, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_TCP_NODELAY, on); + } + break; + case APR_IPV6_V6ONLY: +#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY) + /* we don't know the initial setting of this option, + * so don't check sock->options since that optimization + * won't work + */ + if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY, + (void *)&on, sizeof(int)) == -1) { + return apr_get_netos_error(); + } + apr_set_option(sock, APR_IPV6_V6ONLY, on); +#else + return APR_ENOTIMPL; +#endif + break; + default: + return APR_EINVAL; + break; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t) +{ + *t = sock->timeout; + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock, + apr_int32_t opt, apr_int32_t *on) +{ + switch (opt) { + case APR_SO_DISCONNECTED: + *on = sock->disconnected; + break; + case APR_SO_KEEPALIVE: + case APR_SO_DEBUG: + case APR_SO_REUSEADDR: + case APR_SO_NONBLOCK: + case APR_SO_LINGER: + default: + *on = apr_is_option_set(sock, opt); + break; + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark) +{ + u_long oobmark; + + if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0) + return apr_get_netos_error(); + + *atmark = (oobmark != 0); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len, + apr_pool_t *cont) +{ + if (gethostname(buf, len) == -1) { + buf[0] = '\0'; + return apr_get_netos_error(); + } + else if (!memchr(buf, '\0', len)) { /* buffer too small */ + buf[0] = '\0'; + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} + diff --git a/srclib/apr/passwd/apr_getpass.c b/srclib/apr/passwd/apr_getpass.c new file mode 100644 index 0000000000..c8dcf3e5fd --- /dev/null +++ b/srclib/apr/passwd/apr_getpass.c @@ -0,0 +1,233 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* apr_password_get.c: abstraction to provide for obtaining a password from the + * command line in whatever way the OS supports. In the best case, it's a + * wrapper for the system library's getpass() routine; otherwise, we + * use one we define ourselves. + */ +#include "apr_private.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_errno.h" +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_ERRNO_H +#include +#endif + +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_CONIO_H +#pragma warning(disable: 4032) +#include +#pragma warning(default: 4032) +#endif +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif + +#if defined(HAVE_TERMIOS_H) && !defined(HAVE_GETPASS) +#include +#endif + +#if !APR_CHARSET_EBCDIC +#define LF 10 +#define CR 13 +#else /* APR_CHARSET_EBCDIC */ +#define LF '\n' +#define CR '\r' +#endif /* APR_CHARSET_EBCDIC */ + +#define MAX_STRING_LEN 256 + +#define ERR_OVERFLOW 5 + +#ifndef HAVE_GETPASS + +/* MPE, Win32, NetWare and BeOS all lack a native getpass() */ + +#if !defined(HAVE_TERMIOS_H) && !defined(WIN32) && !defined(NETWARE) +/* + * MPE lacks getpass() and a way to suppress stdin echo. So for now, just + * issue the prompt and read the results with echo. (Ugh). + */ + +static char *getpass(const char *prompt) +{ + static char password[MAX_STRING_LEN]; + + fputs(prompt, stderr); + fgets((char *) &password, sizeof(password), stdin); + + return (char *) &password; +} + +#elif defined (HAVE_TERMIOS_H) +#include + +static char *getpass(const char *prompt) +{ + struct termios attr; + static char password[MAX_STRING_LEN]; + int n=0; + fputs(prompt, stderr); + fflush(stderr); + + if (tcgetattr(STDIN_FILENO, &attr) != 0) + return NULL; + attr.c_lflag &= ~(ECHO); + + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &attr) != 0) + return NULL; + while ((password[n] = getchar()) != '\n') { + if (n < sizeof(password) - 1 && password[n] >= ' ' && password[n] <= '~') { + n++; + } else { + fprintf(stderr,"\n"); + fputs(prompt, stderr); + fflush(stderr); + n = 0; + } + } + + password[n] = '\0'; + printf("\n"); + if (n > (MAX_STRING_LEN - 1)) { + password[MAX_STRING_LEN - 1] = '\0'; + } + + attr.c_lflag |= ECHO; + tcsetattr(STDIN_FILENO, TCSANOW, &attr); + return (char*) &password; +} + +#else + +/* + * Windows lacks getpass(). So we'll re-implement it here. + */ + +static char *getpass(const char *prompt) +{ +/* WCE lacks console. So the getpass is unsuported + * The only way is to use the GUI so the getpass should be implemented + * on per-application basis. + */ +#ifdef _WIN32_WCE + return NULL; +#else + static char password[128]; + int n = 0; + int ch; + + fputs(prompt, stderr); + + while ((ch = _getch()) != '\r') { + if (ch == EOF) /* EOF */ { + fputs("[EOF]\n", stderr); + return NULL; + } + else if (ch == 0 || ch == 0xE0) { + /* FN Keys (0 or E0) are a sentinal for a FN code */ + ch = (ch << 4) | _getch(); + /* Catch {DELETE}, {<--}, Num{DEL} and Num{<--} */ + if ((ch == 0xE53 || ch == 0xE4B || ch == 0x053 || ch == 0x04b) && n) { + password[--n] = '\0'; + fputs("\b \b", stderr); + } + else { + fputc('\a', stderr); + } + } + else if ((ch == '\b' || ch == 127) && n) /* BS/DEL */ { + password[--n] = '\0'; + fputs("\b \b", stderr); + } + else if (ch == 3) /* CTRL+C */ { + /* _getch() bypasses Ctrl+C but not Ctrl+Break detection! */ + fputs("^C\n", stderr); + exit(-1); + } + else if (ch == 26) /* CTRL+Z */ { + fputs("^Z\n", stderr); + return NULL; + } + else if (ch == 27) /* ESC */ { + fputc('\n', stderr); + fputs(prompt, stderr); + n = 0; + } + else if ((n < sizeof(password) - 1) && !apr_iscntrl(ch)) { + password[n++] = ch; + fputc('*', stderr); + } + else { + fputc('\a', stderr); + } + } + + fputc('\n', stderr); + password[n] = '\0'; + return password; +#endif +} + +#endif /* no getchar or _getch */ + +#endif /* no getpass */ + +/* + * Use the OS getpass() routine (or our own) to obtain a password from + * the input stream. + * + * Exit values: + * 0: Success + * 5: Partial success; entered text truncated to the size of the + * destination buffer + * + * Restrictions: Truncation also occurs according to the host system's + * getpass() semantics, or at position 255 if our own version is used, + * but the caller is *not* made aware of it unless their own buffer is + * smaller than our own. + */ + +APR_DECLARE(apr_status_t) apr_password_get(const char *prompt, char *pwbuf, apr_size_t *bufsiz) +{ +#ifdef HAVE_GETPASSPHRASE + char *pw_got = getpassphrase(prompt); +#else + char *pw_got = getpass(prompt); +#endif + apr_status_t rv = APR_SUCCESS; + + if (!pw_got) + return APR_EINVAL; + if (strlen(pw_got) >= *bufsiz) { + rv = APR_ENAMETOOLONG; + } + apr_cpystrn(pwbuf, pw_got, *bufsiz); + memset(pw_got, 0, strlen(pw_got)); + return rv; +} diff --git a/srclib/apr/poll/os2/poll.c b/srclib/apr/poll/os2/poll.c new file mode 100644 index 0000000000..7116babf5c --- /dev/null +++ b/srclib/apr/poll/os2/poll.c @@ -0,0 +1,105 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_poll.h" +#include "apr_arch_networkio.h" + +APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num, + apr_int32_t *nsds, apr_interval_time_t timeout) +{ + int *pollset; + int i; + int num_read = 0, num_write = 0, num_except = 0, num_total; + int pos_read, pos_write, pos_except; + + for (i = 0; i < num; i++) { + if (aprset[i].desc_type == APR_POLL_SOCKET) { + num_read += (aprset[i].reqevents & APR_POLLIN) != 0; + num_write += (aprset[i].reqevents & APR_POLLOUT) != 0; + num_except += (aprset[i].reqevents & APR_POLLPRI) != 0; + } + } + + num_total = num_read + num_write + num_except; + pollset = alloca(sizeof(int) * num_total); + memset(pollset, 0, sizeof(int) * num_total); + + pos_read = 0; + pos_write = num_read; + pos_except = pos_write + num_write; + + for (i = 0; i < num; i++) { + if (aprset[i].desc_type == APR_POLL_SOCKET) { + if (aprset[i].reqevents & APR_POLLIN) { + pollset[pos_read++] = aprset[i].desc.s->socketdes; + } + + if (aprset[i].reqevents & APR_POLLOUT) { + pollset[pos_write++] = aprset[i].desc.s->socketdes; + } + + if (aprset[i].reqevents & APR_POLLPRI) { + pollset[pos_except++] = aprset[i].desc.s->socketdes; + } + + aprset[i].rtnevents = 0; + } + } + + if (timeout > 0) { + timeout /= 1000; /* convert microseconds to milliseconds */ + } + + i = select(pollset, num_read, num_write, num_except, timeout); + (*nsds) = i; + + if ((*nsds) < 0) { + return APR_FROM_OS_ERROR(sock_errno()); + } + + if ((*nsds) == 0) { + return APR_TIMEUP; + } + + pos_read = 0; + pos_write = num_read; + pos_except = pos_write + num_write; + + for (i = 0; i < num; i++) { + if (aprset[i].desc_type == APR_POLL_SOCKET) { + if (aprset[i].reqevents & APR_POLLIN) { + if (pollset[pos_read++] > 0) { + aprset[i].rtnevents |= APR_POLLIN; + } + } + + if (aprset[i].reqevents & APR_POLLOUT) { + if (pollset[pos_write++] > 0) { + aprset[i].rtnevents |= APR_POLLOUT; + } + } + + if (aprset[i].reqevents & APR_POLLPRI) { + if (pollset[pos_except++] > 0) { + aprset[i].rtnevents |= APR_POLLPRI; + } + } + } + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/poll/os2/pollset.c b/srclib/apr/poll/os2/pollset.c new file mode 100644 index 0000000000..473f2a8a90 --- /dev/null +++ b/srclib/apr/poll/os2/pollset.c @@ -0,0 +1,223 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_poll.h" +#include "apr_arch_networkio.h" + + + +struct apr_pollset_t { + apr_pool_t *pool; + apr_uint32_t nelts; + apr_uint32_t nalloc; + int *pollset; + int num_read; + int num_write; + int num_except; + int num_total; + apr_pollfd_t *query_set; + apr_pollfd_t *result_set; +}; + + + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + *pollset = apr_palloc(p, sizeof(**pollset)); + (*pollset)->pool = p; + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->pollset = apr_palloc(p, size * sizeof(int) * 3); + (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + (*pollset)->num_read = -1; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) +{ + /* A no-op function for now. If we later implement /dev/poll + * support, we'll need to close the /dev/poll fd here + */ + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + if (pollset->nelts == pollset->nalloc) { + return APR_ENOMEM; + } + + pollset->query_set[pollset->nelts] = *descriptor; + + if (descriptor->desc_type != APR_POLL_SOCKET) { + return APR_EBADF; + } + + pollset->nelts++; + pollset->num_read = -1; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_uint32_t i; + + for (i = 0; i < pollset->nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + /* Found an instance of the fd: remove this and any other copies */ + apr_uint32_t dst = i; + apr_uint32_t old_nelts = pollset->nelts; + pollset->nelts--; + + for (i++; i < old_nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + pollset->nelts--; + } + else { + pollset->pollset[dst] = pollset->pollset[i]; + pollset->query_set[dst] = pollset->query_set[i]; + dst++; + } + } + + pollset->num_read = -1; + return APR_SUCCESS; + } + } + + return APR_NOTFOUND; +} + + + +static void make_pollset(apr_pollset_t *pollset) +{ + int i; + int pos = 0; + + pollset->num_read = 0; + pollset->num_write = 0; + pollset->num_except = 0; + + for (i = 0; i < pollset->nelts; i++) { + if (pollset->query_set[i].reqevents & APR_POLLIN) { + pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes; + pollset->num_read++; + } + } + + for (i = 0; i < pollset->nelts; i++) { + if (pollset->query_set[i].reqevents & APR_POLLOUT) { + pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes; + pollset->num_write++; + } + } + + for (i = 0; i < pollset->nelts; i++) { + if (pollset->query_set[i].reqevents & APR_POLLPRI) { + pollset->pollset[pos++] = pollset->query_set[i].desc.s->socketdes; + pollset->num_except++; + } + } + + pollset->num_total = pollset->num_read + pollset->num_write + pollset->num_except; +} + + + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + int rv; + apr_uint32_t i; + int *pollresult; + int read_pos, write_pos, except_pos; + + if (pollset->num_read < 0) { + make_pollset(pollset); + } + + pollresult = alloca(sizeof(int) * pollset->num_total); + memcpy(pollresult, pollset->pollset, sizeof(int) * pollset->num_total); + (*num) = 0; + + if (timeout > 0) { + timeout /= 1000; + } + + rv = select(pollresult, pollset->num_read, pollset->num_write, pollset->num_except, timeout); + + if (rv < 0) { + return APR_FROM_OS_ERROR(sock_errno()); + } + + if (rv == 0) { + return APR_TIMEUP; + } + + read_pos = 0; + write_pos = pollset->num_read; + except_pos = pollset->num_read + pollset->num_write; + + for (i = 0; i < pollset->nelts; i++) { + int rtnevents = 0; + + if (pollset->query_set[i].reqevents & APR_POLLIN) { + if (pollresult[read_pos++] != -1) { + rtnevents |= APR_POLLIN; + } + } + + if (pollset->query_set[i].reqevents & APR_POLLOUT) { + if (pollresult[write_pos++] != -1) { + rtnevents |= APR_POLLOUT; + } + } + + if (pollset->query_set[i].reqevents & APR_POLLPRI) { + if (pollresult[except_pos++] != -1) { + rtnevents |= APR_POLLPRI; + } + } + + if (rtnevents) { + pollset->result_set[*num] = pollset->query_set[i]; + pollset->result_set[*num].rtnevents = rtnevents; + (*num)++; + } + } + + if (descriptors) { + *descriptors = pollset->result_set; + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/poll/unix/epoll.c b/srclib/apr/poll/unix/epoll.c new file mode 100644 index 0000000000..30b30dcd8e --- /dev/null +++ b/srclib/apr/poll/unix/epoll.c @@ -0,0 +1,266 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_poll_private.h" + +#ifdef POLLSET_USES_EPOLL + +static apr_int16_t get_epoll_event(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & APR_POLLIN) + rv |= EPOLLIN; + if (event & APR_POLLPRI) + rv |= EPOLLPRI; + if (event & APR_POLLOUT) + rv |= EPOLLOUT; + if (event & APR_POLLERR) + rv |= EPOLLERR; + if (event & APR_POLLHUP) + rv |= EPOLLHUP; + /* APR_POLLNVAL is not handled by epoll. */ + + return rv; +} + +static apr_int16_t get_epoll_revent(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & EPOLLIN) + rv |= APR_POLLIN; + if (event & EPOLLPRI) + rv |= APR_POLLPRI; + if (event & EPOLLOUT) + rv |= APR_POLLOUT; + if (event & EPOLLERR) + rv |= APR_POLLERR; + if (event & EPOLLHUP) + rv |= APR_POLLHUP; + /* APR_POLLNVAL is not handled by epoll. */ + + return rv; +} + +struct apr_pollset_t +{ + apr_pool_t *pool; + apr_uint32_t nelts; + apr_uint32_t nalloc; + int epoll_fd; + struct epoll_event *pollset; + apr_pollfd_t *result_set; + apr_uint32_t flags; +#if APR_HAS_THREADS + /* A thread mutex to protect operations on the rings */ + apr_thread_mutex_t *ring_lock; +#endif + /* A ring containing all of the pollfd_t that are active */ + APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring; + /* A ring of pollfd_t that have been used, and then _remove()'d */ + APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring; + /* A ring of pollfd_t where rings that have been _remove()`ed but + might still be inside a _poll() */ + APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; +}; + +static apr_status_t backend_cleanup(void *p_) +{ + apr_pollset_t *pollset = (apr_pollset_t *) p_; + close(pollset->epoll_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + apr_status_t rv; + + *pollset = apr_palloc(p, sizeof(**pollset)); +#if APR_HAS_THREADS + if (flags & APR_POLLSET_THREADSAFE && + ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, + APR_THREAD_MUTEX_DEFAULT, + p) != APR_SUCCESS))) { + *pollset = NULL; + return rv; + } +#else + if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; + return APR_ENOTIMPL; + } +#endif + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->flags = flags; + (*pollset)->pool = p; + (*pollset)->epoll_fd = epoll_create(size); + (*pollset)->pollset = apr_palloc(p, size * sizeof(struct epoll_event)); + apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, + apr_pool_cleanup_null); + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + + APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) +{ + return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); +} + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + struct epoll_event ev; + int ret = -1; + pfd_elem_t *elem; + apr_status_t rv = APR_SUCCESS; + + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; + + ev.events = get_epoll_event(descriptor->reqevents); + ev.data.ptr = elem; + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_ADD, + descriptor->desc.f->filedes, &ev); + } + + if (0 != ret) { + rv = APR_EBADF; + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + else { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + pfd_elem_t *ep; + apr_status_t rv = APR_SUCCESS; + struct epoll_event ev; + int ret = -1; + + pollset_lock_rings(); + + ev.events = get_epoll_event(descriptor->reqevents); + + if (descriptor->desc_type == APR_POLL_SOCKET) { + ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.s->socketdes, &ev); + } + else { + ret = epoll_ctl(pollset->epoll_fd, EPOLL_CTL_DEL, + descriptor->desc.f->filedes, &ev); + } + if (ret < 0) { + rv = APR_NOTFOUND; + } + + if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { + for (ep = APR_RING_FIRST(&(pollset->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->dead_ring), + ep, pfd_elem_t, link); + break; + } + } + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + int ret, i; + apr_status_t rv = APR_SUCCESS; + + if (timeout > 0) { + timeout /= 1000; + } + + ret = epoll_wait(pollset->epoll_fd, pollset->pollset, pollset->nalloc, + timeout); + (*num) = ret; + + if (ret < 0) { + rv = apr_get_netos_error(); + } + else if (ret == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < ret; i++) { + pollset->result_set[i] = + (((pfd_elem_t *) (pollset->pollset[i].data.ptr))->pfd); + pollset->result_set[i].rtnevents = + get_epoll_revent(pollset->pollset[i].events); + } + + if (descriptors) { + *descriptors = pollset->result_set; + } + } + + pollset_lock_rings(); + + /* Shift all PFDs in the Dead Ring to be Free Ring */ + APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); + + pollset_unlock_rings(); + + return rv; +} + +#endif /* POLLSET_USES_EPOLL */ diff --git a/srclib/apr/poll/unix/kqueue.c b/srclib/apr/poll/unix/kqueue.c new file mode 100644 index 0000000000..b2beb571a8 --- /dev/null +++ b/srclib/apr/poll/unix/kqueue.c @@ -0,0 +1,284 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_poll_private.h" + +#ifdef POLLSET_USES_KQUEUE + +static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags) +{ + apr_int16_t rv = 0; + + if (event & EVFILT_READ) + rv |= APR_POLLIN; + if (event & EVFILT_WRITE) + rv |= APR_POLLOUT; + if (flags & EV_EOF) + rv |= APR_POLLHUP; + if (flags & EV_ERROR) + rv |= APR_POLLERR; + + return rv; +} + +struct apr_pollset_t +{ + apr_pool_t *pool; + apr_uint32_t nelts; + apr_uint32_t nalloc; + int kqueue_fd; + struct kevent kevent; + struct kevent *ke_set; + apr_pollfd_t *result_set; + apr_uint32_t flags; +#if APR_HAS_THREADS + /* A thread mutex to protect operations on the rings */ + apr_thread_mutex_t *ring_lock; +#endif + /* A ring containing all of the pollfd_t that are active */ + APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring; + /* A ring of pollfd_t that have been used, and then _remove'd */ + APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring; + /* A ring of pollfd_t where rings that have been _remove'd but + might still be inside a _poll */ + APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; +}; + +static apr_status_t backend_cleanup(void *p_) +{ + apr_pollset_t *pollset = (apr_pollset_t *) p_; + close(pollset->kqueue_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + apr_status_t rv = APR_SUCCESS; + *pollset = apr_palloc(p, sizeof(**pollset)); +#if APR_HAS_THREADS + if (flags & APR_POLLSET_THREADSAFE && + ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, + APR_THREAD_MUTEX_DEFAULT, + p) != APR_SUCCESS))) { + *pollset = NULL; + return rv; + } +#else + if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; + return APR_ENOTIMPL; + } +#endif + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->flags = flags; + (*pollset)->pool = p; + + (*pollset)->ke_set = + (struct kevent *) apr_palloc(p, size * sizeof(struct kevent)); + + memset((*pollset)->ke_set, 0, size * sizeof(struct kevent)); + + (*pollset)->kqueue_fd = kqueue(); + + if ((*pollset)->kqueue_fd == -1) { + return APR_ENOMEM; + } + + apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, + apr_pool_cleanup_null); + + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + + APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) +{ + return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); +} + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_os_sock_t fd; + pfd_elem_t *elem; + apr_status_t rv = APR_SUCCESS; + + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + if (descriptor->reqevents & APR_POLLIN) { + EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_ADD, 0, 0, elem); + + if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, + NULL) == -1) { + rv = APR_ENOMEM; + } + } + + if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { + EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_ADD, 0, 0, elem); + + if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, + NULL) == -1) { + rv = APR_ENOMEM; + } + } + + if (rv == APR_SUCCESS) { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + else { + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + pfd_elem_t *ep; + apr_status_t rv = APR_SUCCESS; + apr_os_sock_t fd; + + pollset_lock_rings(); + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + if (descriptor->reqevents & APR_POLLIN) { + EV_SET(&pollset->kevent, fd, EVFILT_READ, EV_DELETE, 0, 0, NULL); + + if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, + NULL) == -1) { + rv = APR_NOTFOUND; + } + } + + if (descriptor->reqevents & APR_POLLOUT && rv == APR_SUCCESS) { + EV_SET(&pollset->kevent, fd, EVFILT_WRITE, EV_DELETE, 0, 0, NULL); + + if (kevent(pollset->kqueue_fd, &pollset->kevent, 1, NULL, 0, + NULL) == -1) { + rv = APR_NOTFOUND; + } + } + + if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { + for (ep = APR_RING_FIRST(&(pollset->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->dead_ring), + ep, pfd_elem_t, link); + break; + } + } + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + int ret, i; + struct timespec tv, *tvptr; + apr_status_t rv = APR_SUCCESS; + + if (timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = (long) apr_time_sec(timeout); + tv.tv_nsec = (long) apr_time_msec(timeout); + tvptr = &tv; + } + + ret = kevent(pollset->kqueue_fd, NULL, 0, pollset->ke_set, pollset->nalloc, + tvptr); + (*num) = ret; + if (ret < 0) { + rv = apr_get_netos_error(); + } + else if (ret == 0) { + rv = APR_TIMEUP; + } + else { + for (i = 0; i < ret; i++) { + pollset->result_set[i] = + (((pfd_elem_t*)(pollset->ke_set[i].udata))->pfd); + pollset->result_set[i].rtnevents = + get_kqueue_revent(pollset->ke_set[i].filter, + pollset->ke_set[i].flags); + } + + if (descriptors) { + *descriptors = pollset->result_set; + } + } + + + pollset_lock_rings(); + + /* Shift all PFDs in the Dead Ring to be Free Ring */ + APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); + + pollset_unlock_rings(); + + return rv; +} + +#endif /* POLLSET_USES_KQUEUE */ diff --git a/srclib/apr/poll/unix/poll.c b/srclib/apr/poll/unix/poll.c new file mode 100644 index 0000000000..b212f2940f --- /dev/null +++ b/srclib/apr/poll/unix/poll.c @@ -0,0 +1,264 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_poll_private.h" + +#if defined(POLL_USES_POLL) || defined(POLLSET_USES_POLL) + +static apr_int16_t get_event(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & APR_POLLIN) + rv |= POLLIN; + if (event & APR_POLLPRI) + rv |= POLLPRI; + if (event & APR_POLLOUT) + rv |= POLLOUT; + if (event & APR_POLLERR) + rv |= POLLERR; + if (event & APR_POLLHUP) + rv |= POLLHUP; + if (event & APR_POLLNVAL) + rv |= POLLNVAL; + + return rv; +} + +static apr_int16_t get_revent(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & POLLIN) + rv |= APR_POLLIN; + if (event & POLLPRI) + rv |= APR_POLLPRI; + if (event & POLLOUT) + rv |= APR_POLLOUT; + if (event & POLLERR) + rv |= APR_POLLERR; + if (event & POLLHUP) + rv |= APR_POLLHUP; + if (event & POLLNVAL) + rv |= APR_POLLNVAL; + + return rv; +} + +#endif /* POLL_USES_POLL || POLLSET_USES_POLL */ + + +#ifdef POLL_USES_POLL + +#define SMALL_POLLSET_LIMIT 8 + +APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, apr_int32_t num, + apr_int32_t *nsds, + apr_interval_time_t timeout) +{ + int i, num_to_poll; +#ifdef HAVE_VLA + /* XXX: I trust that this is a segv when insufficient stack exists? */ + struct pollfd pollset[num]; +#elif defined(HAVE_ALLOCA) + struct pollfd *pollset = alloca(sizeof(struct pollfd) * num); + if (!pollset) + return APR_ENOMEM; +#else + struct pollfd tmp_pollset[SMALL_POLLSET_LIMIT]; + struct pollfd *pollset; + + if (num <= SMALL_POLLSET_LIMIT) { + pollset = tmp_pollset; + } + else { + /* This does require O(n) to copy the descriptors to the internal + * mapping. + */ + pollset = malloc(sizeof(struct pollfd) * num); + /* The other option is adding an apr_pool_abort() fn to invoke + * the pool's out of memory handler + */ + if (!pollset) + return APR_ENOMEM; + } +#endif + for (i = 0; i < num; i++) { + if (aprset[i].desc_type == APR_POLL_SOCKET) { + pollset[i].fd = aprset[i].desc.s->socketdes; + } + else if (aprset[i].desc_type == APR_POLL_FILE) { + pollset[i].fd = aprset[i].desc.f->filedes; + } + else { + break; + } + pollset[i].events = get_event(aprset[i].reqevents); + } + num_to_poll = i; + + if (timeout > 0) { + timeout /= 1000; /* convert microseconds to milliseconds */ + } + + i = poll(pollset, num_to_poll, timeout); + (*nsds) = i; + + for (i = 0; i < num; i++) { + aprset[i].rtnevents = get_revent(pollset[i].revents); + } + +#if !defined(HAVE_VLA) && !defined(HAVE_ALLOCA) + if (num > SMALL_POLLSET_LIMIT) { + free(pollset); + } +#endif + + if ((*nsds) < 0) { + return apr_get_netos_error(); + } + if ((*nsds) == 0) { + return APR_TIMEUP; + } + return APR_SUCCESS; +} + + +#endif /* POLL_USES_POLL */ + + +#ifdef POLLSET_USES_POLL + +struct apr_pollset_t +{ + apr_pool_t *pool; + apr_uint32_t nelts; + apr_uint32_t nalloc; + struct pollfd *pollset; + apr_pollfd_t *query_set; + apr_pollfd_t *result_set; +}; + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; + return APR_ENOTIMPL; + } + + *pollset = apr_palloc(p, sizeof(**pollset)); + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->pool = p; + (*pollset)->pollset = apr_palloc(p, size * sizeof(struct pollfd)); + (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) +{ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + if (pollset->nelts == pollset->nalloc) { + return APR_ENOMEM; + } + + pollset->query_set[pollset->nelts] = *descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + pollset->pollset[pollset->nelts].fd = descriptor->desc.s->socketdes; + } + else { + pollset->pollset[pollset->nelts].fd = descriptor->desc.f->filedes; + } + + pollset->pollset[pollset->nelts].events = + get_event(descriptor->reqevents); + pollset->nelts++; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_uint32_t i; + + for (i = 0; i < pollset->nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + /* Found an instance of the fd: remove this and any other copies */ + apr_uint32_t dst = i; + apr_uint32_t old_nelts = pollset->nelts; + pollset->nelts--; + for (i++; i < old_nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + pollset->nelts--; + } + else { + pollset->pollset[dst] = pollset->pollset[i]; + pollset->query_set[dst] = pollset->query_set[i]; + dst++; + } + } + return APR_SUCCESS; + } + } + + return APR_NOTFOUND; +} + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + int rv; + apr_uint32_t i, j; + + if (timeout > 0) { + timeout /= 1000; + } + rv = poll(pollset->pollset, pollset->nelts, timeout); + (*num) = rv; + if (rv < 0) { + return apr_get_netos_error(); + } + if (rv == 0) { + return APR_TIMEUP; + } + j = 0; + for (i = 0; i < pollset->nelts; i++) { + if (pollset->pollset[i].revents != 0) { + pollset->result_set[j] = pollset->query_set[i]; + pollset->result_set[j].rtnevents = + get_revent(pollset->pollset[i].revents); + j++; + } + } + if (descriptors) + *descriptors = pollset->result_set; + return APR_SUCCESS; +} + +#endif /* POLLSET_USES_POLL */ diff --git a/srclib/apr/poll/unix/port.c b/srclib/apr/poll/unix/port.c new file mode 100644 index 0000000000..f2350ee997 --- /dev/null +++ b/srclib/apr/poll/unix/port.c @@ -0,0 +1,339 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_poll_private.h" + +#ifdef POLLSET_USES_PORT + +static apr_int16_t get_event(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & APR_POLLIN) + rv |= POLLIN; + if (event & APR_POLLPRI) + rv |= POLLPRI; + if (event & APR_POLLOUT) + rv |= POLLOUT; + if (event & APR_POLLERR) + rv |= POLLERR; + if (event & APR_POLLHUP) + rv |= POLLHUP; + if (event & APR_POLLNVAL) + rv |= POLLNVAL; + + return rv; +} + +static apr_int16_t get_revent(apr_int16_t event) +{ + apr_int16_t rv = 0; + + if (event & POLLIN) + rv |= APR_POLLIN; + if (event & POLLPRI) + rv |= APR_POLLPRI; + if (event & POLLOUT) + rv |= APR_POLLOUT; + if (event & POLLERR) + rv |= APR_POLLERR; + if (event & POLLHUP) + rv |= APR_POLLHUP; + if (event & POLLNVAL) + rv |= APR_POLLNVAL; + + return rv; +} + + +struct apr_pollset_t +{ + apr_pool_t *pool; + apr_uint32_t nelts; + apr_uint32_t nalloc; + int port_fd; + port_event_t *port_set; + apr_pollfd_t *result_set; + apr_uint32_t flags; +#if APR_HAS_THREADS + /* A thread mutex to protect operations on the rings */ + apr_thread_mutex_t *ring_lock; +#endif + /* A ring containing all of the pollfd_t that are active */ + APR_RING_HEAD(pfd_query_ring_t, pfd_elem_t) query_ring; + APR_RING_HEAD(pfd_add_ring_t, pfd_elem_t) add_ring; + /* A ring of pollfd_t that have been used, and then _remove'd */ + APR_RING_HEAD(pfd_free_ring_t, pfd_elem_t) free_ring; + /* A ring of pollfd_t where rings that have been _remove'd but + might still be inside a _poll */ + APR_RING_HEAD(pfd_dead_ring_t, pfd_elem_t) dead_ring; +}; + +static apr_status_t backend_cleanup(void *p_) +{ + apr_pollset_t *pollset = (apr_pollset_t *) p_; + close(pollset->port_fd); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + apr_status_t rv = APR_SUCCESS; + *pollset = apr_palloc(p, sizeof(**pollset)); +#if APR_HAS_THREADS + if (flags & APR_POLLSET_THREADSAFE && + ((rv = apr_thread_mutex_create(&(*pollset)->ring_lock, + APR_THREAD_MUTEX_DEFAULT, + p) != APR_SUCCESS))) { + *pollset = NULL; + return rv; + } +#else + if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; + return APR_ENOTIMPL; + } +#endif + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->flags = flags; + (*pollset)->pool = p; + + (*pollset)->port_set = apr_palloc(p, size * sizeof(port_event_t)); + + (*pollset)->port_fd = port_create(); + + if ((*pollset)->port_fd < 0) { + return APR_ENOMEM; + } + + apr_pool_cleanup_register(p, (void *) (*pollset), backend_cleanup, + apr_pool_cleanup_null); + + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + + APR_RING_INIT(&(*pollset)->query_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->add_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->free_ring, pfd_elem_t, link); + APR_RING_INIT(&(*pollset)->dead_ring, pfd_elem_t, link); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t *pollset) +{ + return apr_pool_cleanup_run(pollset->pool, pollset, backend_cleanup); +} + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_os_sock_t fd; + pfd_elem_t *elem; + int res; + apr_status_t rv = APR_SUCCESS; + + pollset_lock_rings(); + + if (!APR_RING_EMPTY(&(pollset->free_ring), pfd_elem_t, link)) { + elem = APR_RING_FIRST(&(pollset->free_ring)); + APR_RING_REMOVE(elem, link); + } + else { + elem = (pfd_elem_t *) apr_palloc(pollset->pool, sizeof(pfd_elem_t)); + APR_RING_ELEM_INIT(elem, link); + } + elem->pfd = *descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + res = port_associate(pollset->port_fd, PORT_SOURCE_FD, fd, + get_event(descriptor->reqevents), (void *)elem); + + if (res < 0) { + rv = APR_ENOMEM; + APR_RING_INSERT_TAIL(&(pollset->free_ring), elem, pfd_elem_t, link); + } + else { + pollset->nelts++; + APR_RING_INSERT_TAIL(&(pollset->query_ring), elem, pfd_elem_t, link); + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_os_sock_t fd; + pfd_elem_t *ep; + apr_status_t rv = APR_SUCCESS; + int res; + + pollset_lock_rings(); + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { + fd = descriptor->desc.f->filedes; + } + + res = port_dissociate(pollset->port_fd, PORT_SOURCE_FD, fd); + + if (res < 0) { + rv = APR_NOTFOUND; + } + + if (!APR_RING_EMPTY(&(pollset->query_ring), pfd_elem_t, link)) { + for (ep = APR_RING_FIRST(&(pollset->query_ring)); + ep != APR_RING_SENTINEL(&(pollset->query_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->dead_ring), + ep, pfd_elem_t, link); + break; + } + } + } + + if (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { + for (ep = APR_RING_FIRST(&(pollset->add_ring)); + ep != APR_RING_SENTINEL(&(pollset->add_ring), + pfd_elem_t, link); + ep = APR_RING_NEXT(ep, link)) { + + if (descriptor->desc.s == ep->pfd.desc.s) { + APR_RING_REMOVE(ep, link); + APR_RING_INSERT_TAIL(&(pollset->dead_ring), + ep, pfd_elem_t, link); + break; + } + } + } + + pollset_unlock_rings(); + + return rv; +} + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + apr_os_sock_t fd; + int ret, i; + unsigned int nget; + pfd_elem_t *ep; + struct timespec tv, *tvptr; + apr_status_t rv = APR_SUCCESS; + + if (timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = (long) apr_time_sec(timeout); + tv.tv_nsec = (long) apr_time_msec(timeout); + tvptr = &tv; + } + + nget = 1; + + pollset_lock_rings(); + + while (!APR_RING_EMPTY(&(pollset->add_ring), pfd_elem_t, link)) { + ep = APR_RING_FIRST(&(pollset->add_ring)); + APR_RING_REMOVE(ep, link); + + if (ep->pfd.desc_type == APR_POLL_SOCKET) { + fd = ep->pfd.desc.s->socketdes; + } + else { + fd = ep->pfd.desc.f->filedes; + } + + port_associate(pollset->port_fd, PORT_SOURCE_FD, + fd, get_event(ep->pfd.reqevents), ep); + + } + + pollset_unlock_rings(); + + ret = port_getn(pollset->port_fd, pollset->port_set, pollset->nalloc, + &nget, tvptr); + + (*num) = nget; + + if (ret == -1) { + (*num) = 0; + if (errno == ETIME || errno == EINTR) { + rv = APR_TIMEUP; + } + else { + rv = APR_EGENERAL; + } + } + else if (nget == 0) { + rv = APR_TIMEUP; + } + else { + + pollset_lock_rings(); + + for (i = 0; i < nget; i++) { + pollset->result_set[i] = + (((pfd_elem_t*)(pollset->port_set[i].portev_user))->pfd); + pollset->result_set[i].rtnevents = + get_revent(pollset->port_set[i].portev_events); + + APR_RING_INSERT_TAIL(&(pollset->add_ring), + (pfd_elem_t*)pollset->port_set[i].portev_user, + pfd_elem_t, link); + } + + pollset_unlock_rings(); + + if (descriptors) { + *descriptors = pollset->result_set; + } + } + + + pollset_lock_rings(); + + /* Shift all PFDs in the Dead Ring to be Free Ring */ + APR_RING_CONCAT(&(pollset->free_ring), &(pollset->dead_ring), pfd_elem_t, link); + + pollset_unlock_rings(); + + return rv; +} + +#endif /* POLLSET_USES_PORT */ diff --git a/srclib/apr/poll/unix/select.c b/srclib/apr/poll/unix/select.c new file mode 100644 index 0000000000..d9212b0070 --- /dev/null +++ b/srclib/apr/poll/unix/select.c @@ -0,0 +1,404 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef WIN32 +/* POSIX defines 1024 for the FD_SETSIZE */ +#define FD_SETSIZE 1024 +#endif + +#include "apr.h" +#include "apr_poll.h" +#include "apr_time.h" +#include "apr_portable.h" +#include "apr_arch_networkio.h" +#include "apr_arch_file_io.h" +#include "apr_arch_poll_private.h" + +#ifdef POLL_USES_SELECT + +APR_DECLARE(apr_status_t) apr_poll(apr_pollfd_t *aprset, int num, + apr_int32_t *nsds, + apr_interval_time_t timeout) +{ + fd_set readset, writeset, exceptset; + int rv, i; + int maxfd = -1; + struct timeval tv, *tvptr; +#ifdef NETWARE + apr_datatype_e set_type = APR_NO_DESC; +#endif + + if (timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = (long) apr_time_sec(timeout); + tv.tv_usec = (long) apr_time_usec(timeout); + tvptr = &tv; + } + + FD_ZERO(&readset); + FD_ZERO(&writeset); + FD_ZERO(&exceptset); + + for (i = 0; i < num; i++) { + apr_os_sock_t fd; + + aprset[i].rtnevents = 0; + + if (aprset[i].desc_type == APR_POLL_SOCKET) { +#ifdef NETWARE + if (HAS_PIPES(set_type)) { + return APR_EBADF; + } + else { + set_type = APR_POLL_SOCKET; + } +#endif + fd = aprset[i].desc.s->socketdes; + } + else if (aprset[i].desc_type == APR_POLL_FILE) { +#if !APR_FILES_AS_SOCKETS + return APR_EBADF; +#else +#ifdef NETWARE + if (aprset[i].desc.f->is_pipe && !HAS_SOCKETS(set_type)) { + set_type = APR_POLL_FILE; + } + else + return APR_EBADF; +#endif /* NETWARE */ + + fd = aprset[i].desc.f->filedes; + +#endif /* APR_FILES_AS_SOCKETS */ + } + else { + break; + } +#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */ + if (fd >= FD_SETSIZE) { + /* XXX invent new error code so application has a clue */ + return APR_EBADF; + } +#endif + if (aprset[i].reqevents & APR_POLLIN) { + FD_SET(fd, &readset); + } + if (aprset[i].reqevents & APR_POLLOUT) { + FD_SET(fd, &writeset); + } + if (aprset[i].reqevents & + (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { + FD_SET(fd, &exceptset); + } + if ((int) fd > maxfd) { + maxfd = (int) fd; + } + } + +#ifdef NETWARE + if (HAS_PIPES(set_type)) { + rv = pipe_select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); + } + else { +#endif + + rv = select(maxfd + 1, &readset, &writeset, &exceptset, tvptr); + +#ifdef NETWARE + } +#endif + + (*nsds) = rv; + if ((*nsds) == 0) { + return APR_TIMEUP; + } + if ((*nsds) < 0) { + return apr_get_netos_error(); + } + + for (i = 0; i < num; i++) { + apr_os_sock_t fd; + + if (aprset[i].desc_type == APR_POLL_SOCKET) { + fd = aprset[i].desc.s->socketdes; + } + else if (aprset[i].desc_type == APR_POLL_FILE) { +#if !APR_FILES_AS_SOCKETS + return APR_EBADF; +#else + fd = aprset[i].desc.f->filedes; +#endif + } + else { + break; + } + if (FD_ISSET(fd, &readset)) { + aprset[i].rtnevents |= APR_POLLIN; + } + if (FD_ISSET(fd, &writeset)) { + aprset[i].rtnevents |= APR_POLLOUT; + } + if (FD_ISSET(fd, &exceptset)) { + aprset[i].rtnevents |= APR_POLLERR; + } + } + + return APR_SUCCESS; +} + +#endif /* POLL_USES_SELECT */ + +#ifdef POLLSET_USES_SELECT + +struct apr_pollset_t +{ + apr_pool_t *pool; + + apr_uint32_t nelts; + apr_uint32_t nalloc; + fd_set readset, writeset, exceptset; + int maxfd; + apr_pollfd_t *query_set; + apr_pollfd_t *result_set; +#ifdef NETWARE + int set_type; +#endif +}; + +APR_DECLARE(apr_status_t) apr_pollset_create(apr_pollset_t **pollset, + apr_uint32_t size, + apr_pool_t *p, + apr_uint32_t flags) +{ + if (flags & APR_POLLSET_THREADSAFE) { + *pollset = NULL; + return APR_ENOTIMPL; + } +#ifdef FD_SETSIZE + if (size > FD_SETSIZE) { + *pollset = NULL; + return APR_EINVAL; + } +#endif + *pollset = apr_palloc(p, sizeof(**pollset)); + (*pollset)->nelts = 0; + (*pollset)->nalloc = size; + (*pollset)->pool = p; + FD_ZERO(&((*pollset)->readset)); + FD_ZERO(&((*pollset)->writeset)); + FD_ZERO(&((*pollset)->exceptset)); + (*pollset)->maxfd = 0; +#ifdef NETWARE + (*pollset)->set_type = APR_NO_DESC; +#endif + (*pollset)->query_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + (*pollset)->result_set = apr_palloc(p, size * sizeof(apr_pollfd_t)); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_destroy(apr_pollset_t * pollset) +{ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_add(apr_pollset_t *pollset, + const apr_pollfd_t *descriptor) +{ + apr_os_sock_t fd; + + if (pollset->nelts == pollset->nalloc) { + return APR_ENOMEM; + } + + pollset->query_set[pollset->nelts] = *descriptor; + + if (descriptor->desc_type == APR_POLL_SOCKET) { +#ifdef NETWARE + /* NetWare can't handle mixed descriptor types in select() */ + if (HAS_PIPES(pollset->set_type)) { + return APR_EBADF; + } + else { + pollset->set_type = APR_POLL_SOCKET; + } +#endif + fd = descriptor->desc.s->socketdes; + } + else { +#if !APR_FILES_AS_SOCKETS + return APR_EBADF; +#else +#ifdef NETWARE + /* NetWare can't handle mixed descriptor types in select() */ + if (descriptor->desc.f->is_pipe && !HAS_SOCKETS(pollset->set_type)) { + pollset->set_type = APR_POLL_FILE; + fd = descriptor->desc.f->filedes; + } + else { + return APR_EBADF; + } +#else + fd = descriptor->desc.f->filedes; +#endif +#endif + } +#if !defined(WIN32) && !defined(NETWARE) /* socket sets handled with array of handles */ + if (fd >= FD_SETSIZE) { + /* XXX invent new error code so application has a clue */ + return APR_EBADF; + } +#endif + if (descriptor->reqevents & APR_POLLIN) { + FD_SET(fd, &(pollset->readset)); + } + if (descriptor->reqevents & APR_POLLOUT) { + FD_SET(fd, &(pollset->writeset)); + } + if (descriptor->reqevents & + (APR_POLLPRI | APR_POLLERR | APR_POLLHUP | APR_POLLNVAL)) { + FD_SET(fd, &(pollset->exceptset)); + } + if ((int) fd > pollset->maxfd) { + pollset->maxfd = (int) fd; + } + pollset->nelts++; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_pollset_remove(apr_pollset_t * pollset, + const apr_pollfd_t * descriptor) +{ + apr_uint32_t i; + apr_os_sock_t fd; + + if (descriptor->desc_type == APR_POLL_SOCKET) { + fd = descriptor->desc.s->socketdes; + } + else { +#if !APR_FILES_AS_SOCKETS + return APR_EBADF; +#else + fd = descriptor->desc.f->filedes; +#endif + } + + for (i = 0; i < pollset->nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + /* Found an instance of the fd: remove this and any other copies */ + apr_uint32_t dst = i; + apr_uint32_t old_nelts = pollset->nelts; + pollset->nelts--; + for (i++; i < old_nelts; i++) { + if (descriptor->desc.s == pollset->query_set[i].desc.s) { + pollset->nelts--; + } + else { + pollset->query_set[dst] = pollset->query_set[i]; + dst++; + } + } + FD_CLR(fd, &(pollset->readset)); + FD_CLR(fd, &(pollset->writeset)); + FD_CLR(fd, &(pollset->exceptset)); + if (((int) fd == pollset->maxfd) && (pollset->maxfd > 0)) { + pollset->maxfd--; + } + return APR_SUCCESS; + } + } + + return APR_NOTFOUND; +} + +APR_DECLARE(apr_status_t) apr_pollset_poll(apr_pollset_t *pollset, + apr_interval_time_t timeout, + apr_int32_t *num, + const apr_pollfd_t **descriptors) +{ + int rv; + apr_uint32_t i, j; + struct timeval tv, *tvptr; + fd_set readset, writeset, exceptset; + + if (timeout < 0) { + tvptr = NULL; + } + else { + tv.tv_sec = (long) apr_time_sec(timeout); + tv.tv_usec = (long) apr_time_usec(timeout); + tvptr = &tv; + } + + memcpy(&readset, &(pollset->readset), sizeof(fd_set)); + memcpy(&writeset, &(pollset->writeset), sizeof(fd_set)); + memcpy(&exceptset, &(pollset->exceptset), sizeof(fd_set)); + +#ifdef NETWARE + if (HAS_PIPES(pollset->set_type)) { + rv = pipe_select(pollset->maxfd + 1, &readset, &writeset, &exceptset, + tvptr); + } + else +#endif + rv = select(pollset->maxfd + 1, &readset, &writeset, &exceptset, + tvptr); + + (*num) = rv; + if (rv < 0) { + return apr_get_netos_error(); + } + if (rv == 0) { + return APR_TIMEUP; + } + j = 0; + for (i = 0; i < pollset->nelts; i++) { + apr_os_sock_t fd; + if (pollset->query_set[i].desc_type == APR_POLL_SOCKET) { + fd = pollset->query_set[i].desc.s->socketdes; + } + else { +#if !APR_FILES_AS_SOCKETS + return APR_EBADF; +#else + fd = pollset->query_set[i].desc.f->filedes; +#endif + } + if (FD_ISSET(fd, &readset) || FD_ISSET(fd, &writeset) || + FD_ISSET(fd, &exceptset)) { + pollset->result_set[j] = pollset->query_set[i]; + pollset->result_set[j].rtnevents = 0; + if (FD_ISSET(fd, &readset)) { + pollset->result_set[j].rtnevents |= APR_POLLIN; + } + if (FD_ISSET(fd, &writeset)) { + pollset->result_set[j].rtnevents |= APR_POLLOUT; + } + if (FD_ISSET(fd, &exceptset)) { + pollset->result_set[j].rtnevents |= APR_POLLERR; + } + j++; + } + } + + if (descriptors) + *descriptors = pollset->result_set; + return APR_SUCCESS; +} + +#endif /* POLLSET_USES_SELECT */ diff --git a/srclib/apr/random/unix/apr_random.c b/srclib/apr/random/unix/apr_random.c new file mode 100644 index 0000000000..ae80e0bf8a --- /dev/null +++ b/srclib/apr/random/unix/apr_random.c @@ -0,0 +1,300 @@ +/* Copyright 2003-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * See the paper "???" by Ben Laurie for an explanation of this PRNG. + */ + +#include "apr.h" +#include "apr_pools.h" +#include "apr_random.h" +#include "apr_thread_proc.h" +#include + +#ifdef min +#undef min +#endif +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#define APR_RANDOM_DEFAULT_POOLS 32 +#define APR_RANDOM_DEFAULT_REHASH_SIZE 1024 +#define APR_RANDOM_DEFAULT_RESEED_SIZE 32 +#define APR_RANDOM_DEFAULT_HASH_SECRET_SIZE 32 +#define APR_RANDOM_DEFAULT_G_FOR_INSECURE 32 +#define APR_RANDOM_DEFAULT_G_FOR_SECURE 320 + +typedef struct apr_random_pool_t { + unsigned char *pool; + unsigned int bytes; + unsigned int pool_size; +} apr_random_pool_t; + +#define hash_init(h) (h)->init(h) +#define hash_add(h,b,n) (h)->add(h,b,n) +#define hash_finish(h,r) (h)->finish(h,r) + +#define hash(h,r,b,n) hash_init(h),hash_add(h,b,n),hash_finish(h,r) + +#define crypt_setkey(c,k) (c)->set_key((c)->data,k) +#define crypt_crypt(c,out,in) (c)->crypt((c)->date,out,in) + +struct apr_random_t { + apr_pool_t *apr_pool; + apr_crypto_hash_t *pool_hash; + unsigned int npools; + apr_random_pool_t *pools; + unsigned int next_pool; + unsigned int generation; + apr_size_t rehash_size; + apr_size_t reseed_size; + apr_crypto_hash_t *key_hash; +#define K_size(g) ((g)->key_hash->size) + apr_crypto_hash_t *prng_hash; +#define B_size(g) ((g)->prng_hash->size) + + unsigned char *H; + unsigned char *H_waiting; +#define H_size(g) (B_size(g)+K_size(g)) +#define H_current(g) (((g)->insecure_started && !(g)->secure_started) \ + ? (g)->H_waiting : (g)->H) + + unsigned char *randomness; + apr_size_t random_bytes; + unsigned int g_for_insecure; + unsigned int g_for_secure; + unsigned int secure_base; + unsigned int insecure_started:1; + unsigned int secure_started:1; + + apr_random_t *next; +}; + +static apr_random_t *all_random; + +APR_DECLARE(void) apr_random_init(apr_random_t *g,apr_pool_t *p, + apr_crypto_hash_t *pool_hash, + apr_crypto_hash_t *key_hash, + apr_crypto_hash_t *prng_hash) +{ + unsigned int n; + + g->apr_pool = p; + + g->pool_hash = pool_hash; + g->key_hash = key_hash; + g->prng_hash = prng_hash; + + g->npools = APR_RANDOM_DEFAULT_POOLS; + g->pools = apr_palloc(p,g->npools*sizeof *g->pools); + for (n = 0; n < g->npools; ++n) { + g->pools[n].bytes = g->pools[n].pool_size = 0; + g->pools[n].pool = NULL; + } + g->next_pool = 0; + + g->generation = 0; + + g->rehash_size = APR_RANDOM_DEFAULT_REHASH_SIZE; + /* Ensure that the rehash size is twice the size of the pool hasher */ + g->rehash_size = ((g->rehash_size+2*g->pool_hash->size-1)/g->pool_hash->size + /2)*g->pool_hash->size*2; + g->reseed_size = APR_RANDOM_DEFAULT_RESEED_SIZE; + + g->H = apr_pcalloc(p,H_size(g)); + g->H_waiting = apr_pcalloc(p,H_size(g)); + + g->randomness = apr_palloc(p,B_size(g)); + g->random_bytes = 0; + + g->g_for_insecure = APR_RANDOM_DEFAULT_G_FOR_INSECURE; + g->secure_base = 0; + g->g_for_secure = APR_RANDOM_DEFAULT_G_FOR_SECURE; + g->secure_started = g->insecure_started = 0; + + g->next = all_random; + all_random = g; +} + +static void mix_pid(apr_random_t *g,unsigned char *H,pid_t pid) +{ + hash_init(g->key_hash); + hash_add(g->key_hash,H,H_size(g)); + hash_add(g->key_hash,&pid,sizeof pid); + hash_finish(g->key_hash,H); +} + +static void mixer(apr_random_t *g,pid_t pid) +{ + unsigned char *H = H_current(g); + + /* mix the PID into the current H */ + mix_pid(g,H,pid); + /* if we are in waiting, then also mix into main H */ + if (H != g->H) + mix_pid(g,g->H,pid); + /* change order of pool mixing for good measure - note that going + backwards is much better than going forwards */ + --g->generation; + /* blow away any lingering randomness */ + g->random_bytes = 0; +} + +APR_DECLARE(void) apr_random_after_fork(apr_proc_t *proc) +{ + apr_random_t *r; + + for (r = all_random; r; r = r->next) + mixer(r,proc->pid); +} + +APR_DECLARE(apr_random_t *) apr_random_standard_new(apr_pool_t *p) +{ + apr_random_t *r = apr_palloc(p,sizeof *r); + + apr_random_init(r,p,apr_crypto_sha256_new(p),apr_crypto_sha256_new(p), + apr_crypto_sha256_new(p)); + return r; +} + +static void rekey(apr_random_t *g) +{ + unsigned int n; + unsigned char *H = H_current(g); + + hash_init(g->key_hash); + hash_add(g->key_hash,H,H_size(g)); + for (n = 0 ; n < g->npools && (n == 0 || g->generation&(1 << (n-1))) + ; ++n) { + hash_add(g->key_hash,g->pools[n].pool,g->pools[n].bytes); + g->pools[n].bytes = 0; + } + hash_finish(g->key_hash,H+B_size(g)); + + ++g->generation; + if (!g->insecure_started && g->generation > g->g_for_insecure) { + g->insecure_started = 1; + if (!g->secure_started) { + memcpy(g->H_waiting,g->H,H_size(g)); + g->secure_base = g->generation; + } + } + + if (!g->secure_started && g->generation > g->secure_base+g->g_for_secure) { + g->secure_started = 1; + memcpy(g->H,g->H_waiting,H_size(g)); + } +} + +APR_DECLARE(void) apr_random_add_entropy(apr_random_t *g,const void *entropy_, + apr_size_t bytes) +{ + unsigned int n; + const unsigned char *entropy = entropy_; + + for (n = 0; n < bytes; ++n) { + apr_random_pool_t *p = &g->pools[g->next_pool]; + + if (++g->next_pool == g->npools) + g->next_pool = 0; + + if (p->pool_size < p->bytes+1) { + unsigned char *np = apr_palloc(g->apr_pool,(p->bytes+1)*2); + + memcpy(np,p->pool,p->bytes); + p->pool = np; + p->pool_size = (p->bytes+1)*2; + } + p->pool[p->bytes++] = entropy[n]; + + if (p->bytes == g->rehash_size) { + unsigned int r; + + for (r = 0; r < p->bytes/2; r+=g->pool_hash->size) + hash(g->pool_hash,p->pool+r,p->pool+r*2,g->pool_hash->size*2); + p->bytes/=2; + } + assert(p->bytes < g->rehash_size); + } + + if (g->pools[0].bytes >= g->reseed_size) + rekey(g); +} + +/* This will give g->B_size bytes of randomness */ +static void apr_random_block(apr_random_t *g,unsigned char *random) +{ + /* FIXME: in principle, these are different hashes */ + hash(g->prng_hash,g->H,g->H,H_size(g)); + hash(g->prng_hash,random,g->H,B_size(g)); +} + +static void apr_random_bytes(apr_random_t *g,unsigned char *random, + apr_size_t bytes) +{ + apr_size_t n; + + for (n = 0; n < bytes; ) { + int l; + + if (g->random_bytes == 0) { + apr_random_block(g,g->randomness); + g->random_bytes = B_size(g); + } + l = min(bytes-n,g->random_bytes); + memcpy(&random[n],g->randomness+B_size(g)-g->random_bytes,l); + g->random_bytes-=l; + n+=l; + } +} + +APR_DECLARE(apr_status_t) apr_random_secure_bytes(apr_random_t *g, + void *random, + apr_size_t bytes) +{ + if (!g->secure_started) + return APR_ENOTENOUGHENTROPY; + apr_random_bytes(g,random,bytes); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_random_insecure_bytes(apr_random_t *g, + void *random, + apr_size_t bytes) +{ + if (!g->insecure_started) + return APR_ENOTENOUGHENTROPY; + apr_random_bytes(g,random,bytes); + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_random_barrier(apr_random_t *g) +{ + g->secure_started = 0; + g->secure_base = g->generation; +} + +APR_DECLARE(apr_status_t) apr_random_secure_ready(apr_random_t *r) +{ + if (!r->secure_started) + return APR_ENOTENOUGHENTROPY; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_random_insecure_ready(apr_random_t *r) +{ + if (!r->insecure_started) + return APR_ENOTENOUGHENTROPY; + return APR_SUCCESS; +} diff --git a/srclib/apr/random/unix/sha2.c b/srclib/apr/random/unix/sha2.c new file mode 100644 index 0000000000..94259ca850 --- /dev/null +++ b/srclib/apr/random/unix/sha2.c @@ -0,0 +1,1000 @@ +/* Copyright 2003-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FILE: sha2.c + * AUTHOR: Aaron D. Gifford + * + * A licence was granted to the ASF by Aaron on 4 November 2003. + */ + +#include /* memcpy()/memset() or bcopy()/bzero() */ +#include /* assert() */ +#include "sha2.h" + +/* + * ASSERT NOTE: + * Some sanity checking code is included using assert(). On my FreeBSD + * system, this additional code can be removed by compiling with NDEBUG + * defined. Check your own systems manpage on assert() to see how to + * compile WITHOUT the sanity checking code on your system. + * + * UNROLLED TRANSFORM LOOP NOTE: + * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform + * loop version for the hash transform rounds (defined using macros + * later in this file). Either define on the command line, for example: + * + * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c + * + * or define below: + * + * #define SHA2_UNROLL_TRANSFORM + * + */ + +/*** SHA-256/384/512 Machine Architecture Definitions *****************/ +typedef apr_byte_t sha2_byte; /* Exactly 1 byte */ +typedef apr_uint32_t sha2_word32; /* Exactly 4 bytes */ +typedef apr_uint64_t sha2_word64; /* Exactly 8 bytes */ + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +/* NOTE: Most of these are in sha2.h */ +#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8) +#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16) +#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16) + + +/*** ENDIAN REVERSAL MACROS *******************************************/ +#if !APR_IS_BIGENDIAN +#define REVERSE32(w,x) { \ + sha2_word32 tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ +} +#define REVERSE64(w,x) { \ + sha2_word64 tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & APR_UINT64_C(0xff00ff00ff00ff00)) >> 8) | \ + ((tmp & APR_UINT64_C(0x00ff00ff00ff00ff)) << 8); \ + (x) = ((tmp & APR_UINT64_C(0xffff0000ffff0000)) >> 16) | \ + ((tmp & APR_UINT64_C(0x0000ffff0000ffff)) << 16); \ +} +#endif /* !APR_IS_BIGENDIAN */ + +/* + * Macro for incrementally adding the unsigned 64-bit integer n to the + * unsigned 128-bit integer (represented using a two-element array of + * 64-bit words): + */ +#define ADDINC128(w,n) { \ + (w)[0] += (sha2_word64)(n); \ + if ((w)[0] < (n)) { \ + (w)[1]++; \ + } \ +} + +/* + * Macros for copying blocks of memory and for zeroing out ranges + * of memory. Using these macros makes it easy to switch from + * using memset()/memcpy() and using bzero()/bcopy(). + * + * Please define either SHA2_USE_MEMSET_MEMCPY or define + * SHA2_USE_BZERO_BCOPY depending on which function set you + * choose to use: + */ +#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY) +/* Default to memset()/memcpy() if no option is specified */ +#define SHA2_USE_MEMSET_MEMCPY 1 +#endif +#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY) +/* Abort with an error if BOTH options are defined */ +#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both! +#endif + +#ifdef SHA2_USE_MEMSET_MEMCPY +#define MEMSET_BZERO(p,l) memset((p), 0, (l)) +#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l)) +#endif +#ifdef SHA2_USE_BZERO_BCOPY +#define MEMSET_BZERO(p,l) bzero((p), (l)) +#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l)) +#endif + + +/*** THE SIX LOGICAL FUNCTIONS ****************************************/ +/* + * Bit shifting and rotation (used by the six SHA-XYZ logical functions: + * + * NOTE: The naming of R and S appears backwards here (R is a SHIFT and + * S is a ROTATION) because the SHA-256/384/512 description document + * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this + * same "backwards" definition. + */ +/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */ +#define R(b,x) ((x) >> (b)) +/* 32-bit Rotate-right (used in SHA-256): */ +#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b)))) +/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */ +#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b)))) + +/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */ +#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z))) +#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +/* Four of six logical functions used in SHA-256: */ +#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x))) +#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x))) +#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x))) +#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x))) + +/* Four of six logical functions used in SHA-384 and SHA-512: */ +#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x))) +#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x))) +#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x))) +#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x))) + +/*** INTERNAL FUNCTION PROTOTYPES *************************************/ +/* NOTE: These should not be accessed directly from outside this + * library -- they are intended for private internal visibility/use + * only. + */ +void SHA512_Last(SHA512_CTX*); +void SHA256_Transform(SHA256_CTX*, const sha2_word32*); +void SHA512_Transform(SHA512_CTX*, const sha2_word64*); + + +/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/ +/* Hash constant words K for SHA-256: */ +const static sha2_word32 K256[64] = { + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; + +/* Initial hash value H for SHA-256: */ +const static sha2_word32 sha256_initial_hash_value[8] = { + 0x6a09e667UL, + 0xbb67ae85UL, + 0x3c6ef372UL, + 0xa54ff53aUL, + 0x510e527fUL, + 0x9b05688cUL, + 0x1f83d9abUL, + 0x5be0cd19UL +}; + +/* Hash constant words K for SHA-384 and SHA-512: */ +const static sha2_word64 K512[80] = { + APR_UINT64_C(0x428a2f98d728ae22), APR_UINT64_C(0x7137449123ef65cd), + APR_UINT64_C(0xb5c0fbcfec4d3b2f), APR_UINT64_C(0xe9b5dba58189dbbc), + APR_UINT64_C(0x3956c25bf348b538), APR_UINT64_C(0x59f111f1b605d019), + APR_UINT64_C(0x923f82a4af194f9b), APR_UINT64_C(0xab1c5ed5da6d8118), + APR_UINT64_C(0xd807aa98a3030242), APR_UINT64_C(0x12835b0145706fbe), + APR_UINT64_C(0x243185be4ee4b28c), APR_UINT64_C(0x550c7dc3d5ffb4e2), + APR_UINT64_C(0x72be5d74f27b896f), APR_UINT64_C(0x80deb1fe3b1696b1), + APR_UINT64_C(0x9bdc06a725c71235), APR_UINT64_C(0xc19bf174cf692694), + APR_UINT64_C(0xe49b69c19ef14ad2), APR_UINT64_C(0xefbe4786384f25e3), + APR_UINT64_C(0x0fc19dc68b8cd5b5), APR_UINT64_C(0x240ca1cc77ac9c65), + APR_UINT64_C(0x2de92c6f592b0275), APR_UINT64_C(0x4a7484aa6ea6e483), + APR_UINT64_C(0x5cb0a9dcbd41fbd4), APR_UINT64_C(0x76f988da831153b5), + APR_UINT64_C(0x983e5152ee66dfab), APR_UINT64_C(0xa831c66d2db43210), + APR_UINT64_C(0xb00327c898fb213f), APR_UINT64_C(0xbf597fc7beef0ee4), + APR_UINT64_C(0xc6e00bf33da88fc2), APR_UINT64_C(0xd5a79147930aa725), + APR_UINT64_C(0x06ca6351e003826f), APR_UINT64_C(0x142929670a0e6e70), + APR_UINT64_C(0x27b70a8546d22ffc), APR_UINT64_C(0x2e1b21385c26c926), + APR_UINT64_C(0x4d2c6dfc5ac42aed), APR_UINT64_C(0x53380d139d95b3df), + APR_UINT64_C(0x650a73548baf63de), APR_UINT64_C(0x766a0abb3c77b2a8), + APR_UINT64_C(0x81c2c92e47edaee6), APR_UINT64_C(0x92722c851482353b), + APR_UINT64_C(0xa2bfe8a14cf10364), APR_UINT64_C(0xa81a664bbc423001), + APR_UINT64_C(0xc24b8b70d0f89791), APR_UINT64_C(0xc76c51a30654be30), + APR_UINT64_C(0xd192e819d6ef5218), APR_UINT64_C(0xd69906245565a910), + APR_UINT64_C(0xf40e35855771202a), APR_UINT64_C(0x106aa07032bbd1b8), + APR_UINT64_C(0x19a4c116b8d2d0c8), APR_UINT64_C(0x1e376c085141ab53), + APR_UINT64_C(0x2748774cdf8eeb99), APR_UINT64_C(0x34b0bcb5e19b48a8), + APR_UINT64_C(0x391c0cb3c5c95a63), APR_UINT64_C(0x4ed8aa4ae3418acb), + APR_UINT64_C(0x5b9cca4f7763e373), APR_UINT64_C(0x682e6ff3d6b2b8a3), + APR_UINT64_C(0x748f82ee5defb2fc), APR_UINT64_C(0x78a5636f43172f60), + APR_UINT64_C(0x84c87814a1f0ab72), APR_UINT64_C(0x8cc702081a6439ec), + APR_UINT64_C(0x90befffa23631e28), APR_UINT64_C(0xa4506cebde82bde9), + APR_UINT64_C(0xbef9a3f7b2c67915), APR_UINT64_C(0xc67178f2e372532b), + APR_UINT64_C(0xca273eceea26619c), APR_UINT64_C(0xd186b8c721c0c207), + APR_UINT64_C(0xeada7dd6cde0eb1e), APR_UINT64_C(0xf57d4f7fee6ed178), + APR_UINT64_C(0x06f067aa72176fba), APR_UINT64_C(0x0a637dc5a2c898a6), + APR_UINT64_C(0x113f9804bef90dae), APR_UINT64_C(0x1b710b35131c471b), + APR_UINT64_C(0x28db77f523047d84), APR_UINT64_C(0x32caab7b40c72493), + APR_UINT64_C(0x3c9ebe0a15c9bebc), APR_UINT64_C(0x431d67c49c100d4c), + APR_UINT64_C(0x4cc5d4becb3e42b6), APR_UINT64_C(0x597f299cfc657e2a), + APR_UINT64_C(0x5fcb6fab3ad6faec), APR_UINT64_C(0x6c44198c4a475817) +}; + +/* Initial hash value H for SHA-384 */ +const static sha2_word64 sha384_initial_hash_value[8] = { + APR_UINT64_C(0xcbbb9d5dc1059ed8), + APR_UINT64_C(0x629a292a367cd507), + APR_UINT64_C(0x9159015a3070dd17), + APR_UINT64_C(0x152fecd8f70e5939), + APR_UINT64_C(0x67332667ffc00b31), + APR_UINT64_C(0x8eb44a8768581511), + APR_UINT64_C(0xdb0c2e0d64f98fa7), + APR_UINT64_C(0x47b5481dbefa4fa4) +}; + +/* Initial hash value H for SHA-512 */ +const static sha2_word64 sha512_initial_hash_value[8] = { + APR_UINT64_C(0x6a09e667f3bcc908), + APR_UINT64_C(0xbb67ae8584caa73b), + APR_UINT64_C(0x3c6ef372fe94f82b), + APR_UINT64_C(0xa54ff53a5f1d36f1), + APR_UINT64_C(0x510e527fade682d1), + APR_UINT64_C(0x9b05688c2b3e6c1f), + APR_UINT64_C(0x1f83d9abfb41bd6b), + APR_UINT64_C(0x5be0cd19137e2179) +}; + +/* + * Constant used by SHA256/384/512_End() functions for converting the + * digest to a readable hexadecimal character string: + */ +static const char *sha2_hex_digits = "0123456789abcdef"; + + +/*** SHA-256: *********************************************************/ +void SHA256_Init(SHA256_CTX* context) { + if (context == (SHA256_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH); + context->bitcount = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-256 round macros: */ + +#if !APR_IS_BIGENDIAN + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE32(*data++, W256[j]); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + W256[j]; \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + + +#else /* APR_IS_BIGENDIAN */ + +#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \ + K256[j] + (W256[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* APR_IS_BIGENDIAN */ + +#define ROUND256(a,b,c,d,e,f,g,h) \ + s0 = W256[(j+1)&0x0f]; \ + s0 = sigma0_256(s0); \ + s1 = W256[(j+14)&0x0f]; \ + s1 = sigma1_256(s1); \ + T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \ + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \ + j++ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + /* Rounds 0 to 15 (unrolled): */ + ROUND256_0_TO_15(a,b,c,d,e,f,g,h); + ROUND256_0_TO_15(h,a,b,c,d,e,f,g); + ROUND256_0_TO_15(g,h,a,b,c,d,e,f); + ROUND256_0_TO_15(f,g,h,a,b,c,d,e); + ROUND256_0_TO_15(e,f,g,h,a,b,c,d); + ROUND256_0_TO_15(d,e,f,g,h,a,b,c); + ROUND256_0_TO_15(c,d,e,f,g,h,a,b); + ROUND256_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds to 64: */ + do { + ROUND256(a,b,c,d,e,f,g,h); + ROUND256(h,a,b,c,d,e,f,g); + ROUND256(g,h,a,b,c,d,e,f); + ROUND256(f,g,h,a,b,c,d,e); + ROUND256(e,f,g,h,a,b,c,d); + ROUND256(d,e,f,g,h,a,b,c); + ROUND256(c,d,e,f,g,h,a,b); + ROUND256(b,c,d,e,f,g,h,a); + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) { + sha2_word32 a, b, c, d, e, f, g, h, s0, s1; + sha2_word32 T1, T2, *W256; + int j; + + W256 = (sha2_word32*)context->buffer; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if !APR_IS_BIGENDIAN + /* Copy data while converting to host byte order */ + REVERSE32(*data++,W256[j]); + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j]; +#else /* APR_IS_BIGENDIAN */ + /* Apply the SHA-256 compression function to update a..h with copy */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++); +#endif /* APR_IS_BIGENDIAN */ + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W256[(j+1)&0x0f]; + s0 = sigma0_256(s0); + s1 = W256[(j+14)&0x0f]; + s1 = sigma1_256(s1); + + /* Apply the SHA-256 compression function to update a..h */ + T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + + (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); + T2 = Sigma0_256(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 64); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (unsigned int)((context->bitcount >> 3) + % SHA256_BLOCK_LENGTH); + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA256_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + context->bitcount += freespace << 3; + len -= freespace; + data += freespace; + SHA256_Transform(context, (sha2_word32*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + context->bitcount += len << 3; + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA256_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA256_Transform(context, (sha2_word32*)data); + context->bitcount += SHA256_BLOCK_LENGTH << 3; + len -= SHA256_BLOCK_LENGTH; + data += SHA256_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + context->bitcount += len << 3; + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) { + sha2_word32 *d = (sha2_word32*)digest; + unsigned int usedspace; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + usedspace = (unsigned int)((context->bitcount >> 3) + % SHA256_BLOCK_LENGTH); +#if !APR_IS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount,context->bitcount); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA256_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + } + } else { + /* Set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Set the bit count: */ + *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount; + + /* Final transform: */ + SHA256_Transform(context, (sha2_word32*)context->buffer); + +#if !APR_IS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE32(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else + MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH); +#endif + } + + /* Clean up state data: */ + MEMSET_BZERO(context, sizeof(context)); + usedspace = 0; +} + +char *SHA256_End(SHA256_CTX* context, char buffer[]) { + sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA256_CTX*)0); + + if (buffer != (char*)0) { + SHA256_Final(digest, context); + + for (i = 0; i < SHA256_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH); + return buffer; +} + +char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) { + SHA256_CTX context; + + SHA256_Init(&context); + SHA256_Update(&context, data, len); + return SHA256_End(&context, digest); +} + + +/*** SHA-512: *********************************************************/ +void SHA512_Init(SHA512_CTX* context) { + if (context == (SHA512_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +#ifdef SHA2_UNROLL_TRANSFORM + +/* Unrolled SHA-512 round macros: */ +#if !APR_IS_BIGENDIAN + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + REVERSE64(*data++, W512[j]); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + W512[j]; \ + (d) += T1, \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \ + j++ + + +#else /* APR_IS_BIGENDIAN */ + +#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \ + K512[j] + (W512[j] = *data++); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +#endif /* APR_IS_BIGENDIAN */ + +#define ROUND512(a,b,c,d,e,f,g,h) \ + s0 = W512[(j+1)&0x0f]; \ + s0 = sigma0_512(s0); \ + s1 = W512[(j+14)&0x0f]; \ + s1 = sigma1_512(s1); \ + T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \ + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \ + (d) += T1; \ + (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \ + j++ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { + ROUND512_0_TO_15(a,b,c,d,e,f,g,h); + ROUND512_0_TO_15(h,a,b,c,d,e,f,g); + ROUND512_0_TO_15(g,h,a,b,c,d,e,f); + ROUND512_0_TO_15(f,g,h,a,b,c,d,e); + ROUND512_0_TO_15(e,f,g,h,a,b,c,d); + ROUND512_0_TO_15(d,e,f,g,h,a,b,c); + ROUND512_0_TO_15(c,d,e,f,g,h,a,b); + ROUND512_0_TO_15(b,c,d,e,f,g,h,a); + } while (j < 16); + + /* Now for the remaining rounds up to 79: */ + do { + ROUND512(a,b,c,d,e,f,g,h); + ROUND512(h,a,b,c,d,e,f,g); + ROUND512(g,h,a,b,c,d,e,f); + ROUND512(f,g,h,a,b,c,d,e); + ROUND512(e,f,g,h,a,b,c,d); + ROUND512(d,e,f,g,h,a,b,c); + ROUND512(c,d,e,f,g,h,a,b); + ROUND512(b,c,d,e,f,g,h,a); + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = 0; +} + +#else /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) { + sha2_word64 a, b, c, d, e, f, g, h, s0, s1; + sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer; + int j; + + /* Initialize registers with the prev. intermediate value */ + a = context->state[0]; + b = context->state[1]; + c = context->state[2]; + d = context->state[3]; + e = context->state[4]; + f = context->state[5]; + g = context->state[6]; + h = context->state[7]; + + j = 0; + do { +#if !APR_IS_BIGENDIAN + /* Convert TO host byte order */ + REVERSE64(*data++, W512[j]); + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j]; +#else /* APR_IS_BIGENDIAN */ + /* Apply the SHA-512 compression function to update a..h with copy */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++); +#endif /* APR_IS_BIGENDIAN */ + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 16); + + do { + /* Part of the message block expansion: */ + s0 = W512[(j+1)&0x0f]; + s0 = sigma0_512(s0); + s1 = W512[(j+14)&0x0f]; + s1 = sigma1_512(s1); + + /* Apply the SHA-512 compression function to update a..h */ + T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + + (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); + T2 = Sigma0_512(a) + Maj(a, b, c); + h = g; + g = f; + f = e; + e = d + T1; + d = c; + c = b; + b = a; + a = T1 + T2; + + j++; + } while (j < 80); + + /* Compute the current intermediate hash value */ + context->state[0] += a; + context->state[1] += b; + context->state[2] += c; + context->state[3] += d; + context->state[4] += e; + context->state[5] += f; + context->state[6] += g; + context->state[7] += h; + + /* Clean up */ + a = b = c = d = e = f = g = h = T1 = T2 = 0; +} + +#endif /* SHA2_UNROLL_TRANSFORM */ + +void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) { + unsigned int freespace, usedspace; + + if (len == 0) { + /* Calling with no data is valid - we do nothing */ + return; + } + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0); + + usedspace = (unsigned int)((context->bitcount[0] >> 3) + % SHA512_BLOCK_LENGTH); + if (usedspace > 0) { + /* Calculate how much free space is available in the buffer */ + freespace = SHA512_BLOCK_LENGTH - usedspace; + + if (len >= freespace) { + /* Fill the buffer completely and process it */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace); + ADDINC128(context->bitcount, freespace << 3); + len -= freespace; + data += freespace; + SHA512_Transform(context, (sha2_word64*)context->buffer); + } else { + /* The buffer is not yet full */ + MEMCPY_BCOPY(&context->buffer[usedspace], data, len); + ADDINC128(context->bitcount, len << 3); + /* Clean up: */ + usedspace = freespace = 0; + return; + } + } + while (len >= SHA512_BLOCK_LENGTH) { + /* Process as many complete blocks as we can */ + SHA512_Transform(context, (sha2_word64*)data); + ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3); + len -= SHA512_BLOCK_LENGTH; + data += SHA512_BLOCK_LENGTH; + } + if (len > 0) { + /* There's left-overs, so save 'em */ + MEMCPY_BCOPY(context->buffer, data, len); + ADDINC128(context->bitcount, len << 3); + } + /* Clean up: */ + usedspace = freespace = 0; +} + +void SHA512_Last(SHA512_CTX* context) { + unsigned int usedspace; + + usedspace = (unsigned int)((context->bitcount[0] >> 3) + % SHA512_BLOCK_LENGTH); +#if !APR_IS_BIGENDIAN + /* Convert FROM host byte order */ + REVERSE64(context->bitcount[0],context->bitcount[0]); + REVERSE64(context->bitcount[1],context->bitcount[1]); +#endif + if (usedspace > 0) { + /* Begin padding with a 1 bit: */ + context->buffer[usedspace++] = 0x80; + + if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) { + /* Set-up for the last transform: */ + MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace); + } else { + if (usedspace < SHA512_BLOCK_LENGTH) { + MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace); + } + /* Do second-to-last transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); + + /* And set-up for the last transform: */ + MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2); + } + } else { + /* Prepare for final transform: */ + MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH); + + /* Begin padding with a 1 bit: */ + *context->buffer = 0x80; + } + /* Store the length of input data (in bits): */ + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1]; + *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0]; + + /* Final transform: */ + SHA512_Transform(context, (sha2_word64*)context->buffer); +} + +void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last(context); + + /* Save the hash data for output: */ +#if !APR_IS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 8; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else /* APR_IS_BIGENDIAN */ + MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH); +#endif /* APR_IS_BIGENDIAN */ + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(context)); +} + +char *SHA512_End(SHA512_CTX* context, char buffer[]) { + sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA512_CTX*)0); + + if (buffer != (char*)0) { + SHA512_Final(digest, context); + + for (i = 0; i < SHA512_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH); + return buffer; +} + +char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) { + SHA512_CTX context; + + SHA512_Init(&context); + SHA512_Update(&context, data, len); + return SHA512_End(&context, digest); +} + + +/*** SHA-384: *********************************************************/ +void SHA384_Init(SHA384_CTX* context) { + if (context == (SHA384_CTX*)0) { + return; + } + MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH); + MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH); + context->bitcount[0] = context->bitcount[1] = 0; +} + +void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) { + SHA512_Update((SHA512_CTX*)context, data, len); +} + +void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) { + sha2_word64 *d = (sha2_word64*)digest; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + /* If no digest buffer is passed, we don't bother doing this: */ + if (digest != (sha2_byte*)0) { + SHA512_Last((SHA512_CTX*)context); + + /* Save the hash data for output: */ +#if !APR_IS_BIGENDIAN + { + /* Convert TO host byte order */ + int j; + for (j = 0; j < 6; j++) { + REVERSE64(context->state[j],context->state[j]); + *d++ = context->state[j]; + } + } +#else /* APR_IS_BIGENDIAN */ + MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH); +#endif /* APR_IS_BIGENDIAN */ + } + + /* Zero out state data */ + MEMSET_BZERO(context, sizeof(context)); +} + +char *SHA384_End(SHA384_CTX* context, char buffer[]) { + sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest; + int i; + + /* Sanity check: */ + assert(context != (SHA384_CTX*)0); + + if (buffer != (char*)0) { + SHA384_Final(digest, context); + + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) { + *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4]; + *buffer++ = sha2_hex_digits[*d & 0x0f]; + d++; + } + *buffer = (char)0; + } else { + MEMSET_BZERO(context, sizeof(context)); + } + MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH); + return buffer; +} + +char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) { + SHA384_CTX context; + + SHA384_Init(&context); + SHA384_Update(&context, data, len); + return SHA384_End(&context, digest); +} + diff --git a/srclib/apr/random/unix/sha2.h b/srclib/apr/random/unix/sha2.h new file mode 100644 index 0000000000..7f58216149 --- /dev/null +++ b/srclib/apr/random/unix/sha2.h @@ -0,0 +1,86 @@ +/* Copyright 2003-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * FILE: sha2.h + * AUTHOR: Aaron D. Gifford + * + * A licence was granted to the ASF by Aaron on 4 November 2003. + */ + +#ifndef __SHA2_H__ +#define __SHA2_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "apr.h" + +/*** SHA-256/384/512 Various Length Definitions ***********************/ +#define SHA256_BLOCK_LENGTH 64 +#define SHA256_DIGEST_LENGTH 32 +#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1) +#define SHA384_BLOCK_LENGTH 128 +#define SHA384_DIGEST_LENGTH 48 +#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1) +#define SHA512_BLOCK_LENGTH 128 +#define SHA512_DIGEST_LENGTH 64 +#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1) + + +/*** SHA-256/384/512 Context Structures *******************************/ +typedef struct _SHA256_CTX { + apr_uint32_t state[8]; + apr_uint64_t bitcount; + apr_byte_t buffer[SHA256_BLOCK_LENGTH]; +} SHA256_CTX; +typedef struct _SHA512_CTX { + apr_uint64_t state[8]; + apr_uint64_t bitcount[2]; + apr_byte_t buffer[SHA512_BLOCK_LENGTH]; +} SHA512_CTX; + +typedef SHA512_CTX SHA384_CTX; + + +/*** SHA-256/384/512 Function Prototypes ******************************/ +void SHA256_Init(SHA256_CTX *); +void SHA256_Update(SHA256_CTX *, const apr_byte_t *, size_t); +void SHA256_Final(apr_byte_t [SHA256_DIGEST_LENGTH], SHA256_CTX *); +char* SHA256_End(SHA256_CTX *, char [SHA256_DIGEST_STRING_LENGTH]); +char* SHA256_Data(const apr_byte_t *, size_t, + char [SHA256_DIGEST_STRING_LENGTH]); + +void SHA384_Init(SHA384_CTX *); +void SHA384_Update(SHA384_CTX *, const apr_byte_t *, size_t); +void SHA384_Final(apr_byte_t [SHA384_DIGEST_LENGTH], SHA384_CTX *); +char* SHA384_End(SHA384_CTX *, char [SHA384_DIGEST_STRING_LENGTH]); +char* SHA384_Data(const apr_byte_t *, size_t, + char [SHA384_DIGEST_STRING_LENGTH]); + +void SHA512_Init(SHA512_CTX *); +void SHA512_Update(SHA512_CTX *, const apr_byte_t *, size_t); +void SHA512_Final(apr_byte_t [SHA512_DIGEST_LENGTH], SHA512_CTX *); +char* SHA512_End(SHA512_CTX *, char [SHA512_DIGEST_STRING_LENGTH]); +char* SHA512_Data(const apr_byte_t *, size_t, + char [SHA512_DIGEST_STRING_LENGTH]); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __SHA2_H__ */ + diff --git a/srclib/apr/random/unix/sha2_glue.c b/srclib/apr/random/unix/sha2_glue.c new file mode 100644 index 0000000000..08f4de3f63 --- /dev/null +++ b/srclib/apr/random/unix/sha2_glue.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include "sha2.h" + +static void sha256_init(apr_crypto_hash_t *h) + { + SHA256_Init(h->data); + } + +static void sha256_add(apr_crypto_hash_t *h,const void *data, + apr_size_t bytes) + { + SHA256_Update(h->data,data,bytes); + } + +static void sha256_finish(apr_crypto_hash_t *h,unsigned char *result) + { + SHA256_Final(result,h->data); + } + +APR_DECLARE(apr_crypto_hash_t *) apr_crypto_sha256_new(apr_pool_t *p) + { + apr_crypto_hash_t *h=apr_palloc(p,sizeof *h); + + h->data=apr_palloc(p,sizeof(SHA256_CTX)); + h->init=sha256_init; + h->add=sha256_add; + h->finish=sha256_finish; + h->size=256/8; + + return h; + } diff --git a/srclib/apr/renames_pending b/srclib/apr/renames_pending new file mode 100644 index 0000000000..ca007a729c --- /dev/null +++ b/srclib/apr/renames_pending @@ -0,0 +1,39 @@ +Pending symbol renames for APR [for some discussion yet] + +apr_file_info_t from apr_finfo_t +apr_file_attrs_t from apr_fileattrs_t +apr_file_seek_where_t from apr_seek_where_t + +#apr_filepath_name_get from apr_filename_of_pathname + +apr_lock_mech_e from apr_lockmech_e + +#apr_gid_get from apr_get_groupid +#apr_gid_name_get from apr_get_groupname +#apr_gid_name_get from apr_group_name_get +#apr_gid_compare from apr_compare_groups + +#apr_socket_shutdown from apr_shutdown +#apr_socket_bind from apr_bind +#apr_socket_listen from apr_listen +#apr_socket_accept from apr_accept +#apr_socket_connect from apr_connect +#apr_socket_send from apr_send +#apr_socket_sendv from apr_sendv +#apr_socket_sendto from apr_sendto +#apr_socket_recvfrom from apr_recvfrom +#apr_socket_sendfile from apr_sendfile +#apr_socket_recv from apr_recv +#apr_socket_inherit_set from apr_socket_set_inherit +#apr_socket_inherit_unset from apr_socket_unset_inherit + + +#apr_time_exp_gmt_get from apr_implode_gmt +apr_time_interval_t from apr_interval_time_t +apr_time_interval_short_t from apr_short_interval_time_t + +#apr_uid_homepath_get from apr_get_home_directory +#apr_uid_get from apr_get_userid +#apr_uid_current from apr_current_userid +#apr_uid_compare from apr_compare_users +#apr_uid_name_get from apr_get_username diff --git a/srclib/apr/shmem/beos/shm.c b/srclib/apr/shmem/beos/shm.c new file mode 100644 index 0000000000..0f70eed1c8 --- /dev/null +++ b/srclib/apr/shmem/beos/shm.c @@ -0,0 +1,166 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_shm.h" +#include "apr_errno.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include +#include +#include +#include "apr_portable.h" + +struct apr_shm_t { + apr_pool_t *pool; + void *memblock; + void *ptr; + apr_size_t reqsize; + apr_size_t avail; + area_id aid; +}; + +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *p) +{ + apr_size_t pagesize; + area_id newid; + char *addr; + char shname[B_OS_NAME_LENGTH]; + + (*m) = (apr_shm_t *)apr_pcalloc(p, sizeof(apr_shm_t)); + /* we MUST allocate in pages, so calculate how big an area we need... */ + pagesize = ((reqsize + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE; + + if (!filename) { + int num = 0; + snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL)); + while (find_area(shname) >= 0) + snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d", + find_thread(NULL), num++); + } + newid = create_area(filename ? filename : shname, + (void*)&addr, B_ANY_ADDRESS, + pagesize, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA); + + if (newid < 0) + return errno; + + (*m)->pool = p; + (*m)->aid = newid; + (*m)->memblock = addr; + (*m)->ptr = (void*)addr; + (*m)->avail = pagesize; /* record how big an area we actually created... */ + (*m)->reqsize = reqsize; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) +{ + delete_area(m->aid); + m->avail = 0; + m->memblock = NULL; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, + apr_pool_t *pool) +{ + area_id deleteme = find_area(filename); + + if (deleteme == B_NAME_NOT_FOUND) + return APR_EINVAL; + + delete_area(deleteme); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool) +{ + area_info ai; + thread_info ti; + apr_shm_t *new_m; + area_id deleteme = find_area(filename); + + if (deleteme == B_NAME_NOT_FOUND) + return APR_EINVAL; + + new_m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*)); + if (new_m == NULL) + return APR_ENOMEM; + new_m->pool = pool; + + get_area_info(deleteme, &ai); + get_thread_info(find_thread(NULL), &ti); + + if (ti.team != ai.team) { + area_id narea; + + narea = clone_area(ai.name, &(ai.address), B_CLONE_ADDRESS, + B_READ_AREA|B_WRITE_AREA, ai.area); + + if (narea < B_OK) + return narea; + + get_area_info(narea, &ai); + new_m->aid = narea; + new_m->memblock = ai.address; + new_m->ptr = (void*)ai.address; + new_m->avail = ai.size; + new_m->reqsize = ai.size; + } + + (*m) = new_m; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) +{ + delete_area(m->aid); + return APR_SUCCESS; +} + +APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m) +{ + return m->memblock; +} + +APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m) +{ + return m->reqsize; +} + +APR_POOL_IMPLEMENT_ACCESSOR(shm) + +APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m, + apr_os_shm_t *osshm, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + diff --git a/srclib/apr/shmem/os2/shm.c b/srclib/apr/shmem/os2/shm.c new file mode 100644 index 0000000000..6294923382 --- /dev/null +++ b/srclib/apr/shmem/os2/shm.c @@ -0,0 +1,144 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_shm.h" +#include "apr_errno.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_portable.h" + +struct apr_shm_t { + apr_pool_t *pool; + void *memblock; +}; + +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool) +{ + int rc; + apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t)); + char *name = NULL; + ULONG flags = PAG_COMMIT|PAG_READ|PAG_WRITE; + + newm->pool = pool; + + if (filename) { + name = apr_pstrcat(pool, "\\SHAREMEM\\", filename, NULL); + } + + if (name == NULL) { + flags |= OBJ_GETTABLE; + } + + rc = DosAllocSharedMem(&(newm->memblock), name, reqsize, flags); + + if (rc) { + return APR_OS2_STATUS(rc); + } + + *m = newm; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) +{ + DosFreeMem(m->memblock); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool) +{ + int rc; + apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t)); + char *name = NULL; + ULONG flags = PAG_READ|PAG_WRITE; + + newm->pool = pool; + name = apr_pstrcat(pool, "\\SHAREMEM\\", filename, NULL); + + rc = DosGetNamedSharedMem(&(newm->memblock), name, flags); + + if (rc) { + return APR_FROM_OS_ERROR(rc); + } + + *m = newm; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) +{ + int rc = 0; + + if (m->memblock) { + rc = DosFreeMem(m->memblock); + } + + return APR_FROM_OS_ERROR(rc); +} + +APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m) +{ + return m->memblock; +} + +APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m) +{ + ULONG flags, size = 0x1000000; + DosQueryMem(m->memblock, &size, &flags); + return size; +} + +APR_POOL_IMPLEMENT_ACCESSOR(shm) + +APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm) +{ + *osshm = shm->memblock; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m, + apr_os_shm_t *osshm, + apr_pool_t *pool) +{ + int rc; + apr_shm_t *newm = (apr_shm_t *)apr_palloc(pool, sizeof(apr_shm_t)); + ULONG flags = PAG_COMMIT|PAG_READ|PAG_WRITE; + + newm->pool = pool; + + rc = DosGetSharedMem(&(newm->memblock), flags); + + if (rc) { + return APR_FROM_OS_ERROR(rc); + } + + *m = newm; + return APR_SUCCESS; +} + diff --git a/srclib/apr/shmem/unix/shm.c b/srclib/apr/shmem/unix/shm.c new file mode 100644 index 0000000000..d5b0bc6a3d --- /dev/null +++ b/srclib/apr/shmem/unix/shm.c @@ -0,0 +1,597 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_shm.h" + +#include "apr_general.h" +#include "apr_errno.h" +#include "apr_user.h" +#include "apr_strings.h" + +static apr_status_t shm_cleanup_owner(void *m_) +{ + apr_shm_t *m = (apr_shm_t *)m_; + + /* anonymous shared memory */ + if (m->filename == NULL) { +#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON + if (munmap(m->base, m->realsize) == -1) { + return errno; + } + return APR_SUCCESS; +#endif +#if APR_USE_SHMEM_SHMGET_ANON + if (shmdt(m->base) == -1) { + return errno; + } + /* This segment will automatically remove itself after all + * references have detached. */ + return APR_SUCCESS; +#endif + } + + /* name-based shared memory */ + else { +#if APR_USE_SHMEM_MMAP_TMP + if (munmap(m->base, m->realsize) == -1) { + return errno; + } + return apr_file_remove(m->filename, m->pool); +#endif +#if APR_USE_SHMEM_MMAP_SHM + if (munmap(m->base, m->realsize) == -1) { + return errno; + } + if (shm_unlink(m->filename) == -1) { + return errno; + } + return APR_SUCCESS; +#endif +#if APR_USE_SHMEM_SHMGET + /* Indicate that the segment is to be destroyed as soon + * as all processes have detached. This also disallows any + * new attachments to the segment. */ + if (shmctl(m->shmid, IPC_RMID, NULL) == -1) { + return errno; + } + if (shmdt(m->base) == -1) { + return errno; + } + return apr_file_remove(m->filename, m->pool); +#endif + } + + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *filename, + apr_pool_t *pool) +{ + apr_shm_t *new_m; + apr_status_t status; +#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON + struct shmid_ds shmbuf; + apr_uid_t uid; + apr_gid_t gid; +#endif +#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM || \ + APR_USE_SHMEM_MMAP_ZERO + int tmpfd; +#endif +#if APR_USE_SHMEM_SHMGET + apr_size_t nbytes; + key_t shmkey; +#endif +#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_SHMGET || \ + APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM + apr_file_t *file; /* file where metadata is stored */ +#endif + + /* Check if they want anonymous or name-based shared memory */ + if (filename == NULL) { +#if APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON + new_m = apr_palloc(pool, sizeof(apr_shm_t)); + new_m->pool = pool; + new_m->reqsize = reqsize; + new_m->realsize = reqsize + + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ + new_m->filename = NULL; + +#if APR_USE_SHMEM_MMAP_ZERO + status = apr_file_open(&file, "/dev/zero", APR_READ | APR_WRITE, + APR_OS_DEFAULT, pool); + if (status != APR_SUCCESS) { + return status; + } + status = apr_os_file_get(&tmpfd, file); + if (status != APR_SUCCESS) { + return status; + } + + new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, + MAP_SHARED, tmpfd, 0); + if (new_m->base == (void *)MAP_FAILED) { + return errno; + } + + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } + + /* store the real size in the metadata */ + *(apr_size_t*)(new_m->base) = new_m->realsize; + /* metadata isn't usable */ + new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#elif APR_USE_SHMEM_MMAP_ANON + new_m->base = mmap(NULL, new_m->realsize, PROT_READ|PROT_WRITE, + MAP_ANON|MAP_SHARED, -1, 0); + if (new_m->base == (void *)MAP_FAILED) { + return errno; + } + + /* store the real size in the metadata */ + *(apr_size_t*)(new_m->base) = new_m->realsize; + /* metadata isn't usable */ + new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#endif /* APR_USE_SHMEM_MMAP_ZERO */ +#endif /* APR_USE_SHMEM_MMAP_ZERO || APR_USE_SHMEM_MMAP_ANON */ +#if APR_USE_SHMEM_SHMGET_ANON + + new_m = apr_palloc(pool, sizeof(apr_shm_t)); + new_m->pool = pool; + new_m->reqsize = reqsize; + new_m->realsize = reqsize; + new_m->filename = NULL; + + if ((new_m->shmid = shmget(IPC_PRIVATE, new_m->realsize, + SHM_R | SHM_W | IPC_CREAT)) < 0) { + return errno; + } + + if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { + return errno; + } + new_m->usable = new_m->base; + + if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { + return errno; + } + apr_uid_current(&uid, &gid, pool); + shmbuf.shm_perm.uid = uid; + shmbuf.shm_perm.gid = gid; + if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { + return errno; + } + + /* Remove the segment once use count hits zero. + * We will not attach to this segment again, since it is + * anonymous memory, so it is ok to mark it for deletion. + */ + if (shmctl(new_m->shmid, IPC_RMID, NULL) == -1) { + return errno; + } + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; +#endif /* APR_USE_SHMEM_SHMGET_ANON */ + /* It is an error if they want anonymous memory but we don't have it. */ + return APR_ENOTIMPL; /* requested anonymous but we don't have it */ + } + + /* Name-based shared memory */ + else { + new_m = apr_palloc(pool, sizeof(apr_shm_t)); + new_m->pool = pool; + new_m->reqsize = reqsize; + new_m->filename = apr_pstrdup(pool, filename); + +#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM + new_m->realsize = reqsize + + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); /* room for metadata */ + /* FIXME: Ignore error for now. * + * status = apr_file_remove(file, pool);*/ + status = APR_SUCCESS; + +#if APR_USE_SHMEM_MMAP_TMP + /* FIXME: Is APR_OS_DEFAULT sufficient? */ + status = apr_file_open(&file, filename, + APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, + APR_OS_DEFAULT, pool); + if (status != APR_SUCCESS) { + return status; + } + + status = apr_os_file_get(&tmpfd, file); + if (status != APR_SUCCESS) { + apr_file_close(file); /* ignore errors, we're failing */ + apr_file_remove(new_m->filename, new_m->pool); + return status; + } + + status = apr_file_trunc(file, new_m->realsize); + if (status != APR_SUCCESS) { + apr_file_close(file); /* ignore errors, we're failing */ + apr_file_remove(new_m->filename, new_m->pool); + return status; + } + + new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, + MAP_SHARED, tmpfd, 0); + /* FIXME: check for errors */ + + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } +#endif /* APR_USE_SHMEM_MMAP_TMP */ +#if APR_USE_SHMEM_MMAP_SHM + tmpfd = shm_open(filename, O_RDWR | O_CREAT | O_EXCL, 0644); + if (tmpfd == -1) { + return errno; + } + + status = apr_os_file_put(&file, &tmpfd, + APR_READ | APR_WRITE | APR_CREATE | APR_EXCL, + pool); + if (status != APR_SUCCESS) { + return status; + } + + status = apr_file_trunc(file, new_m->realsize); + if (status != APR_SUCCESS) { + shm_unlink(filename); /* we're failing, remove the object */ + return status; + } + new_m->base = mmap(NULL, reqsize, PROT_READ | PROT_WRITE, + MAP_SHARED, tmpfd, 0); + + /* FIXME: check for errors */ + + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } +#endif /* APR_USE_SHMEM_MMAP_SHM */ + + /* store the real size in the metadata */ + *(apr_size_t*)(new_m->base) = new_m->realsize; + /* metadata isn't usable */ + new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */ + +#if APR_USE_SHMEM_SHMGET + new_m->realsize = reqsize; + + /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */ + status = apr_file_open(&file, filename, + APR_WRITE | APR_CREATE | APR_EXCL, + APR_OS_DEFAULT, pool); + if (status != APR_SUCCESS) { + return status; + } + + /* ftok() (on solaris at least) requires that the file actually + * exist before calling ftok(). */ + shmkey = ftok(filename, 1); + if (shmkey == (key_t)-1) { + return errno; + } + + if ((new_m->shmid = shmget(shmkey, new_m->realsize, + SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) { + return errno; + } + + if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { + return errno; + } + new_m->usable = new_m->base; + + if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) { + return errno; + } + apr_uid_current(&uid, &gid, pool); + shmbuf.shm_perm.uid = uid; + shmbuf.shm_perm.gid = gid; + if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) { + return errno; + } + + nbytes = sizeof(reqsize); + status = apr_file_write(file, (const void *)&reqsize, + &nbytes); + if (status != APR_SUCCESS) { + return status; + } + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_owner, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#endif /* APR_USE_SHMEM_SHMGET */ + } + + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, + apr_pool_t *pool) +{ +#if APR_USE_SHMEM_SHMGET + apr_status_t status; + apr_file_t *file; + key_t shmkey; + int shmid; +#endif + +#if APR_USE_SHMEM_MMAP_TMP + return apr_file_remove(filename, pool); +#endif +#if APR_USE_SHMEM_MMAP_SHM + if (shm_unlink(filename) == -1) { + return errno; + } + return APR_SUCCESS; +#endif +#if APR_USE_SHMEM_SHMGET + /* Presume that the file already exists; just open for writing */ + status = apr_file_open(&file, filename, APR_WRITE, + APR_OS_DEFAULT, pool); + if (status) { + return status; + } + + /* ftok() (on solaris at least) requires that the file actually + * exist before calling ftok(). */ + shmkey = ftok(filename, 1); + if (shmkey == (key_t)-1) { + goto shm_remove_failed; + } + + apr_file_close(file); + + if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) { + goto shm_remove_failed; + } + + /* Indicate that the segment is to be destroyed as soon + * as all processes have detached. This also disallows any + * new attachments to the segment. */ + if (shmctl(shmid, IPC_RMID, NULL) == -1) { + goto shm_remove_failed; + } + return apr_file_remove(filename, pool); + +shm_remove_failed: + status = errno; + /* ensure the file has been removed anyway. */ + apr_file_remove(filename, pool); + return status; +#endif + + /* No support for anonymous shm */ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) +{ + return apr_pool_cleanup_run(m->pool, m, shm_cleanup_owner); +} + +static apr_status_t shm_cleanup_attach(void *m_) +{ + apr_shm_t *m = (apr_shm_t *)m_; + + if (m->filename == NULL) { + /* It doesn't make sense to detach from an anonymous memory segment. */ + return APR_EINVAL; + } + else { +#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM + if (munmap(m->base, m->realsize) == -1) { + return errno; + } + return APR_SUCCESS; +#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */ +#if APR_USE_SHMEM_SHMGET + if (shmdt(m->base) == -1) { + return errno; + } + return APR_SUCCESS; +#endif + } + + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *filename, + apr_pool_t *pool) +{ + if (filename == NULL) { + /* It doesn't make sense to attach to a segment if you don't know + * the filename. */ + return APR_EINVAL; + } + else { +#if APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM + apr_shm_t *new_m; + apr_status_t status; + int tmpfd; + apr_file_t *file; /* file where metadata is stored */ + apr_size_t nbytes; + + new_m = apr_palloc(pool, sizeof(apr_shm_t)); + new_m->pool = pool; + new_m->filename = apr_pstrdup(pool, filename); + + status = apr_file_open(&file, filename, + APR_READ | APR_WRITE, + APR_OS_DEFAULT, pool); + if (status != APR_SUCCESS) { + return status; + } + status = apr_os_file_get(&tmpfd, file); + if (status != APR_SUCCESS) { + return status; + } + + nbytes = sizeof(new_m->realsize); + status = apr_file_read(file, (void *)&(new_m->realsize), + &nbytes); + if (status != APR_SUCCESS) { + return status; + } + + status = apr_os_file_get(&tmpfd, file); + if (status != APR_SUCCESS) { + apr_file_close(file); /* ignore errors, we're failing */ + apr_file_remove(new_m->filename, new_m->pool); + return status; + } + + new_m->reqsize = new_m->realsize - sizeof(apr_size_t); + + new_m->base = mmap(NULL, new_m->realsize, PROT_READ | PROT_WRITE, + MAP_SHARED, tmpfd, 0); + /* FIXME: check for errors */ + + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } + + /* metadata isn't part of the usable segment */ + new_m->usable = (char *)new_m->base + APR_ALIGN_DEFAULT(sizeof(apr_size_t)); + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#endif /* APR_USE_SHMEM_MMAP_TMP || APR_USE_SHMEM_MMAP_SHM */ +#if APR_USE_SHMEM_SHMGET + apr_shm_t *new_m; + apr_status_t status; + apr_file_t *file; /* file where metadata is stored */ + apr_size_t nbytes; + key_t shmkey; + + new_m = apr_palloc(pool, sizeof(apr_shm_t)); + + status = apr_file_open(&file, filename, + APR_READ, APR_OS_DEFAULT, pool); + if (status != APR_SUCCESS) { + return status; + } + + nbytes = sizeof(new_m->reqsize); + status = apr_file_read(file, (void *)&(new_m->reqsize), + &nbytes); + if (status != APR_SUCCESS) { + return status; + } + status = apr_file_close(file); + if (status != APR_SUCCESS) { + return status; + } + + new_m->filename = apr_pstrdup(pool, filename); + new_m->pool = pool; + shmkey = ftok(filename, 1); + if (shmkey == (key_t)-1) { + return errno; + } + if ((new_m->shmid = shmget(shmkey, 0, SHM_R | SHM_W)) == -1) { + return errno; + } + if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) { + return errno; + } + new_m->usable = new_m->base; + new_m->realsize = new_m->reqsize; + + apr_pool_cleanup_register(new_m->pool, new_m, shm_cleanup_attach, + apr_pool_cleanup_null); + *m = new_m; + return APR_SUCCESS; + +#endif /* APR_USE_SHMEM_SHMGET */ + } + + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) +{ + apr_status_t rv = shm_cleanup_attach(m); + apr_pool_cleanup_kill(m->pool, m, shm_cleanup_attach); + return rv; +} + +APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m) +{ + return m->usable; +} + +APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m) +{ + return m->reqsize; +} + +APR_POOL_IMPLEMENT_ACCESSOR(shm) + +APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m, + apr_os_shm_t *osshm, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + diff --git a/srclib/apr/shmem/win32/shm.c b/srclib/apr/shmem/win32/shm.c new file mode 100644 index 0000000000..32c952e0a7 --- /dev/null +++ b/srclib/apr/shmem/win32/shm.c @@ -0,0 +1,306 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_errno.h" +#include "apr_file_io.h" +#include "apr_shm.h" +#include "apr_arch_file_io.h" + +typedef struct memblock_t { + apr_size_t size; + apr_size_t length; +} memblock_t; + +struct apr_shm_t { + apr_pool_t *pool; + memblock_t *memblk; + void *usrmem; + apr_size_t size; + apr_size_t length; + HANDLE hMap; +}; + +static apr_status_t shm_cleanup(void* shm) +{ + apr_status_t rv = APR_SUCCESS; + apr_shm_t *m = shm; + + if (UnmapViewOfFile(m->memblk)) { + rv = apr_get_os_error(); + } + if (CloseHandle(m->hMap)) { + return (rv != APR_SUCCESS) ? rv : apr_get_os_error(); + } + /* ### Do we want to make a point of unlinking m->file here? + * Need to add the fname to the apr_shm_t, in that case. + */ + return rv; +} + +APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, + apr_size_t reqsize, + const char *file, + apr_pool_t *pool) +{ + static apr_size_t memblock = 0; + HANDLE hMap, hFile; + apr_status_t rv; + apr_size_t size; + apr_file_t *f; + void *base; + void *mapkey; + DWORD err; + + reqsize += sizeof(memblock_t); + + if (!memblock) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + memblock = si.dwAllocationGranularity; + } + + /* Compute the granualar multiple of the pagesize */ + size = memblock * (1 + (reqsize - 1) / memblock); + + if (!file) { + /* Do Anonymous, which must be passed as a duplicated handle */ +#ifndef _WIN32_WCE + hFile = INVALID_HANDLE_VALUE; +#endif + mapkey = NULL; + } + else { + /* Do file backed, which is not an inherited handle + * While we could open APR_EXCL, it doesn't seem that Unix + * ever did. Ignore that error here, but fail later when + * we discover we aren't the creator of the file map object. + */ + rv = apr_file_open(&f, file, + APR_READ | APR_WRITE | APR_BINARY | APR_CREATE, + APR_UREAD | APR_UWRITE, pool); + if ((rv != APR_SUCCESS) + || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) { + return rv; + } + rv = apr_file_trunc(f, size); + + /* res_name_from_filename turns file into a pseudo-name + * without slashes or backslashes, and prepends the \global + * prefix on Win2K and later + */ + mapkey = res_name_from_filename(file, 1, pool); + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + DWORD sizelo = (DWORD)size; + DWORD sizehi = (DWORD)(size >> 32); + hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE, + sizehi, sizelo, mapkey); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + DWORD sizelo = (DWORD)size; + DWORD sizehi = (DWORD)(size >> 32); + hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, + sizehi, sizelo, mapkey); + } +#endif + err = apr_get_os_error(); + + if (file) { + apr_file_close(f); + } + + if (hMap && err == ERROR_ALREADY_EXISTS) { + CloseHandle(hMap); + return APR_EEXIST; + } + if (!hMap) { + return err; + } + + base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, + 0, 0, size); + if (!base) { + CloseHandle(hMap); + return apr_get_os_error(); + } + + *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); + (*m)->pool = pool; + (*m)->hMap = hMap; + (*m)->memblk = base; + (*m)->size = size; + + (*m)->usrmem = (char*)base + sizeof(memblock_t); + (*m)->length = reqsize - sizeof(memblock_t);; + + (*m)->memblk->length = (*m)->length; + (*m)->memblk->size = (*m)->size; + + apr_pool_cleanup_register((*m)->pool, *m, + shm_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) +{ + apr_status_t rv = shm_cleanup(m); + apr_pool_cleanup_kill(m->pool, m, shm_cleanup); + return rv; +} + +APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, + apr_pool_t *pool) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_shm_attach(apr_shm_t **m, + const char *file, + apr_pool_t *pool) +{ + HANDLE hMap; + void *mapkey; + void *base; + + if (!file) { + return APR_EINVAL; + } + else { + /* res_name_from_filename turns file into a pseudo-name + * without slashes or backslashes, and prepends the \global + * prefix on Win2K and later + */ + mapkey = res_name_from_filename(file, 1, pool); + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { +#ifndef _WIN32_WCE + hMap = OpenFileMappingW(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey); +#else + /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with + * opening the existing shmem and reading its size from the header + */ + hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey); +#endif + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + hMap = OpenFileMappingA(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, mapkey); + } +#endif + + if (!hMap) { + return apr_get_os_error(); + } + + base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (!base) { + CloseHandle(hMap); + return apr_get_os_error(); + } + + *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); + (*m)->pool = pool; + (*m)->memblk = base; + /* Real (*m)->mem->size could be recovered with VirtualQuery */ + (*m)->size = (*m)->memblk->size; +#if _WIN32_WCE + /* Reopen with real size */ + UnmapViewOfFile(base); + CloseHandle(hMap); + + hMap = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, + PAGE_READWRITE, 0, (*m)->size, mapkey); + if (!hMap) { + return apr_get_os_error(); + } + base = MapViewOfFile(hMap, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (!base) { + CloseHandle(hMap); + return apr_get_os_error(); + } +#endif + (*m)->hMap = hMap; + (*m)->length = (*m)->memblk->length; + (*m)->usrmem = (char*)base + sizeof(memblock_t); + apr_pool_cleanup_register((*m)->pool, *m, + shm_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) +{ + apr_status_t rv = shm_cleanup(m); + apr_pool_cleanup_kill(m->pool, m, shm_cleanup); + return rv; +} + +APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m) +{ + return m->usrmem; +} + +APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m) +{ + return m->length; +} + +APR_POOL_IMPLEMENT_ACCESSOR(shm) + +APR_DECLARE(apr_status_t) apr_os_shm_get(apr_os_shm_t *osshm, + apr_shm_t *shm) +{ + *osshm = shm->hMap; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_shm_put(apr_shm_t **m, + apr_os_shm_t *osshm, + apr_pool_t *pool) +{ + void* base; + base = MapViewOfFile(*osshm, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0); + if (!base) { + return apr_get_os_error(); + } + + *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t)); + (*m)->pool = pool; + (*m)->hMap = *osshm; + (*m)->memblk = base; + (*m)->usrmem = (char*)base + sizeof(memblock_t); + /* Real (*m)->mem->size could be recovered with VirtualQuery */ + (*m)->size = (*m)->memblk->size; + (*m)->length = (*m)->memblk->length; + + apr_pool_cleanup_register((*m)->pool, *m, + shm_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + diff --git a/srclib/apr/strings/apr_cpystrn.c b/srclib/apr/strings/apr_cpystrn.c new file mode 100644 index 0000000000..9edba846a3 --- /dev/null +++ b/srclib/apr/strings/apr_cpystrn.c @@ -0,0 +1,312 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_strings.h" +#include "apr_private.h" +#include "apr_lib.h" + +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_CTYPE_H +#include +#endif + +/* + * Apache's "replacement" for the strncpy() function. We roll our + * own to implement these specific changes: + * (1) strncpy() doesn't always null terminate and we want it to. + * (2) strncpy() null fills, which is bogus, esp. when copy 8byte + * strings into 8k blocks. + * (3) Instead of returning the pointer to the beginning of + * the destination string, we return a pointer to the + * terminating '\0' to allow us to "check" for truncation + * + * apr_cpystrn() follows the same call structure as strncpy(). + */ + +APR_DECLARE(char *) apr_cpystrn(char *dst, const char *src, apr_size_t dst_size) +{ + + char *d, *end; + + if (dst_size == 0) { + return (dst); + } + + d = dst; + end = dst + dst_size - 1; + + for (; d < end; ++d, ++src) { + if (!(*d = *src)) { + return (d); + } + } + + *d = '\0'; /* always null terminate */ + + return (d); +} + + +/* + * This function provides a way to parse a generic argument string + * into a standard argv[] form of argument list. It respects the + * usual "whitespace" and quoteing rules. In the future this could + * be expanded to include support for the apr_call_exec command line + * string processing (including converting '+' to ' ' and doing the + * url processing. It does not currently support this function. + * + * token_context: Context from which pool allocations will occur. + * arg_str: Input argument string for conversion to argv[]. + * argv_out: Output location. This is a pointer to an array + * of pointers to strings (ie. &(char *argv[]). + * This value will be allocated from the contexts + * pool and filled in with copies of the tokens + * found during parsing of the arg_str. + */ +APR_DECLARE(apr_status_t) apr_tokenize_to_argv(const char *arg_str, + char ***argv_out, + apr_pool_t *token_context) +{ + const char *cp; + const char *ct; + char *cleaned, *dirty; + int escaped; + int isquoted, numargs = 0, argnum; + +#define SKIP_WHITESPACE(cp) \ + for ( ; *cp == ' ' || *cp == '\t'; ) { \ + cp++; \ + }; + +#define CHECK_QUOTATION(cp,isquoted) \ + isquoted = 0; \ + if (*cp == '"') { \ + isquoted = 1; \ + cp++; \ + } \ + else if (*cp == '\'') { \ + isquoted = 2; \ + cp++; \ + } + +/* DETERMINE_NEXTSTRING: + * At exit, cp will point to one of the following: NULL, SPACE, TAB or QUOTE. + * NULL implies the argument string has been fully traversed. + */ +#define DETERMINE_NEXTSTRING(cp,isquoted) \ + for ( ; *cp != '\0'; cp++) { \ + if ( (isquoted && (*cp == ' ' || *cp == '\t')) \ + || (*cp == '\\' && (*(cp+1) == ' ' || *(cp+1) == '\t' || \ + *(cp+1) == '"' || *(cp+1) == '\''))) { \ + cp++; \ + continue; \ + } \ + if ( (!isquoted && (*cp == ' ' || *cp == '\t')) \ + || (isquoted == 1 && *cp == '"') \ + || (isquoted == 2 && *cp == '\'') ) { \ + break; \ + } \ + } + +/* REMOVE_ESCAPE_CHARS: + * Compresses the arg string to remove all of the '\' escape chars. + * The final argv strings should not have any extra escape chars in it. + */ +#define REMOVE_ESCAPE_CHARS(cleaned, dirty, escaped) \ + escaped = 0; \ + while(*dirty) { \ + if (!escaped && *dirty == '\\') { \ + escaped = 1; \ + } \ + else { \ + escaped = 0; \ + *cleaned++ = *dirty; \ + } \ + ++dirty; \ + } \ + *cleaned = 0; /* last line of macro... */ + + cp = arg_str; + SKIP_WHITESPACE(cp); + ct = cp; + + /* This is ugly and expensive, but if anyone wants to figure a + * way to support any number of args without counting and + * allocating, please go ahead and change the code. + * + * Must account for the trailing NULL arg. + */ + numargs = 1; + while (*ct != '\0') { + CHECK_QUOTATION(ct, isquoted); + DETERMINE_NEXTSTRING(ct, isquoted); + if (*ct != '\0') { + ct++; + } + numargs++; + SKIP_WHITESPACE(ct); + } + *argv_out = apr_palloc(token_context, numargs * sizeof(char*)); + + /* determine first argument */ + for (argnum = 0; argnum < (numargs-1); argnum++) { + CHECK_QUOTATION(cp, isquoted); + ct = cp; + DETERMINE_NEXTSTRING(cp, isquoted); + cp++; + (*argv_out)[argnum] = apr_palloc(token_context, cp - ct); + apr_cpystrn((*argv_out)[argnum], ct, cp - ct); + cleaned = dirty = (*argv_out)[argnum]; + REMOVE_ESCAPE_CHARS(cleaned, dirty, escaped); + SKIP_WHITESPACE(cp); + } + (*argv_out)[argnum] = NULL; + + return APR_SUCCESS; +} + +/* Filepath_name_get returns the final element of the pathname. + * Using the current platform's filename syntax. + * "/foo/bar/gum" -> "gum" + * "/foo/bar/gum/" -> "" + * "gum" -> "gum" + * "wi\\n32\\stuff" -> "stuff + * + * Corrected Win32 to accept "a/b\\stuff", "a:stuff" + */ + +APR_DECLARE(const char *) apr_filepath_name_get(const char *pathname) +{ + const char path_separator = '/'; + const char *s = strrchr(pathname, path_separator); + +#ifdef WIN32 + const char path_separator_win = '\\'; + const char drive_separator_win = ':'; + const char *s2 = strrchr(pathname, path_separator_win); + + if (s2 > s) s = s2; + + if (!s) s = strrchr(pathname, drive_separator_win); +#endif + + return s ? ++s : pathname; +} + +/* length of dest assumed >= length of src + * collapse in place (src == dest) is legal. + * returns terminating null ptr to dest string. + */ +APR_DECLARE(char *) apr_collapse_spaces(char *dest, const char *src) +{ + while (*src) { + if (!apr_isspace(*src)) + *dest++ = *src; + ++src; + } + *dest = 0; + return (dest); +} + +#if !APR_HAVE_STRDUP +char *strdup(const char *str) +{ + char *sdup; + size_t len = strlen(str) + 1; + + sdup = (char *) malloc(len); + memcpy(sdup, str, len); + + return sdup; +} +#endif + +/* The following two routines were donated for SVR4 by Andreas Vogel */ +#if (!APR_HAVE_STRCASECMP && !APR_HAVE_STRICMP) +int strcasecmp(const char *a, const char *b) +{ + const char *p = a; + const char *q = b; + for (p = a, q = b; *p && *q; p++, q++) { + int diff = apr_tolower(*p) - apr_tolower(*q); + if (diff) + return diff; + } + if (*p) + return 1; /* p was longer than q */ + if (*q) + return -1; /* p was shorter than q */ + return 0; /* Exact match */ +} + +#endif + +#if (!APR_HAVE_STRNCASECMP && !APR_HAVE_STRNICMP) +int strncasecmp(const char *a, const char *b, size_t n) +{ + const char *p = a; + const char *q = b; + + for (p = a, q = b; /*NOTHING */ ; p++, q++) { + int diff; + if (p == a + n) + return 0; /* Match up to n characters */ + if (!(*p && *q)) + return *p - *q; + diff = apr_tolower(*p) - apr_tolower(*q); + if (diff) + return diff; + } + /*NOTREACHED */ +} +#endif + +/* The following routine was donated for UTS21 by dwd@bell-labs.com */ +#if (!APR_HAVE_STRSTR) +char *strstr(char *s1, char *s2) +{ + char *p1, *p2; + if (*s2 == '\0') { + /* an empty s2 */ + return(s1); + } + while((s1 = strchr(s1, *s2)) != NULL) { + /* found first character of s2, see if the rest matches */ + p1 = s1; + p2 = s2; + while (*++p1 == *++p2) { + if (*p1 == '\0') { + /* both strings ended together */ + return(s1); + } + } + if (*p2 == '\0') { + /* second string ended, a match */ + break; + } + /* didn't find a match here, try starting at next character in s1 */ + s1++; + } + return(s1); +} +#endif + diff --git a/srclib/apr/strings/apr_fnmatch.c b/srclib/apr/strings/apr_fnmatch.c new file mode 100644 index 0000000000..7c41ea6585 --- /dev/null +++ b/srclib/apr/strings/apr_fnmatch.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#endif /* LIBC_SCCS and not lint */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ +#ifndef WIN32 +#include "apr_private.h" +#endif +#include "apr_file_info.h" +#include "apr_fnmatch.h" +#include "apr_tables.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include +#if APR_HAVE_CTYPE_H +# include +#endif + +#define EOS '\0' + +static const char *rangematch(const char *, int, int); + +APR_DECLARE(apr_status_t) apr_fnmatch(const char *pattern, const char *string, int flags) +{ + const char *stringstart; + char c, test; + + for (stringstart = string;;) { + switch (c = *pattern++) { + case EOS: + return (*string == EOS ? APR_SUCCESS : APR_FNM_NOMATCH); + case '?': + if (*string == EOS) { + return (APR_FNM_NOMATCH); + } + if (*string == '/' && (flags & APR_FNM_PATHNAME)) { + return (APR_FNM_NOMATCH); + } + if (*string == '.' && (flags & APR_FNM_PERIOD) && + (string == stringstart || + ((flags & APR_FNM_PATHNAME) && *(string - 1) == '/'))) { + return (APR_FNM_NOMATCH); + } + ++string; + break; + case '*': + c = *pattern; + /* Collapse multiple stars. */ + while (c == '*') { + c = *++pattern; + } + + if (*string == '.' && (flags & APR_FNM_PERIOD) && + (string == stringstart || + ((flags & APR_FNM_PATHNAME) && *(string - 1) == '/'))) { + return (APR_FNM_NOMATCH); + } + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & APR_FNM_PATHNAME) { + return (strchr(string, '/') == NULL ? APR_SUCCESS : APR_FNM_NOMATCH); + } + else { + return (APR_SUCCESS); + } + } + else if (c == '/' && flags & APR_FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) { + return (APR_FNM_NOMATCH); + } + break; + } + + /* General case, use recursion. */ + while ((test = *string) != EOS) { + if (!apr_fnmatch(pattern, string, flags & ~APR_FNM_PERIOD)) { + return (APR_SUCCESS); + } + if (test == '/' && flags & APR_FNM_PATHNAME) { + break; + } + ++string; + } + return (APR_FNM_NOMATCH); + case '[': + if (*string == EOS) { + return (APR_FNM_NOMATCH); + } + if (*string == '/' && flags & APR_FNM_PATHNAME) { + return (APR_FNM_NOMATCH); + } + if (*string == '.' && (flags & APR_FNM_PERIOD) && + (string == stringstart || + ((flags & APR_FNM_PATHNAME) && *(string - 1) == '/'))) { + return (APR_FNM_NOMATCH); + } + if ((pattern = rangematch(pattern, *string, flags)) == NULL) { + return (APR_FNM_NOMATCH); + } + ++string; + break; + case '\\': + if (!(flags & APR_FNM_NOESCAPE)) { + if ((c = *pattern++) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (flags & APR_FNM_CASE_BLIND) { + if (apr_tolower(c) != apr_tolower(*string)) { + return (APR_FNM_NOMATCH); + } + } + else if (c != *string) { + return (APR_FNM_NOMATCH); + } + string++; + break; + } + /* NOTREACHED */ + } +} + +static const char *rangematch(const char *pattern, int test, int flags) +{ + int negate, ok; + char c, c2; + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^'))) { + ++pattern; + } + + for (ok = 0; (c = *pattern++) != ']';) { + if (c == '\\' && !(flags & APR_FNM_NOESCAPE)) { + c = *pattern++; + } + if (c == EOS) { + return (NULL); + } + if (*pattern == '-' && (c2 = *(pattern + 1)) != EOS && c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & APR_FNM_NOESCAPE)) { + c2 = *pattern++; + } + if (c2 == EOS) { + return (NULL); + } + if ((c <= test && test <= c2) + || ((flags & APR_FNM_CASE_BLIND) + && ((apr_tolower(c) <= apr_tolower(test)) + && (apr_tolower(test) <= apr_tolower(c2))))) { + ok = 1; + } + } + else if ((c == test) + || ((flags & APR_FNM_CASE_BLIND) + && (apr_tolower(c) == apr_tolower(test)))) { + ok = 1; + } + } + return (ok == negate ? NULL : pattern); +} + + +/* This function is an Apache addition */ +/* return non-zero if pattern has any glob chars in it */ +APR_DECLARE(int) apr_fnmatch_test(const char *pattern) +{ + int nesting; + + nesting = 0; + while (*pattern) { + switch (*pattern) { + case '?': + case '*': + return 1; + + case '\\': + if (*pattern++ == '\0') { + return 0; + } + break; + + case '[': /* '[' is only a glob if it has a matching ']' */ + ++nesting; + break; + + case ']': + if (nesting) { + return 1; + } + break; + } + ++pattern; + } + return 0; +} + +/* Find all files matching the specified pattern */ +APR_DECLARE(apr_status_t) apr_match_glob(const char *pattern, + apr_array_header_t **result, + apr_pool_t *p) +{ + apr_dir_t *dir; + apr_finfo_t finfo; + apr_status_t rv; + char *path; + + /* XXX So, this is kind of bogus. Basically, I need to strip any leading + * directories off the pattern, but there is no portable way to do that. + * So, for now we just find the last occurance of '/' and if that doesn't + * return anything, then we look for '\'. This means that we could + * screw up on unix if the pattern is something like "foo\.*" That '\' + * isn't a directory delimiter, it is a part of the filename. To fix this, + * we really need apr_filepath_basename, which will be coming as soon as + * I get to it. rbb + */ + char *idx = strrchr(pattern, '/'); + + if (idx == NULL) { + idx = strrchr(pattern, '\\'); + } + if (idx == NULL) { + path = "."; + } + else { + path = apr_pstrndup(p, pattern, idx - pattern); + pattern = idx + 1; + } + + *result = apr_array_make(p, 0, sizeof(char *)); + rv = apr_dir_open(&dir, path, p); + if (rv != APR_SUCCESS) { + return rv; + } + + while (apr_dir_read(&finfo, APR_FINFO_NAME, dir) == APR_SUCCESS) { + if (apr_fnmatch(pattern, finfo.name, 0) == APR_SUCCESS) { + *(const char **)apr_array_push(*result) = apr_pstrdup(p, finfo.name); + } + } + apr_dir_close(dir); + return APR_SUCCESS; +} diff --git a/srclib/apr/strings/apr_snprintf.c b/srclib/apr/strings/apr_snprintf.c new file mode 100644 index 0000000000..0d5dad0bb2 --- /dev/null +++ b/srclib/apr/strings/apr_snprintf.c @@ -0,0 +1,1310 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_private.h" + +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_network_io.h" +#include "apr_portable.h" +#include +#if APR_HAVE_CTYPE_H +#include +#endif +#if APR_HAVE_NETINET_IN_H +#include +#endif +#if APR_HAVE_SYS_SOCKET_H +#include +#endif +#if APR_HAVE_ARPA_INET_H +#include +#endif +#if APR_HAVE_LIMITS_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif + +typedef enum { + NO = 0, YES = 1 +} boolean_e; + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif +#define NUL '\0' +#define WIDE_INT long + +typedef WIDE_INT wide_int; +typedef unsigned WIDE_INT u_wide_int; +typedef apr_int64_t widest_int; +#ifdef __TANDEM +/* Although Tandem supports "long long" there is no unsigned variant. */ +typedef unsigned long u_widest_int; +#else +typedef apr_uint64_t u_widest_int; +#endif +typedef int bool_int; + +#define S_NULL "(null)" +#define S_NULL_LEN 6 + +#define FLOAT_DIGITS 6 +#define EXPONENT_LENGTH 10 + +/* + * NUM_BUF_SIZE is the size of the buffer used for arithmetic conversions + * + * NOTICE: this is a magic number; do not decrease it + */ +#define NUM_BUF_SIZE 512 + +/* + * cvt.c - IEEE floating point formatting routines for FreeBSD + * from GNU libc-4.6.27. Modified to be thread safe. + */ + +/* + * apr_ecvt converts to decimal + * the number of digits is specified by ndigit + * decpt is set to the position of the decimal point + * sign is set to 0 for positive, 1 for negative + */ + +#define NDIG 80 + +/* buf must have at least NDIG bytes */ +static char *apr_cvt(double arg, int ndigits, int *decpt, int *sign, + int eflag, char *buf) +{ + register int r2; + double fi, fj; + register char *p, *p1; + + if (ndigits >= NDIG - 1) + ndigits = NDIG - 2; + r2 = 0; + *sign = 0; + p = &buf[0]; + if (arg < 0) { + *sign = 1; + arg = -arg; + } + arg = modf(arg, &fi); + p1 = &buf[NDIG]; + /* + * Do integer part + */ + if (fi != 0) { + p1 = &buf[NDIG]; + while (p1 > &buf[0] && fi != 0) { + fj = modf(fi / 10, &fi); + *--p1 = (int) ((fj + .03) * 10) + '0'; + r2++; + } + while (p1 < &buf[NDIG]) + *p++ = *p1++; + } + else if (arg > 0) { + while ((fj = arg * 10) < 1) { + arg = fj; + r2--; + } + } + p1 = &buf[ndigits]; + if (eflag == 0) + p1 += r2; + if (p1 < &buf[0]) { + *decpt = -ndigits; + buf[0] = '\0'; + return (buf); + } + *decpt = r2; + while (p <= p1 && p < &buf[NDIG]) { + arg *= 10; + arg = modf(arg, &fj); + *p++ = (int) fj + '0'; + } + if (p1 >= &buf[NDIG]) { + buf[NDIG - 1] = '\0'; + return (buf); + } + p = p1; + *p1 += 5; + while (*p1 > '9') { + *p1 = '0'; + if (p1 > buf) + ++ * --p1; + else { + *p1 = '1'; + (*decpt)++; + if (eflag == 0) { + if (p > buf) + *p = '0'; + p++; + } + } + } + *p = '\0'; + return (buf); +} + +static char *apr_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf) +{ + return (apr_cvt(arg, ndigits, decpt, sign, 1, buf)); +} + +static char *apr_fcvt(double arg, int ndigits, int *decpt, int *sign, char *buf) +{ + return (apr_cvt(arg, ndigits, decpt, sign, 0, buf)); +} + +/* + * apr_gcvt - Floating output conversion to + * minimal length string + */ + +static char *apr_gcvt(double number, int ndigit, char *buf, boolean_e altform) +{ + int sign, decpt; + register char *p1, *p2; + register int i; + char buf1[NDIG]; + + p1 = apr_ecvt(number, ndigit, &decpt, &sign, buf1); + p2 = buf; + if (sign) + *p2++ = '-'; + for (i = ndigit - 1; i > 0 && p1[i] == '0'; i--) + ndigit--; + if ((decpt >= 0 && decpt - ndigit > 4) + || (decpt < 0 && decpt < -3)) { /* use E-style */ + decpt--; + *p2++ = *p1++; + *p2++ = '.'; + for (i = 1; i < ndigit; i++) + *p2++ = *p1++; + *p2++ = 'e'; + if (decpt < 0) { + decpt = -decpt; + *p2++ = '-'; + } + else + *p2++ = '+'; + if (decpt / 100 > 0) + *p2++ = decpt / 100 + '0'; + if (decpt / 10 > 0) + *p2++ = (decpt % 100) / 10 + '0'; + *p2++ = decpt % 10 + '0'; + } + else { + if (decpt <= 0) { + if (*p1 != '0') + *p2++ = '.'; + while (decpt < 0) { + decpt++; + *p2++ = '0'; + } + } + for (i = 1; i <= ndigit; i++) { + *p2++ = *p1++; + if (i == decpt) + *p2++ = '.'; + } + if (ndigit < decpt) { + while (ndigit++ < decpt) + *p2++ = '0'; + *p2++ = '.'; + } + } + if (p2[-1] == '.' && !altform) + p2--; + *p2 = '\0'; + return (buf); +} + +/* + * The INS_CHAR macro inserts a character in the buffer and writes + * the buffer back to disk if necessary + * It uses the char pointers sp and bep: + * sp points to the next available character in the buffer + * bep points to the end-of-buffer+1 + * While using this macro, note that the nextb pointer is NOT updated. + * + * NOTE: Evaluation of the c argument should not have any side-effects + */ +#define INS_CHAR(c, sp, bep, cc) \ +{ \ + if (sp) { \ + if (sp >= bep) { \ + vbuff->curpos = sp; \ + if (flush_func(vbuff)) \ + return -1; \ + sp = vbuff->curpos; \ + bep = vbuff->endpos; \ + } \ + *sp++ = (c); \ + } \ + cc++; \ +} + +#define NUM(c) (c - '0') + +#define STR_TO_DEC(str, num) \ + num = NUM(*str++); \ + while (apr_isdigit(*str)) \ + { \ + num *= 10 ; \ + num += NUM(*str++); \ + } + +/* + * This macro does zero padding so that the precision + * requirement is satisfied. The padding is done by + * adding '0's to the left of the string that is going + * to be printed. We don't allow precision to be large + * enough that we continue past the start of s. + * + * NOTE: this makes use of the magic info that s is + * always based on num_buf with a size of NUM_BUF_SIZE. + */ +#define FIX_PRECISION(adjust, precision, s, s_len) \ + if (adjust) { \ + int p = precision < NUM_BUF_SIZE - 1 ? precision : NUM_BUF_SIZE - 1; \ + while (s_len < p) \ + { \ + *--s = '0'; \ + s_len++; \ + } \ + } + +/* + * Macro that does padding. The padding is done by printing + * the character ch. + */ +#define PAD(width, len, ch) \ +do \ +{ \ + INS_CHAR(ch, sp, bep, cc); \ + width--; \ +} \ +while (width > len) + +/* + * Prefix the character ch to the string str + * Increase length + * Set the has_prefix flag + */ +#define PREFIX(str, length, ch) \ + *--str = ch; \ + length++; \ + has_prefix=YES; + + +/* + * Convert num to its decimal format. + * Return value: + * - a pointer to a string containing the number (no sign) + * - len contains the length of the string + * - is_negative is set to TRUE or FALSE depending on the sign + * of the number (always set to FALSE if is_unsigned is TRUE) + * + * The caller provides a buffer for the string: that is the buf_end argument + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) + * + * Note: we have 2 versions. One is used when we need to use quads + * (conv_10_quad), the other when we don't (conv_10). We're assuming the + * latter is faster. + */ +static char *conv_10(register wide_int num, register bool_int is_unsigned, + register bool_int *is_negative, char *buf_end, + register apr_size_t *len) +{ + register char *p = buf_end; + register u_wide_int magnitude; + + if (is_unsigned) { + magnitude = (u_wide_int) num; + *is_negative = FALSE; + } + else { + *is_negative = (num < 0); + + /* + * On a 2's complement machine, negating the most negative integer + * results in a number that cannot be represented as a signed integer. + * Here is what we do to obtain the number's magnitude: + * a. add 1 to the number + * b. negate it (becomes positive) + * c. convert it to unsigned + * d. add 1 + */ + if (*is_negative) { + wide_int t = num + 1; + + magnitude = ((u_wide_int) -t) + 1; + } + else + magnitude = (u_wide_int) num; + } + + /* + * We use a do-while loop so that we write at least 1 digit + */ + do { + register u_wide_int new_magnitude = magnitude / 10; + + *--p = (char) (magnitude - new_magnitude * 10 + '0'); + magnitude = new_magnitude; + } + while (magnitude); + + *len = buf_end - p; + return (p); +} + +static char *conv_10_quad(widest_int num, register bool_int is_unsigned, + register bool_int *is_negative, char *buf_end, + register apr_size_t *len) +{ + register char *p = buf_end; + u_widest_int magnitude; + + /* + * We see if we can use the faster non-quad version by checking the + * number against the largest long value it can be. If <=, we + * punt to the quicker version. + */ + if ((num <= ULONG_MAX && is_unsigned) + || (num <= LONG_MAX && num >= LONG_MIN && !is_unsigned)) + return(conv_10( (wide_int)num, is_unsigned, is_negative, + buf_end, len)); + + if (is_unsigned) { + magnitude = (u_widest_int) num; + *is_negative = FALSE; + } + else { + *is_negative = (num < 0); + + /* + * On a 2's complement machine, negating the most negative integer + * results in a number that cannot be represented as a signed integer. + * Here is what we do to obtain the number's magnitude: + * a. add 1 to the number + * b. negate it (becomes positive) + * c. convert it to unsigned + * d. add 1 + */ + if (*is_negative) { + widest_int t = num + 1; + + magnitude = ((u_widest_int) -t) + 1; + } + else + magnitude = (u_widest_int) num; + } + + /* + * We use a do-while loop so that we write at least 1 digit + */ + do { + u_widest_int new_magnitude = magnitude / 10; + + *--p = (char) (magnitude - new_magnitude * 10 + '0'); + magnitude = new_magnitude; + } + while (magnitude); + + *len = buf_end - p; + return (p); +} + + + +static char *conv_in_addr(struct in_addr *ia, char *buf_end, apr_size_t *len) +{ + unsigned addr = ntohl(ia->s_addr); + char *p = buf_end; + bool_int is_negative; + apr_size_t sub_len; + + p = conv_10((addr & 0x000000FF) , TRUE, &is_negative, p, &sub_len); + *--p = '.'; + p = conv_10((addr & 0x0000FF00) >> 8, TRUE, &is_negative, p, &sub_len); + *--p = '.'; + p = conv_10((addr & 0x00FF0000) >> 16, TRUE, &is_negative, p, &sub_len); + *--p = '.'; + p = conv_10((addr & 0xFF000000) >> 24, TRUE, &is_negative, p, &sub_len); + + *len = buf_end - p; + return (p); +} + + + +static char *conv_apr_sockaddr(apr_sockaddr_t *sa, char *buf_end, apr_size_t *len) +{ + char *p = buf_end; + bool_int is_negative; + apr_size_t sub_len; + char *ipaddr_str; + + p = conv_10(sa->port, TRUE, &is_negative, p, &sub_len); + *--p = ':'; + apr_sockaddr_ip_get(&ipaddr_str, sa); + sub_len = strlen(ipaddr_str); +#if APR_HAVE_IPV6 + if (sa->family == APR_INET6 && + !IN6_IS_ADDR_V4MAPPED(&sa->sa.sin6.sin6_addr)) { + *(p - 1) = ']'; + p -= sub_len + 2; + *p = '['; + memcpy(p + 1, ipaddr_str, sub_len); + } + else +#endif + { + p -= sub_len; + memcpy(p, ipaddr_str, sub_len); + } + + *len = buf_end - p; + return (p); +} + + + +#if APR_HAS_THREADS +static char *conv_os_thread_t(apr_os_thread_t *tid, char *buf_end, apr_size_t *len) +{ + union { + apr_os_thread_t tid; + apr_uint64_t alignme; + } u; + int is_negative; + + u.tid = *tid; + switch(sizeof(u.tid)) { + case sizeof(apr_int32_t): + return conv_10(*(apr_uint32_t *)&u.tid, TRUE, &is_negative, buf_end, len); + case sizeof(apr_int64_t): + return conv_10_quad(*(apr_uint64_t *)&u.tid, TRUE, &is_negative, buf_end, len); + default: + /* not implemented; stick 0 in the buffer */ + return conv_10(0, TRUE, &is_negative, buf_end, len); + } +} +#endif + + + +/* + * Convert a floating point number to a string formats 'f', 'e' or 'E'. + * The result is placed in buf, and len denotes the length of the string + * The sign is returned in the is_negative argument (and is not placed + * in buf). + */ +static char *conv_fp(register char format, register double num, + boolean_e add_dp, int precision, bool_int *is_negative, + char *buf, apr_size_t *len) +{ + register char *s = buf; + register char *p; + int decimal_point; + char buf1[NDIG]; + + if (format == 'f') + p = apr_fcvt(num, precision, &decimal_point, is_negative, buf1); + else /* either e or E format */ + p = apr_ecvt(num, precision + 1, &decimal_point, is_negative, buf1); + + /* + * Check for Infinity and NaN + */ + if (apr_isalpha(*p)) { + *len = strlen(p); + memcpy(buf, p, *len + 1); + *is_negative = FALSE; + return (buf); + } + + if (format == 'f') { + if (decimal_point <= 0) { + *s++ = '0'; + if (precision > 0) { + *s++ = '.'; + while (decimal_point++ < 0) + *s++ = '0'; + } + else if (add_dp) + *s++ = '.'; + } + else { + while (decimal_point-- > 0) + *s++ = *p++; + if (precision > 0 || add_dp) + *s++ = '.'; + } + } + else { + *s++ = *p++; + if (precision > 0 || add_dp) + *s++ = '.'; + } + + /* + * copy the rest of p, the NUL is NOT copied + */ + while (*p) + *s++ = *p++; + + if (format != 'f') { + char temp[EXPONENT_LENGTH]; /* for exponent conversion */ + apr_size_t t_len; + bool_int exponent_is_negative; + + *s++ = format; /* either e or E */ + decimal_point--; + if (decimal_point != 0) { + p = conv_10((wide_int) decimal_point, FALSE, &exponent_is_negative, + &temp[EXPONENT_LENGTH], &t_len); + *s++ = exponent_is_negative ? '-' : '+'; + + /* + * Make sure the exponent has at least 2 digits + */ + if (t_len == 1) + *s++ = '0'; + while (t_len--) + *s++ = *p++; + } + else { + *s++ = '+'; + *s++ = '0'; + *s++ = '0'; + } + } + + *len = s - buf; + return (buf); +} + + +/* + * Convert num to a base X number where X is a power of 2. nbits determines X. + * For example, if nbits is 3, we do base 8 conversion + * Return value: + * a pointer to a string containing the number + * + * The caller provides a buffer for the string: that is the buf_end argument + * which is a pointer to the END of the buffer + 1 (i.e. if the buffer + * is declared as buf[ 100 ], buf_end should be &buf[ 100 ]) + * + * As with conv_10, we have a faster version which is used when + * the number isn't quad size. + */ +static char *conv_p2(register u_wide_int num, register int nbits, + char format, char *buf_end, register apr_size_t *len) +{ + register int mask = (1 << nbits) - 1; + register char *p = buf_end; + static const char low_digits[] = "0123456789abcdef"; + static const char upper_digits[] = "0123456789ABCDEF"; + register const char *digits = (format == 'X') ? upper_digits : low_digits; + + do { + *--p = digits[num & mask]; + num >>= nbits; + } + while (num); + + *len = buf_end - p; + return (p); +} + +static char *conv_p2_quad(u_widest_int num, register int nbits, + char format, char *buf_end, register apr_size_t *len) +{ + register int mask = (1 << nbits) - 1; + register char *p = buf_end; + static const char low_digits[] = "0123456789abcdef"; + static const char upper_digits[] = "0123456789ABCDEF"; + register const char *digits = (format == 'X') ? upper_digits : low_digits; + + if (num <= ULONG_MAX) + return(conv_p2((u_wide_int)num, nbits, format, buf_end, len)); + + do { + *--p = digits[num & mask]; + num >>= nbits; + } + while (num); + + *len = buf_end - p; + return (p); +} + + +/* + * Do format conversion placing the output in buffer + */ +APR_DECLARE(int) apr_vformatter(int (*flush_func)(apr_vformatter_buff_t *), + apr_vformatter_buff_t *vbuff, const char *fmt, va_list ap) +{ + register char *sp; + register char *bep; + register int cc = 0; + register apr_size_t i; + + register char *s = NULL; + char *q; + apr_size_t s_len; + + register int min_width = 0; + int precision = 0; + enum { + LEFT, RIGHT + } adjust; + char pad_char; + char prefix_char; + + double fp_num; + widest_int i_quad = (widest_int) 0; + u_widest_int ui_quad; + wide_int i_num = (wide_int) 0; + u_wide_int ui_num; + + char num_buf[NUM_BUF_SIZE]; + char char_buf[2]; /* for printing %% and % */ + + enum var_type_enum { + IS_QUAD, IS_LONG, IS_SHORT, IS_INT + }; + enum var_type_enum var_type = IS_INT; + + /* + * Flag variables + */ + boolean_e alternate_form; + boolean_e print_sign; + boolean_e print_blank; + boolean_e adjust_precision; + boolean_e adjust_width; + bool_int is_negative; + + sp = vbuff->curpos; + bep = vbuff->endpos; + + while (*fmt) { + if (*fmt != '%') { + INS_CHAR(*fmt, sp, bep, cc); + } + else { + /* + * Default variable settings + */ + boolean_e print_something = YES; + adjust = RIGHT; + alternate_form = print_sign = print_blank = NO; + pad_char = ' '; + prefix_char = NUL; + + fmt++; + + /* + * Try to avoid checking for flags, width or precision + */ + if (!apr_islower(*fmt)) { + /* + * Recognize flags: -, #, BLANK, + + */ + for (;; fmt++) { + if (*fmt == '-') + adjust = LEFT; + else if (*fmt == '+') + print_sign = YES; + else if (*fmt == '#') + alternate_form = YES; + else if (*fmt == ' ') + print_blank = YES; + else if (*fmt == '0') + pad_char = '0'; + else + break; + } + + /* + * Check if a width was specified + */ + if (apr_isdigit(*fmt)) { + STR_TO_DEC(fmt, min_width); + adjust_width = YES; + } + else if (*fmt == '*') { + min_width = va_arg(ap, int); + fmt++; + adjust_width = YES; + if (min_width < 0) { + adjust = LEFT; + min_width = -min_width; + } + } + else + adjust_width = NO; + + /* + * Check if a precision was specified + */ + if (*fmt == '.') { + adjust_precision = YES; + fmt++; + if (apr_isdigit(*fmt)) { + STR_TO_DEC(fmt, precision); + } + else if (*fmt == '*') { + precision = va_arg(ap, int); + fmt++; + if (precision < 0) + precision = 0; + } + else + precision = 0; + } + else + adjust_precision = NO; + } + else + adjust_precision = adjust_width = NO; + + /* + * Modifier check. Note that if APR_INT64_T_FMT is "d", + * the first if condition is never true. + */ + if ((sizeof(APR_INT64_T_FMT) == 4 && + fmt[0] == APR_INT64_T_FMT[0] && + fmt[1] == APR_INT64_T_FMT[1]) || + (sizeof(APR_INT64_T_FMT) == 3 && + fmt[0] == APR_INT64_T_FMT[0]) || + (sizeof(APR_INT64_T_FMT) > 4 && + strncmp(fmt, APR_INT64_T_FMT, + sizeof(APR_INT64_T_FMT) - 2) == 0)) { + /* Need to account for trailing 'd' and null in sizeof() */ + var_type = IS_QUAD; + fmt += (sizeof(APR_INT64_T_FMT) - 2); + } + else if (*fmt == 'q') { + var_type = IS_QUAD; + fmt++; + } + else if (*fmt == 'l') { + var_type = IS_LONG; + fmt++; + } + else if (*fmt == 'h') { + var_type = IS_SHORT; + fmt++; + } + else { + var_type = IS_INT; + } + + /* + * Argument extraction and printing. + * First we determine the argument type. + * Then, we convert the argument to a string. + * On exit from the switch, s points to the string that + * must be printed, s_len has the length of the string + * The precision requirements, if any, are reflected in s_len. + * + * NOTE: pad_char may be set to '0' because of the 0 flag. + * It is reset to ' ' by non-numeric formats + */ + switch (*fmt) { + case 'u': + if (var_type == IS_QUAD) { + i_quad = va_arg(ap, u_widest_int); + s = conv_10_quad(i_quad, 1, &is_negative, + &num_buf[NUM_BUF_SIZE], &s_len); + } + else { + if (var_type == IS_LONG) + i_num = (wide_int) va_arg(ap, u_wide_int); + else if (var_type == IS_SHORT) + i_num = (wide_int) (unsigned short) va_arg(ap, unsigned int); + else + i_num = (wide_int) va_arg(ap, unsigned int); + s = conv_10(i_num, 1, &is_negative, + &num_buf[NUM_BUF_SIZE], &s_len); + } + FIX_PRECISION(adjust_precision, precision, s, s_len); + break; + + case 'd': + case 'i': + if (var_type == IS_QUAD) { + i_quad = va_arg(ap, widest_int); + s = conv_10_quad(i_quad, 0, &is_negative, + &num_buf[NUM_BUF_SIZE], &s_len); + } + else { + if (var_type == IS_LONG) + i_num = (wide_int) va_arg(ap, wide_int); + else if (var_type == IS_SHORT) + i_num = (wide_int) (short) va_arg(ap, int); + else + i_num = (wide_int) va_arg(ap, int); + s = conv_10(i_num, 0, &is_negative, + &num_buf[NUM_BUF_SIZE], &s_len); + } + FIX_PRECISION(adjust_precision, precision, s, s_len); + + if (is_negative) + prefix_char = '-'; + else if (print_sign) + prefix_char = '+'; + else if (print_blank) + prefix_char = ' '; + break; + + + case 'o': + if (var_type == IS_QUAD) { + ui_quad = va_arg(ap, u_widest_int); + s = conv_p2_quad(ui_quad, 3, *fmt, + &num_buf[NUM_BUF_SIZE], &s_len); + } + else { + if (var_type == IS_LONG) + ui_num = (u_wide_int) va_arg(ap, u_wide_int); + else if (var_type == IS_SHORT) + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); + else + ui_num = (u_wide_int) va_arg(ap, unsigned int); + s = conv_p2(ui_num, 3, *fmt, + &num_buf[NUM_BUF_SIZE], &s_len); + } + FIX_PRECISION(adjust_precision, precision, s, s_len); + if (alternate_form && *s != '0') { + *--s = '0'; + s_len++; + } + break; + + + case 'x': + case 'X': + if (var_type == IS_QUAD) { + ui_quad = va_arg(ap, u_widest_int); + s = conv_p2_quad(ui_quad, 4, *fmt, + &num_buf[NUM_BUF_SIZE], &s_len); + } + else { + if (var_type == IS_LONG) + ui_num = (u_wide_int) va_arg(ap, u_wide_int); + else if (var_type == IS_SHORT) + ui_num = (u_wide_int) (unsigned short) va_arg(ap, unsigned int); + else + ui_num = (u_wide_int) va_arg(ap, unsigned int); + s = conv_p2(ui_num, 4, *fmt, + &num_buf[NUM_BUF_SIZE], &s_len); + } + FIX_PRECISION(adjust_precision, precision, s, s_len); + if (alternate_form && i_num != 0) { + *--s = *fmt; /* 'x' or 'X' */ + *--s = '0'; + s_len += 2; + } + break; + + + case 's': + s = va_arg(ap, char *); + if (s != NULL) { + if (!adjust_precision) { + s_len = strlen(s); + } + else { + /* From the C library standard in section 7.9.6.1: + * ...if the precision is specified, no more then + * that many characters are written. If the + * precision is not specified or is greater + * than the size of the array, the array shall + * contain a null character. + * + * My reading is is precision is specified and + * is less then or equal to the size of the + * array, no null character is required. So + * we can't do a strlen. + * + * This figures out the length of the string + * up to the precision. Once it's long enough + * for the specified precision, we don't care + * anymore. + * + * NOTE: you must do the length comparison + * before the check for the null character. + * Otherwise, you'll check one beyond the + * last valid character. + */ + const char *walk; + + for (walk = s, s_len = 0; + (s_len < precision) && (*walk != '\0'); + ++walk, ++s_len); + } + } + else { + s = S_NULL; + s_len = S_NULL_LEN; + } + pad_char = ' '; + break; + + + case 'f': + case 'e': + case 'E': + fp_num = va_arg(ap, double); + /* + * We use &num_buf[ 1 ], so that we have room for the sign + */ + s = NULL; +#ifdef HAVE_ISNAN + if (isnan(fp_num)) { + s = "nan"; + s_len = 3; + } +#endif +#ifdef HAVE_ISINF + if (!s && isinf(fp_num)) { + s = "inf"; + s_len = 3; + } +#endif + if (!s) { + s = conv_fp(*fmt, fp_num, alternate_form, + (adjust_precision == NO) ? FLOAT_DIGITS : precision, + &is_negative, &num_buf[1], &s_len); + if (is_negative) + prefix_char = '-'; + else if (print_sign) + prefix_char = '+'; + else if (print_blank) + prefix_char = ' '; + } + break; + + + case 'g': + case 'G': + if (adjust_precision == NO) + precision = FLOAT_DIGITS; + else if (precision == 0) + precision = 1; + /* + * * We use &num_buf[ 1 ], so that we have room for the sign + */ + s = apr_gcvt(va_arg(ap, double), precision, &num_buf[1], + alternate_form); + if (*s == '-') + prefix_char = *s++; + else if (print_sign) + prefix_char = '+'; + else if (print_blank) + prefix_char = ' '; + + s_len = strlen(s); + + if (alternate_form && (q = strchr(s, '.')) == NULL) { + s[s_len++] = '.'; + s[s_len] = '\0'; /* delimit for following strchr() */ + } + if (*fmt == 'G' && (q = strchr(s, 'e')) != NULL) + *q = 'E'; + break; + + + case 'c': + char_buf[0] = (char) (va_arg(ap, int)); + s = &char_buf[0]; + s_len = 1; + pad_char = ' '; + break; + + + case '%': + char_buf[0] = '%'; + s = &char_buf[0]; + s_len = 1; + pad_char = ' '; + break; + + + case 'n': + if (var_type == IS_QUAD) + *(va_arg(ap, widest_int *)) = cc; + else if (var_type == IS_LONG) + *(va_arg(ap, long *)) = cc; + else if (var_type == IS_SHORT) + *(va_arg(ap, short *)) = cc; + else + *(va_arg(ap, int *)) = cc; + print_something = NO; + break; + + /* + * This is where we extend the printf format, with a second + * type specifier + */ + case 'p': + switch(*++fmt) { + /* + * If the pointer size is equal to or smaller than the size + * of the largest unsigned int, we convert the pointer to a + * hex number, otherwise we print "%p" to indicate that we + * don't handle "%p". + */ + case 'p': +#ifdef APR_VOID_P_IS_QUAD + if (sizeof(void *) <= sizeof(u_widest_int)) { + ui_quad = (u_widest_int) va_arg(ap, void *); + s = conv_p2_quad(ui_quad, 4, 'x', + &num_buf[NUM_BUF_SIZE], &s_len); + } +#else + if (sizeof(void *) <= sizeof(u_wide_int)) { + ui_num = (u_wide_int) va_arg(ap, void *); + s = conv_p2(ui_num, 4, 'x', + &num_buf[NUM_BUF_SIZE], &s_len); + } +#endif + else { + s = "%p"; + s_len = 2; + prefix_char = NUL; + } + pad_char = ' '; + break; + + /* print an apr_sockaddr_t as a.b.c.d:port */ + case 'I': + { + apr_sockaddr_t *sa; + + sa = va_arg(ap, apr_sockaddr_t *); + if (sa != NULL) { + s = conv_apr_sockaddr(sa, &num_buf[NUM_BUF_SIZE], &s_len); + if (adjust_precision && precision < s_len) + s_len = precision; + } + else { + s = S_NULL; + s_len = S_NULL_LEN; + } + pad_char = ' '; + } + break; + + /* print a struct in_addr as a.b.c.d */ + case 'A': + { + struct in_addr *ia; + + ia = va_arg(ap, struct in_addr *); + if (ia != NULL) { + s = conv_in_addr(ia, &num_buf[NUM_BUF_SIZE], &s_len); + if (adjust_precision && precision < s_len) + s_len = precision; + } + else { + s = S_NULL; + s_len = S_NULL_LEN; + } + pad_char = ' '; + } + break; + + case 'T': +#if APR_HAS_THREADS + { + apr_os_thread_t *tid; + + tid = va_arg(ap, apr_os_thread_t *); + if (tid != NULL) { + s = conv_os_thread_t(tid, &num_buf[NUM_BUF_SIZE], &s_len); + if (adjust_precision && precision < s_len) + s_len = precision; + } + else { + s = S_NULL; + s_len = S_NULL_LEN; + } + pad_char = ' '; + } +#else + char_buf[0] = '0'; + s = &char_buf[0]; + s_len = 1; + pad_char = ' '; +#endif + break; + + case NUL: + /* if %p ends the string, oh well ignore it */ + continue; + + default: + s = "bogus %p"; + s_len = 8; + prefix_char = NUL; + (void)va_arg(ap, void *); /* skip the bogus argument on the stack */ + break; + } + break; + + case NUL: + /* + * The last character of the format string was %. + * We ignore it. + */ + continue; + + + /* + * The default case is for unrecognized %'s. + * We print % to help the user identify what + * option is not understood. + * This is also useful in case the user wants to pass + * the output of format_converter to another function + * that understands some other % (like syslog). + * Note that we can't point s inside fmt because the + * unknown could be preceded by width etc. + */ + default: + char_buf[0] = '%'; + char_buf[1] = *fmt; + s = char_buf; + s_len = 2; + pad_char = ' '; + break; + } + + if (prefix_char != NUL && s != S_NULL && s != char_buf) { + *--s = prefix_char; + s_len++; + } + + if (adjust_width && adjust == RIGHT && min_width > s_len) { + if (pad_char == '0' && prefix_char != NUL) { + INS_CHAR(*s, sp, bep, cc); + s++; + s_len--; + min_width--; + } + PAD(min_width, s_len, pad_char); + } + + /* + * Print the string s. + */ + if (print_something == YES) { + for (i = s_len; i != 0; i--) { + INS_CHAR(*s, sp, bep, cc); + s++; + } + } + + if (adjust_width && adjust == LEFT && min_width > s_len) + PAD(min_width, s_len, pad_char); + } + fmt++; + } + vbuff->curpos = sp; + + return cc; +} + + +static int snprintf_flush(apr_vformatter_buff_t *vbuff) +{ + /* if the buffer fills we have to abort immediately, there is no way + * to "flush" an apr_snprintf... there's nowhere to flush it to. + */ + return -1; +} + + +APR_DECLARE_NONSTD(int) apr_snprintf(char *buf, apr_size_t len, + const char *format, ...) +{ + int cc; + va_list ap; + apr_vformatter_buff_t vbuff; + + if (len == 0) { + /* NOTE: This is a special case; we just want to return the number + * of chars that would be written (minus \0) if the buffer + * size was infinite. We leverage the fact that INS_CHAR + * just does actual inserts iff the buffer pointer is non-NULL. + * In this case, we don't care what buf is; it can be NULL, since + * we don't touch it at all. + */ + vbuff.curpos = NULL; + vbuff.endpos = NULL; + } else { + /* save one byte for nul terminator */ + vbuff.curpos = buf; + vbuff.endpos = buf + len - 1; + } + va_start(ap, format); + cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); + va_end(ap); + if (len != 0) { + *vbuff.curpos = '\0'; + } + return (cc == -1) ? (int)len : cc; +} + + +APR_DECLARE(int) apr_vsnprintf(char *buf, apr_size_t len, const char *format, + va_list ap) +{ + int cc; + apr_vformatter_buff_t vbuff; + + if (len == 0) { + /* See above note */ + vbuff.curpos = NULL; + vbuff.endpos = NULL; + } else { + /* save one byte for nul terminator */ + vbuff.curpos = buf; + vbuff.endpos = buf + len - 1; + } + cc = apr_vformatter(snprintf_flush, &vbuff, format, ap); + if (len != 0) { + *vbuff.curpos = '\0'; + } + return (cc == -1) ? (int)len : cc; +} diff --git a/srclib/apr/strings/apr_strings.c b/srclib/apr/strings/apr_strings.c new file mode 100644 index 0000000000..973c3209c5 --- /dev/null +++ b/srclib/apr/strings/apr_strings.c @@ -0,0 +1,466 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "apr.h" +#include "apr_strings.h" +#include "apr_general.h" +#include "apr_private.h" +#include "apr_lib.h" +#define APR_WANT_STDIO +#define APR_WANT_STRFUNC +#include "apr_want.h" + +#ifdef HAVE_STDDEF_H +#include /* NULL */ +#endif + +#ifdef HAVE_STDLIB_H +#include /* strtol and strtoll */ +#endif + +/** this is used to cache lengths in apr_pstrcat */ +#define MAX_SAVED_LENGTHS 6 + +APR_DECLARE(char *) apr_pstrdup(apr_pool_t *a, const char *s) +{ + char *res; + apr_size_t len; + + if (s == NULL) { + return NULL; + } + len = strlen(s) + 1; + res = apr_palloc(a, len); + memcpy(res, s, len); + return res; +} + +APR_DECLARE(char *) apr_pstrndup(apr_pool_t *a, const char *s, apr_size_t n) +{ + char *res; + const char *end; + + if (s == NULL) { + return NULL; + } + end = memchr(s, '\0', n); + if (end != NULL) + n = end - s; + res = apr_palloc(a, n + 1); + memcpy(res, s, n); + res[n] = '\0'; + return res; +} + +APR_DECLARE(char *) apr_pstrmemdup(apr_pool_t *a, const char *s, apr_size_t n) +{ + char *res; + + if (s == NULL) { + return NULL; + } + res = apr_palloc(a, n + 1); + memcpy(res, s, n); + res[n] = '\0'; + return res; +} + +APR_DECLARE(void *) apr_pmemdup(apr_pool_t *a, const void *m, apr_size_t n) +{ + void *res; + + if (m == NULL) + return NULL; + res = apr_palloc(a, n); + memcpy(res, m, n); + return res; +} + +APR_DECLARE_NONSTD(char *) apr_pstrcat(apr_pool_t *a, ...) +{ + char *cp, *argp, *res; + apr_size_t saved_lengths[MAX_SAVED_LENGTHS]; + int nargs = 0; + + /* Pass one --- find length of required string */ + + apr_size_t len = 0; + va_list adummy; + + va_start(adummy, a); + + while ((cp = va_arg(adummy, char *)) != NULL) { + apr_size_t cplen = strlen(cp); + if (nargs < MAX_SAVED_LENGTHS) { + saved_lengths[nargs++] = cplen; + } + len += cplen; + } + + va_end(adummy); + + /* Allocate the required string */ + + res = (char *) apr_palloc(a, len + 1); + cp = res; + + /* Pass two --- copy the argument strings into the result space */ + + va_start(adummy, a); + + nargs = 0; + while ((argp = va_arg(adummy, char *)) != NULL) { + if (nargs < MAX_SAVED_LENGTHS) { + len = saved_lengths[nargs++]; + } + else { + len = strlen(argp); + } + + memcpy(cp, argp, len); + cp += len; + } + + va_end(adummy); + + /* Return the result string */ + + *cp = '\0'; + + return res; +} + +APR_DECLARE(char *) apr_pstrcatv(apr_pool_t *a, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes) +{ + apr_size_t i; + apr_size_t len; + const struct iovec *src; + char *res; + char *dst; + + /* Pass one --- find length of required string */ + len = 0; + src = vec; + for (i = nvec; i; i--) { + len += src->iov_len; + src++; + } + if (nbytes) { + *nbytes = len; + } + + /* Allocate the required string */ + res = (char *) apr_palloc(a, len + 1); + + /* Pass two --- copy the argument strings into the result space */ + src = vec; + dst = res; + for (i = nvec; i; i--) { + memcpy(dst, src->iov_base, src->iov_len); + dst += src->iov_len; + src++; + } + + /* Return the result string */ + *dst = '\0'; + + return res; +} + +#if (!APR_HAVE_MEMCHR) +void *memchr(const void *s, int c, size_t n) +{ + const char *cp; + + for (cp = s; n > 0; n--, cp++) { + if (*cp == c) + return (char *) cp; /* Casting away the const here */ + } + + return NULL; +} +#endif + +#ifndef INT64_MAX +#define INT64_MAX APR_INT64_C(0x7fffffffffffffff) +#endif +#ifndef INT64_MIN +#define INT64_MIN (-APR_INT64_C(0x7fffffffffffffff) - APR_INT64_C(1)) +#endif + +APR_DECLARE(apr_status_t) apr_strtoff(apr_off_t *offset, const char *nptr, + char **endptr, int base) +{ + errno = 0; + *offset = APR_OFF_T_STRFN(nptr, endptr, base); + return APR_FROM_OS_ERROR(errno); +} + +APR_DECLARE(apr_int64_t) apr_strtoi64(const char *nptr, char **endptr, int base) +{ +#ifdef APR_INT64_STRFN + return APR_INT64_STRFN(nptr, endptr, base); +#else + const char *s; + apr_int64_t acc; + apr_int64_t val; + int neg, any; + char c; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (apr_isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + if (base < 2 || base > 36) { + errno = EINVAL; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return acc; + } + + /* The classic bsd implementation requires div/mod operators + * to compute a cutoff. Benchmarking proves that is very, very + * evil to some 32 bit processors. Instead, look for underflow + * in both the mult and add/sub operation. Unlike the bsd impl, + * we also work strictly in a signed int64 word as we haven't + * implemented the unsigned type in win32. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + val = 0; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; +#if (('Z' - 'A') == 25) + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; +#elif APR_CHARSET_EBCDIC + else if (c >= 'A' && c <= 'I') + c -= 'A' - 10; + else if (c >= 'J' && c <= 'R') + c -= 'J' - 19; + else if (c >= 'S' && c <= 'Z') + c -= 'S' - 28; + else if (c >= 'a' && c <= 'i') + c -= 'a' - 10; + else if (c >= 'j' && c <= 'r') + c -= 'j' - 19; + else if (c >= 's' && c <= 'z') + c -= 'z' - 28; +#else +#error "CANNOT COMPILE apr_strtoi64(), only ASCII and EBCDIC supported" +#endif + else + break; + if (c >= base) + break; + val *= base; + if ( (any < 0) /* already noted an over/under flow - short circuit */ + || (neg && (val > acc || (val -= c) > acc)) /* underflow */ + || (!neg && (val < acc || (val += c) < acc))) { /* overflow */ + any = -1; /* once noted, over/underflows never go away */ +#ifdef APR_STRTOI64_OVERFLOW_IS_BAD_CHAR + break; +#endif + } else { + acc = val; + any = 1; + } + } + + if (any < 0) { + acc = neg ? INT64_MIN : INT64_MAX; + errno = ERANGE; + } else if (!any) { + errno = EINVAL; + } + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +#endif +} + +APR_DECLARE(apr_int64_t) apr_atoi64(const char *buf) +{ + return apr_strtoi64(buf, NULL, 10); +} + +APR_DECLARE(char *) apr_itoa(apr_pool_t *p, int n) +{ + const int BUFFER_SIZE = sizeof(int) * 3 + 2; + char *buf = apr_palloc(p, BUFFER_SIZE); + char *start = buf + BUFFER_SIZE - 1; + int negative; + if (n < 0) { + negative = 1; + n = -n; + } + else { + negative = 0; + } + *start = 0; + do { + *--start = '0' + (n % 10); + n /= 10; + } while (n); + if (negative) { + *--start = '-'; + } + return start; +} + +APR_DECLARE(char *) apr_ltoa(apr_pool_t *p, long n) +{ + const int BUFFER_SIZE = sizeof(long) * 3 + 2; + char *buf = apr_palloc(p, BUFFER_SIZE); + char *start = buf + BUFFER_SIZE - 1; + int negative; + if (n < 0) { + negative = 1; + n = -n; + } + else { + negative = 0; + } + *start = 0; + do { + *--start = (char)('0' + (n % 10)); + n /= 10; + } while (n); + if (negative) { + *--start = '-'; + } + return start; +} + +APR_DECLARE(char *) apr_off_t_toa(apr_pool_t *p, apr_off_t n) +{ + const int BUFFER_SIZE = sizeof(apr_off_t) * 3 + 2; + char *buf = apr_palloc(p, BUFFER_SIZE); + char *start = buf + BUFFER_SIZE - 1; + int negative; + if (n < 0) { + negative = 1; + n = -n; + } + else { + negative = 0; + } + *start = 0; + do { + *--start = '0' + (char)(n % 10); + n /= 10; + } while (n); + if (negative) { + *--start = '-'; + } + return start; +} + +APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf) +{ + const char ord[] = "KMGTPE"; + const char *o = ord; + int remain; + + if (size < 0) { + return strcpy(buf, " - "); + } + if (size < 973) { + if (apr_snprintf(buf, 5, "%3d ", (int) size) < 0) + return strcpy(buf, "****"); + return buf; + } + do { + remain = (int)(size & 1023); + size >>= 10; + if (size >= 973) { + ++o; + continue; + } + if (size < 9 || (size == 9 && remain < 973)) { + if ((remain = ((remain * 5) + 256) / 512) >= 10) + ++size, remain = 0; + if (apr_snprintf(buf, 5, "%d.%d%c", (int) size, remain, *o) < 0) + return strcpy(buf, "****"); + return buf; + } + if (remain >= 512) + ++size; + if (apr_snprintf(buf, 5, "%3d%c", (int) size, *o) < 0) + return strcpy(buf, "****"); + return buf; + } while (1); +} + diff --git a/srclib/apr/strings/apr_strnatcmp.c b/srclib/apr/strings/apr_strnatcmp.c new file mode 100644 index 0000000000..73ce516d9f --- /dev/null +++ b/srclib/apr/strings/apr_strnatcmp.c @@ -0,0 +1,149 @@ +/* -*- mode: c; c-file-style: "k&r" -*- + + strnatcmp.c -- Perform 'natural order' comparisons of strings in C. + Copyright (C) 2000 by Martin Pool + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#include +#include +#include "apr_strings.h" +#include "apr_lib.h" /* for apr_is*() */ + +#if defined(__GNUC__) +# define UNUSED __attribute__((__unused__)) +#else +# define UNUSED +#endif + +/* based on "strnatcmp.c,v 1.6 2000/04/20 07:30:11 mbp Exp $" */ + +static int +compare_right(char const *a, char const *b) +{ + int bias = 0; + + /* The longest run of digits wins. That aside, the greatest + value wins, but we can't know that it will until we've scanned + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ + for (;; a++, b++) { + if (!apr_isdigit(*a) && !apr_isdigit(*b)) + return bias; + else if (!apr_isdigit(*a)) + return -1; + else if (!apr_isdigit(*b)) + return +1; + else if (*a < *b) { + if (!bias) + bias = -1; + } else if (*a > *b) { + if (!bias) + bias = +1; + } else if (!*a && !*b) + return bias; + } + + return 0; +} + + +static int +compare_left(char const *a, char const *b) +{ + /* Compare two left-aligned numbers: the first to have a + different value wins. */ + for (;; a++, b++) { + if (!apr_isdigit(*a) && !apr_isdigit(*b)) + return 0; + else if (!apr_isdigit(*a)) + return -1; + else if (!apr_isdigit(*b)) + return +1; + else if (*a < *b) + return -1; + else if (*a > *b) + return +1; + } + + return 0; +} + + +static int strnatcmp0(char const *a, char const *b, int fold_case) +{ + int ai, bi; + char ca, cb; + int fractional, result; + ai = bi = 0; + while (1) { + ca = a[ai]; cb = b[bi]; + + /* skip over leading spaces or zeros */ + while (apr_isspace(ca)) + ca = a[++ai]; + + while (apr_isspace(cb)) + cb = b[++bi]; + + /* process run of digits */ + if (apr_isdigit(ca) && apr_isdigit(cb)) { + fractional = (ca == '0' || cb == '0'); + + if (fractional) { + if ((result = compare_left(a+ai, b+bi)) != 0) + return result; + } else { + if ((result = compare_right(a+ai, b+bi)) != 0) + return result; + } + } + + if (!ca && !cb) { + /* The strings compare the same. Perhaps the caller + will want to call strcmp to break the tie. */ + return 0; + } + + if (fold_case) { + ca = apr_toupper(ca); + cb = apr_toupper(cb); + } + + if (ca < cb) + return -1; + else if (ca > cb) + return +1; + + ++ai; ++bi; + } +} + + + +APR_DECLARE(int) apr_strnatcmp(char const *a, char const *b) +{ + return strnatcmp0(a, b, 0); +} + + +/* Compare, recognizing numeric string and ignoring case. */ +APR_DECLARE(int) apr_strnatcasecmp(char const *a, char const *b) +{ + return strnatcmp0(a, b, 1); +} diff --git a/srclib/apr/strings/apr_strtok.c b/srclib/apr/strings/apr_strtok.c new file mode 100644 index 0000000000..b032633462 --- /dev/null +++ b/srclib/apr/strings/apr_strtok.c @@ -0,0 +1,56 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef HAVE_STDDEF_H +#include /* for NULL */ +#endif + +#include "apr.h" +#include "apr_strings.h" + +#define APR_WANT_STRFUNC /* for strchr() */ +#include "apr_want.h" + +APR_DECLARE(char *) apr_strtok(char *str, const char *sep, char **last) +{ + char *token; + + if (!str) /* subsequent call */ + str = *last; /* start where we left off */ + + /* skip characters in sep (will terminate at '\0') */ + while (*str && strchr(sep, *str)) + ++str; + + if (!*str) /* no more tokens */ + return NULL; + + token = str; + + /* skip valid token characters to terminate token and + * prepare for the next call (will terminate at '\0) + */ + *last = token + 1; + while (**last && !strchr(sep, **last)) + ++*last; + + if (**last) { + **last = '\0'; + ++*last; + } + + return token; +} diff --git a/srclib/apr/support/unix/waitio.c b/srclib/apr/support/unix/waitio.c new file mode 100644 index 0000000000..81fea536b5 --- /dev/null +++ b/srclib/apr/support/unix/waitio.c @@ -0,0 +1,116 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_arch_networkio.h" +#include "apr_poll.h" +#include "apr_errno.h" +#include "apr_support.h" + +/* The only case where we don't use wait_for_io_or_timeout is on + * pre-BONE BeOS, so this check should be sufficient and simpler */ +#if !BEOS_R5 +#define USE_WAIT_FOR_IO +#endif + +#ifdef USE_WAIT_FOR_IO + +#ifdef WAITIO_USES_POLL + +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_SYS_POLL_H +#include +#endif + +apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, + int for_read) +{ + struct pollfd pfd; + int rc, timeout; + + timeout = f ? f->timeout / 1000 : s->timeout / 1000; + pfd.fd = f ? f->filedes : s->socketdes; + pfd.events = for_read ? POLLIN : POLLOUT; + + do { + rc = poll(&pfd, 1, timeout); + } while (rc == -1 && errno == EINTR); + if (rc == 0) { + return APR_TIMEUP; + } + else if (rc > 0) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +#else + +apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, + int for_read) +{ + apr_interval_time_t timeout; + apr_pollfd_t pfd; + int type = for_read ? APR_POLLIN : APR_POLLOUT; + apr_pollset_t *pollset; + apr_status_t status; + + /* TODO - timeout should be less each time through this loop */ + if (f) { + pfd.desc_type = APR_POLL_FILE; + pfd.desc.f = f; + + pollset = f->pollset; + timeout = f->timeout; + } + else { + pfd.desc_type = APR_POLL_SOCKET; + pfd.desc.s = s; + + pollset = s->pollset; + timeout = s->timeout; + } + pfd.reqevents = type; + + /* Remove the object if it was in the pollset, then add in the new + * object with the correct reqevents value. Ignore the status result + * on the remove, because it might not be in there (yet). + */ + (void) apr_pollset_remove(pollset, &pfd); + + /* ### check status code */ + (void) apr_pollset_add(pollset, &pfd); + + do { + int numdesc; + const apr_pollfd_t *pdesc; + + status = apr_pollset_poll(pollset, timeout, &numdesc, &pdesc); + + if (numdesc == 1 && (pdesc[0].rtnevents & type) != 0) { + return APR_SUCCESS; + } + } while (APR_STATUS_IS_EINTR(status)); + + return status; +} +#endif /* WAITIO_USES_POLL */ + +#endif /* USE_WAIT_FOR_IO */ diff --git a/srclib/apr/tables/apr_hash.c b/srclib/apr/tables/apr_hash.c new file mode 100644 index 0000000000..574d4161a9 --- /dev/null +++ b/srclib/apr/tables/apr_hash.c @@ -0,0 +1,469 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" + +#include "apr_general.h" +#include "apr_pools.h" + +#include "apr_hash.h" + +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif + +#if APR_POOL_DEBUG && APR_HAVE_STDIO_H +#include +#endif + +/* + * The internal form of a hash table. + * + * The table is an array indexed by the hash of the key; collisions + * are resolved by hanging a linked list of hash entries off each + * element of the array. Although this is a really simple design it + * isn't too bad given that pools have a low allocation overhead. + */ + +typedef struct apr_hash_entry_t apr_hash_entry_t; + +struct apr_hash_entry_t { + apr_hash_entry_t *next; + unsigned int hash; + const void *key; + apr_ssize_t klen; + const void *val; +}; + +/* + * Data structure for iterating through a hash table. + * + * We keep a pointer to the next hash entry here to allow the current + * hash entry to be freed or otherwise mangled between calls to + * apr_hash_next(). + */ +struct apr_hash_index_t { + apr_hash_t *ht; + apr_hash_entry_t *this, *next; + unsigned int index; +}; + +/* + * The size of the array is always a power of two. We use the maximum + * index rather than the size so that we can use bitwise-AND for + * modular arithmetic. + * The count of hash entries may be greater depending on the chosen + * collision rate. + */ +struct apr_hash_t { + apr_pool_t *pool; + apr_hash_entry_t **array; + apr_hash_index_t iterator; /* For apr_hash_first(NULL, ...) */ + unsigned int count, max; + apr_hashfunc_t hash_func; + apr_hash_entry_t *free; /* List of recycled entries */ +}; + +#define INITIAL_MAX 15 /* tunable == 2^n - 1 */ + + +/* + * Hash creation functions. + */ + +static apr_hash_entry_t **alloc_array(apr_hash_t *ht, unsigned int max) +{ + return apr_pcalloc(ht->pool, sizeof(*ht->array) * (max + 1)); +} + +APR_DECLARE(apr_hash_t *) apr_hash_make(apr_pool_t *pool) +{ + apr_hash_t *ht; + ht = apr_palloc(pool, sizeof(apr_hash_t)); + ht->pool = pool; + ht->free = NULL; + ht->count = 0; + ht->max = INITIAL_MAX; + ht->array = alloc_array(ht, ht->max); + ht->hash_func = apr_hashfunc_default; + return ht; +} + +APR_DECLARE(apr_hash_t *) apr_hash_make_custom(apr_pool_t *pool, + apr_hashfunc_t hash_func) +{ + apr_hash_t *ht = apr_hash_make(pool); + ht->hash_func = hash_func; + return ht; +} + + +/* + * Hash iteration functions. + */ + +APR_DECLARE(apr_hash_index_t *) apr_hash_next(apr_hash_index_t *hi) +{ + hi->this = hi->next; + while (!hi->this) { + if (hi->index > hi->ht->max) + return NULL; + + hi->this = hi->ht->array[hi->index++]; + } + hi->next = hi->this->next; + return hi; +} + +APR_DECLARE(apr_hash_index_t *) apr_hash_first(apr_pool_t *p, apr_hash_t *ht) +{ + apr_hash_index_t *hi; + if (p) + hi = apr_palloc(p, sizeof(*hi)); + else + hi = &ht->iterator; + + hi->ht = ht; + hi->index = 0; + hi->this = NULL; + hi->next = NULL; + return apr_hash_next(hi); +} + +APR_DECLARE(void) apr_hash_this(apr_hash_index_t *hi, + const void **key, + apr_ssize_t *klen, + void **val) +{ + if (key) *key = hi->this->key; + if (klen) *klen = hi->this->klen; + if (val) *val = (void *)hi->this->val; +} + + +/* + * Expanding a hash table + */ + +static void expand_array(apr_hash_t *ht) +{ + apr_hash_index_t *hi; + apr_hash_entry_t **new_array; + unsigned int new_max; + + new_max = ht->max * 2 + 1; + new_array = alloc_array(ht, new_max); + for (hi = apr_hash_first(NULL, ht); hi; hi = apr_hash_next(hi)) { + unsigned int i = hi->this->hash & new_max; + hi->this->next = new_array[i]; + new_array[i] = hi->this; + } + ht->array = new_array; + ht->max = new_max; +} + +unsigned int apr_hashfunc_default(const char *char_key, apr_ssize_t *klen) +{ + unsigned int hash = 0; + const unsigned char *key = (const unsigned char *)char_key; + const unsigned char *p; + apr_ssize_t i; + + /* + * This is the popular `times 33' hash algorithm which is used by + * perl and also appears in Berkeley DB. This is one of the best + * known hash functions for strings because it is both computed + * very fast and distributes very well. + * + * The originator may be Dan Bernstein but the code in Berkeley DB + * cites Chris Torek as the source. The best citation I have found + * is "Chris Torek, Hash function for text in C, Usenet message + * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich + * Salz's USENIX 1992 paper about INN which can be found at + * . + * + * The magic of number 33, i.e. why it works better than many other + * constants, prime or not, has never been adequately explained by + * anyone. So I try an explanation: if one experimentally tests all + * multipliers between 1 and 256 (as I did while writing a low-level + * data structure library some time ago) one detects that even + * numbers are not useable at all. The remaining 128 odd numbers + * (except for the number 1) work more or less all equally well. + * They all distribute in an acceptable way and this way fill a hash + * table with an average percent of approx. 86%. + * + * If one compares the chi^2 values of the variants (see + * Bob Jenkins ``Hashing Frequently Asked Questions'' at + * http://burtleburtle.net/bob/hash/hashfaq.html for a description + * of chi^2), the number 33 not even has the best value. But the + * number 33 and a few other equally good numbers like 17, 31, 63, + * 127 and 129 have nevertheless a great advantage to the remaining + * numbers in the large set of possible multipliers: their multiply + * operation can be replaced by a faster operation based on just one + * shift plus either a single addition or subtraction operation. And + * because a hash function has to both distribute good _and_ has to + * be very fast to compute, those few numbers should be preferred. + * + * -- Ralf S. Engelschall + */ + + if (*klen == APR_HASH_KEY_STRING) { + for (p = key; *p; p++) { + hash = hash * 33 + *p; + } + *klen = p - key; + } + else { + for (p = key, i = *klen; i; i--, p++) { + hash = hash * 33 + *p; + } + } + + return hash; +} + + +/* + * This is where we keep the details of the hash function and control + * the maximum collision rate. + * + * If val is non-NULL it creates and initializes a new hash entry if + * there isn't already one there; it returns an updatable pointer so + * that hash entries can be removed. + */ + +static apr_hash_entry_t **find_entry(apr_hash_t *ht, + const void *key, + apr_ssize_t klen, + const void *val) +{ + apr_hash_entry_t **hep, *he; + unsigned int hash; + + hash = ht->hash_func(key, &klen); + + /* scan linked list */ + for (hep = &ht->array[hash & ht->max], he = *hep; + he; hep = &he->next, he = *hep) { + if (he->hash == hash + && he->klen == klen + && memcmp(he->key, key, klen) == 0) + break; + } + if (he || !val) + return hep; + + /* add a new entry for non-NULL values */ + if ((he = ht->free) != NULL) + ht->free = he->next; + else + he = apr_palloc(ht->pool, sizeof(*he)); + he->next = NULL; + he->hash = hash; + he->key = key; + he->klen = klen; + he->val = val; + *hep = he; + ht->count++; + return hep; +} + +APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool, + const apr_hash_t *orig) +{ + apr_hash_t *ht; + apr_hash_entry_t *new_vals; + unsigned int i, j; + + ht = apr_palloc(pool, sizeof(apr_hash_t) + + sizeof(*ht->array) * (orig->max + 1) + + sizeof(apr_hash_entry_t) * orig->count); + ht->pool = pool; + ht->free = NULL; + ht->count = orig->count; + ht->max = orig->max; + ht->hash_func = orig->hash_func; + ht->array = (apr_hash_entry_t **)((char *)ht + sizeof(apr_hash_t)); + + new_vals = (apr_hash_entry_t *)((char *)(ht) + sizeof(apr_hash_t) + + sizeof(*ht->array) * (orig->max + 1)); + j = 0; + for (i = 0; i <= ht->max; i++) { + apr_hash_entry_t **new_entry = &(ht->array[i]); + apr_hash_entry_t *orig_entry = orig->array[i]; + while (orig_entry) { + *new_entry = &new_vals[j++]; + (*new_entry)->hash = orig_entry->hash; + (*new_entry)->key = orig_entry->key; + (*new_entry)->klen = orig_entry->klen; + (*new_entry)->val = orig_entry->val; + new_entry = &((*new_entry)->next); + orig_entry = orig_entry->next; + } + *new_entry = NULL; + } + return ht; +} + +APR_DECLARE(void *) apr_hash_get(apr_hash_t *ht, + const void *key, + apr_ssize_t klen) +{ + apr_hash_entry_t *he; + he = *find_entry(ht, key, klen, NULL); + if (he) + return (void *)he->val; + else + return NULL; +} + +APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, + const void *key, + apr_ssize_t klen, + const void *val) +{ + apr_hash_entry_t **hep; + hep = find_entry(ht, key, klen, val); + if (*hep) { + if (!val) { + /* delete entry */ + apr_hash_entry_t *old = *hep; + *hep = (*hep)->next; + old->next = ht->free; + ht->free = old; + --ht->count; + } + else { + /* replace entry */ + (*hep)->val = val; + /* check that the collision rate isn't too high */ + if (ht->count > ht->max) { + expand_array(ht); + } + } + } + /* else key not present and val==NULL */ +} + +APR_DECLARE(unsigned int) apr_hash_count(apr_hash_t *ht) +{ + return ht->count; +} + +APR_DECLARE(apr_hash_t*) apr_hash_overlay(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base) +{ + return apr_hash_merge(p, overlay, base, NULL, NULL); +} + +APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, + const apr_hash_t *overlay, + const apr_hash_t *base, + void * (*merger)(apr_pool_t *p, + const void *key, + apr_ssize_t klen, + const void *h1_val, + const void *h2_val, + const void *data), + const void *data) +{ + apr_hash_t *res; + apr_hash_entry_t *new_vals = NULL; + apr_hash_entry_t *iter; + apr_hash_entry_t *ent; + unsigned int i,j,k; + +#if APR_POOL_DEBUG + /* we don't copy keys and values, so it's necessary that + * overlay->a.pool and base->a.pool have a life span at least + * as long as p + */ + if (!apr_pool_is_ancestor(overlay->pool, p)) { + fprintf(stderr, + "apr_hash_merge: overlay's pool is not an ancestor of p\n"); + abort(); + } + if (!apr_pool_is_ancestor(base->pool, p)) { + fprintf(stderr, + "apr_hash_merge: base's pool is not an ancestor of p\n"); + abort(); + } +#endif + + res = apr_palloc(p, sizeof(apr_hash_t)); + res->pool = p; + res->free = NULL; + res->hash_func = base->hash_func; + res->count = base->count; + res->max = (overlay->max > base->max) ? overlay->max : base->max; + if (base->count + overlay->count > res->max) { + res->max = res->max * 2 + 1; + } + res->array = alloc_array(res, res->max); + if (base->count + overlay->count) { + new_vals = apr_palloc(p, sizeof(apr_hash_entry_t) * + (base->count + overlay->count)); + } + j = 0; + for (k = 0; k <= base->max; k++) { + for (iter = base->array[k]; iter; iter = iter->next) { + i = iter->hash & res->max; + new_vals[j].klen = iter->klen; + new_vals[j].key = iter->key; + new_vals[j].val = iter->val; + new_vals[j].hash = iter->hash; + new_vals[j].next = res->array[i]; + res->array[i] = &new_vals[j]; + j++; + } + } + + for (k = 0; k <= overlay->max; k++) { + for (iter = overlay->array[k]; iter; iter = iter->next) { + i = iter->hash & res->max; + for (ent = res->array[i]; ent; ent = ent->next) { + if ((ent->klen == iter->klen) && + (memcmp(ent->key, iter->key, iter->klen) == 0)) { + if (merger) { + ent->val = (*merger)(p, iter->key, iter->klen, + iter->val, ent->val, data); + } + else { + ent->val = iter->val; + } + break; + } + } + if (!ent) { + new_vals[j].klen = iter->klen; + new_vals[j].key = iter->key; + new_vals[j].val = iter->val; + new_vals[j].hash = iter->hash; + new_vals[j].next = res->array[i]; + res->array[i] = &new_vals[j]; + res->count++; + j++; + } + } + } + return res; +} + +APR_POOL_IMPLEMENT_ACCESSOR(hash) diff --git a/srclib/apr/tables/apr_tables.c b/srclib/apr/tables/apr_tables.c new file mode 100644 index 0000000000..c1128c65d4 --- /dev/null +++ b/srclib/apr/tables/apr_tables.c @@ -0,0 +1,1210 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Resource allocation code... the code here is responsible for making + * sure that nothing leaks. + * + * rst --- 4/95 --- 6/95 + */ + +#include "apr_private.h" + +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_tables.h" +#include "apr_strings.h" +#include "apr_lib.h" +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +#if APR_HAVE_STRINGS_H +#include +#endif + +#if APR_POOL_DEBUG && APR_HAVE_STDIO_H +#include +#endif + +/***************************************************************** + * This file contains array and apr_table_t functions only. + */ + +/***************************************************************** + * + * The 'array' functions... + */ + +static void make_array_core(apr_array_header_t *res, apr_pool_t *p, + int nelts, int elt_size, int clear) +{ + /* + * Assure sanity if someone asks for + * array of zero elts. + */ + if (nelts < 1) { + nelts = 1; + } + + if (clear) { + res->elts = apr_pcalloc(p, nelts * elt_size); + } + else { + res->elts = apr_palloc(p, nelts * elt_size); + } + + res->pool = p; + res->elt_size = elt_size; + res->nelts = 0; /* No active elements yet... */ + res->nalloc = nelts; /* ...but this many allocated */ +} + +APR_DECLARE(int) apr_is_empty_array(const apr_array_header_t *a) +{ + return ((a == NULL) || (a->nelts == 0)); +} + +APR_DECLARE(apr_array_header_t *) apr_array_make(apr_pool_t *p, + int nelts, int elt_size) +{ + apr_array_header_t *res; + + res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t)); + make_array_core(res, p, nelts, elt_size, 1); + return res; +} + +APR_DECLARE(void *) apr_array_pop(apr_array_header_t *arr) +{ + if (apr_is_empty_array(arr)) { + return NULL; + } + + return arr->elts + (arr->elt_size * (--arr->nelts)); +} + +APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr) +{ + if (arr->nelts == arr->nalloc) { + int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2; + char *new_data; + + new_data = apr_palloc(arr->pool, arr->elt_size * new_size); + + memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size); + memset(new_data + arr->nalloc * arr->elt_size, 0, + arr->elt_size * (new_size - arr->nalloc)); + arr->elts = new_data; + arr->nalloc = new_size; + } + + ++arr->nelts; + return arr->elts + (arr->elt_size * (arr->nelts - 1)); +} + +static void *apr_array_push_noclear(apr_array_header_t *arr) +{ + if (arr->nelts == arr->nalloc) { + int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2; + char *new_data; + + new_data = apr_palloc(arr->pool, arr->elt_size * new_size); + + memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size); + arr->elts = new_data; + arr->nalloc = new_size; + } + + ++arr->nelts; + return arr->elts + (arr->elt_size * (arr->nelts - 1)); +} + +APR_DECLARE(void) apr_array_cat(apr_array_header_t *dst, + const apr_array_header_t *src) +{ + int elt_size = dst->elt_size; + + if (dst->nelts + src->nelts > dst->nalloc) { + int new_size = (dst->nalloc <= 0) ? 1 : dst->nalloc * 2; + char *new_data; + + while (dst->nelts + src->nelts > new_size) { + new_size *= 2; + } + + new_data = apr_pcalloc(dst->pool, elt_size * new_size); + memcpy(new_data, dst->elts, dst->nalloc * elt_size); + + dst->elts = new_data; + dst->nalloc = new_size; + } + + memcpy(dst->elts + dst->nelts * elt_size, src->elts, + elt_size * src->nelts); + dst->nelts += src->nelts; +} + +APR_DECLARE(apr_array_header_t *) apr_array_copy(apr_pool_t *p, + const apr_array_header_t *arr) +{ + apr_array_header_t *res = + (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t)); + make_array_core(res, p, arr->nalloc, arr->elt_size, 0); + + memcpy(res->elts, arr->elts, arr->elt_size * arr->nelts); + res->nelts = arr->nelts; + memset(res->elts + res->elt_size * res->nelts, 0, + res->elt_size * (res->nalloc - res->nelts)); + return res; +} + +/* This cute function copies the array header *only*, but arranges + * for the data section to be copied on the first push or arraycat. + * It's useful when the elements of the array being copied are + * read only, but new stuff *might* get added on the end; we have the + * overhead of the full copy only where it is really needed. + */ + +static APR_INLINE void copy_array_hdr_core(apr_array_header_t *res, + const apr_array_header_t *arr) +{ + res->elts = arr->elts; + res->elt_size = arr->elt_size; + res->nelts = arr->nelts; + res->nalloc = arr->nelts; /* Force overflow on push */ +} + +APR_DECLARE(apr_array_header_t *) + apr_array_copy_hdr(apr_pool_t *p, + const apr_array_header_t *arr) +{ + apr_array_header_t *res; + + res = (apr_array_header_t *) apr_palloc(p, sizeof(apr_array_header_t)); + res->pool = p; + copy_array_hdr_core(res, arr); + return res; +} + +/* The above is used here to avoid consing multiple new array bodies... */ + +APR_DECLARE(apr_array_header_t *) + apr_array_append(apr_pool_t *p, + const apr_array_header_t *first, + const apr_array_header_t *second) +{ + apr_array_header_t *res = apr_array_copy_hdr(p, first); + + apr_array_cat(res, second); + return res; +} + +/* apr_array_pstrcat generates a new string from the apr_pool_t containing + * the concatenated sequence of substrings referenced as elements within + * the array. The string will be empty if all substrings are empty or null, + * or if there are no elements in the array. + * If sep is non-NUL, it will be inserted between elements as a separator. + */ +APR_DECLARE(char *) apr_array_pstrcat(apr_pool_t *p, + const apr_array_header_t *arr, + const char sep) +{ + char *cp, *res, **strpp; + apr_size_t len; + int i; + + if (arr->nelts <= 0 || arr->elts == NULL) { /* Empty table? */ + return (char *) apr_pcalloc(p, 1); + } + + /* Pass one --- find length of required string */ + + len = 0; + for (i = 0, strpp = (char **) arr->elts; ; ++strpp) { + if (strpp && *strpp != NULL) { + len += strlen(*strpp); + } + if (++i >= arr->nelts) { + break; + } + if (sep) { + ++len; + } + } + + /* Allocate the required string */ + + res = (char *) apr_palloc(p, len + 1); + cp = res; + + /* Pass two --- copy the argument strings into the result space */ + + for (i = 0, strpp = (char **) arr->elts; ; ++strpp) { + if (strpp && *strpp != NULL) { + len = strlen(*strpp); + memcpy(cp, *strpp, len); + cp += len; + } + if (++i >= arr->nelts) { + break; + } + if (sep) { + *cp++ = sep; + } + } + + *cp = '\0'; + + /* Return the result string */ + + return res; +} + + +/***************************************************************** + * + * The "table" functions. + */ + +#if APR_CHARSET_EBCDIC +#define CASE_MASK 0xbfbfbfbf +#else +#define CASE_MASK 0xdfdfdfdf +#endif + +#define TABLE_HASH_SIZE 32 +#define TABLE_INDEX_MASK 0x1f +#define TABLE_HASH(key) (TABLE_INDEX_MASK & *(unsigned char *)(key)) +#define TABLE_INDEX_IS_INITIALIZED(t, i) ((t)->index_initialized & (1 << (i))) +#define TABLE_SET_INDEX_INITIALIZED(t, i) ((t)->index_initialized |= (1 << (i))) + +/* Compute the "checksum" for a key, consisting of the first + * 4 bytes, normalized for case-insensitivity and packed into + * an int...this checksum allows us to do a single integer + * comparison as a fast check to determine whether we can + * skip a strcasecmp + */ +#define COMPUTE_KEY_CHECKSUM(key, checksum) \ +{ \ + const char *k = (key); \ + apr_uint32_t c = (apr_uint32_t)*k; \ + (checksum) = c; \ + (checksum) <<= 8; \ + if (c) { \ + c = (apr_uint32_t)*++k; \ + checksum |= c; \ + } \ + (checksum) <<= 8; \ + if (c) { \ + c = (apr_uint32_t)*++k; \ + checksum |= c; \ + } \ + (checksum) <<= 8; \ + if (c) { \ + c = (apr_uint32_t)*++k; \ + checksum |= c; \ + } \ + checksum &= CASE_MASK; \ +} + +/** The opaque string-content table type */ +struct apr_table_t { + /* This has to be first to promote backwards compatibility with + * older modules which cast a apr_table_t * to an apr_array_header_t *... + * they should use the apr_table_elts() function for most of the + * cases they do this for. + */ + /** The underlying array for the table */ + apr_array_header_t a; +#ifdef MAKE_TABLE_PROFILE + /** Who created the array. */ + void *creator; +#endif + /* An index to speed up table lookups. The way this works is: + * - Take the requested key and compute its checksum + * - Hash the checksum into the index: + * - index_first[TABLE_HASH(checksum)] is the offset within + * the table of the first entry with that key checksum + * - index_last[TABLE_HASH(checksum)] is the offset within + * the table of the first entry with that key checksum + * - If (and only if) there is no entry in the table whose + * checksum hashes to index element i, then the i'th bit + * of index_initialized will be zero. (Check this before + * trying to use index_first[i] or index_last[i]!) + */ + apr_uint32_t index_initialized; + int index_first[TABLE_HASH_SIZE]; + int index_last[TABLE_HASH_SIZE]; +}; + +/* + * NOTICE: if you tweak this you should look at is_empty_table() + * and table_elts() in alloc.h + */ +#ifdef MAKE_TABLE_PROFILE +static apr_table_entry_t *table_push(apr_table_t *t) +{ + if (t->a.nelts == t->a.nalloc) { + return NULL; + } + return (apr_table_entry_t *) apr_array_push_noclear(&t->a); +} +#else /* MAKE_TABLE_PROFILE */ +#define table_push(t) ((apr_table_entry_t *) apr_array_push_noclear(&(t)->a)) +#endif /* MAKE_TABLE_PROFILE */ + +APR_DECLARE(const apr_array_header_t *) apr_table_elts(const apr_table_t *t) +{ + return (const apr_array_header_t *)t; +} + +APR_DECLARE(int) apr_is_empty_table(const apr_table_t *t) +{ + return ((t == NULL) || (t->a.nelts == 0)); +} + +APR_DECLARE(apr_table_t *) apr_table_make(apr_pool_t *p, int nelts) +{ + apr_table_t *t = apr_palloc(p, sizeof(apr_table_t)); + + make_array_core(&t->a, p, nelts, sizeof(apr_table_entry_t), 0); +#ifdef MAKE_TABLE_PROFILE + t->creator = __builtin_return_address(0); +#endif + t->index_initialized = 0; + return t; +} + +APR_DECLARE(apr_table_t *) apr_table_copy(apr_pool_t *p, const apr_table_t *t) +{ + apr_table_t *new = apr_palloc(p, sizeof(apr_table_t)); + +#if APR_POOL_DEBUG + /* we don't copy keys and values, so it's necessary that t->a.pool + * have a life span at least as long as p + */ + if (!apr_pool_is_ancestor(t->a.pool, p)) { + fprintf(stderr, "apr_table_copy: t's pool is not an ancestor of p\n"); + abort(); + } +#endif + make_array_core(&new->a, p, t->a.nalloc, sizeof(apr_table_entry_t), 0); + memcpy(new->a.elts, t->a.elts, t->a.nelts * sizeof(apr_table_entry_t)); + new->a.nelts = t->a.nelts; + memcpy(new->index_first, t->index_first, sizeof(int) * TABLE_HASH_SIZE); + memcpy(new->index_last, t->index_last, sizeof(int) * TABLE_HASH_SIZE); + new->index_initialized = t->index_initialized; + return new; +} + +static void table_reindex(apr_table_t *t) +{ + int i; + int hash; + apr_table_entry_t *next_elt = (apr_table_entry_t *) t->a.elts; + + t->index_initialized = 0; + for (i = 0; i < t->a.nelts; i++, next_elt++) { + hash = TABLE_HASH(next_elt->key); + t->index_last[hash] = i; + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = i; + TABLE_SET_INDEX_INITIALIZED(t, hash); + } + } +} + +APR_DECLARE(void) apr_table_clear(apr_table_t *t) +{ + t->a.nelts = 0; + t->index_initialized = 0; +} + +APR_DECLARE(const char *) apr_table_get(const apr_table_t *t, const char *key) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_uint32_t checksum; + int hash; + + if (key == NULL) { + return NULL; + } + + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + return NULL; + } + COMPUTE_KEY_CHECKSUM(key, checksum); + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + return next_elt->val; + } + } + + return NULL; +} + +APR_DECLARE(void) apr_table_set(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_table_entry_t *table_end; + apr_uint32_t checksum; + int hash; + + COMPUTE_KEY_CHECKSUM(key, checksum); + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + goto add_new_elt; + } + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts; + + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + + /* Found an existing entry with the same key, so overwrite it */ + + int must_reindex = 0; + apr_table_entry_t *dst_elt = NULL; + + next_elt->val = apr_pstrdup(t->a.pool, val); + + /* Remove any other instances of this key */ + for (next_elt++; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + t->a.nelts--; + if (!dst_elt) { + dst_elt = next_elt; + } + } + else if (dst_elt) { + *dst_elt++ = *next_elt; + must_reindex = 1; + } + } + + /* If we've removed anything, shift over the remainder + * of the table (note that the previous loop didn't + * run to the end of the table, just to the last match + * for the index) + */ + if (dst_elt) { + for (; next_elt < table_end; next_elt++) { + *dst_elt++ = *next_elt; + } + must_reindex = 1; + } + if (must_reindex) { + table_reindex(t); + } + return; + } + } + +add_new_elt: + t->index_last[hash] = t->a.nelts; + next_elt = (apr_table_entry_t *) table_push(t); + next_elt->key = apr_pstrdup(t->a.pool, key); + next_elt->val = apr_pstrdup(t->a.pool, val); + next_elt->key_checksum = checksum; +} + +APR_DECLARE(void) apr_table_setn(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_table_entry_t *table_end; + apr_uint32_t checksum; + int hash; + + COMPUTE_KEY_CHECKSUM(key, checksum); + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + goto add_new_elt; + } + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + table_end =((apr_table_entry_t *) t->a.elts) + t->a.nelts; + + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + + /* Found an existing entry with the same key, so overwrite it */ + + int must_reindex = 0; + apr_table_entry_t *dst_elt = NULL; + + next_elt->val = (char *)val; + + /* Remove any other instances of this key */ + for (next_elt++; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + t->a.nelts--; + if (!dst_elt) { + dst_elt = next_elt; + } + } + else if (dst_elt) { + *dst_elt++ = *next_elt; + must_reindex = 1; + } + } + + /* If we've removed anything, shift over the remainder + * of the table (note that the previous loop didn't + * run to the end of the table, just to the last match + * for the index) + */ + if (dst_elt) { + for (; next_elt < table_end; next_elt++) { + *dst_elt++ = *next_elt; + } + must_reindex = 1; + } + if (must_reindex) { + table_reindex(t); + } + return; + } + } + +add_new_elt: + t->index_last[hash] = t->a.nelts; + next_elt = (apr_table_entry_t *) table_push(t); + next_elt->key = (char *)key; + next_elt->val = (char *)val; + next_elt->key_checksum = checksum; +} + +APR_DECLARE(void) apr_table_unset(apr_table_t *t, const char *key) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_table_entry_t *dst_elt; + apr_uint32_t checksum; + int hash; + int must_reindex; + + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + return; + } + COMPUTE_KEY_CHECKSUM(key, checksum); + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash]; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + must_reindex = 0; + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + + /* Found a match: remove this entry, plus any additional + * matches for the same key that might follow + */ + apr_table_entry_t *table_end = ((apr_table_entry_t *) t->a.elts) + + t->a.nelts; + t->a.nelts--; + dst_elt = next_elt; + for (next_elt++; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + t->a.nelts--; + } + else { + *dst_elt++ = *next_elt; + } + } + + /* Shift over the remainder of the table (note that + * the previous loop didn't run to the end of the table, + * just to the last match for the index) + */ + for (; next_elt < table_end; next_elt++) { + *dst_elt++ = *next_elt; + } + must_reindex = 1; + break; + } + } + if (must_reindex) { + table_reindex(t); + } +} + +APR_DECLARE(void) apr_table_merge(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_uint32_t checksum; + int hash; + + COMPUTE_KEY_CHECKSUM(key, checksum); + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + goto add_new_elt; + } + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash]; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + + /* Found an existing entry with the same key, so merge with it */ + next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ", + val, NULL); + return; + } + } + +add_new_elt: + t->index_last[hash] = t->a.nelts; + next_elt = (apr_table_entry_t *) table_push(t); + next_elt->key = apr_pstrdup(t->a.pool, key); + next_elt->val = apr_pstrdup(t->a.pool, val); + next_elt->key_checksum = checksum; +} + +APR_DECLARE(void) apr_table_mergen(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *next_elt; + apr_table_entry_t *end_elt; + apr_uint32_t checksum; + int hash; + +#if APR_POOL_DEBUG + { + if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) { + fprintf(stderr, "apr_table_mergen: key not in ancestor pool of t\n"); + abort(); + } + if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) { + fprintf(stderr, "apr_table_mergen: key not in ancestor pool of t\n"); + abort(); + } + } +#endif + + COMPUTE_KEY_CHECKSUM(key, checksum); + hash = TABLE_HASH(key); + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + goto add_new_elt; + } + next_elt = ((apr_table_entry_t *) t->a.elts) + t->index_first[hash];; + end_elt = ((apr_table_entry_t *) t->a.elts) + t->index_last[hash]; + + for (; next_elt <= end_elt; next_elt++) { + if ((checksum == next_elt->key_checksum) && + !strcasecmp(next_elt->key, key)) { + + /* Found an existing entry with the same key, so merge with it */ + next_elt->val = apr_pstrcat(t->a.pool, next_elt->val, ", ", + val, NULL); + return; + } + } + +add_new_elt: + t->index_last[hash] = t->a.nelts; + next_elt = (apr_table_entry_t *) table_push(t); + next_elt->key = (char *)key; + next_elt->val = (char *)val; + next_elt->key_checksum = checksum; +} + +APR_DECLARE(void) apr_table_add(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *elts; + apr_uint32_t checksum; + int hash; + + hash = TABLE_HASH(key); + t->index_last[hash] = t->a.nelts; + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + } + COMPUTE_KEY_CHECKSUM(key, checksum); + elts = (apr_table_entry_t *) table_push(t); + elts->key = apr_pstrdup(t->a.pool, key); + elts->val = apr_pstrdup(t->a.pool, val); + elts->key_checksum = checksum; +} + +APR_DECLARE(void) apr_table_addn(apr_table_t *t, const char *key, + const char *val) +{ + apr_table_entry_t *elts; + apr_uint32_t checksum; + int hash; + +#if APR_POOL_DEBUG + { + if (!apr_pool_is_ancestor(apr_pool_find(key), t->a.pool)) { + fprintf(stderr, "apr_table_addn: key not in ancestor pool of t\n"); + abort(); + } + if (!apr_pool_is_ancestor(apr_pool_find(val), t->a.pool)) { + fprintf(stderr, "apr_table_addn: key not in ancestor pool of t\n"); + abort(); + } + } +#endif + + hash = TABLE_HASH(key); + t->index_last[hash] = t->a.nelts; + if (!TABLE_INDEX_IS_INITIALIZED(t, hash)) { + t->index_first[hash] = t->a.nelts; + TABLE_SET_INDEX_INITIALIZED(t, hash); + } + COMPUTE_KEY_CHECKSUM(key, checksum); + elts = (apr_table_entry_t *) table_push(t); + elts->key = (char *)key; + elts->val = (char *)val; + elts->key_checksum = checksum; +} + +APR_DECLARE(apr_table_t *) apr_table_overlay(apr_pool_t *p, + const apr_table_t *overlay, + const apr_table_t *base) +{ + apr_table_t *res; + +#if APR_POOL_DEBUG + /* we don't copy keys and values, so it's necessary that + * overlay->a.pool and base->a.pool have a life span at least + * as long as p + */ + if (!apr_pool_is_ancestor(overlay->a.pool, p)) { + fprintf(stderr, + "apr_table_overlay: overlay's pool is not an ancestor of p\n"); + abort(); + } + if (!apr_pool_is_ancestor(base->a.pool, p)) { + fprintf(stderr, + "apr_table_overlay: base's pool is not an ancestor of p\n"); + abort(); + } +#endif + + res = apr_palloc(p, sizeof(apr_table_t)); + /* behave like append_arrays */ + res->a.pool = p; + copy_array_hdr_core(&res->a, &overlay->a); + apr_array_cat(&res->a, &base->a); + table_reindex(res); + return res; +} + +/* And now for something completely abstract ... + + * For each key value given as a vararg: + * run the function pointed to as + * int comp(void *r, char *key, char *value); + * on each valid key-value pair in the apr_table_t t that matches the vararg key, + * or once for every valid key-value pair if the vararg list is empty, + * until the function returns false (0) or we finish the table. + * + * Note that we restart the traversal for each vararg, which means that + * duplicate varargs will result in multiple executions of the function + * for each matching key. Note also that if the vararg list is empty, + * only one traversal will be made and will cut short if comp returns 0. + * + * Note that the table_get and table_merge functions assume that each key in + * the apr_table_t is unique (i.e., no multiple entries with the same key). This + * function does not make that assumption, since it (unfortunately) isn't + * true for some of Apache's tables. + * + * Note that rec is simply passed-on to the comp function, so that the + * caller can pass additional info for the task. + * + * ADDENDUM for apr_table_vdo(): + * + * The caching api will allow a user to walk the header values: + * + * apr_status_t apr_cache_el_header_walk(apr_cache_el *el, + * int (*comp)(void *, const char *, const char *), void *rec, ...); + * + * So it can be ..., however from there I use a callback that use a va_list: + * + * apr_status_t (*cache_el_header_walk)(apr_cache_el *el, + * int (*comp)(void *, const char *, const char *), void *rec, va_list); + * + * To pass those ...'s on down to the actual module that will handle walking + * their headers, in the file case this is actually just an apr_table - and + * rather than reimplementing apr_table_do (which IMHO would be bad) I just + * called it with the va_list. For mod_shmem_cache I don't need it since I + * can't use apr_table's, but mod_file_cache should (though a good hash would + * be better, but that's a different issue :). + * + * So to make mod_file_cache easier to maintain, it's a good thing + */ +APR_DECLARE_NONSTD(int) apr_table_do(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, ...) +{ + int rv; + + va_list vp; + va_start(vp, t); + rv = apr_table_vdo(comp, rec, t, vp); + va_end(vp); + + return rv; +} + +/* XXX: do the semantics of this routine make any sense? Right now, + * if the caller passed in a non-empty va_list of keys to search for, + * the "early termination" facility only terminates on *that* key; other + * keys will continue to process. Note that this only has any effect + * at all if there are multiple entries in the table with the same key, + * otherwise the called function can never effectively early-terminate + * this function, as the zero return value is effectively ignored. + * + * Note also that this behavior is at odds with the behavior seen if an + * empty va_list is passed in -- in that case, a zero return value terminates + * the entire apr_table_vdo (which is what I think should happen in + * both cases). + * + * If nobody objects soon, I'm going to change the order of the nested + * loops in this function so that any zero return value from the (*comp) + * function will cause a full termination of apr_table_vdo. I'm hesitant + * at the moment because these (funky) semantics have been around for a + * very long time, and although Apache doesn't seem to use them at all, + * some third-party vendor might. I can only think of one possible reason + * the existing semantics would make any sense, and it's very Apache-centric, + * which is this: if (*comp) is looking for matches of a particular + * substring in request headers (let's say it's looking for a particular + * cookie name in the Set-Cookie headers), then maybe it wants to be + * able to stop searching early as soon as it finds that one and move + * on to the next key. That's only an optimization of course, but changing + * the behavior of this function would mean that any code that tried + * to do that would stop working right. + * + * Sigh. --JCW, 06/28/02 + */ +APR_DECLARE(int) apr_table_vdo(apr_table_do_callback_fn_t *comp, + void *rec, const apr_table_t *t, va_list vp) +{ + char *argp; + apr_table_entry_t *elts = (apr_table_entry_t *) t->a.elts; + int vdorv = 1; + + argp = va_arg(vp, char *); + do { + int rv = 1, i; + if (argp) { + /* Scan for entries that match the next key */ + int hash = TABLE_HASH(argp); + if (TABLE_INDEX_IS_INITIALIZED(t, hash)) { + apr_uint32_t checksum; + COMPUTE_KEY_CHECKSUM(argp, checksum); + for (i = t->index_first[hash]; + rv && (i <= t->index_last[hash]); ++i) { + if (elts[i].key && (checksum == elts[i].key_checksum) && + !strcasecmp(elts[i].key, argp)) { + rv = (*comp) (rec, elts[i].key, elts[i].val); + } + } + } + } + else { + /* Scan the entire table */ + for (i = 0; rv && (i < t->a.nelts); ++i) { + if (elts[i].key) { + rv = (*comp) (rec, elts[i].key, elts[i].val); + } + } + } + if (rv == 0) { + vdorv = 0; + } + } while (argp && ((argp = va_arg(vp, char *)) != NULL)); + + return vdorv; +} + +static apr_table_entry_t **table_mergesort(apr_pool_t *pool, + apr_table_entry_t **values, int n) +{ + /* Bottom-up mergesort, based on design in Sedgewick's "Algorithms + * in C," chapter 8 + */ + apr_table_entry_t **values_tmp = + (apr_table_entry_t **)apr_palloc(pool, n * sizeof(apr_table_entry_t*)); + apr_size_t i; + int blocksize; + + /* First pass: sort pairs of elements (blocksize=1) */ + for (i = 0; i + 1 < n; i += 2) { + if (strcasecmp(values[i]->key, values[i + 1]->key) > 0) { + apr_table_entry_t *swap = values[i]; + values[i] = values[i + 1]; + values[i + 1] = swap; + } + } + + /* Merge successively larger blocks */ + blocksize = 2; + while (blocksize < n) { + apr_table_entry_t **dst = values_tmp; + int next_start; + apr_table_entry_t **swap; + + /* Merge consecutive pairs blocks of the next blocksize. + * Within a block, elements are in sorted order due to + * the previous iteration. + */ + for (next_start = 0; next_start + blocksize < n; + next_start += (blocksize + blocksize)) { + + int block1_start = next_start; + int block2_start = block1_start + blocksize; + int block1_end = block2_start; + int block2_end = block2_start + blocksize; + if (block2_end > n) { + /* The last block may be smaller than blocksize */ + block2_end = n; + } + for (;;) { + + /* Merge the next two blocks: + * Pick the smaller of the next element from + * block 1 and the next element from block 2. + * Once either of the blocks is emptied, copy + * over all the remaining elements from the + * other block + */ + if (block1_start == block1_end) { + for (; block2_start < block2_end; block2_start++) { + *dst++ = values[block2_start]; + } + break; + } + else if (block2_start == block2_end) { + for (; block1_start < block1_end; block1_start++) { + *dst++ = values[block1_start]; + } + break; + } + if (strcasecmp(values[block1_start]->key, + values[block2_start]->key) > 0) { + *dst++ = values[block2_start++]; + } + else { + *dst++ = values[block1_start++]; + } + } + } + + /* If n is not a multiple of 2*blocksize, some elements + * will be left over at the end of the array. + */ + for (i = dst - values_tmp; i < n; i++) { + values_tmp[i] = values[i]; + } + + /* The output array of this pass becomes the input + * array of the next pass, and vice versa + */ + swap = values_tmp; + values_tmp = values; + values = swap; + + blocksize += blocksize; + } + + return values; +} + +APR_DECLARE(void) apr_table_compress(apr_table_t *t, unsigned flags) +{ + apr_table_entry_t **sort_array; + apr_table_entry_t **sort_next; + apr_table_entry_t **sort_end; + apr_table_entry_t *table_next; + apr_table_entry_t **last; + int i; + int dups_found; + + if (t->a.nelts <= 1) { + return; + } + + /* Copy pointers to all the table elements into an + * array and sort to allow for easy detection of + * duplicate keys + */ + sort_array = (apr_table_entry_t **) + apr_palloc(t->a.pool, t->a.nelts * sizeof(apr_table_entry_t*)); + sort_next = sort_array; + table_next = (apr_table_entry_t *)t->a.elts; + i = t->a.nelts; + do { + *sort_next++ = table_next++; + } while (--i); + + /* Note: the merge is done with mergesort instead of quicksort + * because mergesort is a stable sort and runs in n*log(n) + * time regardless of its inputs (quicksort is quadratic in + * the worst case) + */ + sort_array = table_mergesort(t->a.pool, sort_array, t->a.nelts); + + /* Process any duplicate keys */ + dups_found = 0; + sort_next = sort_array; + sort_end = sort_array + t->a.nelts; + last = sort_next++; + while (sort_next < sort_end) { + if (((*sort_next)->key_checksum == (*last)->key_checksum) && + !strcasecmp((*sort_next)->key, (*last)->key)) { + apr_table_entry_t **dup_last = sort_next + 1; + dups_found = 1; + while ((dup_last < sort_end) && + ((*dup_last)->key_checksum == (*last)->key_checksum) && + !strcasecmp((*dup_last)->key, (*last)->key)) { + dup_last++; + } + dup_last--; /* Elements from last through dup_last, inclusive, + * all have the same key + */ + if (flags == APR_OVERLAP_TABLES_MERGE) { + apr_size_t len = 0; + apr_table_entry_t **next = last; + char *new_val; + char *val_dst; + do { + len += strlen((*next)->val); + len += 2; /* for ", " or trailing null */ + } while (++next <= dup_last); + new_val = (char *)apr_palloc(t->a.pool, len); + val_dst = new_val; + next = last; + for (;;) { + strcpy(val_dst, (*next)->val); + val_dst += strlen((*next)->val); + next++; + if (next > dup_last) { + *val_dst = 0; + break; + } + else { + *val_dst++ = ','; + *val_dst++ = ' '; + } + } + (*last)->val = new_val; + } + else { /* overwrite */ + (*last)->val = (*dup_last)->val; + } + do { + (*sort_next)->key = NULL; + } while (++sort_next <= dup_last); + } + else { + last = sort_next++; + } + } + + /* Shift elements to the left to fill holes left by removing duplicates */ + if (dups_found) { + apr_table_entry_t *src = (apr_table_entry_t *)t->a.elts; + apr_table_entry_t *dst = (apr_table_entry_t *)t->a.elts; + apr_table_entry_t *last_elt = src + t->a.nelts; + do { + if (src->key) { + *dst++ = *src; + } + } while (++src < last_elt); + t->a.nelts -= (int)(last_elt - dst); + } + + table_reindex(t); +} + +static void apr_table_cat(apr_table_t *t, const apr_table_t *s) +{ + const int n = t->a.nelts; + register int idx; + + apr_array_cat(&t->a,&s->a); + + if (n == 0) { + memcpy(t->index_first,s->index_first,sizeof(int) * TABLE_HASH_SIZE); + memcpy(t->index_last, s->index_last, sizeof(int) * TABLE_HASH_SIZE); + t->index_initialized = s->index_initialized; + return; + } + + for (idx = 0; idx < TABLE_HASH_SIZE; ++idx) { + if (TABLE_INDEX_IS_INITIALIZED(s, idx)) { + t->index_last[idx] = s->index_last[idx] + n; + if (!TABLE_INDEX_IS_INITIALIZED(t, idx)) { + t->index_first[idx] = s->index_first[idx] + n; + } + } + } + + t->index_initialized |= s->index_initialized; +} + +APR_DECLARE(void) apr_table_overlap(apr_table_t *a, const apr_table_t *b, + unsigned flags) +{ + if (a->a.nelts + b->a.nelts == 0) { + return; + } + +#if APR_POOL_DEBUG + /* Since the keys and values are not copied, it's required that + * b->a.pool has a lifetime at least as long as a->a.pool. */ + if (!apr_pool_is_ancestor(b->a.pool, a->a.pool)) { + fprintf(stderr, "apr_table_overlap: b's pool is not an ancestor of a's\n"); + abort(); + } +#endif + + apr_table_cat(a, b); + + apr_table_compress(a, flags); +} diff --git a/srclib/apr/test/MakeWin32Make.awk b/srclib/apr/test/MakeWin32Make.awk new file mode 100644 index 0000000000..c5529f8ffd --- /dev/null +++ b/srclib/apr/test/MakeWin32Make.awk @@ -0,0 +1,53 @@ +{ + + if (match($0, /\@INCLUDE_RULES\@/ ) ) { + print "ALL: \$(TARGETS)"; + print ""; + print "CL = cl.exe"; + print "LINK = link.exe /nologo /debug /machine:I386 /subsystem:console /incremental:no "; + print ""; + print "CFLAGS = /nologo /c /MDd /W3 /Gm /GX /Zi /Od /D _DEBUG /D WIN32 /D APR_DECLARE_STATIC /FD "; + print ""; + print ".c.obj::"; + $0 = "\t\$(CL) -c \$< \$(CFLAGS) \$(INCLUDES)"; + } + if ( match( $0, /^ALL_LIBS=/ ) ) { + $0 = ""; + } + if ( match( $0, /^LOCAL_LIBS=/ ) ) { + print "LOCAL_LIBS= ../LibD/apr.lib "; + print "ALL_LIBS= kernel32\.lib user32\.lib advapi32\.lib Rpcrt4\.lib ws2_32\.lib wsock32\.lib ole32\.lib "; + $0 = "" + } + if ( match( $0, /\@CFLAGS\@/ ) ) { + $0 = ""; + } + gsub( /\$\([^\)]* [^\)]*\)/, "", $0 ); + gsub( /\$\{LD_FLAGS\}/, "", $0 ); + gsub( /\.\.\/libapr\.la/, "../LibD/apr.lib", $0 ); + gsub( /\@RM\@/, "del", $0 ); + if (gsub( /\$\(RM\) -f/, "del" ) ) { + gsub( /\*\.a/, "*.lib *.exp *.idb *.ilk *.pdb", $0 ); + gsub( /Makefile/, "Makefile *.ncb *.opt", $0 ); + } + gsub( /\@CC\@/, "cl", $0); + gsub( /\@RANLIB\@/, "", $0); + gsub( /-I\$\(INCDIR\)/, "/I \"$(INCDIR)\"", $0); + + gsub( /\.\.\/libapr\.a/, "../LibD/apr.lib", $0 ); + if ( gsub( /\@EXEEXT\@/, ".exe", $0 ) ) { + gsub( /\$\(CC\) \$\(CFLAGS\)/, "\$\(LINK\) /subsystem:console", $0 ); + gsub( /-o (\S+)/, "/out:\"$1\"", $0 ); + gsub( /--export-dynamic /, "", $0 ); + gsub( /-fPIC /, "", $0 ); + } + if ( gsub( /-shared/, "/subsystem:windows /dll", $0 ) ) { + gsub( /-o (\S+)/ "/out:\"$1\"", $0 ); + } + gsub( /\$\(NONPORTABLE\)/, "", $0 ); + gsub( /\.a /, ".lib ", $0 ); + gsub( /\.o /, ".obj ", $0 ); + gsub( /\.lo /, ".obj ", $0 ); + + print $0; +} diff --git a/srclib/apr/test/Makefile.in b/srclib/apr/test/Makefile.in new file mode 100644 index 0000000000..14b9a37f87 --- /dev/null +++ b/srclib/apr/test/Makefile.in @@ -0,0 +1,117 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +# PROGRAMS includes all test programs built on this platform. +# STDTEST_PORTABLE +# test programs invoked via standard user interface, run on all platforms +# STDTEST_NONPORTABLE +# test programs invoked via standard user interface, not portable +# OTHER_PROGRAMS +# programs such as sendfile, that have to be invoked in a special sequence +# or with special parameters + +STDTEST_PORTABLE = \ + testlockperf@EXEEXT@ \ + testshmproducer@EXEEXT@ \ + testshmconsumer@EXEEXT@ \ + testmutexscope@EXEEXT@ \ + testall@EXEEXT@ + +OTHER_PROGRAMS = sendfile@EXEEXT@ + +PROGRAMS = $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE) $(OTHER_PROGRAMS) + +TARGETS = $(PROGRAMS) + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +LOCAL_LIBS=../lib@APR_LIBNAME@.la + +CLEAN_TARGETS = testfile.tmp mod_test.slo proc_child@EXEEXT@ occhild@EXEEXT@ \ + readchild@EXEEXT@ tryread@EXEEXT@ sockchild@EXEEXT@ \ + globalmutexchild@EXEEXT@ lfstests/large.bin \ + data/testputs.txt data/testbigfprintf.dat data/testwritev.txt \ + data/testwritev_full.txt +CLEAN_SUBDIRS = internal + +INCDIR=../include +INCLUDES=-I$(INCDIR) -I$(srcdir)/../include + +# link programs using -no-install to get real executables not +# libtool wrapper scripts which link an executable when first run. +LINK_PROG = $(LIBTOOL) $(LTFLAGS) --mode=link $(LT_LDFLAGS) $(COMPILE) -no-install $(ALL_LDFLAGS) -o $@ + +check: $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE) + for prog in $(STDTEST_PORTABLE) $(STDTEST_NONPORTABLE); do \ + ./$$prog; \ + if test $$? = 255; then \ + echo "$$prog failed"; \ + break; \ + fi; \ + done + +occhild@EXEEXT@: occhild.lo $(LOCAL_LIBS) + $(LINK_PROG) occhild.lo $(LOCAL_LIBS) $(ALL_LIBS) + +sockchild@EXEEXT@: sockchild.lo $(LOCAL_LIBS) + $(LINK_PROG) sockchild.lo $(LOCAL_LIBS) $(ALL_LIBS) + +readchild@EXEEXT@: readchild.lo $(LOCAL_LIBS) + $(LINK_PROG) readchild.lo $(LOCAL_LIBS) $(ALL_LIBS) + +globalmutexchild@EXEEXT@: globalmutexchild.lo $(LOCAL_LIBS) + $(LINK_PROG) globalmutexchild.lo $(LOCAL_LIBS) $(ALL_LIBS) + +tryread@EXEEXT@: tryread.lo $(LOCAL_LIBS) + $(LINK_PROG) tryread.lo $(LOCAL_LIBS) $(ALL_LIBS) + +proc_child@EXEEXT@: proc_child.lo $(LOCAL_LIBS) + $(LINK_PROG) proc_child.lo $(LOCAL_LIBS) $(ALL_LIBS) + +# FIXME: -prefer-pic is only supported with libtool-1.4+ +mod_test.slo: $(srcdir)/mod_test.c + $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -prefer-pic -c $(srcdir)/mod_test.c && touch $@ + +mod_test.la: mod_test.slo $(LOCAL_LIBS) + $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -avoid-version -module mod_test.lo $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ + +libmod_test.la: mod_test.slo $(LOCAL_LIBS) + $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -avoid-version mod_test.lo $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ $(LOCAL_LIBS) $(ALL_LIBS) + +testlockperf@EXEEXT@: testlockperf.lo $(LOCAL_LIBS) + $(LINK_PROG) testlockperf.lo $(LOCAL_LIBS) $(ALL_LIBS) + +sendfile@EXEEXT@: sendfile.lo $(LOCAL_LIBS) + $(LINK_PROG) sendfile.lo $(LOCAL_LIBS) $(ALL_LIBS) + +testshmproducer@EXEEXT@: testshmproducer.lo $(LOCAL_LIBS) + $(LINK_PROG) testshmproducer.lo $(LOCAL_LIBS) $(ALL_LIBS) + +testshmconsumer@EXEEXT@: testshmconsumer.lo $(LOCAL_LIBS) + $(LINK_PROG) testshmconsumer.lo $(LOCAL_LIBS) $(ALL_LIBS) + +testprocmutex@EXEEXT@: testprocmutex.lo $(LOCAL_LIBS) + $(LINK_PROG) testprocmutex.lo $(LOCAL_LIBS) $(ALL_LIBS) + +testmutexscope@EXEEXT@: testmutexscope.lo $(LOCAL_LIBS) + $(LINK_PROG) testmutexscope.lo $(LOCAL_LIBS) $(ALL_LIBS) + +TESTS = testutil.lo testtime.lo teststr.lo testvsn.lo testipsub.lo \ + testmmap.lo testud.lo testtable.lo testsleep.lo testpools.lo \ + testfmt.lo testfile.lo testdir.lo testfileinfo.lo testrand.lo \ + testdso.lo testoc.lo testdup.lo testsockets.lo testproc.lo \ + testpoll.lo testlock.lo testsockopt.lo testpipe.lo testthread.lo \ + testhash.lo testargs.lo testnames.lo testuser.lo testpath.lo \ + testenv.lo testprocmutex.lo testrand2.lo testfnmatch.lo \ + testatomic.lo testflock.lo testshm.lo testsock.lo testglobalmutex.lo \ + teststrnatcmp.lo testfilecopy.lo testtemp.lo testlfs.lo + +testall@EXEEXT@: $(TESTS) mod_test.la libmod_test.la occhild@EXEEXT@ \ + readchild@EXEEXT@ abts.lo proc_child@EXEEXT@ \ + tryread@EXEEXT@ sockchild@EXEEXT@ globalmutexchild@EXEEXT@ \ + $(LOCAL_LIBS) + $(LINK_PROG) $(TESTS) abts.lo $(LOCAL_LIBS) $(ALL_LIBS) + + +# DO NOT REMOVE diff --git a/srclib/apr/test/Makefile.win b/srclib/apr/test/Makefile.win new file mode 100644 index 0000000000..7e5644e9b1 --- /dev/null +++ b/srclib/apr/test/Makefile.win @@ -0,0 +1,101 @@ + +LINK=link /nologo + +PROGRAMS = \ + globalmutexchild.exe \ + sendfile.exe \ + proc_child.exe \ + tryread.exe \ + occhild.exe \ + readchild.exe \ + sockchild.exe \ + testlockperf.exe \ + testshmproducer.exe \ + testshmconsumer.exe \ + testmutexscope.exe \ + testall.exe \ + mod_test.so + + +TARGETS = $(PROGRAMS) + +LOCAL_LIBS=..\LibD\apr-1.lib +ALL_LIBS=kernel32.lib advapi32.lib ws2_32.lib mswsock.lib ole32.lib shell32.lib rpcrt4.lib + +CLEAN_TARGETS = mod_test.lib mod_test.exp + +INCDIR=../include +INCLUDES=/I "$(INCDIR)" + +all: $(TARGETS) + +clean: + -del $(CLEAN_TARGETS) $(PROGRAMS) *.obj *.pdb *.ilk 2>NUL + +.c.obj: + cl /nologo /c /MDd /W3 /GX /Zi /Od /DWIN32 /D_DEBUG /D_WINDOWS /DAPR_DECLARE_STATIC $(INCLUDES) $< + +tryread.exe: tryread.obj $(LOCAL_LIBS) + $(LINK) tryread.obj $(LOCAL_LIBS) $(ALL_LIBS) + +occhild.exe: occhild.obj $(LOCAL_LIBS) + $(LINK) occhild.obj $(LOCAL_LIBS) $(ALL_LIBS) + +readchild.exe: readchild.obj $(LOCAL_LIBS) + $(LINK) readchild.obj $(LOCAL_LIBS) $(ALL_LIBS) + +proc_child.exe: proc_child.obj $(LOCAL_LIBS) + $(LINK) /debug /subsystem:console /machine:I386 \ + proc_child.obj $(LOCAL_LIBS) $(ALL_LIBS) + +# FIXME: This is BS ... we should deal with namespace decoration within the +# apr_dso_sym() function or within the test (take y'r pick) since many platforms +# have decoration and decoration issues. +mod_test.so: mod_test.obj + $(LINK) mod_test.obj /dll /out:mod_test.so $(LOCAL_LIBS) $(ALL_LIBS) \ + /export:print_hello /export:count_reps + +testlockperf.exe: testlockperf.obj $(LOCAL_LIBS) + $(LINK) testlockperf.obj $(LOCAL_LIBS) $(ALL_LIBS) + +sockchild.exe: sockchild.obj $(LOCAL_LIBS) + $(LINK) sockchild.obj $(LOCAL_LIBS) $(ALL_LIBS) + +sendfile.exe: sendfile.obj $(LOCAL_LIBS) + $(LINK) sendfile.obj $(LOCAL_LIBS) $(ALL_LIBS) + +testshm.exe: testshm.obj $(LOCAL_LIBS) testshmproducer.exe testshmconsumer.exe + $(LINK) testshm.obj $(LOCAL_LIBS) $(ALL_LIBS) + +testshmproducer.exe: testshmproducer.obj $(LOCAL_LIBS) + $(LINK) testshmproducer.obj $(LOCAL_LIBS) $(ALL_LIBS) + +testshmconsumer.exe: testshmconsumer.obj $(LOCAL_LIBS) + $(LINK) testshmconsumer.obj $(LOCAL_LIBS) $(ALL_LIBS) + +testprocmutex.exe: testprocmutex.obj $(LOCAL_LIBS) + $(LINK) testprocmutex.obj $(LOCAL_LIBS) $(ALL_LIBS) + +globalmutexchild.exe: globalmutexchild.obj $(LOCAL_LIBS) + $(LINK) globalmutexchild.obj $(LOCAL_LIBS) $(ALL_LIBS) + +testmutexscope.exe: testmutexscope.obj $(LOCAL_LIBS) + $(LINK) testmutexscope.obj $(LOCAL_LIBS) $(ALL_LIBS) + +TESTS = abts.obj testtime.obj teststr.obj testvsn.obj testipsub.obj \ + testmmap.obj testud.obj testtable.obj testsleep.obj testpools.obj \ + testfmt.obj testfile.obj testdir.obj testfileinfo.obj testrand.obj \ + testdso.obj testoc.obj testdup.obj testsockets.obj testproc.obj \ + testpoll.obj testlock.obj testsockopt.obj testpipe.obj testthread.obj \ + testhash.obj testargs.obj testnames.obj testuser.obj testpath.obj \ + testenv.obj testprocmutex.obj testrand2.obj testfnmatch.obj \ + testatomic.obj testflock.obj testshm.obj testsock.obj \ + testglobalmutex.obj teststrnatcmp.obj testfilecopy.obj \ + testtemp.obj testlfs.obj testutil.obj + +testall.exe: $(TESTS) $(LOCAL_LIBS) + $(LINK) /debug /subsystem:console /machine:I386 /out:$@ $(TESTS) \ + $(LOCAL_LIBS) $(ALL_LIBS) + + +# DO NOT REMOVE diff --git a/srclib/apr/test/NWGNUmakefile b/srclib/apr/test/NWGNUmakefile new file mode 100644 index 0000000000..c5bf24c111 --- /dev/null +++ b/srclib/apr/test/NWGNUmakefile @@ -0,0 +1,264 @@ +# +# Declare the sub-directories to be built here +# + +SUBDIRS = \ + $(EOLIST) + +# +# Get the 'head' of the build environment. This includes default targets and +# paths to tools +# + +include $(APR_WORK)\build\NWGNUhead.inc + +# +# build this level's files + +# +# Make sure all needed macro's are defined +# + + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = NLM is to test the apr layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/aprtest.nlm \ + $(OBJDIR)/mod_test.nlm \ + $(OBJDIR)/proc_child.nlm \ + $(OBJDIR)/readchild.nlm \ + $(OBJDIR)/globalmutexchild.nlm \ + $(OBJDIR)/sockchild.nlm \ + $(OBJDIR)/tryread.nlm \ + $(OBJDIR)/testatmc.nlm \ + $(EOLIST) +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + copy $(OBJDIR)\*.nlm $(INSTALL)\Apache2 + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/README b/srclib/apr/test/README new file mode 100644 index 0000000000..f387157266 --- /dev/null +++ b/srclib/apr/test/README @@ -0,0 +1,233 @@ +Writing APR tests + +All APR tests should be executable in 2 ways, as an individual program, or +as a part of the full test suite. The full test suite is controlled with +the testall program. At the beginning of the testall.c file, there is an +array of functions called tests. The testall program loops through this +array calling each function. Each function returns a CuSuite variable, which +is then added to the SuiteList. Once all Suites have been added, the SuiteList +is executed, and the output is printed to the screen. All functions in the +array should follow the same basic format: + +The Full Suite +-------------- + +/* The driver function. This must return a CuSuite variable, which will + * then be used to actually run the tests. Essentially, all Suites are a + * collection of tests. The driver will take each Suite, and put it in a + * SuiteList, which is a collection of Suites. + */ +CuSuite *testtime(void) +{ + /* The actual suite, this must be created for each test program. Please + * give it a useful name, that will inform the user of the feature being + * tested. + */ + CuSuite *suite = CuSuiteNew("Test Time"); + + /* Each function must be added to the suite. Each function represents + * a single test. It is possible to test multiple features in a single + * function, although no tests currently do that. + */ + SUITE_ADD_TEST(suite, test_now); + SUITE_ADD_TEST(suite, test_gmtstr); + SUITE_ADD_TEST(suite, test_localstr); + SUITE_ADD_TEST(suite, test_exp_get_gmt); + SUITE_ADD_TEST(suite, test_exp_get_lt); + SUITE_ADD_TEST(suite, test_imp_gmt); + SUITE_ADD_TEST(suite, test_rfcstr); + SUITE_ADD_TEST(suite, test_ctime); + SUITE_ADD_TEST(suite, test_strftime); + SUITE_ADD_TEST(suite, test_strftimesmall); + SUITE_ADD_TEST(suite, test_exp_tz); + SUITE_ADD_TEST(suite, test_strftimeoffset); + + /* You must return the suite so that the driver knows which suites to + * run. + */ + return suite; +} + +Building the full driver +------------------------ + +All you need to do to build the full driver is run: + + make testall + +To run it, run: + + ./testall + +Running individual tests +--------------------------------- + +It is not possible to build individual tests, however it is possible to +run individual tests. When running the test suite, specify the name of the +tests that you want to run on the command line. For example: + + ./testall teststr testrand + +Will run the Strings and Random generator tests. + +Reading the test suite output +----------------------------- + +Once you run the test suite, you will get output like: + +All APR Tests: + Test Strings: .... + Test Time: ............ + +16 tests run: 16 passed, 0 failed, 0 not implemented. + +Known test failures are documented in ../STATUS. + +There are a couple of things to look at with this. First, if you look at the +first function in this document, you should notice that the string passed to +the CuSuiteNew function is in the output. That is why the string should +explain the feature you are testing. + +Second, this test passed completely. This is obvious in two ways. First, and +most obvious, the summary line tells you that 16 tests were run and 16 tests +passed. However, the results can also be found in the lines above. Every +'.' in the output represents a passed test. + +If a test fails, the output will look like: + +All APR Tests: + Test Strings: .... + Test Time: ..F......... + +16 tests run: 15 passed, 1 failed, 0 not implemented. + +This is not very useful, because you don't know which test failed. However, +once you know that a test failed, you can run the suite again, with the +-v option. If you do this, you will get something like: + +All APR Tests: + Test Strings: .... + Test Time: ..F......... + +16 tests run: 15 passed, 1 failed, 0 not implemented. +Failed tests: +1) test_localstr: assert failed + +In this case, we know the test_localstr function failed, and there is an +Assert in this that failed (I modified the test to fail for this document). +Now, you can look at what that test does, and why it would have failed. + +There is one other possible output for the test suite (run with -v): + +All APR Tests: + Test Strings: .... + Test Time: ..N......... + +16 tests run: 15 passed, 0 failed, 1 not implemented. + +Not Implemented tests: + +Not Implemented tests: +1) test_localstr: apr_time_exp_lt not implemented on this platform + +The 'N' means that a function has returned APR_ENOTIMPL. This should be +treated as an error, and the function should be implemented as soon as +possible. + +Adding New test Suites to the full driver +------------------------------------------- + +To add a new Suite to the full driver, you must make a couple of modifications. + +1) Edit test_apr.h, and add the prototype for the function. +2) Edit testall.c, and add the function and name to the tests array. +3) Edit Makefile.in, and add the .lo file to the testall target. + +Once those four things are done, your tests will automatically be added +to the suite. + +Writing tests +------------- + +There are a couple of rules for writing good tests for the test suite. + +1) All tests can determine for themselves if it passed or not. This means +that there is no reason for the person running the test suite to interpret +the results of the tests. +2) Never use printf to add to the output of the test suite. The suite +library should be able to print all of the information required to debug +a problem. +3) Functions should be tested with both positive and negative tests. This +means that you should test things that should both succeed and fail. +4) Just checking the return code does _NOT_ make a useful test. You must +check to determine that the test actually did what you expected it to do. + +An example test +--------------- + +Finally, we will look at a quick test: + +/* All tests are passed a CuTest variable. This is how the suite determines + * if the test succeeded or failed. + */ +static void test_localstr(CuTest *tc) +{ + apr_status_t rv; + apr_time_exp_t xt; + time_t os_now; + + rv = apr_time_exp_lt(&xt, now); + os_now = now / APR_USEC_PER_SEC; + + /* If the function can return APR_ENOTIMPL, then you should check for it. + * This allows platform implementors to know if they have to implement + * the function. + */ + if (rv == APR_ENOTIMPL) { + CuNotImpl(tc, "apr_time_exp_lt"); + } + + /* It often helps to ensure that the return code was APR_SUCESS. If it + * wasn't, then we know the test failed. + */ + CuAssertTrue(tc, rv == APR_SUCCESS); + + /* Now that we know APR thinks it worked properly, we need to check the + * output to ensure that we got what we expected. + */ + CuAssertStrEquals(tc, "2002-08-14 12:05:36.186711 -25200 [257 Sat] DST", + print_time(p, &xt)); +} + +Notice, the same test can fail for any of a number of reasons. The first +test to fail ends the test. + +CuTest +------ + +CuTest is an open source test suite written by Asim Jalis. It has been +released under the zlib/libpng license. That license can be found in the +CuTest.c and CuTest.h files. + +The version of CuTest that is included in the APR test suite has been modified +from the original distribution in the following ways: + +1) The original distribution does not have a -v flag, the details are always +printed. +2) The NotImplemented result does not exist. +3) SuiteLists do not exist. In the original distribution, you can add suites +to suites, but it just adds the tests in the first suite to the list of tests +in the original suite. The output wasn't as detailed as I wanted, so I created +SuiteLists. + +The first two modifications have been sent to the original author of CuTest, +but they have not been integrated into the base distribution. The SuiteList +changes will be sent to the original author soon. + +The modified version of CuTest is not currently in any CVS or Subversion +server. In time, it will be hosted at rkbloom.net. + +There are currently no docs for how to write tests, but the teststr and +testtime programs should give an idea of how it is done. In time, a document +should be written to define how tests are written. + diff --git a/srclib/apr/test/abts.c b/srclib/apr/test/abts.c new file mode 100644 index 0000000000..2905a2592d --- /dev/null +++ b/srclib/apr/test/abts.c @@ -0,0 +1,413 @@ +/* Copyright 2000-2004 Ryan Bloom + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Portions of this file were taken from testall.c in the APR test suite, + * written by members of the Apache Software Foundation. + */ + +#include "abts.h" +#include "abts_tests.h" +#include "testutil.h" + +#define ABTS_STAT_SIZE 6 +static char status[ABTS_STAT_SIZE] = {'|', '/', '-', '|', '\\', '-'}; +static int curr_char; +static int verbose = 0; +static int exclude = 0; +static int quiet = 0; +static int list_tests = 0; + +const char **testlist = NULL; + +static int find_test_name(const char *testname) { + int i; + for (i = 0; testlist[i] != NULL; i++) { + if (!strcmp(testlist[i], testname)) { + return 1; + } + } + return 0; +} + +/* Determine if the test should be run at all */ +static int should_test_run(const char *testname) { + int found = 0; + if (list_tests == 1) { + return 0; + } + if (testlist == NULL) { + return 1; + } + found = find_test_name(testname); + if ((found && !exclude) || (!found && exclude)) { + return 1; + } + return 0; +} + +static void reset_status(void) +{ + curr_char = 0; +} + +static void update_status(void) +{ + if (!quiet) { + curr_char = (curr_char + 1) % ABTS_STAT_SIZE; + fprintf(stdout, "\b%c", status[curr_char]); + fflush(stdout); + } +} + +static void end_suite(abts_suite *suite) +{ + if (suite != NULL) { + sub_suite *last = suite->tail; + if (!quiet) { + fprintf(stdout, "\b"); + fflush(stdout); + } + if (last->failed == 0) { + fprintf(stdout, "SUCCESS\n"); + fflush(stdout); + } + else { + fprintf(stdout, "FAILED %d of %d\n", last->failed, last->num_test); + fflush(stdout); + } + } +} + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name_full) +{ + sub_suite *subsuite; + char *p; + const char *suite_name; + curr_char = 0; + + /* Only end the suite if we actually ran it */ + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + subsuite = malloc(sizeof(*subsuite)); + subsuite->num_test = 0; + subsuite->failed = 0; + subsuite->next = NULL; + /* suite_name_full may be an absolute path depending on __FILE__ + * expansion */ + suite_name = strrchr(suite_name_full, '/'); + if (suite_name) { + suite_name++; + } else { + suite_name = suite_name_full; + } + p = strrchr(suite_name, '.'); + if (p) { + subsuite->name = memcpy(calloc(p - suite_name + 1, 1), + suite_name, p - suite_name); + } + else { + subsuite->name = suite_name; + } + + if (list_tests) { + fprintf(stdout, "%s\n", subsuite->name); + } + + subsuite->not_run = 0; + + if (suite == NULL) { + suite = malloc(sizeof(*suite)); + suite->head = subsuite; + suite->tail = subsuite; + } + else { + suite->tail->next = subsuite; + suite->tail = subsuite; + } + + if (!should_test_run(subsuite->name)) { + subsuite->not_run = 1; + return suite; + } + + reset_status(); + fprintf(stdout, "%-20s: ", subsuite->name); + update_status(); + fflush(stdout); + + return suite; +} + +void abts_run_test(abts_suite *ts, test_func f, void *value) +{ + abts_case tc; + sub_suite *ss; + + if (!should_test_run(ts->tail->name)) { + return; + } + ss = ts->tail; + + tc.failed = 0; + tc.suite = ss; + + ss->num_test++; + update_status(); + + f(&tc, value); + + if (tc.failed) { + ss->failed++; + } +} + +static int report(abts_suite *suite) +{ + int count = 0; + sub_suite *dptr; + + if (suite && suite->tail &&!suite->tail->not_run) { + end_suite(suite); + } + + for (dptr = suite->head; dptr; dptr = dptr->next) { + count += dptr->failed; + } + + if (list_tests) { + return 0; + } + + if (count == 0) { + printf("All tests passed.\n"); + return 0; + } + + dptr = suite->head; + fprintf(stdout, "%-15s\t\tTotal\tFail\tFailed %%\n", "Failed Tests"); + fprintf(stdout, "===================================================\n"); + while (dptr != NULL) { + if (dptr->failed != 0) { + float percent = ((float)dptr->failed / (float)dptr->num_test); + fprintf(stdout, "%-15s\t\t%5d\t%4d\t%6.2f%%\n", dptr->name, + dptr->num_test, dptr->failed, percent * 100); + } + dptr = dptr->next; + } + return 1; +} + +void abts_log_message(const char *fmt, ...) +{ + va_list args; + update_status(); + + if (verbose) { + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + fprintf(stderr, "\n"); + fflush(stderr); + } +} + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected != actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%d>, but saw <%d>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!expected && !actual) return; + if (expected && actual) + if (!strcmp(expected, actual)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (!strncmp(expected, actual, n)) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%s>, but saw <%s>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (ptr != NULL) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Expected NULL, but saw <%p>\n", lineno, ptr); + fflush(stderr); + } +} + +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (expected == actual) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: expected <%p>, but saw <%p>\n", lineno, expected, actual); + fflush(stderr); + } +} + +void abts_fail(abts_case *tc, const char *message, int lineno) +{ + update_status(); + if (tc->failed) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_assert(abts_case *tc, const char *message, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +void abts_true(abts_case *tc, int condition, int lineno) +{ + update_status(); + if (tc->failed) return; + + if (condition) return; + + tc->failed = TRUE; + if (verbose) { + fprintf(stderr, "Line %d: Condition is false, but expected true\n", lineno); + fflush(stderr); + } +} + +void abts_not_impl(abts_case *tc, const char *message, int lineno) +{ + update_status(); + + tc->suite->not_impl++; + if (verbose) { + fprintf(stderr, "Line %d: %s\n", lineno, message); + fflush(stderr); + } +} + +int main(int argc, const char *const argv[]) { + int i; + int rv; + int list_provided = 0; + abts_suite *suite = NULL; + + initialize(); + for (i = 1; i < argc; i++) { + if (!strcmp(argv[i], "-v")) { + verbose = 1; + continue; + } + if (!strcmp(argv[i], "-x")) { + exclude = 1; + continue; + } + if (!strcmp(argv[i], "-l")) { + list_tests = 1; + continue; + } + if (!strcmp(argv[i], "-q")) { + quiet = 1; + continue; + } + if (argv[i][0] == '-') { + fprintf(stderr, "Invalid option: `%s'\n", argv[i]); + exit(1); + } + list_provided = 1; + } + + if (list_provided) { + /* Waste a little space here, because it is easier than counting the + * number of tests listed. Besides it is at most three char *. + */ + testlist = calloc(argc + 1, sizeof(char *)); + for (i = 1; i < argc; i++) { + testlist[i - 1] = argv[i]; + } + } + + for (i = 0; i < (sizeof(alltests) / sizeof(struct testlist *)); i++) { + suite = alltests[i].func(suite); + } + + rv = report(suite); + return rv; +} + diff --git a/srclib/apr/test/abts.h b/srclib/apr/test/abts.h new file mode 100644 index 0000000000..51123ff079 --- /dev/null +++ b/srclib/apr/test/abts.h @@ -0,0 +1,98 @@ +/* Copyright 2000-2004 Ryan Bloom + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include + +#ifndef ABTS_H +#define ABTS_H + +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif + +struct sub_suite { + const char *name; + int num_test; + int failed; + int not_run; + int not_impl; + struct sub_suite *next; +}; +typedef struct sub_suite sub_suite; + +struct abts_suite { + sub_suite *head; + sub_suite *tail; +}; +typedef struct abts_suite abts_suite; + +struct abts_case { + int failed; + sub_suite *suite; +}; +typedef struct abts_case abts_case; + +typedef void (*test_func)(abts_case *tc, void *data); + +#define ADD_SUITE(suite) abts_add_suite(suite, __FILE__); + +abts_suite *abts_add_suite(abts_suite *suite, const char *suite_name); +void abts_run_test(abts_suite *ts, test_func f, void *value); +void abts_log_message(const char *fmt, ...); + +void abts_int_equal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_int_nequal(abts_case *tc, const int expected, const int actual, int lineno); +void abts_str_equal(abts_case *tc, const char *expected, const char *actual, int lineno); +void abts_str_nequal(abts_case *tc, const char *expected, const char *actual, + size_t n, int lineno); +void abts_ptr_notnull(abts_case *tc, const void *ptr, int lineno); +void abts_ptr_equal(abts_case *tc, const void *expected, const void *actual, int lineno); +void abts_true(abts_case *tc, int condition, int lineno); +void abts_fail(abts_case *tc, const char *message, int lineno); +void abts_not_impl(abts_case *tc, const char *message, int lineno); +void abts_assert(abts_case *tc, const char *message, int condition, int lineno); + +/* Convenience macros. Ryan hates these! */ +#define ABTS_INT_EQUAL(a, b, c) abts_int_equal(a, b, c, __LINE__) +#define ABTS_INT_NEQUAL(a, b, c) abts_int_nequal(a, b, c, __LINE__) +#define ABTS_STR_EQUAL(a, b, c) abts_str_equal(a, b, c, __LINE__) +#define ABTS_STR_NEQUAL(a, b, c, d) abts_str_nequal(a, b, c, d, __LINE__) +#define ABTS_PTR_NOTNULL(a, b) abts_ptr_notnull(a, b, __LINE__) +#define ABTS_PTR_EQUAL(a, b, c) abts_ptr_equal(a, b, c, __LINE__) +#define ABTS_TRUE(a, b) abts_true(a, b, __LINE__); +#define ABTS_FAIL(a, b) abts_fail(a, b, __LINE__); +#define ABTS_NOT_IMPL(a, b) abts_not_impl(a, b, __LINE__); +#define ABTS_ASSERT(a, b, c) abts_assert(a, b, c, __LINE__); + +abts_suite *run_tests(abts_suite *suite); +abts_suite *run_tests1(abts_suite *suite); + + +#endif + +#ifdef __cplusplus +} +#endif + diff --git a/srclib/apr/test/abts_tests.h b/srclib/apr/test/abts_tests.h new file mode 100644 index 0000000000..744204d0cd --- /dev/null +++ b/srclib/apr/test/abts_tests.h @@ -0,0 +1,72 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef APR_TEST_INCLUDES +#define APR_TEST_INCLUDES + +#include "abts.h" +#include "testutil.h" + +const struct testlist { + abts_suite *(*func)(abts_suite *suite); +} alltests[] = { + {testatomic}, + {testdir}, + {testdso}, + {testdup}, + {testenv}, + {testfile}, + {testfilecopy}, + {testfileinfo}, + {testflock}, + {testfmt}, + {testfnmatch}, + {testgetopt}, +#if 0 /* not ready yet due to API issues */ + {testglobalmutex}, +#endif + {testhash}, + {testipsub}, + {testlock}, + {testlfs}, + {testmmap}, + {testnames}, + {testoc}, + {testpath}, + {testpipe}, + {testpoll}, + {testpool}, + {testproc}, + {testprocmutex}, + {testrand}, + {testrand2}, + {testsleep}, + {testshm}, + {testsock}, + {testsockets}, + {testsockopt}, + {teststr}, + {teststrnatcmp}, + {testtable}, + {testtemp}, + {testthread}, + {testtime}, + {testud}, + {testuser}, + {testvsn} +}; + +#endif /* APR_TEST_INCLUDES */ diff --git a/srclib/apr/test/aprtest.def b/srclib/apr/test/aprtest.def new file mode 100644 index 0000000000..bfea210d86 --- /dev/null +++ b/srclib/apr/test/aprtest.def @@ -0,0 +1,3 @@ +MODULE LIBC.NLM +MODULE APRLIB.NLM + diff --git a/srclib/apr/test/aprtest.dsp b/srclib/apr/test/aprtest.dsp new file mode 100644 index 0000000000..e31b898d0d --- /dev/null +++ b/srclib/apr/test/aprtest.dsp @@ -0,0 +1,199 @@ +# Microsoft Developer Studio Project File - Name="aprtest" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=aprtest - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "aprtest.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "aprtest.mak" CFG="aprtest - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "aprtest - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "aprtest - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "aprtest - Win32 Release" + +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Cmd_Line "NMAKE /f Makefile" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "aprtest.exe" +# PROP BASE Bsc_Name "aprtest.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Cmd_Line "NMAKE /f aprtest.win" +# PROP Rebuild_Opt "/a" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "aprtest - Win32 Debug" + +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Cmd_Line "NMAKE /f aprtest.mak" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "aprtest.exe" +# PROP BASE Bsc_Name "aprtest.bsc" +# PROP BASE Target_Dir "" +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Cmd_Line "NMAKE /f aprtest.win" +# PROP Rebuild_Opt "/a" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "aprtest - Win32 Release" +# Name "aprtest - Win32 Debug" + +!IF "$(CFG)" == "aprtest - Win32 Release" + +!ELSEIF "$(CFG)" == "aprtest - Win32 Debug" + +!ENDIF + +# Begin Group "Sources" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\abc.c +# End Source File +# Begin Source File + +SOURCE=.\client.c +# End Source File +# Begin Source File + +SOURCE=.\mod_test.c +# End Source File +# Begin Source File + +SOURCE=.\occhild.c +# End Source File +# Begin Source File + +SOURCE=.\sendfile.c +# End Source File +# Begin Source File + +SOURCE=.\server.c +# End Source File +# Begin Source File + +SOURCE=.\testargs.c +# End Source File +# Begin Source File + +SOURCE=.\testcontext.c +# End Source File +# Begin Source File + +SOURCE=.\testdso.c +# End Source File +# Begin Source File + +SOURCE=.\testfile.c +# End Source File +# Begin Source File + +SOURCE=.\testflock.c +# End Source File +# Begin Source File + +SOURCE=.\testlock.c +# End Source File +# Begin Source File + +SOURCE=.\testmmap.c +# End Source File +# Begin Source File + +SOURCE=.\testnames.c +# End Source File +# Begin Source File + +SOURCE=.\testoc.c +# End Source File +# Begin Source File + +SOURCE=.\testpath.c +# End Source File +# Begin Source File + +SOURCE=.\testpipe.c +# End Source File +# Begin Source File + +SOURCE=.\testproc.c +# End Source File +# Begin Source File + +SOURCE=.\testshm.c +# End Source File +# Begin Source File + +SOURCE=.\testsock.c +# End Source File +# Begin Source File + +SOURCE=.\testthread.c +# End Source File +# Begin Source File + +SOURCE=.\testtime.c +# End Source File +# Begin Source File + +SOURCE=.\testucs.c +# End Source File +# Begin Source File + +SOURCE=.\testuser.c +# End Source File +# Begin Source File + +SOURCE=.\testuuid.c +# End Source File +# End Group +# Begin Source File + +SOURCE=.\aprtest.win +# End Source File +# Begin Source File + +SOURCE=.\Makefile +# End Source File +# Begin Source File + +SOURCE=.\Makefile.in +# End Source File +# Begin Source File + +SOURCE=.\MakeWin32Make.awk +# End Source File +# End Target +# End Project diff --git a/srclib/apr/test/aprtest.dsw b/srclib/apr/test/aprtest.dsw new file mode 100644 index 0000000000..d82af60f1b --- /dev/null +++ b/srclib/apr/test/aprtest.dsw @@ -0,0 +1,122 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "apr"="..\apr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "apr_app"="..\build\apr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency +}}} + +############################################################################### + +Project: "aprtest"=".\aprtest.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency +}}} + +############################################################################### + +Project: "libapr"="..\libapr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libapr_app"="..\build\libapr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libapr + End Project Dependency +}}} + +############################################################################### + +Project: "testapp"=".\testapp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency + Begin Project Dependency + Project_Dep_Name apr_app + End Project Dependency +}}} + +############################################################################### + +Project: "testappnt"=".\testappnt.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency + Begin Project Dependency + Project_Dep_Name apr_app + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/srclib/apr/test/aprtest.win b/srclib/apr/test/aprtest.win new file mode 100644 index 0000000000..85ad5b4d78 --- /dev/null +++ b/srclib/apr/test/aprtest.win @@ -0,0 +1,18 @@ +# Note: +# +# You may need to modify the configuration of Build - Options - Directories +# for the Executable path to include the perl interpreter within DevStudio. +# E.g. add c:\program files\perl\bin to the list of directories + +!IF "$(TARGET)" == "" +TARGET=ALL +!ENDIF + +$(TARGET): Makefile + $(MAKE) /nologo /f Makefile $(TARGET) + +Makefile: Makefile.in MakeWin32Make.awk + awk -f MakeWin32Make.awk Makefile + +clean: + del Makefile *.obj *.exe *.idb *.pdb diff --git a/srclib/apr/test/data/file_datafile.txt b/srclib/apr/test/data/file_datafile.txt new file mode 100644 index 0000000000..1651a3293f --- /dev/null +++ b/srclib/apr/test/data/file_datafile.txt @@ -0,0 +1 @@ +This is the file data file. \ No newline at end of file diff --git a/srclib/apr/test/data/mmap_datafile.txt b/srclib/apr/test/data/mmap_datafile.txt new file mode 100644 index 0000000000..50f47a609e --- /dev/null +++ b/srclib/apr/test/data/mmap_datafile.txt @@ -0,0 +1 @@ +This is the MMAP data file. diff --git a/srclib/apr/test/globalmutexchild.c b/srclib/apr/test/globalmutexchild.c new file mode 100644 index 0000000000..e26d0a8095 --- /dev/null +++ b/srclib/apr/test/globalmutexchild.c @@ -0,0 +1,64 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testglobalmutex.h" +#include "apr_pools.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_global_mutex.h" +#include "apr_strings.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + + +int main(int argc, const char * const argv[]) +{ + apr_pool_t *p; + int i = 0; + apr_lockmech_e mech; + apr_global_mutex_t *global_lock; + apr_status_t rv; + + apr_initialize(); + atexit(apr_terminate); + + apr_pool_create(&p, NULL); + if (argc >= 2) { + mech = (apr_lockmech_e)apr_strtoi64(argv[1], NULL, 0); + } + else { + mech = APR_LOCK_DEFAULT; + } + rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p); + if (rv != APR_SUCCESS) { + exit(-rv); + } + apr_global_mutex_child_init(&global_lock, LOCKNAME, p); + + while (1) { + apr_global_mutex_lock(global_lock); + if (i == MAX_ITER) { + apr_global_mutex_unlock(global_lock); + exit(i); + } + i++; + apr_global_mutex_unlock(global_lock); + } + exit(0); +} diff --git a/srclib/apr/test/internal/Makefile.in b/srclib/apr/test/internal/Makefile.in new file mode 100644 index 0000000000..b1f6c6a6c4 --- /dev/null +++ b/srclib/apr/test/internal/Makefile.in @@ -0,0 +1,37 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +NONPORTABLE = \ + testregex@EXEEXT@ + +PROGRAMS = \ + +TARGETS = $(PROGRAMS) $(NONPORTABLE) + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +LOCAL_LIBS=../../lib@APR_LIBNAME@.la + +CLEAN_TARGETS = testregex@EXEEXT@ + +INCDIR=../../include +INCLUDES=-I$(INCDIR) + +CFLAGS=$(MY_CFLAGS) + +all: $(PROGRAMS) $(NONPORTABLE) + +check: $(PROGRAMS) $(NONPORTABLE) + for prog in $(PROGRAMS) $(NONPORTABLE); do \ + ./$$prog; \ + if test $$i = 255; then \ + echo "$$prog failed"; \ + break; \ + fi \ + done + +testregex@EXEEXT@: testregex.lo $(LOCAL_LIBS) + $(LINK) testregex.lo $(LOCAL_LIBS) $(ALL_LIBS) + +# DO NOT REMOVE diff --git a/srclib/apr/test/internal/testregex.c b/srclib/apr/test/internal/testregex.c new file mode 100644 index 0000000000..0103d4482b --- /dev/null +++ b/srclib/apr/test/internal/testregex.c @@ -0,0 +1,91 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "apr_strings.h" +#include "apr_pools.h" +#include "apr_general.h" +#include "apr_hash.h" +#include "apr_lib.h" +#include "apr_time.h" +#include +#include +#include + +int main( int argc, char** argv) { + apr_pool_t *context; + regex_t regex; + int rc; + int i; + int iters; + apr_time_t now; + apr_time_t end; + apr_hash_t *h; + + + if (argc !=4 ) { + fprintf(stderr, "Usage %s match string #iterations\n",argv[0]); + return -1; + } + iters = atoi( argv[3]); + + apr_initialize() ; + atexit(apr_terminate); + if (apr_pool_create(&context, NULL) != APR_SUCCESS) { + fprintf(stderr, "Something went wrong\n"); + exit(-1); + } + rc = regcomp( ®ex, argv[1], REG_EXTENDED|REG_NOSUB); + + + if (rc) { + char errbuf[2000]; + regerror(rc, ®ex,errbuf,2000); + fprintf(stderr,"Couldn't compile regex ;(\n%s\n ",errbuf); + return -1; + } + if ( regexec( ®ex, argv[2], 0, NULL,0) == 0 ) { + fprintf(stderr,"Match\n"); + } + else { + fprintf(stderr,"No Match\n"); + } + now = apr_time_now(); + for (i=0;i +#include + +struct testval { + unsigned char n[8]; + wchar_t w[4]; + int nl; + int wl; +}; + +void displaynw(struct testval *f, struct testval *l) +{ + char x[80], *t = x; + int i; + for (i = 0; i < f->nl; ++i) + t += sprintf(t, "%02X ", f->n[i]); + *(t++) = '-'; + for (i = 0; i < l->nl; ++i) + t += sprintf(t, " %02X", l->n[i]); + *(t++) = ' '; + *(t++) = '='; + *(t++) = ' '; + for (i = 0; i < f->wl; ++i) + t += sprintf(t, "%04X ", f->w[i]); + *(t++) = '-'; + for (i = 0; i < l->wl; ++i) + t += sprintf(t, " %04X", l->w[i]); + puts(x); +} + +/* + * Test every possible byte value. + * If the test passes or fails at this byte value we are done. + * Otherwise iterate test_nrange again, appending another byte. + */ +void test_nrange(struct testval *p) +{ + struct testval f, l, s; + apr_status_t rc; + int success = 0; + + memcpy (&s, p, sizeof(s)); + ++s.nl; + + do { + apr_size_t nl = s.nl, wl = sizeof(s.w) / 2; + rc = apr_conv_utf8_to_ucs2(s.n, &nl, s.w, &wl); + s.wl = (sizeof(s.w) / 2) - wl; + if (!nl && rc == APR_SUCCESS) { + if (!success) { + memcpy(&f, &s, sizeof(s)); + success = -1; + } + else { + if (s.wl != l.wl + || memcmp(s.w, l.w, (s.wl - 1) * 2) != 0 + || s.w[s.wl - 1] != l.w[l.wl - 1] + 1) { + displaynw(&f, &l); + memcpy(&f, &s, sizeof(s)); + } + } + memcpy(&l, &s, sizeof(s)); + } + else { + if (success) { + displaynw(&f, &l); + success = 0; + } + if (rc == APR_INCOMPLETE) { + test_nrange(&s); + } + } + } while (++s.n[s.nl - 1]); + + if (success) { + displaynw(&f, &l); + success = 0; + } +} + +/* + * Test every possible word value. + * Once we are finished, retest every possible word value. + * if the test fails on the following null word, iterate test_nrange + * again, appending another word. + * This assures the output order of the two tests are in sync. + */ +void test_wrange(struct testval *p) +{ + struct testval f, l, s; + apr_status_t rc; + int success = 0; + + memcpy (&s, p, sizeof(s)); + ++s.wl; + + do { + apr_size_t nl = sizeof(s.n), wl = s.wl; + rc = apr_conv_ucs2_to_utf8(s.w, &wl, s.n, &nl); + s.nl = sizeof(s.n) - nl; + if (!wl && rc == APR_SUCCESS) { + if (!success) { + memcpy(&f, &s, sizeof(s)); + success = -1; + } + else { + if (s.nl != l.nl + || memcmp(s.n, l.n, s.nl - 1) != 0 + || s.n[s.nl - 1] != l.n[l.nl - 1] + 1) { + displaynw(&f, &l); + memcpy(&f, &s, sizeof(s)); + } + } + memcpy(&l, &s, sizeof(s)); + } + else { + if (success) { + displaynw(&f, &l); + success = 0; + } + } + } while (++s.w[s.wl - 1]); + + if (success) { + displaynw(&f, &l); + success = 0; + } + + do { + int wl = s.wl, nl = sizeof(s.n); + rc = apr_conv_ucs2_to_utf8(s.w, &wl, s.n, &nl); + s.nl = sizeof(s.n) - s.nl; + if (rc == APR_INCOMPLETE) { + test_wrange(&s); + } + } while (++s.w[s.wl - 1]); +} + +/* + * Syntax: testucs [w|n] + * + * If arg is not recognized, run both tests. + */ +int main(int argc, char **argv) +{ + struct testval s; + memset (&s, 0, sizeof(s)); + + if (argc < 2 || apr_tolower(*argv[1]) != 'w') { + printf ("\n\nTesting Narrow Char Ranges\n"); + test_nrange(&s); + } + if (argc < 2 || apr_tolower(*argv[1]) != 'n') { + printf ("\n\nTesting Wide Char Ranges\n"); + test_wrange(&s); + } + return 0; +} diff --git a/srclib/apr/test/mod_test.c b/srclib/apr/test/mod_test.c new file mode 100644 index 0000000000..5184d78c10 --- /dev/null +++ b/srclib/apr/test/mod_test.c @@ -0,0 +1,32 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" + +void print_hello(char str[256]); +int count_reps(int reps); + +void print_hello(char str[256]) +{ + apr_cpystrn(str, "Hello - I'm a DSO!\n", strlen("Hello - I'm a DSO!\n") + 1); +} + +int count_reps(int reps) +{ + int i = 0; + for (i = 0;i < reps; i++); + return i; +} diff --git a/srclib/apr/test/nw_misc.c b/srclib/apr/test/nw_misc.c new file mode 100644 index 0000000000..cf68692bde --- /dev/null +++ b/srclib/apr/test/nw_misc.c @@ -0,0 +1,16 @@ +#include +#include +#include "testutil.h" + +void _NonAppStop( void ) +{ + pressanykey(); +} + +/* +static void test_not_impl(CuTest *tc) +{ + CuNotImpl(tc, "Test not implemented on this platform yet"); +} +*/ + diff --git a/srclib/apr/test/nwgnuaprtest b/srclib/apr/test/nwgnuaprtest new file mode 100644 index 0000000000..22b24b0849 --- /dev/null +++ b/srclib/apr/test/nwgnuaprtest @@ -0,0 +1,299 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME =aprtest +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = NLM is to test the apr layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = aprtest + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = aprtest + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = 524288 + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/aprtest.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# + +FILES_nlm_objs = \ + $(OBJDIR)/abts.o \ + $(OBJDIR)/testargs.o \ + $(OBJDIR)/testatomic.o \ + $(OBJDIR)/testdir.o \ + $(OBJDIR)/testdup.o \ + $(OBJDIR)/testdso.o \ + $(OBJDIR)/testenv.o \ + $(OBJDIR)/testfilecopy.o \ + $(OBJDIR)/testfileinfo.o \ + $(OBJDIR)/testfile.o \ + $(OBJDIR)/testflock.o \ + $(OBJDIR)/testfmt.o \ + $(OBJDIR)/testfnmatch.o \ + $(OBJDIR)/testglobalmutex.o \ + $(OBJDIR)/testhash.o \ + $(OBJDIR)/testipsub.o \ + $(OBJDIR)/testlfs.o \ + $(OBJDIR)/testlock.o \ + $(OBJDIR)/testmmap.o \ + $(OBJDIR)/testnames.o \ + $(OBJDIR)/testoc.o \ + $(OBJDIR)/testpath.o \ + $(OBJDIR)/testpipe.o \ + $(OBJDIR)/testpoll.o \ + $(OBJDIR)/testpools.o \ + $(OBJDIR)/testproc.o \ + $(OBJDIR)/testprocmutex.o \ + $(OBJDIR)/testrand.o \ + $(OBJDIR)/testrand2.o \ + $(OBJDIR)/testshm.o \ + $(OBJDIR)/testsleep.o \ + $(OBJDIR)/testsock.o \ + $(OBJDIR)/testsockets.o \ + $(OBJDIR)/testsockopt.o \ + $(OBJDIR)/teststr.o \ + $(OBJDIR)/teststrnatcmp.o \ + $(OBJDIR)/testtable.o \ + $(OBJDIR)/testtemp.o \ + $(OBJDIR)/testthread.o \ + $(OBJDIR)/testtime.o \ + $(OBJDIR)/testud.o \ + $(OBJDIR)/testuser.o \ + $(OBJDIR)/testutil.o \ + $(OBJDIR)/testvsn.o \ + $(OBJDIR)/nw_misc.o \ + $(EOLIST) + +# Pending tests + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + Libc \ + APRLIB \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @libc.imp \ + @$(APR)/aprlib.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnuglobalmutexchild b/srclib/apr/test/nwgnuglobalmutexchild new file mode 100644 index 0000000000..3d683bab50 --- /dev/null +++ b/srclib/apr/test/nwgnuglobalmutexchild @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = globalmutexchild + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = child NLM to test the global Mutex layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = globalmutexchild + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/globalmutexchild.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/globalmutexchild.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnumod_test b/srclib/apr/test/nwgnumod_test new file mode 100644 index 0000000000..3dfa6df451 --- /dev/null +++ b/srclib/apr/test/nwgnumod_test @@ -0,0 +1,257 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = mod_test + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = DSO NLM to test the apr DSO loading layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = mod_test + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/mod_test.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/mod_test.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + print_hello \ + count_reps \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnuproc_child b/srclib/apr/test/nwgnuproc_child new file mode 100644 index 0000000000..49c1fab6fa --- /dev/null +++ b/srclib/apr/test/nwgnuproc_child @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = proc_child + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = child NLM to test the proc layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = proc_child + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/proc_child.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/proc_child.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnureadchild b/srclib/apr/test/nwgnureadchild new file mode 100644 index 0000000000..0fd984da1c --- /dev/null +++ b/srclib/apr/test/nwgnureadchild @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = readchild + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = child NLM to test the pipe layer + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = readchild + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/readchild.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/readchild.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnusockchild b/srclib/apr/test/nwgnusockchild new file mode 100644 index 0000000000..16dac9e422 --- /dev/null +++ b/srclib/apr/test/nwgnusockchild @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = sockchild + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = socket NLM to test sockets + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = sockchild + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/sockchild.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/sockchild.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnutestatmc b/srclib/apr/test/nwgnutestatmc new file mode 100644 index 0000000000..dbbe4250bd --- /dev/null +++ b/srclib/apr/test/nwgnutestatmc @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME =testatmc +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = NLM is to test the atomic functions + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = testatmc + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = testatmc + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/testatmc.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/testatomic.o \ + $(OBJDIR)/nw_misc.o \ + $(EOLIST) + +# Pending tests + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + Libc \ + APRLIB \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @libc.imp \ + @$(APR)/aprlib.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/nwgnutryread b/srclib/apr/test/nwgnutryread new file mode 100644 index 0000000000..cc4aee0203 --- /dev/null +++ b/srclib/apr/test/nwgnutryread @@ -0,0 +1,255 @@ +# +# Make sure all needed macro's are defined +# + +# +# Get the 'head' of the build environment if necessary. This includes default +# targets and paths to tools +# + +ifndef EnvironmentDefined +include $(APR_WORK)\build\NWGNUhead.inc +endif + +# +# These directories will be at the beginning of the include list, followed by +# INCDIRS +# +XINCDIRS += \ + $(APR)/include \ + $(APR)/include/arch/NetWare \ + $(EOLIST) + +# +# These flags will come after CFLAGS +# +XCFLAGS += \ + $(EOLIST) + +# +# These defines will come after DEFINES +# +XDEFINES += \ + $(EOLIST) + +# +# These flags will be added to the link.opt file +# +XLFLAGS += \ + $(EOLIST) + +# +# These values will be appended to the correct variables based on the value of +# RELEASE +# +ifeq "$(RELEASE)" "debug" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + +endif + +ifeq "$(RELEASE)" "noopt" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) + + $(EOLIST) +endif + +ifeq "$(RELEASE)" "release" +XINCDIRS += \ + $(EOLIST) + +XCFLAGS += \ + $(EOLIST) + +XDEFINES += \ + $(EOLIST) + +XLFLAGS += \ + $(EOLIST) +endif + +# +# These are used by the link target if an NLM is being generated +# This is used by the link 'name' directive to name the nlm. If left blank +# TARGET_nlm (see below) will be used. +# +NLM_NAME = tryread + +# +# This is used by the link '-desc ' directive. +# If left blank, NLM_NAME will be used. +# +NLM_DESCRIPTION = reader NLM to test flock + +# +# This is used by the '-threadname' directive. If left blank, +# NLM_NAME Thread will be used. +# +NLM_THREAD_NAME = try_read + +# +# This is used by the '-screenname' directive. If left blank, +# 'Apache for NetWare' Thread will be used. +# +NLM_SCREEN_NAME = DEFAULT + +# +# If this is specified, it will override VERSION value in +# $(APR_WORK)\build\NWGNUenvironment.inc +# +NLM_VERSION = 1,0,0 + +# +# If this is specified, it will override the default of 64K +# +NLM_STACK_SIZE = + +# +# If this is specified it will be used by the link '-entry' directive +# +NLM_ENTRY_SYM = _LibCPrelude + +# +# If this is specified it will be used by the link '-exit' directive +# +NLM_EXIT_SYM = _LibCPostlude + +# +# If this is specified it will be used by the link '-check' directive +# +NLM_CHECK_SYM = + +# +# If this is specified it will be used by the link '-flags' directive +# +NLM_FLAGS = AUTOUNLOAD, PSEUDOPREEMPTION, MULTIPLE + +# +# If this is specified it will be linked in with the XDCData option in the def +# file instead of the default of $(APR)/misc/netware/apache.xdc. XDCData can +# be disabled by setting APACHE_UNIPROC in the environment +# +XDCDATA = + +# +# Declare all target files (you must add your files here) +# + +# +# If there is an NLM target, put it here +# +TARGET_nlm = \ + $(OBJDIR)/tryread.nlm \ + $(EOLIST) + +# +# If there is an LIB target, put it here +# +TARGET_lib = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the NLM target above. +# Paths must all use the '/' character +# +FILES_nlm_objs = \ + $(OBJDIR)/tryread.o \ + $(EOLIST) + +# +# These are the LIB files needed to create the NLM target above. +# These will be added as a library command in the link.opt file. +# +FILES_nlm_libs = \ + libcpre.o \ + $(EOLIST) + +# +# These are the modules that the above NLM target depends on to load. +# These will be added as a module command in the link.opt file. +# +FILES_nlm_modules = \ + aprlib \ + Libc \ + $(EOLIST) + +# +# If the nlm has a msg file, put it's path here +# +FILE_nlm_msg = + +# +# If the nlm has a hlp file put it's path here +# +FILE_nlm_hlp = + +# +# If this is specified, it will override the default copyright. +# +FILE_nlm_copyright = + +# +# Any additional imports go here +# +FILES_nlm_Ximports = \ + @$(APR)/aprlib.imp \ + @libc.imp \ + $(EOLIST) + +# +# Any symbols exported to here +# +FILES_nlm_exports = \ + $(EOLIST) + +# +# These are the OBJ files needed to create the LIB target above. +# Paths must all use the '/' character +# +FILES_lib_objs = \ + $(EOLIST) + +# +# implement targets and dependancies (leave this section alone) +# + +libs :: $(OBJDIR) $(TARGET_lib) + +nlms :: libs $(TARGET_nlm) + +# +# Updated this target to create necessary directories and copy files to the +# correct place. (See $(APR_WORK)\build\NWGNUhead.inc for examples) +# +install :: nlms FORCE + +# +# Any specialized rules here +# + +# +# Include the 'tail' makefile that has targets that depend on variables defined +# in this makefile +# + +include $(APR_WORK)\build\NWGNUtail.inc + diff --git a/srclib/apr/test/occhild.c b/srclib/apr/test/occhild.c new file mode 100644 index 0000000000..a96885d827 --- /dev/null +++ b/srclib/apr/test/occhild.c @@ -0,0 +1,26 @@ +#include "apr.h" +#include "apr_file_io.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + +int main(void) +{ + char buf[256]; + apr_file_t *err; + apr_pool_t *p; + + apr_initialize(); + atexit(apr_terminate); + + apr_pool_create(&p, NULL); + apr_file_open_stdin(&err, p); + + while (1) { + apr_size_t length = 256; + apr_file_read(err, buf, &length); + } + exit(0); /* just to keep the compiler happy */ +} diff --git a/srclib/apr/test/proc_child.c b/srclib/apr/test/proc_child.c new file mode 100644 index 0000000000..405bb7f5b6 --- /dev/null +++ b/srclib/apr/test/proc_child.c @@ -0,0 +1,21 @@ +#include "apr.h" +#include +#if APR_HAVE_UNISTD_H +#include +#endif +#if APR_HAVE_IO_H +#include +#endif +#include + +int main(void) +{ + char buf[256]; + apr_ssize_t bytes; + + bytes = read(STDIN_FILENO, buf, 256); + if (bytes > 0) + write(STDOUT_FILENO, buf, bytes); + + return 0; /* just to keep the compiler happy */ +} diff --git a/srclib/apr/test/readchild.c b/srclib/apr/test/readchild.c new file mode 100644 index 0000000000..82ef82f667 --- /dev/null +++ b/srclib/apr/test/readchild.c @@ -0,0 +1,46 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "apr_file_io.h" + +int main(int argc, char *argv[]) +{ + apr_file_t *in, *out; + apr_size_t nbytes, total_bytes; + apr_pool_t *p; + char buf[128]; + apr_status_t rv; + + apr_initialize(); + atexit(apr_terminate); + apr_pool_create(&p, NULL); + + apr_file_open_stdin(&in, p); + apr_file_open_stdout(&out, p); + + total_bytes = 0; + nbytes = sizeof(buf); + while ((rv = apr_file_read(in, buf, &nbytes)) == APR_SUCCESS) { + total_bytes += nbytes; + nbytes = sizeof(buf); + } + + apr_file_printf(out, "%" APR_SIZE_T_FMT " bytes were read\n", + total_bytes); + return 0; +} diff --git a/srclib/apr/test/sendfile.c b/srclib/apr/test/sendfile.c new file mode 100644 index 0000000000..efe1b89186 --- /dev/null +++ b/srclib/apr/test/sendfile.c @@ -0,0 +1,757 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_poll.h" + +#if !APR_HAS_SENDFILE +int main(void) +{ + fprintf(stderr, + "This program won't work on this platform because there is no " + "support for sendfile().\n"); + return 0; +} +#else /* !APR_HAS_SENDFILE */ + +#define FILE_LENGTH 200000 + +#define FILE_DATA_CHAR '0' + +#define HDR1 "1234567890ABCD\n" +#define HDR2 "EFGH\n" +#define HDR3_LEN 80000 +#define HDR3_CHAR '^' +#define TRL1 "IJKLMNOPQRSTUVWXYZ\n" +#define TRL2 "!@#$%&*()\n" +#define TRL3_LEN 90000 +#define TRL3_CHAR '@' + +#define TESTSF_PORT 8021 + +#define TESTFILE "testsf.dat" + +typedef enum {BLK, NONBLK, TIMEOUT} client_socket_mode_t; + +static void apr_setup(apr_pool_t **p, apr_socket_t **sock, int *family) +{ + char buf[120]; + apr_status_t rv; + + rv = apr_initialize(); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_initialize()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + atexit(apr_terminate); + + rv = apr_pool_create(p, NULL); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_pool_create()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + *sock = NULL; + rv = apr_socket_create(sock, *family, SOCK_STREAM, 0, *p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_create()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + if (*family == APR_UNSPEC) { + apr_sockaddr_t *localsa; + + rv = apr_socket_addr_get(&localsa, APR_LOCAL, *sock); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_addr_get()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + *family = localsa->family; + } +} + +static void create_testfile(apr_pool_t *p, const char *fname) +{ + apr_file_t *f = NULL; + apr_status_t rv; + char buf[120]; + int i; + apr_finfo_t finfo; + + printf("Creating a test file...\n"); + rv = apr_file_open(&f, fname, + APR_CREATE | APR_WRITE | APR_TRUNCATE | APR_BUFFERED, + APR_UREAD | APR_UWRITE, p); + if (rv) { + fprintf(stderr, "apr_file_open()->%d/%s\n", + rv, apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + buf[0] = FILE_DATA_CHAR; + buf[1] = '\0'; + for (i = 0; i < FILE_LENGTH; i++) { + /* exercise apr_file_putc() and apr_file_puts() on buffered files */ + if ((i % 2) == 0) { + rv = apr_file_putc(buf[0], f); + if (rv) { + fprintf(stderr, "apr_file_putc()->%d/%s\n", + rv, apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + } + else { + rv = apr_file_puts(buf, f); + if (rv) { + fprintf(stderr, "apr_file_puts()->%d/%s\n", + rv, apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + } + } + + rv = apr_file_close(f); + if (rv) { + fprintf(stderr, "apr_file_close()->%d/%s\n", + rv, apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + rv = apr_stat(&finfo, fname, APR_FINFO_NORM, p); + if (rv != APR_SUCCESS && rv != APR_INCOMPLETE) { + fprintf(stderr, "apr_stat()->%d/%s\n", + rv, apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + if (finfo.size != FILE_LENGTH) { + fprintf(stderr, + "test file %s should be %ld-bytes long\n" + "instead it is %ld-bytes long\n", + fname, + (long int)FILE_LENGTH, + (long int)finfo.size); + exit(1); + } +} + +static int client(client_socket_mode_t socket_mode, char *host) +{ + apr_status_t rv, tmprv; + apr_socket_t *sock; + apr_pool_t *p; + char buf[120]; + apr_file_t *f = NULL; + apr_size_t len; + apr_size_t expected_len; + apr_off_t current_file_offset; + apr_hdtr_t hdtr; + struct iovec headers[3]; + struct iovec trailers[3]; + apr_size_t bytes_read; + apr_pollset_t *pset; + apr_int32_t nsocks; + int i; + int family; + apr_sockaddr_t *destsa; + + family = APR_INET; + apr_setup(&p, &sock, &family); + create_testfile(p, TESTFILE); + + rv = apr_file_open(&f, TESTFILE, APR_READ, 0, p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_file_open()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + if (!host) { + host = "127.0.0.1"; + } + rv = apr_sockaddr_info_get(&destsa, host, family, TESTSF_PORT, 0, p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + rv = apr_socket_connect(sock, destsa); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_connect()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + switch(socket_mode) { + case BLK: + /* leave it blocking */ + break; + case NONBLK: + /* set it non-blocking */ + rv = apr_socket_opt_set(sock, APR_SO_NONBLOCK, 1); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + break; + case TIMEOUT: + /* set a timeout */ + rv = apr_socket_timeout_set(sock, 100 * APR_USEC_PER_SEC); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_opt_set(APR_SO_NONBLOCK)->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + break; + default: + assert(1 != 1); + } + + printf("Sending the file...\n"); + + hdtr.headers = headers; + hdtr.numheaders = 3; + hdtr.headers[0].iov_base = HDR1; + hdtr.headers[0].iov_len = strlen(hdtr.headers[0].iov_base); + hdtr.headers[1].iov_base = HDR2; + hdtr.headers[1].iov_len = strlen(hdtr.headers[1].iov_base); + hdtr.headers[2].iov_base = malloc(HDR3_LEN); + assert(hdtr.headers[2].iov_base); + memset(hdtr.headers[2].iov_base, HDR3_CHAR, HDR3_LEN); + hdtr.headers[2].iov_len = HDR3_LEN; + + hdtr.trailers = trailers; + hdtr.numtrailers = 3; + hdtr.trailers[0].iov_base = TRL1; + hdtr.trailers[0].iov_len = strlen(hdtr.trailers[0].iov_base); + hdtr.trailers[1].iov_base = TRL2; + hdtr.trailers[1].iov_len = strlen(hdtr.trailers[1].iov_base); + hdtr.trailers[2].iov_base = malloc(TRL3_LEN); + memset(hdtr.trailers[2].iov_base, TRL3_CHAR, TRL3_LEN); + assert(hdtr.trailers[2].iov_base); + hdtr.trailers[2].iov_len = TRL3_LEN; + + expected_len = + strlen(HDR1) + strlen(HDR2) + HDR3_LEN + + strlen(TRL1) + strlen(TRL2) + TRL3_LEN + + FILE_LENGTH; + + if (socket_mode == BLK) { + current_file_offset = 0; + len = FILE_LENGTH; + rv = apr_socket_sendfile(sock, f, &hdtr, ¤t_file_offset, &len, 0); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_sendfile()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + printf("apr_socket_sendfile() updated offset with %ld\n", + (long int)current_file_offset); + + printf("apr_socket_sendfile() updated len with %ld\n", + (long int)len); + + printf("bytes really sent: %" APR_SIZE_T_FMT "\n", + expected_len); + + if (len != expected_len) { + fprintf(stderr, "apr_socket_sendfile() didn't report the correct " + "number of bytes sent!\n"); + exit(1); + } + } + else { + /* non-blocking... wooooooo */ + apr_size_t total_bytes_sent; + apr_pollfd_t pfd; + + pset = NULL; + rv = apr_pollset_create(&pset, 1, p, 0); + assert(!rv); + pfd.p = p; + pfd.desc_type = APR_POLL_SOCKET; + pfd.reqevents = APR_POLLOUT; + pfd.rtnevents = 0; + pfd.desc.s = sock; + pfd.client_data = NULL; + + rv = apr_pollset_add(pset, &pfd); + assert(!rv); + + total_bytes_sent = 0; + current_file_offset = 0; + len = FILE_LENGTH; + do { + apr_size_t tmplen; + + tmplen = len; /* bytes remaining to send from the file */ + printf("Calling apr_socket_sendfile()...\n"); + printf("Headers (%d):\n", hdtr.numheaders); + for (i = 0; i < hdtr.numheaders; i++) { + printf("\t%ld bytes (%c)\n", + (long)hdtr.headers[i].iov_len, + *(char *)hdtr.headers[i].iov_base); + } + printf("File: %ld bytes from offset %ld\n", + (long)tmplen, (long)current_file_offset); + printf("Trailers (%d):\n", hdtr.numtrailers); + for (i = 0; i < hdtr.numtrailers; i++) { + printf("\t%ld bytes\n", + (long)hdtr.trailers[i].iov_len); + } + + rv = apr_socket_sendfile(sock, f, &hdtr, ¤t_file_offset, &tmplen, 0); + printf("apr_socket_sendfile()->%d, sent %ld bytes\n", rv, (long)tmplen); + if (rv) { + if (APR_STATUS_IS_EAGAIN(rv)) { + assert(tmplen == 0); + nsocks = 1; + tmprv = apr_pollset_poll(pset, -1, &nsocks, NULL); + assert(!tmprv); + assert(nsocks == 1); + /* continue; */ + } + } + + total_bytes_sent += tmplen; + + /* Adjust hdtr to compensate for partially-written + * data. + */ + + /* First, skip over any header data which might have + * been written. + */ + while (tmplen && hdtr.numheaders) { + if (tmplen >= hdtr.headers[0].iov_len) { + tmplen -= hdtr.headers[0].iov_len; + --hdtr.numheaders; + ++hdtr.headers; + } + else { + hdtr.headers[0].iov_len -= tmplen; + hdtr.headers[0].iov_base = + (char*) hdtr.headers[0].iov_base + tmplen; + tmplen = 0; + } + } + + /* Now, skip over any file data which might have been + * written. + */ + + if (tmplen <= len) { + current_file_offset += tmplen; + len -= tmplen; + tmplen = 0; + } + else { + tmplen -= len; + len = 0; + current_file_offset = 0; + } + + /* Last, skip over any trailer data which might have + * been written. + */ + + while (tmplen && hdtr.numtrailers) { + if (tmplen >= hdtr.trailers[0].iov_len) { + tmplen -= hdtr.trailers[0].iov_len; + --hdtr.numtrailers; + ++hdtr.trailers; + } + else { + hdtr.trailers[0].iov_len -= tmplen; + hdtr.trailers[0].iov_base = + (char *)hdtr.trailers[0].iov_base + tmplen; + tmplen = 0; + } + } + + } while (total_bytes_sent < expected_len && + (rv == APR_SUCCESS || + (APR_STATUS_IS_EAGAIN(rv) && socket_mode != TIMEOUT))); + if (total_bytes_sent != expected_len) { + fprintf(stderr, + "client problem: sent %ld of %ld bytes\n", + (long)total_bytes_sent, (long)expected_len); + exit(1); + } + + if (rv) { + fprintf(stderr, + "client problem: rv %d\n", + rv); + exit(1); + } + } + + current_file_offset = 0; + rv = apr_file_seek(f, APR_CUR, ¤t_file_offset); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_file_seek()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + printf("After apr_socket_sendfile(), the kernel file pointer is " + "at offset %ld.\n", + (long int)current_file_offset); + + rv = apr_socket_shutdown(sock, APR_SHUTDOWN_WRITE); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_shutdown()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + /* in case this is the non-blocking test, set socket timeout; + * we're just waiting for EOF */ + + rv = apr_socket_timeout_set(sock, apr_time_from_sec(3)); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_timeout_set()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + bytes_read = 1; + rv = apr_socket_recv(sock, buf, &bytes_read); + if (rv != APR_EOF) { + fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != 0) { + fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n" + "but instead we read %ld bytes.\n", + (long int)bytes_read); + exit(1); + } + + printf("client: apr_socket_sendfile() worked as expected!\n"); + + rv = apr_file_remove(TESTFILE, p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_file_remove()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + return 0; +} + +static int server(void) +{ + apr_status_t rv; + apr_socket_t *sock; + apr_pool_t *p; + char buf[120]; + int i; + apr_socket_t *newsock = NULL; + apr_size_t bytes_read; + apr_sockaddr_t *localsa; + int family; + + family = APR_UNSPEC; + apr_setup(&p, &sock, &family); + + rv = apr_socket_opt_set(sock, APR_SO_REUSEADDR, 1); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_opt_set()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + rv = apr_sockaddr_info_get(&localsa, NULL, family, TESTSF_PORT, 0, p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_sockaddr_info_get()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + rv = apr_socket_bind(sock, localsa); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_bind()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + rv = apr_socket_listen(sock, 5); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_listen()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + printf("Waiting for a client to connect...\n"); + + rv = apr_socket_accept(&newsock, sock, p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_accept()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + + printf("Processing a client...\n"); + + assert(sizeof buf > strlen(HDR1)); + bytes_read = strlen(HDR1); + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != strlen(HDR1)) { + fprintf(stderr, "wrong data read (1)\n"); + exit(1); + } + if (memcmp(buf, HDR1, strlen(HDR1))) { + fprintf(stderr, "wrong data read (2)\n"); + fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n", + (int)bytes_read, buf, HDR1); + exit(1); + } + + assert(sizeof buf > strlen(HDR2)); + bytes_read = strlen(HDR2); + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != strlen(HDR2)) { + fprintf(stderr, "wrong data read (3)\n"); + exit(1); + } + if (memcmp(buf, HDR2, strlen(HDR2))) { + fprintf(stderr, "wrong data read (4)\n"); + fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n", + (int)bytes_read, buf, HDR2); + exit(1); + } + + for (i = 0; i < HDR3_LEN; i++) { + bytes_read = 1; + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != 1) { + fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n", + (long int)bytes_read); + exit(1); + } + if (buf[0] != HDR3_CHAR) { + fprintf(stderr, + "problem with data read (byte %d of hdr 3):\n", + i); + fprintf(stderr, "read `%c' (0x%x) from client; expected " + "`%c'\n", + buf[0], buf[0], HDR3_CHAR); + exit(1); + } + } + + for (i = 0; i < FILE_LENGTH; i++) { + bytes_read = 1; + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != 1) { + fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n", + (long int)bytes_read); + exit(1); + } + if (buf[0] != FILE_DATA_CHAR) { + fprintf(stderr, + "problem with data read (byte %d of file):\n", + i); + fprintf(stderr, "read `%c' (0x%x) from client; expected " + "`%c'\n", + buf[0], buf[0], FILE_DATA_CHAR); + exit(1); + } + } + + assert(sizeof buf > strlen(TRL1)); + bytes_read = strlen(TRL1); + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != strlen(TRL1)) { + fprintf(stderr, "wrong data read (5)\n"); + exit(1); + } + if (memcmp(buf, TRL1, strlen(TRL1))) { + fprintf(stderr, "wrong data read (6)\n"); + fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n", + (int)bytes_read, buf, TRL1); + exit(1); + } + + assert(sizeof buf > strlen(TRL2)); + bytes_read = strlen(TRL2); + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != strlen(TRL2)) { + fprintf(stderr, "wrong data read (7)\n"); + exit(1); + } + if (memcmp(buf, TRL2, strlen(TRL2))) { + fprintf(stderr, "wrong data read (8)\n"); + fprintf(stderr, "received: `%.*s'\nexpected: `%s'\n", + (int)bytes_read, buf, TRL2); + exit(1); + } + + for (i = 0; i < TRL3_LEN; i++) { + bytes_read = 1; + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_socket_recv()->%d/%s\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != 1) { + fprintf(stderr, "apr_socket_recv()->%ld bytes instead of 1\n", + (long int)bytes_read); + exit(1); + } + if (buf[0] != TRL3_CHAR) { + fprintf(stderr, + "problem with data read (byte %d of trl 3):\n", + i); + fprintf(stderr, "read `%c' (0x%x) from client; expected " + "`%c'\n", + buf[0], buf[0], TRL3_CHAR); + exit(1); + } + } + + bytes_read = 1; + rv = apr_socket_recv(newsock, buf, &bytes_read); + if (rv != APR_EOF) { + fprintf(stderr, "apr_socket_recv()->%d/%s (expected APR_EOF)\n", + rv, + apr_strerror(rv, buf, sizeof buf)); + exit(1); + } + if (bytes_read != 0) { + fprintf(stderr, "We expected to get 0 bytes read with APR_EOF\n" + "but instead we read %ld bytes (%c).\n", + (long int)bytes_read, buf[0]); + exit(1); + } + + printf("server: apr_socket_sendfile() worked as expected!\n"); + + return 0; +} + +int main(int argc, char *argv[]) +{ +#ifdef SIGPIPE + signal(SIGPIPE, SIG_IGN); +#endif + + /* Gee whiz this is goofy logic but I wanna drive sendfile right now, + * not dork around with the command line! + */ + if (argc >= 3 && !strcmp(argv[1], "client")) { + char *host = 0; + if (argv[3]) { + host = argv[3]; + } + if (!strcmp(argv[2], "blocking")) { + return client(BLK, host); + } + else if (!strcmp(argv[2], "timeout")) { + return client(TIMEOUT, host); + } + else if (!strcmp(argv[2], "nonblocking")) { + return client(NONBLK, host); + } + } + else if (argc == 2 && !strcmp(argv[1], "server")) { + return server(); + } + + fprintf(stderr, + "Usage: %s client {blocking|nonblocking|timeout}\n" + " %s server\n", + argv[0], argv[0]); + return -1; +} + +#endif /* !APR_HAS_SENDFILE */ diff --git a/srclib/apr/test/sockchild.c b/srclib/apr/test/sockchild.c new file mode 100644 index 0000000000..c81ec4a3fb --- /dev/null +++ b/srclib/apr/test/sockchild.c @@ -0,0 +1,80 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "testsock.h" +#include "apr_network_io.h" +#include "apr_pools.h" + +int main(int argc, char *argv[]) +{ + apr_pool_t *p; + apr_socket_t *sock; + apr_status_t rv; + apr_sockaddr_t *remote_sa; + + apr_initialize(); + atexit(apr_terminate); + apr_pool_create(&p, NULL); + + if (argc < 2) { + exit(-1); + } + + rv = apr_sockaddr_info_get(&remote_sa, "127.0.0.1", APR_UNSPEC, 8021, 0, p); + if (rv != APR_SUCCESS) { + exit(-1); + } + + if (apr_socket_create(&sock, remote_sa->family, SOCK_STREAM, 0, + p) != APR_SUCCESS) { + exit(-1); + } + + rv = apr_socket_timeout_set(sock, apr_time_from_sec(3)); + if (rv) { + exit(-1); + } + + apr_socket_connect(sock, remote_sa); + + if (!strcmp("read", argv[1])) { + char datarecv[STRLEN]; + apr_size_t length = STRLEN; + apr_status_t rv; + + memset(datarecv, 0, STRLEN); + rv = apr_socket_recv(sock, datarecv, &length); + apr_socket_close(sock); + if (APR_STATUS_IS_TIMEUP(rv)) { + exit(SOCKET_TIMEOUT); + } + + if (strcmp(datarecv, DATASTR)) { + exit(-1); + } + + exit(length); + } + else if (!strcmp("write", argv[1])) { + apr_size_t length = strlen(DATASTR); + apr_socket_send(sock, DATASTR, &length); + + apr_socket_close(sock); + exit(length); + } + exit(-1); +} diff --git a/srclib/apr/test/testall.dsp b/srclib/apr/test/testall.dsp new file mode 100644 index 0000000000..2b971d9452 --- /dev/null +++ b/srclib/apr/test/testall.dsp @@ -0,0 +1,257 @@ +# Microsoft Developer Studio Project File - Name="testall" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) External Target" 0x0106 + +CFG=testall - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testall.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testall.mak" CFG="testall - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testall - Win32 Release" (based on "Win32 (x86) External Target") +!MESSAGE "testall - Win32 Debug" (based on "Win32 (x86) External Target") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" + +!IF "$(CFG)" == "testall - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "" +# PROP BASE Cmd_Line "NMAKE /f Makefile.win all" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "testall.exe" +# PROP BASE Bsc_Name "testall.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Cmd_Line "NMAKE /f Makefile.win all" +# PROP Rebuild_Opt "/a" +# PROP Target_File "testall.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "testall - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "" +# PROP BASE Intermediate_Dir "" +# PROP BASE Cmd_Line "NMAKE /f Makefile.win all" +# PROP BASE Rebuild_Opt "/a" +# PROP BASE Target_File "testall.exe" +# PROP BASE Bsc_Name "testall.bsc" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "" +# PROP Intermediate_Dir "" +# PROP Cmd_Line "NMAKE /f Makefile.win all" +# PROP Rebuild_Opt "/a" +# PROP Target_File "testall.exe" +# PROP Bsc_Name "" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "testall - Win32 Release" +# Name "testall - Win32 Debug" + +!IF "$(CFG)" == "testall - Win32 Release" + +!ELSEIF "$(CFG)" == "testall - Win32 Debug" + +!ENDIF + +# Begin Source File + +SOURCE=.\Makefile.win +# End Source File +# Begin Source File + +SOURCE=.\testall.c +# End Source File +# Begin Source File + +SOURCE=.\testapp.c +# End Source File +# Begin Source File + +SOURCE=.\testargs.c +# End Source File +# Begin Source File + +SOURCE=.\testatomic.c +# End Source File +# Begin Source File + +SOURCE=.\testdir.c +# End Source File +# Begin Source File + +SOURCE=.\testdso.c +# End Source File +# Begin Source File + +SOURCE=.\testdup.c +# End Source File +# Begin Source File + +SOURCE=.\testfile.c +# End Source File +# Begin Source File + +SOURCE=.\testfileinfo.c +# End Source File +# Begin Source File + +SOURCE=.\testflock.c +# End Source File +# Begin Source File + +SOURCE=.\testfmt.c +# End Source File +# Begin Source File + +SOURCE=.\testglobalmutex.c +# End Source File +# Begin Source File + +SOURCE=.\testhash.c +# End Source File +# Begin Source File + +SOURCE=.\testipsub.c +# End Source File +# Begin Source File + +SOURCE=.\testlock.c +# End Source File +# Begin Source File + +SOURCE=.\testlockperf.c +# End Source File +# Begin Source File + +SOURCE=.\testmmap.c +# End Source File +# Begin Source File + +SOURCE=.\testmutexscope.c +# End Source File +# Begin Source File + +SOURCE=.\testnames.c +# End Source File +# Begin Source File + +SOURCE=.\testoc.c +# End Source File +# Begin Source File + +SOURCE=.\testpath.c +# End Source File +# Begin Source File + +SOURCE=.\testpipe.c +# End Source File +# Begin Source File + +SOURCE=.\testpoll.c +# End Source File +# Begin Source File + +SOURCE=.\testpools.c +# End Source File +# Begin Source File + +SOURCE=.\testproc.c +# End Source File +# Begin Source File + +SOURCE=.\testprocmutex.c +# End Source File +# Begin Source File + +SOURCE=.\testrand.c +# End Source File +# Begin Source File + +SOURCE=.\testrand2.c +# End Source File +# Begin Source File + +SOURCE=.\testshm.c +# End Source File +# Begin Source File + +SOURCE=.\testshmconsumer.c +# End Source File +# Begin Source File + +SOURCE=.\testshmproducer.c +# End Source File +# Begin Source File + +SOURCE=.\testsleep.c +# End Source File +# Begin Source File + +SOURCE=.\testsock.c +# End Source File +# Begin Source File + +SOURCE=.\testsockets.c +# End Source File +# Begin Source File + +SOURCE=.\testsockopt.c +# End Source File +# Begin Source File + +SOURCE=.\teststr.c +# End Source File +# Begin Source File + +SOURCE=.\testtable.c +# End Source File +# Begin Source File + +SOURCE=.\testthread.c +# End Source File +# Begin Source File + +SOURCE=.\testtime.c +# End Source File +# Begin Source File + +SOURCE=.\testud.c +# End Source File +# Begin Source File + +SOURCE=.\testuser.c +# End Source File +# Begin Source File + +SOURCE=.\testvsn.c +# End Source File +# End Target +# End Project diff --git a/srclib/apr/test/testall.dsw b/srclib/apr/test/testall.dsw new file mode 100644 index 0000000000..f4be05d975 --- /dev/null +++ b/srclib/apr/test/testall.dsw @@ -0,0 +1,122 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "apr"="..\apr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "apr_app"="..\build\apr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency +}}} + +############################################################################### + +Project: "testall"=".\testall.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency +}}} + +############################################################################### + +Project: "libapr"="..\libapr.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libapr_app"="..\build\libapr_app.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libapr + End Project Dependency +}}} + +############################################################################### + +Project: "testapp"=".\testapp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency + Begin Project Dependency + Project_Dep_Name apr_app + End Project Dependency +}}} + +############################################################################### + +Project: "testappnt"=".\testappnt.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name apr + End Project Dependency + Begin Project Dependency + Project_Dep_Name apr_app + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/srclib/apr/test/testapp.c b/srclib/apr/test/testapp.c new file mode 100644 index 0000000000..77607aa388 --- /dev/null +++ b/srclib/apr/test/testapp.c @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, const char * const * argv, const char * const *env) +{ + apr_app_initialize(&argc, &argv, &env); + + + apr_terminate(); +} diff --git a/srclib/apr/test/testapp.dsp b/srclib/apr/test/testapp.dsp new file mode 100644 index 0000000000..9c7733dd38 --- /dev/null +++ b/srclib/apr/test/testapp.dsp @@ -0,0 +1,90 @@ +# Microsoft Developer Studio Project File - Name="testapp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testapp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testapp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testapp.mak" CFG="testapp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testapp - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testapp - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testapp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../include" /D "NDEBUG" /D "WIN32" /D "_CONSOLE" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /Fd"./testapp" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "testapp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "." +# PROP BASE Intermediate_Dir "." +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "." +# PROP Intermediate_Dir "." +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../include" /D "_DEBUG" /D "WIN32" /D "_CONSOLE" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /Fd"./testapp" /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "testapp - Win32 Release" +# Name "testapp - Win32 Debug" +# Begin Source File + +SOURCE=.\testapp.c +# End Source File +# End Target +# End Project diff --git a/srclib/apr/test/testappnt.dsp b/srclib/apr/test/testappnt.dsp new file mode 100644 index 0000000000..54aa698cab --- /dev/null +++ b/srclib/apr/test/testappnt.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="testappnt" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=testappnt - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "testappnt.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "testappnt.mak" CFG="testappnt - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "testappnt - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "testappnt - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "testappnt - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MD /W3 /O2 /D "WIN32" /D "WINNT" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../include" /D "NDEBUG" /D "WIN32" /D "WINNT" /D "_CONSOLE" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /Fd"./testappnt" /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /entry:"wmainCRTStartup" /subsystem:console /machine:I386 + +!ELSEIF "$(CFG)" == "testappnt - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "." +# PROP BASE Intermediate_Dir "." +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "." +# PROP Intermediate_Dir "." +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MDd /W3 /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /FD /c +# ADD CPP /nologo /MDd /W3 /GX /Zi /Od /I "../include" /D "_DEBUG" /D "WIN32" /D "WINNT" /D "_CONSOLE" /D "APR_DECLARE_STATIC" /D "APU_DECLARE_STATIC" /Fd"./testappnt" /FD /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /subsystem:console /incremental:no /debug /machine:I386 +# ADD LINK32 kernel32.lib advapi32.lib wsock32.lib ws2_32.lib /nologo /entry:"wmainCRTStartup" /subsystem:console /incremental:no /debug /machine:I386 + +!ENDIF + +# Begin Target + +# Name "testappnt - Win32 Release" +# Name "testappnt - Win32 Debug" +# Begin Source File + +SOURCE=.\testapp.c + +!IF "$(CFG)" == "testappnt - Win32 Release" + +# ADD CPP /Fo"testappnt" + +!ELSEIF "$(CFG)" == "testappnt - Win32 Debug" + +# ADD CPP /Fo"testappnt" + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/srclib/apr/test/testargs.c b/srclib/apr/test/testargs.c new file mode 100644 index 0000000000..9dc68beb50 --- /dev/null +++ b/srclib/apr/test/testargs.c @@ -0,0 +1,236 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_getopt.h" +#include "apr_strings.h" +#include "testutil.h" + +static void format_arg(char *str, char option, const char *arg) +{ + if (arg) { + apr_snprintf(str, 8196, "%soption: %c with %s\n", str, option, arg); + } + else { + apr_snprintf(str, 8196, "%soption: %c\n", str, option); + } +} + +static void unknown_arg(void *str, const char *err, ...) +{ + va_list va; + + va_start(va, err); + apr_vsnprintf(str, 8196, err, va); + va_end(va); +} + +static void no_options_found(abts_case *tc, void *data) +{ + int largc = 5; + const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + while (apr_getopt(opt, "abcd", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + case 'b': + case 'c': + case 'd': + default: + format_arg(str, ch, optarg); + } + } + ABTS_STR_EQUAL(tc, "option: a\n" + "option: b\n" + "option: c\n" + "option: d\n", str); +} + +static void no_options(abts_case *tc, void *data) +{ + int largc = 5; + const char * const largv[] = {"testprog", "-a", "-b", "-c", "-d"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + opt->errfn = unknown_arg; + opt->errarg = str; + + while (apr_getopt(opt, "efgh", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + case 'b': + case 'c': + case 'd': + format_arg(str, ch, optarg); + break; + default: + break; + } + } + ABTS_STR_EQUAL(tc, "testprog: illegal option -- a\n", str); +} + +static void required_option(abts_case *tc, void *data) +{ + int largc = 3; + const char * const largv[] = {"testprog", "-a", "foo"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + opt->errfn = unknown_arg; + opt->errarg = str; + + while (apr_getopt(opt, "a:", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + format_arg(str, ch, optarg); + break; + default: + break; + } + } + ABTS_STR_EQUAL(tc, "option: a with foo\n", str); +} + +static void required_option_notgiven(abts_case *tc, void *data) +{ + int largc = 2; + const char * const largv[] = {"testprog", "-a"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + opt->errfn = unknown_arg; + opt->errarg = str; + + while (apr_getopt(opt, "a:", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + format_arg(str, ch, optarg); + break; + default: + break; + } + } + ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str); +} + +static void optional_option(abts_case *tc, void *data) +{ + int largc = 3; + const char * const largv[] = {"testprog", "-a", "foo"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + opt->errfn = unknown_arg; + opt->errarg = str; + + while (apr_getopt(opt, "a::", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + format_arg(str, ch, optarg); + break; + default: + break; + } + } + ABTS_STR_EQUAL(tc, "option: a with foo\n", str); +} + +static void optional_option_notgiven(abts_case *tc, void *data) +{ + int largc = 2; + const char * const largv[] = {"testprog", "-a"}; + apr_getopt_t *opt; + apr_status_t rv; + char ch; + const char *optarg; + char str[8196]; + + str[0] = '\0'; + rv = apr_getopt_init(&opt, p, largc, largv); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + opt->errfn = unknown_arg; + opt->errarg = str; + + while (apr_getopt(opt, "a::", &ch, &optarg) == APR_SUCCESS) { + switch (ch) { + case 'a': + format_arg(str, ch, optarg); + break; + default: + break; + } + } +#if 0 +/* Our version of getopt doesn't allow for optional arguments. */ + ABTS_STR_EQUAL(tc, "option: a\n", str); +#endif + ABTS_STR_EQUAL(tc, "testprog: option requires an argument -- a\n", str); +} + +abts_suite *testgetopt(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, no_options, NULL); + abts_run_test(suite, no_options_found, NULL); + abts_run_test(suite, required_option, NULL); + abts_run_test(suite, required_option_notgiven, NULL); + abts_run_test(suite, optional_option, NULL); + abts_run_test(suite, optional_option_notgiven, NULL); + + return suite; +} diff --git a/srclib/apr/test/testatomic.c b/srclib/apr/test/testatomic.c new file mode 100644 index 0000000000..95f31119c7 --- /dev/null +++ b/srclib/apr/test/testatomic.c @@ -0,0 +1,305 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_strings.h" +#include "apr_thread_proc.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_atomic.h" +#include "apr_time.h" + +/* Use pthread_setconcurrency where it is available and not a nullop, + * i.e. platforms using M:N or M:1 thread models: */ +#if APR_HAS_THREADS && \ + ((defined(SOLARIS2) && SOLARIS2 > 26) || defined(_AIX)) +/* also HP-UX, IRIX? ... */ +#define HAVE_PTHREAD_SETCONCURRENCY +#endif + +#ifdef HAVE_PTHREAD_SETCONCURRENCY +#include +#endif + +static void test_init(abts_case *tc, void *data) +{ + APR_ASSERT_SUCCESS(tc, "Could not initliaze atomics", apr_atomic_init(p)); +} + +static void test_set32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + ABTS_INT_EQUAL(tc, 2, y32); +} + +static void test_read32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_atomic_set32(&y32, 2); + ABTS_INT_EQUAL(tc, 2, apr_atomic_read32(&y32)); +} + +static void test_dec32(abts_case *tc, void *data) +{ + apr_uint32_t y32; + int rv; + + apr_atomic_set32(&y32, 2); + + rv = apr_atomic_dec32(&y32); + ABTS_INT_EQUAL(tc, 1, y32); + ABTS_ASSERT(tc, "atomic_dec returned zero when it shouldn't", rv != 0); + + rv = apr_atomic_dec32(&y32); + ABTS_INT_EQUAL(tc, 0, y32); + ABTS_ASSERT(tc, "atomic_dec didn't returned zero when it should", rv == 0); +} + +static void test_xchg32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 100); + oldval = apr_atomic_xchg32(&y32, 50); + + ABTS_INT_EQUAL(tc, 100, oldval); + ABTS_INT_EQUAL(tc, 50, y32); +} + +static void test_cas_equal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 0; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 12, 0); + ABTS_INT_EQUAL(tc, 0, oldval); + ABTS_INT_EQUAL(tc, 12, casval); +} + +static void test_cas_equal_nonnull(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 12); + ABTS_INT_EQUAL(tc, 12, oldval); + ABTS_INT_EQUAL(tc, 23, casval); +} + +static void test_cas_notequal(abts_case *tc, void *data) +{ + apr_uint32_t casval = 12; + apr_uint32_t oldval; + + oldval = apr_atomic_cas32(&casval, 23, 2); + ABTS_INT_EQUAL(tc, 12, oldval); + ABTS_INT_EQUAL(tc, 12, casval); +} + +static void test_add32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_add32(&y32, 4); + ABTS_INT_EQUAL(tc, 23, oldval); + ABTS_INT_EQUAL(tc, 27, y32); +} + +static void test_inc32(abts_case *tc, void *data) +{ + apr_uint32_t oldval; + apr_uint32_t y32; + + apr_atomic_set32(&y32, 23); + oldval = apr_atomic_inc32(&y32); + ABTS_INT_EQUAL(tc, 23, oldval); + ABTS_INT_EQUAL(tc, 24, y32); +} + +static void test_set_add_inc_sub(abts_case *tc, void *data) +{ + apr_uint32_t y32; + + apr_atomic_set32(&y32, 0); + apr_atomic_add32(&y32, 20); + apr_atomic_inc32(&y32); + apr_atomic_sub32(&y32, 10); + + ABTS_INT_EQUAL(tc, 11, y32); +} + +static void test_wrap_zero(abts_case *tc, void *data) +{ + apr_uint32_t y32; + apr_uint32_t rv; + apr_uint32_t minus1 = -1; + char *str; + + apr_atomic_set32(&y32, 0); + rv = apr_atomic_dec32(&y32); + + ABTS_ASSERT(tc, "apr_atomic_dec32 on zero returned zero.", rv != 0); + str = apr_psprintf(p, "zero wrap failed: 0 - 1 = %d", y32); + ABTS_ASSERT(tc, str, y32 == minus1); +} + +static void test_inc_neg1(abts_case *tc, void *data) +{ + apr_uint32_t y32 = -1; + apr_uint32_t minus1 = -1; + apr_uint32_t rv; + char *str; + + rv = apr_atomic_inc32(&y32); + + ABTS_ASSERT(tc, "apr_atomic_dec32 on zero returned zero.", rv == minus1); + str = apr_psprintf(p, "zero wrap failed: -1 + 1 = %d", y32); + ABTS_ASSERT(tc, str, y32 == 0); +} + + +#if APR_HAS_THREADS + +void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data); +void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data); +void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data); + +apr_thread_mutex_t *thread_lock; +volatile apr_uint32_t x = 0; /* mutex locks */ +volatile apr_uint32_t y = 0; /* atomic operations */ +volatile apr_uint32_t z = 0; /* no locks */ +apr_status_t exit_ret_val = 123; /* just some made up number to check on later */ + +#define NUM_THREADS 40 +#define NUM_ITERATIONS 20000 +void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < NUM_ITERATIONS; i++) { + apr_thread_mutex_lock(thread_lock); + x++; + apr_thread_mutex_unlock(thread_lock); + } + apr_thread_exit(thd, exit_ret_val); + return NULL; +} + +void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < NUM_ITERATIONS ; i++) { + apr_atomic_inc32(&y); + apr_atomic_add32(&y, 2); + apr_atomic_dec32(&y); + apr_atomic_dec32(&y); + } + apr_thread_exit(thd, exit_ret_val); + return NULL; +} + +void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < NUM_ITERATIONS ; i++) { + z++; + } + apr_thread_exit(thd, exit_ret_val); + return NULL; +} + +static void test_atomics_threaded(abts_case *tc, void *data) +{ + apr_thread_t *t1[NUM_THREADS]; + apr_thread_t *t2[NUM_THREADS]; + apr_thread_t *t3[NUM_THREADS]; + apr_status_t s1[NUM_THREADS]; + apr_status_t s2[NUM_THREADS]; + apr_status_t s3[NUM_THREADS]; + apr_status_t rv; + int i; + +#ifdef HAVE_PTHREAD_SETCONCURRENCY + pthread_setconcurrency(8); +#endif + + rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "Could not create lock", rv); + + for (i = 0; i < NUM_THREADS; i++) { + apr_status_t r1, r2, r3; + r1 = apr_thread_create(&t1[i], NULL, thread_func_mutex, NULL, p); + r2 = apr_thread_create(&t2[i], NULL, thread_func_atomic, NULL, p); + r3 = apr_thread_create(&t3[i], NULL, thread_func_none, NULL, p); + ABTS_ASSERT(tc, "Failed creating threads", + r1 == APR_SUCCESS && r2 == APR_SUCCESS && + r3 == APR_SUCCESS); + } + + for (i = 0; i < NUM_THREADS; i++) { + apr_thread_join(&s1[i], t1[i]); + apr_thread_join(&s2[i], t2[i]); + apr_thread_join(&s3[i], t3[i]); + + ABTS_ASSERT(tc, "Invalid return value from thread_join", + s1[i] == exit_ret_val && s2[i] == exit_ret_val && + s3[i] == exit_ret_val); + } + + ABTS_INT_EQUAL(tc, x, NUM_THREADS * NUM_ITERATIONS); + ABTS_INT_EQUAL(tc, apr_atomic_read32(&y), NUM_THREADS * NUM_ITERATIONS); + /* Comment out this test, because I have no clue what this test is + * actually telling us. We are checking something that may or may not + * be true, and it isn't really testing APR at all. + ABTS_ASSERT(tc, "We expect this to fail, because we tried to update " + "an integer in a non-thread-safe manner.", + z != NUM_THREADS * NUM_ITERATIONS); + */ +} + +#endif /* !APR_HAS_THREADS */ + +abts_suite *testatomic(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_init, NULL); + abts_run_test(suite, test_set32, NULL); + abts_run_test(suite, test_read32, NULL); + abts_run_test(suite, test_dec32, NULL); + abts_run_test(suite, test_xchg32, NULL); + abts_run_test(suite, test_cas_equal, NULL); + abts_run_test(suite, test_cas_equal_nonnull, NULL); + abts_run_test(suite, test_cas_notequal, NULL); + abts_run_test(suite, test_add32, NULL); + abts_run_test(suite, test_inc32, NULL); + abts_run_test(suite, test_set_add_inc_sub, NULL); + abts_run_test(suite, test_wrap_zero, NULL); + abts_run_test(suite, test_inc_neg1, NULL); + +#if APR_HAS_THREADS + abts_run_test(suite, test_atomics_threaded, NULL); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testdir.c b/srclib/apr/test/testdir.c new file mode 100644 index 0000000000..bc2ca9ae69 --- /dev/null +++ b/srclib/apr/test/testdir.c @@ -0,0 +1,243 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "testutil.h" + +static void test_mkdir(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_finfo_t finfo; + + rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); +} + +static void test_mkdir_recurs(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_finfo_t finfo; + + rv = apr_dir_make_recursive("data/one/two/three", + APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_stat(&finfo, "data/one", APR_FINFO_TYPE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); + + rv = apr_stat(&finfo, "data/one/two", APR_FINFO_TYPE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); + + rv = apr_stat(&finfo, "data/one/two/three", APR_FINFO_TYPE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_DIR, finfo.filetype); +} + +static void test_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_finfo_t finfo; + + rv = apr_dir_remove("data/testdir", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_stat(&finfo, "data/testdir", APR_FINFO_TYPE, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_removeall_fail(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_dir_remove("data/one", p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); +} + +static void test_removeall(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_dir_remove("data/one/two/three", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_dir_remove("data/one/two", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_dir_remove("data/one", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void test_remove_notthere(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_dir_remove("data/notthere", p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_mkdir_twice(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_dir_make("data/testdir", APR_UREAD | APR_UWRITE | APR_UEXECUTE, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv)); + + rv = apr_dir_remove("data/testdir", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void test_opendir(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_dir_t *dir; + + rv = apr_dir_open(&dir, "data", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + apr_dir_close(dir); +} + +static void test_opendir_notthere(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_dir_t *dir; + + rv = apr_dir_open(&dir, "notthere", p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_closedir(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_dir_t *dir; + + rv = apr_dir_open(&dir, "data", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_close(dir); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void test_rewind(abts_case *tc, void *data) +{ + apr_dir_t *dir; + apr_finfo_t first, second; + + APR_ASSERT_SUCCESS(tc, "apr_dir_open failed", apr_dir_open(&dir, "data", p)); + + APR_ASSERT_SUCCESS(tc, "apr_dir_read failed", + apr_dir_read(&first, APR_FINFO_DIRENT, dir)); + + APR_ASSERT_SUCCESS(tc, "apr_dir_rewind failed", apr_dir_rewind(dir)); + + APR_ASSERT_SUCCESS(tc, "second apr_dir_read failed", + apr_dir_read(&second, APR_FINFO_DIRENT, dir)); + + APR_ASSERT_SUCCESS(tc, "apr_dir_close failed", apr_dir_close(dir)); + + ABTS_STR_EQUAL(tc, first.name, second.name); +} + +/* Test for a (fixed) bug in apr_dir_read(). This bug only happened + in threadless cases. */ +static void test_uncleared_errno(abts_case *tc, void *data) +{ + apr_file_t *thefile = NULL; + apr_finfo_t finfo; + apr_int32_t finfo_flags = APR_FINFO_TYPE | APR_FINFO_NAME; + apr_dir_t *this_dir; + apr_status_t rv; + + rv = apr_dir_make("dir1", APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_make("dir2", APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_file_open(&thefile, "dir1/file1", + APR_READ | APR_WRITE | APR_CREATE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_file_close(thefile); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Try to remove dir1. This should fail because it's not empty. + However, on a platform with threads disabled (such as FreeBSD), + `errno' will be set as a result. */ + rv = apr_dir_remove("dir1", p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOTEMPTY(rv)); + + /* Read `.' and `..' out of dir2. */ + rv = apr_dir_open(&this_dir, "dir2", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_read(&finfo, finfo_flags, this_dir); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_read(&finfo, finfo_flags, this_dir); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Now, when we attempt to do a third read of empty dir2, and the + underlying system readdir() returns NULL, the old value of + errno shouldn't cause a false alarm. We should get an ENOENT + back from apr_dir_read, and *not* the old errno. */ + rv = apr_dir_read(&finfo, finfo_flags, this_dir); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); + + rv = apr_dir_close(this_dir); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Cleanup */ + rv = apr_file_remove("dir1/file1", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_remove("dir1", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_dir_remove("dir2", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + +} + +abts_suite *testdir(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_mkdir, NULL); + abts_run_test(suite, test_mkdir_recurs, NULL); + abts_run_test(suite, test_remove, NULL); + abts_run_test(suite, test_removeall_fail, NULL); + abts_run_test(suite, test_removeall, NULL); + abts_run_test(suite, test_remove_notthere, NULL); + abts_run_test(suite, test_mkdir_twice, NULL); + + abts_run_test(suite, test_rewind, NULL); + + abts_run_test(suite, test_opendir, NULL); + abts_run_test(suite, test_opendir_notthere, NULL); + abts_run_test(suite, test_closedir, NULL); + abts_run_test(suite, test_uncleared_errno, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testdso.c b/srclib/apr/test/testdso.c new file mode 100644 index 0000000000..5187cdd256 --- /dev/null +++ b/srclib/apr/test/testdso.c @@ -0,0 +1,256 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "testutil.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_dso.h" +#include "apr_strings.h" +#include "apr.h" +#if APR_HAVE_UNISTD_H +#include +#endif + +#if APR_HAS_DSO + +#ifdef NETWARE +# define MOD_NAME "mod_test.nlm" +#elif defined(BEOS) || defined(WIN32) +# define MOD_NAME "mod_test.so" +#elif defined(DARWIN) +# define MOD_NAME ".libs/mod_test.so" +# define LIB_NAME ".libs/libmod_test.dylib" +#elif defined(__hpux__) || defined(__hpux) +# define MOD_NAME ".libs/mod_test.sl" +# define LIB_NAME ".libs/libmod_test.sl" +#elif defined(_AIX) || defined(__bsdi__) +# define MOD_NAME ".libs/libmod_test.so" +# define LIB_NAME ".libs/libmod_test.so" +#else /* Every other Unix */ +# define MOD_NAME ".libs/mod_test.so" +# define LIB_NAME ".libs/libmod_test.so" +#endif + +static char *modname; + +static void test_load_module(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_status_t status; + char errstr[256]; + + status = apr_dso_load(&h, modname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + apr_dso_unload(h); +} + +static void test_dso_sym(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_dso_handle_sym_t func1 = NULL; + apr_status_t status; + void (*function)(char str[256]); + char teststr[256]; + char errstr[256]; + + status = apr_dso_load(&h, modname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_sym(&func1, h, "print_hello"); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, func1); + + function = (void (*)(char *))func1; + (*function)(teststr); + ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr); + + apr_dso_unload(h); +} + +static void test_dso_sym_return_value(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_dso_handle_sym_t func1 = NULL; + apr_status_t status; + int (*function)(int); + char errstr[256]; + + status = apr_dso_load(&h, modname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_sym(&func1, h, "count_reps"); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, func1); + + function = (int (*)(int))func1; + status = (*function)(5); + ABTS_INT_EQUAL(tc, 5, status); + + apr_dso_unload(h); +} + +static void test_unload_module(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_status_t status; + char errstr[256]; + apr_dso_handle_sym_t func1 = NULL; + + status = apr_dso_load(&h, modname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_unload(h); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + + status = apr_dso_sym(&func1, h, "print_hello"); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ESYMNOTFOUND(status)); +} + + +#ifdef LIB_NAME +static char *libname; + +static void test_load_library(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_status_t status; + char errstr[256]; + + status = apr_dso_load(&h, libname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + apr_dso_unload(h); +} + +static void test_dso_sym_library(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_dso_handle_sym_t func1 = NULL; + apr_status_t status; + void (*function)(char str[256]); + char teststr[256]; + char errstr[256]; + + status = apr_dso_load(&h, libname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_sym(&func1, h, "print_hello"); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, func1); + + function = (void (*)(char *))func1; + (*function)(teststr); + ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr); + + apr_dso_unload(h); +} + +static void test_dso_sym_return_value_library(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_dso_handle_sym_t func1 = NULL; + apr_status_t status; + int (*function)(int); + char errstr[256]; + + status = apr_dso_load(&h, libname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_sym(&func1, h, "count_reps"); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, func1); + + function = (int (*)(int))func1; + status = (*function)(5); + ABTS_INT_EQUAL(tc, 5, status); + + apr_dso_unload(h); +} + +static void test_unload_library(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_status_t status; + char errstr[256]; + apr_dso_handle_sym_t func1 = NULL; + + status = apr_dso_load(&h, libname, p); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + ABTS_PTR_NOTNULL(tc, h); + + status = apr_dso_unload(h); + ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); + + status = apr_dso_sym(&func1, h, "print_hello"); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ESYMNOTFOUND(status)); +} + +#endif /* def(LIB_NAME) */ + +static void test_load_notthere(abts_case *tc, void *data) +{ + apr_dso_handle_t *h = NULL; + apr_status_t status; + + status = apr_dso_load(&h, "No_File.so", p); + + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EDSOOPEN(status)); + ABTS_PTR_NOTNULL(tc, h); +} + +#endif /* APR_HAS_DSO */ + +abts_suite *testdso(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if APR_HAS_DSO + modname = apr_pcalloc(p, 256); + getcwd(modname, 256); + modname = apr_pstrcat(p, modname, "/", MOD_NAME, NULL); + + abts_run_test(suite, test_load_module, NULL); + abts_run_test(suite, test_dso_sym, NULL); + abts_run_test(suite, test_dso_sym_return_value, NULL); + abts_run_test(suite, test_unload_module, NULL); + +#ifdef LIB_NAME + libname = apr_pcalloc(p, 256); + getcwd(libname, 256); + libname = apr_pstrcat(p, libname, "/", LIB_NAME, NULL); + + abts_run_test(suite, test_load_library, NULL); + abts_run_test(suite, test_dso_sym_library, NULL); + abts_run_test(suite, test_dso_sym_return_value_library, NULL); + abts_run_test(suite, test_unload_library, NULL); +#endif + + abts_run_test(suite, test_load_notthere, NULL); +#endif /* APR_HAS_DSO */ + + return suite; +} + diff --git a/srclib/apr/test/testdup.c b/srclib/apr/test/testdup.c new file mode 100644 index 0000000000..9e025069c5 --- /dev/null +++ b/srclib/apr/test/testdup.c @@ -0,0 +1,194 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_file_io.h" +#include "testutil.h" + +#define TEST "Testing\n" +#define TEST2 "Testing again\n" +#define FILEPATH "data/" + +static void test_file_dup(abts_case *tc, void *data) +{ + apr_file_t *file1 = NULL; + apr_file_t *file3 = NULL; + apr_status_t rv; + apr_finfo_t finfo; + + /* First, create a new file, empty... */ + rv = apr_file_open(&file1, FILEPATH "testdup.file", + APR_READ | APR_WRITE | APR_CREATE | + APR_DELONCLOSE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, file1); + + rv = apr_file_dup(&file3, file1, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, file3); + + rv = apr_file_close(file1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* cleanup after ourselves */ + rv = apr_file_close(file3); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_stat(&finfo, FILEPATH "testdup.file", APR_FINFO_NORM, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_file_readwrite(abts_case *tc, void *data) +{ + apr_file_t *file1 = NULL; + apr_file_t *file3 = NULL; + apr_status_t rv; + apr_finfo_t finfo; + apr_size_t txtlen = sizeof(TEST); + char buff[50]; + apr_off_t fpos; + + /* First, create a new file, empty... */ + rv = apr_file_open(&file1, FILEPATH "testdup.readwrite.file", + APR_READ | APR_WRITE | APR_CREATE | + APR_DELONCLOSE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, file1); + + rv = apr_file_dup(&file3, file1, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, file3); + + rv = apr_file_write(file3, TEST, &txtlen); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, sizeof(TEST), txtlen); + + fpos = 0; + rv = apr_file_seek(file1, APR_SET, &fpos); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, fpos); + + txtlen = 50; + rv = apr_file_read(file1, buff, &txtlen); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, TEST, buff); + + /* cleanup after ourselves */ + rv = apr_file_close(file1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_close(file3); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_stat(&finfo, FILEPATH "testdup.readwrite.file", APR_FINFO_NORM, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_dup2(abts_case *tc, void *data) +{ + apr_file_t *testfile = NULL; + apr_file_t *errfile = NULL; + apr_file_t *saveerr = NULL; + apr_status_t rv; + + rv = apr_file_open(&testfile, FILEPATH "testdup2.file", + APR_READ | APR_WRITE | APR_CREATE | + APR_DELONCLOSE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, testfile); + + rv = apr_file_open_stderr(&errfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Set aside the real errfile */ + rv = apr_file_dup(&saveerr, errfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, saveerr); + + rv = apr_file_dup2(errfile, testfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, errfile); + + apr_file_close(testfile); + + rv = apr_file_dup2(errfile, saveerr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, errfile); +} + +static void test_dup2_readwrite(abts_case *tc, void *data) +{ + apr_file_t *errfile = NULL; + apr_file_t *testfile = NULL; + apr_file_t *saveerr = NULL; + apr_status_t rv; + apr_size_t txtlen = sizeof(TEST); + char buff[50]; + apr_off_t fpos; + + rv = apr_file_open(&testfile, FILEPATH "testdup2.readwrite.file", + APR_READ | APR_WRITE | APR_CREATE | + APR_DELONCLOSE, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, testfile); + + rv = apr_file_open_stderr(&errfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* Set aside the real errfile */ + rv = apr_file_dup(&saveerr, errfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, saveerr); + + rv = apr_file_dup2(errfile, testfile, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, errfile); + + txtlen = sizeof(TEST2); + rv = apr_file_write(errfile, TEST2, &txtlen); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, sizeof(TEST2), txtlen); + + fpos = 0; + rv = apr_file_seek(testfile, APR_SET, &fpos); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, fpos); + + txtlen = 50; + rv = apr_file_read(testfile, buff, &txtlen); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, TEST2, buff); + + apr_file_close(testfile); + + rv = apr_file_dup2(errfile, saveerr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, errfile); +} + +abts_suite *testdup(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_file_dup, NULL); + abts_run_test(suite, test_file_readwrite, NULL); + abts_run_test(suite, test_dup2, NULL); + abts_run_test(suite, test_dup2_readwrite, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testenv.c b/srclib/apr/test/testenv.c new file mode 100644 index 0000000000..4d6f55c1c4 --- /dev/null +++ b/srclib/apr/test/testenv.c @@ -0,0 +1,95 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_env.h" +#include "apr_errno.h" +#include "testutil.h" + +#define TEST_ENVVAR_NAME "apr_test_envvar" +#define TEST_ENVVAR_VALUE "Just a value that we'll check" + +static int have_env_set; +static int have_env_get; + +static void test_setenv(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_env_set(TEST_ENVVAR_NAME, TEST_ENVVAR_VALUE, p); + have_env_set = (rv != APR_ENOTIMPL); + if (!have_env_set) { + ABTS_NOT_IMPL(tc, "apr_env_set"); + } else { + APR_ASSERT_SUCCESS(tc, "set environment variable", rv); + } +} + +static void test_getenv(abts_case *tc, void *data) +{ + char *value; + apr_status_t rv; + + if (!have_env_set) { + ABTS_NOT_IMPL(tc, "apr_env_set (skip test for apr_env_get)"); + return; + } + + rv = apr_env_get(&value, TEST_ENVVAR_NAME, p); + have_env_get = (rv != APR_ENOTIMPL); + if (!have_env_get) { + ABTS_NOT_IMPL(tc, "apr_env_get"); + return; + } + APR_ASSERT_SUCCESS(tc, "get environment variable", rv); + ABTS_STR_EQUAL(tc, TEST_ENVVAR_VALUE, value); +} + +static void test_delenv(abts_case *tc, void *data) +{ + char *value; + apr_status_t rv; + + if (!have_env_set) { + ABTS_NOT_IMPL(tc, "apr_env_set (skip test for apr_env_delete)"); + return; + } + + rv = apr_env_delete(TEST_ENVVAR_NAME, p); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_env_delete"); + return; + } + APR_ASSERT_SUCCESS(tc, "delete environment variable", rv); + + if (!have_env_get) { + ABTS_NOT_IMPL(tc, "apr_env_get (skip sanity check for apr_env_delete)"); + return; + } + rv = apr_env_get(&value, TEST_ENVVAR_NAME, p); + ABTS_INT_EQUAL(tc, APR_ENOENT, rv); +} + +abts_suite *testenv(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_setenv, NULL); + abts_run_test(suite, test_getenv, NULL); + abts_run_test(suite, test_delenv, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testfile.c b/srclib/apr/test/testfile.c new file mode 100644 index 0000000000..508ebaf9fa --- /dev/null +++ b/srclib/apr/test/testfile.c @@ -0,0 +1,739 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_poll.h" +#include "apr_lib.h" +#include "testutil.h" + +#define DIRNAME "data" +#define FILENAME DIRNAME "/file_datafile.txt" +#define TESTSTR "This is the file data file." + +#define TESTREAD_BLKSIZE 1024 +#define APR_BUFFERSIZE 4096 /* This should match APR's buffer size. */ + + + +static void test_open_noreadwrite(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *thefile = NULL; + + rv = apr_file_open(&thefile, FILENAME, + APR_CREATE | APR_EXCL, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_TRUE(tc, rv != APR_SUCCESS); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EACCES(rv)); + ABTS_PTR_EQUAL(tc, NULL, thefile); +} + +static void test_open_excl(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *thefile = NULL; + + rv = apr_file_open(&thefile, FILENAME, + APR_CREATE | APR_EXCL | APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_TRUE(tc, rv != APR_SUCCESS); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EEXIST(rv)); + ABTS_PTR_EQUAL(tc, NULL, thefile); +} + +static void test_open_read(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, filetest); + apr_file_close(filetest); +} + +static void test_read(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_size_t nbytes = 256; + char *str = apr_pcalloc(p, nbytes + 1); + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + + APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv); + rv = apr_file_read(filetest, str, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTSTR), nbytes); + ABTS_STR_EQUAL(tc, TESTSTR, str); + + apr_file_close(filetest); +} + +static void test_readzero(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_size_t nbytes = 0; + char *str = NULL; + apr_file_t *filetest; + + rv = apr_file_open(&filetest, FILENAME, APR_READ, APR_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv); + + rv = apr_file_read(filetest, str, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, nbytes); + + apr_file_close(filetest); +} + +static void test_filename(abts_case *tc, void *data) +{ + const char *str; + apr_status_t rv; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv); + + rv = apr_file_name_get(&str, filetest); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, FILENAME, str); + + apr_file_close(filetest); +} + +static void test_fileclose(abts_case *tc, void *data) +{ + char str; + apr_status_t rv; + apr_size_t one = 1; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + APR_ASSERT_SUCCESS(tc, "Opening test file " FILENAME, rv); + + rv = apr_file_close(filetest); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + /* We just closed the file, so this should fail */ + rv = apr_file_read(filetest, &str, &one); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv)); +} + +static void test_file_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + rv = apr_file_remove(FILENAME, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_open(&filetest, FILENAME, APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); +} + +static void test_open_write(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + filetest = NULL; + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ENOENT(rv)); + ABTS_PTR_EQUAL(tc, NULL, filetest); +} + +static void test_open_writecreate(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + filetest = NULL; + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE | APR_CREATE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_close(filetest); +} + +static void test_write(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_size_t bytes = strlen(TESTSTR); + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE | APR_CREATE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_write(filetest, TESTSTR, &bytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_close(filetest); +} + +static void test_open_readwrite(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + filetest = NULL; + rv = apr_file_open(&filetest, FILENAME, + APR_READ | APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, filetest); + + apr_file_close(filetest); +} + +static void test_seek(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_off_t offset = 5; + apr_size_t nbytes = 256; + char *str = apr_pcalloc(p, nbytes + 1); + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_READ, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv); + + rv = apr_file_read(filetest, str, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTSTR), nbytes); + ABTS_STR_EQUAL(tc, TESTSTR, str); + + memset(str, 0, nbytes + 1); + + rv = apr_file_seek(filetest, SEEK_SET, &offset); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_read(filetest, str, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTSTR) - 5, nbytes); + ABTS_STR_EQUAL(tc, TESTSTR + 5, str); + + apr_file_close(filetest); + + /* Test for regression of sign error bug with SEEK_END and + buffered files. */ + rv = apr_file_open(&filetest, FILENAME, + APR_READ | APR_BUFFERED, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + APR_ASSERT_SUCCESS(tc, "Open test file " FILENAME, rv); + + offset = -5; + rv = apr_file_seek(filetest, SEEK_END, &offset); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(TESTSTR) - 5, nbytes); + + memset(str, 0, nbytes + 1); + nbytes = 256; + rv = apr_file_read(filetest, str, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 5, nbytes); + ABTS_STR_EQUAL(tc, TESTSTR + strlen(TESTSTR) - 5, str); + + apr_file_close(filetest); +} + +static void test_userdata_set(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_data_set(filetest, "This is a test", + "test", apr_pool_cleanup_null); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + apr_file_close(filetest); +} + +static void test_userdata_get(abts_case *tc, void *data) +{ + apr_status_t rv; + void *udata; + char *teststr; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_data_set(filetest, "This is a test", + "test", apr_pool_cleanup_null); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_data_get(&udata, "test", filetest); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + teststr = udata; + ABTS_STR_EQUAL(tc, "This is a test", teststr); + + apr_file_close(filetest); +} + +static void test_userdata_getnokey(abts_case *tc, void *data) +{ + apr_status_t rv; + void *teststr; + apr_file_t *filetest = NULL; + + rv = apr_file_open(&filetest, FILENAME, + APR_WRITE, + APR_UREAD | APR_UWRITE | APR_GREAD, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_data_get(&teststr, "nokey", filetest); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_EQUAL(tc, NULL, teststr); + apr_file_close(filetest); +} + +static void test_getc(abts_case *tc, void *data) +{ + apr_file_t *f = NULL; + apr_status_t rv; + char ch; + + rv = apr_file_open(&f, FILENAME, APR_READ, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_getc(&ch, f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch); + apr_file_close(f); +} + +static void test_ungetc(abts_case *tc, void *data) +{ + apr_file_t *f = NULL; + apr_status_t rv; + char ch; + + rv = apr_file_open(&f, FILENAME, APR_READ, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_getc(&ch, f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, (int)TESTSTR[0], (int)ch); + + apr_file_ungetc('X', f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_getc(&ch, f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 'X', (int)ch); + + apr_file_close(f); +} + +static void test_gets(abts_case *tc, void *data) +{ + apr_file_t *f = NULL; + apr_status_t rv; + char *str = apr_palloc(p, 256); + + rv = apr_file_open(&f, FILENAME, APR_READ, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_gets(str, 256, f); + /* Only one line in the test file, so APR will encounter EOF on the first + * call to gets, but we should get APR_SUCCESS on this call and + * APR_EOF on the next. + */ + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, TESTSTR, str); + rv = apr_file_gets(str, 256, f); + ABTS_INT_EQUAL(tc, APR_EOF, rv); + ABTS_STR_EQUAL(tc, "", str); + apr_file_close(f); +} + +static void test_bigread(abts_case *tc, void *data) +{ + apr_file_t *f = NULL; + apr_status_t rv; + char buf[APR_BUFFERSIZE * 2]; + apr_size_t nbytes; + + /* Create a test file with known content. + */ + rv = apr_file_open(&f, "data/created_file", + APR_CREATE | APR_WRITE | APR_TRUNCATE, + APR_UREAD | APR_UWRITE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + nbytes = APR_BUFFERSIZE; + memset(buf, 0xFE, nbytes); + + rv = apr_file_write(f, buf, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_BUFFERSIZE, nbytes); + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + f = NULL; + rv = apr_file_open(&f, "data/created_file", APR_READ, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + nbytes = sizeof buf; + rv = apr_file_read(f, buf, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, APR_BUFFERSIZE, nbytes); + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_remove("data/created_file", p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +/* This is a horrible name for this function. We are testing APR, not how + * Apache uses APR. And, this function tests _way_ too much stuff. + */ +static void test_mod_neg(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *s; + int i; + apr_size_t nbytes; + char buf[8192]; + apr_off_t cur; + const char *fname = "data/modneg.dat"; + + rv = apr_file_open(&f, fname, + APR_CREATE | APR_WRITE, APR_UREAD | APR_UWRITE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + s = "body56789\n"; + nbytes = strlen(s); + rv = apr_file_write(f, s, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(s), nbytes); + + for (i = 0; i < 7980; i++) { + s = "0"; + nbytes = strlen(s); + rv = apr_file_write(f, s, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(s), nbytes); + } + + s = "end456789\n"; + nbytes = strlen(s); + rv = apr_file_write(f, s, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(s), nbytes); + + for (i = 0; i < 10000; i++) { + s = "1"; + nbytes = strlen(s); + rv = apr_file_write(f, s, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(s), nbytes); + } + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_open(&f, fname, APR_READ, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_gets(buf, 11, f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "body56789\n", buf); + + cur = 0; + rv = apr_file_seek(f, APR_CUR, &cur); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 10, cur); + + nbytes = sizeof(buf); + rv = apr_file_read(f, buf, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, nbytes, sizeof(buf)); + + cur = -((apr_off_t)nbytes - 7980); + rv = apr_file_seek(f, APR_CUR, &cur); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 7990, cur); + + rv = apr_file_gets(buf, 11, f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "end456789\n", buf); + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_remove(fname, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +/* Test that the contents of file FNAME are equal to data EXPECT of + * length EXPECTLEN. */ +static void file_contents_equal(abts_case *tc, + const char *fname, + const void *expect, + apr_size_t expectlen) +{ + void *actual = apr_palloc(p, expectlen); + apr_file_t *f; + + APR_ASSERT_SUCCESS(tc, "open file", + apr_file_open(&f, fname, APR_READ|APR_BUFFERED, + 0, p)); + APR_ASSERT_SUCCESS(tc, "read from file", + apr_file_read_full(f, actual, expectlen, NULL)); + + ABTS_ASSERT(tc, "matched expected file contents", + memcmp(expect, actual, expectlen) == 0); + + APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(f)); +} + +#define LINE1 "this is a line of text\n" +#define LINE2 "this is a second line of text\n" + +static void test_puts(abts_case *tc, void *data) +{ + apr_file_t *f; + const char *fname = "data/testputs.txt"; + + APR_ASSERT_SUCCESS(tc, "open file for writing", + apr_file_open(&f, fname, + APR_WRITE|APR_CREATE|APR_TRUNCATE, + APR_OS_DEFAULT, p)); + + APR_ASSERT_SUCCESS(tc, "write line to file", + apr_file_puts(LINE1, f)); + APR_ASSERT_SUCCESS(tc, "write second line to file", + apr_file_puts(LINE2, f)); + + APR_ASSERT_SUCCESS(tc, "close for writing", + apr_file_close(f)); + + file_contents_equal(tc, fname, LINE1 LINE2, strlen(LINE1 LINE2)); +} + +static void test_writev(abts_case *tc, void *data) +{ + apr_file_t *f; + apr_size_t nbytes; + struct iovec vec[5]; + const char *fname = "data/testwritev.txt"; + + APR_ASSERT_SUCCESS(tc, "open file for writing", + apr_file_open(&f, fname, + APR_WRITE|APR_CREATE|APR_TRUNCATE, + APR_OS_DEFAULT, p)); + + vec[0].iov_base = LINE1; + vec[0].iov_len = strlen(LINE1); + + APR_ASSERT_SUCCESS(tc, "writev of size 1 to file", + apr_file_writev(f, vec, 1, &nbytes)); + + file_contents_equal(tc, fname, LINE1, strlen(LINE1)); + + vec[0].iov_base = LINE1; + vec[0].iov_len = strlen(LINE1); + vec[1].iov_base = LINE2; + vec[1].iov_len = strlen(LINE2); + vec[2].iov_base = LINE1; + vec[2].iov_len = strlen(LINE1); + vec[3].iov_base = LINE1; + vec[3].iov_len = strlen(LINE1); + vec[4].iov_base = LINE2; + vec[4].iov_len = strlen(LINE2); + + APR_ASSERT_SUCCESS(tc, "writev of size 5 to file", + apr_file_writev(f, vec, 5, &nbytes)); + + APR_ASSERT_SUCCESS(tc, "close for writing", + apr_file_close(f)); + + file_contents_equal(tc, fname, LINE1 LINE1 LINE2 LINE1 LINE1 LINE2, + strlen(LINE1)*4 + strlen(LINE2)*2); + +} + +static void test_writev_full(abts_case *tc, void *data) +{ + apr_file_t *f; + apr_size_t nbytes; + struct iovec vec[5]; + const char *fname = "data/testwritev_full.txt"; + + APR_ASSERT_SUCCESS(tc, "open file for writing", + apr_file_open(&f, fname, + APR_WRITE|APR_CREATE|APR_TRUNCATE, + APR_OS_DEFAULT, p)); + + vec[0].iov_base = LINE1; + vec[0].iov_len = strlen(LINE1); + vec[1].iov_base = LINE2; + vec[1].iov_len = strlen(LINE2); + vec[2].iov_base = LINE1; + vec[2].iov_len = strlen(LINE1); + vec[3].iov_base = LINE1; + vec[3].iov_len = strlen(LINE1); + vec[4].iov_base = LINE2; + vec[4].iov_len = strlen(LINE2); + + APR_ASSERT_SUCCESS(tc, "writev_full of size 5 to file", + apr_file_writev_full(f, vec, 5, &nbytes)); + + ABTS_INT_EQUAL(tc, strlen(LINE1)*3 + strlen(LINE2)*2, nbytes); + + APR_ASSERT_SUCCESS(tc, "close for writing", + apr_file_close(f)); + + file_contents_equal(tc, fname, LINE1 LINE2 LINE1 LINE1 LINE2, + strlen(LINE1)*3 + strlen(LINE2)*2); + +} + +static void test_truncate(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_file_t *f; + const char *fname = "data/testtruncate.dat"; + const char *s; + apr_size_t nbytes; + apr_finfo_t finfo; + + apr_file_remove(fname, p); + + rv = apr_file_open(&f, fname, + APR_CREATE | APR_WRITE, APR_UREAD | APR_UWRITE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + s = "some data"; + nbytes = strlen(s); + rv = apr_file_write(f, s, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen(s), nbytes); + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_open(&f, fname, + APR_TRUNCATE | APR_WRITE, APR_UREAD | APR_UWRITE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_close(f); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_stat(&finfo, fname, APR_FINFO_SIZE, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, finfo.size); + + rv = apr_file_remove(fname, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void test_bigfprintf(abts_case *tc, void *data) +{ + apr_file_t *f; + const char *fname = "data/testbigfprintf.dat"; + char *to_write; + int i; + + apr_file_remove(fname, p); + + APR_ASSERT_SUCCESS(tc, "open test file", + apr_file_open(&f, fname, + APR_CREATE|APR_WRITE, + APR_UREAD|APR_UWRITE, p)); + + + to_write = malloc(HUGE_STRING_LEN + 3); + + for (i = 0; i < HUGE_STRING_LEN + 1; ++i) + to_write[i] = 'A' + i%26; + + strcpy(to_write + HUGE_STRING_LEN, "42"); + + i = apr_file_printf(f, "%s", to_write); + ABTS_INT_EQUAL(tc, HUGE_STRING_LEN + 2, i); + + apr_file_close(f); + + file_contents_equal(tc, fname, to_write, HUGE_STRING_LEN + 2); + + free(to_write); +} + +abts_suite *testfile(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_open_noreadwrite, NULL); + abts_run_test(suite, test_open_excl, NULL); + abts_run_test(suite, test_open_read, NULL); + abts_run_test(suite, test_open_readwrite, NULL); + abts_run_test(suite, test_read, NULL); + abts_run_test(suite, test_readzero, NULL); + abts_run_test(suite, test_seek, NULL); + abts_run_test(suite, test_filename, NULL); + abts_run_test(suite, test_fileclose, NULL); + abts_run_test(suite, test_file_remove, NULL); + abts_run_test(suite, test_open_write, NULL); + abts_run_test(suite, test_open_writecreate, NULL); + abts_run_test(suite, test_write, NULL); + abts_run_test(suite, test_userdata_set, NULL); + abts_run_test(suite, test_userdata_get, NULL); + abts_run_test(suite, test_userdata_getnokey, NULL); + abts_run_test(suite, test_getc, NULL); + abts_run_test(suite, test_ungetc, NULL); + abts_run_test(suite, test_gets, NULL); + abts_run_test(suite, test_puts, NULL); + abts_run_test(suite, test_writev, NULL); + abts_run_test(suite, test_writev_full, NULL); + abts_run_test(suite, test_bigread, NULL); + abts_run_test(suite, test_mod_neg, NULL); + abts_run_test(suite, test_truncate, NULL); + abts_run_test(suite, test_bigfprintf, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testfilecopy.c b/srclib/apr/test/testfilecopy.c new file mode 100644 index 0000000000..96b24d7fff --- /dev/null +++ b/srclib/apr/test/testfilecopy.c @@ -0,0 +1,138 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_pools.h" + +static void copy_helper(abts_case *tc, const char *from, const char * to, + apr_fileperms_t perms, int append, apr_pool_t *p) +{ + apr_status_t rv; + apr_status_t dest_rv; + apr_finfo_t copy; + apr_finfo_t orig; + apr_finfo_t dest; + + dest_rv = apr_stat(&dest, to, APR_FINFO_SIZE, p); + + if (!append) { + rv = apr_file_copy(from, to, perms, p); + } + else { + rv = apr_file_append(from, to, perms, p); + } + APR_ASSERT_SUCCESS(tc, "Error copying file", rv); + + rv = apr_stat(&orig, from, APR_FINFO_SIZE, p); + APR_ASSERT_SUCCESS(tc, "Couldn't stat original file", rv); + + rv = apr_stat(©, to, APR_FINFO_SIZE, p); + APR_ASSERT_SUCCESS(tc, "Couldn't stat copy file", rv); + + if (!append) { + ABTS_INT_EQUAL(tc, orig.size, copy.size); + } + else { + ABTS_INT_EQUAL(tc, + ((dest_rv == APR_SUCCESS) ? dest.size : 0) + orig.size, + copy.size); + } +} + +static void copy_short_file(abts_case *tc, void *data) +{ + apr_status_t rv; + + /* make absolutely sure that the dest file doesn't exist. */ + apr_file_remove("data/file_copy.txt", p); + + copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 0, p); + rv = apr_file_remove("data/file_copy.txt", p); + APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv); +} + +static void copy_over_existing(abts_case *tc, void *data) +{ + apr_status_t rv; + + /* make absolutely sure that the dest file doesn't exist. */ + apr_file_remove("data/file_copy.txt", p); + + /* This is a cheat. I don't want to create a new file, so I just copy + * one file, then I copy another. If the second copy succeeds, then + * this works. + */ + copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 0, p); + + copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 0, p); + + rv = apr_file_remove("data/file_copy.txt", p); + APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv); +} + +static void append_nonexist(abts_case *tc, void *data) +{ + apr_status_t rv; + + /* make absolutely sure that the dest file doesn't exist. */ + apr_file_remove("data/file_copy.txt", p); + + copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 0, p); + rv = apr_file_remove("data/file_copy.txt", p); + APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv); +} + +static void append_exist(abts_case *tc, void *data) +{ + apr_status_t rv; + + /* make absolutely sure that the dest file doesn't exist. */ + apr_file_remove("data/file_copy.txt", p); + + /* This is a cheat. I don't want to create a new file, so I just copy + * one file, then I copy another. If the second copy succeeds, then + * this works. + */ + copy_helper(tc, "data/file_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 0, p); + + copy_helper(tc, "data/mmap_datafile.txt", "data/file_copy.txt", + APR_FILE_SOURCE_PERMS, 1, p); + + rv = apr_file_remove("data/file_copy.txt", p); + APR_ASSERT_SUCCESS(tc, "Couldn't remove copy file", rv); +} + +abts_suite *testfilecopy(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, copy_short_file, NULL); + abts_run_test(suite, copy_over_existing, NULL); + + abts_run_test(suite, append_nonexist, NULL); + abts_run_test(suite, append_exist, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testfileinfo.c b/srclib/apr/test/testfileinfo.c new file mode 100644 index 0000000000..de5415f115 --- /dev/null +++ b/srclib/apr/test/testfileinfo.c @@ -0,0 +1,263 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_poll.h" +#include "apr_lib.h" +#include "testutil.h" + +#define FILENAME "data/file_datafile.txt" +#define NEWFILENAME "data/new_datafile.txt" +#define NEWFILEDATA "This is new text in a new file." + +static const struct view_fileinfo +{ + apr_int32_t bits; + char *description; +} vfi[] = { + {APR_FINFO_MTIME, "MTIME"}, + {APR_FINFO_CTIME, "CTIME"}, + {APR_FINFO_ATIME, "ATIME"}, + {APR_FINFO_SIZE, "SIZE"}, + {APR_FINFO_DEV, "DEV"}, + {APR_FINFO_INODE, "INODE"}, + {APR_FINFO_NLINK, "NLINK"}, + {APR_FINFO_TYPE, "TYPE"}, + {APR_FINFO_USER, "USER"}, + {APR_FINFO_GROUP, "GROUP"}, + {APR_FINFO_UPROT, "UPROT"}, + {APR_FINFO_GPROT, "GPROT"}, + {APR_FINFO_WPROT, "WPROT"}, + {0, NULL} +}; + +static void finfo_equal(abts_case *tc, apr_finfo_t *f1, apr_finfo_t *f2) +{ + /* Minimum supported flags across all platforms (APR_FINFO_MIN) */ + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_TYPE", + (f1->valid & f2->valid & APR_FINFO_TYPE)); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in filetype", + f1->filetype == f2->filetype); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_SIZE", + (f1->valid & f2->valid & APR_FINFO_SIZE)); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in size", + f1->size == f2->size); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_ATIME", + (f1->valid & f2->valid & APR_FINFO_ATIME)); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in atime", + f1->atime == f2->atime); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_MTIME", + (f1->valid & f2->valid & APR_FINFO_MTIME)); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in mtime", + f1->mtime == f2->mtime); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo must return APR_FINFO_CTIME", + (f1->valid & f2->valid & APR_FINFO_CTIME)); + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in ctime", + f1->ctime == f2->ctime); + + if (f1->valid & f2->valid & APR_FINFO_NAME) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in name", + !strcmp(f1->name, f2->name)); + if (f1->fname && f2->fname) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in fname", + !strcmp(f1->fname, f2->fname)); + + /* Additional supported flags not supported on all platforms */ + if (f1->valid & f2->valid & APR_FINFO_USER) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in user", + !apr_uid_compare(f1->user, f2->user)); + if (f1->valid & f2->valid & APR_FINFO_GROUP) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in group", + !apr_gid_compare(f1->group, f2->group)); + if (f1->valid & f2->valid & APR_FINFO_INODE) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in inode", + f1->inode == f2->inode); + if (f1->valid & f2->valid & APR_FINFO_DEV) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in device", + f1->device == f2->device); + if (f1->valid & f2->valid & APR_FINFO_NLINK) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in nlink", + f1->nlink == f2->nlink); + if (f1->valid & f2->valid & APR_FINFO_CSIZE) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in csize", + f1->csize == f2->csize); + if (f1->valid & f2->valid & APR_FINFO_PROT) + ABTS_ASSERT(tc, "apr_stat and apr_getfileinfo differ in protection", + f1->protection == f2->protection); +} + +static void test_info_get(abts_case *tc, void *data) +{ + apr_file_t *thefile; + apr_finfo_t finfo; + apr_status_t rv; + + rv = apr_file_open(&thefile, FILENAME, APR_READ, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile); + if (rv == APR_INCOMPLETE) { + char *str; + int i; + str = apr_pstrdup(p, "APR_INCOMPLETE: Missing "); + for (i = 0; vfi[i].bits; ++i) { + if (vfi[i].bits & ~finfo.valid) { + str = apr_pstrcat(p, str, vfi[i].description, " ", NULL); + } + } + ABTS_FAIL(tc, str); + } + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + apr_file_close(thefile); +} + +static void test_stat(abts_case *tc, void *data) +{ + apr_finfo_t finfo; + apr_status_t rv; + + rv = apr_stat(&finfo, FILENAME, APR_FINFO_NORM, p); + if (rv == APR_INCOMPLETE) { + char *str; + int i; + str = apr_pstrdup(p, "APR_INCOMPLETE: Missing "); + for (i = 0; vfi[i].bits; ++i) { + if (vfi[i].bits & ~finfo.valid) { + str = apr_pstrcat(p, str, vfi[i].description, " ", NULL); + } + } + ABTS_FAIL(tc, str); + } + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void test_stat_eq_finfo(abts_case *tc, void *data) +{ + apr_file_t *thefile; + apr_finfo_t finfo; + apr_finfo_t stat_finfo; + apr_status_t rv; + + rv = apr_file_open(&thefile, FILENAME, APR_READ, APR_OS_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile); + + /* Opening the file may have toggled the atime member (time last + * accessed), so fetch our apr_stat() after getting the fileinfo + * of the open file... + */ + rv = apr_stat(&stat_finfo, FILENAME, APR_FINFO_NORM, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + apr_file_close(thefile); + + finfo_equal(tc, &stat_finfo, &finfo); +} + +static void test_buffered_write_size(abts_case *tc, void *data) +{ + const apr_size_t data_len = strlen(NEWFILEDATA); + apr_file_t *thefile; + apr_finfo_t finfo; + apr_status_t rv; + apr_size_t bytes; + + rv = apr_file_open(&thefile, NEWFILENAME, + APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED | APR_DELONCLOSE, + APR_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open file", rv); + + /* A funny thing happened to me the other day: I wrote something + * into a buffered file, then asked for its size using + * apr_file_info_get; and guess what? The size was 0! That's not a + * nice way to behave. + */ + bytes = data_len; + rv = apr_file_write(thefile, NEWFILEDATA, &bytes); + APR_ASSERT_SUCCESS(tc, "write file contents", rv); + ABTS_TRUE(tc, data_len == bytes); + + rv = apr_file_info_get(&finfo, APR_FINFO_SIZE, thefile); + APR_ASSERT_SUCCESS(tc, "get file size", rv); + ABTS_TRUE(tc, bytes == (apr_size_t) finfo.size); + apr_file_close(thefile); +} + +static void test_mtime_set(abts_case *tc, void *data) +{ + apr_file_t *thefile; + apr_finfo_t finfo; + apr_time_t epoch = 0; + apr_status_t rv; + + /* This test sort of depends on the system clock being at least + * marginally ccorrect; We'll be setting the modification time to + * the epoch. + */ + rv = apr_file_open(&thefile, NEWFILENAME, + APR_READ | APR_WRITE | APR_CREATE | APR_TRUNCATE + | APR_BUFFERED | APR_DELONCLOSE, + APR_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "open file", rv); + + /* Check that the current mtime is not the epoch */ + rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p); + if (rv == APR_INCOMPLETE) { + char *str; + int i; + str = apr_pstrdup(p, "APR_INCOMPLETE: Missing "); + for (i = 0; vfi[i].bits; ++i) { + if (vfi[i].bits & ~finfo.valid) { + str = apr_pstrcat(p, str, vfi[i].description, " ", NULL); + } + } + ABTS_FAIL(tc, str); + } + APR_ASSERT_SUCCESS(tc, "get initial mtime", rv); + ABTS_TRUE(tc, finfo.mtime != epoch); + + /* Reset the mtime to the epoch and verify the result. + * Note: we blindly assume that if the first apr_stat succeeded, + * the second one will, too. + */ + rv = apr_file_mtime_set(NEWFILENAME, epoch, p); + APR_ASSERT_SUCCESS(tc, "set mtime", rv); + + rv = apr_stat(&finfo, NEWFILENAME, APR_FINFO_MTIME, p); + APR_ASSERT_SUCCESS(tc, "get modified mtime", rv); + ABTS_TRUE(tc, finfo.mtime == epoch); + + apr_file_close(thefile); +} + +abts_suite *testfileinfo(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_info_get, NULL); + abts_run_test(suite, test_stat, NULL); + abts_run_test(suite, test_stat_eq_finfo, NULL); + abts_run_test(suite, test_buffered_write_size, NULL); + abts_run_test(suite, test_mtime_set, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testflock.c b/srclib/apr/test/testflock.c new file mode 100644 index 0000000000..61e469d371 --- /dev/null +++ b/srclib/apr/test/testflock.c @@ -0,0 +1,101 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testflock.h" +#include "testutil.h" +#include "apr_pools.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_general.h" +#include "apr_strings.h" + +static int launch_reader(abts_case *tc) +{ + apr_proc_t proc = {0}; + apr_procattr_t *procattr; + const char *args[2]; + apr_status_t rv; + apr_exit_why_e why; + int exitcode; + + rv = apr_procattr_create(&procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv); + + rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, + APR_NO_PIPE); + APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv); + + rv = apr_procattr_error_check_set(procattr, 1); + APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv); + + args[0] = "tryread" EXTENSION; + args[1] = NULL; + rv = apr_proc_create(&proc, "./tryread" EXTENSION, args, NULL, procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv); + + ABTS_ASSERT(tc, "wait for child process", + apr_proc_wait(&proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE); + + ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT); + return exitcode; +} + +static void test_withlock(abts_case *tc, void *data) +{ + apr_file_t *file; + apr_status_t rv; + int code; + + rv = apr_file_open(&file, TESTFILE, APR_WRITE|APR_CREATE, + APR_OS_DEFAULT, p); + APR_ASSERT_SUCCESS(tc, "Could not create file.", rv); + ABTS_PTR_NOTNULL(tc, file); + + rv = apr_file_lock(file, APR_FLOCK_EXCLUSIVE); + APR_ASSERT_SUCCESS(tc, "Could not lock the file.", rv); + ABTS_PTR_NOTNULL(tc, file); + + code = launch_reader(tc); + ABTS_INT_EQUAL(tc, FAILED_READ, code); + + (void) apr_file_close(file); +} + +static void test_withoutlock(abts_case *tc, void *data) +{ + int code; + + code = launch_reader(tc); + ABTS_INT_EQUAL(tc, SUCCESSFUL_READ, code); +} + +static void remove_lockfile(abts_case *tc, void *data) +{ + APR_ASSERT_SUCCESS(tc, "Couldn't remove lock file.", + apr_file_remove(TESTFILE, p)); +} + +abts_suite *testflock(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_withlock, NULL); + abts_run_test(suite, test_withoutlock, NULL); + abts_run_test(suite, remove_lockfile, NULL); + + return suite; +} diff --git a/srclib/apr/test/testflock.h b/srclib/apr/test/testflock.h new file mode 100644 index 0000000000..0c1fd1852e --- /dev/null +++ b/srclib/apr/test/testflock.h @@ -0,0 +1,27 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TESTFLOCK +#define TESTFLOCK + +#define TESTFILE "data/testfile.lock" + +#define FAILED_READ 0 +#define SUCCESSFUL_READ 1 +#define UNEXPECTED_ERROR 2 + +#endif + diff --git a/srclib/apr/test/testfmt.c b/srclib/apr/test/testfmt.c new file mode 100644 index 0000000000..6cc2c3db40 --- /dev/null +++ b/srclib/apr/test/testfmt.c @@ -0,0 +1,135 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr.h" +#include "apr_portable.h" +#include "apr_strings.h" + +static void ssize_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_ssize_t var = 0; + + sprintf(buf, "%" APR_SSIZE_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_SSIZE_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); +} + +static void size_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_size_t var = 0; + + sprintf(buf, "%" APR_SIZE_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_SIZE_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); +} + +static void off_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_off_t var = 0; + + sprintf(buf, "%" APR_OFF_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_OFF_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); +} + +static void pid_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + pid_t var = 0; + + sprintf(buf, "%" APR_PID_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_PID_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); +} + +static void int64_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_int64_t var = 0; + + sprintf(buf, "%" APR_INT64_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_INT64_T_FMT, var); + ABTS_STR_EQUAL(tc, "0", buf); +} + +static void uint64_t_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_uint64_t var = APR_UINT64_C(14000000); + + sprintf(buf, "%" APR_UINT64_T_FMT, var); + ABTS_STR_EQUAL(tc, "14000000", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_UINT64_T_FMT, var); + ABTS_STR_EQUAL(tc, "14000000", buf); +} + +static void uint64_t_hex_fmt(abts_case *tc, void *data) +{ + char buf[100]; + apr_uint64_t var = APR_UINT64_C(14000000); + + sprintf(buf, "%" APR_UINT64_T_HEX_FMT, var); + ABTS_STR_EQUAL(tc, "d59f80", buf); + apr_snprintf(buf, sizeof(buf), "%" APR_UINT64_T_HEX_FMT, var); + ABTS_STR_EQUAL(tc, "d59f80", buf); +} + +static void more_int64_fmts(abts_case *tc, void *data) +{ + char buf[100]; + apr_int64_t i = APR_INT64_C(-42); + apr_int64_t ibig = APR_INT64_C(-314159265358979323); + apr_uint64_t ui = APR_UINT64_C(42); + apr_uint64_t big = APR_UINT64_C(3141592653589793238); + + apr_snprintf(buf, sizeof buf, "%" APR_INT64_T_FMT, i); + ABTS_STR_EQUAL(tc, buf, "-42"); + + apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, ui); + ABTS_STR_EQUAL(tc, buf, "42"); + + apr_snprintf(buf, sizeof buf, "%" APR_UINT64_T_FMT, big); + ABTS_STR_EQUAL(tc, buf, "3141592653589793238"); + + apr_snprintf(buf, sizeof buf, "%" APR_INT64_T_FMT, ibig); + ABTS_STR_EQUAL(tc, buf, "-314159265358979323"); +} + +abts_suite *testfmt(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, ssize_t_fmt, NULL); + abts_run_test(suite, size_t_fmt, NULL); + abts_run_test(suite, off_t_fmt, NULL); + abts_run_test(suite, pid_t_fmt, NULL); + abts_run_test(suite, int64_t_fmt, NULL); + abts_run_test(suite, uint64_t_fmt, NULL); + abts_run_test(suite, uint64_t_hex_fmt, NULL); + abts_run_test(suite, more_int64_fmts, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testfnmatch.c b/srclib/apr/test/testfnmatch.c new file mode 100644 index 0000000000..3b01b0f31d --- /dev/null +++ b/srclib/apr/test/testfnmatch.c @@ -0,0 +1,76 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_file_info.h" +#include "apr_fnmatch.h" +#include "apr_tables.h" + +/* XXX NUM_FILES must be equal to the nummber of expected files with a + * .txt extension in the data directory at the time testfnmatch + * happens to be run (!?!). */ + +#define NUM_FILES (5) + +static void test_glob(abts_case *tc, void *data) +{ + int i; + char **list; + apr_array_header_t *result; + + APR_ASSERT_SUCCESS(tc, "glob match against data/*.txt", + apr_match_glob("data\\*.txt", &result, p)); + + ABTS_INT_EQUAL(tc, NUM_FILES, result->nelts); + + list = (char **)result->elts; + for (i = 0; i < result->nelts; i++) { + char *dot = strrchr(list[i], '.'); + ABTS_STR_EQUAL(tc, dot, ".txt"); + } +} + +static void test_glob_currdir(abts_case *tc, void *data) +{ + int i; + char **list; + apr_array_header_t *result; + apr_filepath_set("data", p); + + APR_ASSERT_SUCCESS(tc, "glob match against *.txt with data as current", + apr_match_glob("*.txt", &result, p)); + + + ABTS_INT_EQUAL(tc, NUM_FILES, result->nelts); + + list = (char **)result->elts; + for (i = 0; i < result->nelts; i++) { + char *dot = strrchr(list[i], '.'); + ABTS_STR_EQUAL(tc, dot, ".txt"); + } + apr_filepath_set("..", p); +} + +abts_suite *testfnmatch(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_glob, NULL); + abts_run_test(suite, test_glob_currdir, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testglobalmutex.c b/srclib/apr/test/testglobalmutex.c new file mode 100644 index 0000000000..ccd7d7bea5 --- /dev/null +++ b/srclib/apr/test/testglobalmutex.c @@ -0,0 +1,135 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testglobalmutex.h" +#include "apr_thread_proc.h" +#include "apr_global_mutex.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "testutil.h" + +static void launch_child(abts_case *tc, apr_lockmech_e mech, + apr_proc_t *proc, apr_pool_t *p) +{ + apr_procattr_t *procattr; + const char *args[3]; + apr_status_t rv; + + rv = apr_procattr_create(&procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv); + + rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, + APR_NO_PIPE); + APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv); + + rv = apr_procattr_error_check_set(procattr, 1); + APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv); + + args[0] = "globalmutexchild" EXTENSION; + args[1] = (const char*)apr_itoa(p, (int)mech); + args[2] = NULL; + rv = apr_proc_create(proc, "./globalmutexchild" EXTENSION, args, NULL, + procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv); +} + +static int wait_child(abts_case *tc, apr_proc_t *proc) +{ + int exitcode; + apr_exit_why_e why; + + ABTS_ASSERT(tc, "Error waiting for child process", + apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE); + + ABTS_ASSERT(tc, "child didn't terminate normally", why == APR_PROC_EXIT); + return exitcode; +} + +/* return symbolic name for a locking meechanism */ +static const char *mutexname(apr_lockmech_e mech) +{ + switch (mech) { + case APR_LOCK_FCNTL: return "fcntl"; + case APR_LOCK_FLOCK: return "flock"; + case APR_LOCK_SYSVSEM: return "sysvsem"; + case APR_LOCK_PROC_PTHREAD: return "proc_pthread"; + case APR_LOCK_POSIXSEM: return "posixsem"; + case APR_LOCK_DEFAULT: return "default"; + default: return "unknown"; + } +} + +static void test_exclusive(abts_case *tc, void *data) +{ + apr_lockmech_e mech = *(apr_lockmech_e *)data; + apr_proc_t p1, p2, p3, p4; + apr_status_t rv; + apr_global_mutex_t *global_lock; + int x = 0; + abts_log_message("lock mechanism is: "); + abts_log_message(mutexname(mech)); + + rv = apr_global_mutex_create(&global_lock, LOCKNAME, mech, p); + APR_ASSERT_SUCCESS(tc, "Error creating mutex", rv); + + launch_child(tc, mech, &p1, p); + launch_child(tc, mech, &p2, p); + launch_child(tc, mech, &p3, p); + launch_child(tc, mech, &p4, p); + + x += wait_child(tc, &p1); + x += wait_child(tc, &p2); + x += wait_child(tc, &p3); + x += wait_child(tc, &p4); + + if (x != MAX_COUNTER) { + char buf[200]; + sprintf(buf, "global mutex '%s' failed: %d not %d", + mutexname(mech), x, MAX_COUNTER); + abts_fail(tc, buf, __LINE__); + } +} + +abts_suite *testglobalmutex(abts_suite *suite) +{ + apr_lockmech_e mech = APR_LOCK_DEFAULT; + + suite = ADD_SUITE(suite) + abts_run_test(suite, test_exclusive, &mech); +#if APR_HAS_POSIXSEM_SERIALIZE + mech = APR_LOCK_POSIXSEM; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_SYSVSEM_SERIALIZE + mech = APR_LOCK_SYSVSEM; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + mech = APR_LOCK_PROC_PTHREAD; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_FCNTL_SERIALIZE + mech = APR_LOCK_FCNTL; + abts_run_test(suite, test_exclusive, &mech); +#endif +#if APR_HAS_FLOCK_SERIALIZE + mech = APR_LOCK_FLOCK; + abts_run_test(suite, test_exclusive, &mech); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testglobalmutex.h b/srclib/apr/test/testglobalmutex.h new file mode 100644 index 0000000000..87581a2dec --- /dev/null +++ b/srclib/apr/test/testglobalmutex.h @@ -0,0 +1,27 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TESTGLOBALMUTEX_H +#define TESTGLOBALMUTEX_H + +/* set this to 255 so that the child processes can return it successfully. */ +#define MAX_ITER 255 +#define MAX_COUNTER (MAX_ITER * 4) + +#define LOCKNAME "data/apr_globalmutex.lock" + +#endif + diff --git a/srclib/apr/test/testhash.c b/srclib/apr/test/testhash.c new file mode 100644 index 0000000000..b2e2b0ac4f --- /dev/null +++ b/srclib/apr/test/testhash.c @@ -0,0 +1,431 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr.h" +#include "apr_strings.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_hash.h" + +static void dump_hash(apr_pool_t *p, apr_hash_t *h, char *str) +{ + apr_hash_index_t *hi; + char *val, *key; + apr_ssize_t len; + int i = 0; + + str[0] = '\0'; + + for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) { + apr_hash_this(hi,(void*) &key, &len, (void*) &val); + apr_snprintf(str, 8196, "%sKey %s (%" APR_SSIZE_T_FMT ") Value %s\n", + str, key, len, val); + i++; + } + apr_snprintf(str, 8196, "%s#entries %d\n", str, i); +} + +static void sum_hash(apr_pool_t *p, apr_hash_t *h, int *pcount, int *keySum, int *valSum) +{ + apr_hash_index_t *hi; + void *val, *key; + int count = 0; + + *keySum = 0; + *valSum = 0; + *pcount = 0; + for (hi = apr_hash_first(p, h); hi; hi = apr_hash_next(hi)) { + apr_hash_this(hi, (void*)&key, NULL, &val); + *valSum += *(int *)val; + *keySum += *(int *)key; + count++; + } + *pcount=count; +} + +static void hash_make(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); +} + +static void hash_set(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); + result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value", result); +} + +static void hash_reset(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); + result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value", result); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, "new"); + result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "new", result); +} + +static void same_value(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "same1", APR_HASH_KEY_STRING, "same"); + result = apr_hash_get(h, "same1", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "same", result); + + apr_hash_set(h, "same2", APR_HASH_KEY_STRING, "same"); + result = apr_hash_get(h, "same2", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "same", result); +} + +static unsigned int hash_custom( const char *key, apr_ssize_t *klen) +{ + unsigned int hash = 0; + while( *klen ) { + (*klen) --; + hash = hash * 33 + key[ *klen ]; + } + return hash; +} + +static void same_value_custom(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make_custom(p, hash_custom); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "same1", 5, "same"); + result = apr_hash_get(h, "same1", 5); + ABTS_STR_EQUAL(tc, "same", result); + + apr_hash_set(h, "same2", 5, "same"); + result = apr_hash_get(h, "same2", 5); + ABTS_STR_EQUAL(tc, "same", result); +} + +static void key_space(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key with space", APR_HASH_KEY_STRING, "value"); + result = apr_hash_get(h, "key with space", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value", result); +} + +/* This is kind of a hack, but I am just keeping an existing test. This is + * really testing apr_hash_first, apr_hash_next, and apr_hash_this which + * should be tested in three separate tests, but this will do for now. + */ +static void hash_traverse(abts_case *tc, void *data) +{ + apr_hash_t *h; + char str[8196]; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "should not see this"); + apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3"); + apr_hash_set(h, "FOO3", APR_HASH_KEY_STRING, "bar3"); + apr_hash_set(h, "FOO1", APR_HASH_KEY_STRING, "bar1"); + apr_hash_set(h, "FOO2", APR_HASH_KEY_STRING, "bar2"); + apr_hash_set(h, "FOO4", APR_HASH_KEY_STRING, "bar4"); + apr_hash_set(h, "SAME1", APR_HASH_KEY_STRING, "same"); + apr_hash_set(h, "SAME2", APR_HASH_KEY_STRING, "same"); + apr_hash_set(h, "OVERWRITE", APR_HASH_KEY_STRING, "Overwrite key"); + + dump_hash(p, h, str); + ABTS_STR_EQUAL(tc, "Key FOO1 (4) Value bar1\n" + "Key FOO2 (4) Value bar2\n" + "Key OVERWRITE (9) Value Overwrite key\n" + "Key FOO3 (4) Value bar3\n" + "Key SAME1 (5) Value same\n" + "Key FOO4 (4) Value bar4\n" + "Key SAME2 (5) Value same\n" + "#entries 7\n", str); +} + +/* This is kind of a hack, but I am just keeping an existing test. This is + * really testing apr_hash_first, apr_hash_next, and apr_hash_this which + * should be tested in three separate tests, but this will do for now. + */ +static void summation_test(abts_case *tc, void *data) +{ + apr_hash_t *h; + int sumKeys, sumVal, trySumKey, trySumVal; + int i, j, *val, *key; + + h =apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + sumKeys = 0; + sumVal = 0; + trySumKey = 0; + trySumVal = 0; + + for (i = 0; i < 100; i++) { + j = i * 10 + 1; + sumKeys += j; + sumVal += i; + key = apr_palloc(p, sizeof(int)); + *key = j; + val = apr_palloc(p, sizeof(int)); + *val = i; + apr_hash_set(h, key, sizeof(int), val); + } + + sum_hash(p, h, &i, &trySumKey, &trySumVal); + ABTS_INT_EQUAL(tc, 100, i); + ABTS_INT_EQUAL(tc, sumVal, trySumVal); + ABTS_INT_EQUAL(tc, sumKeys, trySumKey); +} + +static void delete_key(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + char *result = NULL; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); + apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2"); + + result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value", result); + + result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value2", result); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, NULL); + + result = apr_hash_get(h, "key", APR_HASH_KEY_STRING); + ABTS_PTR_EQUAL(tc, NULL, result); + + result = apr_hash_get(h, "key2", APR_HASH_KEY_STRING); + ABTS_STR_EQUAL(tc, "value2", result); +} + +static void hash_count_0(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + int count; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + count = apr_hash_count(h); + ABTS_INT_EQUAL(tc, 0, count); +} + +static void hash_count_1(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + int count; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key", APR_HASH_KEY_STRING, "value"); + + count = apr_hash_count(h); + ABTS_INT_EQUAL(tc, 1, count); +} + +static void hash_count_5(abts_case *tc, void *data) +{ + apr_hash_t *h = NULL; + int count; + + h = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, h); + + apr_hash_set(h, "key1", APR_HASH_KEY_STRING, "value1"); + apr_hash_set(h, "key2", APR_HASH_KEY_STRING, "value2"); + apr_hash_set(h, "key3", APR_HASH_KEY_STRING, "value3"); + apr_hash_set(h, "key4", APR_HASH_KEY_STRING, "value4"); + apr_hash_set(h, "key5", APR_HASH_KEY_STRING, "value5"); + + count = apr_hash_count(h); + ABTS_INT_EQUAL(tc, 5, count); +} + +static void overlay_empty(abts_case *tc, void *data) +{ + apr_hash_t *base = NULL; + apr_hash_t *overlay = NULL; + apr_hash_t *result = NULL; + int count; + char str[8196]; + + base = apr_hash_make(p); + overlay = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, base); + ABTS_PTR_NOTNULL(tc, overlay); + + apr_hash_set(base, "key1", APR_HASH_KEY_STRING, "value1"); + apr_hash_set(base, "key2", APR_HASH_KEY_STRING, "value2"); + apr_hash_set(base, "key3", APR_HASH_KEY_STRING, "value3"); + apr_hash_set(base, "key4", APR_HASH_KEY_STRING, "value4"); + apr_hash_set(base, "key5", APR_HASH_KEY_STRING, "value5"); + + result = apr_hash_overlay(p, overlay, base); + + count = apr_hash_count(result); + ABTS_INT_EQUAL(tc, 5, count); + + dump_hash(p, result, str); + ABTS_STR_EQUAL(tc, "Key key1 (4) Value value1\n" + "Key key2 (4) Value value2\n" + "Key key3 (4) Value value3\n" + "Key key4 (4) Value value4\n" + "Key key5 (4) Value value5\n" + "#entries 5\n", str); +} + +static void overlay_2unique(abts_case *tc, void *data) +{ + apr_hash_t *base = NULL; + apr_hash_t *overlay = NULL; + apr_hash_t *result = NULL; + int count; + char str[8196]; + + base = apr_hash_make(p); + overlay = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, base); + ABTS_PTR_NOTNULL(tc, overlay); + + apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1"); + apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2"); + apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3"); + apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4"); + apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5"); + + apr_hash_set(overlay, "overlay1", APR_HASH_KEY_STRING, "value1"); + apr_hash_set(overlay, "overlay2", APR_HASH_KEY_STRING, "value2"); + apr_hash_set(overlay, "overlay3", APR_HASH_KEY_STRING, "value3"); + apr_hash_set(overlay, "overlay4", APR_HASH_KEY_STRING, "value4"); + apr_hash_set(overlay, "overlay5", APR_HASH_KEY_STRING, "value5"); + + result = apr_hash_overlay(p, overlay, base); + + count = apr_hash_count(result); + ABTS_INT_EQUAL(tc, 10, count); + + dump_hash(p, result, str); + /* I don't know why these are out of order, but they are. I would probably + * consider this a bug, but others should comment. + */ + ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n" + "Key overlay1 (8) Value value1\n" + "Key overlay2 (8) Value value2\n" + "Key overlay3 (8) Value value3\n" + "Key overlay4 (8) Value value4\n" + "Key overlay5 (8) Value value5\n" + "Key base1 (5) Value value1\n" + "Key base2 (5) Value value2\n" + "Key base3 (5) Value value3\n" + "Key base4 (5) Value value4\n" + "#entries 10\n", str); +} + +static void overlay_same(abts_case *tc, void *data) +{ + apr_hash_t *base = NULL; + apr_hash_t *result = NULL; + int count; + char str[8196]; + + base = apr_hash_make(p); + ABTS_PTR_NOTNULL(tc, base); + + apr_hash_set(base, "base1", APR_HASH_KEY_STRING, "value1"); + apr_hash_set(base, "base2", APR_HASH_KEY_STRING, "value2"); + apr_hash_set(base, "base3", APR_HASH_KEY_STRING, "value3"); + apr_hash_set(base, "base4", APR_HASH_KEY_STRING, "value4"); + apr_hash_set(base, "base5", APR_HASH_KEY_STRING, "value5"); + + result = apr_hash_overlay(p, base, base); + + count = apr_hash_count(result); + ABTS_INT_EQUAL(tc, 5, count); + + dump_hash(p, result, str); + /* I don't know why these are out of order, but they are. I would probably + * consider this a bug, but others should comment. + */ + ABTS_STR_EQUAL(tc, "Key base5 (5) Value value5\n" + "Key base1 (5) Value value1\n" + "Key base2 (5) Value value2\n" + "Key base3 (5) Value value3\n" + "Key base4 (5) Value value4\n" + "#entries 5\n", str); +} + +abts_suite *testhash(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, hash_make, NULL); + abts_run_test(suite, hash_set, NULL); + abts_run_test(suite, hash_reset, NULL); + abts_run_test(suite, same_value, NULL); + abts_run_test(suite, same_value_custom, NULL); + abts_run_test(suite, key_space, NULL); + abts_run_test(suite, delete_key, NULL); + + abts_run_test(suite, hash_count_0, NULL); + abts_run_test(suite, hash_count_1, NULL); + abts_run_test(suite, hash_count_5, NULL); + + abts_run_test(suite, hash_traverse, NULL); + abts_run_test(suite, summation_test, NULL); + + abts_run_test(suite, overlay_empty, NULL); + abts_run_test(suite, overlay_2unique, NULL); + abts_run_test(suite, overlay_same, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testipsub.c b/srclib/apr/test/testipsub.c new file mode 100644 index 0000000000..a5743b0ae3 --- /dev/null +++ b/srclib/apr/test/testipsub.c @@ -0,0 +1,173 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_general.h" +#include "apr_network_io.h" +#include "apr_errno.h" + +static void test_bad_input(abts_case *tc, void *data) +{ + struct { + const char *ipstr; + const char *mask; + apr_status_t expected_rv; + } testcases[] = + { + /* so we have a few good inputs in here; sue me */ + {"my.host.name", NULL, APR_EINVAL} + ,{"127.0.0.256", NULL, APR_EBADIP} + ,{"127.0.0.1", NULL, APR_SUCCESS} + ,{"127.0.0.1", "32", APR_SUCCESS} + ,{"127.0.0.1", "1", APR_SUCCESS} + ,{"127.0.0.1", "15", APR_SUCCESS} + ,{"127.0.0.1", "-1", APR_EBADMASK} + ,{"127.0.0.1", "0", APR_EBADMASK} + ,{"127.0.0.1", "33", APR_EBADMASK} + ,{"127.0.0.1", "255.0.0.0", APR_SUCCESS} + ,{"127.0.0.1", "255.0", APR_EBADMASK} + ,{"127.0.0.1", "255.255.256.0", APR_EBADMASK} + ,{"127.0.0.1", "abc", APR_EBADMASK} + ,{"127", NULL, APR_SUCCESS} + ,{"127.0.0.1.2", NULL, APR_EBADIP} + ,{"127.0.0.1.2", "8", APR_EBADIP} + ,{"127", "255.0.0.0", APR_EBADIP} /* either EBADIP or EBADMASK seems fine */ +#if APR_HAVE_IPV6 + ,{"::1", NULL, APR_SUCCESS} + ,{"::1", "20", APR_SUCCESS} + ,{"::ffff:9.67.113.15", NULL, APR_EBADIP} /* yes, this is goodness */ + ,{"fe80::", "16", APR_SUCCESS} + ,{"fe80::", "255.0.0.0", APR_EBADMASK} + ,{"fe80::1", "0", APR_EBADMASK} + ,{"fe80::1", "-1", APR_EBADMASK} + ,{"fe80::1", "1", APR_SUCCESS} + ,{"fe80::1", "33", APR_SUCCESS} + ,{"fe80::1", "128", APR_SUCCESS} + ,{"fe80::1", "129", APR_EBADMASK} +#else + /* do some IPv6 stuff and verify that it fails with APR_EBADIP */ + ,{"::ffff:9.67.113.15", NULL, APR_EBADIP} +#endif + }; + int i; + apr_ipsubnet_t *ipsub; + apr_status_t rv; + + for (i = 0; i < (sizeof testcases / sizeof testcases[0]); i++) { + rv = apr_ipsubnet_create(&ipsub, testcases[i].ipstr, testcases[i].mask, p); + ABTS_INT_EQUAL(tc, rv, testcases[i].expected_rv); + } +} + +static void test_singleton_subnets(abts_case *tc, void *data) +{ + const char *v4addrs[] = { + "127.0.0.1", "129.42.18.99", "63.161.155.20", "207.46.230.229", "64.208.42.36", + "198.144.203.195", "192.18.97.241", "198.137.240.91", "62.156.179.119", + "204.177.92.181" + }; + apr_ipsubnet_t *ipsub; + apr_sockaddr_t *sa; + apr_status_t rv; + int i, j, rc; + + for (i = 0; i < sizeof v4addrs / sizeof v4addrs[0]; i++) { + rv = apr_ipsubnet_create(&ipsub, v4addrs[i], NULL, p); + ABTS_TRUE(tc, rv == APR_SUCCESS); + for (j = 0; j < sizeof v4addrs / sizeof v4addrs[0]; j++) { + rv = apr_sockaddr_info_get(&sa, v4addrs[j], APR_INET, 0, 0, p); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rc = apr_ipsubnet_test(ipsub, sa); + if (!strcmp(v4addrs[i], v4addrs[j])) { + ABTS_TRUE(tc, rc != 0); + } + else { + ABTS_TRUE(tc, rc == 0); + } + } + } + + /* same for v6? */ +} + +static void test_interesting_subnets(abts_case *tc, void *data) +{ + struct { + const char *ipstr, *mask; + int family; + char *in_subnet, *not_in_subnet; + } testcases[] = + { + {"9.67", NULL, APR_INET, "9.67.113.15", "10.1.2.3"} + ,{"9.67.0.0", "16", APR_INET, "9.67.113.15", "10.1.2.3"} + ,{"9.67.0.0", "255.255.0.0", APR_INET, "9.67.113.15", "10.1.2.3"} + ,{"9.67.113.99", "16", APR_INET, "9.67.113.15", "10.1.2.3"} + ,{"9.67.113.99", "255.255.255.0", APR_INET, "9.67.113.15", "10.1.2.3"} +#if APR_HAVE_IPV6 + ,{"fe80::", "8", APR_INET6, "fe80::1", "ff01::1"} + ,{"ff01::", "8", APR_INET6, "ff01::1", "fe80::1"} + ,{"3FFE:8160::", "28", APR_INET6, "3ffE:816e:abcd:1234::1", "3ffe:8170::1"} + ,{"127.0.0.1", NULL, APR_INET6, "::ffff:127.0.0.1", "fe80::1"} + ,{"127.0.0.1", "8", APR_INET6, "::ffff:127.0.0.1", "fe80::1"} +#endif + }; + apr_ipsubnet_t *ipsub; + apr_sockaddr_t *sa; + apr_status_t rv; + int i, rc; + + for (i = 0; i < sizeof testcases / sizeof testcases[0]; i++) { + rv = apr_ipsubnet_create(&ipsub, testcases[i].ipstr, testcases[i].mask, p); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rv = apr_sockaddr_info_get(&sa, testcases[i].in_subnet, testcases[i].family, 0, 0, p); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rc = apr_ipsubnet_test(ipsub, sa); + ABTS_TRUE(tc, rc != 0); + rv = apr_sockaddr_info_get(&sa, testcases[i].not_in_subnet, testcases[i].family, 0, 0, p); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rc = apr_ipsubnet_test(ipsub, sa); + ABTS_TRUE(tc, rc == 0); + } +} + +static void test_badmask_str(abts_case *tc, void *data) +{ + char buf[128]; + + ABTS_STR_EQUAL(tc, apr_strerror(APR_EBADMASK, buf, sizeof buf), + "The specified network mask is invalid."); +} + +static void test_badip_str(abts_case *tc, void *data) +{ + char buf[128]; + + ABTS_STR_EQUAL(tc, apr_strerror(APR_EBADIP, buf, sizeof buf), + "The specified IP address is invalid."); +} + +abts_suite *testipsub(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_bad_input, NULL); + abts_run_test(suite, test_singleton_subnets, NULL); + abts_run_test(suite, test_interesting_subnets, NULL); + abts_run_test(suite, test_badmask_str, NULL); + abts_run_test(suite, test_badip_str, NULL); + return suite; +} + diff --git a/srclib/apr/test/testlfs.c b/srclib/apr/test/testlfs.c new file mode 100644 index 0000000000..5f83b453b4 --- /dev/null +++ b/srclib/apr/test/testlfs.c @@ -0,0 +1,285 @@ +/* Copyright 2004 The Apache Software Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_poll.h" +#include "apr_strings.h" +#include "apr_lib.h" +#include "apr_mmap.h" +#include "testutil.h" + +/* Only enable these tests by default on platforms which support sparse + * files... just Unixes? */ +#if APR_HAS_LARGE_FILES && !defined(WIN32) && !defined(OS2) && !defined(NETWARE) +#define USE_LFS_TESTS + +/* Tests which create an 8Gb sparse file and then check it can be used + * as normal. */ + +static apr_off_t eightGb = APR_INT64_C(2) << 32; + +static int madefile = 0; + +#define PRECOND if (!madefile) { ABTS_NOT_IMPL(tc, "Large file tests not enabled"); return; } + +#define TESTDIR "lfstests" +#define TESTFILE "large.bin" +#define TESTFN "lfstests/large.bin" + +static void test_open(abts_case *tc, void *data) +{ + apr_file_t *f; + apr_status_t rv; + + rv = apr_dir_make(TESTDIR, APR_OS_DEFAULT, p); + if (rv && !APR_STATUS_IS_EEXIST(rv)) { + APR_ASSERT_SUCCESS(tc, "make test directory", rv); + } + + APR_ASSERT_SUCCESS(tc, "open file", + apr_file_open(&f, TESTFN, + APR_CREATE | APR_WRITE | APR_TRUNCATE, + APR_OS_DEFAULT, p)); + + rv = apr_file_trunc(f, eightGb); + + APR_ASSERT_SUCCESS(tc, "close large file", apr_file_close(f)); + + /* 8Gb may pass rlimits or filesystem limits */ + + if (APR_STATUS_IS_EINVAL(rv) +#ifdef EFBIG + || rv == EFBIG +#endif + ) { + ABTS_NOT_IMPL(tc, "Creation of large file (limited by rlimit or fs?)"); + } + else { + APR_ASSERT_SUCCESS(tc, "truncate file to 8gb", rv); + } + + madefile = rv == APR_SUCCESS; +} + +static void test_reopen(abts_case *tc, void *data) +{ + apr_file_t *fh; + apr_finfo_t finfo; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "re-open 8Gb file", + apr_file_open(&fh, TESTFN, APR_READ, APR_OS_DEFAULT, p)); + + APR_ASSERT_SUCCESS(tc, "file_info_get failed", + apr_file_info_get(&finfo, APR_FINFO_NORM, fh)); + + ABTS_ASSERT(tc, "file_info_get gave incorrect size", + finfo.size == eightGb); + + APR_ASSERT_SUCCESS(tc, "re-close large file", apr_file_close(fh)); +} + +static void test_stat(abts_case *tc, void *data) +{ + apr_finfo_t finfo; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "stat large file", + apr_stat(&finfo, TESTFN, APR_FINFO_NORM, p)); + + ABTS_ASSERT(tc, "stat gave incorrect size", finfo.size == eightGb); +} + +static void test_readdir(abts_case *tc, void *data) +{ + apr_dir_t *dh; + apr_status_t rv; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "open test directory", + apr_dir_open(&dh, TESTDIR, p)); + + do { + apr_finfo_t finfo; + + rv = apr_dir_read(&finfo, APR_FINFO_NORM, dh); + + if (rv == APR_SUCCESS && strcmp(finfo.name, TESTFILE) == 0) { + ABTS_ASSERT(tc, "apr_dir_read gave incorrect size for large file", + finfo.size == eightGb); + } + + } while (rv == APR_SUCCESS); + + if (!APR_STATUS_IS_ENOENT(rv)) { + APR_ASSERT_SUCCESS(tc, "apr_dir_read failed", rv); + } + + APR_ASSERT_SUCCESS(tc, "close test directory", + apr_dir_close(dh)); +} + +#define TESTSTR "Hello, world." + +static void test_append(abts_case *tc, void *data) +{ + apr_file_t *fh; + apr_finfo_t finfo; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "open 8Gb file for append", + apr_file_open(&fh, TESTFN, APR_WRITE | APR_APPEND, + APR_OS_DEFAULT, p)); + + APR_ASSERT_SUCCESS(tc, "append to 8Gb file", + apr_file_write_full(fh, TESTSTR, strlen(TESTSTR), NULL)); + + APR_ASSERT_SUCCESS(tc, "file_info_get failed", + apr_file_info_get(&finfo, APR_FINFO_NORM, fh)); + + ABTS_ASSERT(tc, "file_info_get gave incorrect size", + finfo.size == eightGb + strlen(TESTSTR)); + + APR_ASSERT_SUCCESS(tc, "close 8Gb file", apr_file_close(fh)); +} + +static void test_seek(abts_case *tc, void *data) +{ + apr_file_t *fh; + apr_off_t pos; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "open 8Gb file for writing", + apr_file_open(&fh, TESTFN, APR_WRITE, + APR_OS_DEFAULT, p)); + + pos = 0; + APR_ASSERT_SUCCESS(tc, "relative seek to end", + apr_file_seek(fh, APR_END, &pos)); + ABTS_ASSERT(tc, "seek to END gave 8Gb", pos == eightGb); + + pos = eightGb; + APR_ASSERT_SUCCESS(tc, "seek to 8Gb", apr_file_seek(fh, APR_SET, &pos)); + ABTS_ASSERT(tc, "seek gave 8Gb offset", pos == eightGb); + + pos = 0; + APR_ASSERT_SUCCESS(tc, "relative seek to 0", apr_file_seek(fh, APR_CUR, &pos)); + ABTS_ASSERT(tc, "relative seek gave 8Gb offset", pos == eightGb); + + apr_file_close(fh); +} + +static void test_write(abts_case *tc, void *data) +{ + apr_file_t *fh; + apr_off_t pos = eightGb - 4; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "re-open 8Gb file", + apr_file_open(&fh, TESTFN, APR_WRITE, APR_OS_DEFAULT, p)); + + APR_ASSERT_SUCCESS(tc, "seek to 8Gb - 4", + apr_file_seek(fh, APR_SET, &pos)); + ABTS_ASSERT(tc, "seek gave 8Gb-4 offset", pos == eightGb - 4); + + APR_ASSERT_SUCCESS(tc, "write magic string to 8Gb-4", + apr_file_write_full(fh, "FISH", 4, NULL)); + + APR_ASSERT_SUCCESS(tc, "close 8Gb file", apr_file_close(fh)); +} + + +#if APR_HAS_MMAP +static void test_mmap(abts_case *tc, void *data) +{ + apr_mmap_t *map; + apr_file_t *fh; + apr_size_t len = 16384; /* hopefully a multiple of the page size */ + apr_off_t off = eightGb - len; + void *ptr; + + PRECOND; + + APR_ASSERT_SUCCESS(tc, "open 8gb file for mmap", + apr_file_open(&fh, TESTFN, APR_READ, APR_OS_DEFAULT, p)); + + APR_ASSERT_SUCCESS(tc, "mmap 8Gb file", + apr_mmap_create(&map, fh, off, len, APR_MMAP_READ, p)); + + APR_ASSERT_SUCCESS(tc, "close file", apr_file_close(fh)); + + ABTS_ASSERT(tc, "mapped a 16K block", map->size == len); + + APR_ASSERT_SUCCESS(tc, "get pointer into mmaped region", + apr_mmap_offset(&ptr, map, len - 4)); + ABTS_ASSERT(tc, "pointer was not NULL", ptr != NULL); + + ABTS_ASSERT(tc, "found the magic string", memcmp(ptr, "FISH", 4) == 0); + + APR_ASSERT_SUCCESS(tc, "delete mmap handle", apr_mmap_delete(map)); +} +#endif /* APR_HAS_MMAP */ + +static void test_format(abts_case *tc, void *data) +{ + apr_off_t off; + + PRECOND; + + off = apr_atoi64(apr_off_t_toa(p, eightGb)); + + ABTS_ASSERT(tc, "apr_atoi64 parsed apr_off_t_toa result incorrectly", + off == eightGb); +} + +#else +static void test_nolfs(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "Large Files not supported"); +} +#endif + +abts_suite *testlfs(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#ifdef USE_LFS_TESTS + abts_run_test(suite, test_open, NULL); + abts_run_test(suite, test_reopen, NULL); + abts_run_test(suite, test_stat, NULL); + abts_run_test(suite, test_readdir, NULL); + abts_run_test(suite, test_seek, NULL); + abts_run_test(suite, test_append, NULL); + abts_run_test(suite, test_write, NULL); +#if APR_HAS_MMAP + abts_run_test(suite, test_mmap, NULL); +#endif + abts_run_test(suite, test_format, NULL); +#else + abts_run_test(suite, test_nolfs, NULL); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testlock.c b/srclib/apr/test/testlock.c new file mode 100644 index 0000000000..8e7943ddec --- /dev/null +++ b/srclib/apr/test/testlock.c @@ -0,0 +1,331 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_thread_mutex.h" +#include "apr_thread_rwlock.h" +#include "apr_thread_cond.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_getopt.h" +#include "testutil.h" + +#if APR_HAS_THREADS + +#define MAX_ITER 40000 +#define MAX_COUNTER 100000 +#define MAX_RETRY 5 + +static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data); +static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data); +static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data); +static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data); + +static apr_thread_mutex_t *thread_mutex; +static apr_thread_rwlock_t *rwlock; +static int i = 0, x = 0; + +static int buff[MAX_COUNTER]; + +struct { + apr_thread_mutex_t *mutex; + int nput; + int nval; +} put; + +struct { + apr_thread_mutex_t *mutex; + apr_thread_cond_t *cond; + int nready; +} nready; + +static apr_thread_mutex_t *timeout_mutex; +static apr_thread_cond_t *timeout_cond; + +static void *APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data) +{ + int exitLoop = 1; + + while (1) + { + apr_thread_rwlock_rdlock(rwlock); + if (i == MAX_ITER) + exitLoop = 0; + apr_thread_rwlock_unlock(rwlock); + + if (!exitLoop) + break; + + apr_thread_rwlock_wrlock(rwlock); + if (i != MAX_ITER) + { + i++; + x++; + } + apr_thread_rwlock_unlock(rwlock); + } + return NULL; +} + +static void *APR_THREAD_FUNC thread_mutex_function(apr_thread_t *thd, void *data) +{ + int exitLoop = 1; + + /* slight delay to allow things to settle */ + apr_sleep (1); + + while (1) + { + apr_thread_mutex_lock(thread_mutex); + if (i == MAX_ITER) + exitLoop = 0; + else + { + i++; + x++; + } + apr_thread_mutex_unlock(thread_mutex); + + if (!exitLoop) + break; + } + return NULL; +} + +static void *APR_THREAD_FUNC thread_cond_producer(apr_thread_t *thd, void *data) +{ + for (;;) { + apr_thread_mutex_lock(put.mutex); + if (put.nput >= MAX_COUNTER) { + apr_thread_mutex_unlock(put.mutex); + return NULL; + } + buff[put.nput] = put.nval; + put.nput++; + put.nval++; + apr_thread_mutex_unlock(put.mutex); + + apr_thread_mutex_lock(nready.mutex); + if (nready.nready == 0) + apr_thread_cond_signal(nready.cond); + nready.nready++; + apr_thread_mutex_unlock(nready.mutex); + + *((int *) data) += 1; + } + + return NULL; +} + +static void *APR_THREAD_FUNC thread_cond_consumer(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < MAX_COUNTER; i++) { + apr_thread_mutex_lock(nready.mutex); + while (nready.nready == 0) + apr_thread_cond_wait(nready.cond, nready.mutex); + nready.nready--; + apr_thread_mutex_unlock(nready.mutex); + + if (buff[i] != i) + printf("buff[%d] = %d\n", i, buff[i]); + } + + return NULL; +} + +static void test_thread_mutex(abts_case *tc, void *data) +{ + apr_thread_t *t1, *t2, *t3, *t4; + apr_status_t s1, s2, s3, s4; + + s1 = apr_thread_mutex_create(&thread_mutex, APR_THREAD_MUTEX_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s1); + ABTS_PTR_NOTNULL(tc, thread_mutex); + + i = 0; + x = 0; + + s1 = apr_thread_create(&t1, NULL, thread_mutex_function, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s1); + s2 = apr_thread_create(&t2, NULL, thread_mutex_function, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s2); + s3 = apr_thread_create(&t3, NULL, thread_mutex_function, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s3); + s4 = apr_thread_create(&t4, NULL, thread_mutex_function, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s4); + + apr_thread_join(&s1, t1); + apr_thread_join(&s2, t2); + apr_thread_join(&s3, t3); + apr_thread_join(&s4, t4); + + ABTS_INT_EQUAL(tc, MAX_ITER, x); +} + +static void test_thread_rwlock(abts_case *tc, void *data) +{ + apr_thread_t *t1, *t2, *t3, *t4; + apr_status_t s1, s2, s3, s4; + + s1 = apr_thread_rwlock_create(&rwlock, p); + if (s1 == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "rwlocks not implemented"); + return; + } + APR_ASSERT_SUCCESS(tc, "rwlock_create", s1); + ABTS_PTR_NOTNULL(tc, rwlock); + + i = 0; + x = 0; + + s1 = apr_thread_create(&t1, NULL, thread_rwlock_func, NULL, p); + APR_ASSERT_SUCCESS(tc, "create thread 1", s1); + s2 = apr_thread_create(&t2, NULL, thread_rwlock_func, NULL, p); + APR_ASSERT_SUCCESS(tc, "create thread 2", s2); + s3 = apr_thread_create(&t3, NULL, thread_rwlock_func, NULL, p); + APR_ASSERT_SUCCESS(tc, "create thread 3", s3); + s4 = apr_thread_create(&t4, NULL, thread_rwlock_func, NULL, p); + APR_ASSERT_SUCCESS(tc, "create thread 4", s4); + + apr_thread_join(&s1, t1); + apr_thread_join(&s2, t2); + apr_thread_join(&s3, t3); + apr_thread_join(&s4, t4); + + ABTS_INT_EQUAL(tc, MAX_ITER, x); +} + +static void test_cond(abts_case *tc, void *data) +{ + apr_thread_t *p1, *p2, *p3, *p4, *c1; + apr_status_t s0, s1, s2, s3, s4; + int count1, count2, count3, count4; + int sum; + + APR_ASSERT_SUCCESS(tc, "create put mutex", + apr_thread_mutex_create(&put.mutex, + APR_THREAD_MUTEX_DEFAULT, p)); + ABTS_PTR_NOTNULL(tc, put.mutex); + + APR_ASSERT_SUCCESS(tc, "create nready mutex", + apr_thread_mutex_create(&nready.mutex, + APR_THREAD_MUTEX_DEFAULT, p)); + ABTS_PTR_NOTNULL(tc, nready.mutex); + + APR_ASSERT_SUCCESS(tc, "create condvar", + apr_thread_cond_create(&nready.cond, p)); + ABTS_PTR_NOTNULL(tc, nready.cond); + + count1 = count2 = count3 = count4 = 0; + put.nput = put.nval = 0; + nready.nready = 0; + i = 0; + x = 0; + + s0 = apr_thread_create(&p1, NULL, thread_cond_producer, &count1, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s0); + s1 = apr_thread_create(&p2, NULL, thread_cond_producer, &count2, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s1); + s2 = apr_thread_create(&p3, NULL, thread_cond_producer, &count3, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s2); + s3 = apr_thread_create(&p4, NULL, thread_cond_producer, &count4, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s3); + s4 = apr_thread_create(&c1, NULL, thread_cond_consumer, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s4); + + apr_thread_join(&s0, p1); + apr_thread_join(&s1, p2); + apr_thread_join(&s2, p3); + apr_thread_join(&s3, p4); + apr_thread_join(&s4, c1); + + APR_ASSERT_SUCCESS(tc, "destroy condvar", + apr_thread_cond_destroy(nready.cond)); + + sum = count1 + count2 + count3 + count4; + /* + printf("count1 = %d count2 = %d count3 = %d count4 = %d\n", + count1, count2, count3, count4); + */ + ABTS_INT_EQUAL(tc, MAX_COUNTER, sum); +} + +static void test_timeoutcond(abts_case *tc, void *data) +{ + apr_status_t s; + apr_interval_time_t timeout; + apr_time_t begin, end; + int i; + + s = apr_thread_mutex_create(&timeout_mutex, APR_THREAD_MUTEX_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s); + ABTS_PTR_NOTNULL(tc, timeout_mutex); + + s = apr_thread_cond_create(&timeout_cond, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, s); + ABTS_PTR_NOTNULL(tc, timeout_cond); + + timeout = apr_time_from_sec(5); + + for (i = 0; i < MAX_RETRY; i++) { + apr_thread_mutex_lock(timeout_mutex); + + begin = apr_time_now(); + s = apr_thread_cond_timedwait(timeout_cond, timeout_mutex, timeout); + end = apr_time_now(); + apr_thread_mutex_unlock(timeout_mutex); + + if (s != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(s)) { + continue; + } + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(s)); + ABTS_ASSERT(tc, "Timer returned too late", end - begin - timeout < 100000); + break; + } + ABTS_ASSERT(tc, "Too many retries", i < MAX_RETRY); + APR_ASSERT_SUCCESS(tc, "Unable to destroy the conditional", + apr_thread_cond_destroy(timeout_cond)); +} + +#endif /* !APR_HAS_THREADS */ + +#if !APR_HAS_THREADS +static void threads_not_impl(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "Threads not implemented on this platform"); +} +#endif + + +abts_suite *testlock(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if !APR_HAS_THREADS + abts_run_test(suite, threads_not_impl, NULL); +#else + abts_run_test(suite, test_thread_mutex, NULL); + abts_run_test(suite, test_thread_rwlock, NULL); + abts_run_test(suite, test_cond, NULL); + abts_run_test(suite, test_timeoutcond, NULL); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testlockperf.c b/srclib/apr/test/testlockperf.c new file mode 100644 index 0000000000..c0c7236f13 --- /dev/null +++ b/srclib/apr/test/testlockperf.c @@ -0,0 +1,282 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_thread_proc.h" +#include "apr_thread_mutex.h" +#include "apr_thread_rwlock.h" +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_getopt.h" +#include "errno.h" +#include +#include +#include "testutil.h" + +#if !APR_HAS_THREADS +int main(void) +{ + printf("This program won't work on this platform because there is no " + "support for threads.\n"); + return 0; +} +#else /* !APR_HAS_THREADS */ + +#define MAX_COUNTER 1000000 +#define MAX_THREADS 6 + +static long mutex_counter; + +static apr_thread_mutex_t *thread_lock; +void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data); +apr_status_t test_thread_mutex(int num_threads); /* apr_thread_mutex_t */ + +static apr_thread_rwlock_t *thread_rwlock; +void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data); +apr_status_t test_thread_rwlock(int num_threads); /* apr_thread_rwlock_t */ + +int test_thread_mutex_nested(int num_threads); + +apr_pool_t *pool; +int i = 0, x = 0; + +void * APR_THREAD_FUNC thread_mutex_func(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < MAX_COUNTER; i++) { + apr_thread_mutex_lock(thread_lock); + mutex_counter++; + apr_thread_mutex_unlock(thread_lock); + } + return NULL; +} + +void * APR_THREAD_FUNC thread_rwlock_func(apr_thread_t *thd, void *data) +{ + int i; + + for (i = 0; i < MAX_COUNTER; i++) { + apr_thread_rwlock_wrlock(thread_rwlock); + mutex_counter++; + apr_thread_rwlock_unlock(thread_rwlock); + } + return NULL; +} + +int test_thread_mutex(int num_threads) +{ + apr_thread_t *t[MAX_THREADS]; + apr_status_t s[MAX_THREADS]; + apr_time_t time_start, time_stop; + int i; + + mutex_counter = 0; + + printf("apr_thread_mutex_t Tests\n"); + printf("%-60s", " Initializing the apr_thread_mutex_t (UNNESTED)"); + s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_UNNESTED, pool); + if (s[0] != APR_SUCCESS) { + printf("Failed!\n"); + return s[0]; + } + printf("OK\n"); + + apr_thread_mutex_lock(thread_lock); + /* set_concurrency(4)? -aaron */ + printf(" Starting %d threads ", num_threads); + for (i = 0; i < num_threads; ++i) { + s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool); + if (s[i] != APR_SUCCESS) { + printf("Failed!\n"); + return s[i]; + } + } + printf("OK\n"); + + time_start = apr_time_now(); + apr_thread_mutex_unlock(thread_lock); + + /* printf("%-60s", " Waiting for threads to exit"); */ + for (i = 0; i < num_threads; ++i) { + apr_thread_join(&s[i], t[i]); + } + /* printf("OK\n"); */ + + time_stop = apr_time_now(); + printf("microseconds: %" APR_INT64_T_FMT " usec\n", + (time_stop - time_start)); + if (mutex_counter != MAX_COUNTER * num_threads) + printf("error: counter = %ld\n", mutex_counter); + + return APR_SUCCESS; +} + +int test_thread_mutex_nested(int num_threads) +{ + apr_thread_t *t[MAX_THREADS]; + apr_status_t s[MAX_THREADS]; + apr_time_t time_start, time_stop; + int i; + + mutex_counter = 0; + + printf("apr_thread_mutex_t Tests\n"); + printf("%-60s", " Initializing the apr_thread_mutex_t (NESTED)"); + s[0] = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_NESTED, pool); + if (s[0] != APR_SUCCESS) { + printf("Failed!\n"); + return s[0]; + } + printf("OK\n"); + + apr_thread_mutex_lock(thread_lock); + /* set_concurrency(4)? -aaron */ + printf(" Starting %d threads ", num_threads); + for (i = 0; i < num_threads; ++i) { + s[i] = apr_thread_create(&t[i], NULL, thread_mutex_func, NULL, pool); + if (s[i] != APR_SUCCESS) { + printf("Failed!\n"); + return s[i]; + } + } + printf("OK\n"); + + time_start = apr_time_now(); + apr_thread_mutex_unlock(thread_lock); + + /* printf("%-60s", " Waiting for threads to exit"); */ + for (i = 0; i < num_threads; ++i) { + apr_thread_join(&s[i], t[i]); + } + /* printf("OK\n"); */ + + time_stop = apr_time_now(); + printf("microseconds: %" APR_INT64_T_FMT " usec\n", + (time_stop - time_start)); + if (mutex_counter != MAX_COUNTER * num_threads) + printf("error: counter = %ld\n", mutex_counter); + + return APR_SUCCESS; +} + +int test_thread_rwlock(int num_threads) +{ + apr_thread_t *t[MAX_THREADS]; + apr_status_t s[MAX_THREADS]; + apr_time_t time_start, time_stop; + int i; + + mutex_counter = 0; + + printf("apr_thread_rwlock_t Tests\n"); + printf("%-60s", " Initializing the apr_thread_rwlock_t"); + s[0] = apr_thread_rwlock_create(&thread_rwlock, pool); + if (s[0] != APR_SUCCESS) { + printf("Failed!\n"); + return s[0]; + } + printf("OK\n"); + + apr_thread_rwlock_wrlock(thread_rwlock); + /* set_concurrency(4)? -aaron */ + printf(" Starting %d threads ", num_threads); + for (i = 0; i < num_threads; ++i) { + s[i] = apr_thread_create(&t[i], NULL, thread_rwlock_func, NULL, pool); + if (s[i] != APR_SUCCESS) { + printf("Failed!\n"); + return s[i]; + } + } + printf("OK\n"); + + time_start = apr_time_now(); + apr_thread_rwlock_unlock(thread_rwlock); + + /* printf("%-60s", " Waiting for threads to exit"); */ + for (i = 0; i < num_threads; ++i) { + apr_thread_join(&s[i], t[i]); + } + /* printf("OK\n"); */ + + time_stop = apr_time_now(); + printf("microseconds: %" APR_INT64_T_FMT " usec\n", + (time_stop - time_start)); + if (mutex_counter != MAX_COUNTER * num_threads) + printf("error: counter = %ld\n", mutex_counter); + + return APR_SUCCESS; +} + +int main(int argc, const char * const *argv) +{ + apr_status_t rv; + char errmsg[200]; + const char *lockname = "multi.lock"; + apr_getopt_t *opt; + char optchar; + const char *optarg; + + printf("APR Lock Performance Test\n==============\n\n"); + + apr_initialize(); + atexit(apr_terminate); + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) + exit(-1); + + if ((rv = apr_getopt_init(&opt, pool, argc, argv)) != APR_SUCCESS) { + fprintf(stderr, "Could not set up to parse options: [%d] %s\n", + rv, apr_strerror(rv, errmsg, sizeof errmsg)); + exit(-1); + } + + while ((rv = apr_getopt(opt, "f:", &optchar, &optarg)) == APR_SUCCESS) { + if (optchar == 'f') { + lockname = optarg; + } + } + + if (rv != APR_SUCCESS && rv != APR_EOF) { + fprintf(stderr, "Could not parse options: [%d] %s\n", + rv, apr_strerror(rv, errmsg, sizeof errmsg)); + exit(-1); + } + + for (i = 1; i <= MAX_THREADS; ++i) { + if ((rv = test_thread_mutex(i)) != APR_SUCCESS) { + fprintf(stderr,"thread_mutex test failed : [%d] %s\n", + rv, apr_strerror(rv, (char*)errmsg, 200)); + exit(-3); + } + + if ((rv = test_thread_mutex_nested(i)) != APR_SUCCESS) { + fprintf(stderr,"thread_mutex (NESTED) test failed : [%d] %s\n", + rv, apr_strerror(rv, (char*)errmsg, 200)); + exit(-4); + } + + if ((rv = test_thread_rwlock(i)) != APR_SUCCESS) { + fprintf(stderr,"thread_rwlock test failed : [%d] %s\n", + rv, apr_strerror(rv, (char*)errmsg, 200)); + exit(-6); + } + } + + return 0; +} + +#endif /* !APR_HAS_THREADS */ diff --git a/srclib/apr/test/testmmap.c b/srclib/apr/test/testmmap.c new file mode 100644 index 0000000000..917ab31f36 --- /dev/null +++ b/srclib/apr/test/testmmap.c @@ -0,0 +1,153 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_mmap.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_file_io.h" +#include "apr_strings.h" + +/* hmmm, what is a truly portable define for the max path + * length on a platform? + */ +#define PATH_LEN 255 +#define TEST_STRING "This is the MMAP data file."APR_EOL_STR + +#if !APR_HAS_MMAP +static void not_implemented(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "User functions"); +} + +#else + +static apr_mmap_t *themmap = NULL; +static apr_file_t *thefile = NULL; +static char *file1; +static apr_finfo_t finfo; +static int fsize; + +static void create_filename(abts_case *tc, void *data) +{ + char *oldfileptr; + + apr_filepath_get(&file1, 0, p); +#ifndef NETWARE +#ifdef WIN32 + ABTS_TRUE(tc, file1[1] == ':'); +#else + ABTS_TRUE(tc, file1[0] == '/'); +#endif +#endif + ABTS_TRUE(tc, file1[strlen(file1) - 1] != '/'); + + oldfileptr = file1; + file1 = apr_pstrcat(p, file1,"/data/mmap_datafile.txt" ,NULL); + ABTS_TRUE(tc, oldfileptr != file1); +} + +static void test_file_close(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_file_close(thefile); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); +} + +static void test_file_open(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_file_open(&thefile, file1, APR_READ, APR_UREAD | APR_GREAD, p); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); + ABTS_PTR_NOTNULL(tc, thefile); +} + +static void test_get_filesize(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_file_info_get(&finfo, APR_FINFO_NORM, thefile); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); + ABTS_INT_EQUAL(tc, fsize, finfo.size); +} + +static void test_mmap_create(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_mmap_create(&themmap, thefile, 0, finfo.size, APR_MMAP_READ, p); + ABTS_PTR_NOTNULL(tc, themmap); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); +} + +static void test_mmap_contents(abts_case *tc, void *data) +{ + + ABTS_PTR_NOTNULL(tc, themmap); + ABTS_PTR_NOTNULL(tc, themmap->mm); + ABTS_INT_EQUAL(tc, fsize, themmap->size); + + /* Must use nEquals since the string is not guaranteed to be NULL terminated */ + ABTS_STR_NEQUAL(tc, themmap->mm, TEST_STRING, fsize); +} + +static void test_mmap_delete(abts_case *tc, void *data) +{ + apr_status_t rv; + + ABTS_PTR_NOTNULL(tc, themmap); + rv = apr_mmap_delete(themmap); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); +} + +static void test_mmap_offset(abts_case *tc, void *data) +{ + apr_status_t rv; + void *addr; + + ABTS_PTR_NOTNULL(tc, themmap); + rv = apr_mmap_offset(&addr, themmap, 5); + + /* Must use nEquals since the string is not guaranteed to be NULL terminated */ + ABTS_STR_NEQUAL(tc, addr, TEST_STRING + 5, fsize-5); +} +#endif + +abts_suite *testmmap(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if APR_HAS_MMAP + fsize = strlen(TEST_STRING); + + abts_run_test(suite, create_filename, NULL); + abts_run_test(suite, test_file_open, NULL); + abts_run_test(suite, test_get_filesize, NULL); + abts_run_test(suite, test_mmap_create, NULL); + abts_run_test(suite, test_mmap_contents, NULL); + abts_run_test(suite, test_mmap_offset, NULL); + abts_run_test(suite, test_mmap_delete, NULL); + abts_run_test(suite, test_file_close, NULL); +#else + abts_run_test(suite, not_implemented, NULL); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testmutexscope.c b/srclib/apr/test/testmutexscope.c new file mode 100644 index 0000000000..087f15d1c0 --- /dev/null +++ b/srclib/apr/test/testmutexscope.c @@ -0,0 +1,218 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "apr.h" +#include "apr_general.h" +#include "apr_proc_mutex.h" +#include "apr_global_mutex.h" +#include "apr_thread_proc.h" + +#if !APR_HAS_THREADS +int main(void) +{ + printf("This test requires APR thread support.\n"); + return 0; +} + +#else /* APR_HAS_THREADS */ + +static apr_thread_mutex_t *thread_mutex; +static apr_proc_mutex_t *proc_mutex; +static apr_global_mutex_t *global_mutex; +static apr_pool_t *p; +static volatile int counter; +typedef enum {TEST_GLOBAL, TEST_PROC} test_mode_e; + +static void lock_init(apr_lockmech_e mech, test_mode_e test_mode) +{ + if (test_mode == TEST_PROC) { + assert(apr_proc_mutex_create(&proc_mutex, + NULL, + mech, + p) == APR_SUCCESS); + } + else { + assert(apr_global_mutex_create(&global_mutex, + NULL, + mech, + p) == APR_SUCCESS); + } +} + +static void lock_destroy(test_mode_e test_mode) +{ + if (test_mode == TEST_PROC) { + assert(apr_proc_mutex_destroy(proc_mutex) == APR_SUCCESS); + } + else { + assert(apr_global_mutex_destroy(global_mutex) == APR_SUCCESS); + } +} + +static void lock_grab(test_mode_e test_mode) +{ + if (test_mode == TEST_PROC) { + assert(apr_proc_mutex_lock(proc_mutex) == APR_SUCCESS); + } + else { + assert(apr_global_mutex_lock(global_mutex) == APR_SUCCESS); + } +} + +static void lock_release(test_mode_e test_mode) +{ + if (test_mode == TEST_PROC) { + assert(apr_proc_mutex_unlock(proc_mutex) == APR_SUCCESS); + } + else { + assert(apr_global_mutex_unlock(global_mutex) == APR_SUCCESS); + } +} + +static void * APR_THREAD_FUNC eachThread(apr_thread_t *id, void *p) +{ + test_mode_e test_mode = (test_mode_e)p; + + lock_grab(test_mode); + ++counter; + assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); + assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); + lock_release(test_mode); + return NULL; +} + +static void test_mech_mode(apr_lockmech_e mech, const char *mech_name, + test_mode_e test_mode) +{ + apr_thread_t *threads[20]; + int numThreads = 5; + int i; + apr_status_t rv; + + printf("Trying %s mutexes with mechanism `%s'...\n", + test_mode == TEST_GLOBAL ? "global" : "proc", mech_name); + + assert(numThreads <= sizeof(threads) / sizeof(threads[0])); + + assert(apr_pool_create(&p, NULL) == APR_SUCCESS); + + assert(apr_thread_mutex_create(&thread_mutex, 0, p) == APR_SUCCESS); + assert(apr_thread_mutex_lock(thread_mutex) == APR_SUCCESS); + + lock_init(mech, test_mode); + + counter = 0; + + i = 0; + while (i < numThreads) + { + rv = apr_thread_create(&threads[i], + NULL, + eachThread, + (void *)test_mode, + p); + if (rv != APR_SUCCESS) { + fprintf(stderr, "apr_thread_create->%d\n", rv); + exit(1); + } + ++i; + } + + apr_sleep(apr_time_from_sec(5)); + + if (test_mode == TEST_PROC) { + printf(" Mutex mechanism `%s' is %sglobal in scope on this platform.\n", + mech_name, counter == 1 ? "" : "not "); + } + else { + if (counter != 1) { + fprintf(stderr, "\n!!!apr_global_mutex operations are broken on this " + "platform for mutex mechanism `%s'!\n" + "They don't block out threads within the same process.\n", + mech_name); + fprintf(stderr, "counter value: %d\n", counter); + exit(1); + } + else { + printf(" no problems encountered...\n"); + } + } + + assert(apr_thread_mutex_unlock(thread_mutex) == APR_SUCCESS); + + i = 0; + while (i < numThreads) + { + apr_status_t ignored; + + rv = apr_thread_join(&ignored, + threads[i]); + assert(rv == APR_SUCCESS); + ++i; + } + + lock_destroy(test_mode); + apr_thread_mutex_destroy(thread_mutex); + apr_pool_destroy(p); +} + +static void test_mech(apr_lockmech_e mech, const char *mech_name) +{ + test_mech_mode(mech, mech_name, TEST_PROC); + test_mech_mode(mech, mech_name, TEST_GLOBAL); +} + +int main(void) +{ + struct { + apr_lockmech_e mech; + const char *mech_name; + } lockmechs[] = { + {APR_LOCK_DEFAULT, "default"} +#if APR_HAS_FLOCK_SERIALIZE + ,{APR_LOCK_FLOCK, "flock"} +#endif +#if APR_HAS_SYSVSEM_SERIALIZE + ,{APR_LOCK_SYSVSEM, "sysvsem"} +#endif +#if APR_HAS_POSIXSEM_SERIALIZE + ,{APR_LOCK_POSIXSEM, "posix"} +#endif +#if APR_HAS_FCNTL_SERIALIZE + ,{APR_LOCK_FCNTL, "fcntl"} +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + ,{APR_LOCK_PROC_PTHREAD, "proc_pthread"} +#endif + }; + int i; + + assert(apr_initialize() == APR_SUCCESS); + + for (i = 0; i < sizeof(lockmechs) / sizeof(lockmechs[0]); i++) { + test_mech(lockmechs[i].mech, lockmechs[i].mech_name); + } + + apr_terminate(); + return 0; +} + +#endif /* APR_HAS_THREADS */ diff --git a/srclib/apr/test/testnames.c b/srclib/apr/test/testnames.c new file mode 100644 index 0000000000..b47cd43c6c --- /dev/null +++ b/srclib/apr/test/testnames.c @@ -0,0 +1,214 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_file_io.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_lib.h" + +#if WIN32 +#define ABS_ROOT "C:/" +#elif defined(NETWARE) +#define ABS_ROOT "SYS:/" +#else +#define ABS_ROOT "/" +#endif + +static void merge_aboveroot(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + char errmsg[256]; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"bar", APR_FILEPATH_NOTABOVEROOT, + p); + apr_strerror(rv, errmsg, sizeof(errmsg)); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EABOVEROOT(rv)); + ABTS_PTR_EQUAL(tc, NULL, dstpath); + ABTS_STR_EQUAL(tc, "The given path was above the root path", errmsg); +} + +static void merge_belowroot(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"foo/bar", + APR_FILEPATH_NOTABOVEROOT, p); + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar", dstpath); +} + +static void merge_noflag(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo", ABS_ROOT"foo/bar", 0, p); + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar", dstpath); +} + +static void merge_dotdot(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz", 0, p); + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT"foo/baz", dstpath); + + rv = apr_filepath_merge(&dstpath, "", "../test", 0, p); + ABTS_INT_EQUAL(tc, 0, APR_SUCCESS); + ABTS_STR_EQUAL(tc, "../test", dstpath); + + /* Very dangerous assumptions here about what the cwd is. However, let's assume + * that the testall is invoked from within apr/test/ so the following test should + * return ../test unless a previously fixed bug remains or the developer changes + * the case of the test directory: + */ + rv = apr_filepath_merge(&dstpath, "", "../test", APR_FILEPATH_TRUENAME, p); + ABTS_INT_EQUAL(tc, 0, APR_SUCCESS); + ABTS_STR_EQUAL(tc, "../test", dstpath); +} + +static void merge_secure(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../bar/baz", 0, p); + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT"foo/bar/baz", dstpath); +} + +static void merge_notrel(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz", + APR_FILEPATH_NOTRELATIVE, p); + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT"foo/baz", dstpath); +} + +static void merge_notrelfail(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + char errmsg[256]; + + rv = apr_filepath_merge(&dstpath, "foo/bar", "../baz", + APR_FILEPATH_NOTRELATIVE, p); + apr_strerror(rv, errmsg, sizeof(errmsg)); + + ABTS_PTR_EQUAL(tc, NULL, dstpath); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ERELATIVE(rv)); + ABTS_STR_EQUAL(tc, "The given path is relative", errmsg); +} + +static void merge_notabsfail(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + char errmsg[256]; + + rv = apr_filepath_merge(&dstpath, ABS_ROOT"foo/bar", "../baz", + APR_FILEPATH_NOTABSOLUTE, p); + apr_strerror(rv, errmsg, sizeof(errmsg)); + + ABTS_PTR_EQUAL(tc, NULL, dstpath); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EABSOLUTE(rv)); + ABTS_STR_EQUAL(tc, "The given path is absolute", errmsg); +} + +static void merge_notabs(abts_case *tc, void *data) +{ + apr_status_t rv; + char *dstpath = NULL; + + rv = apr_filepath_merge(&dstpath, "foo/bar", "../baz", + APR_FILEPATH_NOTABSOLUTE, p); + + ABTS_PTR_NOTNULL(tc, dstpath); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "foo/baz", dstpath); +} + +static void root_absolute(abts_case *tc, void *data) +{ + apr_status_t rv; + const char *root = NULL; + const char *path = ABS_ROOT"foo/bar"; + + rv = apr_filepath_root(&root, &path, 0, p); + + ABTS_PTR_NOTNULL(tc, root); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, ABS_ROOT, root); +} + +static void root_relative(abts_case *tc, void *data) +{ + apr_status_t rv; + const char *root = NULL; + const char *path = "foo/bar"; + char errmsg[256]; + + rv = apr_filepath_root(&root, &path, 0, p); + apr_strerror(rv, errmsg, sizeof(errmsg)); + + ABTS_PTR_EQUAL(tc, NULL, root); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_ERELATIVE(rv)); + ABTS_STR_EQUAL(tc, "The given path is relative", errmsg); +} + + +#if 0 + root_result(rootpath); + root_result(addpath); +} +#endif + +abts_suite *testnames(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, merge_aboveroot, NULL); + abts_run_test(suite, merge_belowroot, NULL); + abts_run_test(suite, merge_noflag, NULL); + abts_run_test(suite, merge_dotdot, NULL); + abts_run_test(suite, merge_secure, NULL); + abts_run_test(suite, merge_notrel, NULL); + abts_run_test(suite, merge_notrelfail, NULL); + abts_run_test(suite, merge_notabs, NULL); + abts_run_test(suite, merge_notabsfail, NULL); + + abts_run_test(suite, root_absolute, NULL); + abts_run_test(suite, root_relative, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testoc.c b/srclib/apr/test/testoc.c new file mode 100644 index 0000000000..b20393b372 --- /dev/null +++ b/srclib/apr/test/testoc.c @@ -0,0 +1,117 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_thread_proc.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" + +#if APR_HAS_OTHER_CHILD + +static char reasonstr[256]; + +static void ocmaint(int reason, void *data, int status) +{ + switch (reason) { + case APR_OC_REASON_DEATH: + apr_cpystrn(reasonstr, "APR_OC_REASON_DEATH", + strlen("APR_OC_REASON_DEATH") + 1); + break; + case APR_OC_REASON_LOST: + apr_cpystrn(reasonstr, "APR_OC_REASON_LOST", + strlen("APR_OC_REASON_LOST") + 1); + break; + case APR_OC_REASON_UNWRITABLE: + apr_cpystrn(reasonstr, "APR_OC_REASON_UNWRITEABLE", + strlen("APR_OC_REASON_UNWRITEABLE") + 1); + break; + case APR_OC_REASON_RESTART: + apr_cpystrn(reasonstr, "APR_OC_REASON_RESTART", + strlen("APR_OC_REASON_RESTART") + 1); + break; + } +} + +#ifndef SIGKILL +#define SIGKILL 1 +#endif + +/* It would be great if we could stress this stuff more, and make the test + * more granular. + */ +static void test_child_kill(abts_case *tc, void *data) +{ + apr_file_t *std = NULL; + apr_proc_t newproc; + apr_procattr_t *procattr = NULL; + const char *args[3]; + apr_status_t rv; + + args[0] = apr_pstrdup(p, "occhild" EXTENSION); + args[1] = apr_pstrdup(p, "-X"); + args[2] = NULL; + + rv = apr_procattr_create(&procattr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_procattr_io_set(procattr, APR_FULL_BLOCK, APR_NO_PIPE, + APR_NO_PIPE); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_proc_create(&newproc, "./occhild" EXTENSION, args, NULL, procattr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, newproc.in); + ABTS_PTR_EQUAL(tc, NULL, newproc.out); + ABTS_PTR_EQUAL(tc, NULL, newproc.err); + + std = newproc.in; + + apr_proc_other_child_register(&newproc, ocmaint, NULL, std, p); + + apr_sleep(apr_time_from_sec(1)); + rv = apr_proc_kill(&newproc, SIGKILL); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* allow time for things to settle... */ + apr_sleep(apr_time_from_sec(3)); + + apr_proc_other_child_refresh_all(APR_OC_REASON_RUNNING); + ABTS_STR_EQUAL(tc, "APR_OC_REASON_DEATH", reasonstr); +} +#else + +static void oc_not_impl(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "Other child logic not implemented on this platform"); +} +#endif + +abts_suite *testoc(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if !APR_HAS_OTHER_CHILD + abts_run_test(suite, oc_not_impl, NULL); +#else + + abts_run_test(suite, test_child_kill, NULL); + +#endif + return suite; +} + diff --git a/srclib/apr/test/testpath.c b/srclib/apr/test/testpath.c new file mode 100644 index 0000000000..4ada86c623 --- /dev/null +++ b/srclib/apr/test/testpath.c @@ -0,0 +1,138 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_file_info.h" +#include "apr_errno.h" +#include "apr_pools.h" +#include "apr_tables.h" + +#if defined(WIN32) || defined(NETWARE) || defined(OS2) +#define PSEP ";" +#define DSEP "\\" +#else +#define PSEP ":" +#define DSEP "/" +#endif + +#define PX "" +#define P1 "first path" +#define P2 "second" DSEP "path" +#define P3 "th ird" DSEP "path" +#define P4 "fourth" DSEP "pa th" +#define P5 "fifthpath" + +static const char *parts_in[] = { P1, P2, P3, PX, P4, P5 }; +static const char *path_in = P1 PSEP P2 PSEP P3 PSEP PX PSEP P4 PSEP P5; +static const int parts_in_count = sizeof(parts_in)/sizeof(*parts_in); + +static const char *parts_out[] = { P1, P2, P3, P4, P5 }; +static const char *path_out = P1 PSEP P2 PSEP P3 PSEP P4 PSEP P5; +static const int parts_out_count = sizeof(parts_out)/sizeof(*parts_out); + +static void list_split_multi(abts_case *tc, void *data) +{ + int i; + apr_status_t rv; + apr_array_header_t *pathelts; + + pathelts = NULL; + rv = apr_filepath_list_split(&pathelts, path_in, p); + ABTS_PTR_NOTNULL(tc, pathelts); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, parts_out_count, pathelts->nelts); + for (i = 0; i < pathelts->nelts; ++i) + ABTS_STR_EQUAL(tc, parts_out[i], ((char**)pathelts->elts)[i]); +} + +static void list_split_single(abts_case *tc, void *data) +{ + int i; + apr_status_t rv; + apr_array_header_t *pathelts; + + for (i = 0; i < parts_in_count; ++i) + { + pathelts = NULL; + rv = apr_filepath_list_split(&pathelts, parts_in[i], p); + ABTS_PTR_NOTNULL(tc, pathelts); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + if (parts_in[i][0] == '\0') + ABTS_INT_EQUAL(tc, 0, pathelts->nelts); + else + { + ABTS_INT_EQUAL(tc, 1, pathelts->nelts); + ABTS_STR_EQUAL(tc, parts_in[i], *(char**)pathelts->elts); + } + } +} + +static void list_merge_multi(abts_case *tc, void *data) +{ + int i; + char *liststr; + apr_status_t rv; + apr_array_header_t *pathelts; + + pathelts = apr_array_make(p, parts_in_count, sizeof(const char*)); + for (i = 0; i < parts_in_count; ++i) + *(const char**)apr_array_push(pathelts) = parts_in[i]; + + liststr = NULL; + rv = apr_filepath_list_merge(&liststr, pathelts, p); + ABTS_PTR_NOTNULL(tc, liststr); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, liststr, path_out); +} + +static void list_merge_single(abts_case *tc, void *data) +{ + int i; + char *liststr; + apr_status_t rv; + apr_array_header_t *pathelts; + + pathelts = apr_array_make(p, 1, sizeof(const char*)); + apr_array_push(pathelts); + for (i = 0; i < parts_in_count; ++i) + { + *(const char**)pathelts->elts = parts_in[i]; + liststr = NULL; + rv = apr_filepath_list_merge(&liststr, pathelts, p); + if (parts_in[i][0] == '\0') + ABTS_PTR_EQUAL(tc, NULL, liststr); + else + { + ABTS_PTR_NOTNULL(tc, liststr); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, liststr, parts_in[i]); + } + } +} + + +abts_suite *testpath(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, list_split_multi, NULL); + abts_run_test(suite, list_split_single, NULL); + abts_run_test(suite, list_merge_multi, NULL); + abts_run_test(suite, list_merge_single, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testpipe.c b/srclib/apr/test/testpipe.c new file mode 100644 index 0000000000..402aa257ec --- /dev/null +++ b/srclib/apr/test/testpipe.c @@ -0,0 +1,199 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "testutil.h" +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_thread_proc.h" +#include "apr_strings.h" + +static apr_file_t *readp = NULL; +static apr_file_t *writep = NULL; + +static void create_pipe(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_file_pipe_create(&readp, &writep, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, readp); + ABTS_PTR_NOTNULL(tc, writep); +} + +static void close_pipe(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_size_t nbytes = 256; + char buf[256]; + + rv = apr_file_close(readp); + rv = apr_file_close(writep); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_read(readp, buf, &nbytes); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_EBADF(rv)); +} + +static void set_timeout(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_interval_time_t timeout; + + rv = apr_file_pipe_create(&readp, &writep, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, readp); + ABTS_PTR_NOTNULL(tc, writep); + + rv = apr_file_pipe_timeout_get(readp, &timeout); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, -1, timeout); + + rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_pipe_timeout_get(readp, &timeout); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, apr_time_from_sec(1), timeout); +} + +static void read_write(abts_case *tc, void *data) +{ + apr_status_t rv; + char *buf; + apr_size_t nbytes; + + nbytes = strlen("this is a test"); + buf = (char *)apr_palloc(p, nbytes + 1); + + rv = apr_file_pipe_create(&readp, &writep, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, readp); + ABTS_PTR_NOTNULL(tc, writep); + + rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_read(readp, buf, &nbytes); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + ABTS_INT_EQUAL(tc, 0, nbytes); +} + +static void read_write_notimeout(abts_case *tc, void *data) +{ + apr_status_t rv; + char *buf = "this is a test"; + char *input; + apr_size_t nbytes; + + nbytes = strlen("this is a test"); + + rv = apr_file_pipe_create(&readp, &writep, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, readp); + ABTS_PTR_NOTNULL(tc, writep); + + rv = apr_file_write(writep, buf, &nbytes); + ABTS_INT_EQUAL(tc, strlen("this is a test"), nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + nbytes = 256; + input = apr_pcalloc(p, nbytes + 1); + rv = apr_file_read(readp, input, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen("this is a test"), nbytes); + ABTS_STR_EQUAL(tc, "this is a test", input); +} + +static void test_pipe_writefull(abts_case *tc, void *data) +{ + int iterations = 1000; + int i; + int bytes_per_iteration = 8000; + char *buf = (char *)malloc(bytes_per_iteration); + char responsebuf[128]; + apr_size_t nbytes; + int bytes_processed; + apr_proc_t proc = {0}; + apr_procattr_t *procattr; + const char *args[2]; + apr_status_t rv; + apr_exit_why_e why; + + rv = apr_procattr_create(&procattr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_procattr_io_set(procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, + APR_CHILD_BLOCK); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_procattr_error_check_set(procattr, 1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + args[0] = "readchild" EXTENSION; + args[1] = NULL; + rv = apr_proc_create(&proc, "./readchild" EXTENSION, args, NULL, procattr, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_pipe_timeout_set(proc.in, apr_time_from_sec(10)); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_file_pipe_timeout_set(proc.out, apr_time_from_sec(10)); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + i = iterations; + do { + rv = apr_file_write_full(proc.in, buf, bytes_per_iteration, NULL); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + } while (--i); + + free(buf); + + rv = apr_file_close(proc.in); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + nbytes = sizeof(responsebuf); + rv = apr_file_read(proc.out, responsebuf, &nbytes); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + bytes_processed = (int)apr_strtoi64(responsebuf, NULL, 10); + ABTS_INT_EQUAL(tc, iterations * bytes_per_iteration, bytes_processed); + + ABTS_ASSERT(tc, "wait for child process", + apr_proc_wait(&proc, NULL, &why, APR_WAIT) == APR_CHILD_DONE); + + ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT); +} + +abts_suite *testpipe(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, create_pipe, NULL); + abts_run_test(suite, close_pipe, NULL); + abts_run_test(suite, set_timeout, NULL); + abts_run_test(suite, close_pipe, NULL); + abts_run_test(suite, read_write, NULL); + abts_run_test(suite, close_pipe, NULL); + abts_run_test(suite, read_write_notimeout, NULL); + abts_run_test(suite, test_pipe_writefull, NULL); + abts_run_test(suite, close_pipe, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testpoll.c b/srclib/apr/test/testpoll.c new file mode 100644 index 0000000000..ebcb8acd95 --- /dev/null +++ b/srclib/apr/test/testpoll.c @@ -0,0 +1,538 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_strings.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_network_io.h" +#include "apr_poll.h" + +#define SMALL_NUM_SOCKETS 3 +/* We can't use 64 here, because some platforms *ahem* Solaris *ahem* have + * a default limit of 64 open file descriptors per process. If we use + * 64, the test will fail even though the code is correct. + */ +#define LARGE_NUM_SOCKETS 50 + +static apr_socket_t *s[LARGE_NUM_SOCKETS]; +static apr_sockaddr_t *sa[LARGE_NUM_SOCKETS]; +static apr_pollset_t *pollset; + +/* ###: tests surrounded by ifdef OLD_POLL_INTERFACE either need to be + * converted to use the pollset interface or removed. */ + +#ifdef OLD_POLL_INTERFACE +static apr_pollfd_t *pollarray; +static apr_pollfd_t *pollarray_large; +#endif + +static void make_socket(apr_socket_t **sock, apr_sockaddr_t **sa, + apr_port_t port, apr_pool_t *p, abts_case *tc) +{ + apr_status_t rv; + + rv = apr_sockaddr_info_get(sa, "127.0.0.1", APR_UNSPEC, port, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_create(sock, (*sa)->family, SOCK_DGRAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv =apr_socket_bind((*sock), (*sa)); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +#ifdef OLD_POLL_INTERFACE +static void check_sockets(const apr_pollfd_t *pollarray, + apr_socket_t **sockarray, int which, int pollin, + abts_case *tc) +{ + apr_status_t rv; + apr_int16_t event; + char *str; + + rv = apr_poll_revents_get(&event, sockarray[which], + (apr_pollfd_t *)pollarray); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + if (pollin) { + str = apr_psprintf(p, "Socket %d not signalled when it should be", + which); + ABTS_ASSERT(tc, str, event & APR_POLLIN); + } else { + str = apr_psprintf(p, "Socket %d signalled when it should not be", + which); + ABTS_ASSERT(tc, str, !(event & APR_POLLIN)); + } +} +#endif + +static void send_msg(apr_socket_t **sockarray, apr_sockaddr_t **sas, int which, + abts_case *tc) +{ + apr_size_t len = 5; + apr_status_t rv; + + ABTS_PTR_NOTNULL(tc, sockarray[which]); + + rv = apr_socket_sendto(sockarray[which], sas[which], 0, "hello", &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen("hello"), len); +} + +static void recv_msg(apr_socket_t **sockarray, int which, apr_pool_t *p, + abts_case *tc) +{ + apr_size_t buflen = 5; + char *buffer = apr_pcalloc(p, sizeof(char) * (buflen + 1)); + apr_sockaddr_t *recsa; + apr_status_t rv; + + ABTS_PTR_NOTNULL(tc, sockarray[which]); + + apr_sockaddr_info_get(&recsa, "127.0.0.1", APR_UNSPEC, 7770, 0, p); + + rv = apr_socket_recvfrom(recsa, sockarray[which], 0, buffer, &buflen); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, strlen("hello"), buflen); + ABTS_STR_EQUAL(tc, "hello", buffer); +} + + +static void create_all_sockets(abts_case *tc, void *data) +{ + int i; + + for (i = 0; i < LARGE_NUM_SOCKETS; i++){ + make_socket(&s[i], &sa[i], 7777 + i, p, tc); + } +} + +#ifdef OLD_POLL_INTERFACE +static void setup_small_poll(abts_case *tc, void *data) +{ + apr_status_t rv; + int i; + + rv = apr_poll_setup(&pollarray, SMALL_NUM_SOCKETS, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + for (i = 0; i < SMALL_NUM_SOCKETS;i++){ + ABTS_INT_EQUAL(tc, 0, pollarray[i].reqevents); + ABTS_INT_EQUAL(tc, 0, pollarray[i].rtnevents); + + rv = apr_poll_socket_add(pollarray, s[i], APR_POLLIN); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_EQUAL(tc, s[i], pollarray[i].desc.s); + } +} + +static void setup_large_poll(abts_case *tc, void *data) +{ + apr_status_t rv; + int i; + + rv = apr_poll_setup(&pollarray_large, LARGE_NUM_SOCKETS, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + for (i = 0; i < LARGE_NUM_SOCKETS;i++){ + ABTS_INT_EQUAL(tc, 0, pollarray_large[i].reqevents); + ABTS_INT_EQUAL(tc, 0, pollarray_large[i].rtnevents); + + rv = apr_poll_socket_add(pollarray_large, s[i], APR_POLLIN); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_EQUAL(tc, s[i], pollarray_large[i].desc.s); + } +} + +static void nomessage(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + check_sockets(pollarray, s, 0, 0, tc); + check_sockets(pollarray, s, 1, 0, tc); + check_sockets(pollarray, s, 2, 0, tc); +} + +static void send_2(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + send_msg(s, sa, 2, tc); + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + check_sockets(pollarray, s, 0, 0, tc); + check_sockets(pollarray, s, 1, 0, tc); + check_sockets(pollarray, s, 2, 1, tc); +} + +static void recv_2_send_1(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + recv_msg(s, 2, p, tc); + send_msg(s, sa, 1, tc); + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + check_sockets(pollarray, s, 0, 0, tc); + check_sockets(pollarray, s, 1, 1, tc); + check_sockets(pollarray, s, 2, 0, tc); +} + +static void send_2_signaled_1(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + send_msg(s, sa, 2, tc); + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + check_sockets(pollarray, s, 0, 0, tc); + check_sockets(pollarray, s, 1, 1, tc); + check_sockets(pollarray, s, 2, 1, tc); +} + +static void recv_1_send_0(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + recv_msg(s, 1, p, tc); + send_msg(s, sa, 0, tc); + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + check_sockets(pollarray, s, 0, 1, tc); + check_sockets(pollarray, s, 1, 0, tc); + check_sockets(pollarray, s, 2, 1, tc); +} + +static void clear_all_signalled(abts_case *tc, void *data) +{ + apr_status_t rv; + int srv = SMALL_NUM_SOCKETS; + + recv_msg(s, 0, p, tc); + recv_msg(s, 2, p, tc); + + rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + check_sockets(pollarray, s, 0, 0, tc); + check_sockets(pollarray, s, 1, 0, tc); + check_sockets(pollarray, s, 2, 0, tc); +} + +static void send_large_pollarray(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv = LARGE_NUM_SOCKETS; + int i; + + send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc); + + rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv, + 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + for (i = 0; i < LARGE_NUM_SOCKETS; i++) { + if (i == (LARGE_NUM_SOCKETS - 1)) { + check_sockets(pollarray_large, s, i, 1, tc); + } + else { + check_sockets(pollarray_large, s, i, 0, tc); + } + } +} + +static void recv_large_pollarray(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv = LARGE_NUM_SOCKETS; + int i; + + recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc); + + rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv, + 2 * APR_USEC_PER_SEC); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + + for (i = 0; i < LARGE_NUM_SOCKETS; i++) { + check_sockets(pollarray_large, s, i, 0, tc); + } +} +#endif + +static void setup_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + rv = apr_pollset_create(&pollset, LARGE_NUM_SOCKETS, p, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void add_sockets_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + int i; + + for (i = 0; i < LARGE_NUM_SOCKETS;i++){ + apr_pollfd_t socket_pollfd; + + ABTS_PTR_NOTNULL(tc, s[i]); + + socket_pollfd.desc_type = APR_POLL_SOCKET; + socket_pollfd.reqevents = APR_POLLIN; + socket_pollfd.desc.s = s[i]; + socket_pollfd.client_data = s[i]; + rv = apr_pollset_add(pollset, &socket_pollfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + } +} + +static void nomessage_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv; + const apr_pollfd_t *descs = NULL; + + rv = apr_pollset_poll(pollset, 0, &lrv, &descs); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + ABTS_INT_EQUAL(tc, 0, lrv); + ABTS_PTR_EQUAL(tc, NULL, descs); +} + +static void send0_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + const apr_pollfd_t *descs = NULL; + int num; + + send_msg(s, sa, 0, tc); + rv = apr_pollset_poll(pollset, 0, &num, &descs); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, num); + ABTS_PTR_NOTNULL(tc, descs); + + ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s); + ABTS_PTR_EQUAL(tc, s[0], descs[0].client_data); +} + +static void recv0_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv; + const apr_pollfd_t *descs = NULL; + + recv_msg(s, 0, p, tc); + rv = apr_pollset_poll(pollset, 0, &lrv, &descs); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + ABTS_INT_EQUAL(tc, 0, lrv); + ABTS_PTR_EQUAL(tc, NULL, descs); +} + +static void send_middle_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + const apr_pollfd_t *descs = NULL; + int num; + + send_msg(s, sa, 2, tc); + send_msg(s, sa, 5, tc); + rv = apr_pollset_poll(pollset, 0, &num, &descs); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 2, num); + ABTS_PTR_NOTNULL(tc, descs); + + ABTS_ASSERT(tc, "Incorrect socket in result set", + ((descs[0].desc.s == s[2]) && (descs[1].desc.s == s[5])) || + ((descs[0].desc.s == s[5]) && (descs[1].desc.s == s[2]))); +} + +static void clear_middle_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv; + const apr_pollfd_t *descs = NULL; + + recv_msg(s, 2, p, tc); + recv_msg(s, 5, p, tc); + + rv = apr_pollset_poll(pollset, 0, &lrv, &descs); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + ABTS_INT_EQUAL(tc, 0, lrv); + ABTS_PTR_EQUAL(tc, NULL, descs); +} + +static void send_last_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + const apr_pollfd_t *descs = NULL; + int num; + + send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc); + rv = apr_pollset_poll(pollset, 0, &num, &descs); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, num); + ABTS_PTR_NOTNULL(tc, descs); + + ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].desc.s); + ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].client_data); +} + +static void clear_last_pollset(abts_case *tc, void *data) +{ + apr_status_t rv; + int lrv; + const apr_pollfd_t *descs = NULL; + + recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc); + + rv = apr_pollset_poll(pollset, 0, &lrv, &descs); + ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); + ABTS_INT_EQUAL(tc, 0, lrv); + ABTS_PTR_EQUAL(tc, NULL, descs); +} + +static void close_all_sockets(abts_case *tc, void *data) +{ + apr_status_t rv; + int i; + + for (i = 0; i < LARGE_NUM_SOCKETS; i++){ + rv = apr_socket_close(s[i]); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + } +} + +static void pollset_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_pollset_t *pollset; + const apr_pollfd_t *hot_files; + apr_pollfd_t pfd; + apr_int32_t num; + + rv = apr_pollset_create(&pollset, 5, p, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + pfd.p = p; + pfd.desc_type = APR_POLL_SOCKET; + pfd.reqevents = APR_POLLOUT; + + pfd.desc.s = s[0]; + pfd.client_data = (void *)1; + rv = apr_pollset_add(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + pfd.desc.s = s[1]; + pfd.client_data = (void *)2; + rv = apr_pollset_add(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + pfd.desc.s = s[2]; + pfd.client_data = (void *)3; + rv = apr_pollset_add(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + pfd.desc.s = s[3]; + pfd.client_data = (void *)4; + rv = apr_pollset_add(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_pollset_poll(pollset, 1000, &num, &hot_files); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 4, num); + + /* now remove the pollset element referring to desc s[1] */ + pfd.desc.s = s[1]; + pfd.client_data = (void *)999; /* not used on this call */ + rv = apr_pollset_remove(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* this time only three should match */ + rv = apr_pollset_poll(pollset, 1000, &num, &hot_files); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 3, num); + ABTS_PTR_EQUAL(tc, (void *)1, hot_files[0].client_data); + ABTS_PTR_EQUAL(tc, s[0], hot_files[0].desc.s); + ABTS_PTR_EQUAL(tc, (void *)3, hot_files[1].client_data); + ABTS_PTR_EQUAL(tc, s[2], hot_files[1].desc.s); + ABTS_PTR_EQUAL(tc, (void *)4, hot_files[2].client_data); + ABTS_PTR_EQUAL(tc, s[3], hot_files[2].desc.s); + + /* now remove the pollset elements referring to desc s[2] */ + pfd.desc.s = s[2]; + pfd.client_data = (void *)999; /* not used on this call */ + rv = apr_pollset_remove(pollset, &pfd); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + /* this time only two should match */ + rv = apr_pollset_poll(pollset, 1000, &num, &hot_files); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 2, num); + ABTS_ASSERT(tc, "Incorrect socket in result set", + ((hot_files[0].desc.s == s[0]) && (hot_files[1].desc.s == s[3])) || + ((hot_files[0].desc.s == s[3]) && (hot_files[1].desc.s == s[0]))); + ABTS_ASSERT(tc, "Incorrect client data in result set", + ((hot_files[0].client_data == (void *)1) && + (hot_files[1].client_data == (void *)4)) || + ((hot_files[0].client_data == (void *)4) && + (hot_files[1].client_data == (void *)1))); +} + +abts_suite *testpoll(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, create_all_sockets, NULL); + +#ifdef OLD_POLL_INTERFACE + abts_run_test(suite, setup_small_poll, NULL); + abts_run_test(suite, setup_large_poll, NULL); + abts_run_test(suite, nomessage, NULL); + abts_run_test(suite, send_2, NULL); + abts_run_test(suite, recv_2_send_1, NULL); + abts_run_test(suite, send_2_signaled_1, NULL); + abts_run_test(suite, recv_1_send_0, NULL); + abts_run_test(suite, clear_all_signalled, NULL); + abts_run_test(suite, send_large_pollarray, NULL); + abts_run_test(suite, recv_large_pollarray, NULL); +#endif + + abts_run_test(suite, setup_pollset, NULL); + abts_run_test(suite, add_sockets_pollset, NULL); + abts_run_test(suite, nomessage_pollset, NULL); + abts_run_test(suite, send0_pollset, NULL); + abts_run_test(suite, recv0_pollset, NULL); + abts_run_test(suite, send_middle_pollset, NULL); + abts_run_test(suite, clear_middle_pollset, NULL); + abts_run_test(suite, send_last_pollset, NULL); + abts_run_test(suite, clear_last_pollset, NULL); + + abts_run_test(suite, pollset_remove, NULL); + + abts_run_test(suite, close_all_sockets, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testpools.c b/srclib/apr/test/testpools.c new file mode 100644 index 0000000000..2e81c154bf --- /dev/null +++ b/srclib/apr/test/testpools.c @@ -0,0 +1,156 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_errno.h" +#include "apr_file_io.h" +#include +#include +#include +#if APR_HAVE_UNISTD_H +#include +#endif +#include "testutil.h" + +#define ALLOC_BYTES 1024 + +static apr_pool_t *pmain = NULL; +static apr_pool_t *pchild = NULL; + +static void alloc_bytes(abts_case *tc, void *data) +{ + int i; + char *alloc; + + alloc = apr_palloc(pmain, ALLOC_BYTES); + ABTS_PTR_NOTNULL(tc, alloc); + + for (i=0;i +#include +#include "testutil.h" + +#if APR_HAS_FORK + +#define MAX_ITER 200 +#define CHILDREN 6 +#define MAX_COUNTER (MAX_ITER * CHILDREN) + +static apr_proc_mutex_t *proc_lock; +static volatile int *x; + +/* a slower more racy way to implement (*x)++ */ +static int increment(int n) +{ + apr_sleep(1); + return n+1; +} + +static void make_child(abts_case *tc, apr_proc_t **proc, apr_pool_t *p) +{ + apr_status_t rv; + + *proc = apr_pcalloc(p, sizeof(**proc)); + + /* slight delay to allow things to settle */ + apr_sleep (1); + + rv = apr_proc_fork(*proc, p); + if (rv == APR_INCHILD) { + int i = 0; + /* The parent process has setup all processes to call apr_terminate + * at exit. But, that means that all processes must also call + * apr_initialize at startup. You cannot have an unequal number + * of apr_terminate and apr_initialize calls. If you do, bad things + * will happen. In this case, the bad thing is that if the mutex + * is a semaphore, it will be destroyed before all of the processes + * die. That means that the test will most likely fail. + */ + apr_initialize(); + + if (apr_proc_mutex_child_init(&proc_lock, NULL, p)) + exit(1); + + do { + if (apr_proc_mutex_lock(proc_lock)) + exit(1); + i++; + *x = increment(*x); + if (apr_proc_mutex_unlock(proc_lock)) + exit(1); + } while (i < MAX_ITER); + exit(0); + } + + ABTS_ASSERT(tc, "fork failed", rv == APR_INPARENT); +} + +/* Wait for a child process and check it terminated with success. */ +static void await_child(abts_case *tc, apr_proc_t *proc) +{ + int code; + apr_exit_why_e why; + apr_status_t rv; + + rv = apr_proc_wait(proc, &code, &why, APR_WAIT); + ABTS_ASSERT(tc, "child did not terminate with success", + rv == APR_CHILD_DONE && why == APR_PROC_EXIT && code == 0); +} + +static void test_exclusive(abts_case *tc, const char *lockname, + apr_lockmech_e mech) +{ + apr_proc_t *child[CHILDREN]; + apr_status_t rv; + int n; + + rv = apr_proc_mutex_create(&proc_lock, lockname, mech, p); + APR_ASSERT_SUCCESS(tc, "create the mutex", rv); + if (rv != APR_SUCCESS) + return; + + for (n = 0; n < CHILDREN; n++) + make_child(tc, &child[n], p); + + for (n = 0; n < CHILDREN; n++) + await_child(tc, child[n]); + + ABTS_ASSERT(tc, "Locks don't appear to work", *x == MAX_COUNTER); +} +#endif + +static void proc_mutex(abts_case *tc, void *data) +{ +#if APR_HAS_FORK + apr_status_t rv; + const char *shmname = "tpm.shm"; + apr_shm_t *shm; + apr_lockmech_e *mech = data; + + /* Use anonymous shm if available. */ + rv = apr_shm_create(&shm, sizeof(int), NULL, p); + if (rv == APR_ENOTIMPL) { + apr_file_remove(shmname, p); + rv = apr_shm_create(&shm, sizeof(int), shmname, p); + } + + APR_ASSERT_SUCCESS(tc, "create shm segment", rv); + if (rv != APR_SUCCESS) + return; + + x = apr_shm_baseaddr_get(shm); + test_exclusive(tc, NULL, *mech); + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +#else + ABTS_NOT_IMPL(tc, "APR lacks fork() support"); +#endif +} + + +abts_suite *testprocmutex(abts_suite *suite) +{ + apr_lockmech_e mech = APR_LOCK_DEFAULT; + + suite = ADD_SUITE(suite) + abts_run_test(suite, proc_mutex, &mech); +#if APR_HAS_POSIXSEM_SERIALIZE + mech = APR_LOCK_POSIXSEM; + abts_run_test(suite, proc_mutex, &mech); +#endif +#if APR_HAS_SYSVSEM_SERIALIZE + mech = APR_LOCK_SYSVSEM; + abts_run_test(suite, proc_mutex, &mech); +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + mech = APR_LOCK_PROC_PTHREAD; + abts_run_test(suite, proc_mutex, &mech); +#endif +#if APR_HAS_FCNTL_SERIALIZE + mech = APR_LOCK_FCNTL; + abts_run_test(suite, proc_mutex, &mech); +#endif +#if APR_HAS_FLOCK_SERIALIZE + mech = APR_LOCK_FLOCK; + abts_run_test(suite, proc_mutex, &mech); +#endif + + return suite; +} diff --git a/srclib/apr/test/testrand.c b/srclib/apr/test/testrand.c new file mode 100644 index 0000000000..ca94b60b9d --- /dev/null +++ b/srclib/apr/test/testrand.c @@ -0,0 +1,46 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include +#include +#include +#include "testutil.h" + +static void rand_exists(abts_case *tc, void *data) +{ +#if !APR_HAS_RANDOM + ABTS_NOT_IMPL(tc, "apr_generate_random_bytes"); +#else + unsigned char c[42]; + + /* There must be a better way to test random-ness, but I don't know + * what it is right now. + */ + APR_ASSERT_SUCCESS(tc, "apr_generate_random_bytes failed", + apr_generate_random_bytes(c, sizeof c)); +#endif +} + +abts_suite *testrand(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, rand_exists, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testrand2.c b/srclib/apr/test/testrand2.c new file mode 100644 index 0000000000..6dd7b5d6c0 --- /dev/null +++ b/srclib/apr/test/testrand2.c @@ -0,0 +1,298 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_general.h" +#include "apr_random.h" +#include "apr_thread_proc.h" +#include +#include +#include +#include "testutil.h" + +static void hexdump(const unsigned char *b,int n) + { + int i; + + for(i=0 ; i < n ; ++i) + { +#if 0 + if((i&0xf) == 0) + printf("%04x",i); + printf(" %02x",b[i]); + if((i&0xf) == 0xf) + printf("\n"); +#else + printf("0x%02x,",b[i]); + if((i&7) == 7) + printf("\n"); +#endif + } + printf("\n"); + } + +static apr_random_t *r; + +typedef apr_status_t APR_THREAD_FUNC rnd_fn(apr_random_t *r,void *b,apr_size_t n); + +static void rand_run_kat(abts_case *tc,rnd_fn *f,apr_random_t *r, + const unsigned char expected[128]) + { + unsigned char c[128]; + apr_status_t rv; + + rv=f(r,c,128); + ABTS_INT_EQUAL(tc,0,rv); + if(rv) + return; + if(memcmp(c,expected,128)) + { + hexdump(c,128); + hexdump(expected,128); + ABTS_FAIL(tc,"Randomness mismatch"); + } + } + +static int rand_check_kat(rnd_fn *f,apr_random_t *r, + const unsigned char expected[128]) + { + unsigned char c[128]; + apr_status_t rv; + + rv=f(r,c,128); + if(rv) + return 2; + if(memcmp(c,expected,128)) + return 1; + return 0; + } + +static void rand_add_zeroes(apr_random_t *r) + { + static unsigned char c[2048]; + + apr_random_add_entropy(r,c,sizeof c); + } + +static void rand_run_seed_short(abts_case *tc,rnd_fn *f,apr_random_t *r, + int count) + { + int i; + apr_status_t rv; + char c[1]; + + for(i=0 ; i < count ; ++i) + rand_add_zeroes(r); + rv=f(r,c,1); + ABTS_INT_EQUAL(tc,1,APR_STATUS_IS_ENOTENOUGHENTROPY(rv)); + } + +static void rand_seed_short(abts_case *tc, void *data) + { + r=apr_random_standard_new(p); + rand_run_seed_short(tc,apr_random_insecure_bytes,r,32); + } + +static void rand_kat(abts_case *tc, void *data) + { + unsigned char expected[128]= + { 0x82,0x04,0xad,0xd2,0x0b,0xd5,0xac,0xda, + 0x3d,0x85,0x58,0x38,0x54,0x6b,0x69,0x45, + 0x37,0x4c,0xc7,0xd7,0x87,0xeb,0xbf,0xd9, + 0xb1,0xb8,0xb8,0x2d,0x9b,0x33,0x6e,0x97, + 0x04,0x1d,0x4c,0xb0,0xd1,0xdf,0x3d,0xac, + 0xd2,0xaa,0xfa,0xcd,0x96,0xb7,0xcf,0xb1, + 0x8e,0x3d,0xb3,0xe5,0x37,0xa9,0x95,0xb4, + 0xaa,0x3d,0x11,0x1a,0x08,0x20,0x21,0x9f, + 0xdb,0x08,0x3a,0xb9,0x57,0x9f,0xf2,0x1f, + 0x27,0xdc,0xb6,0xc0,0x85,0x08,0x05,0xbb, + 0x13,0xbe,0xb1,0xe9,0x63,0x2a,0xe2,0xa4, + 0x23,0x15,0x2a,0x10,0xbf,0xdf,0x09,0xb3, + 0xc7,0xfb,0x2d,0x87,0x48,0x19,0xfb,0xc0, + 0x15,0x8c,0xcb,0xc6,0xbd,0x89,0x38,0x69, + 0xa3,0xae,0xa3,0x21,0x58,0x50,0xe7,0xc4, + 0x87,0xec,0x2e,0xb1,0x2d,0x6a,0xbd,0x46 }; + + rand_add_zeroes(r); + rand_run_kat(tc,apr_random_insecure_bytes,r,expected); + } + +static void rand_seed_short2(abts_case *tc, void *data) + { + rand_run_seed_short(tc,apr_random_secure_bytes,r,320); + } + +static void rand_kat2(abts_case *tc, void *data) + { + unsigned char expected[128]= + { 0x38,0x8f,0x01,0x29,0x5a,0x5c,0x1f,0xa8, + 0x00,0xde,0x16,0x4c,0xe5,0xf7,0x1f,0x58, + 0xc0,0x67,0xe2,0x98,0x3d,0xde,0x4a,0x75, + 0x61,0x3f,0x23,0xd8,0x45,0x7a,0x10,0x60, + 0x59,0x9b,0xd6,0xaf,0xcb,0x0a,0x2e,0x34, + 0x9c,0x39,0x5b,0xd0,0xbc,0x9a,0xf0,0x7b, + 0x7f,0x40,0x8b,0x33,0xc0,0x0e,0x2a,0x56, + 0xfc,0xe5,0xab,0xde,0x7b,0x13,0xf5,0xec, + 0x15,0x68,0xb8,0x09,0xbc,0x2c,0x15,0xf0, + 0x7b,0xef,0x2a,0x97,0x19,0xa8,0x69,0x51, + 0xdf,0xb0,0x5f,0x1a,0x4e,0xdf,0x42,0x02, + 0x71,0x36,0xa7,0x25,0x64,0x85,0xe2,0x72, + 0xc7,0x87,0x4d,0x7d,0x15,0xbb,0x15,0xd1, + 0xb1,0x62,0x0b,0x25,0xd9,0xd3,0xd9,0x5a, + 0xe3,0x47,0x1e,0xae,0x67,0xb4,0x19,0x9e, + 0xed,0xd2,0xde,0xce,0x18,0x70,0x57,0x12 }; + + rand_add_zeroes(r); + rand_run_kat(tc,apr_random_secure_bytes,r,expected); + } + +static void rand_barrier(abts_case *tc, void *data) + { + apr_random_barrier(r); + rand_run_seed_short(tc,apr_random_secure_bytes,r,320); + } + +static void rand_kat3(abts_case *tc, void *data) + { + unsigned char expected[128]= + { 0xe8,0xe7,0xc9,0x45,0xe2,0x2a,0x54,0xb2, + 0xdd,0xe0,0xf9,0xbc,0x3d,0xf9,0xce,0x3c, + 0x4c,0xbd,0xc9,0xe2,0x20,0x4a,0x35,0x1c, + 0x04,0x52,0x7f,0xb8,0x0f,0x60,0x89,0x63, + 0x8a,0xbe,0x0a,0x44,0xac,0x5d,0xd8,0xeb, + 0x24,0x7d,0xd1,0xda,0x4d,0x86,0x9b,0x94, + 0x26,0x56,0x4a,0x5e,0x30,0xea,0xd4,0xa9, + 0x9a,0xdf,0xdd,0xb6,0xb1,0x15,0xe0,0xfa, + 0x28,0xa4,0xd6,0x95,0xa4,0xf1,0xd8,0x6e, + 0xeb,0x8c,0xa4,0xac,0x34,0xfe,0x06,0x92, + 0xc5,0x09,0x99,0x86,0xdc,0x5a,0x3c,0x92, + 0xc8,0x3e,0x52,0x00,0x4d,0x01,0x43,0x6f, + 0x69,0xcf,0xe2,0x60,0x9c,0x23,0xb3,0xa5, + 0x5f,0x51,0x47,0x8c,0x07,0xde,0x60,0xc6, + 0x04,0xbf,0x32,0xd6,0xdc,0xb7,0x31,0x01, + 0x29,0x51,0x51,0xb3,0x19,0x6e,0xe4,0xf8 }; + + rand_run_kat(tc,apr_random_insecure_bytes,r,expected); + } + +static void rand_kat4(abts_case *tc, void *data) + { + unsigned char expected[128]= + { 0x7d,0x0e,0xc4,0x4e,0x3e,0xac,0x86,0x50, + 0x37,0x95,0x7a,0x98,0x23,0x26,0xa7,0xbf, + 0x60,0xfb,0xa3,0x70,0x90,0xc3,0x58,0xc6, + 0xbd,0xd9,0x5e,0xa6,0x77,0x62,0x7a,0x5c, + 0x96,0x83,0x7f,0x80,0x3d,0xf4,0x9c,0xcc, + 0x9b,0x0c,0x8c,0xe1,0x72,0xa8,0xfb,0xc9, + 0xc5,0x43,0x91,0xdc,0x9d,0x92,0xc2,0xce, + 0x1c,0x5e,0x36,0xc7,0x87,0xb1,0xb4,0xa3, + 0xc8,0x69,0x76,0xfc,0x35,0x75,0xcb,0x08, + 0x2f,0xe3,0x98,0x76,0x37,0x80,0x04,0x5c, + 0xb8,0xb0,0x7f,0xb2,0xda,0xe3,0xa3,0xba, + 0xed,0xff,0xf5,0x9d,0x3b,0x7b,0xf3,0x32, + 0x6c,0x50,0xa5,0x3e,0xcc,0xe1,0x84,0x9c, + 0x17,0x9e,0x80,0x64,0x09,0xbb,0x62,0xf1, + 0x95,0xf5,0x2c,0xc6,0x9f,0x6a,0xee,0x6d, + 0x17,0x35,0x5f,0x35,0x8d,0x55,0x0c,0x07 }; + + rand_add_zeroes(r); + rand_run_kat(tc,apr_random_secure_bytes,r,expected); + } + +#if APR_HAS_FORK +static void rand_fork(abts_case *tc, void *data) + { + apr_proc_t proc; + apr_status_t rv; + unsigned char expected[128]= + { 0xac,0x93,0xd2,0x5c,0xc7,0xf5,0x8d,0xc2, + 0xd8,0x8d,0xb6,0x7a,0x94,0xe1,0x83,0x4c, + 0x26,0xe2,0x38,0x6d,0xf5,0xbd,0x9d,0x6e, + 0x91,0x77,0x3a,0x4b,0x9b,0xef,0x9b,0xa3, + 0x9f,0xf6,0x6d,0x0c,0xdc,0x4b,0x02,0xe9, + 0x5d,0x3d,0xfc,0x92,0x6b,0xdf,0xc9,0xef, + 0xb9,0xa8,0x74,0x09,0xa3,0xff,0x64,0x8d, + 0x19,0xc1,0x31,0x31,0x17,0xe1,0xb7,0x7a, + 0xe7,0x55,0x14,0x92,0x05,0xe3,0x1e,0xb8, + 0x9b,0x1b,0xdc,0xac,0x0e,0x15,0x08,0xa2, + 0x93,0x13,0xf6,0x04,0xc6,0x9d,0xf8,0x7f, + 0x26,0x32,0x68,0x43,0x2e,0x5a,0x4f,0x47, + 0xe8,0xf8,0x59,0xb7,0xfb,0xbe,0x30,0x04, + 0xb6,0x63,0x6f,0x19,0xf3,0x2c,0xd4,0xeb, + 0x32,0x8a,0x54,0x01,0xd0,0xaf,0x3f,0x13, + 0xc1,0x7f,0x10,0x2e,0x08,0x1c,0x28,0x4b, }; + + rv=apr_proc_fork(&proc,p); + if(rv == APR_INCHILD) + { + int n; + + n=rand_check_kat(apr_random_secure_bytes,r,expected); + + exit(n); + } + else if(rv == APR_INPARENT) + { + int exitcode; + apr_exit_why_e why; + + rand_run_kat(tc,apr_random_secure_bytes,r,expected); + apr_proc_wait(&proc,&exitcode,&why,APR_WAIT); + if(why != APR_PROC_EXIT) + { + ABTS_FAIL(tc,"Child terminated abnormally"); + return; + } + if(exitcode == 0) + { + ABTS_FAIL(tc,"Child produced our randomness"); + return; + } + else if(exitcode == 2) + { + ABTS_FAIL(tc,"Child randomness failed"); + return; + } + else if(exitcode != 1) + { + ABTS_FAIL(tc,"Uknown child error"); + return; + } + } + else + { + ABTS_FAIL(tc,"Fork failed"); + return; + } + } +#endif + +abts_suite *testrand2(abts_suite *suite) + { + suite = ADD_SUITE(suite) + + abts_run_test(suite, rand_seed_short, NULL); + abts_run_test(suite, rand_kat, NULL); + abts_run_test(suite, rand_seed_short2, NULL); + abts_run_test(suite, rand_kat2, NULL); + abts_run_test(suite, rand_barrier, NULL); + abts_run_test(suite, rand_kat3, NULL); + abts_run_test(suite, rand_kat4, NULL); +#if APR_HAS_FORK + abts_run_test(suite, rand_fork, NULL); +#endif + + return suite; + } diff --git a/srclib/apr/test/testshm.c b/srclib/apr/test/testshm.c new file mode 100644 index 0000000000..7329aa6de0 --- /dev/null +++ b/srclib/apr/test/testshm.c @@ -0,0 +1,272 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_shm.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_thread_proc.h" +#include "apr_time.h" +#include "testshm.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + +#if APR_HAS_SHARED_MEMORY + +static int msgwait(int sleep_sec, int first_box, int last_box) +{ + int i; + int recvd = 0; + apr_time_t start = apr_time_now(); + apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec); + while (apr_time_now() - start < sleep_duration) { + for (i = first_box; i < last_box; i++) { + if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) { + recvd++; + boxes[i].msgavail = 0; /* reset back to 0 */ + /* reset the msg field. 1024 is a magic number and it should + * be a macro, but I am being lazy. + */ + memset(boxes[i].msg, 0, 1024); + } + } + apr_sleep(apr_time_make(0, 10000)); /* 10ms */ + } + return recvd; +} + +static void msgput(int boxnum, char *msg) +{ + apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1); + boxes[boxnum].msgavail = 1; +} + +static void test_anon_create(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm = NULL; + + rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + ABTS_PTR_NOTNULL(tc, shm); + + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +} + +static void test_check_size(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm = NULL; + apr_size_t retsize; + + rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + ABTS_PTR_NOTNULL(tc, shm); + + retsize = apr_shm_size_get(shm); + ABTS_INT_EQUAL(tc, SHARED_SIZE, retsize); + + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +} + +static void test_shm_allocate(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm = NULL; + + rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + ABTS_PTR_NOTNULL(tc, shm); + + boxes = apr_shm_baseaddr_get(shm); + ABTS_PTR_NOTNULL(tc, boxes); + + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +} + +#if APR_HAS_FORK +static void test_anon(abts_case *tc, void *data) +{ + apr_proc_t proc; + apr_status_t rv; + apr_shm_t *shm; + apr_size_t retsize; + int cnt, i; + int recvd; + + rv = apr_shm_create(&shm, SHARED_SIZE, NULL, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + ABTS_PTR_NOTNULL(tc, shm); + + retsize = apr_shm_size_get(shm); + ABTS_INT_EQUAL(tc, SHARED_SIZE, retsize); + + boxes = apr_shm_baseaddr_get(shm); + ABTS_PTR_NOTNULL(tc, boxes); + + rv = apr_proc_fork(&proc, p); + if (rv == APR_INCHILD) { /* child */ + int num = msgwait(5, 0, N_BOXES); + /* exit with the number of messages received so that the parent + * can check that all messages were received. + */ + exit(num); + } + else if (rv == APR_INPARENT) { /* parent */ + i = N_BOXES; + cnt = 0; + while (cnt++ < N_MESSAGES) { + if ((i-=3) < 0) { + i += N_BOXES; /* start over at the top */ + } + msgput(i, MSG); + apr_sleep(apr_time_make(0, 10000)); + } + } + else { + ABTS_FAIL(tc, "apr_proc_fork failed"); + } + /* wait for the child */ + rv = apr_proc_wait(&proc, &recvd, NULL, APR_WAIT); + ABTS_INT_EQUAL(tc, N_MESSAGES, recvd); + + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +} +#endif + +static void test_named(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm = NULL; + apr_size_t retsize; + apr_proc_t pidproducer, pidconsumer; + apr_procattr_t *attr1 = NULL, *attr2 = NULL; + int sent, received; + apr_exit_why_e why; + const char *args[4]; + + apr_shm_remove(SHARED_FILENAME, p); + + rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + if (rv != APR_SUCCESS) { + return; + } + ABTS_PTR_NOTNULL(tc, shm); + + retsize = apr_shm_size_get(shm); + ABTS_INT_EQUAL(tc, SHARED_SIZE, retsize); + + boxes = apr_shm_baseaddr_get(shm); + ABTS_PTR_NOTNULL(tc, boxes); + + rv = apr_procattr_create(&attr1, p); + ABTS_PTR_NOTNULL(tc, attr1); + APR_ASSERT_SUCCESS(tc, "Couldn't create attr1", rv); + args[0] = apr_pstrdup(p, "testshmproducer" EXTENSION); + args[1] = NULL; + rv = apr_proc_create(&pidproducer, "./testshmproducer" EXTENSION, args, + NULL, attr1, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch producer", rv); + + rv = apr_procattr_create(&attr2, p); + ABTS_PTR_NOTNULL(tc, attr2); + APR_ASSERT_SUCCESS(tc, "Couldn't create attr2", rv); + args[0] = apr_pstrdup(p, "testshmconsumer" EXTENSION); + rv = apr_proc_create(&pidconsumer, "./testshmconsumer" EXTENSION, args, + NULL, attr2, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch consumer", rv); + + rv = apr_proc_wait(&pidconsumer, &received, &why, APR_WAIT); + ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv); + ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why); + + rv = apr_proc_wait(&pidproducer, &sent, &why, APR_WAIT); + ABTS_INT_EQUAL(tc, APR_CHILD_DONE, rv); + ABTS_INT_EQUAL(tc, APR_PROC_EXIT, why); + + /* Cleanup before testing that producer and consumer worked correctly. + * This way, if they didn't succeed, we can just run this test again + * without having to cleanup manually. + */ + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory", + apr_shm_destroy(shm)); + + ABTS_INT_EQUAL(tc, sent, received); + +} + +static void test_named_remove(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_shm_t *shm; + + apr_shm_remove(SHARED_FILENAME, p); + + rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + if (rv != APR_SUCCESS) { + return; + } + ABTS_PTR_NOTNULL(tc, shm); + + rv = apr_shm_remove(SHARED_FILENAME, p); + APR_ASSERT_SUCCESS(tc, "Error removing shared memory block", rv); + if (rv != APR_SUCCESS) { + return ; + } + + rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, p); + APR_ASSERT_SUCCESS(tc, "Error allocating shared memory block", rv); + if (rv != APR_SUCCESS) { + return; + } + ABTS_PTR_NOTNULL(tc, shm); + + rv = apr_shm_destroy(shm); + APR_ASSERT_SUCCESS(tc, "Error destroying shared memory block", rv); +} + +#endif + +abts_suite *testshm(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if APR_HAS_SHARED_MEMORY + abts_run_test(suite, test_anon_create, NULL); + abts_run_test(suite, test_check_size, NULL); + abts_run_test(suite, test_shm_allocate, NULL); +#if APR_HAS_FORK + abts_run_test(suite, test_anon, NULL); +#endif + abts_run_test(suite, test_named, NULL); + abts_run_test(suite, test_named_remove, NULL); +#endif + + return suite; +} + + diff --git a/srclib/apr/test/testshm.h b/srclib/apr/test/testshm.h new file mode 100644 index 0000000000..e61b315be4 --- /dev/null +++ b/srclib/apr/test/testshm.h @@ -0,0 +1,33 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TESTSHM_H +#define TESTSHM_H + +typedef struct mbox { + char msg[1024]; + int msgavail; +} mbox; +mbox *boxes; + +#define N_BOXES 10 +#define SHARED_SIZE (apr_size_t)(N_BOXES * sizeof(mbox)) +#define SHARED_FILENAME "data/apr.testshm.shm" +#define N_MESSAGES 100 +#define MSG "Sending a message" + +#endif + diff --git a/srclib/apr/test/testshmconsumer.c b/srclib/apr/test/testshmconsumer.c new file mode 100644 index 0000000000..bede62fe88 --- /dev/null +++ b/srclib/apr/test/testshmconsumer.c @@ -0,0 +1,94 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_shm.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_time.h" +#include "testshm.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + + +#if APR_HAS_SHARED_MEMORY + +static int msgwait(int sleep_sec, int first_box, int last_box) +{ + int i; + int recvd = 0; + apr_time_t start = apr_time_now(); + apr_interval_time_t sleep_duration = apr_time_from_sec(sleep_sec); + while (apr_time_now() - start < sleep_duration) { + for (i = first_box; i < last_box; i++) { + if (boxes[i].msgavail && !strcmp(boxes[i].msg, MSG)) { + recvd++; + boxes[i].msgavail = 0; /* reset back to 0 */ + memset(boxes[i].msg, 0, 1024); + } + } + apr_sleep(apr_time_from_sec(1)); + } + return recvd; +} + +int main(void) +{ + apr_status_t rv; + apr_pool_t *pool; + apr_shm_t *shm; + int recvd; + + apr_initialize(); + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { + exit(-1); + } + + rv = apr_shm_attach(&shm, SHARED_FILENAME, pool); + if (rv != APR_SUCCESS) { + exit(-2); + } + + boxes = apr_shm_baseaddr_get(shm); + + /* consume messages on all of the boxes */ + recvd = msgwait(30, 0, N_BOXES); /* wait for 30 seconds for messages */ + + rv = apr_shm_detach(shm); + if (rv != APR_SUCCESS) { + exit(-3); + } + + return recvd; +} + +#else /* APR_HAS_SHARED_MEMORY */ + +int main(void) +{ + /* Just return, this program will never be called, so we don't need + * to print a message + */ + return 0; +} + +#endif /* APR_HAS_SHARED_MEMORY */ + diff --git a/srclib/apr/test/testshmproducer.c b/srclib/apr/test/testshmproducer.c new file mode 100644 index 0000000000..dbab1298fd --- /dev/null +++ b/srclib/apr/test/testshmproducer.c @@ -0,0 +1,89 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_shm.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "apr_time.h" +#include "testshm.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + + +#if APR_HAS_SHARED_MEMORY +static void msgput(int boxnum, char *msg) +{ + apr_cpystrn(boxes[boxnum].msg, msg, strlen(msg) + 1); + boxes[boxnum].msgavail = 1; +} + +int main(void) +{ + apr_status_t rv; + apr_pool_t *pool; + apr_shm_t *shm; + int i; + int sent = 0; + + apr_initialize(); + + if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { + exit(-1); + } + + rv = apr_shm_attach(&shm, SHARED_FILENAME, pool); + if (rv != APR_SUCCESS) { + exit(-2); + } + + boxes = apr_shm_baseaddr_get(shm); + + /* produce messages on all of the boxes, in descending order, + * Yes, we could just return N_BOXES, but I want to have a double-check + * in this code. The original code actually sent N_BOXES - 1 messages, + * so rather than rely on possibly buggy code, this way we know that we + * are returning the right number. + */ + for (i = N_BOXES - 1, sent = 0; i >= 0; i--, sent++) { + msgput(i, MSG); + apr_sleep(apr_time_from_sec(1)); + } + + rv = apr_shm_detach(shm); + if (rv != APR_SUCCESS) { + exit(-3); + } + + return sent; +} + +#else /* APR_HAS_SHARED_MEMORY */ + +int main(void) +{ + /* Just return, this program will never be launched, so there is no + * reason to print a message. + */ + return 0; +} + +#endif /* APR_HAS_SHARED_MEMORY */ + diff --git a/srclib/apr/test/testsleep.c b/srclib/apr/test/testsleep.c new file mode 100644 index 0000000000..38a3b354d7 --- /dev/null +++ b/srclib/apr/test/testsleep.c @@ -0,0 +1,54 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "time.h" +#include "apr_thread_proc.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include +#include +#include +#include "testutil.h" + +#define SLEEP_INTERVAL 5 + +static void sleep_one(abts_case *tc, void *data) +{ + time_t pretime = time(NULL); + time_t posttime; + time_t timediff; + + apr_sleep(apr_time_from_sec(SLEEP_INTERVAL)); + posttime = time(NULL); + + /* normalize the timediff. We should have slept for SLEEP_INTERVAL, so + * we should just subtract that out. + */ + timediff = posttime - pretime - SLEEP_INTERVAL; + ABTS_TRUE(tc, timediff >= 0); + ABTS_TRUE(tc, timediff <= 1); +} + +abts_suite *testsleep(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, sleep_one, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testsock.c b/srclib/apr/test/testsock.c new file mode 100644 index 0000000000..e6c8280ca2 --- /dev/null +++ b/srclib/apr/test/testsock.c @@ -0,0 +1,218 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "testsock.h" +#include "apr_thread_proc.h" +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" + +static void launch_child(abts_case *tc, apr_proc_t *proc, const char *arg1, apr_pool_t *p) +{ + apr_procattr_t *procattr; + const char *args[3]; + apr_status_t rv; + + rv = apr_procattr_create(&procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't create procattr", rv); + + rv = apr_procattr_io_set(procattr, APR_NO_PIPE, APR_NO_PIPE, + APR_NO_PIPE); + APR_ASSERT_SUCCESS(tc, "Couldn't set io in procattr", rv); + + rv = apr_procattr_error_check_set(procattr, 1); + APR_ASSERT_SUCCESS(tc, "Couldn't set error check in procattr", rv); + + args[0] = "sockchild" EXTENSION; + args[1] = arg1; + args[2] = NULL; + rv = apr_proc_create(proc, "./sockchild" EXTENSION, args, NULL, + procattr, p); + APR_ASSERT_SUCCESS(tc, "Couldn't launch program", rv); +} + +static int wait_child(abts_case *tc, apr_proc_t *proc) +{ + int exitcode; + apr_exit_why_e why; + + ABTS_ASSERT(tc, "Error waiting for child process", + apr_proc_wait(proc, &exitcode, &why, APR_WAIT) == APR_CHILD_DONE); + + ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT); + return exitcode; +} + +static void test_addr_info(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_sockaddr_t *sa; + + rv = apr_sockaddr_info_get(&sa, NULL, APR_UNSPEC, 80, 0, p); + APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv); + + rv = apr_sockaddr_info_get(&sa, "127.0.0.1", APR_UNSPEC, 80, 0, p); + APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv); + ABTS_STR_EQUAL(tc, "127.0.0.1", sa->hostname); +} + +static apr_socket_t *setup_socket(abts_case *tc) +{ + apr_status_t rv; + apr_sockaddr_t *sa; + apr_socket_t *sock; + + rv = apr_sockaddr_info_get(&sa, NULL, APR_INET, 8021, 0, p); + APR_ASSERT_SUCCESS(tc, "Problem generating sockaddr", rv); + + rv = apr_socket_create(&sock, sa->family, SOCK_STREAM, APR_PROTO_TCP, p); + APR_ASSERT_SUCCESS(tc, "Problem creating socket", rv); + + rv = apr_socket_bind(sock, sa); + APR_ASSERT_SUCCESS(tc, "Problem binding to port", rv); + if (rv) return NULL; + + rv = apr_socket_listen(sock, 5); + APR_ASSERT_SUCCESS(tc, "Problem listening on socket", rv); + + return sock; +} + +static void test_create_bind_listen(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock = setup_socket(tc); + + if (!sock) return; + + rv = apr_socket_close(sock); + APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); +} + +static void test_send(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock; + apr_socket_t *sock2; + apr_proc_t proc; + int protocol; + apr_size_t length; + + sock = setup_socket(tc); + if (!sock) return; + + launch_child(tc, &proc, "read", p); + + rv = apr_socket_accept(&sock2, sock, p); + APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); + + apr_socket_protocol_get(sock2, &protocol); + ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); + + length = strlen(DATASTR); + apr_socket_send(sock2, DATASTR, &length); + + /* Make sure that the client received the data we sent */ + ABTS_INT_EQUAL(tc, strlen(DATASTR), wait_child(tc, &proc)); + + rv = apr_socket_close(sock2); + APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); + rv = apr_socket_close(sock); + APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); +} + +static void test_recv(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock; + apr_socket_t *sock2; + apr_proc_t proc; + int protocol; + apr_size_t length = STRLEN; + char datastr[STRLEN]; + + sock = setup_socket(tc); + if (!sock) return; + + launch_child(tc, &proc, "write", p); + + rv = apr_socket_accept(&sock2, sock, p); + APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); + + apr_socket_protocol_get(sock2, &protocol); + ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); + + memset(datastr, 0, STRLEN); + apr_socket_recv(sock2, datastr, &length); + + /* Make sure that the server received the data we sent */ + ABTS_STR_EQUAL(tc, DATASTR, datastr); + ABTS_INT_EQUAL(tc, strlen(datastr), wait_child(tc, &proc)); + + rv = apr_socket_close(sock2); + APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); + rv = apr_socket_close(sock); + APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); +} + +static void test_timeout(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock; + apr_socket_t *sock2; + apr_proc_t proc; + int protocol; + int exit; + + sock = setup_socket(tc); + if (!sock) return; + + launch_child(tc, &proc, "read", p); + + rv = apr_socket_accept(&sock2, sock, p); + APR_ASSERT_SUCCESS(tc, "Problem with receiving connection", rv); + + apr_socket_protocol_get(sock2, &protocol); + ABTS_INT_EQUAL(tc, APR_PROTO_TCP, protocol); + + exit = wait_child(tc, &proc); + ABTS_INT_EQUAL(tc, SOCKET_TIMEOUT, exit); + + /* We didn't write any data, so make sure the child program returns + * an error. + */ + rv = apr_socket_close(sock2); + APR_ASSERT_SUCCESS(tc, "Problem closing connected socket", rv); + rv = apr_socket_close(sock); + APR_ASSERT_SUCCESS(tc, "Problem closing socket", rv); +} + +abts_suite *testsock(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_addr_info, NULL); + abts_run_test(suite, test_create_bind_listen, NULL); + abts_run_test(suite, test_send, NULL); + abts_run_test(suite, test_recv, NULL); + abts_run_test(suite, test_timeout, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testsock.h b/srclib/apr/test/testsock.h new file mode 100644 index 0000000000..243cbf9eef --- /dev/null +++ b/srclib/apr/test/testsock.h @@ -0,0 +1,34 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TESTSOCK_H +#define TESTSOCK_H + +#define DATASTR "This is a test" +#define STRLEN 8092 + +/* This is a hack. We can't return APR_TIMEOUT from sockchild, because + * Unix OSes only return the least significant 8 bits of the return code, + * which means that instead of receiving 70007, testsock gets 119. But, + * we also don't want to return -1, because we use that value for general + * errors from sockchild. So, we define 1 to mean that the read/write + * operation timed out. This means that we can't write a test that tries + * to send a single character between ends of the socket. + */ +#define SOCKET_TIMEOUT 1 + +#endif + diff --git a/srclib/apr/test/testsockets.c b/srclib/apr/test/testsockets.c new file mode 100644 index 0000000000..69fdf1e5bc --- /dev/null +++ b/srclib/apr/test/testsockets.c @@ -0,0 +1,208 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "testutil.h" + +#define STRLEN 21 + +static void tcp_socket(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock = NULL; + int type; + + rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, sock); + + rv = apr_socket_type_get(sock, &type); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, SOCK_STREAM, type); + + apr_socket_close(sock); +} + +static void udp_socket(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock = NULL; + int type; + + rv = apr_socket_create(&sock, APR_INET, SOCK_DGRAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, sock); + + rv = apr_socket_type_get(sock, &type); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, SOCK_DGRAM, type); + + apr_socket_close(sock); +} + +/* On recent Linux systems, whilst IPv6 is always supported by glibc, + * socket(AF_INET6, ...) calls will fail with EAFNOSUPPORT if the + * "ipv6" kernel module is not loaded. */ +#ifdef EAFNOSUPPORT +#define V6_NOT_ENABLED(e) ((e) == EAFNOSUPPORT) +#else +#define V6_NOT_ENABLED(e) (0) +#endif + +static void tcp6_socket(abts_case *tc, void *data) +{ +#if APR_HAVE_IPV6 + apr_status_t rv; + apr_socket_t *sock = NULL; + + rv = apr_socket_create(&sock, APR_INET6, SOCK_STREAM, 0, p); + if (V6_NOT_ENABLED(rv)) { + ABTS_NOT_IMPL(tc, "IPv6 not enabled"); + return; + } + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, sock); + apr_socket_close(sock); +#else + ABTS_NOT_IMPL(tc, "IPv6"); +#endif +} + +static void udp6_socket(abts_case *tc, void *data) +{ +#if APR_HAVE_IPV6 + apr_status_t rv; + apr_socket_t *sock = NULL; + + rv = apr_socket_create(&sock, APR_INET6, SOCK_DGRAM, 0, p); + if (V6_NOT_ENABLED(rv)) { + ABTS_NOT_IMPL(tc, "IPv6 not enabled"); + return; + } + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, sock); + apr_socket_close(sock); +#else + ABTS_NOT_IMPL(tc, "IPv6"); +#endif +} + +static void sendto_receivefrom(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_socket_t *sock = NULL; + apr_socket_t *sock2 = NULL; + char sendbuf[STRLEN] = "APR_INET, SOCK_DGRAM"; + char recvbuf[80]; + char *ip_addr; + apr_port_t fromport; + apr_sockaddr_t *from; + apr_sockaddr_t *to; + apr_size_t len = 30; + int family; + const char *addr; + +#if APR_HAVE_IPV6 + family = APR_INET6; + addr = "::1"; + rv = apr_socket_create(&sock, family, SOCK_DGRAM, 0, p); + if (V6_NOT_ENABLED(rv)) { +#endif + family = APR_INET; + addr = "127.0.0.1"; + rv = apr_socket_create(&sock, family, SOCK_DGRAM, 0, p); +#if APR_HAVE_IPV6 + } +#endif + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_socket_create(&sock2, family, SOCK_DGRAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_sockaddr_info_get(&to, addr, APR_UNSPEC, 7772, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_sockaddr_info_get(&from, addr, APR_UNSPEC, 7771, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_bind(sock, to); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_socket_bind(sock2, from); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + len = STRLEN; + rv = apr_socket_sendto(sock2, to, 0, sendbuf, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, STRLEN, len); + + len = 80; + rv = apr_socket_recvfrom(from, sock, 0, recvbuf, &len); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, STRLEN, len); + ABTS_STR_EQUAL(tc, "APR_INET, SOCK_DGRAM", recvbuf); + + apr_sockaddr_ip_get(&ip_addr, from); + fromport = from->port; + ABTS_STR_EQUAL(tc, addr, ip_addr); + ABTS_INT_EQUAL(tc, 7771, fromport); + + apr_socket_close(sock); + apr_socket_close(sock2); +} + +static void socket_userdata(abts_case *tc, void *data) +{ + apr_socket_t *sock1, *sock2; + apr_status_t rv; + void *user; + const char *key = "GENERICKEY"; + + rv = apr_socket_create(&sock1, AF_INET, SOCK_STREAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_socket_create(&sock2, AF_INET, SOCK_STREAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_data_set(sock1, "SOCK1", key, NULL); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_socket_data_set(sock2, "SOCK2", key, NULL); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_data_get(&user, key, sock1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "SOCK1", user); + rv = apr_socket_data_get(&user, key, sock2); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_STR_EQUAL(tc, "SOCK2", user); +} + +abts_suite *testsockets(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, tcp_socket, NULL); + abts_run_test(suite, udp_socket, NULL); + + abts_run_test(suite, tcp6_socket, NULL); + abts_run_test(suite, udp6_socket, NULL); + + abts_run_test(suite, sendto_receivefrom, NULL); + + abts_run_test(suite, socket_userdata, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testsockopt.c b/srclib/apr/test/testsockopt.c new file mode 100644 index 0000000000..28d4fe31d5 --- /dev/null +++ b/srclib/apr/test/testsockopt.c @@ -0,0 +1,137 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_network_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "testutil.h" + +static apr_socket_t *sock = NULL; + +static void create_socket(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_socket_create(&sock, APR_INET, SOCK_STREAM, 0, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_PTR_NOTNULL(tc, sock); +} + +static void set_keepalive(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_int32_t ck; + + rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, ck); +} + +static void set_debug(abts_case *tc, void *data) +{ + apr_status_t rv1, rv2; + apr_int32_t ck; + + /* On some platforms APR_SO_DEBUG can only be set as root; just test + * for get/set consistency of this option. */ + rv1 = apr_socket_opt_set(sock, APR_SO_DEBUG, 1); + rv2 = apr_socket_opt_get(sock, APR_SO_DEBUG, &ck); + APR_ASSERT_SUCCESS(tc, "get SO_DEBUG option", rv2); + if (rv1 == APR_SUCCESS) { + ABTS_INT_EQUAL(tc, 1, ck); + } else { + ABTS_INT_EQUAL(tc, 0, ck); + } +} + +static void remove_keepalive(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_int32_t ck; + + rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, ck); + + rv = apr_socket_opt_set(sock, APR_SO_KEEPALIVE, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, ck); +} + +static void corkable(abts_case *tc, void *data) +{ +#if !APR_HAVE_CORKABLE_TCP + ABTS_NOT_IMPL(tc, "TCP isn't corkable"); +#else + apr_status_t rv; + apr_int32_t ck; + + rv = apr_socket_opt_set(sock, APR_TCP_NODELAY, 1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, ck); + + rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 1); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_opt_get(sock, APR_TCP_NOPUSH, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, ck); + + rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 0, ck); + + rv = apr_socket_opt_set(sock, APR_TCP_NOPUSH, 0); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_socket_opt_get(sock, APR_TCP_NODELAY, &ck); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + ABTS_INT_EQUAL(tc, 1, ck); +#endif +} + +static void close_socket(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_socket_close(sock); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +abts_suite *testsockopt(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, create_socket, NULL); + abts_run_test(suite, set_keepalive, NULL); + abts_run_test(suite, set_debug, NULL); + abts_run_test(suite, remove_keepalive, NULL); + abts_run_test(suite, corkable, NULL); + abts_run_test(suite, close_socket, NULL); + + return suite; +} + diff --git a/srclib/apr/test/teststr.c b/srclib/apr/test/teststr.c new file mode 100644 index 0000000000..490d5e184c --- /dev/null +++ b/srclib/apr/test/teststr.c @@ -0,0 +1,370 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" + +#include +#include +#include +#include + +#if APR_HAVE_LIMITS_H +#include +#endif + +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_errno.h" + +/* I haven't bothered to check for APR_ENOTIMPL here, AFAIK, all string + * functions exist on all platforms. + */ + +static void test_strtok(abts_case *tc, void *data) +{ + struct { + char *input; + char *sep; + } + cases[] = { + { + "", + "Z" + }, + { + " asdf jkl; 77889909 \r\n\1\2\3Z", + " \r\n\3\2\1" + }, + { + NULL, /* but who cares if apr_strtok() segfaults? */ + " \t" + }, +#if 0 /* don't do this... you deserve to segfault */ + { + "a b c ", + NULL + }, +#endif + { + " a b c ", + "" + }, + { + "a b c ", + " " + } + }; + int curtc; + + for (curtc = 0; curtc < sizeof cases / sizeof cases[0]; curtc++) { + char *retval1, *retval2; + char *str1, *str2; + char *state; + + str1 = apr_pstrdup(p, cases[curtc].input); + str2 = apr_pstrdup(p, cases[curtc].input); + + do { + retval1 = apr_strtok(str1, cases[curtc].sep, &state); + retval2 = strtok(str2, cases[curtc].sep); + + if (!retval1) { + ABTS_TRUE(tc, retval2 == NULL); + } + else { + ABTS_TRUE(tc, retval2 != NULL); + ABTS_STR_EQUAL(tc, retval2, retval1); + } + + str1 = str2 = NULL; /* make sure we pass NULL on subsequent calls */ + } while (retval1); + } +} + +static void snprintf_noNULL(abts_case *tc, void *data) +{ + char buff[100]; + char *testing = apr_palloc(p, 10); + + testing[0] = 't'; + testing[1] = 'e'; + testing[2] = 's'; + testing[3] = 't'; + testing[4] = 'i'; + testing[5] = 'n'; + testing[6] = 'g'; + + /* If this test fails, we are going to seg fault. */ + apr_snprintf(buff, sizeof(buff), "%.*s", 7, testing); + ABTS_STR_NEQUAL(tc, buff, testing, 7); +} + +static void snprintf_0NULL(abts_case *tc, void *data) +{ + int rv; + + rv = apr_snprintf(NULL, 0, "%sBAR", "FOO"); + ABTS_INT_EQUAL(tc, 6, rv); +} + +static void snprintf_0nonNULL(abts_case *tc, void *data) +{ + int rv; + char *buff = "testing"; + + rv = apr_snprintf(buff, 0, "%sBAR", "FOO"); + ABTS_INT_EQUAL(tc, 6, rv); + ABTS_ASSERT(tc, "buff unmangled", strcmp(buff, "FOOBAR") != 0); +} + +static void snprintf_underflow(abts_case *tc, void *data) +{ + char buf[20]; + int rv; + + rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.0001); + ABTS_INT_EQUAL(tc, 4, rv); + ABTS_STR_EQUAL(tc, "0.00", buf); + + rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.001); + ABTS_INT_EQUAL(tc, 4, rv); + ABTS_STR_EQUAL(tc, "0.00", buf); + + rv = apr_snprintf(buf, sizeof buf, "%.2f", (double)0.01); + ABTS_INT_EQUAL(tc, 4, rv); + ABTS_STR_EQUAL(tc, "0.01", buf); +} + +static void string_error(abts_case *tc, void *data) +{ + char buf[128], *rv; + apr_status_t n; + + buf[0] = '\0'; + rv = apr_strerror(APR_ENOENT, buf, sizeof buf); + ABTS_PTR_EQUAL(tc, buf, rv); + ABTS_TRUE(tc, strlen(buf) > 0); + + rv = apr_strerror(APR_TIMEUP, buf, sizeof buf); + ABTS_PTR_EQUAL(tc, buf, rv); + ABTS_STR_EQUAL(tc, "The timeout specified has expired", buf); + + /* throw some randomish numbers at it to check for robustness */ + for (n = 1; n < 1000000; n *= 2) { + apr_strerror(n, buf, sizeof buf); + } +} + +#define SIZE 180000 +static void string_long(abts_case *tc, void *data) +{ + char s[SIZE + 1]; + + memset(s, 'A', SIZE); + s[SIZE] = '\0'; + + apr_psprintf(p, "%s", s); +} + +/* ### FIXME: apr.h/apr_strings.h should provide these! */ +#define MY_LLONG_MAX (APR_INT64_C(9223372036854775807)) +#define MY_LLONG_MIN (-MY_LLONG_MAX - APR_INT64_C(1)) + +static void string_strtoi64(abts_case *tc, void *data) +{ + static const struct { + int errnum, base; + const char *in, *end; + apr_int64_t result; + } ts[] = { + + /* base 10 tests */ + { 0, 10, "123545", NULL, APR_INT64_C(123545) }, + { 0, 10, " 123545", NULL, APR_INT64_C(123545) }, + { 0, 10, " +123545", NULL, APR_INT64_C(123545) }, + { 0, 10, "-123545", NULL, APR_INT64_C(-123545) }, + { 0, 10, " 00000123545", NULL, APR_INT64_C(123545) }, + { 0, 10, "123545ZZZ", "ZZZ", APR_INT64_C(123545) }, + { 0, 10, " 123545 ", " ", APR_INT64_C(123545) }, + + /* base 16 tests */ + { 0, 16, "1E299", NULL, APR_INT64_C(123545) }, + { 0, 16, "1e299", NULL, APR_INT64_C(123545) }, + { 0, 16, "0x1e299", NULL, APR_INT64_C(123545) }, + { 0, 16, "0X1E299", NULL, APR_INT64_C(123545) }, + { 0, 16, "+1e299", NULL, APR_INT64_C(123545) }, + { 0, 16, "-1e299", NULL, APR_INT64_C(-123545) }, + { 0, 16, " -1e299", NULL, APR_INT64_C(-123545) }, + + /* automatic base detection tests */ + { 0, 0, "123545", NULL, APR_INT64_C(123545) }, + { 0, 0, "0x1e299", NULL, APR_INT64_C(123545) }, + { 0, 0, " 0x1e299", NULL, APR_INT64_C(123545) }, + { 0, 0, "+0x1e299", NULL, APR_INT64_C(123545) }, + { 0, 0, "-0x1e299", NULL, APR_INT64_C(-123545) }, + + /* large number tests */ + { 0, 10, "8589934605", NULL, APR_INT64_C(8589934605) }, + { 0, 10, "-8589934605", NULL, APR_INT64_C(-8589934605) }, + { 0, 16, "0x20000000D", NULL, APR_INT64_C(8589934605) }, + { 0, 16, "-0x20000000D", NULL, APR_INT64_C(-8589934605) }, + { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) }, + { 0, 16, " 0x20000000D", NULL, APR_INT64_C(8589934605) }, + + /* error cases */ + { ERANGE, 10, "999999999999999999999999999999999", "", MY_LLONG_MAX }, + { ERANGE, 10, "-999999999999999999999999999999999", "", MY_LLONG_MIN }, + +#if 0 + /* C99 doesn't require EINVAL for an invalid range. */ + { EINVAL, 99, "", (void *)-1 /* don't care */, 0 }, +#endif + + /* some strtoll implementations give EINVAL when no conversion + * is performed. */ + { -1 /* don't care */, 10, "zzz", "zzz", APR_INT64_C(0) }, + { -1 /* don't care */, 10, "", NULL, APR_INT64_C(0) } + + }; + int n; + + for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) { + char *end = "end ptr not changed"; + apr_int64_t result; + int errnum; + + errno = 0; + result = apr_strtoi64(ts[n].in, &end, ts[n].base); + errnum = errno; + + ABTS_ASSERT(tc, + apr_psprintf(p, "for '%s': result was %" APR_INT64_T_FMT + " not %" APR_INT64_T_FMT, ts[n].in, + result, ts[n].result), + result == ts[n].result); + + if (ts[n].errnum != -1) { + ABTS_ASSERT(tc, + apr_psprintf(p, "for '%s': errno was %d not %d", ts[n].in, + errnum, ts[n].errnum), + ts[n].errnum == errnum); + } + + if (ts[n].end == NULL) { + /* end must point to NUL terminator of .in */ + ABTS_PTR_EQUAL(tc, ts[n].in + strlen(ts[n].in), end); + } else if (ts[n].end != (void *)-1) { + ABTS_ASSERT(tc, + apr_psprintf(p, "for '%s', end was '%s' not '%s'", + ts[n].in, end, ts[n].end), + strcmp(ts[n].end, end) == 0); + } + } +} + +static void string_strtoff(abts_case *tc, void *data) +{ + apr_off_t off; + + ABTS_ASSERT(tc, "strtoff fails on out-of-range integer", + apr_strtoff(&off, "999999999999999999999999999999", + NULL, 10) != APR_SUCCESS); + + ABTS_ASSERT(tc, "strtoff failed for 1234", + apr_strtoff(&off, "1234", NULL, 10) == APR_SUCCESS); + + ABTS_ASSERT(tc, "strtoff failed to parse 1234", off == 1234); +} + +/* random-ish checks for strfsize buffer overflows */ +static void overflow_strfsize(abts_case *tc, void *data) +{ + apr_off_t off; + char buf[7]; + + buf[5] = '$'; + buf[6] = '@'; + + for (off = -9999; off < 20000; off++) { + apr_strfsize(off, buf); + } + for (; off < 9999999; off += 9) { + apr_strfsize(off, buf); + } + for (; off < 999999999; off += 999) { + apr_strfsize(off, buf); + } + for (off = 1; off < LONG_MAX && off > 0; off *= 2) { + apr_strfsize(off, buf); + apr_strfsize(off + 1, buf); + apr_strfsize(off - 1, buf); + } + + ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '$'); + ABTS_ASSERT(tc, "strfsize overflowed", buf[6] == '@'); +} + +static void string_strfsize(abts_case *tc, void *data) +{ + static const struct { + apr_off_t size; + const char *buf; + } ts[] = { + { -1, " - " }, + { 0, " 0 " }, + { 666, "666 " }, + { 1024, "1.0K" }, + { 1536, "1.5K" }, + { 2048, "2.0K" }, + { 1293874, "1.2M" }, + { 9999999, "9.5M" }, + { 103809024, " 99M" }, + { 1047527424, "1.0G" } /* "999M" would be more correct */ + }; + apr_size_t n; + + for (n = 0; n < sizeof(ts)/sizeof(ts[0]); n++) { + char buf[6], *ret; + + buf[5] = '%'; + + ret = apr_strfsize(ts[n].size, buf); + ABTS_ASSERT(tc, "strfsize returned wrong buffer", ret == buf); + ABTS_ASSERT(tc, "strfsize overflowed", buf[5] == '%'); + + ABTS_STR_EQUAL(tc, ts[n].buf, ret); + } +} + +abts_suite *teststr(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, snprintf_0NULL, NULL); + abts_run_test(suite, snprintf_0nonNULL, NULL); + abts_run_test(suite, snprintf_noNULL, NULL); + abts_run_test(suite, snprintf_underflow, NULL); + abts_run_test(suite, test_strtok, NULL); + abts_run_test(suite, string_error, NULL); + abts_run_test(suite, string_long, NULL); + abts_run_test(suite, string_strtoi64, NULL); + abts_run_test(suite, string_strtoff, NULL); + abts_run_test(suite, overflow_strfsize, NULL); + abts_run_test(suite, string_strfsize, NULL); + + return suite; +} + diff --git a/srclib/apr/test/teststrnatcmp.c b/srclib/apr/test/teststrnatcmp.c new file mode 100644 index 0000000000..c0b92d619d --- /dev/null +++ b/srclib/apr/test/teststrnatcmp.c @@ -0,0 +1,78 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_strings.h" +#include "testutil.h" + +static void less0(abts_case *tc, void *data) +{ + int rv = apr_strnatcmp("a", "b"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0); +} + +static void str_equal(abts_case *tc, void *data) +{ + int rv = apr_strnatcmp("a", "a"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv == 0); +} + +static void more0(abts_case *tc, void *data) +{ + int rv = apr_strnatcmp("b", "a"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv > 0); +} + +static void less_ignore_case(abts_case *tc, void *data) +{ + int rv = apr_strnatcasecmp("a", "B"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0); +} + +static void str_equal_ignore_case(abts_case *tc, void *data) +{ + int rv = apr_strnatcasecmp("a", "A"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv == 0); +} + +static void more_ignore_case(abts_case *tc, void *data) +{ + int rv = apr_strnatcasecmp("b", "A"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv > 0); +} + +static void natcmp(abts_case *tc, void *data) +{ + int rv = apr_strnatcasecmp("a2", "a10"); + ABTS_ASSERT(tc, "didn't compare simple strings properly", rv < 0); +} + +abts_suite *teststrnatcmp(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, less0, NULL); + abts_run_test(suite, str_equal, NULL); + abts_run_test(suite, more0, NULL); + abts_run_test(suite, less_ignore_case, NULL); + abts_run_test(suite, str_equal_ignore_case, NULL); + abts_run_test(suite, more_ignore_case, NULL); + abts_run_test(suite, natcmp, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testtable.c b/srclib/apr/test/testtable.c new file mode 100644 index 0000000000..1ba69a5365 --- /dev/null +++ b/srclib/apr/test/testtable.c @@ -0,0 +1,190 @@ +/* Copyright 2002-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr.h" +#include "apr_strings.h" +#include "apr_general.h" +#include "apr_pools.h" +#include "apr_tables.h" +#if APR_HAVE_STDIO_H +#include +#endif +#if APR_HAVE_STDLIB_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif + +static apr_table_t *t1 = NULL; + +static void table_make(abts_case *tc, void *data) +{ + t1 = apr_table_make(p, 5); + ABTS_PTR_NOTNULL(tc, t1); +} + +static void table_get(abts_case *tc, void *data) +{ + const char *val; + + apr_table_set(t1, "foo", "bar"); + val = apr_table_get(t1, "foo"); + ABTS_STR_EQUAL(tc, val, "bar"); +} + +static void table_set(abts_case *tc, void *data) +{ + const char *val; + + apr_table_set(t1, "setkey", "bar"); + apr_table_set(t1, "setkey", "2ndtry"); + val = apr_table_get(t1, "setkey"); + ABTS_STR_EQUAL(tc, val, "2ndtry"); +} + +static void table_getnotthere(abts_case *tc, void *data) +{ + const char *val; + + val = apr_table_get(t1, "keynotthere"); + ABTS_PTR_EQUAL(tc, NULL, (void *)val); +} + +static void table_add(abts_case *tc, void *data) +{ + const char *val; + + apr_table_add(t1, "addkey", "bar"); + apr_table_add(t1, "addkey", "foo"); + val = apr_table_get(t1, "addkey"); + ABTS_STR_EQUAL(tc, val, "bar"); + +} + +static void table_nelts(abts_case *tc, void *data) +{ + const char *val; + apr_table_t *t = apr_table_make(p, 1); + + apr_table_set(t, "abc", "def"); + apr_table_set(t, "def", "abc"); + apr_table_set(t, "foo", "zzz"); + val = apr_table_get(t, "foo"); + ABTS_STR_EQUAL(tc, val, "zzz"); + val = apr_table_get(t, "abc"); + ABTS_STR_EQUAL(tc, val, "def"); + val = apr_table_get(t, "def"); + ABTS_STR_EQUAL(tc, val, "abc"); + ABTS_INT_EQUAL(tc, 3, apr_table_elts(t)->nelts); +} + +static void table_clear(abts_case *tc, void *data) +{ + apr_table_clear(t1); + ABTS_INT_EQUAL(tc, 0, apr_table_elts(t1)->nelts); +} + +static void table_unset(abts_case *tc, void *data) +{ + const char *val; + apr_table_t *t = apr_table_make(p, 1); + + apr_table_set(t, "a", "1"); + apr_table_set(t, "b", "2"); + apr_table_unset(t, "b"); + ABTS_INT_EQUAL(tc, 1, apr_table_elts(t)->nelts); + val = apr_table_get(t, "a"); + ABTS_STR_EQUAL(tc, val, "1"); + val = apr_table_get(t, "b"); + ABTS_PTR_EQUAL(tc, (void *)val, (void *)NULL); +} + +static void table_overlap(abts_case *tc, void *data) +{ + const char *val; + apr_table_t *t1 = apr_table_make(p, 1); + apr_table_t *t2 = apr_table_make(p, 1); + + apr_table_addn(t1, "a", "0"); + apr_table_addn(t1, "g", "7"); + apr_table_addn(t2, "a", "1"); + apr_table_addn(t2, "b", "2"); + apr_table_addn(t2, "c", "3"); + apr_table_addn(t2, "b", "2.0"); + apr_table_addn(t2, "d", "4"); + apr_table_addn(t2, "e", "5"); + apr_table_addn(t2, "b", "2."); + apr_table_addn(t2, "f", "6"); + apr_table_overlap(t1, t2, APR_OVERLAP_TABLES_SET); + + ABTS_INT_EQUAL(tc, apr_table_elts(t1)->nelts, 7); + val = apr_table_get(t1, "a"); + ABTS_STR_EQUAL(tc, val, "1"); + val = apr_table_get(t1, "b"); + ABTS_STR_EQUAL(tc, val, "2."); + val = apr_table_get(t1, "c"); + ABTS_STR_EQUAL(tc, val, "3"); + val = apr_table_get(t1, "d"); + ABTS_STR_EQUAL(tc, val, "4"); + val = apr_table_get(t1, "e"); + ABTS_STR_EQUAL(tc, val, "5"); + val = apr_table_get(t1, "f"); + ABTS_STR_EQUAL(tc, val, "6"); + val = apr_table_get(t1, "g"); + ABTS_STR_EQUAL(tc, val, "7"); +} + +static void table_overlap2(abts_case *tc, void *data) +{ + apr_pool_t *subp; + apr_table_t *t1, *t2; + + apr_pool_create(&subp, p); + + t1 = apr_table_make(subp, 1); + t2 = apr_table_make(p, 1); + apr_table_addn(t1, "t1", "one"); + apr_table_addn(t2, "t2", "two"); + + apr_table_overlap(t1, t2, APR_OVERLAP_TABLES_SET); + + ABTS_INT_EQUAL(tc, 2, apr_table_elts(t1)->nelts); + + ABTS_STR_EQUAL(tc, apr_table_get(t1, "t1"), "one"); + ABTS_STR_EQUAL(tc, apr_table_get(t1, "t2"), "two"); + +} + +abts_suite *testtable(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, table_make, NULL); + abts_run_test(suite, table_get, NULL); + abts_run_test(suite, table_set, NULL); + abts_run_test(suite, table_getnotthere, NULL); + abts_run_test(suite, table_add, NULL); + abts_run_test(suite, table_nelts, NULL); + abts_run_test(suite, table_clear, NULL); + abts_run_test(suite, table_unset, NULL); + abts_run_test(suite, table_overlap, NULL); + abts_run_test(suite, table_overlap2, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testtemp.c b/srclib/apr/test/testtemp.c new file mode 100644 index 0000000000..bff48d2532 --- /dev/null +++ b/srclib/apr/test/testtemp.c @@ -0,0 +1,55 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_file_io.h" +#include "apr_strings.h" + +static void test_temp_dir(abts_case *tc, void *data) +{ + const char *tempdir = NULL; + apr_status_t rv; + + rv = apr_temp_dir_get(&tempdir, p); + APR_ASSERT_SUCCESS(tc, "Error finding Temporary Directory", rv); + ABTS_PTR_NOTNULL(tc, tempdir); +} + +static void test_mktemp(abts_case *tc, void *data) +{ + apr_file_t *f = NULL; + const char *tempdir = NULL; + char *filetemplate; + apr_status_t rv; + + rv = apr_temp_dir_get(&tempdir, p); + APR_ASSERT_SUCCESS(tc, "Error finding Temporary Directory", rv); + + filetemplate = apr_pstrcat(p, tempdir, "/tempfileXXXXXX", NULL); + rv = apr_file_mktemp(&f, filetemplate, 0, p); + APR_ASSERT_SUCCESS(tc, "Error opening Temporary file", rv); +} + +abts_suite *testtemp(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_temp_dir, NULL); + abts_run_test(suite, test_mktemp, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testthread.c b/srclib/apr/test/testthread.c new file mode 100644 index 0000000000..44ed57b282 --- /dev/null +++ b/srclib/apr/test/testthread.c @@ -0,0 +1,133 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_thread_proc.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "errno.h" +#include "apr_time.h" +#include "testutil.h" + +#if APR_HAS_THREADS + +static apr_thread_mutex_t *thread_lock; +static apr_thread_once_t *control = NULL; +static int x = 0; +static int value = 0; + +static apr_thread_t *t1; +static apr_thread_t *t2; +static apr_thread_t *t3; +static apr_thread_t *t4; + +/* just some made up number to check on later */ +static apr_status_t exit_ret_val = 123; + +static void init_func(void) +{ + value++; +} + +static void * APR_THREAD_FUNC thread_func1(apr_thread_t *thd, void *data) +{ + int i; + + apr_thread_once(control, init_func); + + for (i = 0; i < 10000; i++) { + apr_thread_mutex_lock(thread_lock); + x++; + apr_thread_mutex_unlock(thread_lock); + } + apr_thread_exit(thd, exit_ret_val); + return NULL; +} + +static void thread_init(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_thread_once_init(&control, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + + rv = apr_thread_mutex_create(&thread_lock, APR_THREAD_MUTEX_DEFAULT, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void create_threads(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_thread_create(&t1, NULL, thread_func1, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_thread_create(&t2, NULL, thread_func1, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_thread_create(&t3, NULL, thread_func1, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); + rv = apr_thread_create(&t4, NULL, thread_func1, NULL, p); + ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); +} + +static void join_threads(abts_case *tc, void *data) +{ + apr_status_t s; + + apr_thread_join(&s, t1); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + apr_thread_join(&s, t2); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + apr_thread_join(&s, t3); + ABTS_INT_EQUAL(tc, exit_ret_val, s); + apr_thread_join(&s, t4); + ABTS_INT_EQUAL(tc, exit_ret_val, s); +} + +static void check_locks(abts_case *tc, void *data) +{ + ABTS_INT_EQUAL(tc, 40000, x); +} + +static void check_thread_once(abts_case *tc, void *data) +{ + ABTS_INT_EQUAL(tc, 1, value); +} + +#else + +static void threads_not_impl(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "Threads not implemented on this platform"); +} + +#endif + +abts_suite *testthread(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if !APR_HAS_THREADS + abts_run_test(suite, threads_not_impl, NULL); +#else + abts_run_test(suite, thread_init, NULL); + abts_run_test(suite, create_threads, NULL); + abts_run_test(suite, join_threads, NULL); + abts_run_test(suite, check_locks, NULL); + abts_run_test(suite, check_thread_once, NULL); +#endif + + return suite; +} + diff --git a/srclib/apr/test/testtime.c b/srclib/apr/test/testtime.c new file mode 100644 index 0000000000..4ba09e2dca --- /dev/null +++ b/srclib/apr/test/testtime.c @@ -0,0 +1,307 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_time.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "testutil.h" +#include "apr_strings.h" +#include + +#define STR_SIZE 45 + +/* The time value is used throughout the tests, so just make this a global. + * Also, we need a single value that we can test for the positive tests, so + * I chose the number below, it corresponds to: + * 2002-08-14 12:05:36.186711 -25200 [257 Sat]. + * Which happens to be when I wrote the new tests. + */ +static apr_time_t now = APR_INT64_C(1032030336186711); + +static char* print_time (apr_pool_t *pool, const apr_time_exp_t *xt) +{ + return apr_psprintf (pool, + "%04d-%02d-%02d %02d:%02d:%02d.%06d %+05d [%d %s]%s", + xt->tm_year + 1900, + xt->tm_mon, + xt->tm_mday, + xt->tm_hour, + xt->tm_min, + xt->tm_sec, + xt->tm_usec, + xt->tm_gmtoff, + xt->tm_yday + 1, + apr_day_snames[xt->tm_wday], + (xt->tm_isdst ? " DST" : "")); +} + + +static void test_now(abts_case *tc, void *data) +{ + apr_time_t timediff; + apr_time_t current; + time_t os_now; + + current = apr_time_now(); + time(&os_now); + + timediff = os_now - (current / APR_USEC_PER_SEC); + /* Even though these are called so close together, there is the chance + * that the time will be slightly off, so accept anything between -1 and + * 1 second. + */ + ABTS_ASSERT(tc, "apr_time and OS time do not agree", + (timediff > -2) && (timediff < 2)); +} + +static void test_gmtstr(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + + rv = apr_time_exp_gmt(&xt, now); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_gmt"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_STR_EQUAL(tc, "2002-08-14 19:05:36.186711 +0000 [257 Sat]", + print_time(p, &xt)); +} + +static void test_exp_lt(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + struct tm *libc_exp; + time_t now_secs = apr_time_sec(now); + + rv = apr_time_exp_lt(&xt, now); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_lt"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + + libc_exp = localtime(&now_secs); + +#define CHK_FIELD(f) \ + ABTS_INT_EQUAL(tc, libc_exp->f, xt.f) + + CHK_FIELD(tm_sec); + CHK_FIELD(tm_min); + CHK_FIELD(tm_hour); + CHK_FIELD(tm_mday); + CHK_FIELD(tm_mon); + CHK_FIELD(tm_year); + CHK_FIELD(tm_wday); + CHK_FIELD(tm_yday); + CHK_FIELD(tm_isdst); +#undef CHK_FIELD +} + +static void test_exp_get_gmt(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + apr_time_t imp; + apr_int64_t hr_off_64; + + rv = apr_time_exp_gmt(&xt, now); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rv = apr_time_exp_get(&imp, &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_get"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC; + ABTS_TRUE(tc, now + hr_off_64 == imp); +} + +static void test_exp_get_lt(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + apr_time_t imp; + apr_int64_t hr_off_64; + + rv = apr_time_exp_lt(&xt, now); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rv = apr_time_exp_get(&imp, &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_get"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + hr_off_64 = (apr_int64_t) xt.tm_gmtoff * APR_USEC_PER_SEC; + ABTS_TRUE(tc, now + hr_off_64 == imp); +} + +static void test_imp_gmt(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + apr_time_t imp; + + rv = apr_time_exp_gmt(&xt, now); + ABTS_TRUE(tc, rv == APR_SUCCESS); + rv = apr_time_exp_gmt_get(&imp, &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_gmt_get"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_TRUE(tc, now == imp); +} + +static void test_rfcstr(abts_case *tc, void *data) +{ + apr_status_t rv; + char str[STR_SIZE]; + + rv = apr_rfc822_date(str, now); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_rfc822_date"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_STR_EQUAL(tc, "Sat, 14 Sep 2002 19:05:36 GMT", str); +} + +static void test_ctime(abts_case *tc, void *data) +{ + apr_status_t rv; + char apr_str[STR_SIZE]; + char libc_str[STR_SIZE]; + time_t now_sec = apr_time_sec(now); + + rv = apr_ctime(apr_str, now); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_ctime"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + strcpy(libc_str, ctime(&now_sec)); + *strchr(libc_str, '\n') = '\0'; + + ABTS_STR_EQUAL(tc, libc_str, apr_str); +} + +static void test_strftime(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + char *str = NULL; + apr_size_t sz; + + rv = apr_time_exp_gmt(&xt, now); + str = apr_palloc(p, STR_SIZE + 1); + rv = apr_strftime(str, &sz, STR_SIZE, "%R %A %d %B %Y", &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_strftime"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_STR_EQUAL(tc, "19:05 Saturday 14 September 2002", str); +} + +static void test_strftimesmall(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + char str[STR_SIZE]; + apr_size_t sz; + + rv = apr_time_exp_gmt(&xt, now); + rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_strftime"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_STR_EQUAL(tc, "19:05:36", str); +} + +static void test_exp_tz(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */ + + rv = apr_time_exp_tz(&xt, now, hr_off); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_time_exp_tz"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); + ABTS_TRUE(tc, (xt.tm_usec == 186711) && + (xt.tm_sec == 36) && + (xt.tm_min == 5) && + (xt.tm_hour == 14) && + (xt.tm_mday == 14) && + (xt.tm_mon == 8) && + (xt.tm_year == 102) && + (xt.tm_wday == 6) && + (xt.tm_yday == 256)); +} + +static void test_strftimeoffset(abts_case *tc, void *data) +{ + apr_status_t rv; + apr_time_exp_t xt; + char str[STR_SIZE]; + apr_size_t sz; + apr_int32_t hr_off = -5 * 3600; /* 5 hours in seconds */ + + apr_time_exp_tz(&xt, now, hr_off); + rv = apr_strftime(str, &sz, STR_SIZE, "%T", &xt); + if (rv == APR_ENOTIMPL) { + ABTS_NOT_IMPL(tc, "apr_strftime"); + } + ABTS_TRUE(tc, rv == APR_SUCCESS); +} + +/* 0.9.4 and earlier rejected valid dates in 2038 */ +static void test_2038(abts_case *tc, void *data) +{ + apr_time_exp_t xt; + apr_time_t t; + + /* 2038-01-19T03:14:07.000000Z */ + xt.tm_year = 138; + xt.tm_mon = 0; + xt.tm_mday = 19; + xt.tm_hour = 3; + xt.tm_min = 14; + xt.tm_sec = 7; + + APR_ASSERT_SUCCESS(tc, "explode January 19th, 2038", + apr_time_exp_get(&t, &xt)); +} + +abts_suite *testtime(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_now, NULL); + abts_run_test(suite, test_gmtstr, NULL); + abts_run_test(suite, test_exp_lt, NULL); + abts_run_test(suite, test_exp_get_gmt, NULL); + abts_run_test(suite, test_exp_get_lt, NULL); + abts_run_test(suite, test_imp_gmt, NULL); + abts_run_test(suite, test_rfcstr, NULL); + abts_run_test(suite, test_ctime, NULL); + abts_run_test(suite, test_strftime, NULL); + abts_run_test(suite, test_strftimesmall, NULL); + abts_run_test(suite, test_exp_tz, NULL); + abts_run_test(suite, test_strftimeoffset, NULL); + abts_run_test(suite, test_2038, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testud.c b/srclib/apr/test/testud.c new file mode 100644 index 0000000000..ef9a61b32d --- /dev/null +++ b/srclib/apr/test/testud.c @@ -0,0 +1,91 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "apr_file_io.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_strings.h" +#include "testutil.h" + +static apr_pool_t *pool; +static char *testdata; +static int cleanup_called = 0; + +static apr_status_t string_cleanup(void *data) +{ + cleanup_called = 1; + return APR_SUCCESS; +} + +static void set_userdata(abts_case *tc, void *data) +{ + apr_status_t rv; + + rv = apr_pool_userdata_set(testdata, "TEST", string_cleanup, pool); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); +} + +static void get_userdata(abts_case *tc, void *data) +{ + apr_status_t rv; + void *retdata; + + rv = apr_pool_userdata_get(&retdata, "TEST", pool); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); + ABTS_STR_EQUAL(tc, retdata, testdata); +} + +static void get_nonexistkey(abts_case *tc, void *data) +{ + apr_status_t rv; + void *retdata; + + rv = apr_pool_userdata_get(&retdata, "DOESNTEXIST", pool); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); + ABTS_PTR_EQUAL(tc, retdata, NULL); +} + +static void post_pool_clear(abts_case *tc, void *data) +{ + apr_status_t rv; + void *retdata; + + rv = apr_pool_userdata_get(&retdata, "DOESNTEXIST", pool); + ABTS_INT_EQUAL(tc, rv, APR_SUCCESS); + ABTS_PTR_EQUAL(tc, retdata, NULL); +} + +abts_suite *testud(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + apr_pool_create(&pool, p); + testdata = apr_pstrdup(pool, "This is a test\n"); + + abts_run_test(suite, set_userdata, NULL); + abts_run_test(suite, get_userdata, NULL); + abts_run_test(suite, get_nonexistkey, NULL); + + apr_pool_clear(pool); + + abts_run_test(suite, post_pool_clear, NULL); + + return suite; +} + diff --git a/srclib/apr/test/testuser.c b/srclib/apr/test/testuser.c new file mode 100644 index 0000000000..a2ccb887ee --- /dev/null +++ b/srclib/apr/test/testuser.c @@ -0,0 +1,116 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testutil.h" +#include "apr_errno.h" +#include "apr_general.h" +#include "apr_user.h" + +#if APR_HAS_USER +static void uid_current(abts_case *tc, void *data) +{ + apr_uid_t uid; + apr_gid_t gid; + + APR_ASSERT_SUCCESS(tc, "apr_uid_current failed", + apr_uid_current(&uid, &gid, p)); +} + +static void username(abts_case *tc, void *data) +{ + apr_uid_t uid; + apr_gid_t gid; + apr_uid_t retreived_uid; + apr_gid_t retreived_gid; + char *uname = NULL; + + APR_ASSERT_SUCCESS(tc, "apr_uid_current failed", + apr_uid_current(&uid, &gid, p)); + + APR_ASSERT_SUCCESS(tc, "apr_uid_name_get failed", + apr_uid_name_get(&uname, uid, p)); + ABTS_PTR_NOTNULL(tc, uname); + + APR_ASSERT_SUCCESS(tc, "apr_uid_get failed", + apr_uid_get(&retreived_uid, &retreived_gid, uname, p)); + + APR_ASSERT_SUCCESS(tc, "apr_uid_compare failed", + apr_uid_compare(uid, retreived_uid)); +#ifdef WIN32 + /* ### this fudge was added for Win32 but makes the test return NotImpl + * on Unix if run as root, when !gid is also true. */ + if (!gid || !retreived_gid) { + /* The function had no way to recover the gid (this would have been + * an ENOTIMPL if apr_uid_ functions didn't try to double-up and + * also return apr_gid_t values, which was bogus. + */ + if (!gid) { + ABTS_NOT_IMPL(tc, "Groups from apr_uid_current"); + } + else { + ABTS_NOT_IMPL(tc, "Groups from apr_uid_get"); + } + } + else { +#endif + APR_ASSERT_SUCCESS(tc, "apr_gid_compare failed", + apr_gid_compare(gid, retreived_gid)); +#ifdef WIN32 + } +#endif +} + +static void groupname(abts_case *tc, void *data) +{ + apr_uid_t uid; + apr_gid_t gid; + apr_gid_t retreived_gid; + char *gname = NULL; + + APR_ASSERT_SUCCESS(tc, "apr_uid_current failed", + apr_uid_current(&uid, &gid, p)); + + APR_ASSERT_SUCCESS(tc, "apr_gid_name_get failed", + apr_gid_name_get(&gname, gid, p)); + ABTS_PTR_NOTNULL(tc, gname); + + APR_ASSERT_SUCCESS(tc, "apr_gid_get failed", + apr_gid_get(&retreived_gid, gname, p)); + + APR_ASSERT_SUCCESS(tc, "apr_gid_compare failed", + apr_gid_compare(gid, retreived_gid)); +} +#else +static void users_not_impl(abts_case *tc, void *data) +{ + ABTS_NOT_IMPL(tc, "Users not implemented on this platform"); +} +#endif + +abts_suite *testuser(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + +#if !APR_HAS_USER + abts_run_test(suite, users_not_impl, NULL); +#else + abts_run_test(suite, uid_current, NULL); + abts_run_test(suite, username, NULL); + abts_run_test(suite, groupname, NULL); +#endif + + return suite; +} diff --git a/srclib/apr/test/testutil.c b/srclib/apr/test/testutil.c new file mode 100644 index 0000000000..44c0b6b583 --- /dev/null +++ b/srclib/apr/test/testutil.c @@ -0,0 +1,44 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include "abts.h" +#include "testutil.h" +#include "apr_pools.h" + +apr_pool_t *p; + +void apr_assert_success(abts_case* tc, const char* context, apr_status_t rv, + int lineno) +{ + if (rv == APR_ENOTIMPL) { + abts_not_impl(tc, context, lineno); + } else if (rv != APR_SUCCESS) { + char buf[STRING_MAX], ebuf[128]; + sprintf(buf, "%s (%d): %s\n", context, rv, + apr_strerror(rv, ebuf, sizeof ebuf)); + abts_fail(tc, buf, lineno); + } +} + +void initialize(void) { + apr_initialize(); + atexit(apr_terminate); + + apr_pool_create(&p, NULL); +} diff --git a/srclib/apr/test/testutil.h b/srclib/apr/test/testutil.h new file mode 100644 index 0000000000..76dd8d912e --- /dev/null +++ b/srclib/apr/test/testutil.h @@ -0,0 +1,92 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_pools.h" +#include "abts.h" + +#ifndef APR_TEST_UTIL +#define APR_TEST_UTIL + +/* XXX FIXME */ +#ifdef WIN32 +#define EXTENSION ".exe" +#elif NETWARE +#define EXTENSION ".nlm" +#else +#define EXTENSION +#endif + +#define STRING_MAX 8096 + +/* Some simple functions to make the test apps easier to write and + * a bit more consistent... + */ + +extern apr_pool_t *p; + +/* Assert that RV is an APR_SUCCESS value; else fail giving strerror + * for RV and CONTEXT message. */ +void apr_assert_success(abts_case* tc, const char *context, + apr_status_t rv, int lineno); +#define APR_ASSERT_SUCCESS(tc, ctxt, rv) \ + apr_assert_success(tc, ctxt, rv, __LINE__) + +void initialize(void); + +abts_suite *testatomic(abts_suite *suite); +abts_suite *testdir(abts_suite *suite); +abts_suite *testdso(abts_suite *suite); +abts_suite *testdup(abts_suite *suite); +abts_suite *testenv(abts_suite *suite); +abts_suite *testfile(abts_suite *suite); +abts_suite *testfilecopy(abts_suite *suite); +abts_suite *testfileinfo(abts_suite *suite); +abts_suite *testflock(abts_suite *suite); +abts_suite *testfmt(abts_suite *suite); +abts_suite *testfnmatch(abts_suite *suite); +abts_suite *testgetopt(abts_suite *suite); +abts_suite *testglobalmutex(abts_suite *suite); +abts_suite *testhash(abts_suite *suite); +abts_suite *testipsub(abts_suite *suite); +abts_suite *testlock(abts_suite *suite); +abts_suite *testlfs(abts_suite *suite); +abts_suite *testmmap(abts_suite *suite); +abts_suite *testnames(abts_suite *suite); +abts_suite *testoc(abts_suite *suite); +abts_suite *testpath(abts_suite *suite); +abts_suite *testpipe(abts_suite *suite); +abts_suite *testpoll(abts_suite *suite); +abts_suite *testpool(abts_suite *suite); +abts_suite *testproc(abts_suite *suite); +abts_suite *testprocmutex(abts_suite *suite); +abts_suite *testrand(abts_suite *suite); +abts_suite *testrand2(abts_suite *suite); +abts_suite *testsleep(abts_suite *suite); +abts_suite *testshm(abts_suite *suite); +abts_suite *testsock(abts_suite *suite); +abts_suite *testsockets(abts_suite *suite); +abts_suite *testsockopt(abts_suite *suite); +abts_suite *teststr(abts_suite *suite); +abts_suite *teststrnatcmp(abts_suite *suite); +abts_suite *testtable(abts_suite *suite); +abts_suite *testtemp(abts_suite *suite); +abts_suite *testthread(abts_suite *suite); +abts_suite *testtime(abts_suite *suite); +abts_suite *testud(abts_suite *suite); +abts_suite *testuser(abts_suite *suite); +abts_suite *testvsn(abts_suite *suite); + +#endif /* APR_TEST_INCLUDES */ diff --git a/srclib/apr/test/testvsn.c b/srclib/apr/test/testvsn.c new file mode 100644 index 0000000000..1840b7ac5c --- /dev/null +++ b/srclib/apr/test/testvsn.c @@ -0,0 +1,49 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "testutil.h" +#include "apr_version.h" +#include "apr_general.h" + + +static void test_strings(abts_case *tc, void *data) +{ + ABTS_STR_EQUAL(tc, APR_VERSION_STRING, apr_version_string()); +} + +static void test_ints(abts_case *tc, void *data) +{ + apr_version_t vsn; + + apr_version(&vsn); + + ABTS_INT_EQUAL(tc, APR_MAJOR_VERSION, vsn.major); + ABTS_INT_EQUAL(tc, APR_MINOR_VERSION, vsn.minor); + ABTS_INT_EQUAL(tc, APR_PATCH_VERSION, vsn.patch); +} + +abts_suite *testvsn(abts_suite *suite) +{ + suite = ADD_SUITE(suite) + + abts_run_test(suite, test_strings, NULL); + abts_run_test(suite, test_ints, NULL); + + return suite; +} + diff --git a/srclib/apr/test/tryread.c b/srclib/apr/test/tryread.c new file mode 100644 index 0000000000..26274ca5e7 --- /dev/null +++ b/srclib/apr/test/tryread.c @@ -0,0 +1,49 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "testflock.h" +#include "apr_pools.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr.h" + +#if APR_HAVE_STDLIB_H +#include +#endif + +int main(int argc, const char * const *argv) +{ + apr_file_t *file; + apr_status_t status; + apr_pool_t *p; + + apr_initialize(); + apr_pool_create(&p, NULL); + + if (apr_file_open(&file, TESTFILE, APR_WRITE, APR_OS_DEFAULT, p) + != APR_SUCCESS) { + + exit(UNEXPECTED_ERROR); + } + status = apr_file_lock(file, APR_FLOCK_EXCLUSIVE | APR_FLOCK_NONBLOCK); + if (status == APR_SUCCESS) { + exit(SUCCESSFUL_READ); + } + if (APR_STATUS_IS_EAGAIN(status)) { + exit(FAILED_READ); + } + exit(UNEXPECTED_ERROR); +} diff --git a/srclib/apr/threadproc/beos/apr_proc_stub.c b/srclib/apr/threadproc/beos/apr_proc_stub.c new file mode 100644 index 0000000000..0c069f7ec3 --- /dev/null +++ b/srclib/apr/threadproc/beos/apr_proc_stub.c @@ -0,0 +1,76 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +struct pipefd { + int in; + int out; + int err; +}; + +int main(int argc, char *argv[]) { +/* we expect the following... + * + * argv[0] = this stub + * argv[1] = directory to run in... + * argv[2] = progname to execute + * rest of arguments to be passed to program + */ + char *progname = argv[2]; + char *directory = argv[1]; + struct pipefd *pfd; + thread_id sender; + void *buffer; + char ** newargs; + int i = 0; + + newargs = (char**)malloc(sizeof(char*) * (argc - 1)); + + buffer = (void*)malloc(sizeof(struct pipefd)); + /* this will block until we get the data */ + receive_data(&sender, buffer, sizeof(struct pipefd)); + pfd = (struct pipefd*)buffer; + + if (pfd->in > STDERR_FILENO) { + if (dup2(pfd->in, STDIN_FILENO) != STDIN_FILENO) return (-1); + close (pfd->in); + } + if (pfd->out > STDERR_FILENO) { + if (dup2(pfd->out, STDOUT_FILENO) != STDOUT_FILENO) return (-1); + close (pfd->out); + } + if (pfd->err > STDERR_FILENO) { + if (dup2(pfd->err, STDERR_FILENO) != STDERR_FILENO) return (-1); + close (pfd->err); + } + + for (i=3;i<=argc;i++){ + newargs[i-3] = argv[i]; + } + + /* tell the caller we're OK to start */ + send_data(sender,1,NULL,0); + + if (directory != NULL) + chdir(directory); + execve (progname, newargs, environ); + + return (-1); +} diff --git a/srclib/apr/threadproc/beos/proc.c b/srclib/apr/threadproc/beos/proc.c new file mode 100644 index 0000000000..1bde8e3c98 --- /dev/null +++ b/srclib/apr/threadproc/beos/proc.c @@ -0,0 +1,419 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_strings.h" + +struct send_pipe { + int in; + int out; + int err; +}; + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_palloc(pool, + sizeof(apr_procattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + (*new)->pool = pool; + (*new)->parent_in = NULL; + (*new)->child_in = NULL; + (*new)->parent_out = NULL; + (*new)->child_out = NULL; + (*new)->parent_err = NULL; + (*new)->child_err = NULL; + (*new)->currdir = NULL; + (*new)->cmdtype = APR_PROGRAM; + (*new)->detached = 0; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in, + apr_int32_t out, apr_int32_t err) +{ + apr_status_t status; + if (in != 0) { + if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (in) { + case APR_FULL_BLOCK: + apr_file_pipe_timeout_set(attr->child_in, -1); + apr_file_pipe_timeout_set(attr->parent_in, -1); + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_in, -1); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_in, -1); + break; + default: + break; + } + } + if (out) { + if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (out) { + case APR_FULL_BLOCK: + apr_file_pipe_timeout_set(attr->child_out, -1); + apr_file_pipe_timeout_set(attr->parent_out, -1); + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_out, -1); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_out, -1); + break; + default: + break; + } + } + if (err) { + if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (err) { + case APR_FULL_BLOCK: + apr_file_pipe_timeout_set(attr->child_err, -1); + apr_file_pipe_timeout_set(attr->parent_err, -1); + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_err, -1); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_err, -1); + break; + default: + break; + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir) +{ + char * cwd; + if (dir[0] != '/') { + cwd = (char*)malloc(sizeof(char) * PATH_MAX); + getcwd(cwd, PATH_MAX); + attr->currdir = (char *)apr_pstrcat(attr->pool, cwd, "/", dir, NULL); + free(cwd); + } else { + attr->currdir = (char *)apr_pstrdup(attr->pool, dir); + } + if (attr->currdir) { + return APR_SUCCESS; + } + return APR_ENOMEM; +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + attr->cmdtype = cmd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) +{ + attr->detached = detach; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) +{ + int pid; + + if ((pid = fork()) < 0) { + return errno; + } + else if (pid == 0) { + /* This is really ugly... + * The semantics of BeOS's fork() are that areas (used for shared + * memory) get COW'd :-( The only way we can make shared memory + * work across fork() is therefore to find any areas that have + * been created and then clone them into our address space. + * Thankfully only COW'd areas have the lock variable set at + * anything but 0, so we can use that to find the areas we need to + * copy. Of course what makes it even worse is that the loop through + * the area's will go into an infinite loop, eating memory and then + * eventually segfault unless we know when we reach then end of the + * "original" areas and stop. Why? Well, we delete the area and then + * add another to the end of the list... + */ + area_info ai; + int32 cookie = 0; + area_id highest = 0; + + while (get_next_area_info(0, &cookie, &ai) == B_OK) + if (ai.area > highest) + highest = ai.area; + cookie = 0; + while (get_next_area_info(0, &cookie, &ai) == B_OK) { + if (ai.area > highest) + break; + if (ai.lock > 0) { + area_id original = find_area(ai.name); + delete_area(ai.area); + clone_area(ai.name, &ai.address, B_CLONE_ADDRESS, + ai.protection, original); + } + } + + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INCHILD; + } + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INPARENT; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool) +{ + int i=0,nargs=0; + char **newargs = NULL; + thread_id newproc, sender; + struct send_pipe *sp; + char * dir = NULL; + + sp = (struct send_pipe *)apr_palloc(pool, sizeof(struct send_pipe)); + + new->in = attr->parent_in; + new->err = attr->parent_err; + new->out = attr->parent_out; + sp->in = attr->child_in ? attr->child_in->filedes : -1; + sp->out = attr->child_out ? attr->child_out->filedes : -1; + sp->err = attr->child_err ? attr->child_err->filedes : -1; + + i = 0; + while (args && args[i]) { + i++; + } + + newargs = (char**)malloc(sizeof(char *) * (i + 4)); + newargs[0] = strdup("/boot/home/config/bin/apr_proc_stub"); + if (attr->currdir == NULL) { + /* we require the directory , so use a temp. variable */ + dir = malloc(sizeof(char) * PATH_MAX); + getcwd(dir, PATH_MAX); + newargs[1] = strdup(dir); + free(dir); + } else { + newargs[1] = strdup(attr->currdir); + } + newargs[2] = strdup(progname); + i=0;nargs = 3; + + while (args && args[i]) { + newargs[nargs] = strdup(args[i]); + i++;nargs++; + } + newargs[nargs] = NULL; + + /* ### we should be looking at attr->cmdtype in here... */ + + newproc = load_image(nargs, (const char**)newargs, (const char**)env); + + /* load_image copies the data so now we can free it... */ + while (--nargs >= 0) + free (newargs[nargs]); + free(newargs); + + if (newproc < B_NO_ERROR) { + return errno; + } + + resume_thread(newproc); + + if (attr->child_in) { + apr_file_close(attr->child_in); + } + if (attr->child_out) { + apr_file_close(attr->child_out); + } + if (attr->child_err) { + apr_file_close(attr->child_err); + } + + send_data(newproc, 0, (void*)sp, sizeof(struct send_pipe)); + new->pid = newproc; + + /* before we go charging on we need the new process to get to a + * certain point. When it gets there it'll let us know and we + * can carry on. */ + receive_data(&sender, (void*)NULL,0); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + proc->pid = -1; + return apr_proc_wait(proc, exitcode, exitwhy, waithow); +} + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + pid_t pstatus; + int waitpid_options = WUNTRACED; + int exit_int; + int ignore; + apr_exit_why_e ignorewhy; + + if (exitcode == NULL) { + exitcode = &ignore; + } + if (exitwhy == NULL) { + exitwhy = &ignorewhy; + } + + if (waithow != APR_WAIT) { + waitpid_options |= WNOHANG; + } + + if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) { + proc->pid = pstatus; + if (WIFEXITED(exit_int)) { + *exitwhy = APR_PROC_EXIT; + *exitcode = WEXITSTATUS(exit_int); + } + else if (WIFSIGNALED(exit_int)) { + *exitwhy = APR_PROC_SIGNAL; + *exitcode = WTERMSIG(exit_int); + } + else { + + /* unexpected condition */ + return APR_EGENERAL; + } + return APR_CHILD_DONE; + } + else if (pstatus == 0) { + return APR_CHILD_NOTDONE; + } + + return errno; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in, + apr_file_t *parent_in) +{ + if (attr->child_in == NULL && attr->parent_in == NULL) + apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool); + + if (child_in != NULL) + apr_file_dup(&attr->child_in, child_in, attr->pool); + + if (parent_in != NULL) + apr_file_dup(&attr->parent_in, parent_in, attr->pool); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out, + apr_file_t *parent_out) +{ + if (attr->child_out == NULL && attr->parent_out == NULL) + apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool); + + if (child_out != NULL) + apr_file_dup(&attr->child_out, child_out, attr->pool); + + if (parent_out != NULL) + apr_file_dup(&attr->parent_out, parent_out, attr->pool); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err, + apr_file_t *parent_err) +{ + if (attr->child_err == NULL && attr->parent_err == NULL) + apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool); + + if (child_err != NULL) + apr_file_dup(&attr->child_err, child_err, attr->pool); + + if (parent_err != NULL) + apr_file_dup(&attr->parent_err, parent_err, attr->pool); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, + void *limit) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/threadproc/beos/thread.c b/srclib/apr/threadproc/beos/thread.c new file mode 100644 index 0000000000..68cbdf1d85 --- /dev/null +++ b/srclib/apr/threadproc/beos/thread.c @@ -0,0 +1,238 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_portable.h" + +APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool) +{ + (*new) = (apr_threadattr_t *)apr_palloc(pool, + sizeof(apr_threadattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->attr = (int32)B_NORMAL_PRIORITY; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on) +{ + if (on == 1){ + attr->detached = 1; + } else { + attr->detached = 0; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + if (attr->detached == 1){ + return APR_DETACH; + } + return APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + return APR_ENOTIMPL; +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thd = (apr_thread_t*)opaque; + return thd->func(thd, thd->data); +} + +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, + apr_thread_start_t func, void *data, + apr_pool_t *pool) +{ + int32 temp; + apr_status_t stat; + + (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->data = data; + (*new)->func = func; + (*new)->exitval = -1; + + /* First we create the new thread...*/ + if (attr) + temp = attr->attr; + else + temp = B_NORMAL_PRIORITY; + + stat = apr_pool_create(&(*new)->pool, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + (*new)->td = spawn_thread((thread_func)dummy_worker, + "apr thread", + temp, + (*new)); + + /* Now we try to run it...*/ + if (resume_thread((*new)->td) == B_NO_ERROR) { + return APR_SUCCESS; + } + else { + return errno; + } +} + +APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) +{ + return find_thread(NULL); +} + +int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2) +{ + return tid1 == tid2; +} + +APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) +{ + apr_pool_destroy(thd->pool); + thd->exitval = retval; + exit_thread ((status_t)(retval)); + /* This will never be reached... */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd) +{ + status_t rv = 0, ret; + ret = wait_for_thread(thd->td, &rv); + if (ret == B_NO_ERROR) { + *retval = rv; + return APR_SUCCESS; + } + else { + /* if we've missed the thread's death, did we set an exit value prior + * to it's demise? If we did return that. + */ + if (thd->exitval != -1) { + *retval = thd->exitval; + return APR_SUCCESS; + } else + return ret; + } +} + +APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) +{ + if (suspend_thread(thd->td) == B_NO_ERROR){ + return APR_SUCCESS; + } + else { + return errno; + } +} + +void apr_thread_yield() +{ +} + +APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + +APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd) +{ + *thethd = &thd->td; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + (*thd)->td = *thethd; + return APR_SUCCESS; +} + +static apr_status_t thread_once_cleanup(void *vcontrol) +{ + apr_thread_once_t *control = (apr_thread_once_t *)vcontrol; + + if (control->sem) { + release_sem(control->sem); + delete_sem(control->sem); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + int rc; + *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t)); + (*control)->hit = 0; /* we haven't done it yet... */ + rc = ((*control)->sem = create_sem(1, "thread_once")); + if (rc < 0) + return rc; + + apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null); + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + if (!control->hit) { + if (acquire_sem(control->sem) == B_OK) { + control->hit = 1; + func(); + } + } + return APR_SUCCESS; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) diff --git a/srclib/apr/threadproc/beos/threadpriv.c b/srclib/apr/threadproc/beos/threadpriv.c new file mode 100644 index 0000000000..15dcd3a073 --- /dev/null +++ b/srclib/apr/threadproc/beos/threadpriv.c @@ -0,0 +1,180 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" + +static struct beos_key key_table[BEOS_MAX_DATAKEYS]; +static struct beos_private_data *beos_data[BEOS_MAX_DATAKEYS]; +static sem_id lock; + +APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), apr_pool_t *pool) +{ + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + + acquire_sem(lock); + for ((*key)->key=0; (*key)->key < BEOS_MAX_DATAKEYS; (*key)->key++){ + if (key_table[(*key)->key].assigned == 0){ + key_table[(*key)->key].assigned = 1; + key_table[(*key)->key].destructor = dest; + release_sem(lock); + return APR_SUCCESS; + } + + } + release_sem(lock); + return APR_ENOMEM; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, apr_threadkey_t *key) +{ + thread_id tid; + int i, index=0; + tid = find_thread(NULL); + for (i=0;idata){ + /* it's been used */ + if (beos_data[i]->td == tid){ + index = i; + } + } + } + if (index == 0){ + /* no storage for thread so we can't get anything... */ + return APR_ENOMEM; + } + + if ((key->key < BEOS_MAX_DATAKEYS) && (key_table)){ + acquire_sem(key_table[key->key].lock); + if (key_table[key->key].count){ + (*new) = (void*)beos_data[index]->data[key->key]; + } else { + (*new) = NULL; + } + release_sem(key_table[key->key].lock); + } else { + (*new) = NULL; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, apr_threadkey_t *key) +{ + thread_id tid; + int i,index = 0, ret = 0; + + tid = find_thread(NULL); + for (i=0; i < BEOS_MAX_DATAKEYS; i++){ + if (beos_data[i]->data){ + if (beos_data[i]->td == tid){index = i;} + } + } + if (index==0){ + /* not yet been allocated */ + for (i=0; i< BEOS_MAX_DATAKEYS; i++){ + if (! beos_data[i]->data){ + /* we'll take this one... */ + index = i; + beos_data[i]->data = (const void **)malloc(sizeof(void *) * BEOS_MAX_DATAKEYS); + memset((void *)beos_data[i]->data, 0, sizeof(void *) * BEOS_MAX_DATAKEYS); + beos_data[i]->count = (int)malloc(sizeof(int)); + beos_data[i]->td = (thread_id)malloc(sizeof(thread_id)); + beos_data[i]->td = tid; + } + } + } + if (index == 0){ + /* we're out of luck.. */ + return APR_ENOMEM; + } + if ((key->key < BEOS_MAX_DATAKEYS) && (key_table)){ + acquire_sem(key_table[key->key].lock); + if (key_table[key->key].count){ + if (beos_data[index]->data[key->key] == NULL){ + if (priv != NULL){ + beos_data[index]->count++; + key_table[key->key].count++; + } + } else { + if (priv == NULL){ + beos_data[index]->count--; + key_table[key->key].count--; + } + } + beos_data[index]->data[key->key] = priv; + ret = 1; + } else { + ret = 0; + } + release_sem(key_table[key->key].lock); + } + if (ret) + return APR_SUCCESS; + return APR_ENOMEM; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key) +{ + if (key->key < BEOS_MAX_DATAKEYS){ + acquire_sem(key_table[key->key].lock); + if (key_table[key->key].count == 1){ + key_table[key->key].destructor = NULL; + key_table[key->key].count = 0; + } + release_sem(key_table[key->key].lock); + } else { + return APR_ENOMEM; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, apr_threadkey_t *key) +{ + *thekey = key->key; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + (*key)->key = *thekey; + return APR_SUCCESS; +} diff --git a/srclib/apr/threadproc/beos/threadproc_common.c b/srclib/apr/threadproc/beos/threadproc_common.c new file mode 100644 index 0000000000..96c6e8a4ef --- /dev/null +++ b/srclib/apr/threadproc/beos/threadproc_common.c @@ -0,0 +1,21 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* As the signal code is identical, use the unix version to reduce + code duplication */ +#include "../unix/signals.c" +#include "../unix/procsup.c" + diff --git a/srclib/apr/threadproc/netware/proc.c b/srclib/apr/threadproc/netware/proc.c new file mode 100644 index 0000000000..2622ba8955 --- /dev/null +++ b/srclib/apr/threadproc/netware/proc.c @@ -0,0 +1,452 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_portable.h" + +#include + +apr_status_t apr_netware_proc_cleanup(void *theproc) +{ + apr_proc_t *proc = theproc; + int exit_int; + int waitpid_options = WUNTRACED | WNOHANG; + + if (proc->pid > 0) { + waitpid(proc->pid, &exit_int, waitpid_options); + } + +/* NXVmDestroy(proc->pid); */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + (*new)->pool = pool; + (*new)->cmdtype = APR_PROGRAM; + /* Default to a current path since NetWare doesn't handle it very well */ + apr_filepath_get(&((*new)->currdir), APR_FILEPATH_NATIVE, pool); + (*new)->detached = 1; + return APR_SUCCESS; + +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in, + apr_int32_t out, apr_int32_t err) +{ + apr_status_t status; + if (in != 0) { + if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (in) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_in, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_in, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_in, 0); + apr_file_pipe_timeout_set(attr->parent_in, 0); + } + } + if (out) { + if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (out) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_out, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_out, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_out, 0); + apr_file_pipe_timeout_set(attr->parent_out, 0); + } + } + if (err) { + if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err, + attr->pool)) != APR_SUCCESS) { + return status; + } + switch (err) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_err, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_err, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_err, 0); + apr_file_pipe_timeout_set(attr->parent_err, 0); + } + } + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in, + apr_file_t *parent_in) +{ + if (attr->child_in == NULL && attr->parent_in == NULL) + apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool); + + if (child_in != NULL) + apr_file_dup2(attr->child_in, child_in, attr->pool); + + if (parent_in != NULL) + apr_file_dup2(attr->parent_in, parent_in, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out, + apr_file_t *parent_out) +{ + if (attr->child_out == NULL && attr->parent_out == NULL) + apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool); + + if (child_out != NULL) + apr_file_dup2(attr->child_out, child_out, attr->pool); + + if (parent_out != NULL) + apr_file_dup2(attr->parent_out, parent_out, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err, + apr_file_t *parent_err) +{ + if (attr->child_err == NULL && attr->parent_err == NULL) + apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool); + + if (child_err != NULL) + apr_file_dup2(attr->child_err, child_err, attr->pool); + + if (parent_err != NULL) + apr_file_dup2(attr->parent_err, parent_err, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir) +{ + return apr_filepath_merge(&attr->currdir, NULL, dir, + APR_FILEPATH_NATIVE, attr->pool); +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) +{ + attr->detached = detach; + return APR_SUCCESS; +} + +#if APR_HAS_FORK +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) +{ + int pid; + + if ((pid = fork()) < 0) { + return errno; + } + else if (pid == 0) { + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INCHILD; + } + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INPARENT; +} +#endif + +static apr_status_t limit_proc(apr_procattr_t *attr) +{ +#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT +#ifdef RLIMIT_CPU + if (attr->limit_cpu != NULL) { + if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) { + return errno; + } + } +#endif +#ifdef RLIMIT_NPROC + if (attr->limit_nproc != NULL) { + if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) { + return errno; + } + } +#endif +#if defined(RLIMIT_AS) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_DATA) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_VMEM) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) { + return errno; + } + } +#endif +#else + /* + * Maybe make a note in error_log that setrlimit isn't supported?? + */ + +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + attr->addrspace = addrspace; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *newproc, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool) +{ + wiring_t wire; + int addr_space; + + wire.infd = attr->child_in ? attr->child_in->filedes : FD_UNUSED; + wire.outfd = attr->child_out ? attr->child_out->filedes : FD_UNUSED; + wire.errfd = attr->child_err ? attr->child_err->filedes : FD_UNUSED; + + newproc->in = attr->parent_in; + newproc->out = attr->parent_out; + newproc->err = attr->parent_err; + + /* attr->detached and PROC_DETACHED do not mean the same thing. attr->detached means + * start the NLM in a separate address space. PROC_DETACHED means don't wait for the + * NLM to unload by calling wait() or waitpid(), just clean up */ + addr_space = PROC_LOAD_SILENT | (attr->addrspace ? 0 : PROC_CURRENT_SPACE); + addr_space |= (attr->detached ? PROC_DETACHED : 0); + + if (attr->currdir) { + char *fullpath = NULL; + apr_status_t rv; + + if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, + APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) { + return rv; + } + progname = fullpath; + } + + if ((newproc->pid = procve(progname, addr_space, (const char**)env, &wire, + NULL, NULL, 0, NULL, (const char **)args)) == -1) { + return errno; + } + + if (attr->child_in) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), + attr->child_in, apr_unix_file_cleanup); + apr_file_close(attr->child_in); + } + if (attr->child_out) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), + attr->child_out, apr_unix_file_cleanup); + apr_file_close(attr->child_out); + } + if (attr->child_err) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), + attr->child_err, apr_unix_file_cleanup); + apr_file_close(attr->child_err); + } + + + apr_pool_cleanup_register(pool, (void *)newproc, apr_netware_proc_cleanup, + apr_pool_cleanup_null); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + proc->pid = -1; + return apr_proc_wait(proc, exitcode, exitwhy, waithow); +} + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + pid_t pstatus; + int waitpid_options = WUNTRACED; + int exit_int; + int ignore; + apr_exit_why_e ignorewhy; + + if (exitcode == NULL) { + exitcode = &ignore; + } + + if (exitwhy == NULL) { + exitwhy = &ignorewhy; + } + + if (waithow != APR_WAIT) { + waitpid_options |= WNOHANG; + } + + /* If the pid is 0 then the process was started detached. There + is no need to wait since there is nothing to wait for on a + detached process. Starting a process as non-detached and + then calling wait or waitpid could cause the thread to hang. + The reason for this is because NetWare does not have a way + to kill or even signal a process to be killed. Starting + all processes as detached avoids the possibility of a + thread hanging. */ + if (proc->pid == 0) { + *exitwhy = APR_PROC_EXIT; + *exitcode = 0; + return APR_CHILD_DONE; + } + + if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) { + proc->pid = pstatus; + + if (WIFEXITED(exit_int)) { + *exitwhy = APR_PROC_EXIT; + *exitcode = WEXITSTATUS(exit_int); + } + else if (WIFSIGNALED(exit_int)) { + *exitwhy = APR_PROC_SIGNAL; + *exitcode = WIFTERMSIG(exit_int); + } + else { + /* unexpected condition */ + return APR_EGENERAL; + } + + return APR_CHILD_DONE; + } + else if (pstatus == 0) { + return APR_CHILD_NOTDONE; + } + + return errno; +} + +APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, + struct rlimit *limit) +{ + switch(what) { + case APR_LIMIT_CPU: +#ifdef RLIMIT_CPU + attr->limit_cpu = limit; + break; +#else + return APR_ENOTIMPL; +#endif + case APR_LIMIT_MEM: +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) + attr->limit_mem = limit; + break; +#else + return APR_ENOTIMPL; +#endif + case APR_LIMIT_NPROC: +#ifdef RLIMIT_NPROC + attr->limit_nproc = limit; + break; +#else + return APR_ENOTIMPL; +#endif + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + /* Always return SUCCESS because NetWare threads don't run as a user */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + /* Always return SUCCESS because NetWare threads don't run within a group */ + return APR_SUCCESS; +} diff --git a/srclib/apr/threadproc/netware/procsup.c b/srclib/apr/threadproc/netware/procsup.c new file mode 100644 index 0000000000..008dcaae0c --- /dev/null +++ b/srclib/apr/threadproc/netware/procsup.c @@ -0,0 +1,102 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" + +apr_status_t apr_proc_detach(int daemonize) +{ +#if 0 + int x; + pid_t pgrp; + + chdir("/"); +#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS) +/* Don't detach for MPE because child processes can't survive the death of + the parent. */ + if ((x = fork()) > 0) + exit(0); + else if (x == -1) { + perror("fork"); + fprintf(stderr, "unable to fork new process\n"); + exit(1); /* we can't do anything here, so just exit. */ + } +/* RAISE_SIGSTOP(DETACH);*/ +#endif +#if APR_HAVE_SETSID + if ((pgrp = setsid()) == -1) { + return errno; + } +#elif defined(NEXT) || defined(NEWSOS) + if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) { + return errno; + } +#elif defined(OS2) || defined(TPF) + /* OS/2 don't support process group IDs */ + pgrp = getpid(); +#elif defined(MPE) + /* MPE uses negative pid for process group */ + pgrp = -getpid(); +#else + if ((pgrp = setpgid(0, 0)) == -1) { + return errno; + } +#endif + + /* close out the standard file descriptors */ + if (freopen("/dev/null", "r", stdin) == NULL) { + return errno; + /* continue anyhow -- note we can't close out descriptor 0 because we + * have nothing to replace it with, and if we didn't have a descriptor + * 0 the next file would be created with that value ... leading to + * havoc. + */ + } + if (freopen("/dev/null", "w", stdout) == NULL) { + return errno; + } + /* We are going to reopen this again in a little while to the error + * log file, but better to do it twice and suffer a small performance + * hit for consistancy than not reopen it here. + */ + if (freopen("/dev/null", "w", stderr) == NULL) { + return errno; + } +#endif + return APR_SUCCESS; +} + +#if 0 +#if (!HAVE_WAITPID) +/* From ikluft@amdahl.com + * this is not ideal but it works for SVR3 variants + * Modified by dwd@bell-labs.com to call wait3 instead of wait because + * apache started to use the WNOHANG option. + */ +int waitpid(pid_t pid, int *statusp, int options) +{ + int tmp_pid; + if (kill(pid, 0) == -1) { + errno = ECHILD; + return -1; + } + while (((tmp_pid = wait3(statusp, options, 0)) != pid) && + (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) + ; + return tmp_pid; +} +#endif +#endif + diff --git a/srclib/apr/threadproc/netware/signals.c b/srclib/apr/threadproc/netware/signals.c new file mode 100644 index 0000000000..c2903251b4 --- /dev/null +++ b/srclib/apr/threadproc/netware/signals.c @@ -0,0 +1,82 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include +#include "apr_private.h" +#include "apr_pools.h" +#include "apr_signal.h" +#include "apr_strings.h" + +#include +#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H +#include +#endif + +APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum) +{ + return APR_ENOTIMPL; +} + + +void apr_signal_init(apr_pool_t *pglobal) +{ +} + +const char *apr_signal_description_get(int signum) +{ + switch (signum) + { + case SIGABRT: + return "Abort"; + case SIGFPE: + return "Arithmetic exception"; + case SIGILL: + return "Illegal instruction"; + case SIGINT: + return "Interrupt"; + case SIGSEGV: + return "Segmentation fault"; + case SIGTERM: + return "Terminated"; + case SIGPOLL: + return "Pollable event occurred"; + default: + return "unknown signal (not supported)"; + } +} + +static void *signal_thread_func(void *signal_handler) +{ + return NULL; +} + +APR_DECLARE(apr_status_t) apr_setup_signal_thread(void) +{ + int rv = 0; + + return rv; +} + +APR_DECLARE(apr_status_t) apr_signal_block(int signum) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_signal_unblock(int signum) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/threadproc/netware/thread.c b/srclib/apr/threadproc/netware/thread.c new file mode 100644 index 0000000000..35ae8c88c7 --- /dev/null +++ b/srclib/apr/threadproc/netware/thread.c @@ -0,0 +1,256 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_portable.h" +#include "apr_strings.h" +#include "apr_arch_threadproc.h" + +static int thread_count = 0; + +apr_status_t apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + (*new) = (apr_threadattr_t *)apr_palloc(pool, + sizeof(apr_threadattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->stack_size = APR_DEFAULT_STACK_SIZE; + (*new)->detach = 0; + (*new)->thread_name = NULL; + return APR_SUCCESS; +} + +apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr,apr_int32_t on) +{ + attr->detach = on; + return APR_SUCCESS; +} + +apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + if (attr->detach == 1) + return APR_DETACH; + return APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + attr->stack_size = stacksize; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + return APR_ENOTIMPL; +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thd = (apr_thread_t *)opaque; + return thd->func(thd, thd->data); +} + +apr_status_t apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + long flags = NX_THR_BIND_CONTEXT; + char threadName[NX_MAX_OBJECT_NAME_LEN+1]; + size_t stack_size = APR_DEFAULT_STACK_SIZE; + + if (attr && attr->thread_name) { + strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN); + } + else { + sprintf(threadName, "APR_thread %04ld", ++thread_count); + } + + /* An original stack size of 0 will allow NXCreateThread() to + * assign a default system stack size. An original stack + * size of less than 0 will assign the APR default stack size. + * anything else will be taken as is. + */ + if (attr && (attr->stack_size >= 0)) { + stack_size = attr->stack_size; + } + + (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->data = data; + (*new)->func = func; + (*new)->thread_name = (char*)apr_pstrdup(pool, threadName); + + stat = apr_pool_create(&(*new)->pool, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + if (attr && attr->detach) { + flags |= NX_THR_DETACHED; + } + + (*new)->ctx = NXContextAlloc( + /* void(*start_routine)(void *arg)*/(void (*)(void *)) dummy_worker, + /* void *arg */ (*new), + /* int priority */ NX_PRIO_MED, + /* NXSize_t stackSize */ stack_size, + /* long flags */ NX_CTX_NORMAL, + /* int *error */ &stat); + + + stat = NXContextSetName( + /* NXContext_t ctx */ (*new)->ctx, + /* const char *name */ threadName); + + stat = NXThreadCreate( + /* NXContext_t context */ (*new)->ctx, + /* long flags */ flags, + /* NXThreadId_t *thread_id */ &(*new)->td); + + if(stat==0) + return APR_SUCCESS; + + return(stat);// if error +} + +apr_os_thread_t apr_os_thread_current() +{ + return NXThreadGetId(); +} + +int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2) +{ + return (tid1 == tid2); +} + +void apr_thread_yield() +{ + NXThreadYield(); +} + +apr_status_t apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + NXThreadExit(NULL); + return APR_SUCCESS; +} + +apr_status_t apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t stat; + NXThreadId_t dthr; + + if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) { + *retval = thd->exitval; + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_thread_detach(apr_thread_t *thd) +{ + return APR_SUCCESS; +} + +apr_status_t apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + if (thread != NULL) { + return apr_pool_userdata_get(data, key, thread->pool); + } + else { + data = NULL; + return APR_ENOTHREAD; + } +} + +apr_status_t apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread) +{ + if (thread != NULL) { + return apr_pool_userdata_set(data, key, cleanup, thread->pool); + } + else { + data = NULL; + return APR_ENOTHREAD; + } +} + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + if (thd == NULL) { + return APR_ENOTHREAD; + } + *thethd = &(thd->td); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + (*thd)->td = *thethd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + (*control) = apr_pcalloc(p, sizeof(**control)); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + if (!atomic_xchg(&control->value, 1)) { + func(); + } + return APR_SUCCESS; +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) + + diff --git a/srclib/apr/threadproc/netware/threadpriv.c b/srclib/apr/threadproc/netware/threadpriv.c new file mode 100644 index 0000000000..2e99e522f7 --- /dev/null +++ b/srclib/apr/threadproc/netware/threadpriv.c @@ -0,0 +1,102 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_portable.h" +#include "apr_arch_threadproc.h" + +apr_status_t apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), apr_pool_t *pool) +{ + apr_status_t stat; + + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + + if ((stat = NXKeyCreate(NULL, dest, &(*key)->key)) == 0) { + return stat; + } + return stat; +} + +apr_status_t apr_threadkey_private_get(void **new, apr_threadkey_t *key) +{ + apr_status_t stat; + + if ((stat = NXKeyGetValue(key->key, new)) == 0) { + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_threadkey_private_set(void *priv, apr_threadkey_t *key) +{ + apr_status_t stat; + if ((stat = NXKeySetValue(key->key, priv)) == 0) { + return APR_SUCCESS; + } + else { + return stat; + } +} + +apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key) +{ + apr_status_t stat; + if ((stat = NXKeyDelete(key->key)) == 0) { + return APR_SUCCESS; + } + return stat; +} + +apr_status_t apr_threadkey_data_get(void **data, const char *key, apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +apr_status_t apr_threadkey_data_set(void *data, + const char *key, apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key) +{ + thekey = &(key->key); + return APR_SUCCESS; +} + +apr_status_t apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + (*key)->key = *thekey; + return APR_SUCCESS; +} + diff --git a/srclib/apr/threadproc/os2/proc.c b/srclib/apr/threadproc/os2/proc.c new file mode 100644 index 0000000000..3ea770d0a9 --- /dev/null +++ b/srclib/apr/threadproc/os2/proc.c @@ -0,0 +1,617 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOS +#define INCL_DOSERRORS + +#include "apr_arch_threadproc.h" +#include "apr_arch_file_io.h" +#include "apr_private.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "apr_strings.h" +#include "apr_signal.h" +#include +#include +#include +#include +#include +#include + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_palloc(pool, + sizeof(apr_procattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + (*new)->pool = pool; + (*new)->parent_in = NULL; + (*new)->child_in = NULL; + (*new)->parent_out = NULL; + (*new)->child_out = NULL; + (*new)->parent_err = NULL; + (*new)->child_err = NULL; + (*new)->currdir = NULL; + (*new)->cmdtype = APR_PROGRAM; + (*new)->detached = FALSE; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in, + apr_int32_t out, apr_int32_t err) +{ + apr_status_t stat; + if (in) { + if ((stat = apr_file_pipe_create(&attr->child_in, &attr->parent_in, + attr->pool)) != APR_SUCCESS) { + return stat; + } + switch (in) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_in, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_in, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_in, 0); + apr_file_pipe_timeout_set(attr->parent_in, 0); + } + } + if (out) { + if ((stat = apr_file_pipe_create(&attr->parent_out, &attr->child_out, + attr->pool)) != APR_SUCCESS) { + return stat; + } + switch (out) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_out, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_out, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_out, 0); + apr_file_pipe_timeout_set(attr->parent_out, 0); + } + } + if (err) { + if ((stat = apr_file_pipe_create(&attr->parent_err, &attr->child_err, + attr->pool)) != APR_SUCCESS) { + return stat; + } + switch (err) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_err, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_err, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_err, 0); + apr_file_pipe_timeout_set(attr->parent_err, 0); + } + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in, + apr_file_t *parent_in) +{ + if (attr->child_in == NULL && attr->parent_in == NULL) + apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool); + + if (child_in != NULL) + apr_file_dup(&attr->child_in, child_in, attr->pool); + + if (parent_in != NULL) + apr_file_dup(&attr->parent_in, parent_in, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out, + apr_file_t *parent_out) +{ + if (attr->child_out == NULL && attr->parent_out == NULL) + apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool); + + if (child_out != NULL) + apr_file_dup(&attr->child_out, child_out, attr->pool); + + if (parent_out != NULL) + apr_file_dup(&attr->parent_out, parent_out, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err, + apr_file_t *parent_err) +{ + if (attr->child_err == NULL && attr->parent_err == NULL) + apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool); + + if (child_err != NULL) + apr_file_dup(&attr->child_err, child_err, attr->pool); + + if (parent_err != NULL) + apr_file_dup(&attr->parent_err, parent_err, attr->pool); + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, const char *dir) +{ + attr->currdir = apr_pstrdup(attr->pool, dir); + if (attr->currdir) { + return APR_SUCCESS; + } + return APR_ENOMEM; +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + attr->cmdtype = cmd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) +{ + attr->detached = detach; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) +{ + int pid; + + if ((pid = fork()) < 0) { + return errno; + } + else if (pid == 0) { + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INCHILD; + } + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + return APR_INPARENT; +} + + + +/* quotes in the string are doubled up. + * Used to escape quotes in args passed to OS/2's cmd.exe + */ +static char *double_quotes(apr_pool_t *pool, const char *str) +{ + int num_quotes = 0; + int len = 0; + char *quote_doubled_str, *dest; + + while (str[len]) { + num_quotes += str[len++] == '\"'; + } + + quote_doubled_str = apr_palloc(pool, len + num_quotes + 1); + dest = quote_doubled_str; + + while (*str) { + if (*str == '\"') + *(dest++) = '\"'; + *(dest++) = *(str++); + } + + *dest = 0; + return quote_doubled_str; +} + + + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + /* won't ever be called on this platform, so don't save the function pointer */ + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *proc, const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, apr_pool_t *pool) +{ + int i, arg, numargs, cmdlen; + apr_status_t status; + const char **newargs; + char savedir[300]; + HFILE save_in, save_out, save_err, dup; + int criticalsection = FALSE; + char *extension, *newprogname, *extra_arg = NULL, *cmdline, *cmdline_pos; + char interpreter[1024]; + char error_object[260]; + apr_file_t *progfile; + int env_len, e; + char *env_block, *env_block_pos; + RESULTCODES rescodes; + + /* Prevent other threads from running while these process-wide resources are modified */ + if (attr->child_in || attr->child_out || attr->child_err || attr->currdir) { + criticalsection = TRUE; + DosEnterCritSec(); + } + + if (attr->child_in) { + save_in = -1; + DosDupHandle(STDIN_FILENO, &save_in); + dup = STDIN_FILENO; + DosDupHandle(attr->child_in->filedes, &dup); + DosSetFHState(attr->parent_in->filedes, OPEN_FLAGS_NOINHERIT); + } + + if (attr->child_out) { + save_out = -1; + DosDupHandle(STDOUT_FILENO, &save_out); + dup = STDOUT_FILENO; + DosDupHandle(attr->child_out->filedes, &dup); + DosSetFHState(attr->parent_out->filedes, OPEN_FLAGS_NOINHERIT); + } + + if (attr->child_err) { + save_err = -1; + DosDupHandle(STDERR_FILENO, &save_err); + dup = STDERR_FILENO; + DosDupHandle(attr->child_err->filedes, &dup); + DosSetFHState(attr->parent_err->filedes, OPEN_FLAGS_NOINHERIT); + } + + apr_signal(SIGCHLD, SIG_DFL); /*not sure if this is needed or not */ + + if (attr->currdir != NULL) { + _getcwd2(savedir, sizeof(savedir)); + + if (_chdir2(attr->currdir) < 0) { + if (criticalsection) + DosExitCritSec(); + return errno; + } + } + + interpreter[0] = 0; + extension = strrchr(progname, '.'); + + if (extension == NULL || strchr(extension, '/') || strchr(extension, '\\')) + extension = ""; + + /* ### how to handle APR_PROGRAM_ENV and APR_PROGRAM_PATH? */ + + if (attr->cmdtype == APR_SHELLCMD || + attr->cmdtype == APR_SHELLCMD_ENV || + strcasecmp(extension, ".cmd") == 0) { + strcpy(interpreter, "#!" SHELL_PATH); + extra_arg = "/C"; + } else if (stricmp(extension, ".exe") != 0) { + status = apr_file_open(&progfile, progname, APR_READ|APR_BUFFERED, 0, pool); + + if (status != APR_SUCCESS && APR_STATUS_IS_ENOENT(status)) { + progname = apr_pstrcat(pool, progname, ".exe", NULL); + } + + if (status == APR_SUCCESS) { + status = apr_file_gets(interpreter, sizeof(interpreter), progfile); + + if (status == APR_SUCCESS) { + if (interpreter[0] == '#' && interpreter[1] == '!') { + /* delete CR/LF & any other whitespace off the end */ + int end = strlen(interpreter) - 1; + + while (end >= 0 && apr_isspace(interpreter[end])) { + interpreter[end] = '\0'; + end--; + } + + if (interpreter[2] != '/' && interpreter[2] != '\\' && interpreter[3] != ':') { + char buffer[300]; + + if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) { + strcpy(interpreter+2, buffer); + } else { + strcat(interpreter, ".exe"); + if (DosSearchPath(SEARCH_ENVIRONMENT, "PATH", interpreter+2, buffer, sizeof(buffer)) == 0) { + strcpy(interpreter+2, buffer); + } + } + } + } else { + interpreter[0] = 0; + } + } + } + apr_file_close(progfile); + } + + i = 0; + + while (args && args[i]) { + i++; + } + + newargs = (const char **)apr_palloc(pool, sizeof (char *) * (i + 4)); + numargs = 0; + + if (interpreter[0]) + newargs[numargs++] = interpreter + 2; + if (extra_arg) + newargs[numargs++] = "/c"; + + newargs[numargs++] = newprogname = apr_pstrdup(pool, progname); + arg = 1; + + while (args && args[arg]) { + newargs[numargs++] = args[arg++]; + } + + newargs[numargs] = NULL; + + for (i=0; newprogname[i]; i++) + if (newprogname[i] == '/') + newprogname[i] = '\\'; + + cmdlen = 0; + + for (i=0; i\" ")) + a = apr_pstrcat(pool, "\"", double_quotes(pool, a), "\"", NULL); + + if (i) + *(cmdline_pos++) = ' '; + + strcpy(cmdline_pos, a); + cmdline_pos += strlen(cmdline_pos); + } + + *(++cmdline_pos) = 0; /* Add required second terminator */ + cmdline_pos = strchr(cmdline, ' '); + + if (cmdline_pos) { + *cmdline_pos = 0; + cmdline_pos++; + } + + /* Create environment block from list of envariables */ + if (env) { + for (env_len=1, e=0; env[e]; e++) + env_len += strlen(env[e]) + 1; + + env_block = apr_palloc(pool, env_len); + env_block_pos = env_block; + + for (e=0; env[e]; e++) { + strcpy(env_block_pos, env[e]); + env_block_pos += strlen(env_block_pos) + 1; + } + + *env_block_pos = 0; /* environment block is terminated by a double null */ + } else + env_block = NULL; + + status = DosExecPgm(error_object, sizeof(error_object), + attr->detached ? EXEC_BACKGROUND : EXEC_ASYNCRESULT, + cmdline, env_block, &rescodes, cmdline); + + proc->pid = rescodes.codeTerminate; + + if (attr->currdir != NULL) { + chdir(savedir); + } + + if (attr->child_in) { + apr_file_close(attr->child_in); + dup = STDIN_FILENO; + DosDupHandle(save_in, &dup); + DosClose(save_in); + } + + if (attr->child_out) { + apr_file_close(attr->child_out); + dup = STDOUT_FILENO; + DosDupHandle(save_out, &dup); + DosClose(save_out); + } + + if (attr->child_err) { + apr_file_close(attr->child_err); + dup = STDERR_FILENO; + DosDupHandle(save_err, &dup); + DosClose(save_err); + } + + if (criticalsection) + DosExitCritSec(); + + proc->in = attr->parent_in; + proc->err = attr->parent_err; + proc->out = attr->parent_out; + return status; +} + + + +static void proces_result_codes(RESULTCODES codes, + int *exitcode, + apr_exit_why_e *exitwhy) +{ + int result = 0; + apr_exit_why_e why = APR_PROC_EXIT; + + switch (codes.codeTerminate) { + case TC_EXIT: /* Normal exit */ + why = APR_PROC_EXIT; + result = codes.codeResult; + break; + + case TC_HARDERROR: /* Hard error halt */ + why = APR_PROC_SIGNAL; + result = SIGSYS; + break; + + case TC_KILLPROCESS: /* Was killed by a DosKillProcess() */ + why = APR_PROC_SIGNAL; + result = SIGKILL; + break; + + case TC_TRAP: /* TRAP in 16 bit code */ + case TC_EXCEPTION: /* Threw an exception (32 bit code) */ + why = APR_PROC_SIGNAL; + + switch (codes.codeResult | XCPT_FATAL_EXCEPTION) { + case XCPT_ACCESS_VIOLATION: + result = SIGSEGV; + break; + + case XCPT_ILLEGAL_INSTRUCTION: + result = SIGILL; + break; + + case XCPT_FLOAT_DIVIDE_BY_ZERO: + case XCPT_INTEGER_DIVIDE_BY_ZERO: + result = SIGFPE; + break; + + default: + result = codes.codeResult; + break; + } + } + + if (exitcode) { + *exitcode = result; + } + + if (exitwhy) { + *exitwhy = why; + } +} + + + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + RESULTCODES codes; + ULONG rc; + PID pid; + + rc = DosWaitChild(DCWA_PROCESSTREE, waithow == APR_WAIT ? DCWW_WAIT : DCWW_NOWAIT, &codes, &pid, 0); + + if (rc == 0) { + proc->pid = pid; + proces_result_codes(codes, exitcode, exitwhy); + return APR_CHILD_DONE; + } else if (rc == ERROR_CHILD_NOT_COMPLETE) { + return APR_CHILD_NOTDONE; + } + + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + RESULTCODES codes; + ULONG rc; + PID pid; + rc = DosWaitChild(DCWA_PROCESS, waithow == APR_WAIT ? DCWW_WAIT : DCWW_NOWAIT, &codes, &pid, proc->pid); + + if (rc == 0) { + proces_result_codes(codes, exitcode, exitwhy); + return APR_CHILD_DONE; + } else if (rc == ERROR_CHILD_NOT_COMPLETE) { + return APR_CHILD_NOTDONE; + } + + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/threadproc/os2/signals.c b/srclib/apr/threadproc/os2/signals.c new file mode 100644 index 0000000000..e1727125ad --- /dev/null +++ b/srclib/apr/threadproc/os2/signals.c @@ -0,0 +1 @@ +#include "../unix/signals.c" diff --git a/srclib/apr/threadproc/os2/thread.c b/srclib/apr/threadproc/os2/thread.c new file mode 100644 index 0000000000..8235bff8a5 --- /dev/null +++ b/srclib/apr/threadproc/os2/thread.c @@ -0,0 +1,261 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOSERRORS +#define INCL_DOS +#include "apr_arch_threadproc.h" +#include "apr_thread_proc.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#include "apr_arch_file_io.h" +#include + +APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, apr_pool_t *pool) +{ + (*new) = (apr_threadattr_t *)apr_palloc(pool, sizeof(apr_threadattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->attr = 0; + (*new)->stacksize = 0; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on) +{ + attr->attr |= APR_THREADATTR_DETACHED; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + return (attr->attr & APR_THREADATTR_DETACHED) ? APR_DETACH : APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + attr->stacksize = stacksize; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + return APR_ENOTIMPL; +} + +static void apr_thread_begin(void *arg) +{ + apr_thread_t *thread = (apr_thread_t *)arg; + thread->exitval = thread->func(thread, thread->data); +} + + + +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, + apr_thread_start_t func, void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + apr_thread_t *thread; + + thread = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + *new = thread; + + if (thread == NULL) { + return APR_ENOMEM; + } + + thread->pool = pool; + thread->attr = attr; + thread->func = func; + thread->data = data; + stat = apr_pool_create(&thread->pool, pool); + + if (stat != APR_SUCCESS) { + return stat; + } + + if (attr == NULL) { + stat = apr_threadattr_create(&thread->attr, thread->pool); + + if (stat != APR_SUCCESS) { + return stat; + } + } + + thread->tid = _beginthread(apr_thread_begin, NULL, + thread->attr->stacksize > 0 ? + thread->attr->stacksize : APR_THREAD_STACKSIZE, + thread); + + if (thread->tid < 0) { + return errno; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_os_thread_t) apr_os_thread_current() +{ + PIB *ppib; + TIB *ptib; + DosGetInfoBlocks(&ptib, &ppib); + return ptib->tib_ptib2->tib2_ultid; +} + + + +APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, apr_status_t retval) +{ + thd->exitval = retval; + _endthread(); + return -1; /* If we get here something's wrong */ +} + + + +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd) +{ + ULONG rc; + TID waittid = thd->tid; + + if (thd->attr->attr & APR_THREADATTR_DETACHED) + return APR_EINVAL; + + rc = DosWaitThread(&waittid, DCWW_WAIT); + + if (rc == ERROR_INVALID_THREADID) + rc = 0; /* Thread had already terminated */ + + *retval = thd->exitval; + return APR_OS2_STATUS(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) +{ + thd->attr->attr |= APR_THREADATTR_DETACHED; + return APR_SUCCESS; +} + + + +void apr_thread_yield() +{ + DosSleep(0); +} + + + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, apr_thread_t *thd) +{ + *thethd = &thd->tid; + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + (*thd)->tid = *thethd; + return APR_SUCCESS; +} + + + +int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2) +{ + return tid1 == tid2; +} + + + +APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + + + +APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) + + + +static apr_status_t thread_once_cleanup(void *vcontrol) +{ + apr_thread_once_t *control = (apr_thread_once_t *)vcontrol; + + if (control->sem) { + DosCloseEventSem(control->sem); + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + ULONG rc; + *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t)); + rc = DosCreateEventSem(NULL, &(*control)->sem, 0, TRUE); + apr_pool_cleanup_register(p, control, thread_once_cleanup, apr_pool_cleanup_null); + return APR_FROM_OS_ERROR(rc); +} + + + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + if (!control->hit) { + ULONG count, rc; + rc = DosResetEventSem(control->sem, &count); + + if (rc == 0 && count) { + control->hit = 1; + func(); + } + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/threadproc/os2/threadpriv.c b/srclib/apr/threadproc/os2/threadpriv.c new file mode 100644 index 0000000000..041ff182f9 --- /dev/null +++ b/srclib/apr/threadproc/os2/threadpriv.c @@ -0,0 +1,88 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_thread_proc.h" +#include "apr_portable.h" +#include "apr_general.h" +#include "apr_errno.h" +#include "apr_lib.h" +#include "apr_arch_file_io.h" + +APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *pool) +{ + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + return APR_OS2_STATUS(DosAllocThreadLocalMemory(1, &((*key)->key))); +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, apr_threadkey_t *key) +{ + (*new) = (void *)*(key->key); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, apr_threadkey_t *key) +{ + *(key->key) = (ULONG)priv; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key) +{ + return APR_OS2_STATUS(DosFreeThreadLocalMemory(key->key)); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, apr_threadkey_t *key) +{ + *thekey = key->key; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + (*key)->key = *thekey; + return APR_SUCCESS; +} diff --git a/srclib/apr/threadproc/unix/proc.c b/srclib/apr/threadproc/unix/proc.c new file mode 100644 index 0000000000..ce32b09bf7 --- /dev/null +++ b/srclib/apr/threadproc/unix/proc.c @@ -0,0 +1,669 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_signal.h" +#include "apr_random.h" + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, + apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + (*new)->pool = pool; + (*new)->cmdtype = APR_PROGRAM; + (*new)->uid = (*new)->gid = -1; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, + apr_int32_t out, + apr_int32_t err) +{ + apr_status_t status; + if (in != 0) { + if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in, + attr->pool)) != APR_SUCCESS) { + return status; + } + + switch (in) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_in, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_in, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_in, 0); + apr_file_pipe_timeout_set(attr->parent_in, 0); + } + } + + if (out) { + if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out, + attr->pool)) != APR_SUCCESS) { + return status; + } + + switch (out) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_out, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_out, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_out, 0); + apr_file_pipe_timeout_set(attr->parent_out, 0); + } + } + + if (err) { + if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err, + attr->pool)) != APR_SUCCESS) { + return status; + } + + switch (err) { + case APR_FULL_BLOCK: + break; + case APR_PARENT_BLOCK: + apr_file_pipe_timeout_set(attr->child_err, 0); + break; + case APR_CHILD_BLOCK: + apr_file_pipe_timeout_set(attr->parent_err, 0); + break; + default: + apr_file_pipe_timeout_set(attr->child_err, 0); + apr_file_pipe_timeout_set(attr->parent_err, 0); + } + } + + return APR_SUCCESS; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, + apr_file_t *child_in, + apr_file_t *parent_in) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_in == NULL && attr->parent_in == NULL) + rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool); + + if (child_in != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->child_in, child_in, attr->pool); + + if (parent_in != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->parent_in, parent_in, attr->pool); + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, + apr_file_t *child_out, + apr_file_t *parent_out) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_out == NULL && attr->parent_out == NULL) + rv = apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool); + + if (child_out != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->child_out, child_out, attr->pool); + + if (parent_out != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->parent_out, parent_out, attr->pool); + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, + apr_file_t *child_err, + apr_file_t *parent_err) +{ + apr_status_t rv = APR_SUCCESS; + + if (attr->child_err == NULL && attr->parent_err == NULL) + rv = apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool); + + if (child_err != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->child_err, child_err, attr->pool); + + if (parent_err != NULL && rv == APR_SUCCESS) + rv = apr_file_dup2(attr->parent_err, parent_err, attr->pool); + + return rv; +} + + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir) +{ + attr->currdir = apr_pstrdup(attr->pool, dir); + if (attr->currdir) { + return APR_SUCCESS; + } + + return APR_ENOMEM; +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + attr->cmdtype = cmd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, + apr_int32_t detach) +{ + attr->detached = detach; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) +{ + int pid; + + if ((pid = fork()) < 0) { + return errno; + } + else if (pid == 0) { + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + + apr_random_after_fork(proc); + + return APR_INCHILD; + } + + proc->pid = pid; + proc->in = NULL; + proc->out = NULL; + proc->err = NULL; + + return APR_INPARENT; +} + +static apr_status_t limit_proc(apr_procattr_t *attr) +{ +#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT +#ifdef RLIMIT_CPU + if (attr->limit_cpu != NULL) { + if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) { + return errno; + } + } +#endif +#ifdef RLIMIT_NPROC + if (attr->limit_nproc != NULL) { + if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) { + return errno; + } + } +#endif +#ifdef RLIMIT_NOFILE + if (attr->limit_nofile != NULL) { + if ((setrlimit(RLIMIT_NOFILE, attr->limit_nofile)) != 0) { + return errno; + } + } +#endif +#if defined(RLIMIT_AS) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_DATA) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) { + return errno; + } + } +#elif defined(RLIMIT_VMEM) + if (attr->limit_mem != NULL) { + if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) { + return errno; + } + } +#endif +#else + /* + * Maybe make a note in error_log that setrlimit isn't supported?? + */ + +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + attr->errfn = errfn; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + attr->errchk = chk; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ + apr_status_t rv; + apr_gid_t gid; + + if ((rv = apr_uid_get(&attr->uid, &gid, username, + attr->pool)) != APR_SUCCESS) { + attr->uid = -1; + return rv; + } + + /* Use default user group if not already set */ + if (attr->gid == -1) { + attr->gid = gid; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + apr_status_t rv; + + if ((rv = apr_gid_get(&attr->gid, groupname, attr->pool)) != APR_SUCCESS) + attr->gid = -1; + return rv; +} + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool) +{ + int i; + + new->in = attr->parent_in; + new->err = attr->parent_err; + new->out = attr->parent_out; + + if (attr->errchk) { + if (attr->currdir) { + if (access(attr->currdir, X_OK) == -1) { + /* chdir() in child wouldn't have worked */ + return errno; + } + } + + if (attr->cmdtype == APR_PROGRAM || + attr->cmdtype == APR_PROGRAM_ENV || + *progname == '/') { + /* for both of these values of cmdtype, caller must pass + * full path, so it is easy to check; + * caller can choose to pass full path for other + * values of cmdtype + */ + if (access(progname, R_OK|X_OK) == -1) { + /* exec*() in child wouldn't have worked */ + return errno; + } + } + else { + /* todo: search PATH for progname then try to access it */ + } + } + + if ((new->pid = fork()) < 0) { + return errno; + } + else if (new->pid == 0) { + int status; + /* child process */ + + /* + * If we do exec cleanup before the dup2() calls to set up pipes + * on 0-2, we accidentally close the pipes used by programs like + * mod_cgid. + * + * If we do exec cleanup after the dup2() calls, cleanup can accidentally + * close our pipes which replaced any files which previously had + * descriptors 0-2. + * + * The solution is to kill the cleanup for the pipes, then do + * exec cleanup, then do the dup2() calls. + */ + + if (attr->child_in) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), + attr->child_in, apr_unix_file_cleanup); + } + + if (attr->child_out) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), + attr->child_out, apr_unix_file_cleanup); + } + + if (attr->child_err) { + apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), + attr->child_err, apr_unix_file_cleanup); + } + + apr_pool_cleanup_for_exec(); + + if (attr->child_in) { + apr_file_close(attr->parent_in); + dup2(attr->child_in->filedes, STDIN_FILENO); + apr_file_close(attr->child_in); + } + + if (attr->child_out) { + apr_file_close(attr->parent_out); + dup2(attr->child_out->filedes, STDOUT_FILENO); + apr_file_close(attr->child_out); + } + + if (attr->child_err) { + apr_file_close(attr->parent_err); + dup2(attr->child_err->filedes, STDERR_FILENO); + apr_file_close(attr->child_err); + } + + apr_signal(SIGCHLD, SIG_DFL); /* not sure if this is needed or not */ + + if (attr->currdir != NULL) { + if (chdir(attr->currdir) == -1) { + if (attr->errfn) { + attr->errfn(pool, errno, "change of working directory failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + } + + /* Only try to switch if we are running as root */ + if (attr->gid != -1 && !geteuid()) { + if ((status = setgid(attr->gid))) { + if (attr->errfn) { + attr->errfn(pool, errno, "setting of group failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + } + + if (attr->uid != -1 && !geteuid()) { + if ((status = setuid(attr->uid))) { + if (attr->errfn) { + attr->errfn(pool, errno, "setting of user failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + } + + if ((status = limit_proc(attr)) != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, errno, "setting of resource limits failed"); + } + exit(-1); /* We have big problems, the child should exit. */ + } + + if (attr->cmdtype == APR_SHELLCMD || + attr->cmdtype == APR_SHELLCMD_ENV) { + int onearg_len = 0; + const char *newargs[4]; + + newargs[0] = SHELL_PATH; + newargs[1] = "-c"; + + i = 0; + while (args[i]) { + onearg_len += strlen(args[i]); + onearg_len++; /* for space delimiter */ + i++; + } + + switch(i) { + case 0: + /* bad parameters; we're doomed */ + break; + case 1: + /* no args, or caller already built a single string from + * progname and args + */ + newargs[2] = args[0]; + break; + default: + { + char *ch, *onearg; + + ch = onearg = apr_palloc(pool, onearg_len); + i = 0; + while (args[i]) { + size_t len = strlen(args[i]); + + memcpy(ch, args[i], len); + ch += len; + *ch = ' '; + ++ch; + ++i; + } + --ch; /* back up to trailing blank */ + *ch = '\0'; + newargs[2] = onearg; + } + } + + newargs[3] = NULL; + + if (attr->detached) { + apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); + } + + if (attr->cmdtype == APR_SHELLCMD) { + execve(SHELL_PATH, (char * const *) newargs, (char * const *)env); + } + else { + execv(SHELL_PATH, (char * const *)newargs); + } + } + else if (attr->cmdtype == APR_PROGRAM) { + if (attr->detached) { + apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); + } + + execve(progname, (char * const *)args, (char * const *)env); + } + else if (attr->cmdtype == APR_PROGRAM_ENV) { + if (attr->detached) { + apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); + } + + execv(progname, (char * const *)args); + } + else { + /* APR_PROGRAM_PATH */ + if (attr->detached) { + apr_proc_detach(APR_PROC_DETACH_DAEMONIZE); + } + + execvp(progname, (char * const *)args); + } + if (attr->errfn) { + char *desc; + + desc = apr_psprintf(pool, "exec of '%s' failed", + progname); + attr->errfn(pool, errno, desc); + } + + exit(-1); /* if we get here, there is a problem, so exit with an + * error code. */ + } + + /* Parent process */ + if (attr->child_in) { + apr_file_close(attr->child_in); + } + + if (attr->child_out) { + apr_file_close(attr->child_out); + } + + if (attr->child_err) { + apr_file_close(attr->child_err); + } + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + proc->pid = -1; + return apr_proc_wait(proc, exitcode, exitwhy, waithow); +} + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + pid_t pstatus; + int waitpid_options = WUNTRACED; + int exit_int; + int ignore; + apr_exit_why_e ignorewhy; + + if (exitcode == NULL) { + exitcode = &ignore; + } + + if (exitwhy == NULL) { + exitwhy = &ignorewhy; + } + + if (waithow != APR_WAIT) { + waitpid_options |= WNOHANG; + } + + do { + pstatus = waitpid(proc->pid, &exit_int, waitpid_options); + } while (pstatus < 0 && errno == EINTR); + + if (pstatus > 0) { + proc->pid = pstatus; + + if (WIFEXITED(exit_int)) { + *exitwhy = APR_PROC_EXIT; + *exitcode = WEXITSTATUS(exit_int); + } + else if (WIFSIGNALED(exit_int)) { + *exitwhy = APR_PROC_SIGNAL; + +#ifdef WCOREDUMP + if (WCOREDUMP(exit_int)) { + *exitwhy |= APR_PROC_SIGNAL_CORE; + } +#endif + + *exitcode = WTERMSIG(exit_int); + } + else { + /* unexpected condition */ + return APR_EGENERAL; + } + + return APR_CHILD_DONE; + } + else if (pstatus == 0) { + return APR_CHILD_NOTDONE; + } + + return errno; +} + +APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, + apr_int32_t what, + struct rlimit *limit) +{ + switch(what) { + case APR_LIMIT_CPU: +#ifdef RLIMIT_CPU + attr->limit_cpu = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_MEM: +#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS) + attr->limit_mem = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_NPROC: +#ifdef RLIMIT_NPROC + attr->limit_nproc = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + case APR_LIMIT_NOFILE: +#ifdef RLIMIT_NOFILE + attr->limit_nofile = limit; + break; +#else + return APR_ENOTIMPL; +#endif + + } + + return APR_SUCCESS; +} diff --git a/srclib/apr/threadproc/unix/procsup.c b/srclib/apr/threadproc/unix/procsup.c new file mode 100644 index 0000000000..5165a8f9e3 --- /dev/null +++ b/srclib/apr/threadproc/unix/procsup.c @@ -0,0 +1,101 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_threadproc.h" + +APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize) +{ + int x; + + chdir("/"); +#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS) + /* Don't detach for MPE because child processes can't survive the death of + * the parent. */ + if (daemonize) { + if ((x = fork()) > 0) { + exit(0); + } + else if (x == -1) { + perror("fork"); + fprintf(stderr, "unable to fork new process\n"); + exit(1); /* we can't do anything here, so just exit. */ + } + /* RAISE_SIGSTOP(DETACH); */ + } +#endif + +#ifdef HAVE_SETSID + /* A setsid() failure is not fatal if we didn't just fork(). + * The calling process may be the process group leader, in + * which case setsid() will fail with EPERM. + */ + if (setsid() == -1 && daemonize) { + return errno; + } +#elif defined(NEXT) || defined(NEWSOS) + if (setpgrp(0, getpid()) == -1) { + return errno; + } +#elif defined(OS2) || defined(TPF) || defined(MPE) + /* do nothing */ +#else + if (setpgid(0, 0) == -1) { + return errno; + } +#endif + + /* close out the standard file descriptors */ + if (freopen("/dev/null", "r", stdin) == NULL) { + return errno; + /* continue anyhow -- note we can't close out descriptor 0 because we + * have nothing to replace it with, and if we didn't have a descriptor + * 0 the next file would be created with that value ... leading to + * havoc. + */ + } + if (freopen("/dev/null", "w", stdout) == NULL) { + return errno; + } + /* We are going to reopen this again in a little while to the error + * log file, but better to do it twice and suffer a small performance + * hit for consistancy than not reopen it here. + */ + if (freopen("/dev/null", "w", stderr) == NULL) { + return errno; + } + return APR_SUCCESS; +} + +#if (!HAVE_WAITPID) +/* From ikluft@amdahl.com + * this is not ideal but it works for SVR3 variants + * Modified by dwd@bell-labs.com to call wait3 instead of wait because + * apache started to use the WNOHANG option. + */ +int waitpid(pid_t pid, int *statusp, int options) +{ + int tmp_pid; + if (kill(pid, 0) == -1) { + errno = ECHILD; + return -1; + } + while (((tmp_pid = wait3(statusp, options, 0)) != pid) && + (tmp_pid != -1) && (tmp_pid != 0) && (pid != -1)) + ; + return tmp_pid; +} +#endif + diff --git a/srclib/apr/threadproc/unix/signals.c b/srclib/apr/threadproc/unix/signals.c new file mode 100644 index 0000000000..e2f0fe0f15 --- /dev/null +++ b/srclib/apr/threadproc/unix/signals.c @@ -0,0 +1,487 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define INCL_DOSEXCEPTIONS /* for OS2 */ +#include "apr_arch_threadproc.h" +#include "apr_private.h" +#include "apr_pools.h" +#include "apr_signal.h" +#include "apr_strings.h" + +#include +#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H +#include +#endif + +#ifdef SIGWAIT_TAKES_ONE_ARG +#define apr_sigwait(a,b) ((*(b)=sigwait((a)))<0?-1:0) +#else +#define apr_sigwait(a,b) sigwait((a),(b)) +#endif + +APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum) +{ +#ifdef OS2 + /* SIGTERM's don't work too well in OS/2 (only affects other EMX + * programs). CGIs may not be, esp. REXX scripts, so use a native + * call instead + */ + if (signum == SIGTERM) { + return APR_OS2_STATUS(DosSendSignalException(proc->pid, + XCPT_SIGNAL_BREAK)); + } +#endif /* OS2 */ + + if (kill(proc->pid, signum) == -1) { + return errno; + } + + return APR_SUCCESS; +} + + +#if APR_HAVE_SIGACTION + +#ifdef DARWIN +static void avoid_zombies(int signo) +{ + int exit_status; + + while (waitpid(-1, &exit_status, WNOHANG) > 0) { + /* do nothing */ + } +} +#endif /* DARWIN */ + +/* + * Replace standard signal() with the more reliable sigaction equivalent + * from W. Richard Stevens' "Advanced Programming in the UNIX Environment" + * (the version that does not automatically restart system calls). + */ +APR_DECLARE(apr_sigfunc_t *) apr_signal(int signo, apr_sigfunc_t * func) +{ + struct sigaction act, oact; + + act.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_INTERRUPT /* SunOS */ + act.sa_flags |= SA_INTERRUPT; +#endif +#if defined(__osf__) && defined(__alpha) + /* XXX jeff thinks this should be enabled whenever SA_NOCLDWAIT is defined */ + + /* this is required on Tru64 to cause child processes to + * disappear gracefully - XPG4 compatible + */ + if ((signo == SIGCHLD) && (func == SIG_IGN)) { + act.sa_flags |= SA_NOCLDWAIT; + } +#endif +#ifdef DARWIN + /* ignoring SIGCHLD or leaving the default disposition doesn't avoid zombies, + * and there is no SA_NOCLDWAIT flag, so catch the signal and reap status in + * the handler to avoid zombies + */ + if ((signo == SIGCHLD) && (func == SIG_IGN)) { + act.sa_handler = avoid_zombies; + } +#endif + if (sigaction(signo, &act, &oact) < 0) + return SIG_ERR; + return oact.sa_handler; +} + +#endif /* HAVE_SIGACTION */ + +/* AC_DECL_SYS_SIGLIST defines either of these symbols depending + * on the version of autoconf used. */ +#if defined(SYS_SIGLIST_DECLARED) || HAVE_DECL_SYS_SIGLIST + +void apr_signal_init(apr_pool_t *pglobal) +{ +} +const char *apr_signal_description_get(int signum) +{ + return sys_siglist[signum]; +} + +#else /* !(SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST) */ + +/* we need to roll our own signal description stuff */ + +#if defined(NSIG) +#define APR_NUMSIG NSIG +#elif defined(_NSIG) +#define APR_NUMSIG _NSIG +#elif defined(__NSIG) +#define APR_NUMSIG __NSIG +#else +#define APR_NUMSIG 33 /* breaks on OS/390 with < 33; 32 is o.k. for most */ +#endif + +static const char *signal_description[APR_NUMSIG]; + +#define store_desc(index, string) \ + do { \ + if (index >= APR_NUMSIG) { \ + assert(index < APR_NUMSIG); \ + } \ + else { \ + signal_description[index] = string; \ + } \ + } while (0) + +void apr_signal_init(apr_pool_t *pglobal) +{ + int sig; + + store_desc(0, "Signal 0"); + +#ifdef SIGHUP + store_desc(SIGHUP, "Hangup"); +#endif +#ifdef SIGINT + store_desc(SIGINT, "Interrupt"); +#endif +#ifdef SIGQUIT + store_desc(SIGQUIT, "Quit"); +#endif +#ifdef SIGILL + store_desc(SIGILL, "Illegal instruction"); +#endif +#ifdef SIGTRAP + store_desc(SIGTRAP, "Trace/BPT trap"); +#endif +#ifdef SIGIOT + store_desc(SIGIOT, "IOT instruction"); +#endif +#ifdef SIGABRT + store_desc(SIGABRT, "Abort"); +#endif +#ifdef SIGEMT + store_desc(SIGEMT, "Emulator trap"); +#endif +#ifdef SIGFPE + store_desc(SIGFPE, "Arithmetic exception"); +#endif +#ifdef SIGKILL + store_desc(SIGKILL, "Killed"); +#endif +#ifdef SIGBUS + store_desc(SIGBUS, "Bus error"); +#endif +#ifdef SIGSEGV + store_desc(SIGSEGV, "Segmentation fault"); +#endif +#ifdef SIGSYS + store_desc(SIGSYS, "Bad system call"); +#endif +#ifdef SIGPIPE + store_desc(SIGPIPE, "Broken pipe"); +#endif +#ifdef SIGALRM + store_desc(SIGALRM, "Alarm clock"); +#endif +#ifdef SIGTERM + store_desc(SIGTERM, "Terminated"); +#endif +#ifdef SIGUSR1 + store_desc(SIGUSR1, "User defined signal 1"); +#endif +#ifdef SIGUSR2 + store_desc(SIGUSR2, "User defined signal 2"); +#endif +#ifdef SIGCLD + store_desc(SIGCLD, "Child status change"); +#endif +#ifdef SIGCHLD + store_desc(SIGCHLD, "Child status change"); +#endif +#ifdef SIGPWR + store_desc(SIGPWR, "Power-fail restart"); +#endif +#ifdef SIGWINCH + store_desc(SIGWINCH, "Window changed"); +#endif +#ifdef SIGURG + store_desc(SIGURG, "urgent socket condition"); +#endif +#ifdef SIGPOLL + store_desc(SIGPOLL, "Pollable event occurred"); +#endif +#ifdef SIGIO + store_desc(SIGIO, "socket I/O possible"); +#endif +#ifdef SIGSTOP + store_desc(SIGSTOP, "Stopped (signal)"); +#endif +#ifdef SIGTSTP + store_desc(SIGTSTP, "Stopped"); +#endif +#ifdef SIGCONT + store_desc(SIGCONT, "Continued"); +#endif +#ifdef SIGTTIN + store_desc(SIGTTIN, "Stopped (tty input)"); +#endif +#ifdef SIGTTOU + store_desc(SIGTTOU, "Stopped (tty output)"); +#endif +#ifdef SIGVTALRM + store_desc(SIGVTALRM, "virtual timer expired"); +#endif +#ifdef SIGPROF + store_desc(SIGPROF, "profiling timer expired"); +#endif +#ifdef SIGXCPU + store_desc(SIGXCPU, "exceeded cpu limit"); +#endif +#ifdef SIGXFSZ + store_desc(SIGXFSZ, "exceeded file size limit"); +#endif + + for (sig = 0; sig < APR_NUMSIG; ++sig) + if (signal_description[sig] == NULL) + signal_description[sig] = apr_psprintf(pglobal, "signal #%d", sig); +} + +const char *apr_signal_description_get(int signum) +{ + return + signum < APR_NUMSIG + ? signal_description[signum] + : "unknown signal (number)"; +} + +#endif /* SYS_SIGLIST_DECLARED || HAVE_DECL_SYS_SIGLIST */ + +#if APR_HAS_THREADS && (HAVE_SIGSUSPEND || APR_HAVE_SIGWAIT) && !defined(OS2) + +static void remove_sync_sigs(sigset_t *sig_mask) +{ +#ifdef SIGABRT + sigdelset(sig_mask, SIGABRT); +#endif +#ifdef SIGBUS + sigdelset(sig_mask, SIGBUS); +#endif +#ifdef SIGEMT + sigdelset(sig_mask, SIGEMT); +#endif +#ifdef SIGFPE + sigdelset(sig_mask, SIGFPE); +#endif +#ifdef SIGILL + sigdelset(sig_mask, SIGILL); +#endif +#ifdef SIGIOT + sigdelset(sig_mask, SIGIOT); +#endif +#ifdef SIGPIPE + sigdelset(sig_mask, SIGPIPE); +#endif +#ifdef SIGSEGV + sigdelset(sig_mask, SIGSEGV); +#endif +#ifdef SIGSYS + sigdelset(sig_mask, SIGSYS); +#endif +#ifdef SIGTRAP + sigdelset(sig_mask, SIGTRAP); +#endif + +/* the rest of the signals removed from the mask in this function + * absolutely must be removed; you cannot block synchronous signals + * (requirement of pthreads API) + * + * SIGUSR2 is being removed from the mask for the convenience of + * Purify users (Solaris, HP-UX, SGI) since Purify uses SIGUSR2 + */ +#ifdef SIGUSR2 + sigdelset(sig_mask, SIGUSR2); +#endif +} + +APR_DECLARE(apr_status_t) apr_signal_thread(int(*signal_handler)(int signum)) +{ + sigset_t sig_mask; +#if APR_HAVE_SIGWAIT + int (*sig_func)(int signum) = (int (*)(int))signal_handler; +#endif + + /* This thread will be the one responsible for handling signals */ + sigfillset(&sig_mask); + + /* On certain platforms, sigwait() returns EINVAL if any of various + * unblockable signals are included in the mask. This was first + * observed on AIX and Tru64. + */ +#ifdef SIGKILL + sigdelset(&sig_mask, SIGKILL); +#endif +#ifdef SIGSTOP + sigdelset(&sig_mask, SIGSTOP); +#endif +#ifdef SIGCONT + sigdelset(&sig_mask, SIGCONT); +#endif +#ifdef SIGWAITING + sigdelset(&sig_mask, SIGWAITING); +#endif + + /* no synchronous signals should be in the mask passed to sigwait() */ + remove_sync_sigs(&sig_mask); + + /* On AIX (4.3.3, at least), sigwait() won't wake up if the high- + * order bit of the second word of flags is turned on. sigdelset() + * returns an error when trying to turn this off, so we'll turn it + * off manually. + * + * Note that the private fields differ between 32-bit and 64-bit + * and even between _ALL_SOURCE and !_ALL_SOURCE. Except that on + * AIX 4.3 32-bit builds and 64-bit builds use the same definition. + * + * Applicable AIX fixes such that this is no longer needed: + * + * APAR IY23096 for AIX 51B, fix included in AIX 51C, and + * APAR IY24162 for 43X. + */ +#if defined(_AIX) +#if defined(__64BIT__) && defined(_AIXVERSION_510) +#ifdef _ALL_SOURCE + sig_mask.ss_set[3] &= 0x7FFFFFFF; +#else /* not _ALL_SOURCE */ + sig_mask.__ss_set[3] &= 0x7FFFFFFF; +#endif +#else /* not 64-bit build, or 64-bit build on 4.3 */ +#ifdef _ALL_SOURCE + sig_mask.hisigs &= 0x7FFFFFFF; +#else /* not _ALL_SOURCE */ + sig_mask.__hisigs &= 0x7FFFFFFF; +#endif +#endif +#endif /* _AIX */ + + while (1) { +#if APR_HAVE_SIGWAIT + int signal_received; + + if (apr_sigwait(&sig_mask, &signal_received) != 0) + { + /* handle sigwait() error here */ + } + + if (sig_func(signal_received) == 1) { + return APR_SUCCESS; + } +#elif HAVE_SIGSUSPEND + sigsuspend(&sig_mask); +#else +#error No apr_sigwait() and no sigsuspend() +#endif + } +} + +APR_DECLARE(apr_status_t) apr_setup_signal_thread(void) +{ + sigset_t sig_mask; + int rv; + + /* All threads should mask out signals to be handled by + * the thread doing sigwait(). + * + * No thread should ever block synchronous signals. + * See the Solaris man page for pthread_sigmask() for + * some information. Solaris chooses to knock out such + * processes when a blocked synchronous signal is + * delivered, skipping any registered signal handler. + * AIX doesn't call a signal handler either. At least + * one level of linux+glibc does call the handler even + * when the synchronous signal is blocked. + */ + sigfillset(&sig_mask); + remove_sync_sigs(&sig_mask); + +#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS + if ((rv = sigprocmask(SIG_SETMASK, &sig_mask, NULL)) != 0) { + rv = errno; + } +#else + if ((rv = pthread_sigmask(SIG_SETMASK, &sig_mask, NULL)) != 0) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + } +#endif + return rv; +} + +#endif /* APR_HAS_THREADS && ... */ + +APR_DECLARE(apr_status_t) apr_signal_block(int signum) +{ +#if APR_HAVE_SIGACTION + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + +#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS + if ((rv = sigprocmask(SIG_BLOCK, &sig_mask, NULL)) != 0) { + rv = errno; + } +#else + if ((rv = pthread_sigmask(SIG_BLOCK, &sig_mask, NULL)) != 0) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + } +#endif + return rv; +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_signal_unblock(int signum) +{ +#if APR_HAVE_SIGACTION + sigset_t sig_mask; + int rv; + + sigemptyset(&sig_mask); + + sigaddset(&sig_mask, signum); + +#if defined(SIGPROCMASK_SETS_THREAD_MASK) || ! APR_HAS_THREADS + if ((rv = sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) { + rv = errno; + } +#else + if ((rv = pthread_sigmask(SIG_UNBLOCK, &sig_mask, NULL)) != 0) { +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + } +#endif + return rv; +#else + return APR_ENOTIMPL; +#endif +} diff --git a/srclib/apr/threadproc/unix/thread.c b/srclib/apr/threadproc/unix/thread.c new file mode 100644 index 0000000000..c32869c60c --- /dev/null +++ b/srclib/apr/threadproc/unix/thread.c @@ -0,0 +1,320 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_portable.h" +#include "apr_arch_threadproc.h" + +#if APR_HAS_THREADS + +#if APR_HAVE_PTHREAD_H + +/* Destroy the threadattr object */ +static apr_status_t threadattr_cleanup(void *data) +{ + apr_threadattr_t *attr = data; + apr_status_t rv; + + rv = pthread_attr_destroy(&attr->attr); +#ifdef PTHREAD_SETS_ERRNO + if (rv) { + rv = errno; + } +#endif + return rv; +} + +APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + apr_status_t stat; + + (*new) = apr_palloc(pool, sizeof(apr_threadattr_t)); + (*new)->pool = pool; + stat = pthread_attr_init(&(*new)->attr); + + if (stat == 0) { + apr_pool_cleanup_register(pool, *new, threadattr_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; + } +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; +} + +#define DETACH_ARG(v) ((v) ? PTHREAD_CREATE_DETACHED : PTHREAD_CREATE_JOINABLE) + +APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on) +{ + apr_status_t stat; +#ifdef PTHREAD_ATTR_SETDETACHSTATE_ARG2_ADDR + int arg = DETACH_ARG(v); + + if ((stat = pthread_attr_setdetachstate(&attr->attr, &arg)) == 0) { +#else + if ((stat = pthread_attr_setdetachstate(&attr->attr, + DETACH_ARG(on))) == 0) { +#endif + return APR_SUCCESS; + } + else { +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; + } +} + +APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + int state; + +#ifdef PTHREAD_ATTR_GETDETACHSTATE_TAKES_ONE_ARG + state = pthread_attr_getdetachstate(&attr->attr); +#else + pthread_attr_getdetachstate(&attr->attr, &state); +#endif + if (state == 1) + return APR_DETACH; + return APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + int stat; + + stat = pthread_attr_setstacksize(&attr->attr, stacksize); + if (stat == 0) { + return APR_SUCCESS; + } +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ +#ifdef HAVE_PTHREAD_ATTR_SETGUARDSIZE + apr_status_t rv; + + rv = pthread_attr_setguardsize(&attr->attr, size); + if (rv == 0) { + return APR_SUCCESS; + } +#ifdef PTHREAD_SETS_ERRNO + rv = errno; +#endif + return rv; +#else + return APR_ENOTIMPL; +#endif +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thread = (apr_thread_t*)opaque; + return thread->func(thread, thread->data); +} + +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, + apr_pool_t *pool) +{ + apr_status_t stat; + pthread_attr_t *temp; + + (*new) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->td = (pthread_t *)apr_pcalloc(pool, sizeof(pthread_t)); + + if ((*new)->td == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->data = data; + (*new)->func = func; + + if (attr) + temp = &attr->attr; + else + temp = NULL; + + stat = apr_pool_create(&(*new)->pool, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + if ((stat = pthread_create((*new)->td, temp, dummy_worker, (*new))) == 0) { + return APR_SUCCESS; + } + else { +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; + } +} + +APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) +{ + return pthread_self(); +} + +APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2) +{ + return pthread_equal(tid1, tid2); +} + +APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + pthread_exit(NULL); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t stat; + apr_status_t *thread_stat; + + if ((stat = pthread_join(*thd->td,(void *)&thread_stat)) == 0) { + *retval = thd->exitval; + return APR_SUCCESS; + } + else { +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; + } +} + +APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) +{ + apr_status_t stat; + +#ifdef PTHREAD_DETACH_ARG1_ADDR + if ((stat = pthread_detach(thd->td)) == 0) { +#else + if ((stat = pthread_detach(*thd->td)) == 0) { +#endif + + return APR_SUCCESS; + } + else { +#ifdef PTHREAD_SETS_ERRNO + stat = errno; +#endif + + return stat; + } +} + +void apr_thread_yield() +{ +} + +APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + +APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + *thethd = thd->td; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_pcalloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + + (*thd)->td = thethd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + static const pthread_once_t once_init = PTHREAD_ONCE_INIT; + + *control = apr_palloc(p, sizeof(**control)); + (*control)->once = once_init; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + return pthread_once(&control->once, func); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) + +#endif /* HAVE_PTHREAD_H */ +#endif /* APR_HAS_THREADS */ + +#if !APR_HAS_THREADS + +/* avoid warning for no prototype */ +APR_DECLARE(apr_status_t) apr_os_thread_get(void); + +APR_DECLARE(apr_status_t) apr_os_thread_get(void) +{ + return APR_ENOTIMPL; +} + +#endif diff --git a/srclib/apr/threadproc/unix/threadpriv.c b/srclib/apr/threadproc/unix/threadpriv.c new file mode 100644 index 0000000000..77088a1b48 --- /dev/null +++ b/srclib/apr/threadproc/unix/threadpriv.c @@ -0,0 +1,129 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr.h" +#include "apr_portable.h" +#include "apr_arch_threadproc.h" + +#if APR_HAS_THREADS + +#if APR_HAVE_PTHREAD_H +APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *pool) +{ + (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t)); + + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + + return pthread_key_create(&(*key)->key, dest); + +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, + apr_threadkey_t *key) +{ +#ifdef PTHREAD_GETSPECIFIC_TAKES_TWO_ARGS + if (pthread_getspecific(key->key,new)) + *new = NULL; +#else + (*new) = pthread_getspecific(key->key); +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, + apr_threadkey_t *key) +{ + apr_status_t stat; + + if ((stat = pthread_setspecific(key->key, priv)) == 0) { + return APR_SUCCESS; + } + else { + return stat; + } +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key) +{ +#ifdef HAVE_PTHREAD_KEY_DELETE + apr_status_t stat; + + if ((stat = pthread_key_delete(key->key)) == 0) { + return APR_SUCCESS; + } + + return stat; +#else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key) +{ + *thekey = key->key; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + + (*key)->key = *thekey; + return APR_SUCCESS; +} +#endif /* APR_HAVE_PTHREAD_H */ +#endif /* APR_HAS_THREADS */ + +#if !APR_HAS_THREADS + +/* avoid warning for no prototype */ +APR_DECLARE(apr_status_t) apr_os_threadkey_get(void); + +APR_DECLARE(apr_status_t) apr_os_threadkey_get(void) +{ + return APR_ENOTIMPL; +} + +#endif diff --git a/srclib/apr/threadproc/win32/proc.c b/srclib/apr/threadproc/win32/proc.c new file mode 100644 index 0000000000..df75b836b1 --- /dev/null +++ b/srclib/apr/threadproc/win32/proc.c @@ -0,0 +1,898 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_threadproc.h" +#include "win32/apr_arch_file_io.h" + +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_lib.h" +#include +#if APR_HAVE_SIGNAL_H +#include +#endif +#include +#if APR_HAVE_PROCESS_H +#include +#endif + +#ifdef _WIN32_WCE +#ifndef DETACHED_PROCESS +#define DETACHED_PROCESS 0 +#endif +#ifndef CREATE_UNICODE_ENVIRONMENT +#define CREATE_UNICODE_ENVIRONMENT 0 +#endif +#ifndef STARTF_USESHOWWINDOW +#define STARTF_USESHOWWINDOW 0 +#endif +#ifndef SW_HIDE +#define SW_HIDE 0 +#endif +#endif +/* + * some of the ideas expressed herein are based off of Microsoft + * Knowledge Base article: Q190351 + * + */ + +APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, + apr_pool_t *pool) +{ + (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t)); + (*new)->pool = pool; + (*new)->cmdtype = APR_PROGRAM; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, + apr_int32_t in, + apr_int32_t out, + apr_int32_t err) +{ + apr_status_t stat = APR_SUCCESS; + + if (in) { + /* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while + * APR_PARENT_BLOCK maps to APR_READ_BLOCK, so we + * must transpose the CHILD/PARENT blocking flags + * only for the stdin pipe. stdout/stderr naturally + * map to the correct mode. + */ + if (in == APR_CHILD_BLOCK) + in = APR_READ_BLOCK; + else if (in == APR_PARENT_BLOCK) + in = APR_WRITE_BLOCK; + stat = apr_create_nt_pipe(&attr->child_in, &attr->parent_in, in, + attr->pool); + if (stat == APR_SUCCESS) + stat = apr_file_inherit_unset(attr->parent_in); + } + if (out && stat == APR_SUCCESS) { + stat = apr_create_nt_pipe(&attr->parent_out, &attr->child_out, out, + attr->pool); + if (stat == APR_SUCCESS) + stat = apr_file_inherit_unset(attr->parent_out); + } + if (err && stat == APR_SUCCESS) { + stat = apr_create_nt_pipe(&attr->parent_err, &attr->child_err, err, + attr->pool); + if (stat == APR_SUCCESS) + stat = apr_file_inherit_unset(attr->parent_err); + } + return stat; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, + apr_file_t *child_in, + apr_file_t *parent_in) +{ + apr_status_t rv = APR_SUCCESS; + + if (child_in) { + if (attr->child_in == NULL) + rv = apr_file_dup(&attr->child_in, child_in, attr->pool); + else + rv = apr_file_dup2(attr->child_in, child_in, attr->pool); + + if (rv == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_in); + } + + if (parent_in && rv == APR_SUCCESS) { + if (attr->parent_in == NULL) + rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool); + else + rv = apr_file_dup2(attr->parent_in, parent_in, attr->pool); + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, + apr_file_t *child_out, + apr_file_t *parent_out) +{ + apr_status_t rv = APR_SUCCESS; + + if (child_out) { + if (attr->child_out == NULL) + rv = apr_file_dup(&attr->child_out, child_out, attr->pool); + else + rv = apr_file_dup2(attr->child_out, child_out, attr->pool); + + if (rv == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_out); + } + + if (parent_out && rv == APR_SUCCESS) { + if (attr->parent_out == NULL) + rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool); + else + rv = apr_file_dup2(attr->parent_out, parent_out, attr->pool); + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, + apr_file_t *child_err, + apr_file_t *parent_err) +{ + apr_status_t rv = APR_SUCCESS; + + if (child_err) { + if (attr->child_err == NULL) + rv = apr_file_dup(&attr->child_err, child_err, attr->pool); + else + rv = apr_file_dup2(attr->child_err, child_err, attr->pool); + + if (rv == APR_SUCCESS) + rv = apr_file_inherit_set(attr->child_err); + } + + if (parent_err && rv == APR_SUCCESS) { + if (attr->parent_err == NULL) + rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool); + else + rv = apr_file_dup2(attr->parent_err, parent_err, attr->pool); + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, + const char *dir) +{ + /* curr dir must be in native format, there are all sorts of bugs in + * the NT library loading code that flunk the '/' parsing test. + */ + return apr_filepath_merge(&attr->currdir, NULL, dir, + APR_FILEPATH_NATIVE, attr->pool); +} + +APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr, + apr_cmdtype_e cmd) +{ + attr->cmdtype = cmd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, + apr_int32_t det) +{ + attr->detached = det; + return APR_SUCCESS; +} + +static apr_status_t attr_cleanup(void *theattr) +{ + apr_procattr_t *attr = (apr_procattr_t *)theattr; + if (attr->user_token) + CloseHandle(attr->user_token); + attr->user_token = NULL; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, + const char *username, + const char *password) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + HANDLE user; + apr_wchar_t *wusername = NULL; + apr_wchar_t *wpassword = NULL; + apr_status_t rv; + apr_size_t len, wlen; + + if (apr_os_level >= APR_WIN_NT_4) + { + if (attr->user_token) { + /* Cannot set that twice */ + if (attr->errfn) { + attr->errfn(attr->pool, 0, + apr_pstrcat(attr->pool, + "function called twice" + " on username: ", username, NULL)); + } + return APR_EINVAL; + } + len = strlen(username) + 1; + wlen = len; + wusername = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t)); + if ((rv = apr_conv_utf8_to_ucs2(username, &len, wusername, &wlen)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(attr->pool, rv, + apr_pstrcat(attr->pool, + "utf8 to ucs2 conversion failed" + " on username: ", username, NULL)); + } + return rv; + } + if (password) { + len = strlen(password) + 1; + wlen = len; + wpassword = apr_palloc(attr->pool, wlen * sizeof(apr_wchar_t)); + if ((rv = apr_conv_utf8_to_ucs2(password, &len, wpassword, &wlen)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(attr->pool, rv, + apr_pstrcat(attr->pool, + "utf8 to ucs2 conversion failed" + " on password: ", password, NULL)); + } + return rv; + } + } + if (!LogonUserW(wusername, + NULL, + wpassword ? wpassword : L"", + LOGON32_LOGON_NETWORK, + LOGON32_PROVIDER_DEFAULT, + &user)) { + /* Logon Failed */ + return apr_get_os_error(); + } + if (wpassword) + memset(wpassword, 0, wlen * sizeof(apr_wchar_t)); + /* Get the primary token for user */ + if (!DuplicateTokenEx(user, + TOKEN_QUERY | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY, + NULL, + SecurityImpersonation, + TokenPrimary, + &(attr->user_token))) { + /* Failed to duplicate the user token */ + rv = apr_get_os_error(); + CloseHandle(user); + return rv; + } + CloseHandle(user); + + attr->sd = apr_pcalloc(attr->pool, SECURITY_DESCRIPTOR_MIN_LENGTH); + InitializeSecurityDescriptor(attr->sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(attr->sd, -1, 0, 0); + attr->sa = apr_palloc(attr->pool, sizeof(SECURITY_ATTRIBUTES)); + attr->sa->nLength = sizeof (SECURITY_ATTRIBUTES); + attr->sa->lpSecurityDescriptor = attr->sd; + attr->sa->bInheritHandle = TRUE; + + /* register the cleanup */ + apr_pool_cleanup_register(attr->pool, (void *)attr, + attr_cleanup, + apr_pool_cleanup_null); + return APR_SUCCESS; + } + else + return APR_ENOTIMPL; +#endif +} + +APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr, + const char *groupname) +{ + /* Always return SUCCESS cause groups are irrelevant */ + return APR_SUCCESS; +} + +static const char* has_space(const char *str) +{ + const char *ch; + for (ch = str; *ch; ++ch) { + if (apr_isspace(*ch)) { + return ch; + } + } + return NULL; +} + +static char *apr_caret_escape_args(apr_pool_t *p, const char *str) +{ + char *cmd; + unsigned char *d; + const unsigned char *s; + + cmd = apr_palloc(p, 2 * strlen(str) + 1); /* Be safe */ + d = (unsigned char *)cmd; + s = (const unsigned char *)str; + for (; *s; ++s) { + + /* + * Newlines to Win32/OS2 CreateProcess() are ill advised. + * Convert them to spaces since they are effectively white + * space to most applications + */ + if (*s == '\r' || *s == '\n') { + *d++ = ' '; + continue; + } + + if (IS_SHCHAR(*s)) { + *d++ = '^'; + } + *d++ = *s; + } + *d = '\0'; + + return cmd; +} + +APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr, + apr_child_errfn_t *errfn) +{ + attr->errfn = errfn; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr, + apr_int32_t chk) +{ + attr->errchk = chk; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr, + apr_int32_t addrspace) +{ + /* won't ever be used on this platform, so don't save the flag */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, + const char *progname, + const char * const *args, + const char * const *env, + apr_procattr_t *attr, + apr_pool_t *pool) +{ + apr_status_t rv; + apr_size_t i; + const char *argv0; + char *cmdline; + char *pEnvBlock; + PROCESS_INFORMATION pi; + DWORD dwCreationFlags = 0; + + new->in = attr->parent_in; + new->out = attr->parent_out; + new->err = attr->parent_err; + + if (attr->detached) { + /* If we are creating ourselves detached, Then we should hide the + * window we are starting in. And we had better redfine our + * handles for STDIN, STDOUT, and STDERR. Do not set the + * detached attribute for Win9x. We have found that Win9x does + * not manage the stdio handles properly when running old 16 + * bit executables if the detached attribute is set. + */ + if (apr_os_level >= APR_WIN_NT) { + /* + * XXX DETACHED_PROCESS won't on Win9x at all; on NT/W2K + * 16 bit executables fail (MS KB: Q150956) + */ + dwCreationFlags |= DETACHED_PROCESS; + } + } + + /* progname must be unquoted, in native format, as there are all sorts + * of bugs in the NT library loader code that fault when parsing '/'. + * XXX progname must be NULL if this is a 16 bit app running in WOW + */ + if (progname[0] == '\"') { + progname = apr_pstrndup(pool, progname + 1, strlen(progname) - 2); + } + + if (attr->cmdtype == APR_PROGRAM || attr->cmdtype == APR_PROGRAM_ENV) { + char *fullpath = NULL; + if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, + APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, rv, + apr_pstrcat(pool, "filepath_merge failed.", + " currdir: ", attr->currdir, + " progname: ", progname, NULL)); + } + return rv; + } + progname = fullpath; + } + else { + /* Do not fail if the path isn't parseable for APR_PROGRAM_PATH + * or APR_SHELLCMD. We only invoke apr_filepath_merge (with no + * left hand side expression) in order to correct the path slash + * delimiters. But the filename doesn't need to be in the CWD, + * nor does it need to be a filename at all (it could be a + * built-in shell command.) + */ + char *fullpath = NULL; + if ((rv = apr_filepath_merge(&fullpath, "", progname, + APR_FILEPATH_NATIVE, pool)) == APR_SUCCESS) { + progname = fullpath; + } + } + + if (has_space(progname)) { + argv0 = apr_pstrcat(pool, "\"", progname, "\"", NULL); + } + else { + argv0 = progname; + } + + /* Handle the args, seperate from argv0 */ + cmdline = ""; + for (i = 1; args && args[i]; ++i) { + if (has_space(args[i])) { + cmdline = apr_pstrcat(pool, cmdline, " \"", args[i], "\"", NULL); + } + else { + cmdline = apr_pstrcat(pool, cmdline, " ", args[i], NULL); + } + } + +#ifndef _WIN32_WCE + if (attr->cmdtype == APR_SHELLCMD || attr->cmdtype == APR_SHELLCMD_ENV) { + char *shellcmd = getenv("COMSPEC"); + if (!shellcmd) { + if (attr->errfn) { + attr->errfn(pool, APR_EINVAL, "COMSPEC envar is not set"); + } + return APR_EINVAL; + } + if (shellcmd[0] == '"') { + progname = apr_pstrndup(pool, shellcmd + 1, strlen(shellcmd) - 2); + } + else { + progname = shellcmd; + if (has_space(shellcmd)) { + shellcmd = apr_pstrcat(pool, "\"", shellcmd, "\"", NULL); + } + } + /* Command.com does not support a quoted command, while cmd.exe demands one. + */ + i = strlen(progname); + if (i >= 11 && strcasecmp(progname + i - 11, "command.com") == 0) { + cmdline = apr_pstrcat(pool, shellcmd, " /C ", argv0, cmdline, NULL); + } + else { + cmdline = apr_pstrcat(pool, shellcmd, " /C \"", argv0, cmdline, "\"", NULL); + } + } + else +#endif + { + /* Win32 is _different_ than unix. While unix will find the given + * program since it's already chdir'ed, Win32 cannot since the parent + * attempts to open the program with it's own path. + * ###: This solution isn't much better - it may defeat path searching + * when the path search was desired. Open to further discussion. + */ + i = strlen(progname); + if (i >= 4 && (strcasecmp(progname + i - 4, ".bat") == 0 + || strcasecmp(progname + i - 4, ".cmd") == 0)) + { + char *shellcmd = getenv("COMSPEC"); + if (!shellcmd) { + if (attr->errfn) { + attr->errfn(pool, APR_EINVAL, "COMSPEC envar is not set"); + } + return APR_EINVAL; + } + if (shellcmd[0] == '"') { + progname = apr_pstrndup(pool, shellcmd + 1, strlen(shellcmd) - 2); + } + else { + progname = shellcmd; + if (has_space(shellcmd)) { + shellcmd = apr_pstrcat(pool, "\"", shellcmd, "\"", NULL); + } + } + i = strlen(progname); + if (i >= 11 && strcasecmp(progname + i - 11, "command.com") == 0) { + /* XXX: Still insecure - need doubled-quotes on each individual + * arg of cmdline. Suspect we need to postpone cmdline parsing + * until this moment in all four code paths, with some flags + * to toggle 'which flavor' is needed. + */ + cmdline = apr_pstrcat(pool, shellcmd, " /C ", argv0, cmdline, NULL); + } + else { + /* We must protect the cmdline args from any interpolation - this + * is not a shellcmd, and the source of argv[] is untrusted. + * Notice we escape ALL the cmdline args, including the quotes + * around the individual args themselves. No sense in allowing + * the shift-state to be toggled, and the application will + * not see the caret escapes. + */ + cmdline = apr_caret_escape_args(pool, cmdline); + /* + * Our app name must always be quoted so the quotes surrounding + * the entire /c "command args" are unambigious. + */ + if (*argv0 != '"') { + cmdline = apr_pstrcat(pool, shellcmd, " /C \"\"", argv0, "\"", cmdline, "\"", NULL); + } + else { + cmdline = apr_pstrcat(pool, shellcmd, " /C \"", argv0, cmdline, "\"", NULL); + } + } + } + else { + /* A simple command we are directly invoking. Do not pass + * the first arg to CreateProc() for APR_PROGRAM_PATH + * invocation, since it would need to be a literal and + * complete file path. That is; "c:\bin\aprtest.exe" + * would succeed, but "c:\bin\aprtest" or "aprtest.exe" + * can fail. + */ + cmdline = apr_pstrcat(pool, argv0, cmdline, NULL); + + if (attr->cmdtype == APR_PROGRAM_PATH) { + progname = NULL; + } + } + } + + if (!env || attr->cmdtype == APR_PROGRAM_ENV || + attr->cmdtype == APR_SHELLCMD_ENV) { + pEnvBlock = NULL; + } + else { + apr_size_t iEnvBlockLen; + /* + * Win32's CreateProcess call requires that the environment + * be passed in an environment block, a null terminated block of + * null terminated strings. + */ + i = 0; + iEnvBlockLen = 1; + while (env[i]) { + iEnvBlockLen += strlen(env[i]) + 1; + i++; + } + if (!i) + ++iEnvBlockLen; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t *pNext; + pEnvBlock = (char *)apr_palloc(pool, iEnvBlockLen * 2); + dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT; + + i = 0; + pNext = (apr_wchar_t*)pEnvBlock; + while (env[i]) { + apr_size_t in = strlen(env[i]) + 1; + if ((rv = apr_conv_utf8_to_ucs2(env[i], &in, + pNext, &iEnvBlockLen)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, rv, + apr_pstrcat(pool, + "utf8 to ucs2 conversion failed" + " on this string: ", env[i], NULL)); + } + return rv; + } + pNext = wcschr(pNext, L'\0') + 1; + i++; + } + if (!i) + *(pNext++) = L'\0'; + *pNext = L'\0'; + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *pNext; + pEnvBlock = (char *)apr_palloc(pool, iEnvBlockLen); + + i = 0; + pNext = pEnvBlock; + while (env[i]) { + strcpy(pNext, env[i]); + pNext = strchr(pNext, '\0') + 1; + i++; + } + if (!i) + *(pNext++) = '\0'; + *pNext = '\0'; + } +#endif /* APR_HAS_ANSI_FS */ + } + + new->invoked = cmdline; + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + STARTUPINFOW si; + apr_wchar_t *wprg = NULL; + apr_wchar_t *wcmd = NULL; + apr_wchar_t *wcwd = NULL; + + if (progname) { + apr_size_t nprg = strlen(progname) + 1; + apr_size_t nwprg = nprg + 6; + wprg = apr_palloc(pool, nwprg * sizeof(wprg[0])); + if ((rv = apr_conv_utf8_to_ucs2(progname, &nprg, wprg, &nwprg)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, rv, + apr_pstrcat(pool, + "utf8 to ucs2 conversion failed" + " on progname: ", progname, NULL)); + } + return rv; + } + } + + if (cmdline) { + apr_size_t ncmd = strlen(cmdline) + 1; + apr_size_t nwcmd = ncmd; + wcmd = apr_palloc(pool, nwcmd * sizeof(wcmd[0])); + if ((rv = apr_conv_utf8_to_ucs2(cmdline, &ncmd, wcmd, &nwcmd)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, rv, + apr_pstrcat(pool, + "utf8 to ucs2 conversion failed" + " on cmdline: ", cmdline, NULL)); + } + return rv; + } + } + + if (attr->currdir) + { + apr_size_t ncwd = strlen(attr->currdir) + 1; + apr_size_t nwcwd = ncwd; + wcwd = apr_palloc(pool, ncwd * sizeof(wcwd[0])); + if ((rv = apr_conv_utf8_to_ucs2(attr->currdir, &ncwd, + wcwd, &nwcwd)) + != APR_SUCCESS) { + if (attr->errfn) { + attr->errfn(pool, rv, + apr_pstrcat(pool, + "utf8 to ucs2 conversion failed" + " on currdir: ", attr->currdir, NULL)); + } + return rv; + } + } + + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + if (attr->detached) { + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + } + +#ifndef _WIN32_WCE + if ((attr->child_in && attr->child_in->filehand) + || (attr->child_out && attr->child_out->filehand) + || (attr->child_err && attr->child_err->filehand)) + { + si.dwFlags |= STARTF_USESTDHANDLES; + + si.hStdInput = (attr->child_in) + ? attr->child_in->filehand + : INVALID_HANDLE_VALUE; + + si.hStdOutput = (attr->child_out) + ? attr->child_out->filehand + : INVALID_HANDLE_VALUE; + + si.hStdError = (attr->child_err) + ? attr->child_err->filehand + : INVALID_HANDLE_VALUE; + } + if (attr->user_token) { + si.lpDesktop = L"Winsta0\\Default"; + if (!ImpersonateLoggedOnUser(attr->user_token)) { + /* failed to impersonate the logged user */ + rv = apr_get_os_error(); + CloseHandle(attr->user_token); + attr->user_token = NULL; + return rv; + } + rv = CreateProcessAsUserW(attr->user_token, + wprg, wcmd, + attr->sa, + NULL, + TRUE, + dwCreationFlags, + pEnvBlock, + wcwd, + &si, &pi); + + RevertToSelf(); + } + else { + rv = CreateProcessW(wprg, wcmd, /* Executable & Command line */ + NULL, NULL, /* Proc & thread security attributes */ + TRUE, /* Inherit handles */ + dwCreationFlags, /* Creation flags */ + pEnvBlock, /* Environment block */ + wcwd, /* Current directory name */ + &si, &pi); + } +#else + rv = CreateProcessW(wprg, wcmd, /* Executable & Command line */ + NULL, NULL, /* Proc & thread security attributes */ + FALSE, /* must be 0 */ + dwCreationFlags, /* Creation flags */ + NULL, /* Environment block must be NULL */ + NULL, /* Current directory name must be NULL*/ + NULL, /* STARTUPINFO not supported */ + &pi); +#endif + } +#endif /* APR_HAS_UNICODE_FS */ +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + STARTUPINFOA si; + memset(&si, 0, sizeof(si)); + si.cb = sizeof(si); + + if (attr->detached) { + si.dwFlags |= STARTF_USESHOWWINDOW; + si.wShowWindow = SW_HIDE; + } + + if ((attr->child_in && attr->child_in->filehand) + || (attr->child_out && attr->child_out->filehand) + || (attr->child_err && attr->child_err->filehand)) + { + si.dwFlags |= STARTF_USESTDHANDLES; + + si.hStdInput = (attr->child_in) + ? attr->child_in->filehand + : INVALID_HANDLE_VALUE; + + si.hStdOutput = (attr->child_out) + ? attr->child_out->filehand + : INVALID_HANDLE_VALUE; + + si.hStdError = (attr->child_err) + ? attr->child_err->filehand + : INVALID_HANDLE_VALUE; + } + + rv = CreateProcessA(progname, cmdline, /* Command line */ + NULL, NULL, /* Proc & thread security attributes */ + TRUE, /* Inherit handles */ + dwCreationFlags, /* Creation flags */ + pEnvBlock, /* Environment block */ + attr->currdir, /* Current directory name */ + &si, &pi); + } +#endif /* APR_HAS_ANSI_FS */ + + /* Check CreateProcess result + */ + if (!rv) + return apr_get_os_error(); + + /* XXX Orphaned handle warning - no fix due to broken apr_proc_t api. + */ + new->hproc = pi.hProcess; + new->pid = pi.dwProcessId; + + if (attr->child_in) { + apr_file_close(attr->child_in); + } + if (attr->child_out) { + apr_file_close(attr->child_out); + } + if (attr->child_err) { + apr_file_close(attr->child_err); + } + CloseHandle(pi.hThread); + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, + int *exitcode, + apr_exit_why_e *exitwhy, + apr_wait_how_e waithow, + apr_pool_t *p) +{ + /* Unix does apr_proc_wait(proc(-1), exitcode, exitwhy, waithow) + * but Win32's apr_proc_wait won't work that way. We can either + * register all APR created processes in some sort of AsyncWait + * thread, or simply walk from the global process pool for all + * apr_pool_note_subprocess()es registered with APR. + */ + return APR_ENOTIMPL; +} + +static apr_exit_why_e why_from_exit_code(DWORD exit) { + /* See WinNT.h STATUS_ACCESS_VIOLATION and family for how + * this class of failures was determined + */ + if (((exit & 0xC0000000) == 0xC0000000) + && !(exit & 0x3FFF0000)) + return APR_PROC_SIGNAL; + else + return APR_PROC_EXIT; + + /* ### No way to tell if Dr Watson grabbed a core, AFAICT. */ +} + +APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc, + int *exitcode, apr_exit_why_e *exitwhy, + apr_wait_how_e waithow) +{ + DWORD stat; + DWORD time; + + if (waithow == APR_WAIT) + time = INFINITE; + else + time = 0; + + if ((stat = WaitForSingleObject(proc->hproc, time)) == WAIT_OBJECT_0) { + if (GetExitCodeProcess(proc->hproc, &stat)) { + if (exitcode) + *exitcode = stat; + if (exitwhy) + *exitwhy = why_from_exit_code(stat); + CloseHandle(proc->hproc); + proc->hproc = NULL; + return APR_CHILD_DONE; + } + } + else if (stat == WAIT_TIMEOUT) { + return APR_CHILD_NOTDONE; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_proc_detach(int daemonize) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/threadproc/win32/signals.c b/srclib/apr/threadproc/win32/signals.c new file mode 100644 index 0000000000..d4d8a64026 --- /dev/null +++ b/srclib/apr/threadproc/win32/signals.c @@ -0,0 +1,66 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_threadproc.h" +#include "win32/apr_arch_file_io.h" +#include "apr_thread_proc.h" +#include "apr_file_io.h" +#include "apr_general.h" +#if APR_HAVE_SIGNAL_H +#include +#endif +#include +#if APR_HAVE_SYS_WAIT +#include +#endif + +/* Windows only really support killing process, but that will do for now. + * + * ### Actually, closing the input handle to the proc should also do fine + * for most console apps. This definately needs improvement... + */ +APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signal) +{ + if (proc->hproc != NULL) { + if (TerminateProcess(proc->hproc, signal) == 0) { + return apr_get_os_error(); + } + /* On unix, SIGKILL leaves a apr_proc_wait()able pid lying around, + * so we will leave hproc alone until the app calls apr_proc_wait(). + */ + return APR_SUCCESS; + } + return APR_EPROC_UNKNOWN; +} + +void apr_signal_init(apr_pool_t *pglobal) +{ +} + +const char *apr_signal_description_get(int signum) +{ + return "unknown signal (not supported)"; +} + +APR_DECLARE(apr_status_t) apr_signal_block(int signum) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_signal_unblock(int signum) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/threadproc/win32/thread.c b/srclib/apr/threadproc/win32/thread.c new file mode 100644 index 0000000000..33e9afcde4 --- /dev/null +++ b/srclib/apr/threadproc/win32/thread.c @@ -0,0 +1,282 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "win32/apr_arch_threadproc.h" +#include "apr_thread_proc.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#if APR_HAVE_PROCESS_H +#include +#endif +#include "apr_arch_misc.h" + +/* Chosen for us by apr_initialize */ +DWORD tls_apr_thread = 0; + +APR_DECLARE(apr_status_t) apr_threadattr_create(apr_threadattr_t **new, + apr_pool_t *pool) +{ + (*new) = (apr_threadattr_t *)apr_palloc(pool, + sizeof(apr_threadattr_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->detach = 0; + (*new)->stacksize = 0; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, + apr_int32_t on) +{ + attr->detach = on; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) +{ + if (attr->detach == 1) + return APR_DETACH; + return APR_NOTDETACH; +} + +APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, + apr_size_t stacksize) +{ + attr->stacksize = stacksize; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr, + apr_size_t size) +{ + return APR_ENOTIMPL; +} + +static void *dummy_worker(void *opaque) +{ + apr_thread_t *thd = (apr_thread_t *)opaque; + TlsSetValue(tls_apr_thread, thd->td); + return thd->func(thd, thd->data); +} + +APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, + apr_threadattr_t *attr, + apr_thread_start_t func, + void *data, apr_pool_t *pool) +{ + apr_status_t stat; + unsigned temp; + HANDLE handle; + + (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + + if ((*new) == NULL) { + return APR_ENOMEM; + } + + (*new)->pool = pool; + (*new)->data = data; + (*new)->func = func; + (*new)->td = NULL; + stat = apr_pool_create(&(*new)->pool, pool); + if (stat != APR_SUCCESS) { + return stat; + } + + /* Use 0 for Thread Stack Size, because that will default the stack to the + * same size as the calling thread. + */ +#ifndef _WIN32_WCE + if ((handle = (HANDLE)_beginthreadex(NULL, + attr && attr->stacksize > 0 ? attr->stacksize : 0, + (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker, + (*new), 0, &temp)) == 0) { + return APR_FROM_OS_ERROR(_doserrno); + } +#else + if ((handle = CreateThread(NULL, + attr && attr->stacksize > 0 ? attr->stacksize : 0, + (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker, + (*new), 0, &temp)) == 0) { + return apr_get_os_error(); + } +#endif + if (attr && attr->detach) { + CloseHandle(handle); + } + else + (*new)->td = handle; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, + apr_status_t retval) +{ + thd->exitval = retval; + apr_pool_destroy(thd->pool); + thd->pool = NULL; +#ifndef _WIN32_WCE + _endthreadex(0); +#else + ExitThread(0); +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) +{ + apr_status_t rv = APR_SUCCESS; + + if (!thd->td) { + /* Can not join on detached threads */ + return APR_DETACH; + } + rv = WaitForSingleObject(thd->td, INFINITE); + if ( rv == WAIT_OBJECT_0 || rv == WAIT_ABANDONED) { + /* If the thread_exit has been called */ + if (!thd->pool) + *retval = thd->exitval; + else + rv = APR_INCOMPLETE; + } + else + rv = apr_get_os_error(); + CloseHandle(thd->td); + thd->td = NULL; + + return rv; +} + +APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) +{ + if (thd->td && CloseHandle(thd->td)) { + thd->td = NULL; + return APR_SUCCESS; + } + else { + return apr_get_os_error(); + } +} + +APR_DECLARE(void) apr_thread_yield() +{ + /* SwitchToThread is not supported on Win9x, but since it's + * primarily a noop (entering time consuming code, therefore + * providing more critical threads a bit larger timeslice) + * we won't worry too much if it's not available. + */ +#ifndef _WIN32_WCE + if (apr_os_level >= APR_WIN_NT) { + SwitchToThread(); + } +#endif +} + +APR_DECLARE(apr_status_t) apr_thread_data_get(void **data, const char *key, + apr_thread_t *thread) +{ + return apr_pool_userdata_get(data, key, thread->pool); +} + +APR_DECLARE(apr_status_t) apr_thread_data_set(void *data, const char *key, + apr_status_t (*cleanup) (void *), + apr_thread_t *thread) +{ + return apr_pool_userdata_set(data, key, cleanup, thread->pool); +} + + +APR_DECLARE(apr_os_thread_t) apr_os_thread_current(void) +{ + HANDLE hthread = (HANDLE)TlsGetValue(tls_apr_thread); + HANDLE hproc; + + if (hthread) { + return hthread; + } + + hproc = GetCurrentProcess(); + hthread = GetCurrentThread(); + if (!DuplicateHandle(hproc, hthread, + hproc, &hthread, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + return NULL; + } + TlsSetValue(tls_apr_thread, hthread); + return hthread; +} + +APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd, + apr_thread_t *thd) +{ + if (thd == NULL) { + return APR_ENOTHREAD; + } + *thethd = thd->td; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd, + apr_os_thread_t *thethd, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*thd) == NULL) { + (*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); + (*thd)->pool = pool; + } + (*thd)->td = thethd; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control, + apr_pool_t *p) +{ + (*control) = apr_pcalloc(p, sizeof(**control)); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, + void (*func)(void)) +{ + if (!InterlockedExchange(&control->value, 1)) { + func(); + } + return APR_SUCCESS; +} + +APR_DECLARE(int) apr_os_thread_equal(apr_os_thread_t tid1, + apr_os_thread_t tid2) +{ + /* Since the only tid's we support our are own, and + * apr_os_thread_current returns the identical handle + * to the one we created initially, the test is simple. + */ + return (tid1 == tid2); +} + +APR_POOL_IMPLEMENT_ACCESSOR(thread) diff --git a/srclib/apr/threadproc/win32/threadpriv.c b/srclib/apr/threadproc/win32/threadpriv.c new file mode 100644 index 0000000000..0d45b0da23 --- /dev/null +++ b/srclib/apr/threadproc/win32/threadpriv.c @@ -0,0 +1,101 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_threadproc.h" +#include "apr_thread_proc.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_errno.h" +#include "apr_portable.h" + +APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, + void (*dest)(void *), + apr_pool_t *pool) +{ + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + if ((*key) == NULL) { + return APR_ENOMEM; + } + + (*key)->pool = pool; + + if (((*key)->key = TlsAlloc()) != 0xFFFFFFFF) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, + apr_threadkey_t *key) +{ + if ((*new) = TlsGetValue(key->key)) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, + apr_threadkey_t *key) +{ + if (TlsSetValue(key->key, priv)) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key) +{ + if (TlsFree(key->key)) { + return APR_SUCCESS; + } + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_get(data, key, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_threadkey_data_set(void *data, const char *key, + apr_status_t (*cleanup)(void *), + apr_threadkey_t *threadkey) +{ + return apr_pool_userdata_set(data, key, cleanup, threadkey->pool); +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_get(apr_os_threadkey_t *thekey, + apr_threadkey_t *key) +{ + *thekey = key->key; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_threadkey_put(apr_threadkey_t **key, + apr_os_threadkey_t *thekey, + apr_pool_t *pool) +{ + if (pool == NULL) { + return APR_ENOPOOL; + } + if ((*key) == NULL) { + (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + (*key)->pool = pool; + } + (*key)->key = *thekey; + return APR_SUCCESS; +} + diff --git a/srclib/apr/time/unix/time.c b/srclib/apr/time/unix/time.c new file mode 100644 index 0000000000..ffc0c697cc --- /dev/null +++ b/srclib/apr/time/unix/time.c @@ -0,0 +1,332 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_portable.h" +#include "apr_time.h" +#include "apr_lib.h" +#include "apr_private.h" +#include "apr_strings.h" + +/* private APR headers */ +#include "apr_arch_internal_time.h" + +/* System Headers required for time library */ +#if APR_HAVE_SYS_TIME_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +/* End System Headers */ + +#if !defined(HAVE_STRUCT_TM_TM_GMTOFF) && !defined(HAVE_STRUCT_TM___TM_GMTOFF) +static apr_int32_t server_gmt_offset; +#define NO_GMTOFF_IN_STRUCT_TM +#endif + +static apr_int32_t get_offset(struct tm *tm) +{ +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) + return tm->tm_gmtoff; +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) + return tm->__tm_gmtoff; +#else +#ifdef NETWARE + /* Need to adjust the global variable each time otherwise + the web server would have to be restarted when daylight + savings changes. + */ + if (daylightOnOff) { + return server_gmt_offset + daylightOffset; + } +#else + if (tm->tm_isdst) + return server_gmt_offset + 3600; +#endif + return server_gmt_offset; +#endif +} + +APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, + time_t input) +{ + *result = (apr_time_t)input * APR_USEC_PER_SEC; + return APR_SUCCESS; +} + +/* NB NB NB NB This returns GMT!!!!!!!!!! */ +APR_DECLARE(apr_time_t) apr_time_now(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * APR_USEC_PER_SEC + tv.tv_usec; +} + +static void explode_time(apr_time_exp_t *xt, apr_time_t t, + apr_int32_t offset, int use_localtime) +{ + struct tm tm; + time_t tt = (t / APR_USEC_PER_SEC) + offset; + xt->tm_usec = t % APR_USEC_PER_SEC; + +#if APR_HAS_THREADS && defined (_POSIX_THREAD_SAFE_FUNCTIONS) + if (use_localtime) + localtime_r(&tt, &tm); + else + gmtime_r(&tt, &tm); +#else + if (use_localtime) + tm = *localtime(&tt); + else + tm = *gmtime(&tt); +#endif + + xt->tm_sec = tm.tm_sec; + xt->tm_min = tm.tm_min; + xt->tm_hour = tm.tm_hour; + xt->tm_mday = tm.tm_mday; + xt->tm_mon = tm.tm_mon; + xt->tm_year = tm.tm_year; + xt->tm_wday = tm.tm_wday; + xt->tm_yday = tm.tm_yday; + xt->tm_isdst = tm.tm_isdst; + xt->tm_gmtoff = get_offset(&tm); +} + +APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, apr_int32_t offs) +{ + explode_time(result, input, offs, 0); + result->tm_gmtoff = offs; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input) +{ + return apr_time_exp_tz(result, input, 0); +} + +APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input) +{ +#if defined(__EMX__) + /* EMX gcc (OS/2) has a timezone global we can use */ + return apr_time_exp_tz(result, input, -timezone); +#else + explode_time(result, input, 0, 1); + return APR_SUCCESS; +#endif /* __EMX__ */ +} + +APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, apr_time_exp_t *xt) +{ + apr_time_t year = xt->tm_year; + apr_time_t days; + static const int dayoffset[12] = + {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; + + /* shift new year to 1st March in order to make leap year calc easy */ + + if (xt->tm_mon < 2) + year--; + + /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ + + days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; + days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; + days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ + days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; + + if (days < 0) { + return APR_EBADDATE; + } + *t = days * APR_USEC_PER_SEC + xt->tm_usec; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t, + apr_time_exp_t *xt) +{ + apr_status_t status = apr_time_exp_get(t, xt); + if (status == APR_SUCCESS) + *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC; + return status; +} + +APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime) +{ + (*ostime)->tv_usec = *aprtime % APR_USEC_PER_SEC; + (*ostime)->tv_sec = *aprtime / APR_USEC_PER_SEC; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprtime) +{ + (*ostime)->tm_sec = aprtime->tm_sec; + (*ostime)->tm_min = aprtime->tm_min; + (*ostime)->tm_hour = aprtime->tm_hour; + (*ostime)->tm_mday = aprtime->tm_mday; + (*ostime)->tm_mon = aprtime->tm_mon; + (*ostime)->tm_year = aprtime->tm_year; + (*ostime)->tm_wday = aprtime->tm_wday; + (*ostime)->tm_yday = aprtime->tm_yday; + (*ostime)->tm_isdst = aprtime->tm_isdst; + +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) + (*ostime)->tm_gmtoff = aprtime->tm_gmtoff; +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) + (*ostime)->__tm_gmtoff = aprtime->tm_gmtoff; +#endif + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont) +{ + *aprtime = (*ostime)->tv_sec * APR_USEC_PER_SEC + (*ostime)->tv_usec; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont) +{ + aprtime->tm_sec = (*ostime)->tm_sec; + aprtime->tm_min = (*ostime)->tm_min; + aprtime->tm_hour = (*ostime)->tm_hour; + aprtime->tm_mday = (*ostime)->tm_mday; + aprtime->tm_mon = (*ostime)->tm_mon; + aprtime->tm_year = (*ostime)->tm_year; + aprtime->tm_wday = (*ostime)->tm_wday; + aprtime->tm_yday = (*ostime)->tm_yday; + aprtime->tm_isdst = (*ostime)->tm_isdst; + +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) + aprtime->tm_gmtoff = (*ostime)->tm_gmtoff; +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) + aprtime->tm_gmtoff = (*ostime)->__tm_gmtoff; +#endif + + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_sleep(apr_interval_time_t t) +{ +#ifdef OS2 + DosSleep(t/1000); +#elif defined(BEOS) + snooze(t); +#elif defined(NETWARE) + delay(t/1000); +#else + struct timeval tv; + tv.tv_usec = t % APR_USEC_PER_SEC; + tv.tv_sec = t / APR_USEC_PER_SEC; + select(0, NULL, NULL, NULL, &tv); +#endif +} + +#ifdef OS2 +APR_DECLARE(apr_status_t) apr_os2_time_to_apr_time(apr_time_t *result, + FDATE os2date, + FTIME os2time) +{ + struct tm tmpdate; + + memset(&tmpdate, 0, sizeof(tmpdate)); + tmpdate.tm_hour = os2time.hours; + tmpdate.tm_min = os2time.minutes; + tmpdate.tm_sec = os2time.twosecs * 2; + + tmpdate.tm_mday = os2date.day; + tmpdate.tm_mon = os2date.month - 1; + tmpdate.tm_year = os2date.year + 80; + tmpdate.tm_isdst = -1; + + *result = mktime(&tmpdate) * APR_USEC_PER_SEC; + return APR_SUCCESS; +} +#endif + +#ifdef NETWARE +APR_DECLARE(void) apr_netware_setup_time(void) +{ + tzset(); + server_gmt_offset = -TZONE; +} +#else +APR_DECLARE(void) apr_unix_setup_time(void) +{ +#ifdef NO_GMTOFF_IN_STRUCT_TM + /* Precompute the offset from GMT on systems where it's not + in struct tm. + + Note: This offset is normalized to be independent of daylight + savings time; if the calculation happens to be done in a + time/place where a daylight savings adjustment is in effect, + the returned offset has the same value that it would have + in the same location if daylight savings were not in effect. + The reason for this is that the returned offset can be + applied to a past or future timestamp in explode_time(), + so the DST adjustment obtained from the current time won't + necessarily be applicable. + + mktime() is the inverse of localtime(); so, presumably, + passing in a struct tm made by gmtime() let's us calculate + the true GMT offset. However, there's a catch: if daylight + savings is in effect, gmtime()will set the tm_isdst field + and confuse mktime() into returning a time that's offset + by one hour. In that case, we must adjust the calculated GMT + offset. + + */ + + struct timeval now; + time_t t1, t2; + struct tm t; + + gettimeofday(&now, NULL); + t1 = now.tv_sec; + t2 = 0; + +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) + gmtime_r(&t1, &t); +#else + t = *gmtime(&t1); +#endif + t.tm_isdst = 0; /* we know this GMT time isn't daylight-savings */ + t2 = mktime(&t); + server_gmt_offset = (apr_int32_t) difftime(t1, t2); +#endif /* NO_GMTOFF_IN_STRUCT_TM */ +} + +#endif + +/* A noop on all known Unix implementations */ +APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p) +{ + return; +} + + diff --git a/srclib/apr/time/unix/timestr.c b/srclib/apr/time/unix/timestr.c new file mode 100644 index 0000000000..770cdb3b59 --- /dev/null +++ b/srclib/apr/time/unix/timestr.c @@ -0,0 +1,153 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_portable.h" +#include "apr_time.h" +#include "apr_lib.h" +#include "apr_private.h" +/* System Headers required for time library */ +#if APR_HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_TIME_H +#include +#endif +#if APR_HAVE_STRING_H +#include +#endif +/* End System Headers */ + +APR_DECLARE_DATA const char apr_month_snames[12][4] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +APR_DECLARE_DATA const char apr_day_snames[7][4] = +{ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +apr_status_t apr_rfc822_date(char *date_str, apr_time_t t) +{ + apr_time_exp_t xt; + const char *s; + int real_year; + + apr_time_exp_gmt(&xt, t); + + /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */ + /* 12345678901234567890123456789 */ + + s = &apr_day_snames[xt.tm_wday][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ','; + *date_str++ = ' '; + *date_str++ = xt.tm_mday / 10 + '0'; + *date_str++ = xt.tm_mday % 10 + '0'; + *date_str++ = ' '; + s = &apr_month_snames[xt.tm_mon][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + real_year = 1900 + xt.tm_year; + /* This routine isn't y10k ready. */ + *date_str++ = real_year / 1000 + '0'; + *date_str++ = real_year % 1000 / 100 + '0'; + *date_str++ = real_year % 100 / 10 + '0'; + *date_str++ = real_year % 10 + '0'; + *date_str++ = ' '; + *date_str++ = xt.tm_hour / 10 + '0'; + *date_str++ = xt.tm_hour % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_min / 10 + '0'; + *date_str++ = xt.tm_min % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_sec / 10 + '0'; + *date_str++ = xt.tm_sec % 10 + '0'; + *date_str++ = ' '; + *date_str++ = 'G'; + *date_str++ = 'M'; + *date_str++ = 'T'; + *date_str++ = 0; + return APR_SUCCESS; +} + +apr_status_t apr_ctime(char *date_str, apr_time_t t) +{ + apr_time_exp_t xt; + const char *s; + int real_year; + + /* example: "Wed Jun 30 21:49:08 1993" */ + /* 123456789012345678901234 */ + + apr_time_exp_lt(&xt, t); + s = &apr_day_snames[xt.tm_wday][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + s = &apr_month_snames[xt.tm_mon][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + *date_str++ = xt.tm_mday / 10 + '0'; + *date_str++ = xt.tm_mday % 10 + '0'; + *date_str++ = ' '; + *date_str++ = xt.tm_hour / 10 + '0'; + *date_str++ = xt.tm_hour % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_min / 10 + '0'; + *date_str++ = xt.tm_min % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_sec / 10 + '0'; + *date_str++ = xt.tm_sec % 10 + '0'; + *date_str++ = ' '; + real_year = 1900 + xt.tm_year; + *date_str++ = real_year / 1000 + '0'; + *date_str++ = real_year % 1000 / 100 + '0'; + *date_str++ = real_year % 100 / 10 + '0'; + *date_str++ = real_year % 10 + '0'; + *date_str++ = 0; + + return APR_SUCCESS; +} + +apr_status_t apr_strftime(char *s, apr_size_t *retsize, apr_size_t max, + const char *format, apr_time_exp_t *xt) +{ + struct tm tm; + memset(&tm, 0, sizeof tm); + tm.tm_sec = xt->tm_sec; + tm.tm_min = xt->tm_min; + tm.tm_hour = xt->tm_hour; + tm.tm_mday = xt->tm_mday; + tm.tm_mon = xt->tm_mon; + tm.tm_year = xt->tm_year; + tm.tm_wday = xt->tm_wday; + tm.tm_yday = xt->tm_yday; + tm.tm_isdst = xt->tm_isdst; +#if defined(HAVE_STRUCT_TM_TM_GMTOFF) + tm.tm_gmtoff = xt->tm_gmtoff; +#elif defined(HAVE_STRUCT_TM___TM_GMTOFF) + tm.__tm_gmtoff = xt->tm_gmtoff; +#endif + (*retsize) = strftime(s, max, format, &tm); + return APR_SUCCESS; +} diff --git a/srclib/apr/time/win32/access.c b/srclib/apr/time/win32/access.c new file mode 100644 index 0000000000..e746fca1f6 --- /dev/null +++ b/srclib/apr/time/win32/access.c @@ -0,0 +1,204 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_atime.h" +#include "apr_time.h" +#include "apr_general.h" +#include "apr_lib.h" + +apr_status_t apr_get_curtime(struct atime_t *time, apr_time_t *rv) +{ + if (time) { + (*rv) = time->currtime; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_sec(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wSecond; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_min(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wMinute; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_hour(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wHour; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_mday(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wDay; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_mon(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wMonth; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_year(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wYear; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_get_wday(struct atime_t *time, apr_int32_t *rv) +{ + if (time) { + (*rv) = time->explodedtime->wDayOfWeek; + return APR_SUCCESS; + } + return APR_ENOTIME; +} + +apr_status_t apr_set_sec(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wSecond = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_min(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wMinute = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_hour(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wHour = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_mday(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wDay = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_mon(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wMonth = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_year(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wYear = value; + return APR_SUCCESS; +} + +apr_status_t apr_set_wday(struct atime_t *time, apr_int32_t value) +{ + if (!time) { + return APR_ENOTIME; + } + if (time->explodedtime == NULL) { + time->explodedtime = (SYSTEMTIME *)apr_pcalloc(time->cntxt, + sizeof(SYSTEMTIME)); + } + if (time->explodedtime == NULL) { + return APR_ENOMEM; + } + time->explodedtime->wDayOfWeek = value; + return APR_SUCCESS; +} diff --git a/srclib/apr/time/win32/time.c b/srclib/apr/time/win32/time.c new file mode 100644 index 0000000000..89d6d5e400 --- /dev/null +++ b/srclib/apr/time/win32/time.c @@ -0,0 +1,326 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_atime.h" +#include "apr_time.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" +#if APR_HAVE_TIME_H +#include +#endif +#if APR_HAVE_ERRNO_H +#include +#endif +#include +#include +#include "apr_arch_misc.h" + +/* Leap year is any year divisible by four, but not by 100 unless also + * divisible by 400 + */ +#define IsLeapYear(y) ((!(y % 4)) ? (((!(y % 400)) && (y % 100)) ? 1 : 0) : 0) + +static DWORD get_local_timezone(TIME_ZONE_INFORMATION **tzresult) +{ + static TIME_ZONE_INFORMATION tz; + static DWORD result; + static int init = 0; + + if (!init) { + result = GetTimeZoneInformation(&tz); + init = 1; + } + + *tzresult = &tz; + return result; +} + +static void SystemTimeToAprExpTime(apr_time_exp_t *xt, SYSTEMTIME *tm) +{ + static const int dayoffset[12] = + {0, 31, 59, 90, 120, 151, 182, 212, 243, 273, 304, 334}; + + /* Note; the caller is responsible for filling in detailed tm_usec, + * tm_gmtoff and tm_isdst data when applicable. + */ + xt->tm_usec = tm->wMilliseconds * 1000; + xt->tm_sec = tm->wSecond; + xt->tm_min = tm->wMinute; + xt->tm_hour = tm->wHour; + xt->tm_mday = tm->wDay; + xt->tm_mon = tm->wMonth - 1; + xt->tm_year = tm->wYear - 1900; + xt->tm_wday = tm->wDayOfWeek; + xt->tm_yday = dayoffset[xt->tm_mon] + (tm->wDay - 1); + xt->tm_isdst = 0; + xt->tm_gmtoff = 0; + + /* If this is a leap year, and we're past the 28th of Feb. (the + * 58th day after Jan. 1), we'll increment our tm_yday by one. + */ + if (IsLeapYear(tm->wYear) && (xt->tm_yday > 58)) + xt->tm_yday++; +} + +APR_DECLARE(apr_status_t) apr_time_ansi_put(apr_time_t *result, + time_t input) +{ + *result = (apr_time_t) input * APR_USEC_PER_SEC; + return APR_SUCCESS; +} + +/* Return micro-seconds since the Unix epoch (jan. 1, 1970) UTC */ +APR_DECLARE(apr_time_t) apr_time_now(void) +{ + LONGLONG aprtime = 0; + FILETIME time; +#ifndef _WIN32_WCE + GetSystemTimeAsFileTime(&time); +#else + SYSTEMTIME st; + GetSystemTime(&st); + SystemTimeToFileTime(&st, &time); +#endif + FileTimeToAprTime(&aprtime, &time); + return aprtime; +} + +APR_DECLARE(apr_status_t) apr_time_exp_gmt(apr_time_exp_t *result, + apr_time_t input) +{ + FILETIME ft; + SYSTEMTIME st; + AprTimeToFileTime(&ft, input); + FileTimeToSystemTime(&ft, &st); + /* The Platform SDK documents that SYSTEMTIME/FILETIME are + * generally UTC, so no timezone info needed + */ + SystemTimeToAprExpTime(result, &st); + result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_tz(apr_time_exp_t *result, + apr_time_t input, + apr_int32_t offs) +{ + FILETIME ft; + SYSTEMTIME st; + AprTimeToFileTime(&ft, input + (offs * APR_USEC_PER_SEC)); + FileTimeToSystemTime(&ft, &st); + /* The Platform SDK documents that SYSTEMTIME/FILETIME are + * generally UTC, so we will simply note the offs used. + */ + SystemTimeToAprExpTime(result, &st); + result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC); + result->tm_gmtoff = offs; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_lt(apr_time_exp_t *result, + apr_time_t input) +{ + SYSTEMTIME st; + FILETIME ft, localft; + + AprTimeToFileTime(&ft, input); + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + TIME_ZONE_INFORMATION *tz; + SYSTEMTIME localst; + apr_time_t localtime; + + get_local_timezone(&tz); + + FileTimeToSystemTime(&ft, &st); + + /* The Platform SDK documents that SYSTEMTIME/FILETIME are + * generally UTC. We use SystemTimeToTzSpecificLocalTime + * because FileTimeToLocalFileFime is documented that the + * resulting time local file time would have DST relative + * to the *present* date, not the date converted. + */ + SystemTimeToTzSpecificLocalTime(tz, &st, &localst); + SystemTimeToAprExpTime(result, &localst); + result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC); + + + /* Recover the resulting time as an apr time and use the + * delta for gmtoff in seconds (and ignore msec rounding) + */ + SystemTimeToFileTime(&localst, &localft); + FileTimeToAprTime(&localtime, &localft); + result->tm_gmtoff = (int)apr_time_sec(localtime) + - (int)apr_time_sec(input); + + /* To compute the dst flag, we compare the expected + * local (standard) timezone bias to the delta. + * [Note, in war time or double daylight time the + * resulting tm_isdst is, desireably, 2 hours] + */ + result->tm_isdst = (result->tm_gmtoff / 3600) + - (-(tz->Bias + tz->StandardBias) / 60); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + TIME_ZONE_INFORMATION tz; + /* XXX: This code is simply *wrong*. The time converted will always + * map to the *now current* status of daylight savings time. + */ + + FileTimeToLocalFileTime(&ft, &localft); + FileTimeToSystemTime(&localft, &st); + SystemTimeToAprExpTime(result, &st); + result->tm_usec = (apr_int32_t) (input % APR_USEC_PER_SEC); + + switch (GetTimeZoneInformation(&tz)) { + case TIME_ZONE_ID_UNKNOWN: + result->tm_isdst = 0; + /* Bias = UTC - local time in minutes + * tm_gmtoff is seconds east of UTC + */ + result->tm_gmtoff = tz.Bias * -60; + break; + case TIME_ZONE_ID_STANDARD: + result->tm_isdst = 0; + result->tm_gmtoff = (tz.Bias + tz.StandardBias) * -60; + break; + case TIME_ZONE_ID_DAYLIGHT: + result->tm_isdst = 1; + result->tm_gmtoff = (tz.Bias + tz.DaylightBias) * -60; + break; + default: + /* noop */; + } + } +#endif + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_get(apr_time_t *t, + apr_time_exp_t *xt) +{ + apr_time_t year = xt->tm_year; + apr_time_t days; + static const int dayoffset[12] = + {306, 337, 0, 31, 61, 92, 122, 153, 184, 214, 245, 275}; + + /* shift new year to 1st March in order to make leap year calc easy */ + + if (xt->tm_mon < 2) + year--; + + /* Find number of days since 1st March 1900 (in the Gregorian calendar). */ + + days = year * 365 + year / 4 - year / 100 + (year / 100 + 3) / 4; + days += dayoffset[xt->tm_mon] + xt->tm_mday - 1; + days -= 25508; /* 1 jan 1970 is 25508 days since 1 mar 1900 */ + + days = ((days * 24 + xt->tm_hour) * 60 + xt->tm_min) * 60 + xt->tm_sec; + + if (days < 0) { + return APR_EBADDATE; + } + *t = days * APR_USEC_PER_SEC + xt->tm_usec; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_time_exp_gmt_get(apr_time_t *t, + apr_time_exp_t *xt) +{ + apr_status_t status = apr_time_exp_get(t, xt); + if (status == APR_SUCCESS) + *t -= (apr_time_t) xt->tm_gmtoff * APR_USEC_PER_SEC; + return status; +} + +APR_DECLARE(apr_status_t) apr_os_imp_time_get(apr_os_imp_time_t **ostime, + apr_time_t *aprtime) +{ + /* TODO: Consider not passing in pointer to apr_time_t (e.g., call by value) */ + AprTimeToFileTime(*ostime, *aprtime); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_exp_time_get(apr_os_exp_time_t **ostime, + apr_time_exp_t *aprexptime) +{ + (*ostime)->wYear = aprexptime->tm_year + 1900; + (*ostime)->wMonth = aprexptime->tm_mon + 1; + (*ostime)->wDayOfWeek = aprexptime->tm_wday; + (*ostime)->wDay = aprexptime->tm_mday; + (*ostime)->wHour = aprexptime->tm_hour; + (*ostime)->wMinute = aprexptime->tm_min; + (*ostime)->wSecond = aprexptime->tm_sec; + (*ostime)->wMilliseconds = aprexptime->tm_usec / 1000; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_imp_time_put(apr_time_t *aprtime, + apr_os_imp_time_t **ostime, + apr_pool_t *cont) +{ + /* XXX: sanity failure, what is file time, gmt or local ? + */ + FileTimeToAprTime(aprtime, *ostime); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_exp_time_put(apr_time_exp_t *aprtime, + apr_os_exp_time_t **ostime, + apr_pool_t *cont) +{ + /* The Platform SDK documents that SYSTEMTIME/FILETIME are + * generally UTC, so no timezone info needed + */ + SystemTimeToAprExpTime(aprtime, *ostime); + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_sleep(apr_interval_time_t t) +{ + /* One of the few sane situations for a cast, Sleep + * is in ms, not us, and passed as a DWORD value + */ + Sleep((DWORD)(t / 1000)); +} + + +static apr_status_t clock_restore(void *unsetres) +{ + ULONG newRes; + SetTimerResolution((ULONG)unsetres, FALSE, &newRes); + return APR_SUCCESS; +} + +APR_DECLARE(void) apr_time_clock_hires(apr_pool_t *p) +{ + ULONG newRes; + /* Timer resolution is stated in 100ns units. Note that TRUE requests the + * new clock resolution, FALSE above releases the request. + */ + if (SetTimerResolution(10000, TRUE, &newRes) == 0 /* STATUS_SUCCESS */) { + /* register the cleanup... */ + apr_pool_cleanup_register(p, (void*)10000, clock_restore, + apr_pool_cleanup_null); + } +} diff --git a/srclib/apr/time/win32/timestr.c b/srclib/apr/time/win32/timestr.c new file mode 100644 index 0000000000..ce96c867e7 --- /dev/null +++ b/srclib/apr/time/win32/timestr.c @@ -0,0 +1,216 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "win32/apr_arch_atime.h" +#include "apr_portable.h" +#include "apr_strings.h" + +APR_DECLARE_DATA const char apr_month_snames[12][4] = +{ + "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; +APR_DECLARE_DATA const char apr_day_snames[7][4] = +{ + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +APR_DECLARE(apr_status_t) apr_rfc822_date(char *date_str, apr_time_t t) +{ + apr_time_exp_t xt; + const char *s; + int real_year; + + apr_time_exp_gmt(&xt, t); + + /* example: "Sat, 08 Jan 2000 18:31:41 GMT" */ + /* 12345678901234567890123456789 */ + + s = &apr_day_snames[xt.tm_wday][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ','; + *date_str++ = ' '; + *date_str++ = xt.tm_mday / 10 + '0'; + *date_str++ = xt.tm_mday % 10 + '0'; + *date_str++ = ' '; + s = &apr_month_snames[xt.tm_mon][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + real_year = 1900 + xt.tm_year; + /* This routine isn't y10k ready. */ + *date_str++ = real_year / 1000 + '0'; + *date_str++ = real_year % 1000 / 100 + '0'; + *date_str++ = real_year % 100 / 10 + '0'; + *date_str++ = real_year % 10 + '0'; + *date_str++ = ' '; + *date_str++ = xt.tm_hour / 10 + '0'; + *date_str++ = xt.tm_hour % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_min / 10 + '0'; + *date_str++ = xt.tm_min % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_sec / 10 + '0'; + *date_str++ = xt.tm_sec % 10 + '0'; + *date_str++ = ' '; + *date_str++ = 'G'; + *date_str++ = 'M'; + *date_str++ = 'T'; + *date_str++ = 0; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_ctime(char *date_str, apr_time_t t) +{ + apr_time_exp_t xt; + const char *s; + int real_year; + + /* example: "Wed Jun 30 21:49:08 1993" */ + /* 123456789012345678901234 */ + + apr_time_exp_lt(&xt, t); + s = &apr_day_snames[xt.tm_wday][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + s = &apr_month_snames[xt.tm_mon][0]; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = *s++; + *date_str++ = ' '; + *date_str++ = xt.tm_mday / 10 + '0'; + *date_str++ = xt.tm_mday % 10 + '0'; + *date_str++ = ' '; + *date_str++ = xt.tm_hour / 10 + '0'; + *date_str++ = xt.tm_hour % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_min / 10 + '0'; + *date_str++ = xt.tm_min % 10 + '0'; + *date_str++ = ':'; + *date_str++ = xt.tm_sec / 10 + '0'; + *date_str++ = xt.tm_sec % 10 + '0'; + *date_str++ = ' '; + real_year = 1900 + xt.tm_year; + *date_str++ = real_year / 1000 + '0'; + *date_str++ = real_year % 1000 / 100 + '0'; + *date_str++ = real_year % 100 / 10 + '0'; + *date_str++ = real_year % 10 + '0'; + *date_str++ = 0; + + return APR_SUCCESS; +} + + +#ifndef _WIN32_WCE + +apr_size_t win32_strftime_extra(char *s, size_t max, const char *format, + const struct tm *tm) +{ + /* If the new format string is bigger than max, the result string won't fit + * anyway. If format strings are added, made sure the padding below is + * enough */ + char *new_format = (char *) malloc(max + 11); + size_t i, j, format_length = strlen(format); + apr_size_t return_value; + int length_written; + + for (i = 0, j = 0; (i < format_length && j < max);) { + if (format[i] != '%') { + new_format[j++] = format[i++]; + continue; + } + switch (format[i+1]) { + case 'C': + length_written = apr_snprintf(new_format + j, max - j, "%2d", + (tm->tm_year + 1970)/100); + j = (length_written == -1) ? max : (j + length_written); + i += 2; + break; + case 'D': + /* Is this locale dependent? Shouldn't be... + Also note the year 2000 exposure here */ + memcpy(new_format + j, "%m/%d/%y", 8); + i += 2; + j += 8; + break; + case 'r': + memcpy(new_format + j, "%I:%M:%S %p", 11); + i += 2; + j += 11; + break; + case 'R': + memcpy(new_format + j, "%H:%M", 5); + i += 2; + j += 5; + break; + case 'T': + memcpy(new_format + j, "%H:%M:%S", 8); + i += 2; + j += 8; + break; + case 'e': + length_written = apr_snprintf(new_format + j, max - j, "%2d", + tm->tm_mday); + j = (length_written == -1) ? max : (j + length_written); + i += 2; + break; + default: + /* We know we can advance two characters forward here. Also + * makes sure that %% is preserved. */ + new_format[j++] = format[i++]; + new_format[j++] = format[i++]; + } + } + if (j >= max) { + *s = '\0'; /* Defensive programming, okay since output is undefined*/ + return_value = 0; + } else { + new_format[j] = '\0'; + return_value = strftime(s, max, new_format, tm); + } + free(new_format); + return return_value; +} + +#endif + + +APR_DECLARE(apr_status_t) apr_strftime(char *s, apr_size_t *retsize, + apr_size_t max, const char *format, + apr_time_exp_t *xt) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + struct tm tm; + memset(&tm, 0, sizeof tm); + tm.tm_sec = xt->tm_sec; + tm.tm_min = xt->tm_min; + tm.tm_hour = xt->tm_hour; + tm.tm_mday = xt->tm_mday; + tm.tm_mon = xt->tm_mon; + tm.tm_year = xt->tm_year; + tm.tm_wday = xt->tm_wday; + tm.tm_yday = xt->tm_yday; + tm.tm_isdst = xt->tm_isdst; + (*retsize) = win32_strftime_extra(s, max, format, &tm); + return APR_SUCCESS; +#endif +} diff --git a/srclib/apr/user/netware/groupinfo.c b/srclib/apr/user/netware/groupinfo.c new file mode 100644 index 0000000000..5e247474f6 --- /dev/null +++ b/srclib/apr/user/netware/groupinfo.c @@ -0,0 +1,41 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_private.h" +#ifdef HAVE_GRP_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include /* for _POSIX_THREAD_SAFE_FUNCTIONS */ +#endif + +APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid, + apr_pool_t *p) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, + const char *groupname, apr_pool_t *p) +{ + return APR_ENOTIMPL; +} diff --git a/srclib/apr/user/netware/userinfo.c b/srclib/apr/user/netware/userinfo.c new file mode 100644 index 0000000000..a960406b4e --- /dev/null +++ b/srclib/apr/user/netware/userinfo.c @@ -0,0 +1,70 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_private.h" +#ifdef HAVE_PWD_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include /* for _POSIX_THREAD_SAFE_FUNCTIONS */ +#endif + +#define PWBUF_SIZE 512 + +static apr_status_t getpwnam_safe(const char *username, + struct passwd *pw, + char pwbuf[PWBUF_SIZE]) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p) +{ + return APR_ENOTIMPL; +} + + + +APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid, + apr_gid_t *gid, + apr_pool_t *p) +{ + return APR_ENOTIMPL; +} + + + + +APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid, + const char *username, apr_pool_t *p) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p) +{ + return APR_ENOTIMPL; +} + diff --git a/srclib/apr/user/unix/groupinfo.c b/srclib/apr/user/unix/groupinfo.c new file mode 100644 index 0000000000..91ef4df0df --- /dev/null +++ b/srclib/apr/user/unix/groupinfo.c @@ -0,0 +1,67 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_private.h" +#ifdef HAVE_GRP_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include /* for _POSIX_THREAD_SAFE_FUNCTIONS */ +#endif + +APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid, + apr_pool_t *p) +{ + struct group *gr; + +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRGID_R) + struct group grp; + char grbuf[512]; + + if (getgrgid_r(groupid, &grp, grbuf, sizeof(grbuf), &gr)) { +#else + if ((gr = getgrgid(groupid)) == NULL) { +#endif + return errno; + } + *groupname = apr_pstrdup(p, gr->gr_name); + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *groupid, + const char *groupname, apr_pool_t *p) +{ + struct group *gr; + +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETGRNAM_R) + struct group grp; + char grbuf[512]; + + if (getgrnam_r(groupname, &grp, grbuf, sizeof(grbuf), &gr)) { +#else + if ((gr = getgrnam(groupname)) == NULL) { +#endif + return errno; + } + *groupid = gr->gr_gid; + return APR_SUCCESS; +} diff --git a/srclib/apr/user/unix/userinfo.c b/srclib/apr/user/unix/userinfo.c new file mode 100644 index 0000000000..a15b22184c --- /dev/null +++ b/srclib/apr/user/unix/userinfo.c @@ -0,0 +1,126 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_private.h" +#ifdef HAVE_PWD_H +#include +#endif +#if APR_HAVE_SYS_TYPES_H +#include +#endif +#if APR_HAVE_UNISTD_H +#include /* for _POSIX_THREAD_SAFE_FUNCTIONS */ +#endif +#define APR_WANT_MEMFUNC +#include "apr_want.h" + +#define PWBUF_SIZE 512 + +static apr_status_t getpwnam_safe(const char *username, + struct passwd *pw, + char pwbuf[PWBUF_SIZE]) +{ + struct passwd *pwptr; +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWNAM_R) + /* IRIX getpwnam_r() returns 0 and sets pwptr to NULL on failure */ + if (!getpwnam_r(username, pw, pwbuf, PWBUF_SIZE, &pwptr) && pwptr) { + /* nothing extra to do on success */ +#else + if ((pwptr = getpwnam(username)) != NULL) { + memcpy(pw, pwptr, sizeof *pw); +#endif + } + else { + if (errno == 0) { + /* this can happen with getpwnam() on FreeBSD 4.3 */ + return APR_EGENERAL; + } + return errno; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p) +{ + struct passwd pw; + char pwbuf[PWBUF_SIZE]; + apr_status_t rv; + + if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS) + return rv; + +#ifdef OS2 + /* Need to manually add user name for OS/2 */ + *dirname = apr_pstrcat(p, pw.pw_dir, pw.pw_name, NULL); +#else + *dirname = apr_pstrdup(p, pw.pw_dir); +#endif + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid, + apr_gid_t *gid, + apr_pool_t *p) +{ + *uid = getuid(); + *gid = getgid(); + + return APR_SUCCESS; +} + + + + +APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid, + const char *username, apr_pool_t *p) +{ + struct passwd pw; + char pwbuf[PWBUF_SIZE]; + apr_status_t rv; + + if ((rv = getpwnam_safe(username, &pw, pwbuf)) != APR_SUCCESS) + return rv; + + *uid = pw.pw_uid; + *gid = pw.pw_gid; + + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p) +{ + struct passwd *pw; +#if APR_HAS_THREADS && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_GETPWUID_R) + struct passwd pwd; + char pwbuf[PWBUF_SIZE]; + + if (getpwuid_r(userid, &pwd, pwbuf, sizeof(pwbuf), &pw)) { +#else + if ((pw = getpwuid(userid)) == NULL) { +#endif + return errno; + } + *username = apr_pstrdup(p, pw->pw_name); + return APR_SUCCESS; +} diff --git a/srclib/apr/user/win32/groupinfo.c b/srclib/apr/user/win32/groupinfo.c new file mode 100644 index 0000000000..622b9aa1c0 --- /dev/null +++ b/srclib/apr/user/win32/groupinfo.c @@ -0,0 +1,100 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_private.h" +#if APR_HAVE_SYS_TYPES_H +#include +#endif + +APR_DECLARE(apr_status_t) apr_gid_get(apr_gid_t *gid, + const char *groupname, apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + SID_NAME_USE sidtype; + char anydomain[256]; + char *domain; + DWORD sidlen = 0; + DWORD domlen = sizeof(anydomain); + DWORD rv; + char *pos; + + if (pos = strchr(groupname, '/')) { + domain = apr_pstrndup(p, groupname, pos - groupname); + groupname = pos + 1; + } + else if (pos = strchr(groupname, '\\')) { + domain = apr_pstrndup(p, groupname, pos - groupname); + groupname = pos + 1; + } + else { + domain = NULL; + } + /* Get nothing on the first pass ... need to size the sid buffer + */ + rv = LookupAccountName(domain, groupname, domain, &sidlen, + anydomain, &domlen, &sidtype); + if (sidlen) { + /* Give it back on the second pass + */ + *gid = apr_palloc(p, sidlen); + domlen = sizeof(anydomain); + rv = LookupAccountName(domain, groupname, *gid, &sidlen, + anydomain, &domlen, &sidtype); + } + if (!sidlen || !rv) { + return apr_get_os_error(); + } + return APR_SUCCESS; +#endif +} + +APR_DECLARE(apr_status_t) apr_gid_name_get(char **groupname, apr_gid_t groupid, apr_pool_t *p) +{ +#ifdef _WIN32_WCE + *groupname = apr_pstrdup(p, "Administrators"); +#else + SID_NAME_USE type; + char name[MAX_PATH], domain[MAX_PATH]; + DWORD cbname = sizeof(name), cbdomain = sizeof(domain); + if (!groupid) + return APR_EINVAL; + if (!LookupAccountSid(NULL, groupid, name, &cbname, domain, &cbdomain, &type)) + return apr_get_os_error(); + if (type != SidTypeGroup && type != SidTypeWellKnownGroup + && type != SidTypeAlias) + return APR_EINVAL; + *groupname = apr_pstrdup(p, name); +#endif + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_gid_compare(apr_gid_t left, apr_gid_t right) +{ + if (!left || !right) + return APR_EINVAL; +#ifndef _WIN32_WCE + if (!IsValidSid(left) || !IsValidSid(right)) + return APR_EINVAL; + if (!EqualSid(left, right)) + return APR_EMISMATCH; +#endif + return APR_SUCCESS; +} diff --git a/srclib/apr/user/win32/userinfo.c b/srclib/apr/user/win32/userinfo.c new file mode 100644 index 0000000000..a102470c18 --- /dev/null +++ b/srclib/apr/user/win32/userinfo.c @@ -0,0 +1,279 @@ +/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_private.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_user.h" +#include "apr_arch_file_io.h" +#if APR_HAVE_SYS_TYPES_H +#include +#endif + +#ifndef _WIN32_WCE +/* Internal sid binary to string translation, see MSKB Q131320. + * Several user related operations require our SID to access + * the registry, but in a string format. All error handling + * depends on IsValidSid(), which internally we better test long + * before we get here! + */ +void get_sid_string(char *buf, apr_size_t blen, apr_uid_t id) +{ + PSID_IDENTIFIER_AUTHORITY psia; + DWORD nsa; + DWORD sa; + int slen; + + /* Determine authority values (these is a big-endian value, + * and NT records the value as hex if the value is > 2^32.) + */ + psia = GetSidIdentifierAuthority(id); + nsa = (DWORD)(psia->Value[5]) + ((DWORD)(psia->Value[4]) << 8) + + ((DWORD)(psia->Value[3]) << 16) + ((DWORD)(psia->Value[2]) << 24); + sa = (DWORD)(psia->Value[1]) + ((DWORD)(psia->Value[0]) << 8); + if (sa) { + slen = apr_snprintf(buf, blen, "S-%lu-0x%04x%08x", + SID_REVISION, sa, nsa); + } else { + slen = apr_snprintf(buf, blen, "S-%lu-%lu", + SID_REVISION, nsa); + } + + /* Now append all the subauthority strings. + */ + nsa = *GetSidSubAuthorityCount(id); + for (sa = 0; sa < nsa; ++sa) { + slen += apr_snprintf(buf + slen, blen - slen, "-%lu", + *GetSidSubAuthority(id, sa)); + } +} +#endif +/* Query the ProfileImagePath from the version-specific branch, where the + * regkey uses the user's name on 9x, and user's sid string on NT. + */ +APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname, + const char *username, + apr_pool_t *p) +{ +#ifdef _WIN32_WCE + *dirname = apr_pstrdup(p, "/My Documents"); + return APR_SUCCESS; +#else + apr_status_t rv; + char regkey[MAX_PATH * 2]; + char *fixch; + DWORD keylen; + DWORD type; + HKEY key; + + if (apr_os_level >= APR_WIN_NT) { + apr_uid_t uid; + apr_gid_t gid; + + if ((rv = apr_uid_get(&uid, &gid, username, p)) != APR_SUCCESS) + return rv; + + strcpy(regkey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\" + "ProfileList\\"); + keylen = (DWORD)strlen(regkey); + get_sid_string(regkey + keylen, sizeof(regkey) - keylen, uid); + } + else { + strcpy(regkey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\" + "ProfileList\\"); + keylen = (DWORD)strlen(regkey); + apr_cpystrn(regkey + keylen, username, sizeof(regkey) - keylen); + } + + if ((rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey, 0, + KEY_QUERY_VALUE, &key)) != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rv); + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + keylen = sizeof(regkey); + rv = RegQueryValueExW(key, L"ProfileImagePath", NULL, &type, + (void*)regkey, &keylen); + RegCloseKey(key); + if (rv != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rv); + if (type == REG_SZ) { + char retdir[MAX_PATH]; + if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir), + (apr_wchar_t*)regkey)) != APR_SUCCESS) + return rv; + *dirname = apr_pstrdup(p, retdir); + } + else if (type == REG_EXPAND_SZ) { + apr_wchar_t path[MAX_PATH]; + char retdir[MAX_PATH]; + ExpandEnvironmentStringsW((apr_wchar_t*)regkey, path, sizeof(path)); + if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir), path)) + != APR_SUCCESS) + return rv; + *dirname = apr_pstrdup(p, retdir); + } + else + return APR_ENOENT; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + keylen = sizeof(regkey); + rv = RegQueryValueEx(key, "ProfileImagePath", NULL, &type, + (void*)regkey, &keylen); + RegCloseKey(key); + if (rv != ERROR_SUCCESS) + return APR_FROM_OS_ERROR(rv); + if (type == REG_SZ) { + *dirname = apr_pstrdup(p, regkey); + } + else if (type == REG_EXPAND_SZ) { + char path[MAX_PATH]; + ExpandEnvironmentStrings(regkey, path, sizeof(path)); + *dirname = apr_pstrdup(p, path); + } + else + return APR_ENOENT; + } +#endif /* APR_HAS_ANSI_FS */ + for (fixch = *dirname; *fixch; ++fixch) + if (*fixch == '\\') + *fixch = '/'; + return APR_SUCCESS; +#endif /* _WIN32_WCE */ +} + +APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid, + apr_gid_t *gid, + apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + HANDLE threadtok; + DWORD needed; + TOKEN_USER *usr; + TOKEN_PRIMARY_GROUP *grp; + + if(!OpenProcessToken(GetCurrentProcess(), STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY, &threadtok)) { + return apr_get_os_error(); + } + + *uid = NULL; + if (!GetTokenInformation(threadtok, TokenUser, NULL, 0, &needed) + && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + && (usr = apr_palloc(p, needed)) + && GetTokenInformation(threadtok, TokenUser, usr, needed, &needed)) + *uid = usr->User.Sid; + else + return apr_get_os_error(); + + if (!GetTokenInformation(threadtok, TokenPrimaryGroup, NULL, 0, &needed) + && (GetLastError() == ERROR_INSUFFICIENT_BUFFER) + && (grp = apr_palloc(p, needed)) + && GetTokenInformation(threadtok, TokenPrimaryGroup, grp, needed, &needed)) + *gid = grp->PrimaryGroup; + else + return apr_get_os_error(); + + return APR_SUCCESS; +#endif +} + +APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid, + const char *username, apr_pool_t *p) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + SID_NAME_USE sidtype; + char anydomain[256]; + char *domain; + DWORD sidlen = 0; + DWORD domlen = sizeof(anydomain); + DWORD rv; + char *pos; + + if (pos = strchr(username, '/')) { + domain = apr_pstrndup(p, username, pos - username); + username = pos + 1; + } + else if (pos = strchr(username, '\\')) { + domain = apr_pstrndup(p, username, pos - username); + username = pos + 1; + } + else { + domain = NULL; + } + /* Get nothing on the first pass ... need to size the sid buffer + */ + rv = LookupAccountName(domain, username, domain, &sidlen, + anydomain, &domlen, &sidtype); + if (sidlen) { + /* Give it back on the second pass + */ + *uid = apr_palloc(p, sidlen); + domlen = sizeof(anydomain); + rv = LookupAccountName(domain, username, *uid, &sidlen, + anydomain, &domlen, &sidtype); + } + if (!sidlen || !rv) { + return apr_get_os_error(); + } + /* There doesn't seem to be a simple way to retrieve the primary group sid + */ + *gid = NULL; + return APR_SUCCESS; +#endif +} + +APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid, + apr_pool_t *p) +{ +#ifdef _WIN32_WCE + *username = apr_pstrdup(p, "Administrator"); + return APR_SUCCESS; +#else + SID_NAME_USE type; + char name[MAX_PATH], domain[MAX_PATH]; + DWORD cbname = sizeof(name), cbdomain = sizeof(domain); + if (!userid) + return APR_EINVAL; + if (!LookupAccountSid(NULL, userid, name, &cbname, domain, &cbdomain, &type)) + return apr_get_os_error(); + if (type != SidTypeUser && type != SidTypeAlias && type != SidTypeWellKnownGroup) + return APR_EINVAL; + *username = apr_pstrdup(p, name); + return APR_SUCCESS; +#endif +} + +APR_DECLARE(apr_status_t) apr_uid_compare(apr_uid_t left, apr_uid_t right) +{ + if (!left || !right) + return APR_EINVAL; +#ifndef _WIN32_WCE + if (!IsValidSid(left) || !IsValidSid(right)) + return APR_EINVAL; + if (!EqualSid(left, right)) + return APR_EMISMATCH; +#endif + return APR_SUCCESS; +} + -- GitLab