• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500-V1.0.1.40_1.0.68/ap/gpl/timemachine/netatalk-2.2.0/libatalk/adouble/
1/*
2 * $Id: ad_sendfile.c,v 1.11 2010-01-21 14:14:49 didg Exp $
3 *
4 * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
5 * All rights reserved. See COPYRIGHT.
6 *
7 * NOTE: the following uses the fact that sendfile() only exists on
8 * machines with SA_RESTART behaviour. this is all very machine specific.
9 *
10 * sendfile chainsaw from samba.
11 Unix SMB/Netbios implementation.
12 Version 2.2.x / 3.0.x
13 sendfile implementations.
14 Copyright (C) Jeremy Allison 2002.
15
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.
24
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.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif /* HAVE_CONFIG_H */
33
34#ifdef WITH_SENDFILE
35
36#include <atalk/adouble.h>
37
38#include <stdio.h>
39
40#include <sys/socket.h>
41#include <sys/uio.h>
42
43#include <errno.h>
44
45#include <atalk/logger.h>
46#include "ad_private.h"
47
48#if defined(LINUX_BROKEN_SENDFILE_API)
49
50extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count);
51
52ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
53{
54u_int32_t small_total;
55int32_t small_offset;
56int32_t nwritten;
57
58    /*
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.
63     */
64
65     if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) {
66         errno = ENOSYS;
67         return -1;
68     }
69     small_offset = (int32_t)*offset;
70     small_total = (u_int32_t)count;
71     nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
72     if (nwritten > = 0)
73         *offset += nwritten;
74
75    return nwritten;
76}
77
78#elif defined(SENDFILE_FLAVOR_LINUX)
79#include <sys/sendfile.h>
80
81ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
82{
83    return sendfile(tofd, fromfd, offset, count);
84}
85
86#elif defined(SENDFILE_FLAVOR_BSD )
87/* FIXME untested */
88#error sendfile semantic broken
89#include <sys/sendfile.h>
90ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
91{
92size_t total=0;
93int    ret;
94
95    total = count;
96    while (total) {
97        ssize_t nwritten;
98        do {
99           ret = sendfile(fromfd, tofd, offset, count, NULL, &nwritten, 0);
100        while (ret == -1 && errno == EINTR);
101        if (ret == -1)
102            return -1;
103        total -= nwritten;
104        offset += nwritten;
105    }
106    return count;
107}
108
109#else
110
111ssize_t sys_sendfile(int out_fd, int in_fd, off_t *_offset, size_t count)
112{
113    /* No sendfile syscall. */
114    errno = ENOSYS;
115    return -1;
116}
117#endif
118
119/* ------------------------------- */
120int ad_readfile_init(const struct adouble *ad,
121				       const int eid, off_t *off,
122				       const int end)
123{
124  int fd;
125
126  if (end)
127    *off = ad_size(ad, eid) - *off;
128
129  if (eid == ADEID_DFORK) {
130    fd = ad_data_fileno(ad);
131  } else {
132    *off += ad_getentryoff(ad, eid);
133    fd = ad_reso_fileno(ad);
134  }
135
136  return fd;
137}
138
139
140/* ------------------------ */
141#if 0
142#ifdef HAVE_SENDFILE_WRITE
143/* read from a socket and write to an adouble file */
144ssize_t ad_writefile(struct adouble *ad, const int eid,
145		     const int sock, off_t off, const int end,
146		     const size_t len)
147{
148#ifdef __linux__
149  ssize_t cc;
150  int fd;
151
152  fd = ad_sendfile_init(ad, eid, &off, end);
153  if ((cc = sys_sendfile(fd, sock, &off, len)) < 0)
154    return -1;
155
156  if ((eid != ADEID_DFORK) && (off > ad_getentrylen(ad, eid)))
157    ad_setentrylen(ad, eid, off);
158
159  return cc;
160#endif /* __linux__ */
161}
162#endif /* HAVE_SENDFILE_WRITE */
163#endif /* 0 */
164#endif
165