File Coverage

iolayer.c
Criterion Covered Total %
statement 554 653 84.8
branch 278 356 78.0
condition n/a
subroutine n/a
pod n/a
total 832 1009 82.4


line stmt bran cond sub pod time code
1             #define IMAGER_NO_CONTEXT
2             #include "imager.h"
3             #include "iolayer.h"
4             #include "imerror.h"
5             #include "log.h"
6             #include
7             #include
8             #ifdef _MSC_VER
9             #include
10             #endif
11             #include
12             #include
13             #include "imageri.h"
14              
15             #define IOL_DEB(x)
16             #define IOL_DEBs stderr
17              
18             #define IO_BUF_SIZE 8192
19              
20             char *io_type_names[] = { "FDSEEK", "FDNOSEEK", "BUFFER", "CBSEEK", "CBNOSEEK", "BUFCHAIN" };
21              
22             typedef struct io_blink {
23             char buf[BBSIZ];
24             /* size_t cnt; */
25             size_t len; /* How large is this buffer = BBZIS for now */
26             struct io_blink *next;
27             struct io_blink *prev;
28             } io_blink;
29              
30              
31             typedef struct {
32             i_io_glue_t base;
33             int fd;
34             } io_fdseek;
35              
36             typedef struct {
37             i_io_glue_t base;
38             const char *data;
39             size_t len;
40             i_io_closebufp_t closecb; /* free memory mapped segment or decrement refcount */
41             void *closedata;
42             off_t cpos;
43             } io_buffer;
44              
45             typedef struct {
46             i_io_glue_t base;
47             void *p; /* Callback data */
48             i_io_readl_t readcb;
49             i_io_writel_t writecb;
50             i_io_seekl_t seekcb;
51             i_io_closel_t closecb;
52             i_io_destroyl_t destroycb;
53             } io_cb;
54              
55             typedef struct {
56             off_t offset; /* Offset of the source - not used */
57             off_t length; /* Total length of chain in bytes */
58             io_blink *head; /* Start of chain */
59             io_blink *tail; /* End of chain */
60             off_t tfill; /* End of stream in last link */
61             io_blink *cp; /* Current element of list */
62             off_t cpos; /* Offset within the current */
63             off_t gpos; /* Global position in stream */
64             } io_ex_bchain;
65              
66             /* turn current offset, file length, whence and offset into a new offset */
67             #define calc_seek_offset(curr_off, length, offset, whence) \
68             (((whence) == SEEK_SET) ? (offset) : \
69             ((whence) == SEEK_CUR) ? (curr_off) + (offset) : \
70             ((whence) == SEEK_END) ? (length) + (offset) : -1)
71              
72             /*
73             =head1 NAME
74              
75             iolayer.c - encapsulates different source of data into a single framework.
76              
77             =head1 SYNOPSIS
78              
79             io_glue *ig = io_new_fd( fileno(stdin) );
80             method = io_reqmeth( IOL_NOSEEK | IOL_MMAP ); // not implemented yet
81              
82             switch (method) {
83             case IOL_NOSEEK:
84             code that uses ig->readcb()
85             to read data goes here.
86             break;
87             case IOL_MMAP:
88             code that uses ig->readcb()
89             to read data goes here.
90             break;
91             }
92              
93             io_glue_destroy(ig);
94             // and much more
95              
96             =head1 DESCRIPTION
97              
98             iolayer.c implements the basic functions to create and destroy io_glue
99             objects for Imager. The typical usage pattern for data sources is:
100              
101             1. Create the source (io_new_fd)
102             2. Define how you want to get data from it (io_reqmeth)
103             3. read from it using the interface requested (ig->readdb, ig->mmapcb)
104             4. Close the source, which
105             shouldn't really close the underlying source. (io_glue DESTROY)
106              
107             =head1 FUNCTION REFERENCE
108              
109             Some of these functions are internal.
110              
111             =over
112              
113             =cut
114             */
115              
116             static void
117             i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb,
118             i_io_writep_t writecb, i_io_seekp_t seekcb);
119              
120             static ssize_t fd_read(io_glue *ig, void *buf, size_t count);
121             static ssize_t fd_write(io_glue *ig, const void *buf, size_t count);
122             static off_t fd_seek(io_glue *ig, off_t offset, int whence);
123             static int fd_close(io_glue *ig);
124             static ssize_t fd_size(io_glue *ig);
125             static const char *my_strerror(int err);
126             static void i_io_setup_buffer(io_glue *ig);
127             static void
128             i_io_start_write(io_glue *ig);
129             static int
130             i_io_read_fill(io_glue *ig, ssize_t needed);
131             static void
132             dump_data(unsigned char *start, unsigned char *end, int bias);
133             static ssize_t realseek_read(io_glue *igo, void *buf, size_t count);
134             static ssize_t realseek_write(io_glue *igo, const void *buf, size_t count);
135             static int realseek_close(io_glue *igo);
136             static off_t realseek_seek(io_glue *igo, off_t offset, int whence);
137             static void realseek_destroy(io_glue *igo);
138             static ssize_t buffer_read(io_glue *igo, void *buf, size_t count);
139             static ssize_t buffer_write(io_glue *ig, const void *buf, size_t count);
140             static int buffer_close(io_glue *ig);
141             static off_t buffer_seek(io_glue *igo, off_t offset, int whence);
142             static void buffer_destroy(io_glue *igo);
143             static io_blink*io_blink_new(void);
144             static void io_bchain_advance(io_ex_bchain *ieb);
145             static void io_destroy_bufchain(io_ex_bchain *ieb);
146             static ssize_t bufchain_read(io_glue *ig, void *buf, size_t count);
147             static ssize_t bufchain_write(io_glue *ig, const void *buf, size_t count);
148             static int bufchain_close(io_glue *ig);
149             static off_t bufchain_seek(io_glue *ig, off_t offset, int whence);
150             static void bufchain_destroy(io_glue *ig);
151              
152             /*
153             * Methods for setting up data source
154             */
155              
156             /*
157             =item im_io_new_bufchain(ctx)
158             XX
159             =order 10
160             =category I/O Layers
161              
162             Returns a new io_glue object that has the 'empty' source and but can
163             be written to and read from later (like a pseudo file).
164              
165             Also callable as C.
166              
167             =cut
168             */
169              
170             io_glue *
171 53           im_io_new_bufchain(pIMCTX) {
172             io_glue *ig;
173 53           io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
174              
175 53           im_log((aIMCTX, 1, "io_new_bufchain()\n"));
176              
177 53           ig = mymalloc(sizeof(io_glue));
178 53           memset(ig, 0, sizeof(*ig));
179 53           i_io_init(aIMCTX, ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
180              
181 53           ieb->offset = 0;
182 53           ieb->length = 0;
183 53           ieb->cpos = 0;
184 53           ieb->gpos = 0;
185 53           ieb->tfill = 0;
186            
187 53           ieb->head = io_blink_new();
188 53           ieb->cp = ieb->head;
189 53           ieb->tail = ieb->head;
190            
191 53           ig->exdata = ieb;
192 53           ig->closecb = bufchain_close;
193 53           ig->destroycb = bufchain_destroy;
194              
195 53           im_context_refinc(aIMCTX, "im_io_new_bufchain");
196              
197 53           return ig;
198             }
199              
200             /*
201             =item im_io_new_buffer(ctx, data, length)
202             XX
203             =order 10
204             =category I/O Layers
205              
206             Returns a new io_glue object that has the source defined as reading
207             from specified buffer. Note that the buffer is not copied.
208              
209             ctx - an Imager context object
210             data - buffer to read from
211             length - length of buffer
212              
213             Also callable as C.
214              
215             =cut
216             */
217              
218             io_glue *
219 187           im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
220             io_buffer *ig;
221            
222 187           im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
223              
224 187           ig = mymalloc(sizeof(io_buffer));
225 187           memset(ig, 0, sizeof(*ig));
226 187           i_io_init(aIMCTX, &ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
227 187           ig->data = data;
228 187           ig->len = len;
229 187           ig->closecb = closecb;
230 187           ig->closedata = closedata;
231              
232 187           ig->cpos = 0;
233            
234 187           ig->base.closecb = buffer_close;
235 187           ig->base.destroycb = buffer_destroy;
236              
237 187           im_context_refinc(aIMCTX, "im_io_new_bufchain");
238              
239 187           return (io_glue *)ig;
240             }
241              
242              
243             /*
244             =item im_io_new_fd(ctx, file)
245             XX
246             =order 10
247             =category I/O Layers
248              
249             Returns a new io_glue object that has the source defined as reading
250             from specified file descriptor. Note that the interface to receiving
251             data from the io_glue callbacks hasn't been done yet.
252              
253             ctx - and Imager context object
254             file - file descriptor to read/write from
255              
256             Also callable as C.
257              
258             =cut
259             */
260              
261             io_glue *
262 361           im_io_new_fd(pIMCTX, int fd) {
263             io_fdseek *ig;
264              
265 361           im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
266              
267 361           ig = mymalloc(sizeof(io_fdseek));
268 361           memset(ig, 0, sizeof(*ig));
269 361           i_io_init(aIMCTX, &ig->base, FDSEEK, fd_read, fd_write, fd_seek);
270 361           ig->fd = fd;
271              
272 361           ig->base.closecb = fd_close;
273 361           ig->base.sizecb = fd_size;
274 361           ig->base.destroycb = NULL;
275 361           im_context_refinc(aIMCTX, "im_io_new_bufchain");
276              
277 361           im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
278 361           return (io_glue *)ig;
279             }
280              
281             /*
282             =item im_io_new_cb(ctx, p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
283             XX
284             =category I/O Layers
285             =order 10
286              
287             Create a new I/O layer object that calls your supplied callbacks.
288              
289             In general the callbacks should behave like the corresponding POSIX
290             primitives.
291              
292             =over
293              
294             =item *
295              
296             C(p, buffer, length) should read up to C bytes into
297             C and return the number of bytes read. At end of file, return
298             0. On error, return -1.
299              
300             =item *
301              
302             C(p, buffer, length) should write up to C bytes from
303             C and return the number of bytes written. A return value <= 0
304             will be treated as an error.
305              
306             =item *
307              
308             C(p, offset, whence) should seek and return the new offset.
309              
310             =item *
311              
312             C(p) should return 0 on success, -1 on failure.
313              
314             =item *
315              
316             C(p) should release any memory specific to your callback
317             handlers.
318              
319             =back
320              
321             Also callable as C
322             destroycb)>.
323              
324             =cut
325             */
326              
327             io_glue *
328 129           im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb,
329             i_io_seekl_t seekcb, i_io_closel_t closecb,
330             i_io_destroyl_t destroycb) {
331             io_cb *ig;
332              
333 129           im_log((aIMCTX, 1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
334             "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
335 129           ig = mymalloc(sizeof(io_cb));
336 129           memset(ig, 0, sizeof(*ig));
337 129           i_io_init(aIMCTX, &ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
338 129           im_log((aIMCTX, 1, "(%p) <- io_new_cb\n", ig));
339              
340 129           ig->base.closecb = realseek_close;
341 129           ig->base.destroycb = realseek_destroy;
342              
343 129           ig->p = p;
344 129           ig->readcb = readcb;
345 129           ig->writecb = writecb;
346 129           ig->seekcb = seekcb;
347 129           ig->closecb = closecb;
348 129           ig->destroycb = destroycb;
349            
350 129           im_context_refinc(aIMCTX, "im_io_new_bufchain");
351              
352 129           return (io_glue *)ig;
353             }
354              
355             /*
356             =item io_slurp(ig, c)
357             X
358             =category I/O Layers
359              
360             Takes the source that the io_glue is bound to and allocates space for
361             a return buffer and returns the entire content in a single buffer.
362             Note: This only works for io_glue objects created by
363             io_new_bufchain(). It is useful for saving to scalars and such.
364              
365             ig - io_glue object
366             c - pointer to a pointer to where data should be copied to
367              
368             char *data;
369             size_t size = io_slurp(ig, &data);
370             ... do something with the data ...
371             myfree(data);
372              
373             io_slurp() will abort the program if the supplied I/O layer is not
374             from io_new_bufchain().
375              
376             =cut
377             */
378              
379             size_t
380 44           io_slurp(io_glue *ig, unsigned char **c) {
381             ssize_t rc;
382             io_ex_bchain *ieb;
383             unsigned char *cc;
384 44           io_type inn = ig->type;
385            
386 44 50         if ( inn != BUFCHAIN ) {
387 0           dIMCTXio(ig);
388 0           im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
389             }
390              
391 44           ieb = ig->exdata;
392 44           cc = *c = mymalloc( ieb->length );
393            
394 44           bufchain_seek(ig, 0, SEEK_SET);
395            
396 44           rc = bufchain_read(ig, cc, ieb->length);
397              
398 44 50         if (rc != ieb->length) {
399 0           dIMCTXio(ig);
400 0           im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %ld, request was %ld\n",
401 0           (long)rc, (long)ieb->length);
402             }
403              
404 44           return rc;
405             }
406              
407             /*
408             =item io_glue_destroy(ig)
409             X
410             =category I/O Layers
411             =order 90
412             =synopsis io_glue_destroy(ig);
413              
414             Destroy an io_glue objects. Should clean up all related buffers.
415              
416             ig - io_glue object to destroy.
417              
418             =cut
419             */
420              
421             void
422 730           io_glue_destroy(io_glue *ig) {
423 730           dIMCTXio(ig);
424 730           im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
425              
426 730 100         if (ig->destroycb)
427 369           ig->destroycb(ig);
428              
429 730 100         if (ig->buffer)
430 648           myfree(ig->buffer);
431            
432 730           myfree(ig);
433              
434 730           im_context_refdec(aIMCTX, "io_glue_destroy");
435 730           }
436              
437             /*
438             =item i_io_getc(ig)
439             =category I/O Layers
440              
441             A macro to read a single byte from a buffered I/O glue object.
442              
443             Returns EOF on failure, or a byte.
444              
445             =cut
446             */
447              
448             int
449 20075           i_io_getc_imp(io_glue *ig) {
450 20075 100         if (ig->write_ptr)
451 1           return EOF;
452            
453 20074 50         if (ig->error || ig->buf_eof)
    100          
454 4           return EOF;
455            
456 20070 100         if (!ig->buffered) {
457             unsigned char buf;
458 20004           ssize_t rc = i_io_raw_read(ig, &buf, 1);
459 20004 100         if (rc > 0) {
460 20002           return buf;
461             }
462 2 100         else if (rc == 0) {
463 1           ig->buf_eof = 1;
464 1           return EOF;
465             }
466             else {
467 1           ig->error = 1;
468 20004           return EOF;
469             }
470             }
471              
472 66 100         if (!ig->buffer)
473 59           i_io_setup_buffer(ig);
474            
475 66 100         if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
    50          
476 66 100         if (!i_io_read_fill(ig, 1))
477 4           return EOF;
478             }
479            
480 62           return *(ig->read_ptr++);
481             }
482              
483             /*
484             =item i_io_peekc(ig)
485             =category I/O Layers
486              
487             Read the next character from the stream without advancing the stream.
488              
489             On error or end of file, return EOF.
490              
491             For unbuffered streams a single character buffer will be setup.
492              
493             =cut
494             */
495              
496             int
497 23           i_io_peekc_imp(io_glue *ig) {
498 23 100         if (ig->write_ptr)
499 1           return EOF;
500              
501 22 100         if (!ig->buffer)
502 6           i_io_setup_buffer(ig);
503              
504 22 100         if (!ig->buffered) {
505 5           ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
506 5 100         if (rc > 0) {
507 1           ig->read_ptr = ig->buffer;
508 1           ig->read_end = ig->buffer + 1;
509 1           return *(ig->buffer);
510             }
511 4 100         else if (rc == 0) {
512 2           ig->buf_eof = 1;
513 2           return EOF;
514             }
515             else {
516 2           ig->error = 1;
517 2           return EOF;
518             }
519             }
520              
521 17 100         if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
    50          
522 17 100         if (ig->error || ig->buf_eof)
    100          
523 6           return EOF;
524            
525 11 100         if (!i_io_read_fill(ig, 1))
526 10           return EOF;
527             }
528              
529 1           return *(ig->read_ptr);
530             }
531              
532             /*
533             =item i_io_peekn(ig, buffer, size)
534             =category I/O Layers
535             =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
536              
537             Buffer at least C (at most C<< ig->buf_size >> bytes of data
538             from the stream and return C bytes of it to the caller in
539             C.
540              
541             This ignores the buffered state of the stream, and will always setup
542             buffering if needed.
543              
544             If no C parameter is provided to Imager::read() or
545             Imager::read_multi(), Imager will call C when probing
546             for the file format.
547              
548             Returns -1 on error, 0 if there is no data before EOF, or the number
549             of bytes read into C.
550              
551             =cut
552             */
553              
554             ssize_t
555 215           i_io_peekn(io_glue *ig, void *buf, size_t size) {
556             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
557              
558 215 100         if (size == 0) {
559 1           dIMCTXio(ig);
560 1           i_push_error(0, "peekn size must be positive");
561             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
562 1           return -1;
563             }
564              
565 214 100         if (ig->write_ptr) {
566             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
567 1           return -1;
568             }
569              
570 213 100         if (!ig->buffer)
571 202           i_io_setup_buffer(ig);
572              
573 213 100         if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
    100          
574 210 100         && !(ig->buf_eof || ig->error)) {
    100          
575 207           i_io_read_fill(ig, size);
576             }
577              
578 213 100         if (ig->read_ptr && ig->read_end != ig->read_ptr) {
    100          
579 209 100         if (size > ig->read_end - ig->read_ptr)
580 13           size = ig->read_end - ig->read_ptr;
581              
582 418 50         if (size)
583 209           memcpy(buf, ig->read_ptr, size);
584             }
585 4 100         else if (ig->buf_eof) {
586             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
587 1           return 0;
588             }
589 3 50         else if (ig->error) {
590             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
591 3           return -1;
592             }
593             else {
594             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
595 0           return -1;
596             }
597              
598             IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
599              
600 209           return size;
601             }
602              
603             /*
604             =item i_io_putc(ig, c)
605             =category I/O Layers
606              
607             Write a single character to the stream.
608              
609             On success return c, on error returns EOF
610              
611             =cut
612             */
613              
614             int
615 12           i_io_putc_imp(io_glue *ig, int c) {
616             IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
617              
618 12 100         if (!ig->buffered) {
619 3           char buf = c;
620             ssize_t write_result;
621 3           int result = c;
622              
623 3 100         if (ig->error)
624 1           return EOF;
625              
626 2           write_result = i_io_raw_write(ig, &buf, 1);
627 2 100         if (write_result != 1) {
628 1           ig->error = 1;
629 1           result = EOF;
630             IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
631             }
632             IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
633              
634 3           return result;
635             }
636              
637 9 100         if (ig->read_ptr)
638 1           return EOF;
639              
640 8 100         if (ig->error)
641 2           return EOF;
642              
643 6 100         if (!ig->buffer)
644 5           i_io_setup_buffer(ig);
645              
646 6 100         if (ig->write_ptr && ig->write_ptr == ig->write_end) {
    50          
647 1 50         if (!i_io_flush(ig))
648 1           return EOF;
649             }
650              
651 5           i_io_start_write(ig);
652              
653 5           *(ig->write_ptr)++ = c;
654              
655 5           return (unsigned char)c;
656             }
657              
658             /*
659             =item i_io_read(io, buffer, size)
660             =category I/O Layers
661              
662             Read up to C bytes from the stream C into C.
663              
664             Returns the number of bytes read. Returns 0 on end of file. Returns
665             -1 on error.
666              
667             =cut
668             */
669              
670             ssize_t
671 630752           i_io_read(io_glue *ig, void *buf, size_t size) {
672 630752           unsigned char *pbuf = buf;
673 630752           ssize_t read_total = 0;
674              
675             IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
676              
677 630752 100         if (ig->write_ptr) {
678             IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
679 1           return -1;
680             }
681              
682 630751 100         if (!ig->buffer && ig->buffered)
    100          
683 149           i_io_setup_buffer(ig);
684              
685 630751 100         if (ig->read_ptr && ig->read_ptr < ig->read_end) {
    100          
686 627979           size_t alloc = ig->read_end - ig->read_ptr;
687            
688 627979 100         if (alloc > size)
689 627122           alloc = size;
690              
691 627979           memcpy(pbuf, ig->read_ptr, alloc);
692 627979           ig->read_ptr += alloc;
693 627979           pbuf += alloc;
694 627979           size -= alloc;
695 627979           read_total += alloc;
696             }
697              
698 630751 100         if (size > 0 && !(ig->error || ig->buf_eof)) {
    50          
    100          
699 3392 100         if (!ig->buffered || size > ig->buf_size) {
    100          
700             ssize_t rc;
701            
702 9 100         while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
    100          
703 4           size -= rc;
704 4           pbuf += rc;
705 4           read_total += rc;
706             }
707            
708             IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
709              
710 5 100         if (rc < 0)
711 1           ig->error = 1;
712 4 100         else if (rc == 0)
713 1           ig->buf_eof = 1;
714              
715 5 100         if (!read_total)
716 1           return rc;
717             }
718             else {
719 3383 100         if (i_io_read_fill(ig, size)) {
720 3330           size_t alloc = ig->read_end - ig->read_ptr;
721 3330 100         if (alloc > size)
722 3296           alloc = size;
723            
724 3330           memcpy(pbuf, ig->read_ptr, alloc);
725 3330           ig->read_ptr += alloc;
726 3330           pbuf += alloc;
727 3330           size -= alloc;
728 3330           read_total += alloc;
729             }
730             else {
731 53 100         if (!read_total && ig->error) {
    100          
732             IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
733 3           return -1;
734             }
735             }
736             }
737             }
738              
739 630747 100         if (!read_total && ig->error)
    50          
