[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;

Reply via email to