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