X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Fadouble%2Fad_sendfile.c;h=48d9934645a901ba96ac8342cc3178e4e20f8ba0;hb=d81ea56449b54aaeccf8bba1dc7ae88773268c33;hp=35a9bccc0b0aa15b3b75ab4846d0bd7762cf5dd3;hpb=6b814c857d98259bd82737ce8746c6c1d94e9cd5;p=netatalk.git diff --git a/libatalk/adouble/ad_sendfile.c b/libatalk/adouble/ad_sendfile.c index 35a9bccc..48d99346 100644 --- a/libatalk/adouble/ad_sendfile.c +++ b/libatalk/adouble/ad_sendfile.c @@ -1,5 +1,5 @@ /* - * $Id: ad_sendfile.c,v 1.5 2002-10-11 14:18:38 didg Exp $ + * $Id: ad_sendfile.c,v 1.10 2009-10-25 09:47:04 didg Exp $ * * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu) * All rights reserved. See COPYRIGHT. @@ -7,49 +7,118 @@ * NOTE: the following uses the fact that sendfile() only exists on * machines with SA_RESTART behaviour. this is all very machine specific. * - * + * sendfile chainsaw from samba. + Unix SMB/Netbios implementation. + Version 2.2.x / 3.0.x + sendfile implementations. + Copyright (C) Jeremy Allison 2002. + + This program 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., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif /* HAVE_CONFIG_H */ +#ifdef WITH_SENDFILE + +#include + #include -#ifdef HAVE_UNISTD_H -#include -#endif /* HAVE_UNISTD_H */ -#include -#include + #include #include -#include +#include #include - #include "ad_private.h" -static int _ad_sendfile_dummy; +#if defined(LINUX_BROKEN_SENDFILE_API) + +extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count); + +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) +{ +u_int32_t small_total; +int32_t small_offset; +int32_t nwritten; + + /* + * Fix for broken Linux 2.4 systems with no working sendfile64(). + * If the offset+count > 2 GB then pretend we don't have the + * system call sendfile at all. The upper layer catches this + * and uses a normal read. JRA. + */ + + if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) { + errno = ENOSYS; + return -1; + } + small_offset = (int32_t)*offset; + small_total = (u_int32_t)count; + nwritten = sendfile(tofd, fromfd, &small_offset, small_total); + if (nwritten > = 0) + *offset += nwritten; + + return nwritten; +} + +#elif defined(SENDFILE_FLAVOR_LINUX) +#include + +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) +{ + return sendfile(tofd, fromfd, offset, count); +} -#ifdef ATACC -#if defined(HAVE_SENDFILE_READ) -#ifdef __NR_sendfile -int sendfile(int fdout, int fdin, off_t *off, size_t count) +#elif defined(SENDFILE_FLAVOR_BSD ) +/* FIXME untested */ +#error sendfile semantic broken +#include +ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count) { -#if _FILE_OFFSET_BITS == 64 -#error sendfile - return syscall(__NR_sendfile64, fdout, fdin, off, count); +size_t total=0; +int ret; + + total = count; + while (total) { + ssize_t nwritten; + do { + ret = sendfile(fromfd, tofd, offset, count, NULL, &nwritten, 0); + while (ret == -1 && errno == EINTR); + if (ret == -1) + return -1; + total -= nwritten; + offset += nwritten; + } + return count; +} + #else - return syscall(__NR_sendfile, fdout, fdin, off, count); -#endif + +ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count) +{ + /* No sendfile syscall. */ + errno = ENOSYS; + return -1; } #endif -#endif -#endif -#if defined(HAVE_SENDFILE_READ) || defined(HAVE_SENDFILE_WRITE) -static __inline__ int ad_sendfile_init(const struct adouble *ad, +/* ------------------------------- */ +int ad_readfile_init(const struct adouble *ad, const int eid, off_t *off, const int end) { @@ -59,40 +128,17 @@ static __inline__ int ad_sendfile_init(const struct adouble *ad, *off = ad_size(ad, eid) - *off; if (eid == ADEID_DFORK) { - fd = ad_dfileno(ad); + fd = ad_data_fileno(ad); } else { *off += ad_getentryoff(ad, eid); - fd = ad_hfileno(ad); + fd = ad_reso_fileno(ad); } return fd; } -#endif -/* read from adouble file and write to socket. sendfile doesn't change - * the file pointer position. */ -#ifdef HAVE_SENDFILE_READ -ssize_t ad_readfile(const struct adouble *ad, const int eid, - const int sock, off_t off, const size_t len) -{ - off_t cc; - int fd; - - fd = ad_sendfile_init(ad, eid, &off, 0); -#ifdef __linux__ - cc = sendfile(sock, fd, &off, len); -#endif /* __linux__ */ - -#ifdef BSD4_4 - if (sendfile(fd, sock, off, len, NULL, &cc, 0) < 0) - return -1; -#endif /* BSD4_4 */ - - return cc; -} -#endif /* HAVE_SENDFILE_READ */ - +/* ------------------------ */ #if 0 #ifdef HAVE_SENDFILE_WRITE /* read from a socket and write to an adouble file */ @@ -105,7 +151,7 @@ ssize_t ad_writefile(struct adouble *ad, const int eid, int fd; fd = ad_sendfile_init(ad, eid, &off, end); - if ((cc = sendfile(fd, sock, &off, len)) < 0) + if ((cc = sys_sendfile(fd, sock, &off, len)) < 0) return -1; if ((eid != ADEID_DFORK) && (off > ad_getentrylen(ad, eid))) @@ -116,3 +162,4 @@ ssize_t ad_writefile(struct adouble *ad, const int eid, } #endif /* HAVE_SENDFILE_WRITE */ #endif /* 0 */ +#endif