source: branches/samba-3.2.x/source/lib/sendfile.c@ 232

Last change on this file since 232 was 232, checked in by Herwig Bauernfeind, 17 years ago

Update 3.2 branch to 3.2.8

File size: 11.8 KB
Line 
1/*
2 Unix SMB/Netbios implementation.
3 Version 2.2.x / 3.0.x
4 sendfile implementations.
5 Copyright (C) Jeremy Allison 2002.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
18*/
19
20/*
21 * This file handles the OS dependent sendfile implementations.
22 * The API is such that it returns -1 on error, else returns the
23 * number of bytes written.
24 */
25
26#include "includes.h"
27
28#if defined(LINUX_SENDFILE_API)
29
30#include <sys/sendfile.h>
31
32#ifndef MSG_MORE
33#define MSG_MORE 0x8000
34#endif
35
36ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
37{
38 size_t total=0;
39 ssize_t ret;
40 size_t hdr_len = 0;
41
42 /*
43 * Send the header first.
44 * Use MSG_MORE to cork the TCP output until sendfile is called.
45 */
46
47 if (header) {
48 hdr_len = header->length;
49 while (total < hdr_len) {
50 ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
51 if (ret == -1)
52 return -1;
53 total += ret;
54 }
55 }
56
57 total = count;
58 while (total) {
59 ssize_t nwritten;
60 do {
61#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
62 nwritten = sendfile64(tofd, fromfd, &offset, total);
63#else
64 nwritten = sendfile(tofd, fromfd, &offset, total);
65#endif
66 } while (nwritten == -1 && errno == EINTR);
67 if (nwritten == -1) {
68 if (errno == ENOSYS || errno == EINVAL) {
69 /* Ok - we're in a world of pain here. We just sent
70 * the header, but the sendfile failed. We have to
71 * emulate the sendfile at an upper layer before we
72 * disable it's use. So we do something really ugly.
73 * We set the errno to a strange value so we can detect
74 * this at the upper level and take care of it without
75 * layer violation. JRA.
76 */
77 errno = EINTR; /* Normally we can never return this. */
78 }
79 return -1;
80 }
81 if (nwritten == 0)
82 return -1; /* I think we're at EOF here... */
83 total -= nwritten;
84 }
85 return count + hdr_len;
86}
87
88#elif defined(LINUX_BROKEN_SENDFILE_API)
89
90/*
91 * We must use explicit 32 bit types here. This code path means Linux
92 * won't do proper 64-bit sendfile. JRA.
93 */
94
95extern int32 sendfile (int out_fd, int in_fd, int32 *offset, uint32 count);
96
97
98#ifndef MSG_MORE
99#define MSG_MORE 0x8000
100#endif
101
102ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
103{
104 size_t total=0;
105 ssize_t ret;
106 ssize_t hdr_len = 0;
107 uint32 small_total = 0;
108 int32 small_offset;