740 0           read_total = -1;
741              
742             IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
743              
744 630747           return read_total;
745             }
746              
747             /*
748             =item i_io_write(io, buffer, size)
749             =category I/O Layers
750             =synopsis ssize_t result = i_io_write(io, buffer, size)
751              
752             Write to the given I/O stream.
753              
754             Returns the number of bytes written.
755              
756             =cut
757             */
758              
759             ssize_t
760 501868           i_io_write(io_glue *ig, const void *buf, size_t size) {
761 501868           const unsigned char *pbuf = buf;
762 501868           size_t write_count = 0;
763              
764             IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
765              
766 501868 100         if (!ig->buffered) {
767             ssize_t result;
768              
769 4860 100         if (ig->error) {
770             IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
771 1           return -1;
772             }
773              
774 4859           result = i_io_raw_write(ig, buf, size);
775              
776 4859 100         if (result != size) {
777 42           ig->error = 1;
778             IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
779             }
780              
781             IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
782              
783 4859           return result;
784             }
785              
786 497008 100         if (ig->read_ptr) {
787             IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
788 1           return -1;
789             }
790              
791 497007 100         if (ig->error) {
792             IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
793 1           return -1;
794             }
795              
796 497006 100         if (!ig->buffer)
797 227           i_io_setup_buffer(ig);
798              
799 497006 100         if (!ig->write_ptr)
800 232           i_io_start_write(ig);
801              
802 497006 50         if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
    100          
803 496330           size_t alloc = ig->write_end - ig->write_ptr;
804 496330 100         if (alloc > size)
805 496215           alloc = size;
806 496330           memcpy(ig->write_ptr, pbuf, alloc);
807 496330           write_count += alloc;
808 496330           size -= alloc;
809 496330           pbuf += alloc;
810 496330           ig->write_ptr += alloc;
811             }
812              
813 497006 100         if (size) {
814 676 100         if (!i_io_flush(ig)) {
815             IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
816 1 50         return write_count ? write_count : -1;
817             }
818              
819 675           i_io_start_write(ig);
820            
821 675 100         if (size > ig->buf_size) {
822             ssize_t rc;
823 205 100         while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
    100          
824 102           write_count += rc;
825 102           pbuf += rc;
826 102           size -= rc;
827             }
828 103 100         if (rc <= 0) {
829 1           ig->error = 1;
830 1 50         if (!write_count) {
831             IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
832 103           return -1;
833             }
834             }
835             }
836             else {
837 572           memcpy(ig->write_ptr, pbuf, size);
838 572           write_count += size;
839 572           ig->write_ptr += size;
840             }
841             }
842              
843             IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
844              
845 497004           return write_count;
846             }
847              
848             /*
849             =item i_io_seek(io, offset, whence)
850             =category I/O Layers
851              
852             Seek within the stream.
853              
854             Acts like perl's seek.
855              
856             =cut
857             */
858              
859             off_t
860 2584           i_io_seek(io_glue *ig, off_t offset, int whence) {
861             off_t new_off;
862              
863             IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
864              
865 2584 100         if (ig->write_ptr && ig->write_ptr != ig->write_end) {
    50          
866 8 100         if (!i_io_flush(ig))
867 1           return (off_t)(-1);
868             }
869              
870 2583 100         if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
    50          
    50          
871 1           offset -= ig->read_end - ig->read_ptr;
872              
873 2583           ig->read_ptr = ig->read_end = NULL;
874 2583           ig->write_ptr = ig->write_end = NULL;
875 2583           ig->error = 0;
876 2583           ig->buf_eof = 0;
877            
878 2583           new_off = i_io_raw_seek(ig, offset, whence);
879 2583 100         if (new_off < 0)
880 5           ig->error = 1;
881              
882             IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
883              
884 2583           return new_off;
885             }
886              
887             /*
888             =item i_io_flush(io)
889             =category I/O Layers
890              
891             Flush any buffered output.
892              
893             Returns true on success,
894              
895             =cut
896             */
897              
898             int
899 912           i_io_flush(io_glue *ig) {
900             unsigned char *bufp;
901              
902             IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
903              
904 912 100         if (ig->error) {
905             IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
906 1           return 0;
907             }
908              
909             /* nothing to do */
910 911 100         if (!ig->write_ptr)
911 1           return 1;
912              
913 910           bufp = ig->buffer;
914 1699 100         while (bufp < ig->write_ptr) {
915 798           ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
916 798 100         if (rc <= 0) {
917             IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
918 9           ig->error = 1;
919 9           return 0;
920             }
921            
922 789           bufp += rc;
923             }
924              
925 901           ig->write_ptr = ig->write_end = NULL;
926              
927             IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
928              
929 901           return 1;
930             }
931              
932             /*
933             =item i_io_close(io)
934             =category I/O Layers
935              
936             Flush any pending output and perform the close action for the stream.
937              
938             Returns 0 on success.
939              
940             =cut
941             */
942              
943             int
944 282           i_io_close(io_glue *ig) {
945 282           int result = 0;
946              
947             IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
948 282 100         if (ig->error)
949 2           result = -1;
950              
951 282 100         if (ig->write_ptr && !i_io_flush(ig))
    100          
952 6           result = -1;
953              
954 282 100         if (i_io_raw_close(ig))
955 13           result = -1;
956              
957             IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
958              
959 282           return result;
960             }
961              
962             /*
963             =item i_io_gets(ig, buffer, size, end_of_line)
964             =category I/O Layers
965             =synopsis char buffer[BUFSIZ]
966             =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
967              
968             Read up to C-1 bytes from the stream C into C.
969              
970             If the byte C is seen then no further bytes will be read.
971              
972             Returns the number of bytes read.
973              
974             Always C terminates the buffer.
975              
976             =cut
977             */
978              
979             ssize_t
980 7           i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
981 7           ssize_t read_count = 0;
982 7 50         if (size < 2)
983 0           return 0;
984 7           --size; /* room for nul */
985 36 100         while (size > 0) {
986 35 100         int byte = i_io_getc(ig);
987 35 100         if (byte == EOF)
988 1           break;
989 34           *buffer++ = byte;
990 34           ++read_count;
991 34 100         if (byte == eol)
992 5           break;
993 29           --size;
994             }
995 7           *buffer++ = '\0';
996              
997 7           return read_count;
998             }
999              
1000             /*
1001             =item i_io_init(ig, readcb, writecb, seekcb)
1002              
1003             Do common initialization for io_glue objects.
1004              
1005             =cut
1006             */
1007              
1008             static void
1009 730           i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
1010             i_io_seekp_t seekcb) {
1011 730           ig->type = type;
1012 730           ig->exdata = NULL;
1013 730           ig->readcb = readcb;
1014 730           ig->writecb = writecb;
1015 730           ig->seekcb = seekcb;
1016 730           ig->closecb = NULL;
1017 730           ig->sizecb = NULL;
1018 730           ig->destroycb = NULL;
1019 730           ig->context = aIMCTX;
1020              
1021 730           ig->buffer = NULL;
1022 730           ig->read_ptr = NULL;
1023 730           ig->read_end = NULL;
1024 730           ig->write_ptr = NULL;
1025 730           ig->write_end = NULL;
1026 730           ig->buf_size = IO_BUF_SIZE;
1027 730           ig->buf_eof = 0;
1028 730           ig->error = 0;
1029 730           ig->buffered = 1;
1030 730           }
1031              
1032             /*
1033             =item i_io_set_buffered(io, buffered)
1034             =category I/O Layers
1035              
1036             Set the buffering mode of the stream.
1037              
1038             If you switch buffering off on a stream with buffering on:
1039              
1040             =over
1041              
1042             =item *
1043              
1044             any buffered output will be flushed.
1045              
1046             =item *
1047              
1048             any existing buffered input will be consumed before reads become
1049             unbuffered.
1050              
1051             =back
1052              
1053             Returns true on success. This may fail if any buffered output cannot
1054             be flushed.
1055              
1056             =cut
1057             */
1058              
1059             int
1060 56           i_io_set_buffered(io_glue *ig, int buffered) {
1061 56 100         if (!buffered && ig->write_ptr) {
    50          
1062 0 0         if (!i_io_flush(ig)) {
1063 0           ig->error = 1;
1064 0           return 0;
1065             }
1066             }
1067 56           ig->buffered = buffered;
1068              
1069 56           return 1;
1070             }
1071              
1072             /*
1073             =item i_io_dump(ig)
1074              
1075             Dump the base fields of an io_glue object to stdout.
1076              
1077             =cut
1078             */
1079             void
1080 0           i_io_dump(io_glue *ig, int flags) {
1081 0           fprintf(IOL_DEBs, "ig %p:\n", ig);
1082 0           fprintf(IOL_DEBs, " type: %d\n", ig->type);
1083 0           fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1084 0 0         if (flags & I_IO_DUMP_CALLBACKS) {
1085 0           fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1086 0           fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1087 0           fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1088 0           fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1089 0           fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1090             }
1091 0 0         if (flags & I_IO_DUMP_BUFFER) {
1092 0           fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1093 0           fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1094 0 0         if (ig->read_ptr) {
1095 0           fprintf(IOL_DEBs, " ");
1096 0           dump_data(ig->read_ptr, ig->read_end, 0);
1097 0           putc('\n', IOL_DEBs);
1098             }
1099 0           fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1100 0           fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1101 0 0         if (ig->write_ptr) {
1102 0           fprintf(IOL_DEBs, " ");
1103 0           dump_data(ig->buffer, ig->write_ptr, 1);
1104 0           putc('\n', IOL_DEBs);
1105             }
1106 0           fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1107 0           fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1108             }
1109 0 0         if (flags & I_IO_DUMP_STATUS) {
1110 0           fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1111 0           fprintf(IOL_DEBs, " error: %d\n", ig->error);
1112 0           fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1113             }
1114 0           }
1115              
1116             /*
1117             =back
1118              
1119             =head1 INTERNAL FUNCTIONS
1120              
1121             =over
1122              
1123             =item my_strerror
1124              
1125             Calls strerror() and ensures we don't return NULL.
1126              
1127             On some platforms it's possible for strerror() to return NULL, this
1128             wrapper ensures we only get non-NULL values.
1129              
1130             =cut
1131             */
1132              
1133             static
1134 3           const char *my_strerror(int err) {
1135 3           const char *result = strerror(err);
1136            
1137 3 50         if (!result)
1138 0           result = "Unknown error";
1139            
1140 3           return result;
1141             }
1142              
1143             static void
1144 648           i_io_setup_buffer(io_glue *ig) {
1145 648           ig->buffer = mymalloc(ig->buf_size);
1146 648           }
1147              
1148             static void
1149 912           i_io_start_write(io_glue *ig) {
1150 912           ig->write_ptr = ig->buffer;
1151 912           ig->write_end = ig->buffer + ig->buf_size;
1152 912           }
1153              
1154             static int
1155 3667           i_io_read_fill(io_glue *ig, ssize_t needed) {
1156 3667           unsigned char *buf_end = ig->buffer + ig->buf_size;
1157 3667           unsigned char *buf_start = ig->buffer;
1158 3667           unsigned char *work = ig->buffer;
1159             ssize_t rc;
1160 3667           int good = 0;
1161              
1162             IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1163              
1164             /* these conditions may be unused, callers should also be checking them */
1165 3667 50         if (ig->error || ig->buf_eof)
    50          
1166 0           return 0;
1167              
1168 3667 100         if (needed > ig->buf_size)
1169 1           needed = ig->buf_size;
1170              
1171 3672 100         if (ig->read_ptr && ig->read_ptr < ig->read_end) {
    100          
1172 5           size_t kept = ig->read_end - ig->read_ptr;
1173              
1174 5 50         if (needed < kept) {
1175             IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1176 0           return 1;
1177             }
1178              
1179 5 100         if (ig->read_ptr != ig->buffer)
1180 1           memmove(ig->buffer, ig->read_ptr, kept);
1181              
1182 5           good = 1; /* we have *something* available to read */
1183 5           work = buf_start + kept;
1184 5           needed -= kept;
1185             }
1186             else {
1187 3662           work = ig->buffer;
1188             }
1189              
1190             /* there should always be buffer space the first time around, but
1191             avoid a compiler warning here */
1192 3667           rc = -1;
1193 3715 100         while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
    100          
1194 3600           work += rc;
1195 3600           good = 1;
1196 3600 100         if (needed < rc)
1197 3552           break;
1198              
1199 48           needed -= rc;
1200             }
1201              
1202 3667 100         if (rc < 0) {
1203 8           ig->error = 1;
1204             IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1205             (int)rc));
1206             }
1207 3659 100         else if (rc == 0) {
1208 106           ig->buf_eof = 1;
1209             IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1210             }
1211              
1212 3667 100         if (good) {
1213 3598           ig->read_ptr = buf_start;
1214 3598           ig->read_end = work;
1215             }
1216            
1217             IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1218             (unsigned)(ig->read_end - ig->read_ptr)));
1219 3667           return good;
1220             }
1221              
1222             /*
1223             =item dump_data(start, end, bias)
1224              
1225             Hex dump the data between C and C.
1226              
1227             If there is more than a pleasing amount of data, either dump the
1228             beginning (C) or dump the end C() of the range.
1229              
1230             =cut
1231             */
1232              
1233             static void
1234 0           dump_data(unsigned char *start, unsigned char *end, int bias) {
1235             unsigned char *p;
1236 0           size_t count = end - start;
1237              
1238 0 0         if (start == end) {
1239 0           fprintf(IOL_DEBs, "(empty)");
1240 0           return;
1241             }
1242              
1243 0 0         if (count > 15) {
1244 0 0         if (bias) {
1245 0           fprintf(IOL_DEBs, "... ");
1246 0           start = end - 14;
1247             }
1248             else {
1249 0           end = start + 14;
1250             }
1251            
1252 0 0         for (p = start; p < end; ++p) {
1253 0           fprintf(IOL_DEBs, " %02x", *p);
1254             }
1255 0           putc(' ', IOL_DEBs);
1256 0           putc('<', IOL_DEBs);
1257 0 0         for (p = start; p < end; ++p) {
1258 0 0         if (*p < ' ' || *p > '~')
    0          
1259 0           putc('.', IOL_DEBs);
1260             else
1261 0           putc(*p, IOL_DEBs);
1262             }
1263 0           putc('>', IOL_DEBs);
1264 0 0         if (!bias)
1265 0           fprintf(IOL_DEBs, " ...");
1266             }
1267             else {
1268 0 0         for (p = start; p < end; ++p) {
1269 0           fprintf(IOL_DEBs, " %02x", *p);
1270             }
1271 0           putc(' ', IOL_DEBs);
1272 0 0         for (p = start; p < end; ++p) {
1273 0 0         if (*p < ' ' || *p > '~')
    0          
1274 0           putc('.', IOL_DEBs);
1275             else
1276 0           putc(*p, IOL_DEBs);
1277             }
1278             }
1279             }
1280              
1281             /*
1282             * Callbacks for sources that cannot seek
1283             */
1284              
1285             /*
1286             * Callbacks for sources that can seek
1287             */
1288              
1289             /*
1290             =item realseek_read(ig, buf, count)
1291              
1292             Does the reading from a source that can be seeked on
1293              
1294             ig - io_glue object
1295             buf - buffer to return data in
1296             count - number of bytes to read into buffer max
1297              
1298             =cut
1299             */
1300              
1301             static
1302             ssize_t
1303 160           realseek_read(io_glue *igo, void *buf, size_t count) {
1304 160           io_cb *ig = (io_cb *)igo;
1305 160           void *p = ig->p;
1306 160           ssize_t rc = 0;
1307              
1308             IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1309             buf, (unsigned)count) );
1310 160           rc = ig->readcb(p,buf,count);
1311              
1312             IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1313              
1314 160           return rc;
1315             }
1316              
1317              
1318             /*
1319             =item realseek_write(ig, buf, count)
1320              
1321             Does the writing to a 'source' that can be seeked on
1322              
1323             ig - io_glue object
1324             buf - buffer that contains data
1325             count - number of bytes to write
1326              
1327             =cut
1328             */
1329              
1330             static
1331             ssize_t
1332 4983           realseek_write(io_glue *igo, const void *buf, size_t count) {
1333 4983           io_cb *ig = (io_cb *)igo;
1334 4983           void *p = ig->p;
1335 4983           ssize_t rc = 0;
1336 4983           size_t bc = 0;
1337 4983           char *cbuf = (char*)buf;
1338            
1339             IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1340             "count = %u\n", ig, buf, (unsigned)count) );
1341              
1342             /* Is this a good idea? Would it be better to handle differently?
1343             skip handling? */
1344 9910 100         while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
    100          
