From 22c6d03bba83a3c68971e1927628ede12a3b618c Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Sat, 6 Feb 2010 21:55:03 -0800 Subject: [PATCH] sysdump: add back ymodem support; clean up memory dump structure Now we just need more front ends (information providers)... Signed-off-by: H. Peter Anvin --- com32/sysdump/backend.h | 28 +++++- com32/sysdump/backends.c | 26 ------ com32/sysdump/be_null.c | 30 +++++++ com32/sysdump/be_tftp.c | 3 + com32/sysdump/{ymsend.c => be_ymodem.c} | 155 ++++++++++++++++---------------- com32/sysdump/cpio.c | 29 ++++-- com32/sysdump/file.h | 25 ------ com32/sysdump/main.c | 76 +++++++++------- com32/sysdump/memory.c | 50 +++++++++++ com32/sysdump/serial.c | 63 ++++++++++--- com32/sysdump/serial.h | 18 ++++ com32/sysdump/srecsend.c | 76 ---------------- com32/sysdump/sysdump.h | 1 + com32/sysdump/ymsend.h | 10 --- com32/sysdump/zout.c | 10 ++- 15 files changed, 325 insertions(+), 275 deletions(-) delete mode 100644 com32/sysdump/backends.c create mode 100644 com32/sysdump/be_null.c rename com32/sysdump/{ymsend.c => be_ymodem.c} (57%) delete mode 100644 com32/sysdump/file.h create mode 100644 com32/sysdump/memory.c create mode 100644 com32/sysdump/serial.h delete mode 100644 com32/sysdump/srecsend.c delete mode 100644 com32/sysdump/ymsend.h diff --git a/com32/sysdump/backend.h b/com32/sysdump/backend.h index a83e393..343d296 100644 --- a/com32/sysdump/backend.h +++ b/com32/sysdump/backend.h @@ -5,12 +5,23 @@ #include #include #include +#include "serial.h" + +/* Backend flags */ +#define BE_NEEDLEN 0x01 struct backend { const char *name; - int blocksize; + const char *helpmsg; + int minargs; + + unsigned int blocksize; + unsigned int flags; + + size_t dbytes; + size_t zbytes; - int (*open)(struct backend *, const char *argv[]); + int (*open)(struct backend *, const char *argv[], size_t len); int (*write)(struct backend *, const char *buf, size_t len); z_stream zstream; @@ -24,15 +35,19 @@ struct backend { uint16_t srv_port; uint16_t seq; } tftp; + struct { + struct serial_if serial; + uint16_t seq; + } ymodem; }; }; /* zout.c */ -int init_data(struct backend *be, const char *argv[]); +int init_data(struct backend *be, const char *argv[], size_t len); int write_data(struct backend *be, const void *buf, size_t len, bool flush); /* cpio.c */ -int cpio_init(struct backend *be, const char *argv[]); +int cpio_init(struct backend *be, const char *argv[], size_t len); int cpio_mkdir(struct backend *be, const char *filename); int cpio_writefile(struct backend *be, const char *filename, const void *data, size_t len); @@ -41,4 +56,9 @@ int cpio_close(struct backend *be); /* backends.c */ struct backend *get_backend(const char *name); +/* backends */ +extern struct backend be_tftp; +extern struct backend be_ymodem; +extern struct backend be_null; + #endif /* BACKEND_H */ diff --git a/com32/sysdump/backends.c b/com32/sysdump/backends.c deleted file mode 100644 index 4d95dbb..0000000 --- a/com32/sysdump/backends.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * backends.c - */ - -#include -#include "backend.h" - -extern struct backend be_tftp; - -static struct backend *backends[] = -{ - &be_tftp, - NULL -}; - -struct backend *get_backend(const char *name) -{ - struct backend *be, **bep; - - for (bep = backends ; (be = *bep) ; bep++) { - if (!strcmp(name, be->name)) - return be; - } - - return NULL; -} diff --git a/com32/sysdump/be_null.c b/com32/sysdump/be_null.c new file mode 100644 index 0000000..4aab99c --- /dev/null +++ b/com32/sysdump/be_null.c @@ -0,0 +1,30 @@ +/* + * Null data output backend + */ + +#include "backend.h" + +static int be_null_open(struct backend *be, const char *argv[], size_t len) +{ + (void)be; + (void)argv; + (void)len; + return 0; +} + +static int be_null_write(struct backend *be, const char *buf, size_t len) +{ + (void)be; + (void)buf; + (void)len; + return 0; +} + +struct backend be_null = { + .name = "null", + .helpmsg = "", + .minargs = 0, + .blocksize = 32768, /* arbitrary */ + .open = be_null_open, + .write = be_null_write, +}; diff --git a/com32/sysdump/be_tftp.c b/com32/sysdump/be_tftp.c index 9d945f3..61dd4ec 100644 --- a/com32/sysdump/be_tftp.c +++ b/com32/sysdump/be_tftp.c @@ -121,7 +121,10 @@ static int be_tftp_write(struct backend *be, const char *buf, size_t len) struct backend be_tftp = { .name = "tftp", + .helpmsg = "filename tftp_server", + .minargs = 2, .blocksize = 512, + .flags = 0, .open = be_tftp_open, .write = be_tftp_write, }; diff --git a/com32/sysdump/ymsend.c b/com32/sysdump/be_ymodem.c similarity index 57% rename from com32/sysdump/ymsend.c rename to com32/sysdump/be_ymodem.c index 332b2b2..632758d 100644 --- a/com32/sysdump/ymsend.c +++ b/com32/sysdump/be_ymodem.c @@ -5,7 +5,8 @@ #include #include #include -#include "ymsend.h" +#include "backend.h" +#include "serial.h" enum { SOH = 0x01, @@ -64,105 +65,101 @@ static void add_crc16(uint8_t * blk, int len) *blk = crc; } -static void send_ack_blk(struct serial_if *sif, const void *data, size_t bytes) +static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes); + +static void send_ack_blk(struct backend *be, uint8_t *blk) +{ + printf("Sending block %u...\r", be->ymodem.seq); + + blk[0] = STX; + blk[1] = be->ymodem.seq++; + blk[2] = ~blk[1]; + add_crc16(blk+3, 1024); + + send_ack(be, blk, 1024+5); +} + +static void send_ack(struct backend *be, const uint8_t *blk, size_t bytes) { uint8_t ack_buf; - if (bytes) - sif->write(sif, data, bytes); + serial_write(&be->ymodem.serial, blk, bytes); do { do { - sif->read(sif, &ack_buf, 1); + serial_read(&be->ymodem.serial, &ack_buf, 1); } while (ack_buf != ACK && ack_buf != NAK); } while (ack_buf == NAK); } -static const uint8_t eot_buf = EOT; - -void send_ymodem(struct serial_if *sif, struct file_info *fileinfo, - void (*gen_data) (void *, size_t, struct file_info *, size_t)) +static int be_ymodem_open(struct backend *be, const char *argv[], size_t len) { - uint8_t ack_buf, blk_buf[1024 + 5], *np, *q; - const char *p; - size_t len, lx, pos; - int blk; + uint8_t ack_buf, blk_buf[1024 + 5]; + + be->ymodem.seq = 0; + /* Initialize serial port */ + if (serial_init(&be->ymodem.serial, argv+1)) + return -1; + /* Wait for initial handshake */ printf("Waiting for handshake...\n"); do { - sif->read(sif, &ack_buf, 1); + serial_read(&be->ymodem.serial, &ack_buf, 1); } while (ack_buf != 'C'); - /* Send initial batch header (filename, length etc.) */ - q = blk_buf + 3; - p = fileinfo->name; - while (*p) - *q++ = *p++; - *q++ = '\0'; + snprintf((char *)blk_buf+3, 1024, "%s%c%zu", argv[0], 0, len); + send_ack_blk(be, blk_buf); - lx = len = fileinfo->size; - do { - q++; - lx /= 10; - } while (lx); - - np = q; - lx = len; - do { - *--np = (lx % 10) + '0'; - lx /= 10; - } while (lx); - - while (q < blk_buf + 1024 + 3) - *q++ = 0; - - blk = 0; - pos = 0; - do { - if (blk != 0) { - gen_data(blk_buf + 3, 1024, fileinfo, pos); - pos += 1024; - len = (len < 1024) ? 0 : len - 1024; - } - - blk_buf[0] = STX; - blk_buf[1] = blk; - blk_buf[2] = ~blk; - add_crc16(blk_buf + 3, 1024); - - printf("Sending block %d...\r", blk); - send_ack_blk(sif, blk_buf, 1024 + 5); - - blk++; - } while (len); - - printf("\nSending EOT...\n"); - send_ack_blk(sif, &eot_buf, 1); - printf("Done.\n"); + return 0; } -void end_ymodem(struct serial_if *sif) +static int be_ymodem_write(struct backend *be, const char *buf, size_t len) { + static const uint8_t eot_buf = EOT; uint8_t ack_buf; - uint8_t blk_buf[128 + 5]; + uint8_t blk_buf[1024 + 5]; + + memcpy(blk_buf+3, buf, len); + if (len < 1024) + memset(blk_buf+3+1024-len, 0x1a, 1024-len); - /* Wait for initial handshake */ - printf("END: Waiting for handshake...\n"); - do { - sif->read(sif, &ack_buf, 1); - } while (ack_buf != 'C'); + send_ack_blk(be, blk_buf); - memset(blk_buf, 0, sizeof blk_buf); - blk_buf[0] = SOH; - blk_buf[1] = 0; - blk_buf[2] = 0xff; - add_crc16(blk_buf + 3, 128); - printf("Sending block 0...\n"); - send_ack_blk(sif, &blk_buf, 128 + 5); - - printf("Sending EOT...\n"); - sif->write(sif, &eot_buf, 1); - /* rb doesn't ack the EOT for an end batch transfer. */ - printf("Done.\n"); -} + if (len < 1024) { + printf("\nSending EOT...\n"); + send_ack(be, &eot_buf, 1); + + printf("Waiting for handshake...\n"); + do { + serial_read(&be->ymodem.serial, &ack_buf, 1); + } while (ack_buf != 'C'); + be->ymodem.seq = 0; + + printf("Sending batch termination block...\n"); + memset(blk_buf+3, 0, 128); + blk_buf[0] = SOH; + blk_buf[1] = 0; + blk_buf[2] = 0xff; + add_crc16(blk_buf + 3, 128); + serial_write(&be->ymodem.serial, blk_buf, 128 + 5); + /* + * rb doesn't seem to ack the EOT for an end batch transfer, + * contrary to spec. + */ + printf("Done.\n"); + serial_cleanup(&be->ymodem.serial); + } + + return 0; +} + +struct backend be_ymodem = { + .name = "ymodem", + .helpmsg = "filename port [speed]", + .minargs = 2, + .blocksize = 1024, + .flags = BE_NEEDLEN, + .open = be_ymodem_open, + .write = be_ymodem_write, +}; diff --git a/com32/sysdump/cpio.c b/com32/sysdump/cpio.c index b5a48df..120f7eb 100644 --- a/com32/sysdump/cpio.c +++ b/com32/sysdump/cpio.c @@ -12,11 +12,19 @@ #include "backend.h" #include "ctime.h" -static char pad[4]; /* Up to 4 zero bytes */ static uint32_t now; +static int cpio_pad(struct backend *be) +{ + static char pad[4]; /* Up to 4 zero bytes */ + if (be->dbytes & 3) + return write_data(be, pad, -be->dbytes & 3, false); + else + return 0; +} + static int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, - const char *filename, bool flush) + const char *filename) { static uint32_t inode = 2; char hdr[6+13*8+1]; @@ -40,19 +48,19 @@ static int cpio_hdr(struct backend *be, uint32_t mode, size_t datalen, 0); /* c_chksum */ rv |= write_data(be, hdr, 6+13*8, false); rv |= write_data(be, filename, nlen, false); - rv |= write_data(be, pad, (-nlen+6+13*8) & 3, flush); + rv |= cpio_pad(be); return rv; } -int cpio_init(struct backend *be, const char *argv[]) +int cpio_init(struct backend *be, const char *argv[], size_t len) { now = posix_time(); - return init_data(be, argv); + return init_data(be, argv, len); } int cpio_mkdir(struct backend *be, const char *filename) { - return cpio_hdr(be, 0040755, 0, filename, false); + return cpio_hdr(be, 0040755, 0, filename); } int cpio_writefile(struct backend *be, const char *filename, @@ -60,14 +68,17 @@ int cpio_writefile(struct backend *be, const char *filename, { int rv; - rv = cpio_hdr(be, 0100644, len, filename, false); + rv = cpio_hdr(be, 0100644, len, filename); rv |= write_data(be, data, len, false); - rv |= write_data(be, pad, -len & 3, false); + rv |= cpio_pad(be); return rv; } int cpio_close(struct backend *be) { - return cpio_hdr(be, 0, 0, "TRAILER!!!", true); + int rv; + rv = cpio_hdr(be, 0, 0, "TRAILER!!!"); + rv |= write_data(be, NULL, 0, true); + return rv; } diff --git a/com32/sysdump/file.h b/com32/sysdump/file.h deleted file mode 100644 index 72fad3d..0000000 --- a/com32/sysdump/file.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef FILE_H -#define FILE_H - -#include - -struct serial_if { - int port; - void *pvt; - void (*read) (struct serial_if *, void *, size_t); - void (*write) (struct serial_if *, const void *, size_t); -}; - -struct file_info { - const char *name; - size_t base; - size_t size; - void *pvt; -}; - - -int serial_init(struct serial_if *sif); -void serial_read(struct serial_if *sif, void *data, size_t n); -void serial_write(struct serial_if *sif, const void *data, size_t n); - -#endif /* FILE_H */ diff --git a/com32/sysdump/main.c b/com32/sysdump/main.c index d2475c5..decb86d 100644 --- a/com32/sysdump/main.c +++ b/com32/sysdump/main.c @@ -113,54 +113,62 @@ int main(int argc, char *argv[]) } #endif -static char *lowmem; -static size_t lowmem_len; +static void dump_all(struct backend *be, const char *argv[], size_t len) +{ + + cpio_init(be, argv, len); + + dump_memory(be); + dump_vesa_tables(be); -static void snapshot_lowmem(void) + cpio_close(be); +} + +static struct backend *backends[] = { - extern void _start(void); - - lowmem_len = (size_t)_start; - lowmem = malloc(lowmem_len); - if (lowmem) { - printf("Snapshotting lowmem... "); - cli(); - memcpy(lowmem, (void *)0, lowmem_len); - sti(); - printf("ok\n"); - } + &be_tftp, + &be_ymodem, + &be_null, + NULL +}; + +__noreturn usage(void) +{ + struct backend **bep, *be; + + printf("Usage:\n"); + for (bep = backends ; (be = *bep) ; bep++) + printf(" %s %s %s\n", program, be->name, be->helpmsg); + + exit(1); } int main(int argc, char *argv[]) { - struct backend *be; + struct backend **bep, *be; + size_t len = 0; openconsole(&dev_null_r, &dev_stdcon_w); - if (argc < 4) { - printf("Usage:\n" - " sysdump tftp filename server_hostname\n"); - exit(1); + if (argc < 2) + usage(); + + for (bep = backends ; (be = *bep) ; bep++) { + if (!strcmp(be->name, argv[1])) + break; } + if (!be || argc < be->minargs + 2) + usage(); + /* Do this as early as possible */ snapshot_lowmem(); - be = get_backend(argv[1]); - if (!be) - die("unknown backend"); - - if (cpio_init(be, (const char **)argv+2)) - die("backend initialization error"); - - if (lowmem) { - cpio_writefile(be, "lowmem.bin", lowmem, lowmem_len); - free(lowmem); + if (be->flags & BE_NEEDLEN) { + dump_all(&be_null, NULL, 0); + dump_all(be, (const char **)argv + 2, be_null.zbytes); + } else { + dump_all(be, (const char **)argv + 2, 0); } - - dump_vesa_tables(be); - - cpio_close(be); - return 0; } diff --git a/com32/sysdump/memory.c b/com32/sysdump/memory.c new file mode 100644 index 0000000..9d391ec --- /dev/null +++ b/com32/sysdump/memory.c @@ -0,0 +1,50 @@ +/* + * Dump memory + */ + +#include +#include +#include +#include +#include "sysdump.h" +#include "backend.h" + +static char *lowmem; +static size_t lowmem_len; + +void *zero_addr; /* Hack to keep gcc from complaining */ + +void snapshot_lowmem(void) +{ + extern void _start(void); + + lowmem_len = (size_t)_start; + lowmem = malloc(lowmem_len); + if (lowmem) { + printf("Snapshotting lowmem... "); + cli(); + memcpy(lowmem, zero_addr, lowmem_len); + sti(); + printf("ok\n"); + } +} + +static void dump_memory_range(struct backend *be, const void *where, + const void *addr, size_t len) +{ + char filename[32]; + + sprintf(filename, "memory/%08zx", (size_t)addr); + cpio_writefile(be, filename, where, len); +} + +void dump_memory(struct backend *be) +{ + cpio_mkdir(be, "memory"); + + if (lowmem) + dump_memory_range(be, lowmem, zero_addr, lowmem_len); + + /* Look for a DMI header */ +} + diff --git a/com32/sysdump/serial.c b/com32/sysdump/serial.c index 75bbd48..803b05f 100644 --- a/com32/sysdump/serial.c +++ b/com32/sysdump/serial.c @@ -2,7 +2,7 @@ #include #include -#include "file.h" +#include "serial.h" enum { THR = 0, @@ -19,33 +19,57 @@ enum { SCR = 7, }; -int serial_init(struct serial_if *sif) + +int serial_init(struct serial_if *sif, const char *argv[]) { - uint16_t port = sif->port; + uint16_t port; + unsigned int speed, divisor; uint8_t dll, dlm, lcr; + port = strtoul(argv[0], NULL, 0); + if (port <= 3) + port = *(uint16_t *)(0x400 + port*2); + + if (argv[1]) + speed = strtoul(argv[1], NULL, 0); + else + speed = 115200; + + divisor = 115200/speed; + + /* Save old register settings */ + sif->old.lcr = inb(port + LCR); + sif->old.mcr = inb(port + MCR); + sif->old.iir = inb(port + IIR); + /* Set 115200n81 */ - outb(0x83, port + LCR); - outb(0x01, port + DLL); - outb(0x00, port + DLM); + outb(0x83, port + LCR); /* Enable divisor access */ + sif->old.dll = inb(port + DLL); + sif->old.dlm = inb(port + DLM); + outb(divisor, port + DLL); + outb(divisor >> 8, port + DLM); (void)inb(port + IER); /* Synchronize */ + dll = inb(port + DLL); dlm = inb(port + DLM); lcr = inb(port + LCR); outb(0x03, port + LCR); (void)inb(port + IER); /* Synchronize */ + sif->old.ier = inb(port + IER); - if (dll != 0x01 || dlm != 0x00 || lcr != 0x83) + if (dll != (uint8_t)divisor || + dlm != (uint8_t)(divisor >> 8) || + lcr != 0x83) return -1; /* This doesn't look like a serial port */ /* Disable interrupts */ - outb(port + IER, 0); + outb(0, port + IER); /* Enable 16550A FIFOs if available */ - outb(port + FCR, 0x01); /* Enable FIFO */ + outb(0x41, port + FCR); /* Enable FIFO */ (void)inb(port + IER); /* Synchronize */ if (inb(port + IIR) < 0xc0) - outb(port + FCR, 0x00); /* Disable FIFOs if non-functional */ + outb(0x00, port + FCR); /* Disable FIFOs if non-functional */ (void)inb(port + IER); /* Synchronize */ return 0; @@ -80,3 +104,22 @@ void serial_read(struct serial_if *sif, void *data, size_t n) *p++ = inb(port + RBR); } } + +void serial_cleanup(struct serial_if *sif) +{ + uint16_t port = sif->port; + + outb(0x83, port + LCR); + (void)inb(port + IER); + outb(sif->old.dll, port + DLL); + outb(sif->old.dlm, port + DLM); + (void)inb(port + IER); + outb(sif->old.lcr & 0x7f, port + LCR); + (void)inb(port + IER); + outb(sif->old.mcr, port + MCR); + outb(sif->old.ier, port + IER); + if ((sif->old.iir & 0xc0) != 0xc0) + outb(0x00, port + FCR); /* Disable FIFOs */ +} + + diff --git a/com32/sysdump/serial.h b/com32/sysdump/serial.h new file mode 100644 index 0000000..be95f6c --- /dev/null +++ b/com32/sysdump/serial.h @@ -0,0 +1,18 @@ +#ifndef SERIAL_H +#define SERIAL_H + +#include + +struct serial_if { + uint16_t port; + struct { + uint8_t dll, dlm, ier, iir, lcr, mcr; + } old; +}; + +int serial_init(struct serial_if *sif, const char *argv[]); +void serial_read(struct serial_if *sif, void *data, size_t n); +void serial_write(struct serial_if *sif, const void *data, size_t n); +void serial_cleanup(struct serial_if *sif); + +#endif /* SERIAL_H */ diff --git a/com32/sysdump/srecsend.c b/com32/sysdump/srecsend.c deleted file mode 100644 index 6abe32a..0000000 --- a/com32/sysdump/srecsend.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SREC send routine. - */ - -#include -#include -#include -#include "srecsend.h" - -static void make_srec(struct serial_if *sif, char type, size_t addr, - const void *data, size_t len) -{ - char buf[80]; /* More than the largest possible size */ - char *p; - const uint8_t *dp = data; - size_t alen = (type == '0') ? 4 : 8; - uint8_t csum; - - p = buf; - p += sprintf(p, "S%c%02X%0*zX", type, len+alen+1, alen, addr); - - csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24); - while (len) { - p += sprintf(p, "%02X", *dp); - csum += *dp; - dp++; - } - csum = 0xff - csum; - p += sprintf(p, "%02X\r\n", csum); - - sif->write(sif, buf, p-buf); -} - -void send_srec(struct serial_if *sif, struct file_info *fileinfo, - void (*gen_data) (void *, size_t, struct file_info *, size_t)) -{ - uint8_t blk_buf[1024]; - const uint8_t *np; - size_t addr, len, bytes, chunk, offset, pos; - int blk; - - len = fileinfo->size; - - make_srec(sif, '0', 0, NULL, 0); - - blk = 0; - pos = 0; - addr = fileinfo->base; - while (len) { - gen_data(blk_buf, sizeof blk_buf, fileinfo, pos); - pos += sizeof blk_buf; - bytes = sizeof blk_buf; - if (bytes > len) - bytes = len; - len -= bytes; - - printf("Sending block %d...\r", blk); - - np = blk_buf; - while (bytes) { - chunk = bytes > 32 ? 32 : bytes; - - make_srec(sif, '3', addr, np, chunk); - - bytes -= chunk; - offset += chunk; - np += chunk; - addr += chunk; - } - blk++; - } - - printf("\nSending EOT...\n"); - make_srec(sif, '7', fileinfo->base, NULL, 0); - printf("Done.\n"); -} diff --git a/com32/sysdump/sysdump.h b/com32/sysdump/sysdump.h index 04f35b5..87f7e2b 100644 --- a/com32/sysdump/sysdump.h +++ b/com32/sysdump/sysdump.h @@ -3,6 +3,7 @@ struct backend; +void dump_memory(struct backend *); void dump_vesa_tables(struct backend *); #endif /* SYSDUMP_H */ diff --git a/com32/sysdump/ymsend.h b/com32/sysdump/ymsend.h deleted file mode 100644 index ac6bef6..0000000 --- a/com32/sysdump/ymsend.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef YMSEND_H -#define YMSEND_H - -#include "file.h" - -void send_ymodem(struct serial_if *, struct file_info *, - void (*)(void *, size_t, struct file_info *, size_t)); -void end_ymodem(struct serial_if *); - -#endif /* YMSEND_H */ diff --git a/com32/sysdump/zout.c b/com32/sysdump/zout.c index 6ba6a5c..d3be893 100644 --- a/com32/sysdump/zout.c +++ b/com32/sysdump/zout.c @@ -10,13 +10,13 @@ #include #include "backend.h" -int init_data(struct backend *be, const char *argv[]) +int init_data(struct backend *be, const char *argv[], size_t len) { be->outbuf = malloc(be->blocksize); if (!be->outbuf) return -1; - if (be->open(be, argv)) + if (be->open(be, argv, len)) return -1; memset(&be->zstream, 0, sizeof be->zstream); @@ -24,6 +24,8 @@ int init_data(struct backend *be, const char *argv[]) be->zstream.next_out = (void *)be->outbuf; be->zstream.avail_out = be->blocksize; + be->dbytes = be->zbytes = 0; + /* Initialize a gzip data stream */ if (deflateInit2(&be->zstream, 9, Z_DEFLATED, 16+15, 9, Z_DEFAULT_STRATEGY) < 0) @@ -39,11 +41,14 @@ int write_data(struct backend *be, const void *buf, size_t len, bool flush) be->zstream.next_in = (void *)buf; be->zstream.avail_in = len; + be->dbytes += len; + while (be->zstream.avail_in || (flush && rv == Z_OK)) { rv = deflate(&be->zstream, flush ? Z_FINISH : Z_NO_FLUSH); if (be->zstream.avail_out == 0) { if (be->write(be, be->outbuf, be->blocksize)) return -1; + be->zbytes += be->blocksize; be->zstream.next_out = (void *)be->outbuf; be->zstream.avail_out = be->blocksize; } @@ -55,6 +60,7 @@ int write_data(struct backend *be, const void *buf, size_t len, bool flush) /* Output the last (fractional) packet... may be zero */ if (be->write(be, be->outbuf, be->blocksize - be->zstream.avail_out)) return -1; + be->zbytes += be->blocksize - be->zstream.avail_out; free(be->outbuf); } -- 2.7.4