1 /***************************************************************************/
2 /* This code is part of WWW grabber called pavuk */
3 /* Copyright (c) 1997 - 2001 Stefan Ondrejicka */
4 /* Distributed under GPL 2 or later */
5 /***************************************************************************/
6
7 #include <sys/types.h>
8 #include <sys/stat.h>
9 #include <sys/socket.h>
10 #include <fcntl.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <string.h>
14 #include <errno.h>
15
16 #include "config.h"
17 #include "bufio.h"
18 #include "tools.h"
19 #include "absio.h"
20 #include "myssl.h"
21
22 #ifndef MAX
23 #define MAX(x,y) ((x) > (y) ? (x) : (y))
24 #endif
25
26 #define BUFIO_BUF_SIZE 4096
27
_bufio_tl_write(bufio * desc,char * buf,size_t size)28 static int _bufio_tl_write(bufio * desc, char *buf, size_t size)
29 {
30 if(desc->is_sock)
31 return tl_sock_write(desc->fd, buf, size, desc->ssl_hook_data);
32 else
33 return tl_file_write(desc->fd, buf, size);
34 }
35
_bufio_tl_read(bufio * desc,char * buf,size_t size)36 static int _bufio_tl_read(bufio * desc, char *buf, size_t size)
37 {
38 if(desc->is_sock)
39 return tl_sock_read(desc->fd, buf, size, desc->ssl_hook_data);
40 else
41 return tl_file_read(desc->fd, buf, size);
42 }
43
bufio_new(void)44 static bufio *bufio_new(void)
45 {
46 bufio *retv;
47
48 retv = _malloc(sizeof(bufio));
49 retv->buf = _malloc(BUFIO_BUF_SIZE);
50 retv->fd = -1;
51 retv->buf_size = BUFIO_BUF_SIZE;
52 retv->buf_start = 0;
53 retv->buf_end = 0;
54 retv->bufio_errno = 0;
55 retv->eof = 0;
56 retv->is_sock = 0;
57 retv->ssl_hook_data = NULL;
58
59 return retv;
60 }
61
bufio_sock_fdopen(int fd)62 bufio *bufio_sock_fdopen(int fd)
63 {
64 bufio *retv;
65
66 retv = bufio_fdopen(fd);
67
68 if(retv)
69 retv->is_sock = 1;
70
71 return retv;
72 }
73
bufio_fdopen(int fd)74 bufio *bufio_fdopen(int fd)
75 {
76 bufio *retv;
77
78 if(fd < 0)
79 return NULL;
80
81 retv = bufio_new();
82 retv->fd = fd;
83
84 return retv;
85 }
86
bufio_dupfd(int fd)87 bufio *bufio_dupfd(int fd)
88 {
89 int cfd;
90
91 if(fd < 0)
92 return NULL;
93
94 cfd = dup(fd);
95
96 return bufio_fdopen(cfd);
97 }
98
bufio_open(const char * filename,int flags)99 bufio *bufio_open(const char *filename, int flags)
100 {
101 int fd;
102
103 fd = open(filename, flags);
104
105 if(fd < 0)
106 return NULL;
107
108 return bufio_fdopen(fd);
109 }
110
bufio_copen(const char * filename,int flags,int mask)111 bufio *bufio_copen(const char *filename, int flags, int mask)
112 {
113 int fd;
114
115 fd = open(filename, flags, mask);
116
117 if(fd < 0)
118 return NULL;
119
120 return bufio_fdopen(fd);
121 }
122
bufio_new_sslcon(bufio * sock,void * con)123 bufio *bufio_new_sslcon(bufio * sock, void *con)
124 {
125 bufio *retv;
126
127 retv = bufio_new();
128 retv->ssl_hook_data = con;
129 retv->is_sock = 1;
130 retv->fd = bufio_getfd(sock);
131
132 return retv;
133 }
134
bufio_free(bufio * desc)135 void bufio_free(bufio * desc)
136 {
137 _free(desc->buf);
138 _free(desc);
139 }
140
bufio_close(bufio * desc)141 int bufio_close(bufio * desc)
142 {
143 int rv = 0;
144
145 #ifdef USE_SSL
146 if(desc->ssl_hook_data)
147 {
148 my_ssl_connection_destroy(desc->ssl_hook_data);
149 desc->ssl_hook_data = NULL;
150 desc->fd = -1;
151 }
152 #endif
153
154
155 if(desc->fd >= 0)
156 {
157 if(desc->is_sock)
158 {
159 shutdown(desc->fd, 2);
160 #ifdef __BEOS__
161 rv = closesocket(desc->fd);
162 #else
163 rv = close(desc->fd);
164 #endif
165 }
166 else
167 rv = close(desc->fd);
168 }
169
170 desc->fd = -1;
171
172 _free(desc->buf);
173 _free(desc);
174
175 return rv;
176 }
177
bufio_write(bufio * desc,char * buf,size_t size)178 int bufio_write(bufio * desc, char *buf, size_t size)
179 {
180 return _bufio_tl_write(desc, buf, size);
181 }
182
bufio_read(bufio * desc,char * buf,size_t size)183 int bufio_read(bufio * desc, char *buf, size_t size)
184 {
185 int read_sz = 0;
186 int read_act;
187 int miss_size = size;
188 int acnt;
189
190 if(desc->eof)
191 {
192 return 0;
193 }
194
195 if(desc->bufio_errno)
196 {
197 errno = desc->bufio_errno;
198 return -1;
199 }
200
201 for(;;)
202 {
203 if(desc->buf_start < desc->buf_end)
204 {
205 read_act = miss_size < desc->buf_end - desc->buf_start ?
206 miss_size : desc->buf_end - desc->buf_start;
207
208 memcpy(buf + read_sz, desc->buf + desc->buf_start, read_act);
209
210 desc->buf_start += read_act;
211 miss_size -= read_act;
212 read_sz += read_act;
213
214 if(read_sz == size)
215 return read_sz;
216 }
217 else
218 {
219 desc->buf_start = 0;
220 desc->buf_end = 0;
221 acnt = _bufio_tl_read(desc, desc->buf, desc->buf_size);
222
223 if(acnt <= 0)
224 {
225 if(acnt == 0)
226 desc->eof = 1;
227 if(read_sz)
228 {
229 desc->bufio_errno = errno;
230 return read_sz;
231 }
232 else
233 return acnt;
234 }
235
236 desc->buf_end = acnt;
237 }
238 }
239 }
240
bufio_nbfread(bufio * desc,char * buf,size_t size)241 int bufio_nbfread(bufio * desc, char *buf, size_t size)
242 {
243 int read_sz;
244
245 if(desc->eof)
246 {
247 return 0;
248 }
249 if(desc->bufio_errno)
250 {
251 errno = desc->bufio_errno;
252 return -1;
253 }
254
255 if(desc->buf_start < desc->buf_end)
256 {
257 read_sz = size < desc->buf_end - desc->buf_start ?
258 size : desc->buf_end - desc->buf_start;
259
260 memcpy(buf, desc->buf + desc->buf_start, read_sz);
261
262 desc->buf_start += read_sz;
263
264 return read_sz;
265 }
266 else
267 {
268 desc->buf_start = 0;
269 desc->buf_end = 0;
270 read_sz = _bufio_tl_read(desc, buf, size);
271
272 if(read_sz <= 0)
273 {
274 if(read_sz == 0)
275 desc->eof = 1;
276 if(read_sz < 0)
277 desc->bufio_errno = errno;
278 }
279 return read_sz;
280 }
281 }
282
bufio_readln(bufio * desc,char * buf,size_t size)283 int bufio_readln(bufio * desc, char *buf, size_t size)
284 {
285 int read_sz = 0;
286 int read_act;
287 int miss_size = size - 1;
288 int acnt;
289 char *mc = NULL;
290
291 if(desc->eof)
292 {
293 return 0;
294 }
295
296 if(desc->bufio_errno)
297 {
298 errno = desc->bufio_errno;
299 return -1;
300 }
301
302 size--;
303
304 for(;;)
305 {
306 if(desc->buf_start < desc->buf_end)
307 {
308 mc = memchr(desc->buf + desc->buf_start, '\n',
309 desc->buf_end - desc->buf_start);
310
311 if(mc && (mc - (desc->buf + desc->buf_start) < miss_size))
312 {
313 read_act = mc + 1 - (desc->buf + desc->buf_start);
314 }
315 else
316 read_act = miss_size < desc->buf_end - desc->buf_start ?
317 miss_size : desc->buf_end - desc->buf_start;
318
319 memcpy(buf + read_sz, desc->buf + desc->buf_start, read_act);
320
321 desc->buf_start += read_act;
322 miss_size -= read_act;
323 read_sz += read_act;
324
325 if(read_sz == size || mc)
326 {
327 *(buf + read_sz) = '\0';
328 return read_sz;
329 }
330 }
331 else
332 {
333 desc->buf_start = 0;
334 desc->buf_end = 0;
335 acnt = _bufio_tl_read(desc, desc->buf, desc->buf_size);
336
337 if(acnt <= 0)
338 {
339 if(acnt == 0)
340 desc->eof = 1;
341 if(read_sz)
342 {
343 desc->bufio_errno = errno;
344 *(buf + read_sz + 1) = '\0';
345 return read_sz;
346 }
347 else
348 return acnt;
349 }
350
351 desc->buf_end = acnt;
352 }
353 }
354 }
355
bufio_unread(bufio * desc,char * buf,size_t size)356 void bufio_unread(bufio * desc, char *buf, size_t size)
357 {
358 char *p = desc->buf;
359
360 desc->buf_size =
361 MAX(desc->buf_size, (size + desc->buf_end - desc->buf_start));
362
363 desc->buf = _malloc(desc->buf_size);
364
365 memmove(desc->buf, buf, size);
366 memmove(desc->buf + size, p + desc->buf_start,
367 desc->buf_end - desc->buf_start);
368
369 desc->buf_end = size + desc->buf_end - desc->buf_start;
370 desc->buf_start = 0;
371
372 _free(p);
373 }
374
bufio_reset(bufio * desc)375 void bufio_reset(bufio * desc)
376 {
377 desc->buf_start = 0;
378 desc->buf_end = 0;
379 }
380