1345 4927           bc+=rc;
1346             }
1347              
1348             IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1349 4983 100         return rc < 0 ? rc : bc;
1350             }
1351              
1352              
1353             /*
1354             =item realseek_close(ig)
1355              
1356             Closes a source that can be seeked on. Not sure if this should be an
1357             actual close or not. Does nothing for now. Should be fixed.
1358              
1359             ig - data source
1360              
1361             =cut */
1362              
1363             static
1364             int
1365 38           realseek_close(io_glue *igo) {
1366 38           io_cb *ig = (io_cb *)igo;
1367 38           dIMCTXio(igo);
1368              
1369             IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1370 38           im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1371 38 50         if (ig->closecb)
1372 38           return ig->closecb(ig->p);
1373             else
1374 0           return 0;
1375             }
1376              
1377              
1378             /*
1379             =item realseek_seek(ig, offset, whence)
1380              
1381             Implements seeking for a source that is seekable, the purpose of having this is to be able to
1382             have an offset into a file that is different from what the underlying library thinks.
1383              
1384             ig - data source
1385             offset - offset into stream
1386             whence - whence argument a la lseek
1387              
1388             =cut
1389             */
1390              
1391             static
1392             off_t
1393 10           realseek_seek(io_glue *igo, off_t offset, int whence) {
1394 10           io_cb *ig = (io_cb *)igo;
1395 10           void *p = ig->p;
1396             off_t rc;
1397             IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1398 10           rc = ig->seekcb(p, offset, whence);
1399              
1400             IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1401 10           return rc;
1402             /* FIXME: How about implementing this offset handling stuff? */
1403             }
1404              
1405             static
1406             void
1407 129           realseek_destroy(io_glue *igo) {
1408 129           io_cb *ig = (io_cb *)igo;
1409              
1410 129 50         if (ig->destroycb)
1411 129           ig->destroycb(ig->p);
1412 129           }
1413              
1414             /*
1415             * Callbacks for sources that are a fixed size buffer
1416             */
1417              
1418             /*
1419             =item buffer_read(ig, buf, count)
1420              
1421             Does the reading from a buffer source
1422              
1423             ig - io_glue object
1424             buf - buffer to return data in
1425             count - number of bytes to read into buffer max
1426              
1427             =cut
1428             */
1429              
1430             static
1431             ssize_t
1432 21808           buffer_read(io_glue *igo, void *buf, size_t count) {
1433 21808           io_buffer *ig = (io_buffer *)igo;
1434              
1435             IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1436              
1437 21808 100         if ( ig->cpos+count > ig->len ) {
1438 775           dIMCTXio(igo);
1439 775           im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1440 775           count = ig->len - ig->cpos;
1441             }
1442            
1443 21808           memcpy(buf, ig->data+ig->cpos, count);
1444 21808           ig->cpos += count;
1445             IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1446 21808           return count;
1447             }
1448              
1449              
1450             /*
1451             =item buffer_write(ig, buf, count)
1452              
1453             Does nothing, returns -1
1454              
1455             ig - io_glue object
1456             buf - buffer that contains data
1457             count - number of bytes to write
1458              
1459             =cut
1460             */
1461              
1462             static
1463             ssize_t
1464 0           buffer_write(io_glue *ig, const void *buf, size_t count) {
1465 0           dIMCTXio(ig);
1466 0           im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1467 0           return -1;
1468             }
1469              
1470              
1471             /*
1472             =item buffer_close(ig)
1473              
1474             Closes a source that can be seeked on. Not sure if this should be an actual close
1475             or not. Does nothing for now. Should be fixed.
1476              
1477             ig - data source
1478              
1479             =cut
1480             */
1481              
1482             static
1483             int
1484 29           buffer_close(io_glue *ig) {
1485 29           dIMCTXio(ig);
1486 29           im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1487              
1488 29           return 0;
1489             }
1490              
1491              
1492             /*
1493             =item buffer_seek(ig, offset, whence)
1494              
1495             Implements seeking for a buffer source.
1496              
1497             ig - data source
1498             offset - offset into stream
1499             whence - whence argument a la lseek
1500              
1501             =cut
1502             */
1503              
1504             static
1505             off_t
1506 1355           buffer_seek(io_glue *igo, off_t offset, int whence) {
1507 1355           io_buffer *ig = (io_buffer *)igo;
1508 1355 100         off_t reqpos =
    100          
    50          
1509 4           calc_seek_offset(ig->cpos, ig->len, offset, whence);
1510            
1511 1355 100         if (reqpos > ig->len) {
1512 4           dIMCTXio(igo);
1513 4           im_log((aIMCTX, 1, "seeking out of readable range\n"));
1514 4           return (off_t)-1;
1515             }
1516 1351 50         if (reqpos < 0) {
1517 0           dIMCTXio(igo);
1518 0           i_push_error(0, "seek before beginning of file");
1519 0           return (off_t)-1;
1520             }
1521            
1522 1351           ig->cpos = reqpos;
1523             IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1524              
1525 1351           return reqpos;
1526             /* FIXME: How about implementing this offset handling stuff? */
1527             }
1528              
1529             static
1530             void
1531 187           buffer_destroy(io_glue *igo) {
1532 187           io_buffer *ig = (io_buffer *)igo;
1533              
1534 187 50         if (ig->closecb) {
1535 187           dIMCTXio(igo);
1536 187           im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1537             ig->closecb));
1538 187           ig->closecb(ig->closedata);
1539             }
1540 187           }
1541              
1542              
1543              
1544             /*
1545             * Callbacks for sources that are a chain of variable sized buffers
1546             */
1547              
1548              
1549              
1550             /* Helper functions for buffer chains */
1551              
1552             static
1553             io_blink*
1554 186           io_blink_new(void) {
1555             io_blink *ib;
1556              
1557             #if 0
1558             im_log((aIMCTX, 1, "io_blink_new()\n"));
1559             #endif
1560              
1561 186           ib = mymalloc(sizeof(io_blink));
1562              
1563 186           ib->next = NULL;
1564 186           ib->prev = NULL;
1565 186           ib->len = BBSIZ;
1566              
1567 186           memset(&ib->buf, 0, ib->len);
1568 186           return ib;
1569             }
1570              
1571              
1572              
1573             /*
1574             =item io_bchain_advance(ieb)
1575              
1576             Advances the buffer chain to the next link - extending if
1577             necessary. Also adjusts the cpos and tfill counters as needed.
1578              
1579             ieb - buffer chain object
1580              
1581             =cut
1582             */
1583              
1584             static
1585             void
1586 133           io_bchain_advance(io_ex_bchain *ieb) {
1587 133 50         if (ieb->cp->next == NULL) {
1588 133           ieb->tail = io_blink_new();
1589 133           ieb->tail->prev = ieb->cp;
1590 133           ieb->cp->next = ieb->tail;
1591              
1592 133           ieb->tfill = 0; /* Only set this if we added a new slice */
1593             }
1594 133           ieb->cp = ieb->cp->next;
1595 133           ieb->cpos = 0;
1596 133           }
1597              
1598              
1599              
1600             /*
1601             =item io_bchain_destroy()
1602              
1603             frees all resources used by a buffer chain.
1604              
1605             =cut
1606             */
1607              
1608             static void
1609 53           io_destroy_bufchain(io_ex_bchain *ieb) {
1610             io_blink *cp;
1611             #if 0
1612             mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1613             #endif
1614 53           cp = ieb->head;
1615            
1616 239 100         while(cp) {
1617 186           io_blink *t = cp->next;
1618 186           myfree(cp);
1619 186           cp = t;
1620             }
1621 53           }
1622              
1623              
1624              
1625              
1626             /*
1627              
1628             static
1629             void
1630             bufchain_dump(io_ex_bchain *ieb) {
1631             mm_log((1, " buf_chain_dump(ieb %p)\n"));
1632             mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1633             mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1634             mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1635             mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1636             mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1637             mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1638             mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1639             mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1640             }
1641             */
1642              
1643             /*
1644             * TRUE if lengths are NOT equal
1645             */
1646              
1647             /*
1648             static
1649             void
1650             chainlencert( io_glue *ig ) {
1651             int clen;
1652             int cfl = 0;
1653             size_t csize = 0;
1654             size_t cpos = 0;
1655             io_ex_bchain *ieb = ig->exdata;
1656             io_blink *cp = ieb->head;
1657            
1658              
1659             if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1660              
1661             while(cp) {
1662             clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1663             if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1664             if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1665            
1666             if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1667             if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1668            
1669             if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1670             if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1671              
1672             if (cp == ieb->cp) {
1673             cfl = 1;
1674             cpos += ieb->cpos;
1675             }
1676              
1677             if (!cfl) cpos += clen;
1678              
1679             csize += clen;
1680             cp = cp->next;
1681             }
1682             if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1683             if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1684             }
1685              
1686              
1687             static
1688             void
1689             chaincert( io_glue *ig) {
1690             size_t csize = 0;
1691             io_ex_bchain *ieb = ig->exdata;
1692             io_blink *cp = ieb->head;
1693            
1694             mm_log((1, "Chain verification.\n"));
1695              
1696             mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1697             mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1698             mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1699             mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1700             mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1701             mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1702             mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1703             mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1704              
1705             while(cp) {
1706             int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1707             mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1708             if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1709             if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1710            
1711             if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1712             if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1713            
1714             if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1715             if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1716              
1717             csize += clen;
1718             cp = cp->next;
1719             }
1720              
1721             mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1722             }
1723             */
1724              
1725             /*
1726             =item bufchain_read(ig, buf, count)
1727              
1728             Does the reading from a source that can be seeked on
1729              
1730             ig - io_glue object
1731             buf - buffer to return data in
1732             count - number of bytes to read into buffer max
1733              
1734             =cut
1735             */
1736              
1737             static
1738             ssize_t
1739 46           bufchain_read(io_glue *ig, void *buf, size_t count) {
1740 46           io_ex_bchain *ieb = ig->exdata;
1741 46           size_t scount = count;
1742 46           char *cbuf = buf;
1743             size_t sk;
1744 46           dIMCTXio(ig);
1745              
1746 46           im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1747              
1748 225 100         while( scount ) {
1749 180 100         int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1750 180 100         if (clen == ieb->cpos) {
1751 134 100         if (ieb->cp == ieb->tail) break; /* EOF */
1752 133           ieb->cp = ieb->cp->next;
1753 133           ieb->cpos = 0;
1754 133 100         clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1755             }
1756              
1757 179           sk = clen - ieb->cpos;
1758 179           sk = sk > scount ? scount : sk;
1759              
1760 179           memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1761 179           scount -= sk;
1762 179           ieb->cpos += sk;
1763 179           ieb->gpos += sk;
1764             }
1765              
1766 46           im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1767 46           return count-scount;
1768             }
1769              
1770              
1771              
1772              
1773              
1774             /*
1775             =item bufchain_write(ig, buf, count)
1776              
1777             Does the writing to a 'source' that can be seeked on
1778              
1779             ig - io_glue object
1780             buf - buffer that contains data
1781             count - number of bytes to write
1782              
1783             =cut
1784             */
1785              
1786             static
1787             ssize_t
1788 254           bufchain_write(io_glue *ig, const void *buf, size_t count) {
1789 254           char *cbuf = (char *)buf;
1790 254           io_ex_bchain *ieb = ig->exdata;
1791 254           size_t ocount = count;
1792             size_t sk;
1793 254           dIMCTXio(ig);
1794              
1795 254           im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1796              
1797             IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1798            
1799 629 100         while(count) {
1800 375           im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1801 375 100         if (ieb->cp->len == ieb->cpos) {
1802 133           im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1803 133           io_bchain_advance(ieb);
1804             }
1805              
1806 375           sk = ieb->cp->len - ieb->cpos;
1807 375           sk = sk > count ? count : sk;
1808 375           memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1809              
1810 375 100         if (ieb->cp == ieb->tail) {
1811 374           int extend = ieb->cpos + sk - ieb->tfill;
1812 374           im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1813 374 50         if (extend > 0) {
1814 374           ieb->length += extend;
1815 374           ieb->tfill += extend;
1816             }
1817             }
1818              
1819 375           ieb->cpos += sk;
1820 375           ieb->gpos += sk;
1821 375           count -= sk;
1822             }
1823 254           return ocount;
1824             }
1825              
1826             /*
1827             =item bufchain_close(ig)
1828              
1829             Closes a source that can be seeked on. Not sure if this should be an actual close
1830             or not. Does nothing for now. Should be fixed.
1831              
1832             ig - data source
1833              
1834             =cut
1835             */
1836              
1837             static
1838             int
1839 44           bufchain_close(io_glue *ig) {
1840 44           dIMCTXio(ig);
1841 44           im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1842             IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1843              
1844 44           return 0;
1845             }
1846              
1847              
1848             /*
1849             =item bufchain_seek(ig, offset, whence)
1850              
1851             Implements seeking for a source that is seekable, the purpose of having this is to be able to
1852             have an offset into a file that is different from what the underlying library thinks.
1853              
1854             ig - data source
1855             offset - offset into stream
1856             whence - whence argument a la lseek
1857              
1858             =cut
1859             */
1860              
1861             static
1862             off_t
1863 49           bufchain_seek(io_glue *ig, off_t offset, int whence) {
1864 49           io_ex_bchain *ieb = ig->exdata;
1865             int wrlen;
1866              
1867 49 100         off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
    100          
    50          
1868             off_t sk;
1869 49           dIMCTXio(ig);
1870              
1871 49           im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1872              
1873 49 50         if (scount < 0) {
1874 0           i_push_error(0, "invalid whence supplied or seek before start of file");
1875 0           return (off_t)-1;
1876             }
1877              
1878 49           ieb->cp = ieb->head;
1879 49           ieb->cpos = 0;
1880 49           ieb->gpos = 0;
1881            
1882 53 100         while( scount ) {
1883 4 100         int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1884 4 50         if (clen == ieb->cpos) {
1885 0 0         if (ieb->cp == ieb->tail) break; /* EOF */
1886 0           ieb->cp = ieb->cp->next;
1887 0           ieb->cpos = 0;
1888 0 0         clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1889             }
1890            
1891 4           sk = clen - ieb->cpos;
1892 4           sk = sk > scount ? scount : sk;
1893            
1894 4           scount -= sk;
1895 4           ieb->cpos += sk;
1896 4           ieb->gpos += sk;
1897             }
1898            
1899 49           wrlen = scount;
1900              
1901 49 50         if (wrlen > 0) {
1902             /*
1903             * extending file - get ieb into consistent state and then
1904             * call write which will get it to the correct position
1905             */
1906             char TB[BBSIZ];
1907 0           memset(TB, 0, BBSIZ);
1908 0           ieb->gpos = ieb->length;
1909 0           ieb->cpos = ieb->tfill;
1910            
1911 0 0         while(wrlen > 0) {
1912 0           ssize_t rc, wl = i_min(wrlen, BBSIZ);
1913 0           im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1914 0           rc = bufchain_write( ig, TB, wl );
1915 0 0         if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
1916 0           wrlen -= rc;
1917             }
1918             }
1919              
1920 49           im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1921 49           return ieb->gpos;
1922             }
1923              
1924             static
1925             void
1926 53           bufchain_destroy(io_glue *ig) {
1927 53           io_ex_bchain *ieb = ig->exdata;
1928              
1929 53           io_destroy_bufchain(ieb);
1930              
1931 53           myfree(ieb);
1932 53           }
1933              
1934             /*
1935             =item fd_read(ig, buf, count)
1936              
1937             Read callback for file descriptor IO objects.
1938              
1939             =cut
1940             */
1941 1779           static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1942 1779           io_fdseek *ig = (io_fdseek *)igo;
1943             ssize_t result;
1944             #ifdef _MSC_VER
1945             result = _read(ig->fd, buf, count);
1946             #else
1947 1779           result = read(ig->fd, buf, count);
1948             #endif
1949              
1950             IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1951             (unsigned)count, (int)result));
1952              
1953             /* 0 is valid - means EOF */
1954 1779 100         if (result < 0) {
1955 1           dIMCTXio(igo);
1956 1           im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1957             }
1958              
1959 1779           return result;
1960             }
1961              
1962 532           static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1963 532           io_fdseek *ig = (io_fdseek *)igo;
1964             ssize_t result;
1965             #ifdef _MSC_VER
1966             result = _write(ig->fd, buf, count);
1967             #else
1968 532           result = write(ig->fd, buf, count);
1969             #endif
1970              
1971             IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1972             (unsigned)count, (int)result));
1973              
1974 532 100         if (result <= 0) {
1975 1           dIMCTXio(igo);
1976 1           im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1977             }
1978              
1979 532           return result;
1980             }
1981              
1982 1224           static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1983 1224           io_fdseek *ig = (io_fdseek *)igo;
1984             off_t result;
1985             #ifdef _MSC_VER
1986             result = _lseek(ig->fd, offset, whence);
1987             #else
1988 1224           result = lseek(ig->fd, offset, whence);
1989             #endif
1990              
1991 1224 100         if (result == (off_t)-1) {
1992 1           dIMCTXio(igo);
1993 1           im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1994             }
1995              
1996 1224           return result;
1997             }
1998              
1999 173           static int fd_close(io_glue *ig) {
2000             /* no, we don't close it */
2001 173           return 0;
2002             }
2003              
2004 0           static ssize_t fd_size(io_glue *ig) {
2005 0           dIMCTXio(ig);
2006 0           im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
2007            
2008 0           return -1;
2009             }
2010              
2011              
2012             /*
2013             =back
2014              
2015             =head1 AUTHOR
2016              
2017             Arnar M. Hrafnkelsson
2018              
2019             =head1 SEE ALSO
2020              
2021             Imager(3)
2022              
2023             =cut
2024             */