[moved to [EMAIL PROTECTED]
Justin Erenkrantz wrote:
>
> On Fri, Jun 28, 2002 at 04:40:11PM -0400, Jeff Trawick wrote:
> > > What is the change in the FreeBSD API?
> >
> > before the kernel we picked up Wednesday night: bytes to send includes
> > headers
> > after the kernel we picked up Wednesday night: bytes to send doesn't
> > include headers
>
> Ouch.
>
> Good-bye binary compatibility on FreeBSD. -- justin
This patch tries to maintain binary compatibility on FreeBSD 4.4 and above by
doing a runtime kernel version test. It works on daedalus. Jeff said he'd try
it on a 3.x FreeBSD box, where the runtime test I'm using isn't available.
Greg
? srclib/apr/configure.lineno
Index: srclib/apr/configure.in
===================================================================
RCS file: /home/cvspublic/apr/configure.in,v
retrieving revision 1.459
diff -u -d -b -r1.459 configure.in
--- srclib/apr/configure.in 1 Jul 2002 14:50:46 -0000 1.459
+++ srclib/apr/configure.in 2 Jul 2002 15:04:47 -0000
@@ -934,6 +934,7 @@
sys/signal.h \
sys/socket.h \
sys/stat.h \
+ sys/sysctl.h \
sys/syslimits.h \
sys/time.h \
sys/types.h \
Index: srclib/apr/network_io/unix/sendrecv.c
===================================================================
RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v
retrieving revision 1.84
diff -u -d -b -r1.84 sendrecv.c
--- srclib/apr/network_io/unix/sendrecv.c 17 May 2002 21:19:45 -0000
1.84
+++ srclib/apr/network_io/unix/sendrecv.c 2 Jul 2002 15:04:47 -0000
@@ -59,6 +59,10 @@
#include "fileio.h"
#endif /* APR_HAS_SENDFILE */
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
+
apr_status_t apr_wait_for_io_or_timeout(apr_socket_t *sock, int for_read)
{
struct timeval tv, *tvptr;
@@ -435,6 +439,48 @@
#elif defined(__FreeBSD__)
+static int include_hdrs_in_length(void)
+{
+#ifdef HAVE_SYS_SYSCTL_H
+ /* this assumes:
+ * if the header exits, so does the syscall, and
+ * if the header doesn't exist, the kernel is older than 4.4
+ */
+
+/* see http://www.freebsd.org/cgi/cvsweb.cgi/src/sys/sys/param.h
+ * rev 1.61.2.29 for kernel version number
+ */
+#define KERNEL_WITH_SENDFILE_LENGTH_FIX 460001
+
+ typedef enum { UNKNOWN = 0,
+ NEW,
+ OLD
+ } api_e;
+
+ static api_e api;
+ int kernel_version = 0; /* init to silence compiler warning */
+ size_t kernel_version_size = sizeof(kernel_version);
+
+ if (api != UNKNOWN) {
+ return (api == OLD);
+ }
+ if (sysctlbyname("kern.osreldate", &kernel_version,
+ &kernel_version_size, NULL, NULL) == 0 &&
+ kernel_version < KERNEL_WITH_SENDFILE_LENGTH_FIX) {
+ api = OLD;
+ return 1;
+ }
+ /* size of kern.osreldate might change in the future
+ * causing the sysctlbyname to fail,
+ * but if it's the future, we should use the newer API
+ */
+ api = NEW;
+ return 0;
+#elif
+ /* the build system's kernel is older than 4.4. Use the old API */
+ return 1;
+#endif
+}
/* Release 3.1 or greater */
apr_status_t apr_sendfile(apr_socket_t * sock, apr_file_t * file,
apr_hdtr_t * hdtr, apr_off_t * offset, apr_size_t * len,
@@ -445,20 +491,25 @@
struct sf_hdtr headerstruct;
size_t bytes_to_send = *len;
+ /* Ignore flags for now. */
+ flags = 0;
+
if (!hdtr) {
hdtr = &no_hdtr;
}
- /* Ignore flags for now. */
- flags = 0;
+ else if (hdtr->numheaders && include_hdrs_in_length()) {
- /* On FreeBSD, 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().
+ /* 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;
+ }
}
headerstruct.headers = hdtr->headers;