Not only because of its the ugliest mbuf structure and the design of the network packet processing. I did not work with *bsd kernels more than 4 years already and very happy this horror was finished not even seriously started.
But even its userspace part is ugly. Let's see how Solaris and Linux implemented <code>sendfile()</code> call (although Solaris put it into special <code>libsendfile.so</code> library) compared to FreeBSD one:#ifdef HAVE_SENDFILE4_SUPPORT #include <sys/sendfile.h> int dnet_sendfile(struct dnet_net_state *st, int fd, off_t *offset, size_t size) { int err; err = sendfile(st->s, fd, offset, size); if (err < 0) return -errno; return err; } #elif HAVE_SENDFILE7_SUPPORT #include <sys/uio.h> int dnet_sendfile(struct dnet_net_state *st, int fd, off_t *offset, size_t size) { int err; err = sendfile(fd, st->s, *offset, size, NULL, &size, 0); if (err && errno != EAGAIN) return -errno; if (size) { *offset += size; return size; } return -EAGAIN; } #else #error "Your platform does not support sendfile. Sorry." #endif
As you might expect the latter part of the compat layer is for FreeBSD - 7 arguments for the syscall (forget about registers), and weird return values: it may be zero, positive number of bytes and negative error. And <code>EAGAIN</code> mess. What prevented it from following Solaris way of having simple and vectorized sendfiles remains a riddle.
And that's my 'simple' m4 autoconf script to detect the proper sendfile usage. AC_DEFUN([AC_CHECK_SENDFILE],[ AC_MSG_CHECKING([whether sendfile() is supported and what prototype it has]) AC_CACHE_VAL([ac_sendfile4_supported],[ AC_TRY_LINK([#include <sys/sendfile.h> #include <stdio.h>], [sendfile(1, 1, NULL, 0);], [ ac_sendfile4_supported=yes ac_sendfile_supported=yes AC_MSG_RESULT([usual Linux/Solaris sendfile()]) ], [ dnl Checking wether we need libsendfile dnl Presumably on Solaris AC_CHECK_LIB(sendfile, sendfile, [ ac_sendfile4_supported=yes ac_sendfile_supported=yes SENDFILE_LIBS="-lsendfile" AC_SUBST(SENDFILE_LIBS) ], [ac_sendfile_supported=no]) ]) ]) if test x$ac_sendfile_supported = xno; then AC_CACHE_VAL([ac_sendfile7_supported],[ AC_TRY_LINK([#include <sys/socket.h> #include <stdio.h>], [sendfile(1, 1, 0, 0, NULL, NULL, 0);], [ ac_sendfile7_supported=yes ac_sendfile_supported=yes AC_MSG_RESULT([ugly FreeBSD sendfile()]) ], [ac_sendfile_supported=no]) ]) fi if test x$ac_sendfile_supported = xno; then AC_MSG_ERROR([no sendfile support]) fi if test x$ac_sendfile4_supported = xyes; then AC_DEFINE(HAVE_SENDFILE4_SUPPORT, 1, [Define this if Linux/Solaris sendfile() is supported]) fi if test x$ac_sendfile7_supported = xyes; then AC_DEFINE(HAVE_SENDFILE7_SUPPORT, 1, [Define this if FreeBSD sendfile() is supported]) fi ])
I'm slowly starting to like autotools - although my project is about 5 thousands of lines and only generated <code>configure</code> script is about 5 times bigger, it is still simple and somewhat clear (although limited sometimes).
<a href="/projects/elliptics">Elliptics</a> network got full FreeBSD support and I even used it slightly to catch some bugs (mostly because of its <code>sendfile()</code> support). Project also got log events mask, compile-time ID size changes (<code>--with-id-size=$bytes</code> switch) and lots of other smaller bits (especially in the automatic configuration).
Tomorrow (if things will be completed before running out climbing) I will implement the testing tool described and start the process. Do you expect a failure? :)
looks like you never wrote a reasonable large portion of code that's supposed to be portable between say linux 2.4 and 2.6. freebsd 7 is years ahead of 4. not that i love freebsd tho.
Никак не могу заставить себя разобраться с autotools. Это настолько неприятная система, что к ней не хочется даже притрагиваться.
With newer autoconf versions (I think 2.62 and later), the autoconf code there is going to throw a warning (and fail to work as expected): the cache value variables should have "_cv_" in them; also ac_* (and AC_* for macros) should be reserved for autoconf-proper macros so I'd suggest using dnet_cv_sendfile_foo for the variables.