2 * $Id: ad_sendfile.c,v 1.9 2008-12-03 18:35:44 didg Exp $
4 * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
5 * All rights reserved. See COPYRIGHT.
7 * NOTE: the following uses the fact that sendfile() only exists on
8 * machines with SA_RESTART behaviour. this is all very machine specific.
10 * sendfile chainsaw from samba.
11 Unix SMB/Netbios implementation.
13 sendfile implementations.
14 Copyright (C) Jeremy Allison 2002.
16 This program is free software; you can redistribute it and/or modify
17 it under the terms of the GNU General Public License as published by
18 the Free Software Foundation; either version 2 of the License, or
19 (at your option) any later version.
20 This program is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32 #endif /* HAVE_CONFIG_H */
36 #include <atalk/adouble.h>
40 #include <sys/socket.h>
45 #include <atalk/logger.h>
47 #include "ad_private.h"
49 #if defined(LINUX_BROKEN_SENDFILE_API)
51 extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count);
53 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
55 u_int32_t small_total = 0;
59 * Fix for broken Linux 2.4 systems with no working sendfile64().
60 * If the offset+count > 2 GB then pretend we don't have the
61 * system call sendfile at all. The upper layer catches this
62 * and uses a normal read. JRA.
65 if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) {
69 small_total = (u_int32_t)count;
70 small_offset = (int32_t)*offset;
75 nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
76 } while (nwritten == -1 && errno == EINTR);
80 return -1; /* I think we're at EOF here... */
81 small_total -= nwritten;
87 #elif defined(SENDFILE_FLAVOR_LINUX)
88 #include <sys/sendfile.h>
90 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
98 nwritten = sendfile(tofd, fromfd, offset, total);
99 } while (nwritten == -1 && errno == EINTR);
103 return -1; /* I think we're at EOF here... */
110 #elif defined(SENDFILE_FLAVOR_BSD )
112 #include <sys/sendfile.h>
113 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
122 ret = sendfile(fromfd, tofd, offset, count, NULL, &nwritten, 0);
123 while (ret == -1 && errno == EINTR);
134 ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count)
136 /* No sendfile syscall. */
142 /* ------------------------------- */
143 static int ad_sendfile_init(const struct adouble *ad,
144 const int eid, off_t *off,
150 *off = ad_size(ad, eid) - *off;
152 if (eid == ADEID_DFORK) {
155 *off += ad_getentryoff(ad, eid);
163 /* --------------------------------
164 * read from adouble file and write to socket. sendfile doesn't change
165 * the file pointer position. */
166 ssize_t ad_readfile(const struct adouble *ad, const int eid,
167 const int sock, off_t off, const size_t len)
172 fd = ad_sendfile_init(ad, eid, &off, 0);
173 cc = sys_sendfile(sock, fd, &off, len);
177 /* ------------------------ */
179 #ifdef HAVE_SENDFILE_WRITE
180 /* read from a socket and write to an adouble file */
181 ssize_t ad_writefile(struct adouble *ad, const int eid,
182 const int sock, off_t off, const int end,
189 fd = ad_sendfile_init(ad, eid, &off, end);
190 if ((cc = sys_sendfile(fd, sock, &off, len)) < 0)
193 if ((eid != ADEID_DFORK) && (off > ad_getentrylen(ad, eid)))
194 ad_setentrylen(ad, eid, off);
197 #endif /* __linux__ */
199 #endif /* HAVE_SENDFILE_WRITE */