static int _streamref_readdelim (struct _mu_stream *str, char *buf, size_t bufsize, int delim, size_t *pnread) { struct _mu_streamref *sp = (struct _mu_streamref *)str; int rc; size_t nread; mu_off_t off; rc = mu_stream_seek (sp->transport, sp->offset, MU_SEEK_SET, &off); if (rc == 0) { rc = mu_stream_readdelim (sp->transport, buf, bufsize, delim, &nread); if (rc == 0) { if (sp->end) { size_t size = sp->end - off + 1; if (nread > size) nread = size; } sp->offset += nread; *pnread = nread; } } else if (rc == ESPIPE) { *pnread = 0; mu_stream_clearerr (sp->transport); return 0; } return streamref_return (sp, rc); }
/* Copy SIZE bytes from SRC to DST. If SIZE is 0, copy everything up to EOF. */ int mu_stream_copy (mu_stream_t dst, mu_stream_t src, mu_off_t size, mu_off_t *pcsz) { int status; size_t bufsize, n; char *buf; mu_off_t total = 0; if (pcsz) *pcsz = 0; if (size == 0) { status = mu_stream_size (src, &size); switch (status) { case 0: break; case ENOSYS: size = 0; break; default: return status; } if (size) { mu_off_t pos; status = mu_stream_seek (src, 0, MU_SEEK_CUR, &pos); switch (status) { case 0: if (pos > size) return ESPIPE; size -= pos; break; case EACCES: mu_stream_clearerr (src); case ENOSYS: size = 0; break; default: return status; } } } bufsize = size; if (!bufsize) bufsize = STREAMCPY_MAX_BUF_SIZE; for (; (buf = malloc (bufsize)) == NULL; bufsize >>= 1) if (bufsize < STREAMCPY_MIN_BUF_SIZE) return ENOMEM; if (size) while (size) { size_t rdsize = bufsize < size ? bufsize : size; status = mu_stream_read (src, buf, rdsize, &n); if (status) break; if (n == 0) break; status = mu_stream_write (dst, buf, n, NULL); if (status) break; size -= n; total += n; } else while ((status = mu_stream_read (src, buf, bufsize, &n)) == 0 && n > 0) { status = mu_stream_write (dst, buf, n, NULL); if (status) break; total += n; } if (pcsz) *pcsz = total; /* FIXME: When EOF error code is implemented: else if (total == 0) status = EOF; */ free (buf); return status; }