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);
1378 /* realseek_seek(ig, offset, whence)
1380 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1381 have an offset into a file that is different from what the underlying library thinks.
1384 offset - offset into stream
1385 whence - whence argument a la lseek
1392 realseek_seek(io_glue *igo, off_t offset, int whence) {
1393 io_cb *ig = (io_cb *)igo;
1396 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1397 rc = ig->seekcb(p, offset, whence);
1399 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1401 /* FIXME: How about implementing this offset handling stuff? */
1406 realseek_destroy(io_glue *igo) {
1407 io_cb *ig = (io_cb *)igo;
1410 ig->destroycb(ig->p);
1414 * Callbacks for sources that are a fixed size buffer
1418 =item buffer_read(ig, buf, count)
1420 Does the reading from a buffer source
1423 buf - buffer to return data in
1424 count - number of bytes to read into buffer max
1431 buffer_read(io_glue *igo, void *buf, size_t count) {
1432 io_buffer *ig = (io_buffer *)igo;
1434 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1436 if ( ig->cpos+count > ig->len ) {
1438 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1439 count = ig->len - ig->cpos;
1442 memcpy(buf, ig->data+ig->cpos, count);
1444 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1450 =item buffer_write(ig, buf, count)
1452 Does nothing, returns -1
1455 buf - buffer that contains data
1456 count - number of bytes to write
1463 buffer_write(io_glue *ig, const void *buf, size_t count) {
1465 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1471 =item buffer_close(ig)
1473 Closes a source that can be seeked on. Not sure if this should be an actual close
1474 or not. Does nothing for now. Should be fixed.
1483 buffer_close(io_glue *ig) {
1485 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1491 /* buffer_seek(ig, offset, whence)
1493 Implements seeking for a buffer source.
1496 offset - offset into stream
1497 whence - whence argument a la lseek
1504 buffer_seek(io_glue *igo, off_t offset, int whence) {
1505 io_buffer *ig = (io_buffer *)igo;
1507 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1509 if (reqpos > ig->len) {
1511 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1516 i_push_error(0, "seek before beginning of file");
1521 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1524 /* FIXME: How about implementing this offset handling stuff? */
1529 buffer_destroy(io_glue *igo) {
1530 io_buffer *ig = (io_buffer *)igo;
1534 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1536 ig->closecb(ig->closedata);
1543 * Callbacks for sources that are a chain of variable sized buffers
1548 /* Helper functions for buffer chains */
1552 io_blink_new(void) {
1556 im_log((aIMCTX, 1, "io_blink_new()\n"));
1559 ib = mymalloc(sizeof(io_blink));
1565 memset(&ib->buf, 0, ib->len);
1572 =item io_bchain_advance(ieb)
1574 Advances the buffer chain to the next link - extending if
1575 necessary. Also adjusts the cpos and tfill counters as needed.
1577 ieb - buffer chain object
1584 io_bchain_advance(io_ex_bchain *ieb) {
1585 if (ieb->cp->next == NULL) {
1586 ieb->tail = io_blink_new();
1587 ieb->tail->prev = ieb->cp;
1588 ieb->cp->next = ieb->tail;
1590 ieb->tfill = 0; /* Only set this if we added a new slice */
1592 ieb->cp = ieb->cp->next;
1599 =item io_bchain_destroy()
1601 frees all resources used by a buffer chain.
1607 io_destroy_bufchain(io_ex_bchain *ieb) {
1610 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1615 io_blink *t = cp->next;
1628 bufchain_dump(io_ex_bchain *ieb) {
1629 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1630 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1631 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1632 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1633 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1634 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1635 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1636 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1637 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1642 * TRUE if lengths are NOT equal
1648 chainlencert( io_glue *ig ) {
1653 io_ex_bchain *ieb = ig->exdata;
1654 io_blink *cp = ieb->head;
1657 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1660 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1661 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1662 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1664 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1665 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1667 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1668 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1670 if (cp == ieb->cp) {
1675 if (!cfl) cpos += clen;
1680 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1681 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1687 chaincert( io_glue *ig) {
1689 io_ex_bchain *ieb = ig->exdata;
1690 io_blink *cp = ieb->head;
1692 mm_log((1, "Chain verification.\n"));
1694 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1695 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1696 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1697 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1698 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1699 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1700 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1701 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1704 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1705 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1706 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1707 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1709 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1710 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1712 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1713 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1719 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1724 =item bufchain_read(ig, buf, count)
1726 Does the reading from a source that can be seeked on
1729 buf - buffer to return data in
1730 count - number of bytes to read into buffer max
1737 bufchain_read(io_glue *ig, void *buf, size_t count) {
1738 io_ex_bchain *ieb = ig->exdata;
1739 size_t scount = count;
1744 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1747 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1748 if (clen == ieb->cpos) {
1749 if (ieb->cp == ieb->tail) break; /* EOF */
1750 ieb->cp = ieb->cp->next;
1752 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1755 sk = clen - ieb->cpos;
1756 sk = sk > scount ? scount : sk;
1758 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1764 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1765 return count-scount;
1773 =item bufchain_write(ig, buf, count)
1775 Does the writing to a 'source' that can be seeked on
1778 buf - buffer that contains data
1779 count - number of bytes to write
1786 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1787 char *cbuf = (char *)buf;
1788 io_ex_bchain *ieb = ig->exdata;
1789 size_t ocount = count;
1793 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1795 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1798 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1799 if (ieb->cp->len == ieb->cpos) {
1800 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1801 io_bchain_advance(ieb);
1804 sk = ieb->cp->len - ieb->cpos;
1805 sk = sk > count ? count : sk;
1806 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1808 if (ieb->cp == ieb->tail) {
1809 int extend = ieb->cpos + sk - ieb->tfill;
1810 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1812 ieb->length += extend;
1813 ieb->tfill += extend;
1825 =item bufchain_close(ig)
1827 Closes a source that can be seeked on. Not sure if this should be an actual close
1828 or not. Does nothing for now. Should be fixed.
1837 bufchain_close(io_glue *ig) {
1839 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1840 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1846 /* bufchain_seek(ig, offset, whence)
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.
1852 offset - offset into stream
1853 whence - whence argument a la lseek
1860 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1861 io_ex_bchain *ieb = ig->exdata;
1864 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1868 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1871 i_push_error(0, "invalid whence supplied or seek before start of file");
1875 ieb->cp = ieb->head;
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;
1885 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1888 sk = clen - ieb->cpos;
1889 sk = sk > scount ? scount : sk;
1900 * extending file - get ieb into consistent state and then
1901 * call write which will get it to the correct position
1904 memset(TB, 0, BBSIZ);
1905 ieb->gpos = ieb->length;
1906 ieb->cpos = ieb->tfill;
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");
1917 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1923 bufchain_destroy(io_glue *ig) {
1924 io_ex_bchain *ieb = ig->exdata;
1926 io_destroy_bufchain(ieb);
1932 =item fd_read(ig, buf, count)
1934 Read callback for file descriptor IO objects.
1938 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1939 io_fdseek *ig = (io_fdseek *)igo;
1942 result = _read(ig->fd, buf, count);
1944 result = read(ig->fd, buf, count);
1947 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1948 (unsigned)count, (int)result));
1950 /* 0 is valid - means EOF */
1953 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1959 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1960 io_fdseek *ig = (io_fdseek *)igo;
1963 result = _write(ig->fd, buf, count);
1965 result = write(ig->fd, buf, count);
1968 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1969 (unsigned)count, (int)result));
1973 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1979 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1980 io_fdseek *ig = (io_fdseek *)igo;
1983 result = _lseek(ig->fd, offset, whence);
1985 result = lseek(ig->fd, offset, whence);
1988 if (result == (off_t)-1) {
1990 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1996 static int fd_close(io_glue *ig) {
1997 /* no, we don't close it */
2001 static ssize_t fd_size(io_glue *ig) {
2003 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
2014 Arnar M. Hrafnkelsson <addi@umich.edu>