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 io_new_bufchain(ctx)
161 returns a new io_glue object that has the 'empty' source and but can
162 be written to and read from later (like a pseudo file).
168 im_io_new_bufchain(pIMCTX) {
170 io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
172 im_log((aIMCTX, 1, "io_new_bufchain()\n"));
174 ig = mymalloc(sizeof(io_glue));
175 memset(ig, 0, sizeof(*ig));
176 i_io_init(aIMCTX, ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
184 ieb->head = io_blink_new();
186 ieb->tail = ieb->head;
189 ig->closecb = bufchain_close;
190 ig->destroycb = bufchain_destroy;
192 im_context_refinc(aIMCTX, "im_io_new_bufchain");
198 =item io_new_buffer(data, length)
202 Returns a new io_glue object that has the source defined as reading
203 from specified buffer. Note that the buffer is not copied.
205 data - buffer to read from
206 length - length of buffer
212 im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
215 im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
217 ig = mymalloc(sizeof(io_buffer));
218 memset(ig, 0, sizeof(*ig));
219 i_io_init(aIMCTX, &ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
222 ig->closecb = closecb;
223 ig->closedata = closedata;
227 ig->base.closecb = buffer_close;
228 ig->base.destroycb = buffer_destroy;
230 im_context_refinc(aIMCTX, "im_io_new_bufchain");
232 return (io_glue *)ig;
241 returns a new io_glue object that has the source defined as reading
242 from specified file descriptor. Note that the the interface to receiving
243 data from the io_glue callbacks hasn't been done yet.
245 fd - file descriptor to read/write from
251 im_io_new_fd(pIMCTX, int fd) {
254 im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
256 ig = mymalloc(sizeof(io_fdseek));
257 memset(ig, 0, sizeof(*ig));
258 i_io_init(aIMCTX, &ig->base, FDSEEK, fd_read, fd_write, fd_seek);
261 ig->base.closecb = fd_close;
262 ig->base.sizecb = fd_size;
263 ig->base.destroycb = NULL;
264 im_context_refinc(aIMCTX, "im_io_new_bufchain");
266 im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
267 return (io_glue *)ig;
271 =item io_new_cb(p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
275 Create a new I/O layer object that calls your supplied callbacks.
277 In general the callbacks should behave like the corresponding POSIX
284 C<read_cb>(p, buffer, length) should read up to C<length> bytes into
285 C<buffer> and return the number of bytes read. At end of file, return
286 0. On error, return -1.
290 C<write_cb>(p, buffer, length) should write up to C<length> bytes from
291 C<buffer> and return the number of bytes written. A return value <= 0
292 will be treated as an error.
296 C<seekcb>(p, offset, whence) should seek and return the new offset.
300 C<close_cb>(p) should return 0 on success, -1 on failure.
304 C<destroy_cb>(p) should release any memory specific to your callback
313 im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb,
314 i_io_seekl_t seekcb, i_io_closel_t closecb,
315 i_io_destroyl_t destroycb) {
318 im_log((aIMCTX, 1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
319 "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
320 ig = mymalloc(sizeof(io_cb));
321 memset(ig, 0, sizeof(*ig));
322 i_io_init(aIMCTX, &ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
323 im_log((aIMCTX, 1, "(%p) <- io_new_cb\n", ig));
325 ig->base.closecb = realseek_close;
326 ig->base.destroycb = realseek_destroy;
330 ig->writecb = writecb;
332 ig->closecb = closecb;
333 ig->destroycb = destroycb;
335 im_context_refinc(aIMCTX, "im_io_new_bufchain");
337 return (io_glue *)ig;
341 =item io_slurp(ig, c)
344 Takes the source that the io_glue is bound to and allocates space for
345 a return buffer and returns the entire content in a single buffer.
346 Note: This only works for io_glue objects created by
347 io_new_bufchain(). It is useful for saving to scalars and such.
350 c - pointer to a pointer to where data should be copied to
353 size_t size = io_slurp(ig, &data);
354 ... do something with the data ...
357 io_slurp() will abort the program if the supplied I/O layer is not
358 from io_new_bufchain().
364 io_slurp(io_glue *ig, unsigned char **c) {
369 io_type inn = ig->type;
371 if ( inn != BUFCHAIN ) {
373 im_fatal(aIMCTX, 0, "io_slurp: called on a source that is not from a bufchain\n");
377 cc = *c = mymalloc( ieb->length );
381 bufchain_seek(ig, 0, SEEK_SET);
383 rc = bufchain_read(ig, cc, ieb->length);
385 if (rc != ieb->length) {
387 im_fatal(aIMCTX,1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
394 =item io_glue_destroy(ig)
397 =synopsis io_glue_destroy(ig);
399 Destroy an io_glue objects. Should clean up all related buffers.
401 ig - io_glue object to destroy.
407 io_glue_destroy(io_glue *ig) {
409 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
419 im_context_refdec(aIMCTX, "io_glue_destroy");
426 A macro to read a single byte from a buffered I/O glue object.
428 Returns EOF on failure, or a byte.
434 i_io_getc_imp(io_glue *ig) {
438 if (ig->error || ig->buf_eof)
443 ssize_t rc = i_io_raw_read(ig, &buf, 1);
458 i_io_setup_buffer(ig);
460 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
461 if (!i_io_read_fill(ig, 1))
465 return *(ig->read_ptr++);
472 Read the next character from the stream without advancing the stream.
474 On error or end of file, return EOF.
476 For unbuffered streams a single character buffer will be setup.
482 i_io_peekc_imp(io_glue *ig) {
487 i_io_setup_buffer(ig);
490 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
492 ig->read_ptr = ig->buffer;
493 ig->read_end = ig->buffer + 1;
494 return *(ig->buffer);
506 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
507 if (ig->error || ig->buf_eof)
510 if (!i_io_read_fill(ig, 1))
514 return *(ig->read_ptr);
518 =item i_io_peekn(ig, buffer, size)
520 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
522 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
523 from the stream and return C<size> bytes of it to the caller in
526 This ignores the buffered state of the stream, and will always setup
529 If no C<type> parameter is provided to Imager::read() or
530 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
533 Returns -1 on error, 0 if there is no data before EOF, or the number
534 of bytes read into C<buffer>.
540 i_io_peekn(io_glue *ig, void *buf, size_t size) {
541 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
545 i_push_error(0, "peekn size must be positive");
546 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
551 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
556 i_io_setup_buffer(ig);
558 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
559 && !(ig->buf_eof || ig->error)) {
560 i_io_read_fill(ig, size);
563 if (size > ig->read_end - ig->read_ptr)
564 size = ig->read_end - ig->read_ptr;
567 memcpy(buf, ig->read_ptr, size);
568 else if (ig->buf_eof) {
569 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
572 else if (ig->error) {
573 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
577 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
581 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
587 =item i_io_putc(ig, c)
590 Write a single character to the stream.
592 On success return c, on error returns EOF
598 i_io_putc_imp(io_glue *ig, int c) {
599 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
603 ssize_t write_result;
609 write_result = i_io_raw_write(ig, &buf, 1);
610 if (write_result != 1) {
613 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
615 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
627 i_io_setup_buffer(ig);
629 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
634 i_io_start_write(ig);
636 *(ig->write_ptr)++ = c;
638 return (unsigned char)c;
642 =item i_io_read(io, buffer, size)
645 Read up to C<size> bytes from the stream C<io> into C<buffer>.
647 Returns the number of bytes read. Returns 0 on end of file. Returns
654 i_io_read(io_glue *ig, void *buf, size_t size) {
655 unsigned char *pbuf = buf;
656 ssize_t read_total = 0;
658 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
661 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
665 if (!ig->buffer && ig->buffered)
666 i_io_setup_buffer(ig);
668 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
669 size_t alloc = ig->read_end - ig->read_ptr;
674 memcpy(pbuf, ig->read_ptr, alloc);
675 ig->read_ptr += alloc;
681 if (size > 0 && !(ig->error || ig->buf_eof)) {
682 if (!ig->buffered || size > ig->buf_size) {
685 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
691 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
702 if (i_io_read_fill(ig, size)) {
703 size_t alloc = ig->read_end - ig->read_ptr;
707 memcpy(pbuf, ig->read_ptr, alloc);
708 ig->read_ptr += alloc;
714 if (!read_total && ig->error) {
715 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
722 if (!read_total && ig->error)
725 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
731 =item i_io_write(io, buffer, size)
733 =synopsis ssize_t result = i_io_write(io, buffer, size)
735 Write to the given I/O stream.
737 Returns the number of bytes written.
743 i_io_write(io_glue *ig, const void *buf, size_t size) {
744 const unsigned char *pbuf = buf;
745 size_t write_count = 0;
747 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
753 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
757 result = i_io_raw_write(ig, buf, size);
759 if (result != size) {
761 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
764 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
770 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
775 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
780 i_io_setup_buffer(ig);
783 i_io_start_write(ig);
785 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
786 size_t alloc = ig->write_end - ig->write_ptr;
789 memcpy(ig->write_ptr, pbuf, alloc);
790 write_count += alloc;
793 ig->write_ptr += alloc;
797 if (!i_io_flush(ig)) {
798 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
799 return write_count ? write_count : -1;
802 i_io_start_write(ig);
804 if (size > ig->buf_size) {
806 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
814 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
820 memcpy(ig->write_ptr, pbuf, size);
822 ig->write_ptr += size;
826 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
832 =item i_io_seek(io, offset, whence)
835 Seek within the stream.
837 Acts like perl's seek.
843 i_io_seek(io_glue *ig, off_t offset, int whence) {
846 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
848 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
853 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
854 offset -= ig->read_end - ig->read_ptr;
856 ig->read_ptr = ig->read_end = NULL;
857 ig->write_ptr = ig->write_end = NULL;
861 new_off = i_io_raw_seek(ig, offset, whence);
865 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
874 Flush any buffered output.
876 Returns true on success,
882 i_io_flush(io_glue *ig) {
885 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
888 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
897 while (bufp < ig->write_ptr) {
898 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
900 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
908 ig->write_ptr = ig->write_end = NULL;
910 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
919 Flush any pending output and perform the close action for the stream.
921 Returns 0 on success.
927 i_io_close(io_glue *ig) {
930 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
934 if (ig->write_ptr && !i_io_flush(ig))
937 if (i_io_raw_close(ig))
940 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
946 =item i_io_gets(ig, buffer, size, end_of_line)
948 =synopsis char buffer[BUFSIZ]
949 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
951 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
953 If the byte C<end_of_line> is seen then no further bytes will be read.
955 Returns the number of bytes read.
957 Always C<NUL> terminates the buffer.
963 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
964 ssize_t read_count = 0;
967 --size; /* room for nul */
969 int byte = i_io_getc(ig);
984 =item i_io_init(ig, readcb, writecb, seekcb)
986 Do common initialization for io_glue objects.
992 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
993 i_io_seekp_t seekcb) {
997 ig->writecb = writecb;
1001 ig->destroycb = NULL;
1002 ig->context = aIMCTX;
1005 ig->read_ptr = NULL;
1006 ig->read_end = NULL;
1007 ig->write_ptr = NULL;
1008 ig->write_end = NULL;
1009 ig->buf_size = IO_BUF_SIZE;
1016 =item i_io_set_buffered(io, buffered)
1017 =category I/O Layers
1019 Set the buffering mode of the stream.
1021 If you switch buffering off on a stream with buffering on:
1027 any buffered output will be flushed.
1031 any existing buffered input will be consumed before reads become
1036 Returns true on success. This may fail if any buffered output cannot
1043 i_io_set_buffered(io_glue *ig, int buffered) {
1044 if (!buffered && ig->write_ptr) {
1045 if (!i_io_flush(ig)) {
1050 ig->buffered = buffered;
1058 Dump the base fields of an io_glue object to stdout.
1063 i_io_dump(io_glue *ig, int flags) {
1064 fprintf(IOL_DEBs, "ig %p:\n", ig);
1065 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1066 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1067 if (flags & I_IO_DUMP_CALLBACKS) {
1068 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1069 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1070 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1071 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1072 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1074 if (flags & I_IO_DUMP_BUFFER) {
1075 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1076 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1078 fprintf(IOL_DEBs, " ");
1079 dump_data(ig->read_ptr, ig->read_end, 0);
1080 putc('\n', IOL_DEBs);
1082 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1083 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1084 if (ig->write_ptr) {
1085 fprintf(IOL_DEBs, " ");
1086 dump_data(ig->buffer, ig->write_ptr, 1);
1087 putc('\n', IOL_DEBs);
1089 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1090 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1092 if (flags & I_IO_DUMP_STATUS) {
1093 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1094 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1095 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1102 =head1 INTERNAL FUNCTIONS
1108 Calls strerror() and ensures we don't return NULL.
1110 On some platforms it's possible for strerror() to return NULL, this
1111 wrapper ensures we only get non-NULL values.
1117 const char *my_strerror(int err) {
1118 const char *result = strerror(err);
1121 result = "Unknown error";
1127 i_io_setup_buffer(io_glue *ig) {
1128 ig->buffer = mymalloc(ig->buf_size);
1132 i_io_start_write(io_glue *ig) {
1133 ig->write_ptr = ig->buffer;
1134 ig->write_end = ig->buffer + ig->buf_size;
1138 i_io_read_fill(io_glue *ig, ssize_t needed) {
1139 unsigned char *buf_end = ig->buffer + ig->buf_size;
1140 unsigned char *buf_start = ig->buffer;
1141 unsigned char *work = ig->buffer;
1145 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1147 /* these conditions may be unused, callers should also be checking them */
1148 if (ig->error || ig->buf_eof)
1151 if (needed > ig->buf_size)
1152 needed = ig->buf_size;
1154 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1155 size_t kept = ig->read_end - ig->read_ptr;
1157 if (needed < kept) {
1158 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1162 if (ig->read_ptr != ig->buffer)
1163 memmove(ig->buffer, ig->read_ptr, kept);
1165 good = 1; /* we have *something* available to read */
1166 work = buf_start + kept;
1173 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1184 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1189 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1193 ig->read_ptr = buf_start;
1194 ig->read_end = work;
1197 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1198 (unsigned)(ig->read_end - ig->read_ptr)));
1203 =item dump_data(start, end, bias)
1205 Hex dump the data between C<start> and C<end>.
1207 If there is more than a pleasing amount of data, either dump the
1208 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1214 dump_data(unsigned char *start, unsigned char *end, int bias) {
1216 size_t count = end - start;
1219 fprintf(IOL_DEBs, "(empty)");
1225 fprintf(IOL_DEBs, "... ");
1232 for (p = start; p < end; ++p) {
1233 fprintf(IOL_DEBs, " %02x", *p);
1235 putc(' ', IOL_DEBs);
1236 putc('<', IOL_DEBs);
1237 for (p = start; p < end; ++p) {
1238 if (*p < ' ' || *p > '~')
1239 putc('.', IOL_DEBs);
1243 putc('>', IOL_DEBs);
1245 fprintf(IOL_DEBs, " ...");
1248 for (p = start; p < end; ++p) {
1249 fprintf(IOL_DEBs, " %02x", *p);
1251 putc(' ', IOL_DEBs);
1252 for (p = start; p < end; ++p) {
1253 if (*p < ' ' || *p > '~')
1254 putc('.', IOL_DEBs);
1262 * Callbacks for sources that cannot seek
1266 * Callbacks for sources that can seek
1270 =item realseek_read(ig, buf, count)
1272 Does the reading from a source that can be seeked on
1275 buf - buffer to return data in
1276 count - number of bytes to read into buffer max
1283 realseek_read(io_glue *igo, void *buf, size_t count) {
1284 io_cb *ig = (io_cb *)igo;
1288 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1289 buf, (unsigned)count) );
1290 rc = ig->readcb(p,buf,count);
1292 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1299 =item realseek_write(ig, buf, count)
1301 Does the writing to a 'source' that can be seeked on
1304 buf - buffer that contains data
1305 count - number of bytes to write
1312 realseek_write(io_glue *igo, const void *buf, size_t count) {
1313 io_cb *ig = (io_cb *)igo;
1317 char *cbuf = (char*)buf;
1319 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1320 "count = %u\n", ig, buf, (unsigned)count) );
1322 /* Is this a good idea? Would it be better to handle differently?
1324 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1328 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1329 return rc < 0 ? rc : bc;
1334 =item realseek_close(ig)
1336 Closes a source that can be seeked on. Not sure if this should be an
1337 actual close or not. Does nothing for now. Should be fixed.
1345 realseek_close(io_glue *igo) {
1346 io_cb *ig = (io_cb *)igo;
1349 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1350 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1352 return ig->closecb(ig->p);
1358 /* realseek_seek(ig, offset, whence)
1360 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1361 have an offset into a file that is different from what the underlying library thinks.
1364 offset - offset into stream
1365 whence - whence argument a la lseek
1372 realseek_seek(io_glue *igo, off_t offset, int whence) {
1373 io_cb *ig = (io_cb *)igo;
1376 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1377 rc = ig->seekcb(p, offset, whence);
1379 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1381 /* FIXME: How about implementing this offset handling stuff? */
1386 realseek_destroy(io_glue *igo) {
1387 io_cb *ig = (io_cb *)igo;
1390 ig->destroycb(ig->p);
1394 * Callbacks for sources that are a fixed size buffer
1398 =item buffer_read(ig, buf, count)
1400 Does the reading from a buffer source
1403 buf - buffer to return data in
1404 count - number of bytes to read into buffer max
1411 buffer_read(io_glue *igo, void *buf, size_t count) {
1412 io_buffer *ig = (io_buffer *)igo;
1414 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1416 if ( ig->cpos+count > ig->len ) {
1418 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1419 count = ig->len - ig->cpos;
1422 memcpy(buf, ig->data+ig->cpos, count);
1424 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1430 =item buffer_write(ig, buf, count)
1432 Does nothing, returns -1
1435 buf - buffer that contains data
1436 count - number of bytes to write
1443 buffer_write(io_glue *ig, const void *buf, size_t count) {
1445 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1451 =item buffer_close(ig)
1453 Closes a source that can be seeked on. Not sure if this should be an actual close
1454 or not. Does nothing for now. Should be fixed.
1463 buffer_close(io_glue *ig) {
1465 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1471 /* buffer_seek(ig, offset, whence)
1473 Implements seeking for a buffer source.
1476 offset - offset into stream
1477 whence - whence argument a la lseek
1484 buffer_seek(io_glue *igo, off_t offset, int whence) {
1485 io_buffer *ig = (io_buffer *)igo;
1487 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1489 if (reqpos > ig->len) {
1491 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1496 i_push_error(0, "seek before beginning of file");
1501 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1504 /* FIXME: How about implementing this offset handling stuff? */
1509 buffer_destroy(io_glue *igo) {
1510 io_buffer *ig = (io_buffer *)igo;
1514 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1516 ig->closecb(ig->closedata);
1523 * Callbacks for sources that are a chain of variable sized buffers
1528 /* Helper functions for buffer chains */
1532 io_blink_new(void) {
1536 im_log((aIMCTX, 1, "io_blink_new()\n"));
1539 ib = mymalloc(sizeof(io_blink));
1545 memset(&ib->buf, 0, ib->len);
1552 =item io_bchain_advance(ieb)
1554 Advances the buffer chain to the next link - extending if
1555 necessary. Also adjusts the cpos and tfill counters as needed.
1557 ieb - buffer chain object
1564 io_bchain_advance(io_ex_bchain *ieb) {
1565 if (ieb->cp->next == NULL) {
1566 ieb->tail = io_blink_new();
1567 ieb->tail->prev = ieb->cp;
1568 ieb->cp->next = ieb->tail;
1570 ieb->tfill = 0; /* Only set this if we added a new slice */
1572 ieb->cp = ieb->cp->next;
1579 =item io_bchain_destroy()
1581 frees all resources used by a buffer chain.
1587 io_destroy_bufchain(io_ex_bchain *ieb) {
1590 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1595 io_blink *t = cp->next;
1608 bufchain_dump(io_ex_bchain *ieb) {
1609 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1610 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1611 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1612 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1613 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1614 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1615 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1616 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1617 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1622 * TRUE if lengths are NOT equal
1628 chainlencert( io_glue *ig ) {
1633 io_ex_bchain *ieb = ig->exdata;
1634 io_blink *cp = ieb->head;
1637 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1640 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1641 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1642 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1644 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1645 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1647 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1648 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1650 if (cp == ieb->cp) {
1655 if (!cfl) cpos += clen;
1660 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1661 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1667 chaincert( io_glue *ig) {
1669 io_ex_bchain *ieb = ig->exdata;
1670 io_blink *cp = ieb->head;
1672 mm_log((1, "Chain verification.\n"));
1674 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1675 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1676 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1677 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1678 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1679 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1680 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1681 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1684 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1685 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1686 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1687 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1689 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1690 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1692 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1693 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1699 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1704 =item bufchain_read(ig, buf, count)
1706 Does the reading from a source that can be seeked on
1709 buf - buffer to return data in
1710 count - number of bytes to read into buffer max
1717 bufchain_read(io_glue *ig, void *buf, size_t count) {
1718 io_ex_bchain *ieb = ig->exdata;
1719 size_t scount = count;
1724 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1727 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1728 if (clen == ieb->cpos) {
1729 if (ieb->cp == ieb->tail) break; /* EOF */
1730 ieb->cp = ieb->cp->next;
1732 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1735 sk = clen - ieb->cpos;
1736 sk = sk > scount ? scount : sk;
1738 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1744 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1745 return count-scount;
1753 =item bufchain_write(ig, buf, count)
1755 Does the writing to a 'source' that can be seeked on
1758 buf - buffer that contains data
1759 count - number of bytes to write
1766 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1767 char *cbuf = (char *)buf;
1768 io_ex_bchain *ieb = ig->exdata;
1769 size_t ocount = count;
1773 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1775 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1778 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1779 if (ieb->cp->len == ieb->cpos) {
1780 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1781 io_bchain_advance(ieb);
1784 sk = ieb->cp->len - ieb->cpos;
1785 sk = sk > count ? count : sk;
1786 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1788 if (ieb->cp == ieb->tail) {
1789 int extend = ieb->cpos + sk - ieb->tfill;
1790 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1792 ieb->length += extend;
1793 ieb->tfill += extend;
1805 =item bufchain_close(ig)
1807 Closes a source that can be seeked on. Not sure if this should be an actual close
1808 or not. Does nothing for now. Should be fixed.
1817 bufchain_close(io_glue *ig) {
1819 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1820 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1826 /* bufchain_seek(ig, offset, whence)
1828 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1829 have an offset into a file that is different from what the underlying library thinks.
1832 offset - offset into stream
1833 whence - whence argument a la lseek
1840 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1841 io_ex_bchain *ieb = ig->exdata;
1844 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1848 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1851 i_push_error(0, "invalid whence supplied or seek before start of file");
1855 ieb->cp = ieb->head;
1860 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1861 if (clen == ieb->cpos) {
1862 if (ieb->cp == ieb->tail) break; /* EOF */
1863 ieb->cp = ieb->cp->next;
1865 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1868 sk = clen - ieb->cpos;
1869 sk = sk > scount ? scount : sk;
1880 * extending file - get ieb into consistent state and then
1881 * call write which will get it to the correct position
1884 memset(TB, 0, BBSIZ);
1885 ieb->gpos = ieb->length;
1886 ieb->cpos = ieb->tfill;
1889 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1890 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1891 rc = bufchain_write( ig, TB, wl );
1892 if (rc != wl) im_fatal(aIMCTX, 0, "bufchain_seek: Unable to extend file\n");
1897 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1903 bufchain_destroy(io_glue *ig) {
1904 io_ex_bchain *ieb = ig->exdata;
1906 io_destroy_bufchain(ieb);
1912 =item fd_read(ig, buf, count)
1914 Read callback for file descriptor IO objects.
1918 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1919 io_fdseek *ig = (io_fdseek *)igo;
1922 result = _read(ig->fd, buf, count);
1924 result = read(ig->fd, buf, count);
1927 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1928 (unsigned)count, (int)result));
1930 /* 0 is valid - means EOF */
1933 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1939 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1940 io_fdseek *ig = (io_fdseek *)igo;
1943 result = _write(ig->fd, buf, count);
1945 result = write(ig->fd, buf, count);
1948 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1949 (unsigned)count, (int)result));
1953 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1959 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1960 io_fdseek *ig = (io_fdseek *)igo;
1963 result = _lseek(ig->fd, offset, whence);
1965 result = lseek(ig->fd, offset, whence);
1968 if (result == (off_t)-1) {
1970 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1976 static int fd_close(io_glue *ig) {
1977 /* no, we don't close it */
1981 static ssize_t fd_size(io_glue *ig) {
1983 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
1994 Arnar M. Hrafnkelsson <addi@umich.edu>