diff options
40 files changed, 596 insertions, 177 deletions
diff --git a/.cvsignore b/.cvsignore index 4b17e2735..13ef1e0e2 100644 --- a/.cvsignore +++ b/.cvsignore @@ -6,6 +6,7 @@ config.status configure libtool apr-config +apr-*-config apr-config.out LibD LibR @@ -38,4 +39,5 @@ build-outputs.mk *.bbg *.da coverage -apr.pc +apr*.pc +apr.spec @@ -1,3 +1,37 @@ +Changes for APR 1.0.1 + + *) Fix HUP return codes in pollset when using KQueue. + [Paul Querna] + + *) Prevent unbounded memory use during repeated operations on a hash table. + [Julian Foad <julianfoad btopenworld.com> + + *) 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 <steve.hay uk.radan.com>] + + *) 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 diff --git a/Makefile.in b/Makefile.in index 4397c96fc..0c29cba8a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -76,7 +76,7 @@ install: $(TARGET_LIB) apr-config.out build/apr_rules.out for f in libtool shlibtool; do \ if test -f $${f}; then $(INSTALL) -m 755 $${f} $(DESTDIR)$(installbuilddir); fi; \ done - $(INSTALL) -m 755 build/mkdir.sh $(DESTDIR)$(installbuilddir) + $(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 @@ -1,5 +1,5 @@ APACHE PORTABLE RUNTIME (APR) LIBRARY STATUS: -*-text-*- -Last modified at [$Date: 2004/06/30 11:29:48 $] +Last modified at [$Date$] Releases: @@ -23,10 +23,7 @@ Bundled with httpd 2.0a1 : released March 10, 2000 -RELEASE 0.9 SHOWSTOPPERS: - - -RELEASE 1.0 SHOWSTOPPERS: +RELEASE 1.0.1 SHOWSTOPPERS: CURRENT VOTES: diff --git a/atomic/netware/apr_atomic.c b/atomic/netware/apr_atomic.c index 17ffe14d5..069b1bd16 100644 --- a/atomic/netware/apr_atomic.c +++ b/atomic/netware/apr_atomic.c @@ -60,8 +60,7 @@ APR_DECLARE(apr_uint32_t) apr_atomic_xchg32(volatile apr_uint32_t *mem, apr_uint APR_DECLARE(int) apr_atomic_dec32(volatile apr_uint32_t *mem) { - atomic_dec((unsigned long *)mem); - return *mem; + return (atomic_xchgadd((unsigned long *)mem, 0xFFFFFFFF) - 1); } APR_DECLARE(void *) apr_atomic_casptr(volatile void **mem, void *with, const void *cmp) diff --git a/atomic/unix/apr_atomic.c b/atomic/unix/apr_atomic.c index 5827ba091..bf457c1ea 100644 --- a/atomic/unix/apr_atomic.c +++ b/atomic/unix/apr_atomic.c @@ -21,6 +21,12 @@ #include <stdlib.h> +#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) diff --git a/atomic/win32/apr_atomic.c b/atomic/win32/apr_atomic.c index d83d60c89..b42a2028e 100644 --- a/atomic/win32/apr_atomic.c +++ b/atomic/win32/apr_atomic.c @@ -40,7 +40,11 @@ typedef WINBASEAPI void * (WINAPI * apr_atomic_win32_ptr_ptr_ptr_fn) 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 */ @@ -48,7 +52,11 @@ APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint3 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) diff --git a/build/apr_hints.m4 b/build/apr_hints.m4 index 5aa03c952..edd5f9770 100644 --- a/build/apr_hints.m4 +++ b/build/apr_hints.m4 @@ -131,6 +131,9 @@ dnl # Not a problem in 10.20. Otherwise, who knows? ;; *-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]) diff --git a/build/jlibtool.c b/build/jlibtool.c index 6b1c35d69..5f38b6db6 100644 --- a/build/jlibtool.c +++ b/build/jlibtool.c @@ -66,7 +66,8 @@ # define DYNAMIC_LINK_OPTS "-flat_namespace -undefined suppress" # define dynamic_link_version_func darwin_dynamic_link_function # define DYNAMIC_INSTALL_NAME "-install_name" -//-install_name /Users/jerenk/apache-2.0-cvs/lib/libapr.0.dylib -compatibility_version 1 -current_version 1.0 +/*-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__) @@ -80,8 +81,13 @@ # define RANLIB "ranlib" # define PIC_FLAG "-fPIC" # define RPATH "-rpath" -# define DYNAMIC_LINK_OPTS "-shared" +# 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(_OSD_POSIX) @@ -92,11 +98,30 @@ # define OBJECT_EXT "o" # define LIBRARIAN "ar" # define LIBRARIAN_OPTS "cr" -# define DYNAMIC_LINK_OPTS "-G" +# 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 @@ -140,6 +165,14 @@ enum pic_mode_e { 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; @@ -383,6 +416,23 @@ int run_command(command_t *cmd_data, count_chars *cc) 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 +} + int parse_long_opt(char *arg, command_t *cmd_data) { char *equal_pos = strchr(arg, '='); @@ -427,6 +477,8 @@ int parse_long_opt(char *arg, command_t *cmd_data) 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 { return 0; } @@ -651,7 +703,7 @@ char *check_object_exists(command_t *cmd, const char *arg, int arglen) } if (!cmd->options.silent) { - printf("Checking: %s\n", newarg); + printf("Checking (obj): %s\n", newarg); } rv = stat(newarg, &sb); } @@ -672,7 +724,7 @@ char *check_object_exists(command_t *cmd, const char *arg, int arglen) * 1 - .libs suffix */ char *check_library_exists(command_t *cmd, const char *arg, int pathlen, - int libdircheck) + int libdircheck, enum lib_type *libtype) { char *newarg, *ext; int pass, rv, newpathlen; @@ -699,24 +751,29 @@ char *check_library_exists(command_t *cmd, const char *arg, int pathlen, 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: %s\n", newarg); + printf("Checking (lib): %s\n", newarg); } rv = stat(newarg, &sb); } @@ -729,6 +786,72 @@ char *check_library_exists(command_t *cmd, const char *arg, int pathlen, return NULL; } +/* Read the final install location and add it to runtime library search path. */ +#ifdef RPATH +void add_rpath(count_chars *cc, const char *arg) +{ + FILE *f; + char path[256]; + char *tmp; + int size=0; + + f = fopen(arg,"r"); + if (f == NULL) { + return; + } + fgets(path,sizeof(path), f); + fclose(f); + if (path[strlen(path)-1] == '\n') { + path[strlen(path)-1] = '\0'; + } + /* Check that we have an absolut path. + * Otherwise the file could be a GNU libtool file. + */ + if (path[0] != '/') { + return; + } +#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 + strcat(tmp, "="); + strcat(tmp, path); + + push_count_chars(cc, tmp); +} +#endif + +/* use -L -llibname to allow to use installed libraries */ +void add_minus_l(count_chars *cc, const char *arg) +{ + 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); + push_count_chars(cc, "-l"); + push_count_chars(cc, file); + } else { + push_count_chars(cc, arg); + } +} + void add_linker_flag_prefix(count_chars *cc, const char *arg) { #ifndef LINKER_FLAG_PREFIX @@ -747,6 +870,7 @@ 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) { @@ -788,22 +912,34 @@ int parse_input_file_name(char *arg, command_t *cmd_data) switch (cmd_data->mode) { case mLink: /* Try the .libs dir first! */ - newarg = check_library_exists(cmd_data, arg, pathlen, 1); + 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); + newarg = check_library_exists(cmd_data, arg, pathlen, 0, &libtype); if (!newarg) { printf("Can not find suitable library for %s\n", arg); exit(1); } } - if (cmd_data->mode != mLink) { - push_count_chars(cmd_data->arglist, newarg); + /* 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); +#else + push_count_chars(cmd_data->shared_opts.dependencies, newarg); +#endif +#ifdef RPATH + if (libtype == type_DYNAMIC_LIB) { + add_rpath(cmd_data->shared_opts.dependencies, arg); } +#endif break; case mInstall: /* If we've already recorded a library to install, we're most @@ -959,7 +1095,7 @@ void parse_args(int argc, char *argv[], command_t *cmd_data) char *arg; int argused; - for (a=1; a < argc; a++) { + for (a = 1; a < argc; a++) { arg = argv[a]; argused = 1; @@ -985,6 +1121,10 @@ void parse_args(int argc, char *argv[], command_t *cmd_data) /* 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 { @@ -1349,9 +1489,6 @@ int run_mode(command_t *cmd_data) lib_args[2] = NULL; external_spawn(cmd_data, RANLIB, lib_args); #endif - if (!cmd_data->options.dry_run) { - //link( - } } if (cmd_data->output == otDynamicLibraryOnly || @@ -1446,6 +1583,27 @@ int ensure_fake_uptodate(command_t *cmd_data) touch_args[2] = NULL; return external_spawn(cmd_data, "touch", touch_args); } +#ifdef RPATH +/* 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)); + } +} +#endif int main(int argc, char *argv[]) { @@ -1488,7 +1646,11 @@ int main(int argc, char *argv[]) rc = run_mode(&cmd_data); if (!rc) { +#ifdef RPATH + add_for_runtime(&cmd_data); +#else ensure_fake_uptodate(&cmd_data); +#endif } cleanup_tmp_dirs(&cmd_data); diff --git a/configure.in b/configure.in index 0722a3a68..227972a97 100644 --- a/configure.in +++ b/configure.in @@ -155,6 +155,10 @@ case $host in 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 diff --git a/file_io/netware/mktemp.c b/file_io/netware/mktemp.c index 884a8c40b..58e89386b 100644 --- a/file_io/netware/mktemp.c +++ b/file_io/netware/mktemp.c @@ -27,7 +27,7 @@ APR_DECLARE(apr_status_t) apr_file_mktemp(apr_file_t **fp, char *template, apr_i apr_status_t rv; flags = (!flags) ? APR_CREATE | APR_READ | APR_WRITE | - APR_DELONCLOSE : flags; + APR_DELONCLOSE : flags & ~APR_EXCL; fd = mkstemp(template); if (fd == -1) { diff --git a/file_io/os2/filesys.c b/file_io/os2/filesys.c index b323e488d..ef597b38e 100644 --- a/file_io/os2/filesys.c +++ b/file_io/os2/filesys.c @@ -94,12 +94,13 @@ apr_status_t filepath_drive_get(char **rootpath, char drive, apr_status_t filepath_root_case(char **rootpath, char *root, apr_pool_t *p) { - char path[APR_PATH_MAX]; - - strcpy(path, root); - if (path[1] == ':') - path[0] = apr_toupper(path[0]); - *rootpath = apr_pstrdup(p, path); + 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; } diff --git a/file_io/unix/readwrite.c b/file_io/unix/readwrite.c index 1e6a6e665..98a11421d 100644 --- a/file_io/unix/readwrite.c +++ b/file_io/unix/readwrite.c @@ -24,9 +24,6 @@ #define USE_WAIT_FOR_IO #endif -/* problems: - * 1) ungetchar not used for buffered files - */ APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) { apr_ssize_t rv; @@ -311,18 +308,65 @@ APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) return APR_SUCCESS; } - while (str < final) { /* leave room for trailing '\0' */ - nbytes = 1; - rv = apr_file_read(thefile, str, &nbytes); - if (rv != APR_SUCCESS) { - break; + /* 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; } - if (*str == '\n') { + + 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; - 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. */ diff --git a/file_io/win32/dir.c b/file_io/win32/dir.c index ab2d08047..19fe15e8c 100644 --- a/file_io/win32/dir.c +++ b/file_io/win32/dir.c @@ -49,7 +49,7 @@ APR_DECLARE(apr_status_t) apr_dir_open(apr_dir_t **new, const char *dirname, { apr_status_t rv; - int len = strlen(dirname); + 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. @@ -243,7 +243,7 @@ APR_DECLARE(apr_status_t) apr_dir_read(apr_finfo_t *finfo, apr_int32_t wanted, #else char fspec[APR_PATH_MAX]; #endif - int dirlen = strlen(thedir->dirname); + apr_size_t dirlen = strlen(thedir->dirname); if (dirlen >= sizeof(fspec)) dirlen = sizeof(fspec) - 1; apr_cpystrn(fspec, thedir->dirname, sizeof(fspec)); diff --git a/file_io/win32/filedup.c b/file_io/win32/filedup.c index 57c57ea02..63aa25089 100644 --- a/file_io/win32/filedup.c +++ b/file_io/win32/filedup.c @@ -44,6 +44,13 @@ APR_DECLARE(apr_status_t) apr_file_dup(apr_file_t **new_file, (*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); @@ -118,6 +125,13 @@ APR_DECLARE(apr_status_t) apr_file_dup2(apr_file_t *new_file, 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) */ } diff --git a/file_io/win32/open.c b/file_io/win32/open.c index e937801f8..1b950fc21 100644 --- a/file_io/win32/open.c +++ b/file_io/win32/open.c @@ -47,7 +47,7 @@ apr_status_t utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen, * Note that the \\?\ form only works for local drive paths, and * \\?\UNC\ is needed UNC paths. */ - int srcremains = strlen(srcstr) + 1; + apr_size_t srcremains = strlen(srcstr) + 1; apr_wchar_t *t = retstr; apr_status_t rv; @@ -101,7 +101,7 @@ apr_status_t unicode_to_utf8_path(char* retstr, apr_size_t retlen, * then transform \\'s back into /'s since the \\?\ form never * allows '/' path seperators, and APR always uses '/'s. */ - int srcremains = wcslen(srcstr) + 1; + apr_size_t srcremains = wcslen(srcstr) + 1; apr_status_t rv; char *t = retstr; if (srcstr[0] == L'\\' && srcstr[1] == L'\\' && @@ -324,6 +324,8 @@ APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, else { return APR_EACCES; } + if (flag & APR_READCONTROL) + oflags |= READ_CONTROL; } if (flag & APR_XTHREAD) { diff --git a/file_io/win32/readwrite.c b/file_io/win32/readwrite.c index b8a5e4be8..7a5931387 100644 --- a/file_io/win32/readwrite.c +++ b/file_io/win32/readwrite.c @@ -27,9 +27,10 @@ * 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, apr_size_t *nbytes) +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 */ @@ -68,7 +69,8 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le file->pOverlapped->OffsetHigh = (DWORD)(file->filePtr >> 32); } - rv = ReadFile(file->filehand, buf, len, nbytes, file->pOverlapped); + *nbytes = 0; + rv = ReadFile(file->filehand, buf, len, (LPDWORD)nbytes, file->pOverlapped); if (!rv) { rv = apr_get_os_error(); @@ -85,7 +87,7 @@ static apr_status_t read_with_timeout(apr_file_t *file, void *buf, apr_size_t le switch (rv) { case WAIT_OBJECT_0: GetOverlappedResult(file->filehand, file->pOverlapped, - nbytes, TRUE); + (LPDWORD)nbytes, TRUE); rv = APR_SUCCESS; break; case WAIT_TIMEOUT: @@ -286,7 +288,7 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a thefile->pOverlapped->Offset = (DWORD)thefile->filePtr; thefile->pOverlapped->OffsetHigh = (DWORD)(thefile->filePtr >> 32); } - rv = WriteFile(thefile->filehand, buf, *nbytes, &bwrote, + rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, thefile->pOverlapped); if (thefile->append) { apr_file_unlock(thefile); @@ -294,7 +296,7 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a } } else { - rv = WriteFile(thefile->filehand, buf, *nbytes, &bwrote, + rv = WriteFile(thefile->filehand, buf, (DWORD)*nbytes, &bwrote, thefile->pOverlapped); } if (rv) { @@ -309,7 +311,7 @@ APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, a rv = WaitForSingleObject(thefile->pOverlapped->hEvent, INFINITE); switch (rv) { case WAIT_OBJECT_0: - GetOverlappedResult(thefile->filehand, thefile->pOverlapped, nbytes, TRUE); + GetOverlappedResult(thefile->filehand, thefile->pOverlapped, (LPDWORD)nbytes, TRUE); rv = APR_SUCCESS; break; case WAIT_TIMEOUT: @@ -343,7 +345,7 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, { apr_status_t rv = APR_SUCCESS; apr_size_t i; - DWORD bwrote = 0; + apr_size_t bwrote = 0; char *buf; *nbytes = 0; @@ -361,7 +363,7 @@ APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) { - DWORD len = 1; + apr_size_t len = 1; return apr_file_write(thefile, &ch, &len); } @@ -375,7 +377,7 @@ APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) { apr_status_t rc; - int bread; + apr_size_t bread; bread = 1; rc = apr_file_read(thefile, ch, &bread); @@ -393,7 +395,7 @@ APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) { - DWORD len = strlen(str); + apr_size_t len = strlen(str); return apr_file_write(thefile, str, &len); } @@ -431,13 +433,34 @@ APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) { if (thefile->buffered) { - DWORD written = 0; + DWORD numbytes, written = 0; apr_status_t rc = 0; + char *buffer; + apr_size_t bytesleft; if (thefile->direction == 1 && thefile->bufpos) { - if (!WriteFile(thefile->filehand, thefile->buffer, thefile->bufpos, &written, NULL)) - rc = apr_get_os_error(); - thefile->filePtr += written; + 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; diff --git a/include/apr.hw b/include/apr.hw index 53ee01137..7797ed97d 100644 --- a/include/apr.hw +++ b/include/apr.hw @@ -363,7 +363,7 @@ typedef int gid_t; #endif #ifndef WS2TCPIP_INLINE -6:09 PM 11/16/2003#define IN6_IS_ADDR_V4MAPPED(a) \ +#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 diff --git a/include/apr_network_io.h b/include/apr_network_io.h index b160b3f7f..0157a46b6 100644 --- a/include/apr_network_io.h +++ b/include/apr_network_io.h @@ -456,7 +456,8 @@ APR_DECLARE(apr_status_t) apr_socket_data_set(apr_socket_t *sock, void *data, * @remark * <PRE> * This functions acts like a blocking write by default. To change - * this behavior, use apr_socket_timeout_set(). + * 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. * @@ -475,7 +476,8 @@ APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, * @remark * <PRE> * This functions acts like a blocking write by default. To change - * this behavior, use apr_socket_timeout_set(). + * 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. @@ -526,7 +528,8 @@ APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, * 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(). + * this behavior, use apr_socket_timeout_set() or the + * APR_SO_NONBLOCK socket option. * The number of bytes actually sent is stored in argument 5. */ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, @@ -547,8 +550,9 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, * @remark * <PRE> * This functions acts like a blocking read by default. To change - * this behavior, use apr_socket_timeout_set(). - * The number of bytes actually sent is stored in argument 3. + * 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. @@ -568,6 +572,11 @@ APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, * 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. diff --git a/include/apr_shm.h b/include/apr_shm.h index 64dbafe1b..88d184b0e 100644 --- a/include/apr_shm.h +++ b/include/apr_shm.h @@ -114,6 +114,7 @@ APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m); * 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); diff --git a/include/apr_version.h b/include/apr_version.h index af307b48f..08d5f3a26 100644 --- a/include/apr_version.h +++ b/include/apr_version.h @@ -60,8 +60,13 @@ extern "C" { #define APR_MINOR_VERSION 0 /** patch level */ -#define APR_PATCH_VERSION 0 +#define APR_PATCH_VERSION 1 +/** + * This symbol is defined for internal, "development" copies of APR. + * This symbol should be #undef'd for releases. + */ +#define APR_IS_DEV_VERSION /** The formatted string of APR's version */ #define APR_VERSION_STRING \ diff --git a/include/arch/apr_private_common.h b/include/arch/apr_private_common.h index b2a02a8e4..912813b0d 100644 --- a/include/arch/apr_private_common.h +++ b/include/arch/apr_private_common.h @@ -33,4 +33,9 @@ apr_status_t apr_filepath_list_merge_impl(char **liststr, 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/include/arch/netware/apr_private.h b/include/arch/netware/apr_private.h index 5251cb0e2..917b6fa45 100644 --- a/include/arch/netware/apr_private.h +++ b/include/arch/netware/apr_private.h @@ -63,6 +63,8 @@ #define HAVE_SETENV 1 #define HAVE_UNSETENV 1 +#define HAVE_WRITEV 1 + /* 64-bit integer conversion function */ #define APR_INT64_STRFN strtoll @@ -172,6 +174,9 @@ void* getStatCache(); #define APR_OFF_T_STRFN strtol #endif +/* used to check DWORD overflow for 64bit compiles */ +#define APR_DWORD_MAX 0xFFFFFFFFUL + /* * Include common private declarations. */ diff --git a/include/arch/win32/apr_arch_threadproc.h b/include/arch/win32/apr_arch_threadproc.h index 6e8ac8d54..f752fd7df 100644 --- a/include/arch/win32/apr_arch_threadproc.h +++ b/include/arch/win32/apr_arch_threadproc.h @@ -54,6 +54,8 @@ struct apr_procattr_t { char *currdir; apr_int32_t cmdtype; apr_int32_t detached; + apr_child_errfn_t *errfn; + apr_int32_t errchk; }; struct apr_thread_once_t { diff --git a/include/arch/win32/apr_private.h b/include/arch/win32/apr_private.h index de23360b3..0dee29348 100644 --- a/include/arch/win32/apr_private.h +++ b/include/arch/win32/apr_private.h @@ -158,6 +158,9 @@ APR_DECLARE_DATA int errno; #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. */ diff --git a/memory/unix/apr_pools.c b/memory/unix/apr_pools.c index 2ed524eb3..9bf8fa290 100644 --- a/memory/unix/apr_pools.c +++ b/memory/unix/apr_pools.c @@ -139,9 +139,10 @@ APR_DECLARE(apr_pool_t *) apr_allocator_owner_get(apr_allocator_t *allocator) } APR_DECLARE(void) apr_allocator_max_free_set(apr_allocator_t *allocator, - apr_size_t size) + 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; @@ -168,7 +169,8 @@ static APR_INLINE apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) { apr_memnode_t *node, **ref; - apr_uint32_t i, index, max_index; + 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). @@ -181,6 +183,10 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) * 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. @@ -293,7 +299,7 @@ apr_memnode_t *allocator_alloc(apr_allocator_t *allocator, apr_size_t size) return NULL; node->next = NULL; - node->index = index; + node->index = (APR_UINT32_TRUNC_CAST)index; node->first_avail = (char *)node + APR_MEMNODE_T_SIZE; node->endp = (char *)node + size; @@ -582,7 +588,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size) { apr_memnode_t *active, *node; void *mem; - apr_uint32_t free_index; + apr_size_t free_index; size = APR_ALIGN_DEFAULT(size); active = pool->active; @@ -620,7 +626,7 @@ APR_DECLARE(void *) apr_palloc(apr_pool_t *pool, apr_size_t size) free_index = (APR_ALIGN(active->endp - active->first_avail + 1, BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; - active->free_index = free_index; + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; node = active->next; if (free_index >= node->free_index) return mem; @@ -877,7 +883,7 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) apr_size_t cur_len, size; char *strp; apr_pool_t *pool; - apr_uint32_t free_index; + apr_size_t free_index; pool = ps->pool; active = ps->node; @@ -907,7 +913,7 @@ static int psprintf_flush(apr_vformatter_buff_t *vbuff) free_index = (APR_ALIGN(active->endp - active->first_avail + 1, BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; - active->free_index = free_index; + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; node = active->next; if (free_index < node->free_index) { do { @@ -948,7 +954,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) char *strp; apr_size_t size; apr_memnode_t *active, *node; - apr_uint32_t free_index; + apr_size_t free_index; ps.node = active = pool->active; ps.pool = pool; @@ -1008,7 +1014,7 @@ APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *pool, const char *fmt, va_list ap) free_index = (APR_ALIGN(active->endp - active->first_avail + 1, BOUNDARY_SIZE) - BOUNDARY_SIZE) >> BOUNDARY_INDEX; - active->free_index = free_index; + active->free_index = (APR_UINT32_TRUNC_CAST)free_index; node = active->next; if (free_index >= node->free_index) diff --git a/misc/unix/charset.c b/misc/unix/charset.c index 5e1842fac..6acb4e157 100644 --- a/misc/unix/charset.c +++ b/misc/unix/charset.c @@ -55,7 +55,7 @@ APR_DECLARE(const char*) apr_os_default_encoding (apr_pool_t *pool) } if ('A' == 0x41) { - return "ISO8859-1"; /* not necessarily true */ + return "ISO-8859-1"; /* not necessarily true */ } return "unknown"; diff --git a/misc/unix/errorcodes.c b/misc/unix/errorcodes.c index 447b8d859..5c318d530 100644 --- a/misc/unix/errorcodes.c +++ b/misc/unix/errorcodes.c @@ -374,7 +374,13 @@ static char *native_strerror(apr_status_t statcode, char *buf, sprintf(err, "Native Error #%d", statcode); return stuffbuffer(buf, bufsize, err); #else - return stuffbuffer(buf, bufsize, strerror(statcode)); + const char *err = strerror(statcode); + if (err) { + return stuffbuffer(buf, bufsize, err); + } else { + return stuffbuffer(buf, bufsize, + "APR does not understand this error code"); + } #endif } #endif diff --git a/network_io/win32/sendrecv.c b/network_io/win32/sendrecv.c index d7a68cd9c..11573fdad 100644 --- a/network_io/win32/sendrecv.c +++ b/network_io/win32/sendrecv.c @@ -43,7 +43,7 @@ APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, int lasterror; DWORD dwBytes = 0; - wsaData.len = *len; + wsaData.len = (u_long)*len; wsaData.buf = (char*) buf; #ifndef _WIN32_WCE @@ -72,7 +72,7 @@ APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, DWORD dwBytes = 0; DWORD flags = 0; - wsaData.len = *len; + wsaData.len = (u_long)*len; wsaData.buf = (char*) buf; #ifndef _WIN32_WCE @@ -94,21 +94,49 @@ APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, char *buf, APR_DECLARE(apr_status_t) apr_socket_sendv(apr_socket_t *sock, const struct iovec *vec, - apr_int32_t nvec, apr_size_t *nbytes) + apr_int32_t in_vec, apr_size_t *nbytes) { apr_status_t rc = APR_SUCCESS; apr_ssize_t rv; - int i; + apr_size_t cur_len; + apr_int32_t nvec = 0; + int i, j = 0; DWORD dwBytes = 0; - WSABUF *pWsaBuf = (nvec <= WSABUF_ON_STACK) ? _alloca(sizeof(WSABUF) * (nvec)) - : malloc(sizeof(WSABUF) * (nvec)); + 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 < nvec; i++) { - pWsaBuf[i].buf = vec[i].iov_base; - pWsaBuf[i].len = vec[i].iov_len; + 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); @@ -140,7 +168,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendto(apr_socket_t *sock, { apr_ssize_t rv; - rv = sendto(sock->socketdes, buf, (*len), flags, + rv = sendto(sock->socketdes, buf, (int)*len, flags, (const struct sockaddr*)&where->sa, where->salen); if (rv == SOCKET_ERROR) { @@ -160,7 +188,7 @@ APR_DECLARE(apr_status_t) apr_socket_recvfrom(apr_sockaddr_t *from, { apr_ssize_t rv; - rv = recvfrom(sock->socketdes, buf, (*len), flags, + rv = recvfrom(sock->socketdes, buf, (int)*len, flags, (struct sockaddr*)&from->sa, &from->salen); if (rv == SOCKET_ERROR) { (*len) = 0; @@ -225,13 +253,13 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, apr_int32_t flags) { apr_status_t status = APR_SUCCESS; - apr_ssize_t rv; + apr_status_t rv; apr_off_t curoff = *offset; DWORD dwFlags = 0; - DWORD nbytes; + apr_size_t nbytes; TRANSMIT_FILE_BUFFERS tfb, *ptfb = NULL; int ptr = 0; - int bytes_to_send; /* Bytes to send out of the file (not including headers) */ + 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]; @@ -267,11 +295,15 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, /* 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, &ptfb->HeadLength, + 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); @@ -289,19 +321,25 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, sock->overlapped->hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); } while (bytes_to_send) { + DWORD xmitbytes; + if (bytes_to_send > MAX_SEGMENT_SIZE) { - nbytes = MAX_SEGMENT_SIZE; + xmitbytes = MAX_SEGMENT_SIZE; } else { /* Last call to TransmitFile() */ - nbytes = bytes_to_send; + 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, &ptfb->TailLength, + 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; @@ -323,7 +361,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, /* XXX BoundsChecker claims dwFlags must not be zero. */ rv = TransmitFile(sock->socketdes, /* socket */ file->filehand, /* open file descriptor of the file to be sent */ - nbytes, /* number of bytes to send. 0=send all */ + 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 */ @@ -341,7 +379,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, if (!disconnected) { if (!WSAGetOverlappedResult(sock->socketdes, sock->overlapped, - &nbytes, + &xmitbytes, FALSE, &dwFlags)) { status = apr_get_netos_error(); @@ -351,7 +389,7 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, * tracks bytes sent out of the file. */ else if (ptfb) { - nbytes -= (ptfb->HeadLength + ptfb->TailLength); + xmitbytes -= (ptfb->HeadLength + ptfb->TailLength); } } } @@ -374,9 +412,9 @@ APR_DECLARE(apr_status_t) apr_socket_sendfile(apr_socket_t *sock, if (status != APR_SUCCESS) break; - bytes_to_send -= nbytes; - curoff += nbytes; - *len += nbytes; + bytes_to_send -= xmitbytes; + curoff += xmitbytes; + *len += xmitbytes; /* Adjust len for any headers/trailers sent */ if (ptfb) { *len += (ptfb->HeadLength + ptfb->TailLength); diff --git a/poll/unix/poll.c b/poll/unix/poll.c index a04866fcd..b03b086f3 100644 --- a/poll/unix/poll.c +++ b/poll/unix/poll.c @@ -50,7 +50,9 @@ static apr_int16_t get_kqueue_revent(apr_int16_t event, apr_int16_t flags) rv |= APR_POLLIN; if (event & EVFILT_WRITE) rv |= APR_POLLOUT; - if (flags & EV_ERROR || flags & EV_EOF) + if (flags & EV_EOF) + rv |= APR_POLLHUP; + if (flags & EV_ERROR) rv |= APR_POLLERR; return rv; diff --git a/random/unix/apr_random.c b/random/unix/apr_random.c index b4daeb2f5..49af49079 100644 --- a/random/unix/apr_random.c +++ b/random/unix/apr_random.c @@ -111,8 +111,8 @@ APR_DECLARE(void) apr_random_init(apr_random_t *g,apr_pool_t *p, /2)*g->pool_hash->size*2; g->reseed_size = APR_RANDOM_DEFAULT_RESEED_SIZE; - g->H = apr_palloc(p,H_size(g)); - g->H_waiting = apr_palloc(p,H_size(g)); + 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; diff --git a/shmem/unix/shm.c b/shmem/unix/shm.c index ec6e2b41f..db0dc5e79 100644 --- a/shmem/unix/shm.c +++ b/shmem/unix/shm.c @@ -385,20 +385,28 @@ APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, * exist before calling ftok(). */ shmkey = ftok(filename, 1); if (shmkey == (key_t)-1) { - return errno; + goto shm_remove_failed; } + apr_file_close(file); + if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) { - return errno; + 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) { - return errno; + 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 */ diff --git a/tables/apr_hash.c b/tables/apr_hash.c index 8b8a7f3d1..fba4ff162 100644 --- a/tables/apr_hash.c +++ b/tables/apr_hash.c @@ -73,6 +73,7 @@ struct apr_hash_t { 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 */ @@ -92,6 +93,7 @@ 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); @@ -264,7 +266,10 @@ static apr_hash_entry_t **find_entry(apr_hash_t *ht, return hep; /* add a new entry for non-NULL values */ - he = apr_palloc(ht->pool, sizeof(*he)); + 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; @@ -286,6 +291,7 @@ APR_DECLARE(apr_hash_t *) apr_hash_copy(apr_pool_t *pool, 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; @@ -333,7 +339,10 @@ APR_DECLARE(void) apr_hash_set(apr_hash_t *ht, 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 { @@ -396,6 +405,7 @@ APR_DECLARE(apr_hash_t *) apr_hash_merge(apr_pool_t *p, 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; diff --git a/test/Makefile.in b/test/Makefile.in index 1c0c324d1..545536102 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -29,7 +29,8 @@ TARGETS = $(PROGRAMS) LOCAL_LIBS=../lib@APR_LIBNAME@.la CLEAN_TARGETS = testfile.tmp mod_test.slo proc_child@EXEEXT@ occhild@EXEEXT@ \ -readchild@EXEEXT@ tryread@EXEEXT@ sockchid@EXEEXT@ + readchild@EXEEXT@ tryread@EXEEXT@ sockchild@EXEEXT@ \ + globalmutexchild@EXEEXT@ lfstests/large.bin CLEAN_SUBDIRS = internal INCDIR=../include diff --git a/test/Makefile.win b/test/Makefile.win index 2772edff1..7e5644e9b 100644 --- a/test/Makefile.win +++ b/test/Makefile.win @@ -6,7 +6,8 @@ PROGRAMS = \ sendfile.exe \ proc_child.exe \ tryread.exe \ - occhild.exe\ + occhild.exe \ + readchild.exe \ sockchild.exe \ testlockperf.exe \ testshmproducer.exe \ @@ -40,6 +41,9 @@ tryread.exe: tryread.obj $(LOCAL_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) diff --git a/test/testrand2.c b/test/testrand2.c index 2d2e8a625..8d5b7b07c 100644 --- a/test/testrand2.c +++ b/test/testrand2.c @@ -1,55 +1,16 @@ -/* ==================================================================== - * The Apache Software License, Version 1.1 +/* Copyright 2000-2004 The Apache Software Foundation * - * Copyright (c) 2000-2003 The Apache Software Foundation. All rights - * reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * http://www.apache.org/licenses/LICENSE-2.0 * - * 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. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by the - * Apache Software Foundation (http://www.apache.org/)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Apache" and "Apache Software Foundation" must - * not be used to endorse or promote products derived from this - * software without prior written permission. For written - * permission, please contact apache@apache.org. - * - * 5. Products derived from this software may not be called "Apache", - * nor may "Apache" appear in their name, without prior written - * permission of the Apache Software Foundation. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED 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 APACHE SOFTWARE FOUNDATION OR - * ITS 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. - * ==================================================================== - * - * This software consists of voluntary contributions made by many - * individuals on behalf of the Apache Software Foundation. For more - * information on the Apache Software Foundation, please see - * <http://www.apache.org/>. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT 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" diff --git a/test/teststr.c b/test/teststr.c index 2121da41a..99aa8af41 100644 --- a/test/teststr.c +++ b/test/teststr.c @@ -150,6 +150,7 @@ static void snprintf_underflow(abts_case *tc, void *data) 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); @@ -159,6 +160,11 @@ static void string_error(abts_case *tc, void *data) 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 diff --git a/threadproc/beos/.cvsignore b/threadproc/beos/.cvsignore index 11f54a843..f82426797 100644 --- a/threadproc/beos/.cvsignore +++ b/threadproc/beos/.cvsignore @@ -1,5 +1,6 @@ Makefile apr_proc_stub *.lo +*.slo .libs .deps diff --git a/threadproc/win32/proc.c b/threadproc/win32/proc.c index e7c21c105..191d682d4 100644 --- a/threadproc/win32/proc.c +++ b/threadproc/win32/proc.c @@ -245,14 +245,14 @@ static char *apr_caret_escape_args(apr_pool_t *p, const char *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 */ + attr->errfn = errfn; 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 */ + attr->errchk = chk; return APR_SUCCESS; } @@ -311,6 +311,12 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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; @@ -352,6 +358,9 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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] == '"') { @@ -388,6 +397,9 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, { 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] == '"') { @@ -479,6 +491,12 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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; @@ -525,6 +543,12 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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; } } @@ -535,6 +559,12 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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; } } @@ -547,6 +577,12 @@ APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, 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; } } diff --git a/threadproc/win32/thread.c b/threadproc/win32/thread.c index 364d23274..95132cb4b 100644 --- a/threadproc/win32/thread.c +++ b/threadproc/win32/thread.c @@ -85,6 +85,7 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, { apr_status_t stat; unsigned temp; + HANDLE handle; (*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t)); @@ -95,7 +96,7 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, (*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; @@ -105,14 +106,14 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, * same size as the calling thread. */ #ifndef _WIN32_WCE - if (((*new)->td = (HANDLE)_beginthreadex(NULL, + 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 (((*new)->td = CreateThread(NULL, + if ((handle = CreateThread(NULL, attr && attr->stacksize > 0 ? attr->stacksize : 0, (unsigned int (APR_THREAD_FUNC *)(void *))dummy_worker, (*new), 0, &temp)) == 0) { @@ -120,9 +121,10 @@ APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, } #endif if (attr && attr->detach) { - CloseHandle((*new)->td); - (*new)->td = NULL; + CloseHandle(handle); } + else + (*new)->td = handle; return APR_SUCCESS; } @@ -132,10 +134,8 @@ APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, { thd->exitval = retval; apr_pool_destroy(thd->pool); + thd->pool = NULL; #ifndef _WIN32_WCE - if (thd->td) { - CloseHandle(thd->td); - } _endthreadex(0); #else ExitThread(0); @@ -146,15 +146,26 @@ APR_DECLARE(apr_status_t) apr_thread_exit(apr_thread_t *thd, APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd) { - apr_status_t rv; - + 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) { - *retval = thd->exitval; - return APR_SUCCESS; + /* If the thread_exit has been called */ + if (!thd->pool) + *retval = thd->exitval; + else + rv = APR_INCOMPLETE; } - /* Wait failed */ - return apr_get_os_error();; + 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) |