summaryrefslogtreecommitdiff
path: root/com32/libupload
diff options
context:
space:
mode:
Diffstat (limited to 'com32/libupload')
-rw-r--r--com32/libupload/.gitignore2
-rw-r--r--com32/libupload/Makefile39
-rw-r--r--com32/libupload/cpio.c75
-rw-r--r--com32/libupload/ctime.c77
-rw-r--r--com32/libupload/ctime.h8
-rw-r--r--com32/libupload/serial.c169
-rw-r--r--com32/libupload/serial.h19
-rw-r--r--com32/libupload/srecsend.h9
-rw-r--r--com32/libupload/tftp.h22
-rw-r--r--com32/libupload/upload_backend.h56
-rw-r--r--com32/libupload/upload_srec.c85
-rw-r--r--com32/libupload/upload_tftp.c204
-rw-r--r--com32/libupload/upload_ymodem.c175
-rw-r--r--com32/libupload/ymodem.txt2108
-rw-r--r--com32/libupload/zout.c100
15 files changed, 3148 insertions, 0 deletions
diff --git a/com32/libupload/.gitignore b/com32/libupload/.gitignore
new file mode 100644
index 00000000..e0292b19
--- /dev/null
+++ b/com32/libupload/.gitignore
@@ -0,0 +1,2 @@
+*.o
+*.a
diff --git a/com32/libupload/Makefile b/com32/libupload/Makefile
new file mode 100644
index 00000000..83053350
--- /dev/null
+++ b/com32/libupload/Makefile
@@ -0,0 +1,39 @@
+# Include configuration rules
+topdir = ../..
+MAKEDIR = $(topdir)/mk
+include $(MAKEDIR)/com32.mk
+
+REQFLAGS += -I./
+
+SUBDIRS := .
+LIBOBJS := $(foreach dir,$(SUBDIRS),$(patsubst %.c,%.o,$(wildcard $(dir)/*.c)))
+
+BINDIR = /usr/bin
+LIBDIR = /usr/lib
+DATADIR = /usr/share
+AUXDIR = $(DATADIR)/syslinux
+INCDIR = /usr/include
+COM32DIR = $(AUXDIR)/com32
+
+all: libcom32upload.a
+
+libcom32upload.a : $(LIBOBJS)
+ rm -f $@
+ $(AR) cq $@ $^
+ $(RANLIB) $@
+
+tidy dist clean:
+ find . \( -name \*.o -o -name \*.a -o -name .\*.d -o -name \*.tmp \) -print0 | \
+ xargs -0r rm -f
+
+spotless: clean
+ rm -f *.a
+ rm -f *~ \#* */*~ */\#*
+
+install: all
+ mkdir -m 755 -p $(INSTALLROOT)$(COM32DIR)
+ install -m 644 libcom32upload.a $(INSTALLROOT)$(COM32DIR)
+ mkdir -p $(INSTALLROOT)$(COM32DIR)/include/
+ cp -r *.h $(INSTALLROOT)$(COM32DIR)/include/
+
+-include .*.d */.*.d */*/.*.d
diff --git a/com32/libupload/cpio.c b/com32/libupload/cpio.c
new file mode 100644
index 00000000..25b464d4
--- /dev/null
+++ b/com32/libupload/cpio.c
@@ -0,0 +1,75 @@
+/*
+ * cpio.c
+ *
+ * Write a compressed CPIO file
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <zlib.h>
+#include "upload_backend.h"
+#include "ctime.h"
+
+int cpio_pad(struct upload_backend *be)
+{
+ static char pad[4]; /* Up to 4 zero bytes */
+ if (be->dbytes & 3)
+ return write_data(be, pad, -be->dbytes & 3);
+ else
+ return 0;
+}
+
+int cpio_hdr(struct upload_backend *be, uint32_t mode, size_t datalen,
+ const char *filename)
+{
+ static uint32_t inode = 2;
+ char hdr[6+13*8+1];
+ int nlen = strlen(filename)+1;
+ int rv = 0;
+
+ cpio_pad(be);
+
+ sprintf(hdr, "%06o%08x%08x%08x%08x%08x%08x%08zx%08x%08x%08x%08x%08x%08x",
+ 070701, /* c_magic */
+ inode++, /* c_ino */
+ mode, /* c_mode */
+ 0, /* c_uid */
+ 0, /* c_gid */
+ 1, /* c_nlink */
+ be->now, /* c_mtime */
+ datalen, /* c_filesize */
+ 0, /* c_maj */
+ 0, /* c_min */
+ 0, /* c_rmaj */
+ 0, /* c_rmin */
+ nlen, /* c_namesize */
+ 0); /* c_chksum */
+ rv |= write_data(be, hdr, 6+13*8);
+ rv |= write_data(be, filename, nlen);
+ rv |= cpio_pad(be);
+ return rv;
+}
+
+int cpio_mkdir(struct upload_backend *be, const char *filename)
+{
+ return cpio_hdr(be, MODE_DIR, 0, filename);
+}
+
+int cpio_writefile(struct upload_backend *be, const char *filename,
+ const void *data, size_t len)
+{
+ int rv;
+
+ rv = cpio_hdr(be, MODE_FILE, len, filename);
+ rv |= write_data(be, data, len);
+ rv |= cpio_pad(be);
+
+ return rv;
+}
+
+int cpio_close(struct upload_backend *be)
+{
+ return cpio_hdr(be, 0, 0, "TRAILER!!!");
+}
diff --git a/com32/libupload/ctime.c b/com32/libupload/ctime.c
new file mode 100644
index 00000000..56c8efb6
--- /dev/null
+++ b/com32/libupload/ctime.c
@@ -0,0 +1,77 @@
+#include <com32.h>
+#include <string.h>
+#include "ctime.h"
+
+static uint8_t frombcd(uint8_t v)
+{
+ uint8_t a = v & 0x0f;
+ uint8_t b = v >> 4;
+
+ return a + b*10;
+}
+
+uint32_t posix_time(void)
+{
+ /* Days from March 1 for a specific month, starting in March */
+ static const unsigned int yday[12] =
+ { 0, 31, 61, 92, 122, 153, 184, 214, 245, 275, 306, 337 };
+ com32sys_t ir, d0, d1, t0;
+ unsigned int c, y, mo, d, h, m, s;
+ uint32_t t;
+
+ memset(&ir, 0, sizeof ir);
+
+ ir.eax.b[1] = 0x04;
+ __intcall(0x1A, &ir, &d0);
+
+ ir.eax.b[1] = 0x02;
+ __intcall(0x1A, &ir, &t0);
+
+ ir.eax.b[1] = 0x04;
+ __intcall(0x1A, &ir, &d1);
+
+ if (t0.ecx.b[1] < 0x12)
+ d0 = d1;
+
+ c = frombcd(d0.ecx.b[1]);
+ y = frombcd(d0.ecx.b[0]);
+ mo = frombcd(d0.edx.b[1]);
+ d = frombcd(d0.edx.b[0]);
+
+ h = frombcd(t0.ecx.b[1]);
+ m = frombcd(t0.ecx.b[0]);
+ s = frombcd(t0.edx.b[1]);
+
+ /* We of course have no idea about the timezone, so ignore it */
+
+ /*
+ * Look for impossible dates... this code was written in 2010, so
+ * assume any century less than 20 is just broken.
+ */
+ if (c < 20)
+ c = 20;
+ y += c*100;
+
+ /* Consider Jan and Feb as the last months of the previous year */
+ if (mo < 3) {
+ y--;
+ mo += 12;
+ }
+
+ /*
+ * Just in case: if the month is nonsense, don't read off the end
+ * of the table...
+ */
+ if (mo-3 > 11)
+ return 0;
+
+ t = y*365 + y/4 - y/100 + y/400 + yday[mo-3] + d - 719469;
+ t *= 24;
+ t += h;
+ t *= 60;
+ t += m;
+ t *= 60;
+ t += s;
+
+ return t;
+}
diff --git a/com32/libupload/ctime.h b/com32/libupload/ctime.h
new file mode 100644
index 00000000..e6461253
--- /dev/null
+++ b/com32/libupload/ctime.h
@@ -0,0 +1,8 @@
+#ifndef CTIME_H
+#define CTIME_H
+
+#include <inttypes.h>
+
+uint32_t posix_time(void);
+
+#endif /* CTIME_H */
diff --git a/com32/libupload/serial.c b/com32/libupload/serial.c
new file mode 100644
index 00000000..a3987531
--- /dev/null
+++ b/com32/libupload/serial.c
@@ -0,0 +1,169 @@
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <console.h>
+#include <sys/io.h>
+#include <sys/cpu.h>
+#include <syslinux/config.h>
+
+#include "serial.h"
+
+enum {
+ THR = 0,
+ RBR = 0,
+ DLL = 0,
+ DLM = 1,
+ IER = 1,
+ IIR = 2,
+ FCR = 2,
+ LCR = 3,
+ MCR = 4,
+ LSR = 5,
+ MSR = 6,
+ SCR = 7,
+};
+
+
+int serial_init(struct serial_if *sif, const char *argv[])
+{
+ const struct syslinux_serial_console_info *sci
+ = syslinux_serial_console_info();
+ uint16_t port;
+ unsigned int divisor;
+ uint8_t dll, dlm, lcr;
+
+ if (!argv[0]) {
+ if (sci->iobase) {
+ port = sci->iobase;
+ } else {
+ printf("No port number specified and not using serial console!\n");
+ return -1;
+ }
+ } else {
+ port = strtoul(argv[0], NULL, 0);
+ if (port <= 3) {
+ uint16_t addr = ((uint16_t *)0x400)[port];
+ if (!addr) {
+ printf("No serial port address found!\n");
+ return -1;
+ }
+ printf("Serial port %u is at 0x%04x\n", port, addr);
+ port = addr;
+ }
+ }
+
+ sif->port = port;
+ sif->console = false;
+
+ divisor = 1; /* Default speed = 115200 bps */
+
+ /* Check to see if this is the same as the serial console */
+ if (port == sci->iobase) {
+ /* Overlaying the console... */
+ sif->console = true;
+
+ /* Default to already configured speed */
+ divisor = sci->divisor;
+
+ /* Shut down I/O to the console for the time being */
+ openconsole(&dev_null_r, &dev_null_w);
+ }
+
+ if (argv[0] && argv[1])
+ divisor = 115200/strtoul(argv[1], NULL, 0);
+
+ cli(); /* Just in case... */
+
+ /* Save old register settings */
+ sif->old.lcr = inb(port + LCR);
+ sif->old.mcr = inb(port + MCR);
+ sif->old.iir = inb(port + IIR);
+
+ /* Set speed */
+ 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); /* Enable data access, n81 */
+ (void)inb(port + IER); /* Synchronize */
+ sif->old.ier = inb(port + IER);
+
+ /* Disable interrupts */
+ outb(0, port + IER);
+
+ sti();
+
+ if (dll != (uint8_t)divisor ||
+ dlm != (uint8_t)(divisor >> 8) ||
+ lcr != 0x83) {
+ serial_cleanup(sif);
+ printf("No serial port detected!\n");
+ return -1; /* This doesn't look like a serial port */
+ }
+
+ /* Enable 16550A FIFOs if available */
+ outb(0x01, port + FCR); /* Enable FIFO */
+ (void)inb(port + IER); /* Synchronize */
+ if (inb(port + IIR) < 0xc0)
+ outb(0x00, port + FCR); /* Disable FIFOs if non-functional */
+ (void)inb(port + IER); /* Synchronize */
+
+ return 0;
+}
+
+void serial_write(struct serial_if *sif, const void *data, size_t n)
+{
+ uint16_t port = sif->port;
+ const char *p = data;
+ uint8_t lsr;
+
+ while (n--) {
+ do {
+ lsr = inb(port + LSR);
+ } while (!(lsr & 0x20));
+
+ outb(*p++, port + THR);
+ }
+}
+
+void serial_read(struct serial_if *sif, void *data, size_t n)
+{
+ uint16_t port = sif->port;
+ char *p = data;
+ uint8_t lsr;
+
+ while (n--) {
+ do {
+ lsr = inb(port + LSR);
+ } while (!(lsr & 0x01));
+
+ *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)
+ outb(0x00, port + FCR); /* Disable FIFOs */
+
+ /* Re-enable console messages, if we shut them down */
+ if (sif->console)
+ openconsole(&dev_null_r, &dev_stdcon_w);
+}
diff --git a/com32/libupload/serial.h b/com32/libupload/serial.h
new file mode 100644
index 00000000..356f2cef
--- /dev/null
+++ b/com32/libupload/serial.h
@@ -0,0 +1,19 @@
+#ifndef SERIAL_H
+#define SERIAL_H
+
+#include <stddef.h>
+
+struct serial_if {
+ uint16_t port;
+ bool console;
+ 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/libupload/srecsend.h b/com32/libupload/srecsend.h
new file mode 100644
index 00000000..667be20d
--- /dev/null
+++ b/com32/libupload/srecsend.h
@@ -0,0 +1,9 @@
+#ifndef SRECSEND_H
+#define SRECSEND_H
+
+#include "file.h"
+
+void send_srec(struct serial_if *, struct file_info *,
+ void (*)(void *, size_t, struct file_info *, size_t));
+
+#endif /* SRECSEND_H */
diff --git a/com32/libupload/tftp.h b/com32/libupload/tftp.h
new file mode 100644
index 00000000..323dc16a
--- /dev/null
+++ b/com32/libupload/tftp.h
@@ -0,0 +1,22 @@
+#include <stdint.h>
+
+#ifndef UPLOAD_TFTP
+#define UPLOAD_TFTP
+/* TFTP Error codes */
+enum tftp_error_codes {
+TFTP_ERR_UNKNOWN_ERROR = 0, // We have to use the message from the server
+TFTP_ERR_FILE_NOT_FOUND = 1, /**< File not found */
+TFTP_ERR_ACCESS_DENIED = 2, /**< Access violation */
+TFTP_ERR_DISK_FULL = 3, /**< Disk full or allocation exceeded */
+TFTP_ERR_ILLEGAL_OP = 4, /**< Illegal TFTP operation */
+TFTP_ERR_UNKNOWN_TID = 5, /**< Unknown transfer ID */
+TFTP_ERR_FILE_EXISTS = 6, /**< File already exists */
+TFTP_ERR_UNKNOWN_USER = 7, /**< No such user */
+TFTP_ERR_BAD_OPTS = 8, /**< Option negotiation failed */
+TFTP_ERR_UNABLE_TO_RESOLVE = 9, // Not in RFC, internal usage
+TFTP_ERR_UNABLE_TO_CONNECT = 10, // Not in RFC, internal usage
+TFTP_OK = 11, /* Not in RFC */
+};
+
+extern const char *tftp_string_error_message[];
+#endif
diff --git a/com32/libupload/upload_backend.h b/com32/libupload/upload_backend.h
new file mode 100644
index 00000000..7ea03e46
--- /dev/null
+++ b/com32/libupload/upload_backend.h
@@ -0,0 +1,56 @@
+#ifndef BACKEND_H
+#define BACKEND_H
+
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <zlib.h>
+#include "serial.h"
+#include "tftp.h"
+
+/* Backend flags */
+#define BE_NEEDLEN 0x01
+
+struct upload_backend {
+ const char *name;
+ const char *helpmsg;
+ int minargs;
+
+ size_t dbytes;
+ size_t zbytes;
+ const char **argv;
+
+ uint32_t now;
+
+ int (*write)(struct upload_backend *);
+
+ z_stream zstream;
+ char *outbuf;
+ size_t alloc;
+};
+
+/* zout.c */
+int init_data(struct upload_backend *be, const char *argv[]);
+int write_data(struct upload_backend *be, const void *buf, size_t len);
+int flush_data(struct upload_backend *be);
+
+/* cpio.c */
+#define cpio_init init_data
+int cpio_hdr(struct upload_backend *be, uint32_t mode, size_t datalen,
+ const char *filename);
+int cpio_mkdir(struct upload_backend *be, const char *filename);
+int cpio_writefile(struct upload_backend *be, const char *filename,
+ const void *data, size_t len);
+int cpio_close(struct upload_backend *be);
+#define MODE_FILE 0100644
+#define MODE_DIR 0040755
+
+/* backends.c */
+struct upload_backend *get_upload_backend(const char *name);
+
+/* backends */
+extern struct upload_backend upload_tftp;
+extern struct upload_backend upload_ymodem;
+extern struct upload_backend upload_srec;
+
+#endif /* BACKEND_H */
diff --git a/com32/libupload/upload_srec.c b/com32/libupload/upload_srec.c
new file mode 100644
index 00000000..c1907131
--- /dev/null
+++ b/com32/libupload/upload_srec.c
@@ -0,0 +1,85 @@
+/*
+ * S-records dump routine -- dumps S-records on the console
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <minmax.h>
+#include "upload_backend.h"
+
+/* Write a single S-record */
+static int write_srecord(unsigned int len, unsigned int alen,
+ uint32_t addr, uint8_t type, const void *data)
+{
+ char buf[2+2+8+255*2+2+2];
+ char *p = buf;
+ uint8_t csum;
+ const uint8_t *dptr = data;
+ unsigned int i;
+
+ switch (alen) {
+ case 2:
+ addr &= 0xffff;
+ break;
+ case 3:
+ addr &= 0xffffff;
+ break;
+ case 4:
+ break;
+ }
+
+ csum = (len+alen+1) + addr + (addr >> 8) + (addr >> 16) + (addr >> 24);
+ for (i = 0; i < len; i++)
+ csum += dptr[i];
+ csum = 0xff-csum;
+
+ p += sprintf(p, "S%c%02X%0*X", type, len+alen+1, alen*2, addr);
+ for (i = 0; i < len; i++)
+ p += sprintf(p, "%02X", dptr[i]);
+ p += sprintf(p, "%02X\n", csum);
+
+ fputs(buf, stdout);
+ return 0;
+}
+
+static int upload_srec_write(struct upload_backend *be)
+{
+ char name[33];
+ const char *buf;
+ size_t len, chunk, offset, hdrlen;
+
+ buf = be->outbuf;
+ len = be->zbytes;
+
+ putchar('\n');
+
+ hdrlen = snprintf(name, sizeof name, "%.32s",
+ be->argv[0] ? be->argv[0] : "");
+
+ /* Write head record */
+ write_srecord(hdrlen, 2, 0, '0', name);
+
+ /* Write data records */
+ offset = 0;
+ while (len) {
+ chunk = min(len, (size_t)32);
+
+ write_srecord(chunk, 4, offset, '3', buf);
+ buf += chunk;
+ len -= chunk;
+ offset += chunk;
+ }
+
+ /* Write termination record */
+ write_srecord(0, 4, 0, '7', NULL);
+
+ return 0;
+}
+
+struct upload_backend upload_srec = {
+ .name = "srec",
+ .helpmsg = "[filename]",
+ .minargs = 0,
+ .write = upload_srec_write,
+};
diff --git a/com32/libupload/upload_tftp.c b/com32/libupload/upload_tftp.c
new file mode 100644
index 00000000..5e73c1c5
--- /dev/null
+++ b/com32/libupload/upload_tftp.c
@@ -0,0 +1,204 @@
+/*
+ * TFTP data output backend
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <syslinux/pxe.h>
+#include <syslinux/config.h>
+#include <netinet/in.h>
+#include <sys/times.h>
+#include "upload_backend.h"
+
+enum tftp_opcode {
+ TFTP_RRQ = 1,
+ TFTP_WRQ = 2,
+ TFTP_DATA = 3,
+ TFTP_ACK = 4,
+ TFTP_ERROR = 5,
+};
+
+struct tftp_error {
+ uint16_t opcode;
+ uint16_t errcode;
+ char errmsg[0];
+} __attribute__ (( packed ));
+
+struct tftp_state {
+ uint32_t my_ip;
+ uint32_t srv_ip;
+ uint32_t srv_gw;
+ uint16_t my_port;
+ uint16_t srv_port;
+ uint16_t seq;
+};
+
+const char *tftp_string_error_message[]={
+"",
+"File not found",
+"Access Denied",
+"Disk Full",
+"Illegal Operation",
+"Unknown Transfert ID",
+"File already exists",
+"Unknown User",
+"Negociation failed",
+"Unable to resolve hostname", // not in RFC
+"Unable to connect", // not in RFC
+"No Error",
+};
+
+#define RCV_BUF 2048
+
+static int send_ack_packet(struct tftp_state *tftp,
+ const void *pkt, size_t len)
+{
+ com32sys_t ireg, oreg;
+ t_PXENV_UDP_WRITE *uw;
+ t_PXENV_UDP_READ *ur;
+ clock_t start;
+ static const clock_t timeouts[] = {
+ 2, 2, 3, 3, 4, 5, 6, 7, 9, 10, 12, 15, 18, 21, 26, 31,
+ 37, 44, 53, 64, 77, 92, 110, 132, 159, 191, 229, 0
+ };
+ const clock_t *timeout;
+ int err = -1;
+
+ uw = lmalloc(sizeof *uw + len);
+ ur = lmalloc(sizeof *ur + RCV_BUF);
+
+ memset(&ireg, 0, sizeof ireg);
+ ireg.eax.w[0] = 0x0009;
+
+ for (timeout = timeouts ; *timeout ; timeout++) {
+ memset(uw, 0, sizeof *uw);
+ memcpy(uw+1, pkt, len);
+ uw->ip = tftp->srv_ip;
+ uw->gw = tftp->srv_gw;
+ uw->src_port = tftp->my_port;
+ uw->dst_port = tftp->srv_port ? tftp->srv_port : htons(69);
+ uw->buffer_size = len;
+ uw->buffer = FAR_PTR(uw+1);
+
+ ireg.ebx.w[0] = PXENV_UDP_WRITE;
+ ireg.es = SEG(uw);
+ ireg.edi.w[0] = OFFS(uw);
+
+ __intcall(0x22, &ireg, &oreg);
+
+ start = times(NULL);
+
+ do {
+ memset(ur, 0, sizeof *ur);
+ ur->src_ip = tftp->srv_ip;
+ ur->dest_ip = tftp->my_ip;
+ ur->s_port = tftp->srv_port;
+ ur->d_port = tftp->my_port;
+ ur->buffer_size = RCV_BUF;
+ ur->buffer = FAR_PTR(ur+1);
+
+ ireg.ebx.w[0] = PXENV_UDP_READ;
+ ireg.es = SEG(ur);
+ ireg.edi.w[0] = OFFS(ur);
+ __intcall(0x22, &ireg, &oreg);
+
+ if (!(oreg.eflags.l & EFLAGS_CF) &&
+ ur->status == PXENV_STATUS_SUCCESS &&
+ tftp->srv_ip == ur->src_ip &&
+ (tftp->srv_port == 0 ||
+ tftp->srv_port == ur->s_port)) {
+ uint16_t *xb = (uint16_t *)(ur+1);
+ if (ntohs(xb[0]) == TFTP_ACK &&
+ ntohs(xb[1]) == tftp->seq) {
+ tftp->srv_port = ur->s_port;
+ err = TFTP_OK; /* All good! */
+ goto done;
+ } else if (ntohs(xb[0]) == TFTP_ERROR) {
+ struct tftp_error *te = (struct tftp_error *)(ur+1);
+ if (te->errcode == TFTP_ERR_UNKNOWN_ERROR) {
+ tftp_string_error_message[TFTP_ERR_UNKNOWN_ERROR]=strdup(te->errmsg);
+ }
+ err=-ntohs(te->errcode); // Return the associated error code
+ goto done;
+ }
+ }
+ } while ((clock_t)(times(NULL) - start) < *timeout);
+ }
+
+done:
+ lfree(ur);
+ lfree(uw);
+
+ return err;
+}
+
+static int upload_tftp_write(struct upload_backend *be)
+{
+ static uint16_t local_port = 0x4000;
+ struct tftp_state tftp;
+ char buffer[512+4+6];
+ int nlen;
+ int err=TFTP_OK;
+ const union syslinux_derivative_info *sdi =
+ syslinux_derivative_info();
+ const char *data = be->outbuf;
+ size_t len = be->zbytes;
+ size_t chunk;
+
+ tftp.my_ip = sdi->pxe.myip;
+ tftp.my_port = htons(local_port++);
+ tftp.srv_gw = ((tftp.srv_ip ^ tftp.my_ip) & sdi->pxe.ipinfo->netmask)
+ ? sdi->pxe.ipinfo->gateway : 0;
+ tftp.srv_port = 0;
+ tftp.seq = 0;
+
+ if (be->argv[1]) {
+ tftp.srv_ip = pxe_dns(be->argv[1]);
+ if (!tftp.srv_ip) {
+// printf("\nUnable to resolve hostname: %s\n", be->argv[1]);
+ return -TFTP_ERR_UNABLE_TO_RESOLVE;
+ }
+ } else {
+ tftp.srv_ip = sdi->pxe.ipinfo->serverip;
+ if (!tftp.srv_ip) {
+// printf("\nNo server IP address\n");
+ return -TFTP_ERR_UNABLE_TO_CONNECT;
+ }
+ }
+
+/* printf("server %u.%u.%u.%u... ",
+ ((uint8_t *)&tftp.srv_ip)[0],
+ ((uint8_t *)&tftp.srv_ip)[1],
+ ((uint8_t *)&tftp.srv_ip)[2],
+ ((uint8_t *)&tftp.srv_ip)[3]);*/
+
+ buffer[0] = 0;
+ buffer[1] = TFTP_WRQ;
+ nlen = strlcpy(buffer+2, be->argv[0], 512);
+ memcpy(buffer+3+nlen, "octet", 6);
+
+ if ((err=send_ack_packet(&tftp, buffer, 2+nlen+1+6))!=TFTP_OK)
+ return err;
+
+ do {
+ chunk = len >= 512 ? 512 : len;
+
+ buffer[1] = TFTP_DATA;
+ *((uint16_t *)(buffer+2)) = htons(++tftp.seq);
+ memcpy(buffer+4, data, chunk);
+ data += chunk;
+ len -= chunk;
+
+ if ((err=send_ack_packet(&tftp, buffer, chunk+4))!=TFTP_OK)
+ return err;
+ } while (chunk == 512);
+
+ return TFTP_OK;
+}
+
+struct upload_backend upload_tftp = {
+ .name = "tftp",
+ .helpmsg = "filename [tftp_server]",
+ .minargs = 1,
+ .write = upload_tftp_write,
+};
diff --git a/com32/libupload/upload_ymodem.c b/com32/libupload/upload_ymodem.c
new file mode 100644
index 00000000..c42327d8
--- /dev/null
+++ b/com32/libupload/upload_ymodem.c
@@ -0,0 +1,175 @@
+/*
+ * Ymodem send routine. Only supports 1K blocks and CRC mode.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include "upload_backend.h"
+#include "serial.h"
+
+enum {
+ SOH = 0x01,
+ STX = 0x02,
+ EOT = 0x04,
+ ACK = 0x06,
+ NAK = 0x15,
+ CAN = 0x18,
+};
+
+struct ymodem_state {
+ struct serial_if serial;
+ unsigned int seq, blocks;
+};
+
+/*
+ * Append a CRC16 to a block
+ */
+static void add_crc16(uint8_t * blk, int len)
+{
+ static const uint16_t crctab[256] = {
+ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
+ 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
+ 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
+ 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
+ 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
+ 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
+ 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
+ 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
+ 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
+ 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
+ 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
+ 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
+ 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
+ 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
+ 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
+ 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
+ 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
+ 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
+ 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
+ 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
+ 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
+ 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
+ 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
+ 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
+ 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
+ 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
+ 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
+ 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
+ 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
+ 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
+ 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
+ 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
+ };
+ uint16_t crc = 0;
+
+ while (len--)
+ crc = crctab[(crc >> 8) ^ *blk++] ^ crc << 8;
+
+ *blk++ = crc >> 8;
+ *blk = crc;
+}
+
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk,
+ size_t bytes);
+
+static void send_ack_blk(struct ymodem_state *ym, uint8_t *blk)
+{
+ printf("Sending block %u/%u...\r", ym->seq, ym->blocks);
+
+ blk[0] = STX;
+ blk[1] = ym->seq++;
+ blk[2] = ~blk[1];
+ add_crc16(blk+3, 1024);
+
+ send_ack(ym, blk, 1024+5);
+}
+
+static void send_ack(struct ymodem_state *ym, const uint8_t *blk, size_t bytes)
+{
+ uint8_t ack_buf;
+
+ do {
+ serial_write(&ym->serial, blk, bytes);
+
+ do {
+ serial_read(&ym->serial, &ack_buf, 1);
+ } while (ack_buf != ACK && ack_buf != NAK);
+ } while (ack_buf == NAK);
+}
+
+static int upload_ymodem_write(struct upload_backend *be)
+{
+ static const uint8_t eot_buf = EOT;
+ uint8_t ack_buf;
+ uint8_t blk_buf[1024 + 5];
+ struct ymodem_state ym;
+ const char *buf;
+ size_t len, chunk;
+ const char ymodem_banner[] = "Now begin Ymodem download...\r\n";
+
+ buf = be->outbuf;
+ len = be->zbytes;
+
+ putchar('\n');
+
+ ym.seq = 0;
+ ym.blocks = (len+1023)/1024;
+
+ /* Initialize serial port */
+ if (serial_init(&ym.serial, &be->argv[1]))
+ return -1;
+
+ /* Write banner */
+ printf("Writing banner...\n");
+ serial_write(&ym.serial, ymodem_banner, sizeof ymodem_banner-1);
+
+ /* Wait for initial handshake */
+ printf("Waiting for handshake...\n");
+ do {
+ serial_read(&ym.serial, &ack_buf, 1);
+ } while (ack_buf != 'C');
+
+ /* Send filename block */
+ memset(blk_buf, 0, sizeof blk_buf);
+ snprintf((char *)blk_buf+3, 1024, "%s%c%zu 0%o 0644",
+ be->argv[0], 0, be->zbytes, be->now);
+ send_ack_blk(&ym, blk_buf);
+
+ while (len) {
+ chunk = len < 1024 ? len : 1024;
+
+ memcpy(blk_buf+3, buf, chunk);
+ if (chunk < 1024)
+ memset(blk_buf+3+chunk, 0x1a, 1024-chunk);
+
+ send_ack_blk(&ym, blk_buf);
+ buf += chunk;
+ len -= chunk;
+ }
+
+ printf("\nSending EOT...\n");
+ send_ack(&ym, &eot_buf, 1);
+
+ printf("Waiting for handshake...\n");
+ do {
+ serial_read(&ym.serial, &ack_buf, 1);
+ } while (ack_buf != 'C');
+ ym.seq = 0;
+
+ printf("Sending batch termination block...\n");
+ memset(blk_buf+3, 0, 1024);
+ send_ack_blk(&ym, blk_buf);
+
+ printf("Cleaning up... \n");
+ serial_cleanup(&ym.serial);
+
+ return 0;
+}
+
+struct upload_backend upload_ymodem = {
+ .name = "ymodem",
+ .helpmsg = "filename [port [speed]]",
+ .minargs = 1,
+ .write = upload_ymodem_write,
+};
diff --git a/com32/libupload/ymodem.txt b/com32/libupload/ymodem.txt
new file mode 100644
index 00000000..2264ff78
--- /dev/null
+++ b/com32/libupload/ymodem.txt
@@ -0,0 +1,2108 @@
+
+
+
+ - 1 -
+
+
+
+ XMODEM/YMODEM PROTOCOL REFERENCE
+ A compendium of documents describing the
+
+ XMODEM and YMODEM
+
+ File Transfer Protocols
+
+
+
+
+ This document was formatted 10-14-88.
+
+
+
+
+
+
+
+ Edited by Chuck Forsberg
+
+
+
+
+
+
+
+
+
+ This file may be redistributed without restriction
+ provided the text is not altered.
+
+ Please distribute as widely as possible.
+
+ Questions to Chuck Forsberg
+
+
+
+
+
+ Omen Technology Inc
+ The High Reliability Software
+ 17505-V Sauvie Island Road
+ Portland Oregon 97231
+ VOICE: 503-621-3406 :VOICE
+ TeleGodzilla BBS: 503-621-3746 Speed 19200(Telebit PEP),2400,1200,300
+ CompuServe: 70007,2304
+ GEnie: CAF
+ UUCP: ...!tektronix!reed!omen!caf
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 2 -
+
+
+
+ 1. TOWER OF BABEL
+
+ A "YMODEM Tower of Babel" has descended on the microcomputing community
+ bringing with it confusion, frustration, bloated phone bills, and wasted
+ man hours. Sadly, I (Chuck Forsberg) am partly to blame for this mess.
+
+ As author of the early 1980s batch and 1k XMODEM extensions, I assumed
+ readers of earlier versions of this document would implement as much of
+ the YMODEM protocol as their programming skills and computing environments
+ would permit. This proved a rather naive assumption as programmers
+ motivated by competitive pressure implemented as little of YMODEM as
+ possible. Some have taken whatever parts of YMODEM that appealed to them,
+ applied them to MODEM7 Batch, Telink, XMODEM or whatever, and called the
+ result YMODEM.
+
+ Jeff Garbers (Crosstalk package development director) said it all: "With
+ protocols in the public domain, anyone who wants to dink around with them
+ can go ahead." [1]
+
+ Documents containing altered examples derived from YMODEM.DOC have added
+ to the confusion. In one instance, some self styled rewriter of history
+ altered the heading in YMODEM.DOC's Figure 1 from "1024 byte Packets" to
+ "YMODEM/CRC File Transfer Protocol". None of the XMODEM and YMODEM
+ examples shown in that document were correct.
+
+ To put an end to this confusion, we must make "perfectly clear" what
+ YMODEM stands for, as Ward Christensen defined it in his 1985 coining of
+ the term.
+
+ To the majority of you who read, understood, and respected Ward's
+ definition of YMODEM, I apologize for the inconvenience.
+
+ 1.1 Definitions
+
+ ARC ARC is a program that compresses one or more files into an archive
+ and extracts files from such archives.
+
+ XMODEM refers to the file transfer etiquette introduced by Ward
+ Christensen's 1977 MODEM.ASM program. The name XMODEM comes from
+ Keith Petersen's XMODEM.ASM program, an adaptation of MODEM.ASM
+ for Remote CP/M (RCPM) systems. It's also called the MODEM or
+ MODEM2 protocol. Some who are unaware of MODEM7's unusual batch
+ file mode call it MODEM7. Other aliases include "CP/M Users'
+ Group" and "TERM II FTP 3". The name XMODEM caught on partly
+ because it is distinctive and partly because of media interest in
+
+
+ __________
+
+ 1. Page C/12, PC-WEEK July 12, 1987
+
+
+
+
+ Chapter 1
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 3
+
+
+
+ bulletin board and RCPM systems where it was accessed with an
+ "XMODEM" command. This protocol is supported by every serious
+ communications program because of its universality, simplicity,
+ and reasonable performance.
+
+ XMODEM/CRC replaces XMODEM's 1 byte checksum with a two byte Cyclical
+ Redundancy Check (CRC-16), giving modern error detection
+ protection.
+
+ XMODEM-1k Refers to the XMODEM/CRC protocol with 1024 byte data blocks.
+
+ YMODEM Refers to the XMODEM/CRC (optional 1k blocks) protocol with batch
+ transmission as described below. In a nutshell, YMODEM means
+ BATCH.
+
+ YMODEM-g Refers to the streaming YMODEM variation described below.
+
+ True YMODEM(TM) In an attempt to sort out the YMODEM Tower of Babel, Omen
+ Technology has trademarked the term True YMODEM(TM) to represent
+ the complete YMODEM protocol described in this document, including
+ pathname, length, and modification date transmitted in block 0.
+ Please contact Omen Technology about certifying programs for True
+ YMODEM(TM) compliance.
+
+ ZMODEM uses familiar XMODEM/CRC and YMODEM technology in a new protocol
+ that provides reliability, throughput, file management, and user
+ amenities appropriate to contemporary data communications.
+
+ ZOO Like ARC, ZOO is a program that compresses one or more files into
+ a "zoo archive". ZOO supports many different operating systems
+ including Unix and VMS.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 1
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 4
+
+
+
+ 2. YMODEM MINIMUM REQUIREMENTS
+
+ All programs claiming to support YMODEM must meet the following minimum
+ requirements:
+
+ + The sending program shall send the pathname (file name) in block 0.
+
+ + The pathname shall be a null terminated ASCII string as described
+ below.
+
+ For those who are too lazy to read the entire document:
+
+ + Unless specifically requested, only the file name portion is
+ sent.
+
+ + No drive letter is sent.
+
+ + Systems that do not distinguish between upper and lower case
+ letters in filenames shall send the pathname in lower case only.
+
+
+ + The receiving program shall use this pathname for the received file
+ name, unless explicitly overridden.
+
+ + When the receiving program receives this block and successfully
+ opened the output file, it shall acknowledge this block with an ACK
+ character and then proceed with a normal XMODEM file transfer
+ beginning with a "C" or NAK tranmsitted by the receiver.
+
+ + The sending program shall use CRC-16 in response to a "C" pathname
+ nak, otherwise use 8 bit checksum.
+
+ + The receiving program must accept any mixture of 128 and 1024 byte
+ blocks within each file it receives. Sending programs may
+ arbitrarily switch between 1024 and 128 byte blocks.
+
+ + The sending program must not change the length of an unacknowledged
+ block.
+
+ + At the end of each file, the sending program shall send EOT up to ten
+ times until it receives an ACK character. (This is part of the
+ XMODEM spec.)
+
+ + The end of a transfer session shall be signified by a null (empty)
+ pathname, this pathname block shall be acknowledged the same as other
+ pathname blocks.
+
+ Programs not meeting all of these requirements are not YMODEM compatible,
+ and shall not be described as supporting YMODEM.
+
+ Meeting these MINIMUM requirements does not guarantee reliable file
+
+
+
+ Chapter 2
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 5
+
+
+
+ transfers under stress. Particular attention is called to XMODEM's single
+ character supervisory messages that are easily corrupted by transmission
+ errors.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 2
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 6
+
+
+
+ 3. WHY YMODEM?
+
+ Since its development half a decade ago, the Ward Christensen modem
+ protocol has enabled a wide variety of computer systems to interchange
+ data. There is hardly a communications program that doesn't at least
+ claim to support this protocol.
+
+ Advances in computing, modems and networking have revealed a number of
+ weaknesses in the original protocol:
+
+ + The short block length caused throughput to suffer when used with
+ timesharing systems, packet switched networks, satellite circuits,
+ and buffered (error correcting) modems.
+
+ + The 8 bit arithmetic checksum and other aspects allowed line
+ impairments to interfere with dependable, accurate transfers.
+
+ + Only one file could be sent per command. The file name had to be
+ given twice, first to the sending program and then again to the
+ receiving program.
+
+ + The transmitted file could accumulate as many as 127 extraneous
+ bytes.
+
+ + The modification date of the file was lost.
+
+ A number of other protocols have been developed over the years, but none
+ have displaced XMODEM to date:
+
+ + Lack of public domain documentation and example programs have kept
+ proprietary protocols such as Blast, Relay, and others tightly bound
+ to the fortunes of their suppliers.
+
+ + Complexity discourages the widespread application of BISYNC, SDLC,
+ HDLC, X.25, and X.PC protocols.
+
+ + Performance compromises and complexity have limited the popularity of
+ the Kermit protocol, which was developed to allow file transfers in
+ environments hostile to XMODEM.
+
+ The XMODEM protocol extensions and YMODEM Batch address some of these
+ weaknesses while maintaining most of XMODEM's simplicity.
+
+ YMODEM is supported by the public domain programs YAM (CP/M),
+ YAM(CP/M-86), YAM(CCPM-86), IMP (CP/M), KMD (CP/M), rz/sz (Unix, Xenix,
+ VMS, Berkeley Unix, Venix, Xenix, Coherent, IDRIS, Regulus). Commercial
+ implementations include MIRROR, and Professional-YAM.[1] Communications
+
+
+
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 7
+
+
+
+ programs supporting these extensions have been in use since 1981.
+
+ The 1k block length (XMODEM-1k) described below may be used in conjunction
+ with YMODEM Batch Protocol, or with single file transfers identical to the
+ XMODEM/CRC protocol except for minimal changes to support 1k blocks.
+
+ Another extension is the YMODEM-g protocol. YMODEM-g provides batch
+ transfers with maximum throughput when used with end to end error
+ correcting media, such as X.PC and error correcting modems, including 9600
+ bps units by TeleBit, U.S.Robotics, Hayes, Electronic Vaults, Data Race,
+ and others.
+
+ To complete this tome, edited versions of Ward Christensen's original
+ protocol document and John Byrns's CRC-16 document are included for
+ reference.
+
+ References to the MODEM or MODEM7 protocol have been changed to XMODEM to
+ accommodate the vernacular. In Australia, it is properly called the
+ Christensen Protocol.
+
+
+ 3.1 Some Messages from the Pioneer
+
+ #: 130940 S0/Communications 25-Apr-85 18:38:47
+ Sb: my protocol
+ Fm: Ward Christensen 76703,302 [2]
+ To: all
+
+ Be aware the article[3] DID quote me correctly in terms of the phrases
+ like "not robust", etc.
+
+ It was a quick hack I threw together, very unplanned (like everything I
+ do), to satisfy a personal need to communicate with "some other" people.
+
+ ONLY the fact that it was done in 8/77, and that I put it in the public
+ domain immediately, made it become the standard that it is.
+
+
+
+
+
+
+
+ __________________________________________________________________________
+
+ 1. Available for IBM PC,XT,AT, Unix and Xenix
+
+ 2. Edited for typesetting appearance
+
+ 3. Infoworld April 29 p. 16
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 8
+
+
+
+ I think its time for me to
+
+ (1) document it; (people call me and say "my product is going to include
+ it - what can I 'reference'", or "I'm writing a paper on it, what do I put
+ in the bibliography") and
+
+ (2) propose an "incremental extension" to it, which might take "exactly"
+ the form of Chuck Forsberg's YAM protocol. He wrote YAM in C for CP/M and
+ put it in the public domain, and wrote a batch protocol for Unix[4] called
+ rb and sb (receive batch, send batch), which was basically XMODEM with
+ (a) a record 0 containing filename date time and size
+ (b) a 1K block size option
+ (c) CRC-16.
+
+ He did some clever programming to detect false ACK or EOT, but basically
+ left them the same.
+
+ People who suggest I make SIGNIFICANT changes to the protocol, such as
+ "full duplex", "multiple outstanding blocks", "multiple destinations", etc
+ etc don't understand that the incredible simplicity of the protocol is one
+ of the reasons it survived to this day in as many machines and programs as
+ it may be found in!
+
+ Consider the PC-NET group back in '77 or so - documenting to beat the band
+ - THEY had a protocol, but it was "extremely complex", because it tried to
+ be "all things to all people" - i.e. send binary files on a 7-bit system,
+ etc. I was not that "benevolent". I (emphasize > I < ) had an 8-bit UART,
+ so "my protocol was an 8-bit protocol", and I would just say "sorry" to
+ people who were held back by 7-bit limitations. ...
+
+ Block size: Chuck Forsberg created an extension of my protocol, called
+ YAM, which is also supported via his public domain programs for UNIX
+ called rb and sb - receive batch and send batch. They cleverly send a
+ "block 0" which contains the filename, date, time, and size.
+ Unfortunately, its UNIX style, and is a bit weird[5] - octal numbers, etc.
+ BUT, it is a nice way to overcome the kludgy "echo the chars of the name"
+ introduced with MODEM7. Further, chuck uses CRC-16 and optional 1K
+ blocks. Thus the record 0, 1K, and CRC, make it a "pretty slick new
+ protocol" which is not significantly different from my own.
+
+ Also, there is a catchy name - YMODEM. That means to some that it is the
+ "next thing after XMODEM", and to others that it is the Y(am)MODEM
+
+
+ __________
+
+ 4. VAX/VMS versions of these programs are also available.
+
+ 5. The file length, time, and file mode are optional. The pathname and
+ file length may be sent alone if desired.
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 9
+
+
+
+ protocol. I don't want to emphasize that too much - out of fear that
+ other mfgrs might think it is a "competitive" protocol, rather than an
+ "unaffiliated" protocol. Chuck is currently selling a much-enhanced
+ version of his CP/M-80 C program YAM, calling it Professional Yam, and its
+ for the PC - I'm using it right now. VERY slick! 32K capture buffer,
+ script, scrolling, previously captured text search, plus built-in commands
+ for just about everything - directory (sorted every which way), XMODEM,
+ YMODEM, KERMIT, and ASCII file upload/download, etc. You can program it
+ to "behave" with most any system - for example when trying a number for
+ CIS it detects the "busy" string back from the modem and substitutes a
+ diff phone # into the dialing string and branches back to try it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 3
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 10
+
+
+
+ 4. XMODEM PROTOCOL ENHANCEMENTS
+
+ This chapter discusses the protocol extensions to Ward Christensen's 1982
+ XMODEM protocol description document.
+
+ The original document recommends the user be asked whether to continue
+ trying or abort after 10 retries. Most programs no longer ask the
+ operator whether he wishes to keep retrying. Virtually all correctable
+ errors are corrected within the first few retransmissions. If the line is
+ so bad that ten attempts are insufficient, there is a significant danger
+ of undetected errors. If the connection is that bad, it's better to
+ redial for a better connection, or mail a floppy disk.
+
+
+ 4.1 Graceful Abort
+
+ The YAM and Professional-YAM X/YMODEM routines recognize a sequence of two
+ consecutive CAN (Hex 18) characters without modem errors (overrun,
+ framing, etc.) as a transfer abort command. This sequence is recognized
+ when is waiting for the beginning of a block or for an acknowledgement to
+ a block that has been sent. The check for two consecutive CAN characters
+ reduces the number of transfers aborted by line hits. YAM sends eight CAN
+ characters when it aborts an XMODEM, YMODEM, or ZMODEM protocol file
+ transfer. Pro-YAM then sends eight backspaces to delete the CAN
+ characters from the remote's keyboard input buffer, in case the remote had
+ already aborted the transfer and was awaiting a keyboarded command.
+
+
+ 4.2 CRC-16 Option
+
+ The XMODEM protocol uses an optional two character CRC-16 instead of the
+ one character arithmetic checksum used by the original protocol and by
+ most commercial implementations. CRC-16 guarantees detection of all
+ single and double bit errors, all errors with an odd number of error
+ bits, all burst errors of length 16 or less, 99.9969% of all 17-bit error
+ bursts, and 99.9984 per cent of all possible longer error bursts. By
+ contrast, a double bit error, or a burst error of 9 bits or more can sneak
+ past the XMODEM protocol arithmetic checksum.
+
+ The XMODEM/CRC protocol is similar to the XMODEM protocol, except that the
+ receiver specifies CRC-16 by sending C (Hex 43) instead of NAK when
+ requesting the FIRST block. A two byte CRC is sent in place of the one
+ byte arithmetic checksum.
+
+ YAM's c option to the r command enables CRC-16 in single file reception,
+ corresponding to the original implementation in the MODEM7 series
+ programs. This remains the default because many commercial communications
+ programs and bulletin board systems still do not support CRC-16,
+ especially those written in Basic or Pascal.
+
+ XMODEM protocol with CRC is accurate provided both sender and receiver
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 11
+
+
+
+ both report a successful transmission. The protocol is robust in the
+ presence of characters lost by buffer overloading on timesharing systems.
+
+ The single character ACK/NAK responses generated by the receiving program
+ adapt well to split speed modems, where the reverse channel is limited to
+ ten per cent or less of the main channel's speed.
+
+ XMODEM and YMODEM are half duplex protocols which do not attempt to
+ transmit information and control signals in both directions at the same
+ time. This avoids buffer overrun problems that have been reported by
+ users attempting to exploit full duplex asynchronous file transfer
+ protocols such as Blast.
+
+ Professional-YAM adds several proprietary logic enhancements to XMODEM's
+ error detection and recovery. These compatible enhancements eliminate
+ most of the bad file transfers other programs make when using the XMODEM
+ protocol under less than ideal conditions.
+
+
+ 4.3 XMODEM-1k 1024 Byte Block
+
+ Disappointing throughput downloading from Unix with YMODEM[1] lead to the
+ development of 1024 byte blocks in 1982. 1024 byte blocks reduce the
+ effect of delays from timesharing systems, modems, and packet switched
+ networks on throughput by 87.5 per cent in addition to decreasing XMODEM's
+ 3 per cent overhead (block number, CRC, etc.).
+
+ Some environments cannot accept 1024 byte bursts, including some networks
+ and minicomputer ports. The longer block length should be an option.
+
+ The choice to use 1024 byte blocks is expressed to the sending program on
+ its command line or selection menu.[2] 1024 byte blocks improve throughput
+ in many applications.
+
+ An STX (02) replaces the SOH (01) at the beginning of the transmitted
+ block to notify the receiver of the longer block length. The transmitted
+ block contains 1024 bytes of data. The receiver should be able to accept
+ any mixture of 128 and 1024 byte blocks. The block number (in the second
+ and third bytes of the block) is incremented by one for each block
+ regardless of the block length.
+
+ The sender must not change between 128 and 1024 byte block lengths if it
+ has not received a valid ACK for the current block. Failure to observe
+
+
+ __________
+
+ 1. The name hadn't been coined yet, but the protocol was the same.
+
+ 2. See "KMD/IMP Exceptions to YMODEM" below.
+
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 12
+
+
+
+ this restriction allows transmission errors to pass undetected.
+
+ If 1024 byte blocks are being used, it is possible for a file to "grow" up
+ to the next multiple of 1024 bytes. This does not waste disk space if the
+ allocation granularity is 1k or greater. With YMODEM batch transmission,
+ the optional file length transmitted in the file name block allows the
+ receiver to discard the padding, preserving the exact file length and
+ contents.
+
+ 1024 byte blocks may be used with batch file transmission or with single
+ file transmission. CRC-16 should be used with the k option to preserve
+ data integrity over phone lines. If a program wishes to enforce this
+ recommendation, it should cancel the transfer, then issue an informative
+ diagnostic message if the receiver requests checksum instead of CRC-16.
+
+ Under no circumstances may a sending program use CRC-16 unless the
+ receiver commands CRC-16.
+
+ Figure 1. XMODEM-1k Blocks
+
+ SENDER RECEIVER
+ "sx -k foo.bar"
+ "foo.bar open x.x minutes"
+ C
+ STX 01 FE Data[1024] CRC CRC
+ ACK
+ STX 02 FD Data[1024] CRC CRC
+ ACK
+ STX 03 FC Data[1000] CPMEOF[24] CRC CRC
+ ACK
+ EOT
+ ACK
+
+ Figure 2. Mixed 1024 and 128 byte Blocks
+
+ SENDER RECEIVER
+ "sx -k foo.bar"
+ "foo.bar open x.x minutes"
+ C
+ STX 01 FE Data[1024] CRC CRC
+ ACK
+ STX 02 FD Data[1024] CRC CRC
+ ACK
+ SOH 03 FC Data[128] CRC CRC
+ ACK
+ SOH 04 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ ACK
+
+
+
+
+
+ Chapter 4 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 13
+
+
+
+ 5. YMODEM Batch File Transmission
+
+ The YMODEM Batch protocol is an extension to the XMODEM/CRC protocol that
+ allows 0 or more files to be transmitted with a single command. (Zero
+ files may be sent if none of the requested files is accessible.) The
+ design approach of the YMODEM Batch protocol is to use the normal routines
+ for sending and receiving XMODEM blocks in a layered fashion similar to
+ packet switching methods.
+
+ Why was it necessary to design a new batch protocol when one already
+ existed in MODEM7?[1] The batch file mode used by MODEM7 is unsuitable
+ because it does not permit full pathnames, file length, file date, or
+ other attribute information to be transmitted. Such a restrictive design,
+ hastily implemented with only CP/M in mind, would not have permitted
+ extensions to current areas of personal computing such as Unix, DOS, and
+ object oriented systems. In addition, the MODEM7 batch file mode is
+ somewhat susceptible to transmission impairments.
+
+ As in the case of single a file transfer, the receiver initiates batch
+ file transmission by sending a "C" character (for CRC-16).
+
+ The sender opens the first file and sends block number 0 with the
+ following information.[2]
+
+ Only the pathname (file name) part is required for batch transfers.
+
+ To maintain upwards compatibility, all unused bytes in block 0 must be set
+ to null.
+
+ Pathname The pathname (conventionally, the file name) is sent as a null
+ terminated ASCII string. This is the filename format used by the
+ handle oriented MSDOS(TM) functions and C library fopen functions.
+ An assembly language example follows:
+ DB 'foo.bar',0
+ No spaces are included in the pathname. Normally only the file name
+ stem (no directory prefix) is transmitted unless the sender has
+ selected YAM's f option to send the full pathname. The source drive
+ (A:, B:, etc.) is not sent.
+
+ Filename Considerations:
+
+
+
+ __________
+
+ 1. The MODEM7 batch protocol transmitted CP/M FCB bytes f1...f8 and
+ t1...t3 one character at a time. The receiver echoed these bytes as
+ received, one at a time.
+
+ 2. Only the data part of the block is described here.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 14
+
+
+
+ + File names are forced to lower case unless the sending system
+ supports upper/lower case file names. This is a convenience for
+ users of systems (such as Unix) which store filenames in upper
+ and lower case.
+
+ + The receiver should accommodate file names in lower and upper
+ case.
+
+ + When transmitting files between different operating systems,
+ file names must be acceptable to both the sender and receiving
+ operating systems.
+
+ If directories are included, they are delimited by /; i.e.,
+ "subdir/foo" is acceptable, "subdir\foo" is not.
+
+ Length The file length and each of the succeeding fields are optional.[3]
+ The length field is stored in the block as a decimal string counting
+ the number of data bytes in the file. The file length does not
+ include any CPMEOF (^Z) or other garbage characters used to pad the
+ last block.
+
+ If the file being transmitted is growing during transmission, the
+ length field should be set to at least the final expected file
+ length, or not sent.
+
+ The receiver stores the specified number of characters, discarding
+ any padding added by the sender to fill up the last block.
+
+ Modification Date The mod date is optional, and the filename and length
+ may be sent without requiring the mod date to be sent.
+
+ Iff the modification date is sent, a single space separates the
+ modification date from the file length.
+
+ The mod date is sent as an octal number giving the time the contents
+ of the file were last changed, measured in seconds from Jan 1 1970
+ Universal Coordinated Time (GMT). A date of 0 implies the
+ modification date is unknown and should be left as the date the file
+ is received.
+
+ This standard format was chosen to eliminate ambiguities arising from
+ transfers between different time zones.
+
+
+
+
+
+ __________
+
+ 3. Fields may not be skipped.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 15
+
+
+
+ Mode Iff the file mode is sent, a single space separates the file mode
+ from the modification date. The file mode is stored as an octal
+ string. Unless the file originated from a Unix system, the file mode
+ is set to 0. rb(1) checks the file mode for the 0x8000 bit which
+ indicates a Unix type regular file. Files with the 0x8000 bit set
+ are assumed to have been sent from another Unix (or similar) system
+ which uses the same file conventions. Such files are not translated
+ in any way.
+
+
+ Serial Number Iff the serial number is sent, a single space separates the
+ serial number from the file mode. The serial number of the
+ transmitting program is stored as an octal string. Programs which do
+ not have a serial number should omit this field, or set it to 0. The
+ receiver's use of this field is optional.
+
+
+ Other Fields YMODEM was designed to allow additional header fields to be
+ added as above without creating compatibility problems with older
+ YMODEM programs. Please contact Omen Technology if other fields are
+ needed for special application requirements.
+
+ The rest of the block is set to nulls. This is essential to preserve
+ upward compatibility.[4]
+
+ If the filename block is received with a CRC or other error, a
+ retransmission is requested. After the filename block has been received,
+ it is ACK'ed if the write open is successful. If the file cannot be
+ opened for writing, the receiver cancels the transfer with CAN characters
+ as described above.
+
+ The receiver then initiates transfer of the file contents with a "C"
+ character, according to the standard XMODEM/CRC protocol.
+
+ After the file contents and XMODEM EOT have been transmitted and
+ acknowledged, the receiver again asks for the next pathname.
+
+ Transmission of a null pathname terminates batch file transmission.
+
+ Note that transmission of no files is not necessarily an error. This is
+ possible if none of the files requested of the sender could be opened for
+ reading.
+
+
+
+ __________
+
+ 4. If, perchance, this information extends beyond 128 bytes (possible
+ with Unix 4.2 BSD extended file names), the block should be sent as a
+ 1k block as described above.
+
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 16
+
+
+
+ Most YMODEM receivers request CRC-16 by default.
+
+ The Unix programs sz(1) and rz(1) included in the source code file
+ RZSZ.ZOO should answer other questions about YMODEM batch protocol.
+
+ Figure 3. YMODEM Batch Transmission Session (1 file)
+
+ SENDER RECEIVER
+ "sb foo.*<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FE Data[128] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 7. YMODEM Header Information and Features
+
+ _____________________________________________________________
+ | Program | Length | Date | Mode | S/N | 1k-Blk | YMODEM-g |
+ |___________|________|______|______|_____|________|__________|
+ |Unix rz/sz | yes | yes | yes | no | yes | sb only |
+ |___________|________|______|______|_____|________|__________|
+ |VMS rb/sb | yes | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+ |Pro-YAM | yes | yes | no | yes | yes | yes |
+ |___________|________|______|______|_____|________|__________|
+ |CP/M YAM | no | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+ |KMD/IMP | ? | no | no | no | yes | no |
+ |___________|________|______|______|_____|________|__________|
+
+ 5.1 KMD/IMP Exceptions to YMODEM
+
+ KMD and IMP use a "CK" character sequence emitted by the receiver to
+ trigger the use of 1024 byte blocks as an alternative to specifying this
+ option to the sending program. This two character sequence generally
+ works well on single process micros in direct communication, provided the
+ programs rigorously adhere to all the XMODEM recommendations included
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 17
+
+
+
+ Figure 4. YMODEM Batch Transmission Session (2 files)
+
+ SENDER RECEIVER
+ "sb foo.c baz.c<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FE Data[128] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF baz.c NUL[123] CRC CRC
+ ACK
+ C
+ SOH 01 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 5. YMODEM Batch Transmission Session-1k Blocks
+
+ SENDER RECEIVER
+ "sb -k foo.*<CR>"
+ "sending in batch mode etc."
+ C (command:rb)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ ACK
+ C
+ STX 01 FD Data[1024] CRC CRC
+ ACK
+ SOH 02 FC Data[128] CRC CRC
+ ACK
+ SOH 03 FB Data[100] CPMEOF[28] CRC CRC
+ ACK
+ EOT
+ NAK
+ EOT
+
+
+
+ Chapter 5 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 18
+
+
+
+ ACK
+ C
+ SOH 00 FF NUL[128] CRC CRC
+ ACK
+
+ Figure 6. YMODEM Filename block transmitted by sz
+
+ -rw-r--r-- 6347 Jun 17 1984 20:34 bbcsched.txt
+
+ 00 0100FF62 62637363 6865642E 74787400 |...bbcsched.txt.|
+ 10 36333437 20333331 34373432 35313320 |6347 3314742513 |
+ 20 31303036 34340000 00000000 00000000 |100644..........|
+ 30 00000000 00000000 00000000 00000000
+ 40 00000000 00000000 00000000 00000000
+ 50 00000000 00000000 00000000 00000000
+ 60 00000000 00000000 00000000 00000000
+ 70 00000000 00000000 00000000 00000000
+ 80 000000CA 56
+
+ herein. Programs with marginal XMODEM implementations do not fare so
+ well. Timesharing systems and packet switched networks can separate the
+ successive characters, rendering this method unreliable.
+
+ Sending programs may detect the CK sequence if the operating enviornment
+ does not preclude reliable implementation.
+
+ Instead of the standard YMODEM file length in decimal, KMD and IMP
+ transmit the CP/M record count in the last two bytes of the header block.
+
+
+ 6. YMODEM-g File Transmission
+
+ Developing technology is providing phone line data transmission at ever
+ higher speeds using very specialized techniques. These high speed modems,
+ as well as session protocols such as X.PC, provide high speed, nearly
+ error free communications at the expense of considerably increased delay
+ time.
+
+ This delay time is moderate compared to human interactions, but it
+ cripples the throughput of most error correcting protocols.
+
+ The g option to YMODEM has proven effective under these circumstances.
+ The g option is driven by the receiver, which initiates the batch transfer
+ by transmitting a G instead of C. When the sender recognizes the G, it
+ bypasses the usual wait for an ACK to each transmitted block, sending
+ succeeding blocks at full speed, subject to XOFF/XON or other flow control
+ exerted by the medium.
+
+ The sender expects an inital G to initiate the transmission of a
+ particular file, and also expects an ACK on the EOT sent at the end of
+ each file. This synchronization allows the receiver time to open and
+
+
+
+ Chapter 6 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 19
+
+
+
+ close files as necessary.
+
+ If an error is detected in a YMODEM-g transfer, the receiver aborts the
+ transfer with the multiple CAN abort sequence. The ZMODEM protocol should
+ be used in applications that require both streaming throughput and error
+ recovery.
+
+ Figure 8. YMODEM-g Transmission Session
+
+ SENDER RECEIVER
+ "sb foo.*<CR>"
+ "sending in batch mode etc..."
+ G (command:rb -g)
+ SOH 00 FF foo.c NUL[123] CRC CRC
+ G
+ SOH 01 FE Data[128] CRC CRC
+ STX 02 FD Data[1024] CRC CRC
+ SOH 03 FC Data[128] CRC CRC
+ SOH 04 FB Data[100] CPMEOF[28] CRC CRC
+ EOT
+ ACK
+ G
+ SOH 00 FF NUL[128] CRC CRC
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 6 XMODEM Protocol Enhancements
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 20
+
+
+
+ 7. XMODEM PROTOCOL OVERVIEW
+
+ 8/9/82 by Ward Christensen.
+
+ I will maintain a master copy of this. Please pass on changes or
+ suggestions via CBBS/Chicago at (312) 545-8086, CBBS/CPMUG (312) 849-1132
+ or by voice at (312) 849-6279.
+
+ 7.1 Definitions
+
+ <soh> 01H
+ <eot> 04H
+ <ack> 06H
+ <nak> 15H
+ <can> 18H
+ <C> 43H
+
+
+ 7.2 Transmission Medium Level Protocol
+
+ Asynchronous, 8 data bits, no parity, one stop bit.
+
+ The protocol imposes no restrictions on the contents of the data being
+ transmitted. No control characters are looked for in the 128-byte data
+ messages. Absolutely any kind of data may be sent - binary, ASCII, etc.
+ The protocol has not formally been adopted to a 7-bit environment for the
+ transmission of ASCII-only (or unpacked-hex) data , although it could be
+ simply by having both ends agree to AND the protocol-dependent data with
+ 7F hex before validating it. I specifically am referring to the checksum,
+ and the block numbers and their ones- complement.
+
+ Those wishing to maintain compatibility of the CP/M file structure, i.e.
+ to allow modemming ASCII files to or from CP/M systems should follow this
+ data format:
+
+ + ASCII tabs used (09H); tabs set every 8.
+
+ + Lines terminated by CR/LF (0DH 0AH)
+
+ + End-of-file indicated by ^Z, 1AH. (one or more)
+
+ + Data is variable length, i.e. should be considered a continuous
+ stream of data bytes, broken into 128-byte chunks purely for the
+ purpose of transmission.
+
+ + A CP/M "peculiarity": If the data ends exactly on a 128-byte
+ boundary, i.e. CR in 127, and LF in 128, a subsequent sector
+ containing the ^Z EOF character(s) is optional, but is preferred.
+ Some utilities or user programs still do not handle EOF without ^Zs.
+
+
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 21
+
+
+
+ + The last block sent is no different from others, i.e. there is no
+ "short block".
+ Figure 9. XMODEM Message Block Level Protocol
+
+ Each block of the transfer looks like:
+ <SOH><blk #><255-blk #><--128 data bytes--><cksum>
+ in which:
+ <SOH> = 01 hex
+ <blk #> = binary number, starts at 01 increments by 1, and
+ wraps 0FFH to 00H (not to 01)
+ <255-blk #> = blk # after going thru 8080 "CMA" instr, i.e.
+ each bit complemented in the 8-bit block number.
+ Formally, this is the "ones complement".
+ <cksum> = the sum of the data bytes only. Toss any carry.
+
+ 7.3 File Level Protocol
+
+ 7.3.1 Common_to_Both_Sender_and_Receiver
+ All errors are retried 10 times. For versions running with an operator
+ (i.e. NOT with XMODEM), a message is typed after 10 errors asking the
+ operator whether to "retry or quit".
+
+ Some versions of the protocol use <can>, ASCII ^X, to cancel transmission.
+ This was never adopted as a standard, as having a single "abort" character
+ makes the transmission susceptible to false termination due to an <ack>
+ <nak> or <soh> being corrupted into a <can> and aborting transmission.
+
+ The protocol may be considered "receiver driven", that is, the sender need
+ not automatically re-transmit, although it does in the current
+ implementations.
+
+
+ 7.3.2 Receive_Program_Considerations
+ The receiver has a 10-second timeout. It sends a <nak> every time it
+ times out. The receiver's first timeout, which sends a <nak>, signals the
+ transmitter to start. Optionally, the receiver could send a <nak>
+ immediately, in case the sender was ready. This would save the initial 10
+ second timeout. However, the receiver MUST continue to timeout every 10
+ seconds in case the sender wasn't ready.
+
+ Once into a receiving a block, the receiver goes into a one-second timeout
+ for each character and the checksum. If the receiver wishes to <nak> a
+ block for any reason (invalid header, timeout receiving data), it must
+ wait for the line to clear. See "programming tips" for ideas
+
+ Synchronizing: If a valid block number is received, it will be: 1) the
+ expected one, in which case everything is fine; or 2) a repeat of the
+ previously received block. This should be considered OK, and only
+ indicates that the receivers <ack> got glitched, and the sender re-
+ transmitted; 3) any other block number indicates a fatal loss of
+ synchronization, such as the rare case of the sender getting a line-glitch
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 22
+
+
+
+ that looked like an <ack>. Abort the transmission, sending a <can>
+
+
+ 7.3.3 Sending_program_considerations
+ While waiting for transmission to begin, the sender has only a single very
+ long timeout, say one minute. In the current protocol, the sender has a
+ 10 second timeout before retrying. I suggest NOT doing this, and letting
+ the protocol be completely receiver-driven. This will be compatible with
+ existing programs.
+
+ When the sender has no more data, it sends an <eot>, and awaits an <ack>,
+ resending the <eot> if it doesn't get one. Again, the protocol could be
+ receiver-driven, with the sender only having the high-level 1-minute
+ timeout to abort.
+
+
+ Here is a sample of the data flow, sending a 3-block message. It includes
+ the two most common line hits - a garbaged block, and an <ack> reply
+ getting garbaged. <xx> represents the checksum byte.
+
+ Figure 10. Data flow including Error Recovery
+
+ SENDER RECEIVER
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 01 FE -data- <xx> --->
+ <--- <ack>
+ <soh> 02 FD -data- xx ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- xx --->
+ <--- <ack>
+ <soh> 03 FC -data- xx --->
+ (ack gets garbaged) <--- <ack>
+ <soh> 03 FC -data- xx ---> <ack>
+ <eot> --->
+ <--- <anything except ack>
+ <eot> --->
+ <--- <ack>
+ (finished)
+
+ 7.4 Programming Tips
+
+ + The character-receive subroutine should be called with a parameter
+ specifying the number of seconds to wait. The receiver should first
+ call it with a time of 10, then <nak> and try again, 10 times.
+
+ After receiving the <soh>, the receiver should call the character
+ receive subroutine with a 1-second timeout, for the remainder of the
+ message and the <cksum>. Since they are sent as a continuous stream,
+ timing out of this implies a serious like glitch that caused, say,
+ 127 characters to be seen instead of 128.
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 23
+
+
+
+ + When the receiver wishes to <nak>, it should call a "PURGE"
+ subroutine, to wait for the line to clear. Recall the sender tosses
+ any characters in its UART buffer immediately upon completing sending
+ a block, to ensure no glitches were mis- interpreted.
+
+ The most common technique is for "PURGE" to call the character
+ receive subroutine, specifying a 1-second timeout,[1] and looping
+ back to PURGE until a timeout occurs. The <nak> is then sent,
+ ensuring the other end will see it.
+
+ + You may wish to add code recommended by John Mahr to your character
+ receive routine - to set an error flag if the UART shows framing
+ error, or overrun. This will help catch a few more glitches - the
+ most common of which is a hit in the high bits of the byte in two
+ consecutive bytes. The <cksum> comes out OK since counting in 1-byte
+ produces the same result of adding 80H + 80H as with adding 00H +
+ 00H.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __________
+
+ 1. These times should be adjusted for use with timesharing systems.
+
+
+
+
+ Chapter 7 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 24
+
+
+
+ 8. XMODEM/CRC Overview
+
+ Original 1/13/85 by John Byrns -- CRC option.
+
+ Please pass on any reports of errors in this document or suggestions for
+ improvement to me via Ward's/CBBS at (312) 849-1132, or by voice at (312)
+ 885-1105.
+
+ The CRC used in the Modem Protocol is an alternate form of block check
+ which provides more robust error detection than the original checksum.
+ Andrew S. Tanenbaum says in his book, Computer Networks, that the CRC-
+ CCITT used by the Modem Protocol will detect all single and double bit
+ errors, all errors with an odd number of bits, all burst errors of length
+ 16 or less, 99.997% of 17-bit error bursts, and 99.998% of 18-bit and
+ longer bursts.[1]
+
+ The changes to the Modem Protocol to replace the checksum with the CRC are
+ straight forward. If that were all that we did we would not be able to
+ communicate between a program using the old checksum protocol and one
+ using the new CRC protocol. An initial handshake was added to solve this
+ problem. The handshake allows a receiving program with CRC capability to
+ determine whether the sending program supports the CRC option, and to
+ switch it to CRC mode if it does. This handshake is designed so that it
+ will work properly with programs which implement only the original
+ protocol. A description of this handshake is presented in section 10.
+
+ Figure 11. Message Block Level Protocol, CRC mode
+
+ Each block of the transfer in CRC mode looks like:
+ <SOH><blk #><255-blk #><--128 data bytes--><CRC hi><CRC lo>
+ in which:
+ <SOH> = 01 hex
+ <blk #> = binary number, starts at 01 increments by 1, and
+ wraps 0FFH to 00H (not to 01)
+ <255-blk #> = ones complement of blk #.
+ <CRC hi> = byte containing the 8 hi order coefficients of the CRC.
+ <CRC lo> = byte containing the 8 lo order coefficients of the CRC.
+
+ 8.1 CRC Calculation
+
+ 8.1.1 Formal_Definition
+ To calculate the 16 bit CRC the message bits are considered to be the
+ coefficients of a polynomial. This message polynomial is first multiplied
+ by X^16 and then divided by the generator polynomial (X^16 + X^12 + X^5 +
+
+
+ __________
+
+ 1. This reliability figure is misleading because XMODEM's critical
+ supervisory functions are not protected by this CRC.
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 25
+
+
+
+ 1) using modulo two arithmetic. The remainder left after the division is
+ the desired CRC. Since a message block in the Modem Protocol is 128 bytes
+ or 1024 bits, the message polynomial will be of order X^1023. The hi order
+ bit of the first byte of the message block is the coefficient of X^1023 in
+ the message polynomial. The lo order bit of the last byte of the message
+ block is the coefficient of X^0 in the message polynomial.
+
+ Figure 12. Example of CRC Calculation written in C
+
+ The following XMODEM crc routine is taken from "rbsb.c". Please refer to
+ the source code for these programs (contained in RZSZ.ZOO) for usage. A
+ fast table driven version is also included in this file.
+
+ /* update CRC */
+ unsigned short
+ updcrc(c, crc)
+ register c;
+ register unsigned crc;
+ {
+ register count;
+
+ for (count=8; --count>=0;) {
+ if (crc & 0x8000) {
+ crc <<= 1;
+ crc += (((c<<=1) & 0400) != 0);
+ crc ^= 0x1021;
+ }
+ else {
+ crc <<= 1;
+ crc += (((c<<=1) & 0400) != 0);
+ }
+ }
+ return crc;
+ }
+
+ 8.2 CRC File Level Protocol Changes
+
+ 8.2.1 Common_to_Both_Sender_and_Receiver
+ The only change to the File Level Protocol for the CRC option is the
+ initial handshake which is used to determine if both the sending and the
+ receiving programs support the CRC mode. All Modem Programs should support
+ the checksum mode for compatibility with older versions. A receiving
+ program that wishes to receive in CRC mode implements the mode setting
+ handshake by sending a <C> in place of the initial <nak>. If the sending
+ program supports CRC mode it will recognize the <C> and will set itself
+ into CRC mode, and respond by sending the first block as if a <nak> had
+ been received. If the sending program does not support CRC mode it will
+ not respond to the <C> at all. After the receiver has sent the <C> it will
+ wait up to 3 seconds for the <soh> that starts the first block. If it
+ receives a <soh> within 3 seconds it will assume the sender supports CRC
+ mode and will proceed with the file exchange in CRC mode. If no <soh> is
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 26
+
+
+
+ received within 3 seconds the receiver will switch to checksum mode, send
+ a <nak>, and proceed in checksum mode. If the receiver wishes to use
+ checksum mode it should send an initial <nak> and the sending program
+ should respond to the <nak> as defined in the original Modem Protocol.
+ After the mode has been set by the initial <C> or <nak> the protocol
+ follows the original Modem Protocol and is identical whether the checksum
+ or CRC is being used.
+
+
+ 8.2.2 Receive_Program_Considerations
+ There are at least 4 things that can go wrong with the mode setting
+ handshake.
+
+ 1. the initial <C> can be garbled or lost.
+
+ 2. the initial <soh> can be garbled.
+
+ 3. the initial <C> can be changed to a <nak>.
+
+ 4. the initial <nak> from a receiver which wants to receive in checksum
+ can be changed to a <C>.
+
+ The first problem can be solved if the receiver sends a second <C> after
+ it times out the first time. This process can be repeated several times.
+ It must not be repeated too many times before sending a <nak> and
+ switching to checksum mode or a sending program without CRC support may
+ time out and abort. Repeating the <C> will also fix the second problem if
+ the sending program cooperates by responding as if a <nak> were received
+ instead of ignoring the extra <C>.
+
+ It is possible to fix problems 3 and 4 but probably not worth the trouble
+ since they will occur very infrequently. They could be fixed by switching
+ modes in either the sending or the receiving program after a large number
+ of successive <nak>s. This solution would risk other problems however.
+
+
+ 8.2.3 Sending_Program_Considerations
+ The sending program should start in the checksum mode. This will insure
+ compatibility with checksum only receiving programs. Anytime a <C> is
+ received before the first <nak> or <ack> the sending program should set
+ itself into CRC mode and respond as if a <nak> were received. The sender
+ should respond to additional <C>s as if they were <nak>s until the first
+ <ack> is received. This will assist the receiving program in determining
+ the correct mode when the <soh> is lost or garbled. After the first <ack>
+ is received the sending program should ignore <C>s.
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 27
+
+
+
+ 8.3 Data Flow Examples with CRC Option
+
+ Here is a data flow example for the case where the receiver requests
+ transmission in the CRC mode but the sender does not support the CRC
+ option. This example also includes various transmission errors. <xx>
+ represents the checksum byte.
+
+ Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't
+
+ SENDER RECEIVER
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <C>
+ times out after 3 seconds,
+ <--- <nak>
+ <soh> 01 FE -data- <xx> --->
+ <--- <ack>
+ <soh> 02 FD -data- <xx> ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- <xx> --->
+ <--- <ack>
+ <soh> 03 FC -data- <xx> --->
+ (ack gets garbaged) <--- <ack>
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 03 FC -data- <xx> --->
+ <--- <ack>
+ <eot> --->
+ <--- <ack>
+
+ Here is a data flow example for the case where the receiver requests
+ transmission in the CRC mode and the sender supports the CRC option. This
+ example also includes various transmission errors. <xxxx> represents the
+ 2 CRC bytes.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 28
+
+
+
+ Figure 14. Receiver and Sender Both have CRC Option
+
+ SENDER RECEIVER
+ <--- <C>
+ <soh> 01 FE -data- <xxxx> --->
+ <--- <ack>
+ <soh> 02 FD -data- <xxxx> ---> (data gets line hit)
+ <--- <nak>
+ <soh> 02 FD -data- <xxxx> --->
+ <--- <ack>
+ <soh> 03 FC -data- <xxxx> --->
+ (ack gets garbaged) <--- <ack>
+ times out after 10 seconds,
+ <--- <nak>
+ <soh> 03 FC -data- <xxxx> --->
+ <--- <ack>
+ <eot> --->
+ <--- <ack>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Chapter 8 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 29
+
+
+
+ 9. MORE INFORMATION
+
+ Please contact Omen Technology for troff source files and typeset copies
+ of this document.
+
+
+ 9.1 TeleGodzilla Bulletin Board
+
+ More information may be obtained by calling TeleGodzilla at 503-621-3746.
+ Speed detection is automatic for 1200, 2400 and 19200(Telebit PEP) bps.
+ TrailBlazer modem users may issue the TeleGodzilla trailblazer command to
+ swith to 19200 bps once they have logged in.
+
+ Interesting files include RZSZ.ZOO (C source code), YZMODEM.ZOO (Official
+ XMODEM, YMODEM, and ZMODEM protocol descriptions), ZCOMMEXE.ARC,
+ ZCOMMDOC.ARC, and ZCOMMHLP.ARC (PC-DOS shareware comm program with XMODEM,
+ True YMODEM(TM), ZMODEM, Kermit Sliding Windows, Telink, MODEM7 Batch,
+ script language, etc.).
+
+
+ 9.2 Unix UUCP Access
+
+ UUCP sites can obtain the current version of this file with
+ uucp omen!/u/caf/public/ymodem.doc /tmp
+ A continually updated list of available files is stored in
+ /usr/spool/uucppublic/FILES. When retrieving these files with uucp,
+ remember that the destination directory on your system must be writeable
+ by anyone, or the UUCP transfer will fail.
+
+ The following L.sys line calls TeleGodzilla (Pro-YAM in host operation).
+ TeleGodzilla determines the incoming speed automatically.
+
+ In response to "Name Please:" uucico gives the Pro-YAM "link" command as a
+ user name. The password (Giznoid) controls access to the Xenix system
+ connected to the IBM PC's other serial port. Communications between
+ Pro-YAM and Xenix use 9600 bps; YAM converts this to the caller's speed.
+
+ Finally, the calling uucico logs in as uucp.
+
+ omen Any ACU 2400 1-503-621-3746 se:--se: link ord: Giznoid in:--in: uucp
+
+
+
+ 10. REVISIONS
+
+ 6-18-88 Further revised for clarity. Corrected block numbering in two
+ examples.
+ 10-27-87 Optional fields added for number of files remaining to be sent
+ and total number of bytes remaining to be sent.
+ 10-18-87 Flow control discussion added to 1024 byte block descritpion,
+ minor revisions for clarity per user comments.
+
+
+
+ Chapter 10 Xmodem Protocol Overview
+
+
+
+
+
+
+
+ X/YMODEM Protocol Reference June 18 1988 30
+
+
+
+ 8-03-87 Revised for clarity.
+ 5-31-1987 emphasizes minimum requirements for YMODEM, and updates
+ information on accessing files.
+ 9-11-1986 clarifies nomenclature and some minor points.
+ The April 15 1986 edition clarifies some points concerning CRC
+ calculations and spaces in the header.
+
+
+ 11. YMODEM Programs
+
+ ZCOMM, A shareware little brother to Professional-YAM, is available as
+ ZCOMMEXE.ARC on TeleGodzilla and other bulletin board systems. ZCOMM may
+ be used to test YMODEM amd ZMODEM implementations.
+
+ Unix programs supporting YMODEM are available on TeleGodzilla in RZSZ.ZOO.
+ This ZOO archive includes a ZCOMM/Pro-YAM/PowerCom script ZUPL.T to upload
+ a bootstrap program MINIRB.C, compile it, and then upload the rest of the
+ files using the compiled MINIRB. Most Unix like systems are supported,
+ including V7, Xenix, Sys III, 4.2 BSD, SYS V, Idris, Coherent, and
+ Regulus.
+
+ A version for VAX-VMS is available in VRBSB.SHQ.
+
+ Irv Hoff has added 1k blocks and basic YMODEM batch transfers to the KMD
+ and IMP series programs, which replace the XMODEM and MODEM7/MDM7xx series
+ respectively. Overlays are available for a wide variety of CP/M systems.
+
+ Questions about Professional-YAM communications software may be directed
+ to:
+ Chuck Forsberg
+ Omen Technology Inc
+ 17505-V Sauvie Island Road
+ Portland Oregon 97231
+ VOICE: 503-621-3406 :VOICE
+ Modem: 503-621-3746 Speed: 19200(Telebit PEP),2400,1200,300
+ Usenet: ...!tektronix!reed!omen!caf
+ CompuServe: 70007,2304
+ GEnie: CAF
+
+ Unlike ZMODEM and Kermit, XMODEM and YMODEM place obstacles in the path of
+ a reliable high performance implementation, evidenced by poor reliability
+ under stress of the industry leaders' XMODEM and YMODEM programs. Omen
+ Technology provides consulting and other services to those wishing to
+ implement XMODEM, YMODEM, and ZMODEM with state of the art features and
+ reliability.
+
+
+
+
+
+
+
+
+
+ Chapter 11 Xmodem Protocol Overview
+
+
+
+
+
+
+
+
+
+
+
+ CONTENTS
+
+
+ 1. TOWER OF BABEL................................................... 2
+ 1.1 Definitions................................................. 2
+
+ 2. YMODEM MINIMUM REQUIREMENTS...................................... 4
+
+ 3. WHY YMODEM?...................................................... 6
+ 3.1 Some Messages from the Pioneer.............................. 7
+
+ 4. XMODEM PROTOCOL ENHANCEMENTS..................................... 10
+ 4.1 Graceful Abort.............................................. 10
+ 4.2 CRC-16 Option............................................... 10
+ 4.3 XMODEM-1k 1024 Byte Block................................... 11
+
+ 5. YMODEM Batch File Transmission................................... 13
+ 5.1 KMD/IMP Exceptions to YMODEM................................ 16
+
+ 6. YMODEM-g File Transmission....................................... 18
+
+ 7. XMODEM PROTOCOL OVERVIEW......................................... 20
+ 7.1 Definitions................................................. 20
+ 7.2 Transmission Medium Level Protocol.......................... 20
+ 7.3 File Level Protocol......................................... 21
+ 7.4 Programming Tips............................................ 22
+
+ 8. XMODEM/CRC Overview.............................................. 24
+ 8.1 CRC Calculation............................................. 24
+ 8.2 CRC File Level Protocol Changes............................. 25
+ 8.3 Data Flow Examples with CRC Option.......................... 27
+
+ 9. MORE INFORMATION................................................. 29
+ 9.1 TeleGodzilla Bulletin Board................................. 29
+ 9.2 Unix UUCP Access............................................ 29
+
+ 10. REVISIONS........................................................ 29
+
+ 11. YMODEM Programs.................................................. 30
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - i -
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ LIST OF FIGURES
+
+
+ Figure 1. XMODEM-1k Blocks.......................................... 12
+
+ Figure 2. Mixed 1024 and 128 byte Blocks............................ 12
+
+ Figure 3. YMODEM Batch Transmission Session (1 file)................ 16
+
+ Figure 4. YMODEM Batch Transmission Session (2 files)............... 16
+
+ Figure 5. YMODEM Batch Transmission Session-1k Blocks............... 16
+
+ Figure 6. YMODEM Filename block transmitted by sz................... 16
+
+ Figure 7. YMODEM Header Information and Features.................... 16
+
+ Figure 8. YMODEM-g Transmission Session............................. 19
+
+ Figure 9. XMODEM Message Block Level Protocol....................... 21
+
+ Figure 10. Data flow including Error Recovery........................ 22
+
+ Figure 11. Message Block Level Protocol, CRC mode.................... 24
+
+ Figure 12. Example of CRC Calculation written in C................... 25
+
+ Figure 13. Data Flow: Receiver has CRC Option, Sender Doesn't........ 27
+
+ Figure 14. Receiver and Sender Both have CRC Option.................. 28
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - ii -
diff --git a/com32/libupload/zout.c b/com32/libupload/zout.c
new file mode 100644
index 00000000..47c0d308
--- /dev/null
+++ b/com32/libupload/zout.c
@@ -0,0 +1,100 @@
+/*
+ * Compress input and feed it to a block-oriented back end.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <zlib.h>
+#include "upload_backend.h"
+#include "ctime.h"
+
+#define ALLOC_CHUNK 65536
+
+int init_data(struct upload_backend *be, const char *argv[])
+{
+ be->now = posix_time();
+ be->argv = argv;
+
+ memset(&be->zstream, 0, sizeof be->zstream);
+
+ be->zstream.next_out = NULL;
+ be->outbuf = NULL;
+ be->zstream.avail_out = be->alloc = 0;
+ be->dbytes = be->zbytes = 0;
+
+ /* Initialize a gzip data stream */
+ if (deflateInit2(&be->zstream, 9, Z_DEFLATED,
+ 16+15, 9, Z_DEFAULT_STRATEGY) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int do_deflate(struct upload_backend *be, int flush)
+{
+ int rv;
+ char *buf;
+
+ while (1) {
+ rv = deflate(&be->zstream, flush);
+ be->zbytes = be->alloc - be->zstream.avail_out;
+ if (be->zstream.avail_out)
+ return rv; /* Not an issue of output space... */
+
+ buf = realloc(be->outbuf, be->alloc + ALLOC_CHUNK);
+ if (!buf)
+ return Z_MEM_ERROR;
+ be->outbuf = buf;
+ be->alloc += ALLOC_CHUNK;
+ be->zstream.next_out = (void *)(buf + be->zbytes);
+ be->zstream.avail_out = be->alloc - be->zbytes;
+ }
+}
+
+
+int write_data(struct upload_backend *be, const void *buf, size_t len)
+{
+ int rv = Z_OK;
+
+ be->zstream.next_in = (void *)buf;
+ be->zstream.avail_in = len;
+
+ be->dbytes += len;
+
+ while (be->zstream.avail_in) {
+ rv = do_deflate(be, Z_NO_FLUSH);
+ if (rv < 0) {
+ printf("do_deflate returned %d\n", rv);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/* Output the data and shut down the stream */
+int flush_data(struct upload_backend *be)
+{
+ int rv = Z_OK;
+ int err=-1;
+
+ while (rv != Z_STREAM_END) {
+ rv = do_deflate(be, Z_FINISH);
+ if (rv < 0)
+ return -1;
+ }
+
+// printf("Uploading data, %u bytes... ", be->zbytes);
+
+ if ((err=be->write(be)) != 0)
+ return err;
+
+ free(be->outbuf);
+ be->outbuf = NULL;
+ be->dbytes = be->zbytes = be->alloc = 0;
+
+// printf("done.\n");
+ return 0;
+}