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 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) {
384 io_type inn = ig->type;
386 if ( inn != BUFCHAIN ) {
388 im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
392 cc = *c = mymalloc( ieb->length );
394 bufchain_seek(ig, 0, SEEK_SET);
396 rc = bufchain_read(ig, cc, ieb->length);
398 if (rc != ieb->length) {
400 im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
407 =item io_glue_destroy(ig)
408 X<io_glue_destroy API>
411 =synopsis io_glue_destroy(ig);
413 Destroy an io_glue objects. Should clean up all related buffers.
415 ig - io_glue object to destroy.
421 io_glue_destroy(io_glue *ig) {
423 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
433 im_context_refdec(aIMCTX, "io_glue_destroy");
440 A macro to read a single byte from a buffered I/O glue object.
442 Returns EOF on failure, or a byte.
448 i_io_getc_imp(io_glue *ig) {
452 if (ig->error || ig->buf_eof)
457 ssize_t rc = i_io_raw_read(ig, &buf, 1);
472 i_io_setup_buffer(ig);
474 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
475 if (!i_io_read_fill(ig, 1))
479 return *(ig->read_ptr++);
486 Read the next character from the stream without advancing the stream.
488 On error or end of file, return EOF.
490 For unbuffered streams a single character buffer will be setup.
496 i_io_peekc_imp(io_glue *ig) {
501 i_io_setup_buffer(ig);
504 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
506 ig->read_ptr = ig->buffer;
507 ig->read_end = ig->buffer + 1;
508 return *(ig->buffer);
520 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
521 if (ig->error || ig->buf_eof)
524 if (!i_io_read_fill(ig, 1))
528 return *(ig->read_ptr);
532 =item i_io_peekn(ig, buffer, size)
534 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
536 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
537 from the stream and return C<size> bytes of it to the caller in
540 This ignores the buffered state of the stream, and will always setup
543 If no C<type> parameter is provided to Imager::read() or
544 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
547 Returns -1 on error, 0 if there is no data before EOF, or the number
548 of bytes read into C<buffer>.
554 i_io_peekn(io_glue *ig, void *buf, size_t size) {
555 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
559 i_push_error(0, "peekn size must be positive");
560 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
565 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
570 i_io_setup_buffer(ig);
572 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
573 && !(ig->buf_eof || ig->error)) {
574 i_io_read_fill(ig, size);
577 if (size > ig->read_end - ig->read_ptr)
578 size = ig->read_end - ig->read_ptr;
581 memcpy(buf, ig->read_ptr, size);
582 else if (ig->buf_eof) {
583 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
586 else if (ig->error) {
587 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
591 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
595 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
601 =item i_io_putc(ig, c)
604 Write a single character to the stream.
606 On success return c, on error returns EOF
612 i_io_putc_imp(io_glue *ig, int c) {
613 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
617 ssize_t write_result;
623 write_result = i_io_raw_write(ig, &buf, 1);
624 if (write_result != 1) {
627 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
629 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
641 i_io_setup_buffer(ig);
643 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
648 i_io_start_write(ig);
650 *(ig->write_ptr)++ = c;
652 return (unsigned char)c;
656 =item i_io_read(io, buffer, size)
659 Read up to C<size> bytes from the stream C<io> into C<buffer>.
661 Returns the number of bytes read. Returns 0 on end of file. Returns
668 i_io_read(io_glue *ig, void *buf, size_t size) {
669 unsigned char *pbuf = buf;
670 ssize_t read_total = 0;
672 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
675 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
679 if (!ig->buffer && ig->buffered)
680 i_io_setup_buffer(ig);
682 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
683 size_t alloc = ig->read_end - ig->read_ptr;
688 memcpy(pbuf, ig->read_ptr, alloc);
689 ig->read_ptr += alloc;
695 if (size > 0 && !(ig->error || ig->buf_eof)) {
696 if (!ig->buffered || size > ig->buf_size) {
699 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
705 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
716 if (i_io_read_fill(ig, size)) {
717 size_t alloc = ig->read_end - ig->read_ptr;
721 memcpy(pbuf, ig->read_ptr, alloc);
722 ig->read_ptr += alloc;
728 if (!read_total && ig->error) {
729 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
736 if (!read_total && ig->error)
739 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
745 =item i_io_write(io, buffer, size)
747 =synopsis ssize_t result = i_io_write(io, buffer, size)
749 Write to the given I/O stream.
751 Returns the number of bytes written.
757 i_io_write(io_glue *ig, const void *buf, size_t size) {
758 const unsigned char *pbuf = buf;
759 size_t write_count = 0;
761 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
767 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
771 result = i_io_raw_write(ig, buf, size);
773 if (result != size) {
775 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
778 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
784 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
789 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
794 i_io_setup_buffer(ig);
797 i_io_start_write(ig);
799 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
800 size_t alloc = ig->write_end - ig->write_ptr;
803 memcpy(ig->write_ptr, pbuf, alloc);
804 write_count += alloc;
807 ig->write_ptr += alloc;
811 if (!i_io_flush(ig)) {
812 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
813 return write_count ? write_count : -1;
816 i_io_start_write(ig);
818 if (size > ig->buf_size) {
820 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
828 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
834 memcpy(ig->write_ptr, pbuf, size);
836 ig->write_ptr += size;
840 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
846 =item i_io_seek(io, offset, whence)
849 Seek within the stream.
851 Acts like perl's seek.
857 i_io_seek(io_glue *ig, off_t offset, int whence) {
860 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
862 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
867 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
868 offset -= ig->read_end - ig->read_ptr;
870 ig->read_ptr = ig->read_end = NULL;
871 ig->write_ptr = ig->write_end = NULL;
875 new_off = i_io_raw_seek(ig, offset, whence);
879 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
888 Flush any buffered output.
890 Returns true on success,
896 i_io_flush(io_glue *ig) {
899 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
902 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
911 while (bufp < ig->write_ptr) {
912 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
914 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
922 ig->write_ptr = ig->write_end = NULL;
924 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
933 Flush any pending output and perform the close action for the stream.
935 Returns 0 on success.
941 i_io_close(io_glue *ig) {
944 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
948 if (ig->write_ptr && !i_io_flush(ig))
951 if (i_io_raw_close(ig))
954 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
960 =item i_io_gets(ig, buffer, size, end_of_line)
962 =synopsis char buffer[BUFSIZ]
963 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
965 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
967 If the byte C<end_of_line> is seen then no further bytes will be read.
969 Returns the number of bytes read.
971 Always C<NUL> terminates the buffer.
977 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
978 ssize_t read_count = 0;
981 --size; /* room for nul */
983 int byte = i_io_getc(ig);
998 =item i_io_init(ig, readcb, writecb, seekcb)
1000 Do common initialization for io_glue objects.
1006 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
1007 i_io_seekp_t seekcb) {
1010 ig->readcb = readcb;
1011 ig->writecb = writecb;
1012 ig->seekcb = seekcb;
1015 ig->destroycb = NULL;
1016 ig->context = aIMCTX;
1019 ig->read_ptr = NULL;
1020 ig->read_end = NULL;
1021 ig->write_ptr = NULL;
1022 ig->write_end = NULL;
1023 ig->buf_size = IO_BUF_SIZE;
1030 =item i_io_set_buffered(io, buffered)
1031 =category I/O Layers
1033 Set the buffering mode of the stream.
1035 If you switch buffering off on a stream with buffering on:
1041 any buffered output will be flushed.
1045 any existing buffered input will be consumed before reads become
1050 Returns true on success. This may fail if any buffered output cannot
1057 i_io_set_buffered(io_glue *ig, int buffered) {
1058 if (!buffered && ig->write_ptr) {
1059 if (!i_io_flush(ig)) {
1064 ig->buffered = buffered;
1072 Dump the base fields of an io_glue object to stdout.
1077 i_io_dump(io_glue *ig, int flags) {
1078 fprintf(IOL_DEBs, "ig %p:\n", ig);
1079 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1080 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1081 if (flags & I_IO_DUMP_CALLBACKS) {
1082 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1083 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1084 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1085 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1086 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1088 if (flags & I_IO_DUMP_BUFFER) {
1089 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1090 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1092 fprintf(IOL_DEBs, " ");
1093 dump_data(ig->read_ptr, ig->read_end, 0);
1094 putc('\n', IOL_DEBs);
1096 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1097 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1098 if (ig->write_ptr) {
1099 fprintf(IOL_DEBs, " ");
1100 dump_data(ig->buffer, ig->write_ptr, 1);
1101 putc('\n', IOL_DEBs);
1103 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1104 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1106 if (flags & I_IO_DUMP_STATUS) {
1107 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1108 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1109 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1116 =head1 INTERNAL FUNCTIONS
1122 Calls strerror() and ensures we don't return NULL.
1124 On some platforms it's possible for strerror() to return NULL, this
1125 wrapper ensures we only get non-NULL values.
1131 const char *my_strerror(int err) {
1132 const char *result = strerror(err);
1135 result = "Unknown error";
1141 i_io_setup_buffer(io_glue *ig) {
1142 ig->buffer = mymalloc(ig->buf_size);
1146 i_io_start_write(io_glue *ig) {
1147 ig->write_ptr = ig->buffer;
1148 ig->write_end = ig->buffer + ig->buf_size;
1152 i_io_read_fill(io_glue *ig, ssize_t needed) {
1153 unsigned char *buf_end = ig->buffer + ig->buf_size;
1154 unsigned char *buf_start = ig->buffer;
1155 unsigned char *work = ig->buffer;
1159 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1161 /* these conditions may be unused, callers should also be checking them */
1162 if (ig->error || ig->buf_eof)
1165 if (needed > ig->buf_size)
1166 needed = ig->buf_size;
1168 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1169 size_t kept = ig->read_end - ig->read_ptr;
1171 if (needed < kept) {
1172 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1176 if (ig->read_ptr != ig->buffer)
1177 memmove(ig->buffer, ig->read_ptr, kept);
1179 good = 1; /* we have *something* available to read */
1180 work = buf_start + kept;
1187 /* there should always be buffer space the first time around, but
1188 avoid a compiler warning here */
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);
1376 =item realseek_seek(ig, offset, whence)
1378 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1379 have an offset into a file that is different from what the underlying library thinks.
1382 offset - offset into stream
1383 whence - whence argument a la lseek
1390 realseek_seek(io_glue *igo, off_t offset, int whence) {
1391 io_cb *ig = (io_cb *)igo;
1394 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1395 rc = ig->seekcb(p, offset, whence);
1397 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1399 /* FIXME: How about implementing this offset handling stuff? */
1404 realseek_destroy(io_glue *igo) {
1405 io_cb *ig = (io_cb *)igo;
1408 ig->destroycb(ig->p);
1412 * Callbacks for sources that are a fixed size buffer
1416 =item buffer_read(ig, buf, count)
1418 Does the reading from a buffer source
1421 buf - buffer to return data in
1422 count - number of bytes to read into buffer max
1429 buffer_read(io_glue *igo, void *buf, size_t count) {
1430 io_buffer *ig = (io_buffer *)igo;
1432 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1434 if ( ig->cpos+count > ig->len ) {
1436 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1437 count = ig->len - ig->cpos;
1440 memcpy(buf, ig->data+ig->cpos, count);
1442 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1448 =item buffer_write(ig, buf, count)
1450 Does nothing, returns -1
1453 buf - buffer that contains data
1454 count - number of bytes to write
1461 buffer_write(io_glue *ig, const void *buf, size_t count) {
1463 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1469 =item buffer_close(ig)
1471 Closes a source that can be seeked on. Not sure if this should be an actual close
1472 or not. Does nothing for now. Should be fixed.
1481 buffer_close(io_glue *ig) {
1483 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1490 =item buffer_seek(ig, offset, whence)
1492 Implements seeking for a buffer source.
1495 offset - offset into stream
1496 whence - whence argument a la lseek
1503 buffer_seek(io_glue *igo, off_t offset, int whence) {
1504 io_buffer *ig = (io_buffer *)igo;
1506 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1508 if (reqpos > ig->len) {
1510 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1515 i_push_error(0, "seek before beginning of file");
1520 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1523 /* FIXME: How about implementing this offset handling stuff? */
1528 buffer_destroy(io_glue *igo) {
1529 io_buffer *ig = (io_buffer *)igo;
1533 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1535 ig->closecb(ig->closedata);
1542 * Callbacks for sources that are a chain of variable sized buffers
1547 /* Helper functions for buffer chains */
1551 io_blink_new(void) {
1555 im_log((aIMCTX, 1, "io_blink_new()\n"));
1558 ib = mymalloc(sizeof(io_blink));
1564 memset(&ib->buf, 0, ib->len);
1571 =item io_bchain_advance(ieb)
1573 Advances the buffer chain to the next link - extending if
1574 necessary. Also adjusts the cpos and tfill counters as needed.
1576 ieb - buffer chain object
1583 io_bchain_advance(io_ex_bchain *ieb) {
1584 if (ieb->cp->next == NULL) {
1585 ieb->tail = io_blink_new();
1586 ieb->tail->prev = ieb->cp;
1587 ieb->cp->next = ieb->tail;
1589 ieb->tfill = 0; /* Only set this if we added a new slice */
1591 ieb->cp = ieb->cp->next;
1598 =item io_bchain_destroy()
1600 frees all resources used by a buffer chain.
1606 io_destroy_bufchain(io_ex_bchain *ieb) {
1609 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1614 io_blink *t = cp->next;
1627 bufchain_dump(io_ex_bchain *ieb) {
1628 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1629 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1630 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1631 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1632 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1633 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1634 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1635 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1636 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1641 * TRUE if lengths are NOT equal
1647 chainlencert( io_glue *ig ) {
1652 io_ex_bchain *ieb = ig->exdata;
1653 io_blink *cp = ieb->head;
1656 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1659 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1660 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1661 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1663 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1664 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1666 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1667 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1669 if (cp == ieb->cp) {
1674 if (!cfl) cpos += clen;
1679 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1680 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1686 chaincert( io_glue *ig) {
1688 io_ex_bchain *ieb = ig->exdata;
1689 io_blink *cp = ieb->head;
1691 mm_log((1, "Chain verification.\n"));
1693 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1694 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1695 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1696 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1697 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1698 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1699 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1700 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1703 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1704 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1705 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1706 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1708 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1709 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1711 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1712 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1718 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1723 =item bufchain_read(ig, buf, count)
1725 Does the reading from a source that can be seeked on
1728 buf - buffer to return data in
1729 count - number of bytes to read into buffer max
1736 bufchain_read(io_glue *ig, void *buf, size_t count) {
1737 io_ex_bchain *ieb = ig->exdata;
1738 size_t scount = count;
1743 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1746 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1747 if (clen == ieb->cpos) {
1748 if (ieb->cp == ieb->tail) break; /* EOF */
1749 ieb->cp = ieb->cp->next;
1751 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1754 sk = clen - ieb->cpos;
1755 sk = sk > scount ? scount : sk;
1757 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1763 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1764 return count-scount;
1772 =item bufchain_write(ig, buf, count)
1774 Does the writing to a 'source' that can be seeked on
1777 buf - buffer that contains data
1778 count - number of bytes to write
1785 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1786 char *cbuf = (char *)buf;
1787 io_ex_bchain *ieb = ig->exdata;
1788 size_t ocount = count;
1792 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1794 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1797 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1798 if (ieb->cp->len == ieb->cpos) {
1799 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1800 io_bchain_advance(ieb);
1803 sk = ieb->cp->len - ieb->cpos;
1804 sk = sk > count ? count : sk;
1805 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1807 if (ieb->cp == ieb->tail) {
1808 int extend = ieb->cpos + sk - ieb->tfill;
1809 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1811 ieb->length += extend;
1812 ieb->tfill += extend;
1824 =item bufchain_close(ig)
1826 Closes a source that can be seeked on. Not sure if this should be an actual close
1827 or not. Does nothing for now. Should be fixed.
1836 bufchain_close(io_glue *ig) {
1838 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1839 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1846 =item 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>