1 #define IMAGER_NO_CONTEXT
16 #define IOL_DEBs stderr
18 #define IO_BUF_SIZE 8192
20 char *io_type_names[] = { "FDSEEK", "FDNOSEEK", "BUFFER", "CBSEEK", "CBNOSEEK", "BUFCHAIN" };
22 typedef struct io_blink {
25 size_t len; /* How large is this buffer = BBZIS for now */
26 struct io_blink *next;
27 struct io_blink *prev;
40 i_io_closebufp_t closecb; /* free memory mapped segment or decrement refcount */
47 void *p; /* Callback data */
49 i_io_writel_t writecb;
51 i_io_closel_t closecb;
52 i_io_destroyl_t destroycb;
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 */
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)
75 iolayer.c - encapsulates different source of data into a single framework.
79 io_glue *ig = io_new_fd( fileno(stdin) );
80 method = io_reqmeth( IOL_NOSEEK | IOL_MMAP ); // not implemented yet
84 code that uses ig->readcb()
85 to read data goes here.
88 code that uses ig->readcb()
89 to read data goes here.
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:
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)
107 =head1 FUNCTION REFERENCE
109 Some of these functions are internal.
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);
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);
128 i_io_start_write(io_glue *ig);
130 i_io_read_fill(io_glue *ig, ssize_t needed);
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);
153 * Methods for setting up data source
157 =item im_io_new_bufchain(ctx)
158 X<im_io_new_bufchain API>X<i_io_new_bufchain API>
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).
165 Also callable as C<io_new_bufchain()>.
171 im_io_new_bufchain(pIMCTX) {
173 io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
175 im_log((aIMCTX, 1, "io_new_bufchain()\n"));
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);
187 ieb->head = io_blink_new();
189 ieb->tail = ieb->head;
192 ig->closecb = bufchain_close;
193 ig->destroycb = bufchain_destroy;
195 im_context_refinc(aIMCTX, "im_io_new_bufchain");
201 =item im_io_new_buffer(ctx, data, length)
202 X<im_io_new_buffer API>X<io_new_buffer API>
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.
209 ctx - an Imager context object
210 data - buffer to read from
211 length - length of buffer
213 Also callable as C<io_new_buffer(data, length>.
219 im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
222 im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
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);
229 ig->closecb = closecb;
230 ig->closedata = closedata;
234 ig->base.closecb = buffer_close;
235 ig->base.destroycb = buffer_destroy;
237 im_context_refinc(aIMCTX, "im_io_new_bufchain");
239 return (io_glue *)ig;
244 =item im_io_new_fd(ctx, file)
245 X<io_new_fd API>X<im_io_new_fd API>
249 Returns a new io_glue object that has the source defined as reading
250 from specified file descriptor. Note that the the interface to receiving
251 data from the io_glue callbacks hasn't been done yet.
253 ctx - and Imager context object
254 file - file descriptor to read/write from
256 Also callable as C<io_new_fd(file)>.
262 im_io_new_fd(pIMCTX, int fd) {
265 im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
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);
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");
277 im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
278 return (io_glue *)ig;
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>
287 Create a new I/O layer object that calls your supplied callbacks.
289 In general the callbacks should behave like the corresponding POSIX
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.
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.
308 C<seekcb>(p, offset, whence) should seek and return the new offset.
312 C<close_cb>(p) should return 0 on success, -1 on failure.
316 C<destroy_cb>(p) should release any memory specific to your callback
321 Also callable as C<io_new_cb(p, readcb, writecb, seekcb, closecb,
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) {
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));
340 ig->base.closecb = realseek_close;
341 ig->base.destroycb = realseek_destroy;
345 ig->writecb = writecb;
347 ig->closecb = closecb;
348 ig->destroycb = destroycb;
350 im_context_refinc(aIMCTX, "im_io_new_bufchain");
352 return (io_glue *)ig;
356 =item io_slurp(ig, c)
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.
366 c - pointer to a pointer to where data should be copied to
369 size_t size = io_slurp(ig, &data);
370 ... do something with the data ...
373 io_slurp() will abort the program if the supplied I/O layer is not
374 from io_new_bufchain().
380 io_slurp(io_glue *ig, unsigned char **c) {
385 io_type inn = ig->type;
387 if ( inn != BUFCHAIN ) {
389 im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
393 cc = *c = mymalloc( ieb->length );
397 bufchain_seek(ig, 0, SEEK_SET);
399 rc = bufchain_read(ig, cc, ieb->length);
401 if (rc != ieb->length) {
403 im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
410 =item io_glue_destroy(ig)
411 X<io_glue_destroy API>
414 =synopsis io_glue_destroy(ig);
416 Destroy an io_glue objects. Should clean up all related buffers.
418 ig - io_glue object to destroy.
424 io_glue_destroy(io_glue *ig) {
426 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
436 im_context_refdec(aIMCTX, "io_glue_destroy");
443 A macro to read a single byte from a buffered I/O glue object.
445 Returns EOF on failure, or a byte.
451 i_io_getc_imp(io_glue *ig) {
455 if (ig->error || ig->buf_eof)
460 ssize_t rc = i_io_raw_read(ig, &buf, 1);
475 i_io_setup_buffer(ig);
477 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
478 if (!i_io_read_fill(ig, 1))
482 return *(ig->read_ptr++);
489 Read the next character from the stream without advancing the stream.
491 On error or end of file, return EOF.
493 For unbuffered streams a single character buffer will be setup.
499 i_io_peekc_imp(io_glue *ig) {
504 i_io_setup_buffer(ig);
507 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
509 ig->read_ptr = ig->buffer;
510 ig->read_end = ig->buffer + 1;
511 return *(ig->buffer);
523 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
524 if (ig->error || ig->buf_eof)
527 if (!i_io_read_fill(ig, 1))
531 return *(ig->read_ptr);
535 =item i_io_peekn(ig, buffer, size)
537 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
539 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
540 from the stream and return C<size> bytes of it to the caller in
543 This ignores the buffered state of the stream, and will always setup
546 If no C<type> parameter is provided to Imager::read() or
547 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
550 Returns -1 on error, 0 if there is no data before EOF, or the number
551 of bytes read into C<buffer>.
557 i_io_peekn(io_glue *ig, void *buf, size_t size) {
558 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
562 i_push_error(0, "peekn size must be positive");
563 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
568 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
573 i_io_setup_buffer(ig);
575 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
576 && !(ig->buf_eof || ig->error)) {
577 i_io_read_fill(ig, size);
580 if (size > ig->read_end - ig->read_ptr)
581 size = ig->read_end - ig->read_ptr;
584 memcpy(buf, ig->read_ptr, size);
585 else if (ig->buf_eof) {
586 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
589 else if (ig->error) {
590 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
594 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
598 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
604 =item i_io_putc(ig, c)
607 Write a single character to the stream.
609 On success return c, on error returns EOF
615 i_io_putc_imp(io_glue *ig, int c) {
616 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
620 ssize_t write_result;
626 write_result = i_io_raw_write(ig, &buf, 1);
627 if (write_result != 1) {
630 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
632 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
644 i_io_setup_buffer(ig);
646 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
651 i_io_start_write(ig);
653 *(ig->write_ptr)++ = c;
655 return (unsigned char)c;
659 =item i_io_read(io, buffer, size)
662 Read up to C<size> bytes from the stream C<io> into C<buffer>.
664 Returns the number of bytes read. Returns 0 on end of file. Returns
671 i_io_read(io_glue *ig, void *buf, size_t size) {
672 unsigned char *pbuf = buf;
673 ssize_t read_total = 0;
675 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
678 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
682 if (!ig->buffer && ig->buffered)
683 i_io_setup_buffer(ig);
685 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
686 size_t alloc = ig->read_end - ig->read_ptr;
691 memcpy(pbuf, ig->read_ptr, alloc);
692 ig->read_ptr += alloc;
698 if (size > 0 && !(ig->error || ig->buf_eof)) {
699 if (!ig->buffered || size > ig->buf_size) {
702 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
708 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
719 if (i_io_read_fill(ig, size)) {
720 size_t alloc = ig->read_end - ig->read_ptr;
724 memcpy(pbuf, ig->read_ptr, alloc);
725 ig->read_ptr += alloc;
731 if (!read_total && ig->error) {
732 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
739 if (!read_total && ig->error)
742 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
748 =item i_io_write(io, buffer, size)
750 =synopsis ssize_t result = i_io_write(io, buffer, size)
752 Write to the given I/O stream.
754 Returns the number of bytes written.
760 i_io_write(io_glue *ig, const void *buf, size_t size) {
761 const unsigned char *pbuf = buf;
762 size_t write_count = 0;
764 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
770 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
774 result = i_io_raw_write(ig, buf, size);
776 if (result != size) {
778 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
781 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
787 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
792 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
797 i_io_setup_buffer(ig);
800 i_io_start_write(ig);
802 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
803 size_t alloc = ig->write_end - ig->write_ptr;
806 memcpy(ig->write_ptr, pbuf, alloc);
807 write_count += alloc;
810 ig->write_ptr += alloc;
814 if (!i_io_flush(ig)) {
815 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
816 return write_count ? write_count : -1;
819 i_io_start_write(ig);
821 if (size > ig->buf_size) {
823 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
831 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
837 memcpy(ig->write_ptr, pbuf, size);
839 ig->write_ptr += size;
843 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
849 =item i_io_seek(io, offset, whence)
852 Seek within the stream.
854 Acts like perl's seek.
860 i_io_seek(io_glue *ig, off_t offset, int whence) {
863 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
865 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
870 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
871 offset -= ig->read_end - ig->read_ptr;
873 ig->read_ptr = ig->read_end = NULL;
874 ig->write_ptr = ig->write_end = NULL;
878 new_off = i_io_raw_seek(ig, offset, whence);
882 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
891 Flush any buffered output.
893 Returns true on success,
899 i_io_flush(io_glue *ig) {
902 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
905 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
914 while (bufp < ig->write_ptr) {
915 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
917 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
925 ig->write_ptr = ig->write_end = NULL;
927 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
936 Flush any pending output and perform the close action for the stream.
938 Returns 0 on success.
944 i_io_close(io_glue *ig) {
947 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
951 if (ig->write_ptr && !i_io_flush(ig))
954 if (i_io_raw_close(ig))
957 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
963 =item i_io_gets(ig, buffer, size, end_of_line)
965 =synopsis char buffer[BUFSIZ]
966 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
968 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
970 If the byte C<end_of_line> is seen then no further bytes will be read.
972 Returns the number of bytes read.
974 Always C<NUL> terminates the buffer.
980 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
981 ssize_t read_count = 0;
984 --size; /* room for nul */
986 int byte = i_io_getc(ig);
1001 =item i_io_init(ig, readcb, writecb, seekcb)
1003 Do common initialization for io_glue objects.
1009 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) {
1013 ig->readcb = readcb;
1014 ig->writecb = writecb;
1015 ig->seekcb = seekcb;
1018 ig->destroycb = NULL;
1019 ig->context = aIMCTX;
1022 ig->read_ptr = NULL;
1023 ig->read_end = NULL;
1024 ig->write_ptr = NULL;
1025 ig->write_end = NULL;
1026 ig->buf_size = IO_BUF_SIZE;
1033 =item i_io_set_buffered(io, buffered)
1034 =category I/O Layers
1036 Set the buffering mode of the stream.
1038 If you switch buffering off on a stream with buffering on:
1044 any buffered output will be flushed.
1048 any existing buffered input will be consumed before reads become
1053 Returns true on success. This may fail if any buffered output cannot
1060 i_io_set_buffered(io_glue *ig, int buffered) {
1061 if (!buffered && ig->write_ptr) {
1062 if (!i_io_flush(ig)) {
1067 ig->buffered = buffered;
1075 Dump the base fields of an io_glue object to stdout.
1080 i_io_dump(io_glue *ig, int flags) {
1081 fprintf(IOL_DEBs, "ig %p:\n", ig);
1082 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1083 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1084 if (flags & I_IO_DUMP_CALLBACKS) {
1085 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1086 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1087 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1088 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1089 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1091 if (flags & I_IO_DUMP_BUFFER) {
1092 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1093 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1095 fprintf(IOL_DEBs, " ");
1096 dump_data(ig->read_ptr, ig->read_end, 0);
1097 putc('\n', IOL_DEBs);
1099 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1100 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1101 if (ig->write_ptr) {
1102 fprintf(IOL_DEBs, " ");
1103 dump_data(ig->buffer, ig->write_ptr, 1);
1104 putc('\n', IOL_DEBs);
1106 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1107 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1109 if (flags & I_IO_DUMP_STATUS) {
1110 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1111 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1112 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1119 =head1 INTERNAL FUNCTIONS
1125 Calls strerror() and ensures we don't return NULL.
1127 On some platforms it's possible for strerror() to return NULL, this
1128 wrapper ensures we only get non-NULL values.
1134 const char *my_strerror(int err) {
1135 const char *result = strerror(err);
1138 result = "Unknown error";
1144 i_io_setup_buffer(io_glue *ig) {
1145 ig->buffer = mymalloc(ig->buf_size);
1149 i_io_start_write(io_glue *ig) {
1150 ig->write_ptr = ig->buffer;
1151 ig->write_end = ig->buffer + ig->buf_size;
1155 i_io_read_fill(io_glue *ig, ssize_t needed) {
1156 unsigned char *buf_end = ig->buffer + ig->buf_size;
1157 unsigned char *buf_start = ig->buffer;
1158 unsigned char *work = ig->buffer;
1162 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1164 /* these conditions may be unused, callers should also be checking them */
1165 if (ig->error || ig->buf_eof)
1168 if (needed > ig->buf_size)
1169 needed = ig->buf_size;
1171 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1172 size_t kept = ig->read_end - ig->read_ptr;
1174 if (needed < kept) {
1175 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1179 if (ig->read_ptr != ig->buffer)
1180 memmove(ig->buffer, ig->read_ptr, kept);
1182 good = 1; /* we have *something* available to read */
1183 work = buf_start + kept;
1190 /* there should always be buffer space the first time around, but
1191 avoid a compiler warning here */
1193 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1204 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1209 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1213 ig->read_ptr = buf_start;
1214 ig->read_end = work;
1217 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1218 (unsigned)(ig->read_end - ig->read_ptr)));
1223 =item dump_data(start, end, bias)
1225 Hex dump the data between C<start> and C<end>.
1227 If there is more than a pleasing amount of data, either dump the
1228 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1234 dump_data(unsigned char *start, unsigned char *end, int bias) {
1236 size_t count = end - start;
1239 fprintf(IOL_DEBs, "(empty)");
1245 fprintf(IOL_DEBs, "... ");
1252 for (p = start; p < end; ++p) {
1253 fprintf(IOL_DEBs, " %02x", *p);
1255 putc(' ', IOL_DEBs);
1256 putc('<', IOL_DEBs);
1257 for (p = start; p < end; ++p) {
1258 if (*p < ' ' || *p > '~')
1259 putc('.', IOL_DEBs);
1263 putc('>', IOL_DEBs);
1265 fprintf(IOL_DEBs, " ...");
1268 for (p = start; p < end; ++p) {
1269 fprintf(IOL_DEBs, " %02x", *p);
1271 putc(' ', IOL_DEBs);
1272 for (p = start; p < end; ++p) {
1273 if (*p < ' ' || *p > '~')
1274 putc('.', IOL_DEBs);
1282 * Callbacks for sources that cannot seek
1286 * Callbacks for sources that can seek
1290 =item realseek_read(ig, buf, count)
1292 Does the reading from a source that can be seeked on
1295 buf - buffer to return data in
1296 count - number of bytes to read into buffer max
1303 realseek_read(io_glue *igo, void *buf, size_t count) {
1304 io_cb *ig = (io_cb *)igo;
1308 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1309 buf, (unsigned)count) );
1310 rc = ig->readcb(p,buf,count);
1312 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1319 =item realseek_write(ig, buf, count)
1321 Does the writing to a 'source' that can be seeked on
1324 buf - buffer that contains data
1325 count - number of bytes to write
1332 realseek_write(io_glue *igo, const void *buf, size_t count) {
1333 io_cb *ig = (io_cb *)igo;
1337 char *cbuf = (char*)buf;
1339 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1340 "count = %u\n", ig, buf, (unsigned)count) );
1342 /* Is this a good idea? Would it be better to handle differently?
1344 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1348 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1349 return rc < 0 ? rc : bc;
1354 =item realseek_close(ig)
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.
1365 realseek_close(io_glue *igo) {
1366 io_cb *ig = (io_cb *)igo;
1369 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1370 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1372 return ig->closecb(ig->p);
1379 =item realseek_seek(ig, offset, whence)
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.
1385 offset - offset into stream
1386 whence - whence argument a la lseek
1393 realseek_seek(io_glue *igo, off_t offset, int whence) {
1394 io_cb *ig = (io_cb *)igo;
1397 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1398 rc = ig->seekcb(p, offset, whence);
1400 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1402 /* FIXME: How about implementing this offset handling stuff? */
1407 realseek_destroy(io_glue *igo) {
1408 io_cb *ig = (io_cb *)igo;
1411 ig->destroycb(ig->p);
1415 * Callbacks for sources that are a fixed size buffer
1419 =item buffer_read(ig, buf, count)
1421 Does the reading from a buffer source
1424 buf - buffer to return data in
1425 count - number of bytes to read into buffer max
1432 buffer_read(io_glue *igo, void *buf, size_t count) {
1433 io_buffer *ig = (io_buffer *)igo;
1435 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1437 if ( ig->cpos+count > ig->len ) {
1439 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1440 count = ig->len - ig->cpos;
1443 memcpy(buf, ig->data+ig->cpos, count);
1445 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1451 =item buffer_write(ig, buf, count)
1453 Does nothing, returns -1
1456 buf - buffer that contains data
1457 count - number of bytes to write
1464 buffer_write(io_glue *ig, const void *buf, size_t count) {
1466 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1472 =item buffer_close(ig)
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.
1484 buffer_close(io_glue *ig) {
1486 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1493 =item buffer_seek(ig, offset, whence)
1495 Implements seeking for a buffer source.
1498 offset - offset into stream
1499 whence - whence argument a la lseek
1506 buffer_seek(io_glue *igo, off_t offset, int whence) {
1507 io_buffer *ig = (io_buffer *)igo;
1509 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1511 if (reqpos > ig->len) {
1513 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1518 i_push_error(0, "seek before beginning of file");
1523 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1526 /* FIXME: How about implementing this offset handling stuff? */
1531 buffer_destroy(io_glue *igo) {
1532 io_buffer *ig = (io_buffer *)igo;
1536 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1538 ig->closecb(ig->closedata);
1545 * Callbacks for sources that are a chain of variable sized buffers
1550 /* Helper functions for buffer chains */
1554 io_blink_new(void) {
1558 im_log((aIMCTX, 1, "io_blink_new()\n"));
1561 ib = mymalloc(sizeof(io_blink));
1567 memset(&ib->buf, 0, ib->len);
1574 =item io_bchain_advance(ieb)
1576 Advances the buffer chain to the next link - extending if
1577 necessary. Also adjusts the cpos and tfill counters as needed.
1579 ieb - buffer chain object
1586 io_bchain_advance(io_ex_bchain *ieb) {
1587 if (ieb->cp->next == NULL) {
1588 ieb->tail = io_blink_new();
1589 ieb->tail->prev = ieb->cp;
1590 ieb->cp->next = ieb->tail;
1592 ieb->tfill = 0; /* Only set this if we added a new slice */
1594 ieb->cp = ieb->cp->next;
1601 =item io_bchain_destroy()
1603 frees all resources used by a buffer chain.
1609 io_destroy_bufchain(io_ex_bchain *ieb) {
1612 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1617 io_blink *t = cp->next;
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 ));
1644 * TRUE if lengths are NOT equal
1650 chainlencert( io_glue *ig ) {
1655 io_ex_bchain *ieb = ig->exdata;
1656 io_blink *cp = ieb->head;
1659 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
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"));
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"));
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));
1672 if (cp == ieb->cp) {
1677 if (!cfl) cpos += clen;
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 ));
1689 chaincert( io_glue *ig) {
1691 io_ex_bchain *ieb = ig->exdata;
1692 io_blink *cp = ieb->head;
1694 mm_log((1, "Chain verification.\n"));
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 ));
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"));
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"));
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));
1721 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1726 =item bufchain_read(ig, buf, count)
1728 Does the reading from a source that can be seeked on
1731 buf - buffer to return data in
1732 count - number of bytes to read into buffer max
1739 bufchain_read(io_glue *ig, void *buf, size_t count) {
1740 io_ex_bchain *ieb = ig->exdata;
1741 size_t scount = count;
1746 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1749 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1750 if (clen == ieb->cpos) {
1751 if (ieb->cp == ieb->tail) break; /* EOF */
1752 ieb->cp = ieb->cp->next;
1754 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1757 sk = clen - ieb->cpos;
1758 sk = sk > scount ? scount : sk;
1760 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1766 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1767 return count-scount;
1775 =item bufchain_write(ig, buf, count)
1777 Does the writing to a 'source' that can be seeked on
1780 buf - buffer that contains data
1781 count - number of bytes to write
1788 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1789 char *cbuf = (char *)buf;
1790 io_ex_bchain *ieb = ig->exdata;
1791 size_t ocount = count;
1795 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
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) );
1800 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1801 if (ieb->cp->len == ieb->cpos) {
1802 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1803 io_bchain_advance(ieb);
1806 sk = ieb->cp->len - ieb->cpos;
1807 sk = sk > count ? count : sk;
1808 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1810 if (ieb->cp == ieb->tail) {
1811 int extend = ieb->cpos + sk - ieb->tfill;
1812 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1814 ieb->length += extend;
1815 ieb->tfill += extend;
1827 =item bufchain_close(ig)
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.
1839 bufchain_close(io_glue *ig) {
1841 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1842 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1849 =item bufchain_seek(ig, offset, whence)
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.
1855 offset - offset into stream
1856 whence - whence argument a la lseek
1863 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1864 io_ex_bchain *ieb = ig->exdata;
1867 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1871 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1874 i_push_error(0, "invalid whence supplied or seek before start of file");
1878 ieb->cp = ieb->head;
1883 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1884 if (clen == ieb->cpos) {
1885 if (ieb->cp == ieb->tail) break; /* EOF */
1886 ieb->cp = ieb->cp->next;
1888 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1891 sk = clen - ieb->cpos;
1892 sk = sk > scount ? scount : sk;
1903 * extending file - get ieb into consistent state and then
1904 * call write which will get it to the correct position
1907 memset(TB, 0, BBSIZ);
1908 ieb->gpos = ieb->length;
1909 ieb->cpos = ieb->tfill;
1912 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1913 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1914 rc = bufchain_write( ig, TB, wl );
1915 if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
1920 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1926 bufchain_destroy(io_glue *ig) {
1927 io_ex_bchain *ieb = ig->exdata;
1929 io_destroy_bufchain(ieb);
1935 =item fd_read(ig, buf, count)
1937 Read callback for file descriptor IO objects.
1941 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1942 io_fdseek *ig = (io_fdseek *)igo;
1945 result = _read(ig->fd, buf, count);
1947 result = read(ig->fd, buf, count);
1950 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1951 (unsigned)count, (int)result));
1953 /* 0 is valid - means EOF */
1956 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1962 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1963 io_fdseek *ig = (io_fdseek *)igo;
1966 result = _write(ig->fd, buf, count);
1968 result = write(ig->fd, buf, count);
1971 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1972 (unsigned)count, (int)result));
1976 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1982 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1983 io_fdseek *ig = (io_fdseek *)igo;
1986 result = _lseek(ig->fd, offset, whence);
1988 result = lseek(ig->fd, offset, whence);
1991 if (result == (off_t)-1) {
1993 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1999 static int fd_close(io_glue *ig) {
2000 /* no, we don't close it */
2004 static ssize_t fd_size(io_glue *ig) {
2006 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
2017 Arnar M. Hrafnkelsson <addi@umich.edu>