• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/src/
1#include "network_backends.h"
2
3#if defined(USE_LINUX_SENDFILE)
4
5#include "network.h"
6#include "log.h"
7
8#include <sys/sendfile.h>
9
10#include <errno.h>
11#include <string.h>
12
13#ifdef HAVE_LIBSMBCLIENT_H
14#include <libsmbclient.h>
15#define BUFF_SIZE (1460*10)
16#endif
17
18#define DBE 0
19
20int network_write_file_chunk_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) {
21	chunk* const c = cq->first;
22	ssize_t r;
23	off_t offset;
24	off_t toSend;
25
26	force_assert(NULL != c);
27	force_assert(FILE_CHUNK == c->type);
28	force_assert(c->offset >= 0 && c->offset <= c->file.length);
29
30	offset = c->file.start + c->offset;
31	toSend = c->file.length - c->offset;
32
33	if (toSend > *p_max_bytes) toSend = *p_max_bytes;
34
35	if (0 == toSend) {
36		chunkqueue_remove_finished_chunks(cq);
37		return 0;
38	}
39
40	if (0 != network_open_file_chunk(srv, con, cq)) return -1;
41
42	if (-1 == (r = sendfile(fd, c->file.fd, &offset, toSend))) {
43		switch (errno) {
44		case EAGAIN:
45		case EINTR:
46			break;
47		case EPIPE:
48		case ECONNRESET:
49			return -2;
50		default:
51			log_error_write(srv, __FILE__, __LINE__, "ssd",
52					"sendfile failed:", strerror(errno), fd);
53			return -1;
54		}
55	}
56
57	if (r >= 0) {
58		chunkqueue_mark_written(cq, r);
59		*p_max_bytes -= r;
60	}
61
62	return (r > 0 && r == toSend) ? 0 : -3;
63}
64
65int network_write_smbfile_chunk_sendfile(server *srv, connection *con, int fd, chunkqueue *cq, off_t *p_max_bytes) {
66
67
68	chunk* const c = cq->first;
69	ssize_t r;
70	off_t offset;
71	off_t toSend;
72	stat_cache_entry *sce = NULL;
73
74#ifdef HAVE_LIBSMBCLIENT_H
75
76	force_assert(NULL != c);
77	force_assert(SMB_CHUNK == c->type);
78	force_assert(c->offset >= 0 && c->offset <= c->file.length);
79
80	char buff[BUFF_SIZE]={0};
81
82	Cdbg(DBE, "*****************************************");
83
84	offset = c->file.start + c->offset;
85	toSend = ( c->file.length - c->offset > BUFF_SIZE) ? BUFF_SIZE : c->file.length - c->offset;
86
87	if (toSend > *p_max_bytes) toSend = *p_max_bytes;
88
89	if (0 == toSend) {
90		chunkqueue_remove_finished_chunks(cq);
91		return 0;
92	}
93
94	if (0 != network_open_file_chunk(srv, con, cq)) return -1;
95
96	//Cdbg(DBE, "c->file.fd=[%d], c->file.length=[%zu]", c->file.fd, c->file.length);
97
98	smbc_wrapper_lseek(con, c->file.fd, offset, SEEK_SET );
99
100	//Cdbg(DBE, "offset=%zu, toSend=%zu", offset, toSend);
101	r = smbc_wrapper_read(con, c->file.fd, buff, toSend);
102
103	Cdbg(DBE, "toSend=[%lld], errno=[%d], r=[%lld]", toSend, errno, r);
104
105	if( toSend == -1 || r < 0 ) {
106		smbc_wrapper_close(con, c->file.fd);
107
108		switch (errno) {
109		case EAGAIN:
110		case EINTR:
111			break;
112		case EPIPE:
113		case ECONNRESET:
114			return -2;
115		default:
116			log_error_write(srv, __FILE__, __LINE__, "ssd",
117					"sendfile failed:", strerror(errno), fd);
118			return -1;
119		}
120	}
121	else if (r == 0) {
122		int oerrno = errno;
123		/* We got an event to write but we wrote nothing
124		 *
125		 * - the file shrinked -> error
126		 * - the remote side closed inbetween -> remote-close */
127
128		if (HANDLER_ERROR == stat_cache_get_entry(srv, con, c->file.name, &sce)) {
129			/* file is gone ? */
130			return -1;
131		}
132
133		if (offset > sce->st.st_size) {
134			/* file shrinked, close the connection */
135			errno = oerrno;
136
137			return -1;
138		}
139
140		errno = oerrno;
141		return -2;
142	}
143
144	r = write(fd, buff, toSend);
145
146	if (r >= 0) {
147		chunkqueue_mark_written(cq, r);
148		*p_max_bytes -= r;
149	}
150#endif
151
152	return (r > 0 && r == toSend) ? 0 : -3;
153}
154
155#endif /* USE_LINUX_SENDFILE */
156