15 #define IOL_DEBs stderr
17 #define IO_BUF_SIZE 8192
19 char *io_type_names[] = { "FDSEEK", "FDNOSEEK", "BUFFER", "CBSEEK", "CBNOSEEK", "BUFCHAIN" };
21 typedef struct io_blink {
24 size_t len; /* How large is this buffer = BBZIS for now */
25 struct io_blink *next;
26 struct io_blink *prev;
39 i_io_closebufp_t closecb; /* free memory mapped segment or decrement refcount */
46 void *p; /* Callback data */
48 i_io_writel_t writecb;
50 i_io_closel_t closecb;
51 i_io_destroyl_t destroycb;
55 off_t offset; /* Offset of the source - not used */
56 off_t length; /* Total length of chain in bytes */
57 io_blink *head; /* Start of chain */
58 io_blink *tail; /* End of chain */
59 off_t tfill; /* End of stream in last link */
60 io_blink *cp; /* Current element of list */
61 off_t cpos; /* Offset within the current */
62 off_t gpos; /* Global position in stream */
65 /* turn current offset, file length, whence and offset into a new offset */
66 #define calc_seek_offset(curr_off, length, offset, whence) \
67 (((whence) == SEEK_SET) ? (offset) : \
68 ((whence) == SEEK_CUR) ? (curr_off) + (offset) : \
69 ((whence) == SEEK_END) ? (length) + (offset) : -1)
74 iolayer.c - encapsulates different source of data into a single framework.
78 io_glue *ig = io_new_fd( fileno(stdin) );
79 method = io_reqmeth( IOL_NOSEEK | IOL_MMAP ); // not implemented yet
83 code that uses ig->readcb()
84 to read data goes here.
87 code that uses ig->readcb()
88 to read data goes here.
97 iolayer.c implements the basic functions to create and destroy io_glue
98 objects for Imager. The typical usage pattern for data sources is:
100 1. Create the source (io_new_fd)
101 2. Define how you want to get data from it (io_reqmeth)
102 3. read from it using the interface requested (ig->readdb, ig->mmapcb)
103 4. Close the source, which
104 shouldn't really close the underlying source. (io_glue DESTROY)
106 =head1 FUNCTION REFERENCE
108 Some of these functions are internal.
116 i_io_init(io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
117 i_io_seekp_t seekcb);
119 static ssize_t fd_read(io_glue *ig, void *buf, size_t count);
120 static ssize_t fd_write(io_glue *ig, const void *buf, size_t count);
121 static off_t fd_seek(io_glue *ig, off_t offset, int whence);
122 static int fd_close(io_glue *ig);
123 static ssize_t fd_size(io_glue *ig);
124 static const char *my_strerror(int err);
125 static void i_io_setup_buffer(io_glue *ig);
127 i_io_start_write(io_glue *ig);
129 i_io_read_fill(io_glue *ig, ssize_t needed);
131 dump_data(unsigned char *start, unsigned char *end, int bias);
132 static ssize_t realseek_read(io_glue *igo, void *buf, size_t count);
133 static ssize_t realseek_write(io_glue *igo, const void *buf, size_t count);
134 static int realseek_close(io_glue *igo);
135 static off_t realseek_seek(io_glue *igo, off_t offset, int whence);
136 static void realseek_destroy(io_glue *igo);
137 static ssize_t buffer_read(io_glue *igo, void *buf, size_t count);
138 static ssize_t buffer_write(io_glue *ig, const void *buf, size_t count);
139 static int buffer_close(io_glue *ig);
140 static off_t buffer_seek(io_glue *igo, off_t offset, int whence);
141 static void buffer_destroy(io_glue *igo);
142 static io_blink*io_blink_new(void);
143 static void io_bchain_advance(io_ex_bchain *ieb);
144 static void io_destroy_bufchain(io_ex_bchain *ieb);
145 static ssize_t bufchain_read(io_glue *ig, void *buf, size_t count);
146 static ssize_t bufchain_write(io_glue *ig, const void *buf, size_t count);
147 static int bufchain_close(io_glue *ig);
148 static off_t bufchain_seek(io_glue *ig, off_t offset, int whence);
149 static void bufchain_destroy(io_glue *ig);
152 * Methods for setting up data source
156 =item io_new_bufchain()
160 returns a new io_glue object that has the 'empty' source and but can
161 be written to and read from later (like a pseudo file).
169 io_ex_bchain *ieb = mymalloc(sizeof(io_ex_bchain));
171 mm_log((1, "io_new_bufchain()\n"));
173 ig = mymalloc(sizeof(io_glue));
174 memset(ig, 0, sizeof(*ig));
175 i_io_init(ig, BUFCHAIN, bufchain_read, bufchain_write, bufchain_seek);
183 ieb->head = io_blink_new();
185 ieb->tail = ieb->head;
188 ig->closecb = bufchain_close;
189 ig->destroycb = bufchain_destroy;
195 =item io_new_buffer(data, length)
199 Returns a new io_glue object that has the source defined as reading
200 from specified buffer. Note that the buffer is not copied.
202 data - buffer to read from
203 length - length of buffer
209 io_new_buffer(const char *data, size_t len, i_io_closebufp_t closecb, void *closedata) {
212 mm_log((1, "io_new_buffer(data %p, len %ld, closecb %p, closedata %p)\n", data, (long)len, closecb, closedata));
214 ig = mymalloc(sizeof(io_buffer));
215 memset(ig, 0, sizeof(*ig));
216 i_io_init(&ig->base, BUFFER, buffer_read, buffer_write, buffer_seek);
219 ig->closecb = closecb;
220 ig->closedata = closedata;
224 ig->base.closecb = buffer_close;
225 ig->base.destroycb = buffer_destroy;
227 return (io_glue *)ig;
236 returns a new io_glue object that has the source defined as reading
237 from specified file descriptor. Note that the the interface to receiving
238 data from the io_glue callbacks hasn't been done yet.
240 fd - file descriptor to read/write from
249 mm_log((1, "io_new_fd(fd %d)\n", fd));
251 ig = mymalloc(sizeof(io_fdseek));
252 memset(ig, 0, sizeof(*ig));
253 i_io_init(&ig->base, FDSEEK, fd_read, fd_write, fd_seek);
256 ig->base.closecb = fd_close;
257 ig->base.sizecb = fd_size;
258 ig->base.destroycb = NULL;
260 mm_log((1, "(%p) <- io_new_fd\n", ig));
261 return (io_glue *)ig;
265 =item io_new_cb(p, read_cb, write_cb, seek_cb, close_cb, destroy_cb)
269 Create a new I/O layer object that calls your supplied callbacks.
271 In general the callbacks should behave like the corresponding POSIX
278 C<read_cb>(p, buffer, length) should read up to C<length> bytes into
279 C<buffer> and return the number of bytes read. At end of file, return
280 0. On error, return -1.
284 C<write_cb>(p, buffer, length) should write up to C<length> bytes from
285 C<buffer> and return the number of bytes written. A return value <= 0
286 will be treated as an error.
290 C<seekcb>(p, offset, whence) should seek and return the new offset.
294 C<close_cb>(p) should return 0 on success, -1 on failure.
298 C<destroy_cb>(p) should release any memory specific to your callback
307 io_new_cb(void *p, i_io_readl_t readcb, i_io_writel_t writecb,
308 i_io_seekl_t seekcb, i_io_closel_t closecb,
309 i_io_destroyl_t destroycb) {
312 mm_log((1, "io_new_cb(p %p, readcb %p, writecb %p, seekcb %p, closecb %p, "
313 "destroycb %p)\n", p, readcb, writecb, seekcb, closecb, destroycb));
314 ig = mymalloc(sizeof(io_cb));
315 memset(ig, 0, sizeof(*ig));
316 i_io_init(&ig->base, CBSEEK, realseek_read, realseek_write, realseek_seek);
317 mm_log((1, "(%p) <- io_new_cb\n", ig));
319 ig->base.closecb = realseek_close;
320 ig->base.destroycb = realseek_destroy;
324 ig->writecb = writecb;
326 ig->closecb = closecb;
327 ig->destroycb = destroycb;
329 return (io_glue *)ig;
333 =item io_slurp(ig, c)
336 Takes the source that the io_glue is bound to and allocates space for
337 a return buffer and returns the entire content in a single buffer.
338 Note: This only works for io_glue objects created by
339 io_new_bufchain(). It is useful for saving to scalars and such.
342 c - pointer to a pointer to where data should be copied to
345 size_t size = io_slurp(ig, &data);
346 ... do something with the data ...
349 io_slurp() will abort the program if the supplied I/O layer is not
350 from io_new_bufchain().
356 io_slurp(io_glue *ig, unsigned char **c) {
361 io_type inn = ig->type;
363 if ( inn != BUFCHAIN ) {
364 i_fatal(0, "io_slurp: called on a source that is not from a bufchain\n");
368 cc = *c = mymalloc( ieb->length );
372 bufchain_seek(ig, 0, SEEK_SET);
374 rc = bufchain_read(ig, cc, ieb->length);
376 if (rc != ieb->length)
377 i_fatal(1, "io_slurp: bufchain_read returned an incomplete read: rc = %d, request was %d\n", rc, ieb->length);
383 =item io_glue_destroy(ig)
386 =synopsis io_glue_destroy(ig);
388 Destroy an io_glue objects. Should clean up all related buffers.
390 ig - io_glue object to destroy.
396 io_glue_destroy(io_glue *ig) {
397 mm_log((1, "io_glue_DESTROY(ig %p)\n", ig));
412 A macro to read a single byte from a buffered I/O glue object.
414 Returns EOF on failure, or a byte.
420 i_io_getc_imp(io_glue *ig) {
424 if (ig->error || ig->buf_eof)
429 ssize_t rc = i_io_raw_read(ig, &buf, 1);
444 i_io_setup_buffer(ig);
446 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
447 if (!i_io_read_fill(ig, 1))
451 return *(ig->read_ptr++);
458 Read the next character from the stream without advancing the stream.
460 On error or end of file, return EOF.
462 For unbuffered streams a single character buffer will be setup.
468 i_io_peekc_imp(io_glue *ig) {
473 i_io_setup_buffer(ig);
476 ssize_t rc = i_io_raw_read(ig, ig->buffer, 1);
478 ig->read_ptr = ig->buffer;
479 ig->read_end = ig->buffer + 1;
480 return *(ig->buffer);
492 if (!ig->read_ptr || ig->read_ptr == ig->read_end) {
493 if (ig->error || ig->buf_eof)
496 if (!i_io_read_fill(ig, 1))
500 return *(ig->read_ptr);
504 =item i_io_peekn(ig, buffer, size)
506 =synopsis ssize_t count = i_io_peekn(ig, buffer, sizeof(buffer));
508 Buffer at least C<size> (at most C<< ig->buf_size >> bytes of data
509 from the stream and return C<size> bytes of it to the caller in
512 This ignores the buffered state of the stream, and will always setup
515 If no C<type> parameter is provided to Imager::read() or
516 Imager::read_multi(), Imager will call C<i_io_peekn()> when probing
519 Returns -1 on error, 0 if there is no data before EOF, or the number
520 of bytes read into C<buffer>.
526 i_io_peekn(io_glue *ig, void *buf, size_t size) {
527 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn(%p, %p, %d)\n", ig, buf, (int)size));
530 i_push_error(0, "peekn size must be positive");
531 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (zero size)\n"));
536 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (write_ptr set)\n"));
541 i_io_setup_buffer(ig);
543 if ((!ig->read_ptr || size > ig->read_end - ig->read_ptr)
544 && !(ig->buf_eof || ig->error)) {
545 i_io_read_fill(ig, size);
548 if (size > ig->read_end - ig->read_ptr)
549 size = ig->read_end - ig->read_ptr;
552 memcpy(buf, ig->read_ptr, size);
553 else if (ig->buf_eof) {
554 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => 0 (eof)\n"));
557 else if (ig->error) {
558 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => -1 (error)\n"));
562 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() - size 0 but not eof or error!\n"));
566 IOL_DEB(fprintf(IOL_DEBs, "i_io_peekn() => %d\n", (int)size));
572 =item i_io_putc(ig, c)
575 Write a single character to the stream.
577 On success return c, on error returns EOF
583 i_io_putc_imp(io_glue *ig, int c) {
584 IOL_DEB(fprintf(IOL_DEBs, "i_io_putc_imp(%p, %d)\n", ig, c));
588 ssize_t write_result;
594 write_result = i_io_raw_write(ig, &buf, 1);
595 if (write_result != 1) {
598 IOL_DEB(fprintf(IOL_DEBs, " unbuffered putc() failed, setting error mode\n"));
600 IOL_DEB(fprintf(IOL_DEBs, " unbuffered: result %d\n", result));
612 i_io_setup_buffer(ig);
614 if (ig->write_ptr && ig->write_ptr == ig->write_end) {
619 i_io_start_write(ig);
621 *(ig->write_ptr)++ = c;
623 return (unsigned char)c;
627 =item i_io_read(io, buffer, size)
630 Read up to C<size> bytes from the stream C<io> into C<buffer>.
632 Returns the number of bytes read. Returns 0 on end of file. Returns
639 i_io_read(io_glue *ig, void *buf, size_t size) {
640 unsigned char *pbuf = buf;
641 ssize_t read_total = 0;
643 IOL_DEB(fprintf(IOL_DEBs, "i_io_read(%p, %p, %u)\n", ig, buf, (unsigned)size));
646 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (write_ptr set)\n"));
650 if (!ig->buffer && ig->buffered)
651 i_io_setup_buffer(ig);
653 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
654 size_t alloc = ig->read_end - ig->read_ptr;
659 memcpy(pbuf, ig->read_ptr, alloc);
660 ig->read_ptr += alloc;
666 if (size > 0 && !(ig->error || ig->buf_eof)) {
667 if (!ig->buffered || size > ig->buf_size) {
670 while (size > 0 && (rc = i_io_raw_read(ig, pbuf, size)) > 0) {
676 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d (raw read)\n", (int)read_total));
687 if (i_io_read_fill(ig, size)) {
688 size_t alloc = ig->read_end - ig->read_ptr;
692 memcpy(pbuf, ig->read_ptr, alloc);
693 ig->read_ptr += alloc;
699 if (!read_total && ig->error) {
700 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => -1 (fill failure)\n"));
707 if (!read_total && ig->error)
710 IOL_DEB(fprintf(IOL_DEBs, "i_io_read() => %d\n", (int)read_total));
716 =item i_io_write(io, buffer, size)
718 =synopsis ssize_t result = i_io_write(io, buffer, size)
720 Write to the given I/O stream.
722 Returns the number of bytes written.
728 i_io_write(io_glue *ig, const void *buf, size_t size) {
729 const unsigned char *pbuf = buf;
730 size_t write_count = 0;
732 IOL_DEB(fprintf(IOL_DEBs, "i_io_write(%p, %p, %u)\n", ig, buf, (unsigned)size));
738 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, error state\n"));
742 result = i_io_raw_write(ig, buf, size);
744 if (result != size) {
746 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, setting error flag\n"));
749 IOL_DEB(fprintf(IOL_DEBs, " unbuffered, result: %d\n", (int)result));
755 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (read_ptr set)\n"));
760 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (error)\n"));
765 i_io_setup_buffer(ig);
768 i_io_start_write(ig);
770 if (ig->write_ptr && ig->write_ptr + size <= ig->write_end) {
771 size_t alloc = ig->write_end - ig->write_ptr;
774 memcpy(ig->write_ptr, pbuf, alloc);
775 write_count += alloc;
778 ig->write_ptr += alloc;
782 if (!i_io_flush(ig)) {
783 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d (i_io_flush failure)\n", (int)write_count));
784 return write_count ? write_count : -1;
787 i_io_start_write(ig);
789 if (size > ig->buf_size) {
791 while (size > 0 && (rc = i_io_raw_write(ig, pbuf, size)) > 0) {
799 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => -1 (direct write failure)\n"));
805 memcpy(ig->write_ptr, pbuf, size);
807 ig->write_ptr += size;
811 IOL_DEB(fprintf(IOL_DEBs, "i_io_write() => %d\n", (int)write_count));
817 =item i_io_seek(io, offset, whence)
820 Seek within the stream.
822 Acts like perl's seek.
828 i_io_seek(io_glue *ig, off_t offset, int whence) {
831 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek(%p, %ld, %d)\n", ig, (long)offset, whence));
833 if (ig->write_ptr && ig->write_ptr != ig->write_end) {
838 if (whence == SEEK_CUR && ig->read_ptr && ig->read_ptr != ig->read_end)
839 offset -= ig->read_end - ig->read_ptr;
841 ig->read_ptr = ig->read_end = NULL;
842 ig->write_ptr = ig->write_end = NULL;
846 new_off = i_io_raw_seek(ig, offset, whence);
850 IOL_DEB(fprintf(IOL_DEBs, "i_io_seek() => %ld\n", (long)new_off));
859 Flush any buffered output.
861 Returns true on success,
867 i_io_flush(io_glue *ig) {
870 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush(%p)\n", ig));
873 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (error set)\n", ig));
882 while (bufp < ig->write_ptr) {
883 ssize_t rc = i_io_raw_write(ig, bufp, ig->write_ptr - bufp);
885 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 0 (write error)\n", ig));
893 ig->write_ptr = ig->write_end = NULL;
895 IOL_DEB(fprintf(IOL_DEBs, "i_io_flush() => 1\n", ig));
904 Flush any pending output and perform the close action for the stream.
906 Returns 0 on success.
912 i_io_close(io_glue *ig) {
915 IOL_DEB(fprintf(IOL_DEBs, "i_io_close(%p)\n", ig));
919 if (ig->write_ptr && !i_io_flush(ig))
922 if (i_io_raw_close(ig))
925 IOL_DEB(fprintf(IOL_DEBs, "i_io_close() => %d\n", result));
931 =item i_io_gets(ig, buffer, size, end_of_line)
933 =synopsis char buffer[BUFSIZ]
934 =synopsis ssize_t len = i_io_gets(buffer, sizeof(buffer), '\n');
936 Read up to C<size>-1 bytes from the stream C<ig> into C<buffer>.
938 If the byte C<end_of_line> is seen then no further bytes will be read.
940 Returns the number of bytes read.
942 Always C<NUL> terminates the buffer.
948 i_io_gets(io_glue *ig, char *buffer, size_t size, int eol) {
949 ssize_t read_count = 0;
952 --size; /* room for nul */
954 int byte = i_io_getc(ig);
969 =item i_io_init(ig, readcb, writecb, seekcb)
971 Do common initialization for io_glue objects.
977 i_io_init(io_glue *ig, int type, i_io_readp_t readcb, i_io_writep_t writecb,
978 i_io_seekp_t seekcb) {
982 ig->writecb = writecb;
986 ig->destroycb = NULL;
991 ig->write_ptr = NULL;
992 ig->write_end = NULL;
993 ig->buf_size = IO_BUF_SIZE;
1000 =item i_io_set_buffered(io, buffered)
1001 =category I/O Layers
1003 Set the buffering mode of the stream.
1005 If you switch buffering off on a stream with buffering on:
1011 any buffered output will be flushed.
1015 any existing buffered input will be consumed before reads become
1020 Returns true on success. This may fail if any buffered output cannot
1027 i_io_set_buffered(io_glue *ig, int buffered) {
1028 if (!buffered && ig->write_ptr) {
1029 if (!i_io_flush(ig)) {
1034 ig->buffered = buffered;
1042 Dump the base fields of an io_glue object to stdout.
1047 i_io_dump(io_glue *ig, int flags) {
1048 fprintf(IOL_DEBs, "ig %p:\n", ig);
1049 fprintf(IOL_DEBs, " type: %d\n", ig->type);
1050 fprintf(IOL_DEBs, " exdata: %p\n", ig->exdata);
1051 if (flags & I_IO_DUMP_CALLBACKS) {
1052 fprintf(IOL_DEBs, " readcb: %p\n", ig->readcb);
1053 fprintf(IOL_DEBs, " writecb: %p\n", ig->writecb);
1054 fprintf(IOL_DEBs, " seekcb: %p\n", ig->seekcb);
1055 fprintf(IOL_DEBs, " closecb: %p\n", ig->closecb);
1056 fprintf(IOL_DEBs, " sizecb: %p\n", ig->sizecb);
1058 if (flags & I_IO_DUMP_BUFFER) {
1059 fprintf(IOL_DEBs, " buffer: %p\n", ig->buffer);
1060 fprintf(IOL_DEBs, " read_ptr: %p\n", ig->read_ptr);
1062 fprintf(IOL_DEBs, " ");
1063 dump_data(ig->read_ptr, ig->read_end, 0);
1064 putc('\n', IOL_DEBs);
1066 fprintf(IOL_DEBs, " read_end: %p\n", ig->read_end);
1067 fprintf(IOL_DEBs, " write_ptr: %p\n", ig->write_ptr);
1068 if (ig->write_ptr) {
1069 fprintf(IOL_DEBs, " ");
1070 dump_data(ig->buffer, ig->write_ptr, 1);
1071 putc('\n', IOL_DEBs);
1073 fprintf(IOL_DEBs, " write_end: %p\n", ig->write_end);
1074 fprintf(IOL_DEBs, " buf_size: %u\n", (unsigned)(ig->buf_size));
1076 if (flags & I_IO_DUMP_STATUS) {
1077 fprintf(IOL_DEBs, " buf_eof: %d\n", ig->buf_eof);
1078 fprintf(IOL_DEBs, " error: %d\n", ig->error);
1079 fprintf(IOL_DEBs, " buffered: %d\n", ig->buffered);
1086 =head1 INTERNAL FUNCTIONS
1092 Calls strerror() and ensures we don't return NULL.
1094 On some platforms it's possible for strerror() to return NULL, this
1095 wrapper ensures we only get non-NULL values.
1101 const char *my_strerror(int err) {
1102 const char *result = strerror(err);
1105 result = "Unknown error";
1111 i_io_setup_buffer(io_glue *ig) {
1112 ig->buffer = mymalloc(ig->buf_size);
1116 i_io_start_write(io_glue *ig) {
1117 ig->write_ptr = ig->buffer;
1118 ig->write_end = ig->buffer + ig->buf_size;
1122 i_io_read_fill(io_glue *ig, ssize_t needed) {
1123 unsigned char *buf_end = ig->buffer + ig->buf_size;
1124 unsigned char *buf_start = ig->buffer;
1125 unsigned char *work = ig->buffer;
1129 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%p, %d)\n", ig, (int)needed));
1131 /* these conditions may be unused, callers should also be checking them */
1132 if (ig->error || ig->buf_eof)
1135 if (needed > ig->buf_size)
1136 needed = ig->buf_size;
1138 if (ig->read_ptr && ig->read_ptr < ig->read_end) {
1139 size_t kept = ig->read_end - ig->read_ptr;
1141 if (needed < kept) {
1142 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill(%u) -> 1 (already have enough)\n", (unsigned)needed));
1146 if (ig->read_ptr != ig->buffer)
1147 memmove(ig->buffer, ig->read_ptr, kept);
1149 good = 1; /* we have *something* available to read */
1150 work = buf_start + kept;
1157 while (work < buf_end && (rc = i_io_raw_read(ig, work, buf_end - work)) > 0) {
1168 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc %d, setting error\n",
1173 IOL_DEB(fprintf(IOL_DEBs, " i_io_read_fill -> rc 0, setting eof\n"));
1177 ig->read_ptr = buf_start;
1178 ig->read_end = work;
1181 IOL_DEB(fprintf(IOL_DEBs, "i_io_read_fill => %d, %u buffered\n", good,
1182 (unsigned)(ig->read_end - ig->read_ptr)));
1187 =item dump_data(start, end, bias)
1189 Hex dump the data between C<start> and C<end>.
1191 If there is more than a pleasing amount of data, either dump the
1192 beginning (C<bias == 0>) or dump the end C(<bias != 0>) of the range.
1198 dump_data(unsigned char *start, unsigned char *end, int bias) {
1200 size_t count = end - start;
1203 fprintf(IOL_DEBs, "(empty)");
1209 fprintf(IOL_DEBs, "... ");
1216 for (p = start; p < end; ++p) {
1217 fprintf(IOL_DEBs, " %02x", *p);
1219 putc(' ', IOL_DEBs);
1220 putc('<', IOL_DEBs);
1221 for (p = start; p < end; ++p) {
1222 if (*p < ' ' || *p > '~')
1223 putc('.', IOL_DEBs);
1227 putc('>', IOL_DEBs);
1229 fprintf(IOL_DEBs, " ...");
1232 for (p = start; p < end; ++p) {
1233 fprintf(IOL_DEBs, " %02x", *p);
1235 putc(' ', IOL_DEBs);
1236 for (p = start; p < end; ++p) {
1237 if (*p < ' ' || *p > '~')
1238 putc('.', IOL_DEBs);
1246 * Callbacks for sources that cannot seek
1250 * Callbacks for sources that can seek
1254 =item realseek_read(ig, buf, count)
1256 Does the reading from a source that can be seeked on
1259 buf - buffer to return data in
1260 count - number of bytes to read into buffer max
1267 realseek_read(io_glue *igo, void *buf, size_t count) {
1268 io_cb *ig = (io_cb *)igo;
1272 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: buf = %p, count = %u\n",
1273 buf, (unsigned)count) );
1274 rc = ig->readcb(p,buf,count);
1276 IOL_DEB( fprintf(IOL_DEBs, "realseek_read: rc = %d\n", (int)rc) );
1283 =item realseek_write(ig, buf, count)
1285 Does the writing to a 'source' that can be seeked on
1288 buf - buffer that contains data
1289 count - number of bytes to write
1296 realseek_write(io_glue *igo, const void *buf, size_t count) {
1297 io_cb *ig = (io_cb *)igo;
1301 char *cbuf = (char*)buf;
1303 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: ig = %p, buf = %p, "
1304 "count = %u\n", ig, buf, (unsigned)count) );
1306 /* Is this a good idea? Would it be better to handle differently?
1308 while( count!=bc && (rc = ig->writecb(p,cbuf+bc,count-bc))>0 ) {
1312 IOL_DEB( fprintf(IOL_DEBs, "realseek_write: rc = %d, bc = %u\n", (int)rc, (unsigned)bc) );
1313 return rc < 0 ? rc : bc;
1318 =item realseek_close(ig)
1320 Closes a source that can be seeked on. Not sure if this should be an
1321 actual close or not. Does nothing for now. Should be fixed.
1329 realseek_close(io_glue *igo) {
1330 io_cb *ig = (io_cb *)igo;
1332 IOL_DEB(fprintf(IOL_DEBs, "realseek_close(%p)\n", ig));
1333 mm_log((1, "realseek_close(ig %p)\n", ig));
1335 return ig->closecb(ig->p);
1341 /* realseek_seek(ig, offset, whence)
1343 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1344 have an offset into a file that is different from what the underlying library thinks.
1347 offset - offset into stream
1348 whence - whence argument a la lseek
1355 realseek_seek(io_glue *igo, off_t offset, int whence) {
1356 io_cb *ig = (io_cb *)igo;
1359 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1360 rc = ig->seekcb(p, offset, whence);
1362 IOL_DEB( fprintf(IOL_DEBs, "realseek_seek: rc %ld\n", (long) rc) );
1364 /* FIXME: How about implementing this offset handling stuff? */
1369 realseek_destroy(io_glue *igo) {
1370 io_cb *ig = (io_cb *)igo;
1373 ig->destroycb(ig->p);
1377 * Callbacks for sources that are a fixed size buffer
1381 =item buffer_read(ig, buf, count)
1383 Does the reading from a buffer source
1386 buf - buffer to return data in
1387 count - number of bytes to read into buffer max
1394 buffer_read(io_glue *igo, void *buf, size_t count) {
1395 io_buffer *ig = (io_buffer *)igo;
1397 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: ig->cpos = %ld, buf = %p, count = %u\n", (long) ig->cpos, buf, (unsigned)count) );
1399 if ( ig->cpos+count > ig->len ) {
1400 mm_log((1,"buffer_read: short read: cpos=%ld, len=%ld, count=%ld\n", (long)ig->cpos, (long)ig->len, (long)count));
1401 count = ig->len - ig->cpos;
1404 memcpy(buf, ig->data+ig->cpos, count);
1406 IOL_DEB( fprintf(IOL_DEBs, "buffer_read: count = %ld\n", (long)count) );
1412 =item buffer_write(ig, buf, count)
1414 Does nothing, returns -1
1417 buf - buffer that contains data
1418 count - number of bytes to write
1425 buffer_write(io_glue *ig, const void *buf, size_t count) {
1426 mm_log((1, "buffer_write called, this method should never be called.\n"));
1432 =item buffer_close(ig)
1434 Closes a source that can be seeked on. Not sure if this should be an actual close
1435 or not. Does nothing for now. Should be fixed.
1444 buffer_close(io_glue *ig) {
1445 mm_log((1, "buffer_close(ig %p)\n", ig));
1451 /* buffer_seek(ig, offset, whence)
1453 Implements seeking for a buffer source.
1456 offset - offset into stream
1457 whence - whence argument a la lseek
1464 buffer_seek(io_glue *igo, off_t offset, int whence) {
1465 io_buffer *ig = (io_buffer *)igo;
1467 calc_seek_offset(ig->cpos, ig->len, offset, whence);
1469 if (reqpos > ig->len) {
1470 mm_log((1, "seeking out of readable range\n"));
1474 i_push_error(0, "seek before beginning of file");
1479 IOL_DEB( fprintf(IOL_DEBs, "buffer_seek(ig %p, offset %ld, whence %d)\n", ig, (long) offset, whence) );
1482 /* FIXME: How about implementing this offset handling stuff? */
1487 buffer_destroy(io_glue *igo) {
1488 io_buffer *ig = (io_buffer *)igo;
1491 mm_log((1,"calling close callback %p for io_buffer\n",
1493 ig->closecb(ig->closedata);
1500 * Callbacks for sources that are a chain of variable sized buffers
1505 /* Helper functions for buffer chains */
1509 io_blink_new(void) {
1512 mm_log((1, "io_blink_new()\n"));
1514 ib = mymalloc(sizeof(io_blink));
1520 memset(&ib->buf, 0, ib->len);
1527 =item io_bchain_advance(ieb)
1529 Advances the buffer chain to the next link - extending if
1530 necessary. Also adjusts the cpos and tfill counters as needed.
1532 ieb - buffer chain object
1539 io_bchain_advance(io_ex_bchain *ieb) {
1540 if (ieb->cp->next == NULL) {
1541 ieb->tail = io_blink_new();
1542 ieb->tail->prev = ieb->cp;
1543 ieb->cp->next = ieb->tail;
1545 ieb->tfill = 0; /* Only set this if we added a new slice */
1547 ieb->cp = ieb->cp->next;
1554 =item io_bchain_destroy()
1556 frees all resources used by a buffer chain.
1562 io_destroy_bufchain(io_ex_bchain *ieb) {
1564 mm_log((1, "io_destroy_bufchain(ieb %p)\n", ieb));
1568 io_blink *t = cp->next;
1581 bufchain_dump(io_ex_bchain *ieb) {
1582 mm_log((1, " buf_chain_dump(ieb %p)\n"));
1583 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1584 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1585 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1586 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1587 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1588 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1589 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1590 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1595 * TRUE if lengths are NOT equal
1601 chainlencert( io_glue *ig ) {
1606 io_ex_bchain *ieb = ig->exdata;
1607 io_blink *cp = ieb->head;
1610 if (ieb->gpos > ieb->length) mm_log((1, "BBAR : ieb->gpos = %d, ieb->length = %d\n", ieb->gpos, ieb->length));
1613 clen = (cp == ieb->tail) ? ieb->tfill : cp->len;
1614 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1615 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1617 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1618 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1620 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1621 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1623 if (cp == ieb->cp) {
1628 if (!cfl) cpos += clen;
1633 if (( csize != ieb->length )) mm_log((1, "BAR : csize = %d, ieb->length = %d\n", csize, ieb->length));
1634 if (( cpos != ieb->gpos )) mm_log((1, "BAR : cpos = %d, ieb->gpos = %d\n", cpos, ieb->gpos ));
1640 chaincert( io_glue *ig) {
1642 io_ex_bchain *ieb = ig->exdata;
1643 io_blink *cp = ieb->head;
1645 mm_log((1, "Chain verification.\n"));
1647 mm_log((1, " buf_chain_dump: ieb->offset = %d\n", ieb->offset));
1648 mm_log((1, " buf_chain_dump: ieb->length = %d\n", ieb->length));
1649 mm_log((1, " buf_chain_dump: ieb->head = %p\n", ieb->head ));
1650 mm_log((1, " buf_chain_dump: ieb->tail = %p\n", ieb->tail ));
1651 mm_log((1, " buf_chain_dump: ieb->tfill = %d\n", ieb->tfill ));
1652 mm_log((1, " buf_chain_dump: ieb->cp = %p\n", ieb->cp ));
1653 mm_log((1, " buf_chain_dump: ieb->cpos = %d\n", ieb->cpos ));
1654 mm_log((1, " buf_chain_dump: ieb->gpos = %d\n", ieb->gpos ));
1657 int clen = cp == ieb->tail ? ieb->tfill : cp->len;
1658 mm_log((1, "link: %p <- %p -> %p\n", cp->prev, cp, cp->next));
1659 if (ieb->head == cp && cp->prev) mm_log((1, "Head of chain has a non null prev\n"));
1660 if (ieb->tail == cp && cp->next) mm_log((1, "Tail of chain has a non null next\n"));
1662 if (ieb->head != cp && !cp->prev) mm_log((1, "Middle of chain has a null prev\n"));
1663 if (ieb->tail != cp && !cp->next) mm_log((1, "Middle of chain has a null next\n"));
1665 if (cp->prev && cp->prev->next != cp) mm_log((1, "%p = cp->prev->next != cp\n", cp->prev->next));
1666 if (cp->next && cp->next->prev != cp) mm_log((1, "%p cp->next->prev != cp\n", cp->next->prev));
1672 mm_log((1, "csize = %d %s ieb->length = %d\n", csize, csize == ieb->length ? "==" : "!=", ieb->length));
1677 =item bufchain_read(ig, buf, count)
1679 Does the reading from a source that can be seeked on
1682 buf - buffer to return data in
1683 count - number of bytes to read into buffer max
1690 bufchain_read(io_glue *ig, void *buf, size_t count) {
1691 io_ex_bchain *ieb = ig->exdata;
1692 size_t scount = count;
1696 mm_log((1, "bufchain_read(ig %p, buf %p, count %ld)\n", ig, buf, (long)count));
1699 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1700 if (clen == ieb->cpos) {
1701 if (ieb->cp == ieb->tail) break; /* EOF */
1702 ieb->cp = ieb->cp->next;
1704 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1707 sk = clen - ieb->cpos;
1708 sk = sk > scount ? scount : sk;
1710 memcpy(&cbuf[count-scount], &ieb->cp->buf[ieb->cpos], sk);
1716 mm_log((1, "bufchain_read: returning %ld\n", (long)(count-scount)));
1717 return count-scount;
1725 =item bufchain_write(ig, buf, count)
1727 Does the writing to a 'source' that can be seeked on
1730 buf - buffer that contains data
1731 count - number of bytes to write
1738 bufchain_write(io_glue *ig, const void *buf, size_t count) {
1739 char *cbuf = (char *)buf;
1740 io_ex_bchain *ieb = ig->exdata;
1741 size_t ocount = count;
1744 mm_log((1, "bufchain_write: ig = %p, buf = %p, count = %ld\n", ig, buf, (long)count));
1746 IOL_DEB( fprintf(IOL_DEBs, "bufchain_write: ig = %p, ieb->cpos = %ld, buf = %p, count = %ld\n", ig, (long) ieb->cpos, buf, (long)count) );
1749 mm_log((2, "bufchain_write: - looping - count = %ld\n", (long)count));
1750 if (ieb->cp->len == ieb->cpos) {
1751 mm_log((1, "bufchain_write: cp->len == ieb->cpos = %ld - advancing chain\n", (long) ieb->cpos));
1752 io_bchain_advance(ieb);
1755 sk = ieb->cp->len - ieb->cpos;
1756 sk = sk > count ? count : sk;
1757 memcpy(&ieb->cp->buf[ieb->cpos], &cbuf[ocount-count], sk);
1759 if (ieb->cp == ieb->tail) {
1760 int extend = ieb->cpos + sk - ieb->tfill;
1761 mm_log((2, "bufchain_write: extending tail by %d\n", extend));
1763 ieb->length += extend;
1764 ieb->tfill += extend;
1776 =item bufchain_close(ig)
1778 Closes a source that can be seeked on. Not sure if this should be an actual close
1779 or not. Does nothing for now. Should be fixed.
1788 bufchain_close(io_glue *ig) {
1789 mm_log((1, "bufchain_close(ig %p)\n",ig));
1790 IOL_DEB( fprintf(IOL_DEBs, "bufchain_close(ig %p)\n", ig) );
1796 /* bufchain_seek(ig, offset, whence)
1798 Implements seeking for a source that is seekable, the purpose of having this is to be able to
1799 have an offset into a file that is different from what the underlying library thinks.
1802 offset - offset into stream
1803 whence - whence argument a la lseek
1810 bufchain_seek(io_glue *ig, off_t offset, int whence) {
1811 io_ex_bchain *ieb = ig->exdata;
1814 off_t scount = calc_seek_offset(ieb->gpos, ieb->length, offset, whence);
1817 mm_log((1, "bufchain_seek(ig %p, offset %ld, whence %d)\n", ig, (long)offset, whence));
1820 i_push_error(0, "invalid whence supplied or seek before start of file");
1824 ieb->cp = ieb->head;
1829 int clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1830 if (clen == ieb->cpos) {
1831 if (ieb->cp == ieb->tail) break; /* EOF */
1832 ieb->cp = ieb->cp->next;
1834 clen = (ieb->cp == ieb->tail) ? ieb->tfill : ieb->cp->len;
1837 sk = clen - ieb->cpos;
1838 sk = sk > scount ? scount : sk;
1849 * extending file - get ieb into consistent state and then
1850 * call write which will get it to the correct position
1853 memset(TB, 0, BBSIZ);
1854 ieb->gpos = ieb->length;
1855 ieb->cpos = ieb->tfill;
1858 ssize_t rc, wl = i_min(wrlen, BBSIZ);
1859 mm_log((1, "bufchain_seek: wrlen = %d, wl = %ld\n", wrlen, (long)wl));
1860 rc = bufchain_write( ig, TB, wl );
1861 if (rc != wl) i_fatal(0, "bufchain_seek: Unable to extend file\n");
1866 mm_log((2, "bufchain_seek: returning ieb->gpos = %ld\n", (long)ieb->gpos));
1872 bufchain_destroy(io_glue *ig) {
1873 io_ex_bchain *ieb = ig->exdata;
1875 io_destroy_bufchain(ieb);
1881 =item fd_read(ig, buf, count)
1883 Read callback for file descriptor IO objects.
1887 static ssize_t fd_read(io_glue *igo, void *buf, size_t count) {
1888 io_fdseek *ig = (io_fdseek *)igo;
1891 result = _read(ig->fd, buf, count);
1893 result = read(ig->fd, buf, count);
1896 IOL_DEB(fprintf(IOL_DEBs, "fd_read(%p, %p, %u) => %d\n", ig, buf,
1897 (unsigned)count, (int)result));
1899 /* 0 is valid - means EOF */
1901 i_push_errorf(0, "read() failure: %s (%d)", my_strerror(errno), errno);
1907 static ssize_t fd_write(io_glue *igo, const void *buf, size_t count) {
1908 io_fdseek *ig = (io_fdseek *)igo;
1911 result = _write(ig->fd, buf, count);
1913 result = write(ig->fd, buf, count);
1916 IOL_DEB(fprintf(IOL_DEBs, "fd_write(%p, %p, %u) => %d\n", ig, buf,
1917 (unsigned)count, (int)result));
1920 i_push_errorf(errno, "write() failure: %s (%d)", my_strerror(errno), errno);
1926 static off_t fd_seek(io_glue *igo, off_t offset, int whence) {
1927 io_fdseek *ig = (io_fdseek *)igo;
1930 result = _lseek(ig->fd, offset, whence);
1932 result = lseek(ig->fd, offset, whence);
1935 if (result == (off_t)-1) {
1936 i_push_errorf(errno, "lseek() failure: %s (%d)", my_strerror(errno), errno);
1942 static int fd_close(io_glue *ig) {
1943 /* no, we don't close it */
1947 static ssize_t fd_size(io_glue *ig) {
1948 mm_log((1, "fd_size(ig %p) unimplemented\n", ig));
1959 Arnar M. Hrafnkelsson <addi@umich.edu>