+void chunklist_unlink(struct chunklist * l, struct chunk * p) {
+ if (p && l) {
+ struct chunk * prev = p->prev;
+ struct chunk * next = p->next;
+
+ /* Fix link to previous */
+ if (prev)
+ prev->next = next;
+ else
+ l->head = next;
+
+ if (next)
+ next->prev = prev;
+ else
+ l->tail = prev;
+
+ p->prev = NULL;
+ p->next = NULL;
+ l->numitems--;
+ }
+}
+
+/* Add a new list item to the tail */
+void chunklist_addtail(struct chunklist * l, struct chunk * p) {
+ if (!p || !l)
+ return;
+ if (l->tail) {
+ if (l->tail->next)
+ g_warning("addtail found list tail has a next pointer");
+ l->tail->next = p;
+ p->next = NULL;
+ p->prev = l->tail;
+ l->tail = p;
+ } else {
+ if (l->head)
+ g_warning("addtail found no list tail but a list head");
+ l->head = p;
+ l->tail = p;
+ p->prev = NULL;
+ p->next = NULL;
+ }
+ l->numitems++;
+}
+
+/* Add some new bytes to a chunklist */
+void addbuffer(struct chunklist * l, void * data, uint64_t len) {
+ void * buf;
+ uint64_t size = 64*1024;
+ struct chunk * pchunk;
+
+ while (len>0)
+ {
+ /* First see if there is a current chunk, and if it has space */
+ if (l->tail && l->tail->space) {
+ uint64_t towrite = len;
+ if (towrite > l->tail->space)
+ towrite = l->tail->space;
+ memcpy(l->tail->writeptr, data, towrite);
+ l->tail->length += towrite;
+ l->tail->space -= towrite;
+ l->tail->writeptr += towrite;
+ len -= towrite;
+ data += towrite;
+ }
+
+ if (len>0) {
+ /* We still need to write more, so prepare a new chunk */
+ if ((NULL == (buf = malloc(size))) || (NULL == (pchunk = calloc(1, sizeof(struct chunk))))) {
+ g_critical("Out of memory");
+ exit (1);
+ }
+
+ pchunk->buffer = buf;
+ pchunk->readptr = buf;
+ pchunk->writeptr = buf;
+ pchunk->space = size;
+ chunklist_addtail(l, pchunk);
+ }
+ }
+
+}
+
+/* returns 0 on success, -1 on failure */
+int writebuffer(int fd, struct chunklist * l) {
+
+ struct chunk * pchunk = NULL;
+ int res;
+ if (!l)
+ return 0;
+
+ while (!pchunk)
+ {
+ pchunk = l->head;
+ if (!pchunk)
+ return 0;
+ if (!(pchunk->length) || !(pchunk->readptr)) {
+ chunklist_unlink(l, pchunk);
+ free(pchunk->buffer);
+ free(pchunk);
+ pchunk = NULL;
+ }
+ }
+
+ /* OK we have a chunk with some data in */
+ res = write(fd, pchunk->readptr, pchunk->length);
+ if (res==0)
+ errno = EAGAIN;
+ if (res<=0)
+ return -1;
+ pchunk->length -= res;
+ pchunk->readptr += res;
+ if (!pchunk->length) {
+ chunklist_unlink(l, pchunk);
+ free(pchunk->buffer);
+ free(pchunk);
+ }
+ return 0;
+}
+
+
+