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 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1201 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1206 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1210 ig->read_ptr = buf_start;
1211 ig->read_end = work;
1214 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1215 (unsigned)(ig->read_end - ig->read_ptr)));
1220 =item dump_data(start, end, bias)
1222 Hex dump the data between C<start> and C<end>.
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.
1231 dump_data(unsigned char *start, unsigned char *end, int bias) {
1233 size_t count = end - start;
1236 fprintf(IOL_DEBs, "(empty)");
1242 fprintf(IOL_DEBs, "... ");
1249 for (p = start; p < end; ++p) {
1250 fprintf(IOL_DEBs, " %02x", *p);
1252 putc(' ', IOL_DEBs);
1253 putc('<', IOL_DEBs);
1254 for (p = start; p < end; ++p) {
1255 if (*p < ' ' || *p > '~')
1256 putc('.', IOL_DEBs);
1260 putc('>', IOL_DEBs);
1262 fprintf(IOL_DEBs, " ...");
1265 for (p = start; p < end; ++p) {
1266 fprintf(IOL_DEBs, " %02x", *p);
1268 putc(' ', IOL_DEBs);
1269 for (p = start; p < end; ++p) {
1270 if (*p < ' ' || *p > '~')
1271 putc('.', IOL_DEBs);
1279 * Callbacks for sources that cannot seek
1283 * Callbacks for sources that can seek
1287 =item realseek_read(ig, buf, count)
1289 Does the reading from a source that can be seeked on
1292 buf - buffer to return data in
1293 count - number of bytes to read into buffer max
1300 realseek_read(io_glue *igo, void *buf, size_t count) {
1301 io_cb *ig = (io_cb *)igo;
1305 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1306 buf, (unsigned)count) );
1307 rc = ig->readcb(p,buf,count);
1309 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1316 =item realseek_write(ig, buf, count)
1318 Does the writing to a 'source' that can be seeked on
1321 buf - buffer that contains data
1322 count - number of bytes to write
1329 realseek_write(io_glue *igo, const void *buf, size_t count) {
1330 io_cb *ig = (io_cb *)igo;
1334 char *cbuf = (char*)buf;
1336 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1337 "count = %u\n", ig, buf, (unsigned)count) );
1339 /* Is this a good idea? Would it be better to handle differently?
1341 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1345 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1346 return rc < 0 ? rc : bc;
1351 =item realseek_close(ig)
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.
1362 realseek_close(io_glue *igo) {
1363 io_cb *ig = (io_cb *)igo;
1366 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1367 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1369 return ig->closecb(ig->p);
1375 /* realseek_seek(ig, offset, whence)
1377 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1378 have an offset into a file that is different from what the underlying library thinks.
1381 offset - offset into stream
1382 whence - whence argument a la lseek
1389 realseek_seek(io_glue *igo, off_t offset, int whence) {
1390 io_cb *ig = (io_cb *)igo;
1393 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1394 rc = ig->seekcb(p, offset, whence);
1396 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1398 /* FIXME: How about implementing this offset handling stuff? */
1403 realseek_destroy(io_glue *igo) {
1404 io_cb *ig = (io_cb *)igo;
1407 ig->destroycb(ig->p);
1411 * Callbacks for sources that are a fixed size buffer
1415 =item buffer_read(ig, buf, count)
1417 Does the reading from a buffer source
1420 buf - buffer to return data in
1421 count - number of bytes to read into buffer max
1428 buffer_read(io_glue *igo, void *buf, size_t count) {
1429 io_buffer *ig = (io_buffer *)igo;
1431 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1433 if ( ig->cpos+count > ig->len ) {
1435 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1436 count = ig->len - ig->cpos;
1439 memcpy(buf, ig->data+ig->cpos, count);
1441 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1447 =item buffer_write(ig, buf, count)
1449 Does nothing, returns -1
1452 buf - buffer that contains data
1453 count - number of bytes to write
1460 buffer_write(io_glue *ig, const void *buf, size_t count) {
1462 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1468 =item buffer_close(ig)
1470 Closes a source that can be seeked on. Not sure if this should be an actual close
1471 or not. Does nothing for now. Should be fixed.
1480 buffer_close(io_glue *ig) {
1482 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1488 /* buffer_seek(ig, offset, whence)
1490 Implements seeking for a buffer source.
1493 offset - offset into stream
1494 whence - whence argument a la lseek
1501 buffer_seek(io_glue *igo, off_t offset, int whence) {
1502 io_buffer *ig = (io_buffer *)igo;
1504 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1506 if (reqpos > ig->len) {
1508 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1513 i_push_error(0, "seek before beginning of file");
1518 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1521 /* FIXME: How about implementing this offset handling stuff? */
1526 buffer_destroy(io_glue *igo) {
1527 io_buffer *ig = (io_buffer *)igo;
1531 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1533 ig->closecb(ig->closedata);
1540 * Callbacks for sources that are a chain of variable sized buffers
1545 /* Helper functions for buffer chains */
1549 io_blink_new(void) {
1553 im_log((aIMCTX, 1, "io_blink_new()\n"));
1556 ib = mymalloc(sizeof(io_blink));
1562 memset(&ib->buf, 0, ib->len);
1569 =item io_bchain_advance(ieb)
1571 Advances the buffer chain to the next link - extending if
1572 necessary. Also adjusts the cpos and tfill counters as needed.
1574 ieb - buffer chain object
1581 io_bchain_advance(io_ex_bchain *ieb) {
1582 if (ieb->cp->next == NULL) {
1583 ieb->tail = io_blink_new();
1584 ieb->tail->prev = ieb->cp;
1585 ieb->cp->next = ieb->tail;
1587 ieb->tfill = 0; /* Only set this if we added a new slice */
1589 ieb->cp = ieb->cp->next;
1596 =item io_bchain_destroy()
1598 frees all resources used by a buffer chain.
1604 io_destroy_bufchain(io_ex_bchain *ieb) {
1607 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1612 io_blink *t = cp->next;
1625 bufchain_dump(io_ex_bchain *ieb) {
1626 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1627 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1628 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1629 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1630 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1631 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1632 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1633 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1634 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1639 * TRUE if lengths are NOT equal
1645 chainlencert( io_glue *ig ) {
1650 io_ex_bchain *ieb = ig->exdata;
1651 io_blink *cp = ieb->head;
1654 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1657 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1658 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1659 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1661 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1662 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1664 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1665 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1667 if (cp == ieb->cp) {
1672 if (!cfl) cpos += clen;
1677 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1678 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1684 chaincert( io_glue *ig) {
1686 io_ex_bchain *ieb = ig->exdata;
1687 io_blink *cp = ieb->head;
1689 mm_log((1, "Chain verification.\n"));
1691 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1692 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1693 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1694 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1695 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1696 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1697 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1698 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1701 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1702 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1703 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1704 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1706 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1707 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1709 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1710 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1716 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1721 =item bufchain_read(ig, buf, count)
1723 Does the reading from a source that can be seeked on
1726 buf - buffer to return data in
1727 count - number of bytes to read into buffer max
1734 bufchain_read(io_glue *ig, void *buf, size_t count) {
1735 io_ex_bchain *ieb = ig->exdata;
1736 size_t scount = count;
1741 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1744 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1745 if (clen == ieb->cpos) {
1746 if (ieb->cp == ieb->tail) break; /* EOF */
1747 ieb->cp = ieb->cp->next;
1749 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1752 sk = clen - ieb->cpos;
1753 sk = sk > scount ? scount : sk;
1755 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1761 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1762 return count-scount;
1770 =item bufchain_write(ig, buf, count)
1772 Does the writing to a 'source' that can be seeked on
1775 buf - buffer that contains data
1776 count - number of bytes to write
1783 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1784 char *cbuf = (char *)buf;
1785 io_ex_bchain *ieb = ig->exdata;
1786 size_t ocount = count;
1790 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1792 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 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1796 if (ieb->cp->len == ieb->cpos) {
1797 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1798 io_bchain_advance(ieb);
1801 sk = ieb->cp->len - ieb->cpos;
1802 sk = sk > count ? count : sk;
1803 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1805 if (ieb->cp == ieb->tail) {
1806 int extend = ieb->cpos + sk - ieb->tfill;
1807 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1809 ieb->length += extend;
1810 ieb->tfill += extend;
1822 =item bufchain_close(ig)
1824 Closes a source that can be seeked on. Not sure if this should be an actual close
1825 or not. Does nothing for now. Should be fixed.
1834 bufchain_close(io_glue *ig) {
1836 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1837 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1843 /* bufchain_seek(ig, offset, whence)
1845 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1846 have an offset into a file that is different from what the underlying library thinks.
1849 offset - offset into stream
1850 whence - whence argument a la lseek
1857 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1858 io_ex_bchain *ieb = ig->exdata;
1861 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1865 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1868 i_push_error(0, "invalid whence supplied or seek before start of file");
1872 ieb->cp = ieb->head;
1877 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1878 if (clen == ieb->cpos) {
1879 if (ieb->cp == ieb->tail) break; /* EOF */
1880 ieb->cp = ieb->cp->next;
1882 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1885 sk = clen - ieb->cpos;
1886 sk = sk > scount ? scount : sk;
1897 * extending file - get ieb into consistent state and then
1898 * call write which will get it to the correct position
1901 memset(TB, 0, BBSIZ);
1902 ieb->gpos = ieb->length;
1903 ieb->cpos = ieb->tfill;
1906 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1907 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1908 rc = bufchain_write( ig, TB, wl );
1909 if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
1914 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1920 bufchain_destroy(io_glue *ig) {
1921 io_ex_bchain *ieb = ig->exdata;
1923 io_destroy_bufchain(ieb);
1929 =item fd_read(ig, buf, count)
1931 Read callback for file descriptor IO objects.
1935 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1936 io_fdseek *ig = (io_fdseek *)igo;
1939 result = _read(ig->fd, buf, count);
1941 result = read(ig->fd, buf, count);
1944 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1945 (unsigned)count, (int)result));
1947 /* 0 is valid - means EOF */
1950 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1956 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1957 io_fdseek *ig = (io_fdseek *)igo;
1960 result = _write(ig->fd, buf, count);
1962 result = write(ig->fd, buf, count);
1965 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1966 (unsigned)count, (int)result));
1970 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1976 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1977 io_fdseek *ig = (io_fdseek *)igo;
1980 result = _lseek(ig->fd, offset, whence);
1982 result = lseek(ig->fd, offset, whence);
1985 if (result == (off_t)-1) {
1987 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1993 static int fd_close(io_glue *ig) {
1994 /* no, we don't close it */
1998 static ssize_t fd_size(io_glue *ig) {
2000 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
2011 Arnar M. Hrafnkelsson <addi@umich.edu>