diff options
-rw-r--r-- | apps/system/zmodem/sz_main.c | 180 | ||||
-rw-r--r-- | apps/system/zmodem/zm.h | 2 | ||||
-rw-r--r-- | apps/system/zmodem/zm_proto.c | 14 |
3 files changed, 176 insertions, 20 deletions
diff --git a/apps/system/zmodem/sz_main.c b/apps/system/zmodem/sz_main.c index 6f77042c1..c6693f0b5 100644 --- a/apps/system/zmodem/sz_main.c +++ b/apps/system/zmodem/sz_main.c @@ -1,5 +1,5 @@ /**************************************************************************** - * system/xmodem/sz_main.c + * system/zmodem/sz_main.c * * Copyright (C) 2013 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <gnutt@nuttx.org> @@ -40,28 +40,182 @@ #include <nuttx/config.h> #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <time.h> +#include <errno.h> #include <apps/zmodem.h> /**************************************************************************** - * Definitions + * Private Functions ****************************************************************************/ -/**************************************************************************** - * Private Data - ****************************************************************************/ +static void show_usage(FAR const char *progname, int errcode) +{ + fprintf(stderr, "USAGE: %s [OPTIONS] <lname> [<lname> [<lname> ...]]\n", progname); + fprintf(stderr, "\nWhere:\n"); + fprintf(stderr, "\t<lname> is the local file name\n"); + fprintf(stderr, "\nand OPTIONS include the following:\n"); + fprintf(stderr, "\t-d <device>: Communication device to use. Default /dev/console\n"); + fprintf(stderr, "\t-r <rname>: Remote file name. Default <lname>\n"); + fprintf(stderr, "\t-x <mode>: Transfer type\n"); + fprintf(stderr, "\t\t0: Normal file (default)\n"); + fprintf(stderr, "\t\t1: Binary file\n"); + fprintf(stderr, "\t\t2: Convert \\n to local EOF convention\n"); + fprintf(stderr, "\t\t3: Resume or append to existing file\n"); + fprintf(stderr, "\t-o <option>: Transfer option\n"); + fprintf(stderr, "\t\t0: Implementation dependent\n"); + fprintf(stderr, "\t\t1: Transfer if source newer or longer\n"); + fprintf(stderr, "\t\t2: Transfer if different CRC or length\n"); + fprintf(stderr, "\t\t3: Append to existing file, if any\n"); + fprintf(stderr, "\t\t4: Replace existing file (default)\n"); + fprintf(stderr, "\t\t5: Transfer if source is newer\n"); + fprintf(stderr, "\t\t6: Transfer if dates or lengths different\n"); + fprintf(stderr, "\t\t7: Protect: transfer only if dest doesn't exist\n"); + fprintf(stderr, "\t\t8: Change filename if destination exists\n"); + fprintf(stderr, "\t-s: Skip if file not present at receiving end\n"); + fprintf(stderr, "\t-h: Show this text and exit\n"); + exit(errcode); +} /**************************************************************************** * Public Functions ****************************************************************************/ -/**************************************************************************** - * Name: sz_main - ****************************************************************************/ - -int sz_main(int argc, char *argv[]) +int sz_main(int argc, FAR char **argv) { - printf("Not yet implemented!!\n"); - return 0; -} + enum zm_xfertype_e xfrtype = XM_XFERTYPE_NORMAL; + enum zm_option_e xfroption = XM_OPTION_REPLACE; + ZMSHANDLE handle; + FAR const char *rname = NULL; + FAR const char *devname = "/dev/console"; + FAR char *endptr; + bool skip = false; + long tmp; + int exitcode = EXIT_FAILURE; + int option; + int ret; + int fd; + + /* Parse input parameters */ + + while ((option = getopt(argc, argv, ":d:ho:r:sx:")) != ERROR) + { + switch (option) + { + case 'd': + devname = optarg; + break; + + case 'h': + show_usage(argv[0], EXIT_SUCCESS); + break; + + case 'o': + tmp = strtol(optarg, &endptr, 10); + if (tmp < 0 || tmp > 8) + { + fprintf(stderr, "ERROR: Transfer option out of range: %ld\n", tmp); + show_usage(argv[0], EXIT_FAILURE); + } + else + { + xfroption = (enum zm_option_e)tmp; + } + break; + + case 'r': + rname = optarg; + break; + + case 's': + skip = true; + break; + + case 'x': + tmp = strtol(optarg, &endptr, 10); + if (tmp < 0 || tmp > 3) + { + fprintf(stderr, "ERROR: Transfer type out of range: %ld\n", tmp); + show_usage(argv[0], EXIT_FAILURE); + } + else + { + xfrtype = (enum zm_xfertype_e)tmp; + } + break; + case ':': + fprintf(stderr, "ERROR: Missing required argument\n"); + show_usage(argv[0], EXIT_FAILURE); + break; + + default: + case '?': + fprintf(stderr, "ERROR: Unrecognized option\n"); + show_usage(argv[0], EXIT_FAILURE); + break; + } + } + + /* There should be one final parameters remaining on the command line */ + + if (optind >= argc) + { + printf("ERROR: Missing required 'lname' argument\n"); + show_usage(argv[0], EXIT_FAILURE); + } + + /* Open the device for read/write access */ + + fd = open(devname, O_RDWR); + if (fd < 0) + { + fprintf(stderr, "ERROR: Failed to open %s\n", devname); + goto errout; + } + + /* Get the Zmodem handle */ + + handle = zms_initialize(fd); + if (!handle) + { + fprintf(stderr, "ERROR: Failed to get Zmodem handle\n"); + goto errout_with_device; + } + + /* And perform the transfer(s) */ + + for (; optind < argc; optind++) + { + /* By the default, the remote file name is the same as the local file + * name. This will, of course, fail miserably if rname is specified + * and there more than one lnames on the command line. Don't do that. + */ + + FAR const char *nextlname = argv[optind]; + FAR const char *nextrname = rname ? rname : nextlname; + + /* Transfer the file */ + + ret = zms_send(handle, nextlname, nextrname, xfrtype, xfroption, skip); + if (ret < 0) + { + fprintf(stderr, "ERROR: Transfer of %s failed: %d\n", + nextlname, errno); + goto errout_with_zmodem; + } + } + + exitcode = EXIT_SUCCESS; + +errout_with_zmodem: + (void)zms_release(handle); +errout_with_device: + (void)close(fd); +errout: + return exitcode; +} diff --git a/apps/system/zmodem/zm.h b/apps/system/zmodem/zm.h index 3747b0feb..e0caf8837 100644 --- a/apps/system/zmodem/zm.h +++ b/apps/system/zmodem/zm.h @@ -603,7 +603,7 @@ FAR uint8_t *zm_putzdle(FAR struct zm_state_s *pzm, FAR uint8_t *buffer, * * Input Parameters: * pzm - Zmodem session state - * buffer - Buffer of data to be sent (must not be pzm->rcvbuf) + * buffer - Buffer of data to be sent * buflen - The number of bytes in buffer to be sent * ****************************************************************************/ diff --git a/apps/system/zmodem/zm_proto.c b/apps/system/zmodem/zm_proto.c index 4ef1c143d..9af600f8a 100644 --- a/apps/system/zmodem/zm_proto.c +++ b/apps/system/zmodem/zm_proto.c @@ -169,8 +169,8 @@ FAR uint8_t *zm_putzdle(FAR struct zm_state_s *pzm, FAR uint8_t *buffer, * (ZBIN or ZBIN32 format assumed, ZCRCW terminator is always used) * * Input Parameters: - * pzm - Zmodem session state - * buffer - Buffer of data to be sent (must not be pzm->rcvbuf) + * pzm - Zmodem session state + * buffer - Buffer of data to be sent * buflen - The number of bytes in buffer to be sent * ****************************************************************************/ @@ -178,21 +178,24 @@ FAR uint8_t *zm_putzdle(FAR struct zm_state_s *pzm, FAR uint8_t *buffer, int zm_senddata(FAR struct zm_state_s *pzm, FAR const uint8_t *buffer, size_t buflen) { - uint8_t *ptr = pzm->rcvbuf; + uint8_t *ptr = pzm->scratch; ssize_t nwritten; uint32_t crc; uint8_t zbin; uint8_t term; + int i; /* Make select ZBIN or ZBIN32 format and the ZCRCW terminator */ if ((pzm->flags & ZM_FLAG_CRC32) != 0) { zbin = ZBIN32; + crc = 0xffffffff; } else { zbin = ZBIN; + crc = 0; } term = ZCRCW; @@ -200,7 +203,6 @@ int zm_senddata(FAR struct zm_state_s *pzm, FAR const uint8_t *buffer, /* Transfer the data to the I/O buffer, accumulating the CRC */ - crc = (zbin == ZBIN) ? 0 : 0xffffffff; while (buflen-- > 0) { if (zbin == ZBIN) @@ -243,7 +245,7 @@ int zm_senddata(FAR struct zm_state_s *pzm, FAR const uint8_t *buffer, else { crc = ~crc; - for (buflen = 4; --buflen >= 0; crc >>= 8) + for (i = 0; i < 4; i++, crc >>= 8) { ptr = zm_putzdle(pzm, ptr, crc & 0xff); } @@ -251,7 +253,7 @@ int zm_senddata(FAR struct zm_state_s *pzm, FAR const uint8_t *buffer, /* Send the header */ - nwritten = zm_remwrite(pzm->remfd, pzm->rcvbuf, ptr - pzm->rcvbuf); + nwritten = zm_remwrite(pzm->remfd, pzm->scratch, ptr - pzm->scratch); return nwritten < 0 ? (int)nwritten : OK; } |