]> arthur.barton.de Git - netatalk.git/blob - libatalk/adouble/ad_sendfile.c
Merge master
[netatalk.git] / libatalk / adouble / ad_sendfile.c
1 /*
2  * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
3  * All rights reserved. See COPYRIGHT.
4  *
5  * NOTE: the following uses the fact that sendfile() only exists on
6  * machines with SA_RESTART behaviour. this is all very machine specific. 
7  *
8  * sendfile chainsaw from samba.
9  Unix SMB/Netbios implementation.
10  Version 2.2.x / 3.0.x
11  sendfile implementations.
12  Copyright (C) Jeremy Allison 2002.
13  
14  This program is free software; you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation; either version 2 of the License, or
17  (at your option) any later version.
18  This program is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  GNU General Public License for more details.
22  
23  You should have received a copy of the GNU General Public License
24  along with this program; if not, write to the Free Software
25  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif /* HAVE_CONFIG_H */
31
32 #ifdef WITH_SENDFILE
33 #include <stdio.h>
34 #include <sys/socket.h>
35 #include <sys/uio.h>
36 #include <errno.h>  
37
38 #include <atalk/adouble.h>
39 #include <atalk/logger.h>
40
41 #include "ad_lock.h"
42
43 #if defined(LINUX_BROKEN_SENDFILE_API)
44
45 extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count);
46
47 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
48 {
49 u_int32_t small_total;
50 int32_t small_offset;
51 int32_t nwritten;
52
53     /*
54      * Fix for broken Linux 2.4 systems with no working sendfile64().
55      * If the offset+count > 2 GB then pretend we don't have the
56      * system call sendfile at all. The upper layer catches this
57      * and uses a normal read. JRA.
58      */
59  
60      if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) {
61          errno = ENOSYS;
62          return -1;
63      }
64      small_offset = (int32_t)*offset;
65      small_total = (u_int32_t)count;
66      nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
67      if (nwritten > = 0)
68          *offset += nwritten;
69      
70     return nwritten;
71 }
72
73 #elif defined(SENDFILE_FLAVOR_LINUX)
74 #include <sys/sendfile.h>
75
76 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
77 {
78     return sendfile(tofd, fromfd, offset, count);
79 }
80
81 #elif defined(SENDFILE_FLAVOR_BSD )
82 /* FIXME untested */
83 #error sendfile semantic broken
84 #include <sys/sendfile.h>
85 ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
86 {
87 size_t total=0;
88 int    ret;
89
90     total = count;
91     while (total) {
92         ssize_t nwritten;
93         do {
94            ret = sendfile(fromfd, tofd, offset, count, NULL, &nwritten, 0);
95         while (ret == -1 && errno == EINTR);
96         if (ret == -1)
97             return -1;
98         total -= nwritten;
99         offset += nwritten;
100     }
101     return count;
102 }
103
104 #else
105
106 ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count)
107 {
108     /* No sendfile syscall. */
109     errno = ENOSYS;
110     return -1;
111 }
112 #endif
113
114 /* ------------------------------- */
115 int ad_readfile_init(const struct adouble *ad, 
116                                        const int eid, off_t *off,
117                                        const int end)
118 {
119   int fd;
120
121   if (end) 
122     *off = ad_size(ad, eid) - *off;
123
124   if (eid == ADEID_DFORK) {
125     fd = ad_data_fileno(ad);
126   } else {
127     *off += ad_getentryoff(ad, eid);
128     fd = ad_reso_fileno(ad);
129   }
130
131   return fd;
132 }
133
134
135 /* ------------------------ */
136 #if 0
137 #ifdef HAVE_SENDFILE_WRITE
138 /* read from a socket and write to an adouble file */
139 ssize_t ad_writefile(struct adouble *ad, const int eid, 
140                      const int sock, off_t off, const int end,
141                      const size_t len)
142 {
143 #ifdef __linux__
144   ssize_t cc;
145   int fd;
146
147   fd = ad_sendfile_init(ad, eid, &off, end);
148   if ((cc = sys_sendfile(fd, sock, &off, len)) < 0)
149     return -1;
150
151   if ((eid != ADEID_DFORK) && (off > ad_getentrylen(ad, eid))) 
152     ad_setentrylen(ad, eid, off);
153
154   return cc;
155 #endif /* __linux__ */
156 }
157 #endif /* HAVE_SENDFILE_WRITE */
158 #endif /* 0 */
159 #endif