1 #define IMAGER_NO_CONTEXT
15 #define dIMCTXio(io) dIMCTXctx((io)->context)
18 #define IOL_DEBs stderr
20 #define IO_BUF_SIZE 8192
22 char *io_type_names[] = { "FDSEEK", "FDNOSEEK", "BUFFER", "CBSEEK", "CBNOSEEK", "BUFCHAIN" };
24 typedef struct io_blink {
27 size_t len; /* How large is this buffer = BBZIS for now */
28 struct io_blink *next;
29 struct io_blink *prev;
42 i_io_closebufp_t closecb; /* free memory mapped segment or decrement refcount */
49 void *p; /* Callback data */
51 i_io_writel_t writecb;
53 i_io_closel_t closecb;
54 i_io_destroyl_t destroycb;
58 off_t offset; /* Offset of the source - not used */
59 off_t length; /* Total length of chain in bytes */
60 io_blink *head; /* Start of chain */
61 io_blink *tail; /* End of chain */
62 off_t tfill; /* End of stream in last link */
63 io_blink *cp; /* Current element of list */
64 off_t cpos; /* Offset within the current */
65 off_t gpos; /* Global position in stream */
68 /* turn current offset, file length, whence and offset into a new offset */
69 #define calc_seek_offset(curr_off, length, offset, whence) \
70 (((whence) == SEEK_SET) ? (offset) : \
71 ((whence) == SEEK_CUR) ? (curr_off) + (offset) : \
72 ((whence) == SEEK_END) ? (length) + (offset) : -1)
77 iolayer.c - encapsulates different source of data into a single framework.
81 io_glue *ig = io_new_fd( fileno(stdin) );
82 method = io_reqmeth( IOL_NOSEEK | IOL_MMAP ); // not implemented yet
86 code that uses ig->readcb()
87 to read data goes here.
90 code that uses ig->readcb()
91 to read data goes here.
100 iolayer.c implements the basic functions to create and destroy io_glue
101 objects for Imager. The typical usage pattern for data sources is:
103 1. Create the source (io_new_fd)
104 2. Define how you want to get data from it (io_reqmeth)
105 3. read from it using the interface requested (ig->readdb, ig->mmapcb)
106 4. Close the source, which
107 shouldn't really close the underlying source. (io_glue DESTROY)
109 =head1 FUNCTION REFERENCE
111 Some of these functions are internal.
119 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb,
120 i_io_writep_t writecb, i_io_seekp_t seekcb);
122 static ssize_t fd_read(io_glue *ig, void *buf, size_t count);
123 static ssize_t fd_write(io_glue *ig, const void *buf, size_t count);
124 static off_t fd_seek(io_glue *ig, off_t offset, int whence);
125 static int fd_close(io_glue *ig);
126 static ssize_t fd_size(io_glue *ig);
127 static const char *my_strerror(int err);
128 static void i_io_setup_buffer(io_glue *ig);
130 i_io_start_write(io_glue *ig);
132 i_io_read_fill(io_glue *ig, ssize_t needed);
134 dump_data(unsigned char *start, unsigned char *end, int bias);
135 static ssize_t realseek_read(io_glue *igo, void *buf, size_t count);
136 static ssize_t realseek_write(io_glue *igo, const void *buf, size_t count);
137 static int realseek_close(io_glue *igo);
138 static off_t realseek_seek(io_glue *igo, off_t offset, int whence);
139 static void realseek_destroy(io_glue *igo);
140 static ssize_t buffer_read(io_glue *igo, void *buf, size_t count);
141 static ssize_t buffer_write(io_glue *ig, const void *buf, size_t count);
142 static int buffer_close(io_glue *ig);
143 static off_t buffer_seek(io_glue *igo, off_t offset, int whence);
144 static void buffer_destroy(io_glue *igo);
145 static io_blink*io_blink_new(void);
146 static void io_bchain_advance(io_ex_bchain *ieb);
147 static void io_destroy_bufchain(io_ex_bchain *ieb);
148 static ssize_t bufchain_read(io_glue *ig, void *buf, size_t count);
149 static ssize_t bufchain_write(io_glue *ig, const void *buf, size_t count);
150 static int bufchain_close(io_glue *ig);
151 static off_t bufchain_seek(io_glue *ig, off_t offset, int whence);
152 static void bufchain_destroy(io_glue *ig);
155 * Methods for setting up data source
159 =item io_new_bufchain(ctx)
163 returns a new io_glue object that has the 'empty' source and but can
164 be written to and read from later (like a pseudo file).
170 im_io_new_bufchain(pIMCTX) {
172 io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
174 im_log((aIMCTX, 1, "io_new_bufchain()\n"));
176 ig = mymalloc(sizeof(io_glue));
177 memset(ig, 0, sizeof(*ig));
178 i_io_init(aIMCTX, ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
186 ieb->head = io_blink_new();
188 ieb->tail = ieb->head;
191 ig->closecb = bufchain_close;
192 ig->destroycb = bufchain_destroy;
194 im_context_refinc(aIMCTX, "im_io_new_bufchain");
200 =item io_new_buffer(data, length)
204 Returns a new io_glue object that has the source defined as reading
205 from specified buffer. Note that the buffer is not copied.
207 data - buffer to read from
208 length - length of buffer
214 im_io_new_buffer(pIMCTX, const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
217 im_log((aIMCTX, 1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
219 ig = mymalloc(sizeof(io_buffer));
220 memset(ig, 0, sizeof(*ig));
221 i_io_init(aIMCTX, &ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
224 ig->closecb = closecb;
225 ig->closedata = closedata;
229 ig->base.closecb = buffer_close;
230 ig->base.destroycb = buffer_destroy;
232 im_context_refinc(aIMCTX, "im_io_new_bufchain");
234 return (io_glue *)ig;
243 returns a new io_glue object that has the source defined as reading
244 from specified file descriptor. Note that the the interface to receiving
245 data from the io_glue callbacks hasn't been done yet.
247 fd - file descriptor to read/write from
253 im_io_new_fd(pIMCTX, int fd) {
256 im_log((aIMCTX, 1, "io_new_fd(fd %d)\n", fd));
258 ig = mymalloc(sizeof(io_fdseek));
259 memset(ig, 0, sizeof(*ig));
260 i_io_init(aIMCTX, &ig->base, FDSEEK, fd_read, fd_write, fd_seek);
263 ig->base.closecb = fd_close;
264 ig->base.sizecb = fd_size;
265 ig->base.destroycb = NULL;
266 im_context_refinc(aIMCTX, "im_io_new_bufchain");
268 im_log((aIMCTX, 1, "(%p) <- io_new_fd\n", ig));
269 return (io_glue *)ig;
273 =item io_new_cb(p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
277 Create a new I/O layer object that calls your supplied callbacks.
279 In general the callbacks should behave like the corresponding POSIX
286 C<read_cb>(p, buffer, length) should read up to C<length> bytes into
287 C<buffer> and return the number of bytes read. At end of file, return
288 0. On error, return -1.
292 C<write_cb>(p, buffer, length) should write up to C<length> bytes from
293 C<buffer> and return the number of bytes written. A return value <= 0
294 will be treated as an error.
298 C<seekcb>(p, offset, whence) should seek and return the new offset.
302 C<close_cb>(p) should return 0 on success, -1 on failure.
306 C<destroy_cb>(p) should release any memory specific to your callback
315 im_io_new_cb(pIMCTX, void *p, i_io_readl_t readcb, i_io_writel_t writecb,
316 i_io_seekl_t seekcb, i_io_closel_t closecb,
317 i_io_destroyl_t destroycb) {
320 im_log((aIMCTX, 1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
321 "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
322 ig = mymalloc(sizeof(io_cb));
323 memset(ig, 0, sizeof(*ig));
324 i_io_init(aIMCTX, &ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
325 im_log((aIMCTX, 1, "(%p) <- io_new_cb\n", ig));
327 ig->base.closecb = realseek_close;
328 ig->base.destroycb = realseek_destroy;
332 ig->writecb = writecb;
334 ig->closecb = closecb;
335 ig->destroycb = destroycb;
337 im_context_refinc(aIMCTX, "im_io_new_bufchain");
339 return (io_glue *)ig;
343 =item io_slurp(ig, c)
346 Takes the source that the io_glue is bound to and allocates space for
347 a return buffer and returns the entire content in a single buffer.
348 Note: This only works for io_glue objects created by
349 io_new_bufchain(). It is useful for saving to scalars and such.
352 c - pointer to a pointer to where data should be copied to
355 size_t size = io_slurp(ig, &data);
356 ... do something with the data ...
359 io_slurp() will abort the program if the supplied I/O layer is not
360 from io_new_bufchain().
366 io_slurp(io_glue *ig, unsigned char **c) {
371 io_type inn = ig->type;
373 if ( inn != BUFCHAIN ) {
374 i_fatal(0, "io_slurp: called on a source that is not from a bufchain\n");
378 cc = *c = mymalloc( ieb->length );
382 bufchain_seek(ig, 0, SEEK_SET);
384 rc = bufchain_read(ig, cc, ieb->length);
386 if (rc != ieb->length)
387 i_fatal(1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
393 =item io_glue_destroy(ig)
396 =synopsis io_glue_destroy(ig);
398 Destroy an io_glue objects. Should clean up all related buffers.
400 ig - io_glue object to destroy.
406 io_glue_destroy(io_glue *ig) {
408 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
418 im_context_refdec(aIMCTX, "io_glue_destroy");
425 A macro to read a single byte from a buffered I/O glue object.
427 Returns EOF on failure, or a byte.
433 i_io_getc_imp(io_glue *ig) {
437 if (ig->error || ig->buf_eof)
442 ssize_t rc = i_io_raw_read(ig, &buf, 1);
457 i_io_setup_buffer(ig);
459 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
460 if (!i_io_read_fill(ig, 1))
464 return *(ig->read_ptr++);
471 Read the next character from the stream without advancing the stream.
473 On error or end of file, return EOF.
475 For unbuffered streams a single character buffer will be setup.
481 i_io_peekc_imp(io_glue *ig) {
486 i_io_setup_buffer(ig);
489 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
491 ig->read_ptr = ig->buffer;
492 ig->read_end = ig->buffer + 1;
493 return *(ig->buffer);
505 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
506 if (ig->error || ig->buf_eof)
509 if (!i_io_read_fill(ig, 1))
513 return *(ig->read_ptr);
517 =item i_io_peekn(ig, buffer, size)
519 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
521 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
522 from the stream and return C<size> bytes of it to the caller in
525 This ignores the buffered state of the stream, and will always setup
528 If no C<type> parameter is provided to Imager::read() or
529 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
532 Returns -1 on error, 0 if there is no data before EOF, or the number
533 of bytes read into C<buffer>.
539 i_io_peekn(io_glue *ig, void *buf, size_t size) {
540 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
544 i_push_error(0, "peekn size must be positive");
545 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
550 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
555 i_io_setup_buffer(ig);
557 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
558 && !(ig->buf_eof || ig->error)) {
559 i_io_read_fill(ig, size);
562 if (size > ig->read_end - ig->read_ptr)
563 size = ig->read_end - ig->read_ptr;
566 memcpy(buf, ig->read_ptr, size);
567 else if (ig->buf_eof) {
568 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
571 else if (ig->error) {
572 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
576 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
580 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
586 =item i_io_putc(ig, c)
589 Write a single character to the stream.
591 On success return c, on error returns EOF
597 i_io_putc_imp(io_glue *ig, int c) {
598 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
602 ssize_t write_result;
608 write_result = i_io_raw_write(ig, &buf, 1);
609 if (write_result != 1) {
612 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
614 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
626 i_io_setup_buffer(ig);
628 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
633 i_io_start_write(ig);
635 *(ig->write_ptr)++ = c;
637 return (unsigned char)c;
641 =item i_io_read(io, buffer, size)
644 Read up to C<size> bytes from the stream C<io> into C<buffer>.
646 Returns the number of bytes read. Returns 0 on end of file. Returns
653 i_io_read(io_glue *ig, void *buf, size_t size) {
654 unsigned char *pbuf = buf;
655 ssize_t read_total = 0;
657 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
660 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
664 if (!ig->buffer && ig->buffered)
665 i_io_setup_buffer(ig);
667 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
668 size_t alloc = ig->read_end - ig->read_ptr;
673 memcpy(pbuf, ig->read_ptr, alloc);
674 ig->read_ptr += alloc;
680 if (size > 0 && !(ig->error || ig->buf_eof)) {
681 if (!ig->buffered || size > ig->buf_size) {
684 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
690 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
701 if (i_io_read_fill(ig, size)) {
702 size_t alloc = ig->read_end - ig->read_ptr;
706 memcpy(pbuf, ig->read_ptr, alloc);
707 ig->read_ptr += alloc;
713 if (!read_total && ig->error) {
714 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
721 if (!read_total && ig->error)
724 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
730 =item i_io_write(io, buffer, size)
732 =synopsis ssize_t result = i_io_write(io, buffer, size)
734 Write to the given I/O stream.
736 Returns the number of bytes written.
742 i_io_write(io_glue *ig, const void *buf, size_t size) {
743 const unsigned char *pbuf = buf;
744 size_t write_count = 0;
746 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
752 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
756 result = i_io_raw_write(ig, buf, size);
758 if (result != size) {
760 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
763 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
769 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
774 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
779 i_io_setup_buffer(ig);
782 i_io_start_write(ig);
784 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
785 size_t alloc = ig->write_end - ig->write_ptr;
788 memcpy(ig->write_ptr, pbuf, alloc);
789 write_count += alloc;
792 ig->write_ptr += alloc;
796 if (!i_io_flush(ig)) {
797 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
798 return write_count ? write_count : -1;
801 i_io_start_write(ig);
803 if (size > ig->buf_size) {
805 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
813 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
819 memcpy(ig->write_ptr, pbuf, size);
821 ig->write_ptr += size;
825 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
831 =item i_io_seek(io, offset, whence)
834 Seek within the stream.
836 Acts like perl's seek.
842 i_io_seek(io_glue *ig, off_t offset, int whence) {
845 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
847 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
852 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
853 offset -= ig->read_end - ig->read_ptr;
855 ig->read_ptr = ig->read_end = NULL;
856 ig->write_ptr = ig->write_end = NULL;
860 new_off = i_io_raw_seek(ig, offset, whence);
864 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
873 Flush any buffered output.
875 Returns true on success,
881 i_io_flush(io_glue *ig) {
884 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
887 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
896 while (bufp < ig->write_ptr) {
897 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
899 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
907 ig->write_ptr = ig->write_end = NULL;
909 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
918 Flush any pending output and perform the close action for the stream.
920 Returns 0 on success.
926 i_io_close(io_glue *ig) {
929 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
933 if (ig->write_ptr && !i_io_flush(ig))
936 if (i_io_raw_close(ig))
939 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
945 =item i_io_gets(ig, buffer, size, end_of_line)
947 =synopsis char buffer[BUFSIZ]
948 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
950 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
952 If the byte C<end_of_line> is seen then no further bytes will be read.
954 Returns the number of bytes read.
956 Always C<NUL> terminates the buffer.
962 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
963 ssize_t read_count = 0;
966 --size; /* room for nul */
968 int byte = i_io_getc(ig);
983 =item i_io_init(ig, readcb, writecb, seekcb)
985 Do common initialization for io_glue objects.
991 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
992 i_io_seekp_t seekcb) {
996 ig->writecb = writecb;
1000 ig->destroycb = NULL;
1001 ig->context = aIMCTX;
1004 ig->read_ptr = NULL;
1005 ig->read_end = NULL;
1006 ig->write_ptr = NULL;
1007 ig->write_end = NULL;
1008 ig->buf_size = IO_BUF_SIZE;
1015 =item i_io_set_buffered(io, buffered)
1016 =category I/O Layers
1018 Set the buffering mode of the stream.
1020 If you switch buffering off on a stream with buffering on:
1026 any buffered output will be flushed.
1030 any existing buffered input will be consumed before reads become
1035 Returns true on success. This may fail if any buffered output cannot
1042 i_io_set_buffered(io_glue *ig, int buffered) {
1043 if (!buffered && ig->write_ptr) {
1044 if (!i_io_flush(ig)) {
1049 ig->buffered = buffered;
1057 Dump the base fields of an io_glue object to stdout.
1062 i_io_dump(io_glue *ig, int flags) {
1063 fprintf(IOL_DEBs, "ig %p:\n", ig);
1064 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1065 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1066 if (flags & I_IO_DUMP_CALLBACKS) {
1067 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1068 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1069 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1070 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1071 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1073 if (flags & I_IO_DUMP_BUFFER) {
1074 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1075 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1077 fprintf(IOL_DEBs, " ");
1078 dump_data(ig->read_ptr, ig->read_end, 0);
1079 putc('\n', IOL_DEBs);
1081 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1082 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1083 if (ig->write_ptr) {
1084 fprintf(IOL_DEBs, " ");
1085 dump_data(ig->buffer, ig->write_ptr, 1);
1086 putc('\n', IOL_DEBs);
1088 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1089 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1091 if (flags & I_IO_DUMP_STATUS) {
1092 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1093 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1094 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1101 =head1 INTERNAL FUNCTIONS
1107 Calls strerror() and ensures we don't return NULL.
1109 On some platforms it's possible for strerror() to return NULL, this
1110 wrapper ensures we only get non-NULL values.
1116 const char *my_strerror(int err) {
1117 const char *result = strerror(err);
1120 result = "Unknown error";
1126 i_io_setup_buffer(io_glue *ig) {
1127 ig->buffer = mymalloc(ig->buf_size);
1131 i_io_start_write(io_glue *ig) {
1132 ig->write_ptr = ig->buffer;
1133 ig->write_end = ig->buffer + ig->buf_size;
1137 i_io_read_fill(io_glue *ig, ssize_t needed) {
1138 unsigned char *buf_end = ig->buffer + ig->buf_size;
1139 unsigned char *buf_start = ig->buffer;
1140 unsigned char *work = ig->buffer;
1144 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1146 /* these conditions may be unused, callers should also be checking them */
1147 if (ig->error || ig->buf_eof)
1150 if (needed > ig->buf_size)
1151 needed = ig->buf_size;
1153 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1154 size_t kept = ig->read_end - ig->read_ptr;
1156 if (needed < kept) {
1157 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1161 if (ig->read_ptr != ig->buffer)
1162 memmove(ig->buffer, ig->read_ptr, kept);
1164 good = 1; /* we have *something* available to read */
1165 work = buf_start + kept;
1172 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1183 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1188 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1192 ig->read_ptr = buf_start;
1193 ig->read_end = work;
1196 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1197 (unsigned)(ig->read_end - ig->read_ptr)));
1202 =item dump_data(start, end, bias)
1204 Hex dump the data between C<start> and C<end>.
1206 If there is more than a pleasing amount of data, either dump the
1207 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1213 dump_data(unsigned char *start, unsigned char *end, int bias) {
1215 size_t count = end - start;
1218 fprintf(IOL_DEBs, "(empty)");
1224 fprintf(IOL_DEBs, "... ");
1231 for (p = start; p < end; ++p) {
1232 fprintf(IOL_DEBs, " %02x", *p);
1234 putc(' ', IOL_DEBs);
1235 putc('<', IOL_DEBs);
1236 for (p = start; p < end; ++p) {
1237 if (*p < ' ' || *p > '~')
1238 putc('.', IOL_DEBs);
1242 putc('>', IOL_DEBs);
1244 fprintf(IOL_DEBs, " ...");
1247 for (p = start; p < end; ++p) {
1248 fprintf(IOL_DEBs, " %02x", *p);
1250 putc(' ', IOL_DEBs);
1251 for (p = start; p < end; ++p) {
1252 if (*p < ' ' || *p > '~')
1253 putc('.', IOL_DEBs);
1261 * Callbacks for sources that cannot seek
1265 * Callbacks for sources that can seek
1269 =item realseek_read(ig, buf, count)
1271 Does the reading from a source that can be seeked on
1274 buf - buffer to return data in
1275 count - number of bytes to read into buffer max
1282 realseek_read(io_glue *igo, void *buf, size_t count) {
1283 io_cb *ig = (io_cb *)igo;
1287 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1288 buf, (unsigned)count) );
1289 rc = ig->readcb(p,buf,count);
1291 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1298 =item realseek_write(ig, buf, count)
1300 Does the writing to a 'source' that can be seeked on
1303 buf - buffer that contains data
1304 count - number of bytes to write
1311 realseek_write(io_glue *igo, const void *buf, size_t count) {
1312 io_cb *ig = (io_cb *)igo;
1316 char *cbuf = (char*)buf;
1318 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1319 "count = %u\n", ig, buf, (unsigned)count) );
1321 /* Is this a good idea? Would it be better to handle differently?
1323 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1327 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1328 return rc < 0 ? rc : bc;
1333 =item realseek_close(ig)
1335 Closes a source that can be seeked on. Not sure if this should be an
1336 actual close or not. Does nothing for now. Should be fixed.
1344 realseek_close(io_glue *igo) {
1345 io_cb *ig = (io_cb *)igo;
1348 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1349 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1351 return ig->closecb(ig->p);
1357 /* realseek_seek(ig, offset, whence)
1359 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1360 have an offset into a file that is different from what the underlying library thinks.
1363 offset - offset into stream
1364 whence - whence argument a la lseek
1371 realseek_seek(io_glue *igo, off_t offset, int whence) {
1372 io_cb *ig = (io_cb *)igo;
1375 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1376 rc = ig->seekcb(p, offset, whence);
1378 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1380 /* FIXME: How about implementing this offset handling stuff? */
1385 realseek_destroy(io_glue *igo) {
1386 io_cb *ig = (io_cb *)igo;
1389 ig->destroycb(ig->p);
1393 * Callbacks for sources that are a fixed size buffer
1397 =item buffer_read(ig, buf, count)
1399 Does the reading from a buffer source
1402 buf - buffer to return data in
1403 count - number of bytes to read into buffer max
1410 buffer_read(io_glue *igo, void *buf, size_t count) {
1411 io_buffer *ig = (io_buffer *)igo;
1413 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1415 if ( ig->cpos+count > ig->len ) {
1417 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1418 count = ig->len - ig->cpos;
1421 memcpy(buf, ig->data+ig->cpos, count);
1423 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1429 =item buffer_write(ig, buf, count)
1431 Does nothing, returns -1
1434 buf - buffer that contains data
1435 count - number of bytes to write
1442 buffer_write(io_glue *ig, const void *buf, size_t count) {
1444 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1450 =item buffer_close(ig)
1452 Closes a source that can be seeked on. Not sure if this should be an actual close
1453 or not. Does nothing for now. Should be fixed.
1462 buffer_close(io_glue *ig) {
1464 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1470 /* buffer_seek(ig, offset, whence)
1472 Implements seeking for a buffer source.
1475 offset - offset into stream
1476 whence - whence argument a la lseek
1483 buffer_seek(io_glue *igo, off_t offset, int whence) {
1484 io_buffer *ig = (io_buffer *)igo;
1486 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1488 if (reqpos > ig->len) {
1490 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1495 i_push_error(0, "seek before beginning of file");
1500 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1503 /* FIXME: How about implementing this offset handling stuff? */
1508 buffer_destroy(io_glue *igo) {
1509 io_buffer *ig = (io_buffer *)igo;
1513 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1515 ig->closecb(ig->closedata);
1522 * Callbacks for sources that are a chain of variable sized buffers
1527 /* Helper functions for buffer chains */
1531 io_blink_new(void) {
1535 im_log((aIMCTX, 1, "io_blink_new()\n"));
1538 ib = mymalloc(sizeof(io_blink));
1544 memset(&ib->buf, 0, ib->len);
1551 =item io_bchain_advance(ieb)
1553 Advances the buffer chain to the next link - extending if
1554 necessary. Also adjusts the cpos and tfill counters as needed.
1556 ieb - buffer chain object
1563 io_bchain_advance(io_ex_bchain *ieb) {
1564 if (ieb->cp->next == NULL) {
1565 ieb->tail = io_blink_new();
1566 ieb->tail->prev = ieb->cp;
1567 ieb->cp->next = ieb->tail;
1569 ieb->tfill = 0; /* Only set this if we added a new slice */
1571 ieb->cp = ieb->cp->next;
1578 =item io_bchain_destroy()
1580 frees all resources used by a buffer chain.
1586 io_destroy_bufchain(io_ex_bchain *ieb) {
1589 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1594 io_blink *t = cp->next;
1607 bufchain_dump(io_ex_bchain *ieb) {
1608 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1609 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1610 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1611 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1612 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1613 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1614 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1615 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1616 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1621 * TRUE if lengths are NOT equal
1627 chainlencert( io_glue *ig ) {
1632 io_ex_bchain *ieb = ig->exdata;
1633 io_blink *cp = ieb->head;
1636 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1639 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1640 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1641 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1643 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1644 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1646 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1647 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1649 if (cp == ieb->cp) {
1654 if (!cfl) cpos += clen;
1659 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1660 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1666 chaincert( io_glue *ig) {
1668 io_ex_bchain *ieb = ig->exdata;
1669 io_blink *cp = ieb->head;
1671 mm_log((1, "Chain verification.\n"));
1673 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1674 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1675 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1676 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1677 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1678 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1679 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1680 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1683 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1684 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1685 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1686 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1688 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1689 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1691 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1692 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1698 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1703 =item bufchain_read(ig, buf, count)
1705 Does the reading from a source that can be seeked on
1708 buf - buffer to return data in
1709 count - number of bytes to read into buffer max
1716 bufchain_read(io_glue *ig, void *buf, size_t count) {
1717 io_ex_bchain *ieb = ig->exdata;
1718 size_t scount = count;
1723 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1726 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1727 if (clen == ieb->cpos) {
1728 if (ieb->cp == ieb->tail) break; /* EOF */
1729 ieb->cp = ieb->cp->next;
1731 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1734 sk = clen - ieb->cpos;
1735 sk = sk > scount ? scount : sk;
1737 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1743 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1744 return count-scount;
1752 =item bufchain_write(ig, buf, count)
1754 Does the writing to a 'source' that can be seeked on
1757 buf - buffer that contains data
1758 count - number of bytes to write
1765 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1766 char *cbuf = (char *)buf;
1767 io_ex_bchain *ieb = ig->exdata;
1768 size_t ocount = count;
1772 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1774 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1777 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1778 if (ieb->cp->len == ieb->cpos) {
1779 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1780 io_bchain_advance(ieb);
1783 sk = ieb->cp->len - ieb->cpos;
1784 sk = sk > count ? count : sk;
1785 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1787 if (ieb->cp == ieb->tail) {
1788 int extend = ieb->cpos + sk - ieb->tfill;
1789 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1791 ieb->length += extend;
1792 ieb->tfill += extend;
1804 =item bufchain_close(ig)
1806 Closes a source that can be seeked on. Not sure if this should be an actual close
1807 or not. Does nothing for now. Should be fixed.
1816 bufchain_close(io_glue *ig) {
1818 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1819 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1825 /* bufchain_seek(ig, offset, whence)
1827 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1828 have an offset into a file that is different from what the underlying library thinks.
1831 offset - offset into stream
1832 whence - whence argument a la lseek
1839 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1840 io_ex_bchain *ieb = ig->exdata;
1843 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1847 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1850 i_push_error(0, "invalid whence supplied or seek before start of file");
1854 ieb->cp = ieb->head;
1859 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1860 if (clen == ieb->cpos) {
1861 if (ieb->cp == ieb->tail) break; /* EOF */
1862 ieb->cp = ieb->cp->next;
1864 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1867 sk = clen - ieb->cpos;
1868 sk = sk > scount ? scount : sk;
1879 * extending file - get ieb into consistent state and then
1880 * call write which will get it to the correct position
1883 memset(TB, 0, BBSIZ);
1884 ieb->gpos = ieb->length;
1885 ieb->cpos = ieb->tfill;
1888 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1889 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1890 rc = bufchain_write( ig, TB, wl );
1891 if (rc != wl) i_fatal(0, "bufchain_seek: Unable to extend file\n");
1896 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1902 bufchain_destroy(io_glue *ig) {
1903 io_ex_bchain *ieb = ig->exdata;
1905 io_destroy_bufchain(ieb);
1911 =item fd_read(ig, buf, count)
1913 Read callback for file descriptor IO objects.
1917 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1918 io_fdseek *ig = (io_fdseek *)igo;
1921 result = _read(ig->fd, buf, count);
1923 result = read(ig->fd, buf, count);
1926 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1927 (unsigned)count, (int)result));
1929 /* 0 is valid - means EOF */
1932 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1938 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1939 io_fdseek *ig = (io_fdseek *)igo;
1942 result = _write(ig->fd, buf, count);
1944 result = write(ig->fd, buf, count);
1947 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1948 (unsigned)count, (int)result));
1952 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1958 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1959 io_fdseek *ig = (io_fdseek *)igo;
1962 result = _lseek(ig->fd, offset, whence);
1964 result = lseek(ig->fd, offset, whence);
1967 if (result == (off_t)-1) {
1969 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1975 static int fd_close(io_glue *ig) {
1976 /* no, we don't close it */
1980 static ssize_t fd_size(io_glue *ig) {
1982 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
1993 Arnar M. Hrafnkelsson <addi@umich.edu>