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 ) {
372 i_fatal(0, "io_slurp: called on a source that is not from a bufchain\n");
376 cc = *c = mymalloc( ieb->length );
380 bufchain_seek(ig, 0, SEEK_SET);
382 rc = bufchain_read(ig, cc, ieb->length);
384 if (rc != ieb->length)
385 i_fatal(1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
391 =item io_glue_destroy(ig)
394 =synopsis io_glue_destroy(ig);
396 Destroy an io_glue objects. Should clean up all related buffers.
398 ig - io_glue object to destroy.
404 io_glue_destroy(io_glue *ig) {
406 im_log((aIMCTX, 1, "io_glue_DESTROY(ig %p)\n", ig));
416 im_context_refdec(aIMCTX, "io_glue_destroy");
423 A macro to read a single byte from a buffered I/O glue object.
425 Returns EOF on failure, or a byte.
431 i_io_getc_imp(io_glue *ig) {
435 if (ig->error || ig->buf_eof)
440 ssize_t rc = i_io_raw_read(ig, &buf, 1);
455 i_io_setup_buffer(ig);
457 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
458 if (!i_io_read_fill(ig, 1))
462 return *(ig->read_ptr++);
469 Read the next character from the stream without advancing the stream.
471 On error or end of file, return EOF.
473 For unbuffered streams a single character buffer will be setup.
479 i_io_peekc_imp(io_glue *ig) {
484 i_io_setup_buffer(ig);
487 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
489 ig->read_ptr = ig->buffer;
490 ig->read_end = ig->buffer + 1;
491 return *(ig->buffer);
503 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
504 if (ig->error || ig->buf_eof)
507 if (!i_io_read_fill(ig, 1))
511 return *(ig->read_ptr);
515 =item i_io_peekn(ig, buffer, size)
517 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
519 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
520 from the stream and return C<size> bytes of it to the caller in
523 This ignores the buffered state of the stream, and will always setup
526 If no C<type> parameter is provided to Imager::read() or
527 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
530 Returns -1 on error, 0 if there is no data before EOF, or the number
531 of bytes read into C<buffer>.
537 i_io_peekn(io_glue *ig, void *buf, size_t size) {
538 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
542 i_push_error(0, "peekn size must be positive");
543 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
548 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
553 i_io_setup_buffer(ig);
555 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
556 && !(ig->buf_eof || ig->error)) {
557 i_io_read_fill(ig, size);
560 if (size > ig->read_end - ig->read_ptr)
561 size = ig->read_end - ig->read_ptr;
564 memcpy(buf, ig->read_ptr, size);
565 else if (ig->buf_eof) {
566 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
569 else if (ig->error) {
570 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
574 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
578 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
584 =item i_io_putc(ig, c)
587 Write a single character to the stream.
589 On success return c, on error returns EOF
595 i_io_putc_imp(io_glue *ig, int c) {
596 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
600 ssize_t write_result;
606 write_result = i_io_raw_write(ig, &buf, 1);
607 if (write_result != 1) {
610 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
612 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
624 i_io_setup_buffer(ig);
626 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
631 i_io_start_write(ig);
633 *(ig->write_ptr)++ = c;
635 return (unsigned char)c;
639 =item i_io_read(io, buffer, size)
642 Read up to C<size> bytes from the stream C<io> into C<buffer>.
644 Returns the number of bytes read. Returns 0 on end of file. Returns
651 i_io_read(io_glue *ig, void *buf, size_t size) {
652 unsigned char *pbuf = buf;
653 ssize_t read_total = 0;
655 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
658 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
662 if (!ig->buffer && ig->buffered)
663 i_io_setup_buffer(ig);
665 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
666 size_t alloc = ig->read_end - ig->read_ptr;
671 memcpy(pbuf, ig->read_ptr, alloc);
672 ig->read_ptr += alloc;
678 if (size > 0 && !(ig->error || ig->buf_eof)) {
679 if (!ig->buffered || size > ig->buf_size) {
682 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
688 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
699 if (i_io_read_fill(ig, size)) {
700 size_t alloc = ig->read_end - ig->read_ptr;
704 memcpy(pbuf, ig->read_ptr, alloc);
705 ig->read_ptr += alloc;
711 if (!read_total && ig->error) {
712 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
719 if (!read_total && ig->error)
722 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
728 =item i_io_write(io, buffer, size)
730 =synopsis ssize_t result = i_io_write(io, buffer, size)
732 Write to the given I/O stream.
734 Returns the number of bytes written.
740 i_io_write(io_glue *ig, const void *buf, size_t size) {
741 const unsigned char *pbuf = buf;
742 size_t write_count = 0;
744 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
750 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
754 result = i_io_raw_write(ig, buf, size);
756 if (result != size) {
758 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
761 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
767 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
772 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
777 i_io_setup_buffer(ig);
780 i_io_start_write(ig);
782 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
783 size_t alloc = ig->write_end - ig->write_ptr;
786 memcpy(ig->write_ptr, pbuf, alloc);
787 write_count += alloc;
790 ig->write_ptr += alloc;
794 if (!i_io_flush(ig)) {
795 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
796 return write_count ? write_count : -1;
799 i_io_start_write(ig);
801 if (size > ig->buf_size) {
803 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
811 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
817 memcpy(ig->write_ptr, pbuf, size);
819 ig->write_ptr += size;
823 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
829 =item i_io_seek(io, offset, whence)
832 Seek within the stream.
834 Acts like perl's seek.
840 i_io_seek(io_glue *ig, off_t offset, int whence) {
843 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
845 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
850 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
851 offset -= ig->read_end - ig->read_ptr;
853 ig->read_ptr = ig->read_end = NULL;
854 ig->write_ptr = ig->write_end = NULL;
858 new_off = i_io_raw_seek(ig, offset, whence);
862 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
871 Flush any buffered output.
873 Returns true on success,
879 i_io_flush(io_glue *ig) {
882 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
885 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
894 while (bufp < ig->write_ptr) {
895 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
897 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
905 ig->write_ptr = ig->write_end = NULL;
907 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
916 Flush any pending output and perform the close action for the stream.
918 Returns 0 on success.
924 i_io_close(io_glue *ig) {
927 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
931 if (ig->write_ptr && !i_io_flush(ig))
934 if (i_io_raw_close(ig))
937 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
943 =item i_io_gets(ig, buffer, size, end_of_line)
945 =synopsis char buffer[BUFSIZ]
946 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
948 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
950 If the byte C<end_of_line> is seen then no further bytes will be read.
952 Returns the number of bytes read.
954 Always C<NUL> terminates the buffer.
960 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
961 ssize_t read_count = 0;
964 --size; /* room for nul */
966 int byte = i_io_getc(ig);
981 =item i_io_init(ig, readcb, writecb, seekcb)
983 Do common initialization for io_glue objects.
989 i_io_init(pIMCTX, io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
990 i_io_seekp_t seekcb) {
994 ig->writecb = writecb;
998 ig->destroycb = NULL;
999 ig->context = aIMCTX;
1002 ig->read_ptr = NULL;
1003 ig->read_end = NULL;
1004 ig->write_ptr = NULL;
1005 ig->write_end = NULL;
1006 ig->buf_size = IO_BUF_SIZE;
1013 =item i_io_set_buffered(io, buffered)
1014 =category I/O Layers
1016 Set the buffering mode of the stream.
1018 If you switch buffering off on a stream with buffering on:
1024 any buffered output will be flushed.
1028 any existing buffered input will be consumed before reads become
1033 Returns true on success. This may fail if any buffered output cannot
1040 i_io_set_buffered(io_glue *ig, int buffered) {
1041 if (!buffered && ig->write_ptr) {
1042 if (!i_io_flush(ig)) {
1047 ig->buffered = buffered;
1055 Dump the base fields of an io_glue object to stdout.
1060 i_io_dump(io_glue *ig, int flags) {
1061 fprintf(IOL_DEBs, "ig %p:\n", ig);
1062 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1063 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1064 if (flags & I_IO_DUMP_CALLBACKS) {
1065 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1066 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1067 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1068 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1069 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1071 if (flags & I_IO_DUMP_BUFFER) {
1072 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1073 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1075 fprintf(IOL_DEBs, " ");
1076 dump_data(ig->read_ptr, ig->read_end, 0);
1077 putc('\n', IOL_DEBs);
1079 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1080 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1081 if (ig->write_ptr) {
1082 fprintf(IOL_DEBs, " ");
1083 dump_data(ig->buffer, ig->write_ptr, 1);
1084 putc('\n', IOL_DEBs);
1086 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1087 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1089 if (flags & I_IO_DUMP_STATUS) {
1090 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1091 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1092 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1099 =head1 INTERNAL FUNCTIONS
1105 Calls strerror() and ensures we don't return NULL.
1107 On some platforms it's possible for strerror() to return NULL, this
1108 wrapper ensures we only get non-NULL values.
1114 const char *my_strerror(int err) {
1115 const char *result = strerror(err);
1118 result = "Unknown error";
1124 i_io_setup_buffer(io_glue *ig) {
1125 ig->buffer = mymalloc(ig->buf_size);
1129 i_io_start_write(io_glue *ig) {
1130 ig->write_ptr = ig->buffer;
1131 ig->write_end = ig->buffer + ig->buf_size;
1135 i_io_read_fill(io_glue *ig, ssize_t needed) {
1136 unsigned char *buf_end = ig->buffer + ig->buf_size;
1137 unsigned char *buf_start = ig->buffer;
1138 unsigned char *work = ig->buffer;
1142 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1144 /* these conditions may be unused, callers should also be checking them */
1145 if (ig->error || ig->buf_eof)
1148 if (needed > ig->buf_size)
1149 needed = ig->buf_size;
1151 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1152 size_t kept = ig->read_end - ig->read_ptr;
1154 if (needed < kept) {
1155 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1159 if (ig->read_ptr != ig->buffer)
1160 memmove(ig->buffer, ig->read_ptr, kept);
1162 good = 1; /* we have *something* available to read */
1163 work = buf_start + kept;
1170 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1181 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1186 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1190 ig->read_ptr = buf_start;
1191 ig->read_end = work;
1194 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1195 (unsigned)(ig->read_end - ig->read_ptr)));
1200 =item dump_data(start, end, bias)
1202 Hex dump the data between C<start> and C<end>.
1204 If there is more than a pleasing amount of data, either dump the
1205 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1211 dump_data(unsigned char *start, unsigned char *end, int bias) {
1213 size_t count = end - start;
1216 fprintf(IOL_DEBs, "(empty)");
1222 fprintf(IOL_DEBs, "... ");
1229 for (p = start; p < end; ++p) {
1230 fprintf(IOL_DEBs, " %02x", *p);
1232 putc(' ', IOL_DEBs);
1233 putc('<', IOL_DEBs);
1234 for (p = start; p < end; ++p) {
1235 if (*p < ' ' || *p > '~')
1236 putc('.', IOL_DEBs);
1240 putc('>', IOL_DEBs);
1242 fprintf(IOL_DEBs, " ...");
1245 for (p = start; p < end; ++p) {
1246 fprintf(IOL_DEBs, " %02x", *p);
1248 putc(' ', IOL_DEBs);
1249 for (p = start; p < end; ++p) {
1250 if (*p < ' ' || *p > '~')
1251 putc('.', IOL_DEBs);
1259 * Callbacks for sources that cannot seek
1263 * Callbacks for sources that can seek
1267 =item realseek_read(ig, buf, count)
1269 Does the reading from a source that can be seeked on
1272 buf - buffer to return data in
1273 count - number of bytes to read into buffer max
1280 realseek_read(io_glue *igo, void *buf, size_t count) {
1281 io_cb *ig = (io_cb *)igo;
1285 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1286 buf, (unsigned)count) );
1287 rc = ig->readcb(p,buf,count);
1289 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1296 =item realseek_write(ig, buf, count)
1298 Does the writing to a 'source' that can be seeked on
1301 buf - buffer that contains data
1302 count - number of bytes to write
1309 realseek_write(io_glue *igo, const void *buf, size_t count) {
1310 io_cb *ig = (io_cb *)igo;
1314 char *cbuf = (char*)buf;
1316 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1317 "count = %u\n", ig, buf, (unsigned)count) );
1319 /* Is this a good idea? Would it be better to handle differently?
1321 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1325 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1326 return rc < 0 ? rc : bc;
1331 =item realseek_close(ig)
1333 Closes a source that can be seeked on. Not sure if this should be an
1334 actual close or not. Does nothing for now. Should be fixed.
1342 realseek_close(io_glue *igo) {
1343 io_cb *ig = (io_cb *)igo;
1346 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1347 im_log((aIMCTX,1, "realseek_close(ig %p)\n", ig));
1349 return ig->closecb(ig->p);
1355 /* realseek_seek(ig, offset, whence)
1357 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1358 have an offset into a file that is different from what the underlying library thinks.
1361 offset - offset into stream
1362 whence - whence argument a la lseek
1369 realseek_seek(io_glue *igo, off_t offset, int whence) {
1370 io_cb *ig = (io_cb *)igo;
1373 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1374 rc = ig->seekcb(p, offset, whence);
1376 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1378 /* FIXME: How about implementing this offset handling stuff? */
1383 realseek_destroy(io_glue *igo) {
1384 io_cb *ig = (io_cb *)igo;
1387 ig->destroycb(ig->p);
1391 * Callbacks for sources that are a fixed size buffer
1395 =item buffer_read(ig, buf, count)
1397 Does the reading from a buffer source
1400 buf - buffer to return data in
1401 count - number of bytes to read into buffer max
1408 buffer_read(io_glue *igo, void *buf, size_t count) {
1409 io_buffer *ig = (io_buffer *)igo;
1411 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1413 if ( ig->cpos+count > ig->len ) {
1415 im_log((aIMCTX, 1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1416 count = ig->len - ig->cpos;
1419 memcpy(buf, ig->data+ig->cpos, count);
1421 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1427 =item buffer_write(ig, buf, count)
1429 Does nothing, returns -1
1432 buf - buffer that contains data
1433 count - number of bytes to write
1440 buffer_write(io_glue *ig, const void *buf, size_t count) {
1442 im_log((aIMCTX, 1, "buffer_write called, this method should never be called.\n"));
1448 =item buffer_close(ig)
1450 Closes a source that can be seeked on. Not sure if this should be an actual close
1451 or not. Does nothing for now. Should be fixed.
1460 buffer_close(io_glue *ig) {
1462 im_log((aIMCTX, 1, "buffer_close(ig %p)\n", ig));
1468 /* buffer_seek(ig, offset, whence)
1470 Implements seeking for a buffer source.
1473 offset - offset into stream
1474 whence - whence argument a la lseek
1481 buffer_seek(io_glue *igo, off_t offset, int whence) {
1482 io_buffer *ig = (io_buffer *)igo;
1484 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1486 if (reqpos > ig->len) {
1488 im_log((aIMCTX, 1, "seeking out of readable range\n"));
1493 i_push_error(0, "seek before beginning of file");
1498 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1501 /* FIXME: How about implementing this offset handling stuff? */
1506 buffer_destroy(io_glue *igo) {
1507 io_buffer *ig = (io_buffer *)igo;
1511 im_log((aIMCTX, 1,"calling close callback %p for io_buffer\n",
1513 ig->closecb(ig->closedata);
1520 * Callbacks for sources that are a chain of variable sized buffers
1525 /* Helper functions for buffer chains */
1529 io_blink_new(void) {
1533 im_log((aIMCTX, 1, "io_blink_new()\n"));
1536 ib = mymalloc(sizeof(io_blink));
1542 memset(&ib->buf, 0, ib->len);
1549 =item io_bchain_advance(ieb)
1551 Advances the buffer chain to the next link - extending if
1552 necessary. Also adjusts the cpos and tfill counters as needed.
1554 ieb - buffer chain object
1561 io_bchain_advance(io_ex_bchain *ieb) {
1562 if (ieb->cp->next == NULL) {
1563 ieb->tail = io_blink_new();
1564 ieb->tail->prev = ieb->cp;
1565 ieb->cp->next = ieb->tail;
1567 ieb->tfill = 0; /* Only set this if we added a new slice */
1569 ieb->cp = ieb->cp->next;
1576 =item io_bchain_destroy()
1578 frees all resources used by a buffer chain.
1584 io_destroy_bufchain(io_ex_bchain *ieb) {
1587 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1592 io_blink *t = cp->next;
1605 bufchain_dump(io_ex_bchain *ieb) {
1606 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1607 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1608 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1609 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1610 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1611 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1612 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1613 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1614 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1619 * TRUE if lengths are NOT equal
1625 chainlencert( io_glue *ig ) {
1630 io_ex_bchain *ieb = ig->exdata;
1631 io_blink *cp = ieb->head;
1634 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1637 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1638 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1639 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1641 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1642 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1644 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1645 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1647 if (cp == ieb->cp) {
1652 if (!cfl) cpos += clen;
1657 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1658 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1664 chaincert( io_glue *ig) {
1666 io_ex_bchain *ieb = ig->exdata;
1667 io_blink *cp = ieb->head;
1669 mm_log((1, "Chain verification.\n"));
1671 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1672 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1673 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1674 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1675 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1676 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1677 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1678 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1681 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1682 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1683 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1684 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1686 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1687 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1689 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1690 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1696 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1701 =item bufchain_read(ig, buf, count)
1703 Does the reading from a source that can be seeked on
1706 buf - buffer to return data in
1707 count - number of bytes to read into buffer max
1714 bufchain_read(io_glue *ig, void *buf, size_t count) {
1715 io_ex_bchain *ieb = ig->exdata;
1716 size_t scount = count;
1721 im_log((aIMCTX, 1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1724 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1725 if (clen == ieb->cpos) {
1726 if (ieb->cp == ieb->tail) break; /* EOF */
1727 ieb->cp = ieb->cp->next;
1729 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1732 sk = clen - ieb->cpos;
1733 sk = sk > scount ? scount : sk;
1735 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1741 im_log((aIMCTX, 1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1742 return count-scount;
1750 =item bufchain_write(ig, buf, count)
1752 Does the writing to a 'source' that can be seeked on
1755 buf - buffer that contains data
1756 count - number of bytes to write
1763 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1764 char *cbuf = (char *)buf;
1765 io_ex_bchain *ieb = ig->exdata;
1766 size_t ocount = count;
1770 im_log((aIMCTX, 1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1772 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1775 im_log((aIMCTX, 2, "bufchain_write: - looping - count = %ld\n", (long)count));
1776 if (ieb->cp->len == ieb->cpos) {
1777 im_log((aIMCTX, 1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1778 io_bchain_advance(ieb);
1781 sk = ieb->cp->len - ieb->cpos;
1782 sk = sk > count ? count : sk;
1783 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1785 if (ieb->cp == ieb->tail) {
1786 int extend = ieb->cpos + sk - ieb->tfill;
1787 im_log((aIMCTX, 2, "bufchain_write: extending tail by %d\n", extend));
1789 ieb->length += extend;
1790 ieb->tfill += extend;
1802 =item bufchain_close(ig)
1804 Closes a source that can be seeked on. Not sure if this should be an actual close
1805 or not. Does nothing for now. Should be fixed.
1814 bufchain_close(io_glue *ig) {
1816 im_log((aIMCTX, 1, "bufchain_close(ig %p)\n",ig));
1817 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1823 /* bufchain_seek(ig, offset, whence)
1825 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1826 have an offset into a file that is different from what the underlying library thinks.
1829 offset - offset into stream
1830 whence - whence argument a la lseek
1837 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1838 io_ex_bchain *ieb = ig->exdata;
1841 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1845 im_log((aIMCTX, 1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1848 i_push_error(0, "invalid whence supplied or seek before start of file");
1852 ieb->cp = ieb->head;
1857 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1858 if (clen == ieb->cpos) {
1859 if (ieb->cp == ieb->tail) break; /* EOF */
1860 ieb->cp = ieb->cp->next;
1862 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1865 sk = clen - ieb->cpos;
1866 sk = sk > scount ? scount : sk;
1877 * extending file - get ieb into consistent state and then
1878 * call write which will get it to the correct position
1881 memset(TB, 0, BBSIZ);
1882 ieb->gpos = ieb->length;
1883 ieb->cpos = ieb->tfill;
1886 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1887 im_log((aIMCTX, 1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1888 rc = bufchain_write( ig, TB, wl );
1889 if (rc != wl) i_fatal(0, "bufchain_seek: Unable to extend file\n");
1894 im_log((aIMCTX, 2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1900 bufchain_destroy(io_glue *ig) {
1901 io_ex_bchain *ieb = ig->exdata;
1903 io_destroy_bufchain(ieb);
1909 =item fd_read(ig, buf, count)
1911 Read callback for file descriptor IO objects.
1915 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1916 io_fdseek *ig = (io_fdseek *)igo;
1919 result = _read(ig->fd, buf, count);
1921 result = read(ig->fd, buf, count);
1924 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1925 (unsigned)count, (int)result));
1927 /* 0 is valid - means EOF */
1930 im_push_errorf(aIMCTX, 0, "read() failure: %s (%d)", my_strerror(errno), errno);
1936 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1937 io_fdseek *ig = (io_fdseek *)igo;
1940 result = _write(ig->fd, buf, count);
1942 result = write(ig->fd, buf, count);
1945 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1946 (unsigned)count, (int)result));
1950 im_push_errorf(aIMCTX, errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1956 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1957 io_fdseek *ig = (io_fdseek *)igo;
1960 result = _lseek(ig->fd, offset, whence);
1962 result = lseek(ig->fd, offset, whence);
1965 if (result == (off_t)-1) {
1967 im_push_errorf(aIMCTX, errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1973 static int fd_close(io_glue *ig) {
1974 /* no, we don't close it */
1978 static ssize_t fd_size(io_glue *ig) {
1980 im_log((aIMCTX, 1, "fd_size(ig %p) unimplemented\n", ig));
1991 Arnar M. Hrafnkelsson <addi@umich.edu>