diff --git a/nshlib/CMakeLists.txt b/nshlib/CMakeLists.txt index d09df277d7d..ddfe1f87e04 100644 --- a/nshlib/CMakeLists.txt +++ b/nshlib/CMakeLists.txt @@ -34,7 +34,6 @@ if(CONFIG_NSH_LIBRARY) nsh_system.c nsh_command.c nsh_fscmds.c - nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c nsh_timcmds.c diff --git a/nshlib/Kconfig b/nshlib/Kconfig index 86863ff99e9..fa7215ce2d2 100644 --- a/nshlib/Kconfig +++ b/nshlib/Kconfig @@ -345,10 +345,6 @@ config NSH_DISABLE_DATE bool "Disable date" default DEFAULT_SMALL || !RTC -config NSH_DISABLE_DD - bool "Disable dd" - default DEFAULT_SMALL - config NSH_DISABLE_DF bool "Disable df" default DEFAULT_SMALL @@ -787,11 +783,6 @@ config NSH_VARS variables variables ============== =========================== =========================== -config NSH_CMDOPT_DD_STATS - bool "dd: Support transfer statistics" - default n - depends on !NSH_DISABLE_DD - config NSH_CODECS_BUFSIZE int "File buffer size used by CODEC commands" default 128 diff --git a/nshlib/Makefile b/nshlib/Makefile index 917d8baeb28..bf6ec06f777 100644 --- a/nshlib/Makefile +++ b/nshlib/Makefile @@ -25,7 +25,7 @@ include $(APPDIR)/Make.defs # NSH Library CSRCS = nsh_init.c nsh_parse.c nsh_console.c nsh_script.c nsh_system.c -CSRCS += nsh_command.c nsh_fscmds.c nsh_ddcmd.c nsh_proccmds.c nsh_mmcmds.c +CSRCS += nsh_command.c nsh_fscmds.c nsh_proccmds.c nsh_mmcmds.c CSRCS += nsh_timcmds.c nsh_envcmds.c nsh_syscmds.c nsh_dbgcmds.c nsh_prompt.c CSRCS += nsh_session.c diff --git a/nshlib/nsh.h b/nshlib/nsh.h index cd0ea0e1a26..8d037f5176f 100644 --- a/nshlib/nsh.h +++ b/nshlib/nsh.h @@ -975,9 +975,6 @@ int cmd_irqinfo(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #ifndef CONFIG_NSH_DISABLE_CMP int cmd_cmp(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif -#ifndef CONFIG_NSH_DISABLE_DD - int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); -#endif #ifndef CONFIG_NSH_DISABLE_HEXDUMP int cmd_hexdump(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv); #endif diff --git a/nshlib/nsh_command.c b/nshlib/nsh_command.c index 3a91a1c2f5a..dc8fab48128 100644 --- a/nshlib/nsh_command.c +++ b/nshlib/nsh_command.c @@ -185,12 +185,6 @@ static const struct cmdmap_s g_cmdmap[] = 1, 4, "[-s \"MMM DD HH:MM:SS YYYY\"] [-u] [+format]"), #endif -#ifndef CONFIG_NSH_DISABLE_DD - CMD_MAP("dd", cmd_dd, 1, 7, - "if= of= [bs=] [count=] " - "[skip=] [seek=] [verify] [conv=]"), -#endif - #if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE) && !defined(CONFIG_NSH_DISABLE_DELROUTE) CMD_MAP("delroute", cmd_delroute, 2, 3, " []"), #endif diff --git a/nshlib/nsh_ddcmd.c b/nshlib/nsh_ddcmd.c deleted file mode 100644 index d24aac52bb8..00000000000 --- a/nshlib/nsh_ddcmd.c +++ /dev/null @@ -1,505 +0,0 @@ -/**************************************************************************** - * apps/nshlib/nsh_ddcmd.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nsh.h" -#include "nsh_console.h" - -#ifndef CONFIG_NSH_DISABLE_DD - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -/* If no sector size is specified with BS=, then the following default value - * is used. - */ - -#define DEFAULT_SECTSIZE 512 -#define g_dd "dd" - -/**************************************************************************** - * Private Types - ****************************************************************************/ - -struct dd_s -{ - FAR struct nsh_vtbl_s *vtbl; - - int infd; /* File descriptor of the input device */ - int outfd; /* File descriptor of the output device */ - uint32_t nsectors; /* Number of sectors to transfer */ - uint32_t skip; /* The number of sectors skipped on input */ - uint32_t seek; /* The number of bytes skipped on output */ - int oflags; /* The open flags on output deivce */ - bool eof; /* true: The end of the input or output file has been hit */ - size_t sectsize; /* Size of one sector */ - size_t nbytes; /* Number of valid bytes in the buffer */ - FAR uint8_t *buffer; /* Buffer of data to write to the output file */ -}; - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: dd_write - ****************************************************************************/ - -static int dd_write(FAR struct dd_s *dd) -{ - FAR uint8_t *buffer = dd->buffer; - size_t written; - ssize_t nbytes; - - /* Is the out buffer full (or is this the last one)? */ - - written = 0; - do - { - nbytes = write(dd->outfd, buffer, dd->nbytes - written); - if (nbytes < 0) - { - FAR struct nsh_vtbl_s *vtbl = dd->vtbl; - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "write", NSH_ERRNO); - return ERROR; - } - - written += nbytes; - buffer += nbytes; - } - while (written < dd->nbytes); - - return OK; -} - -/**************************************************************************** - * Name: dd_read - ****************************************************************************/ - -static int dd_read(FAR struct dd_s *dd) -{ - FAR uint8_t *buffer = dd->buffer; - ssize_t nbytes; - - dd->nbytes = 0; - do - { - nbytes = read(dd->infd, buffer, dd->sectsize - dd->nbytes); - if (nbytes < 0) - { - if (errno == EINTR) - { - continue; - } - - FAR struct nsh_vtbl_s *vtbl = dd->vtbl; - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO); - return ERROR; - } - - dd->nbytes += nbytes; - buffer += nbytes; - } - while (dd->nbytes < dd->sectsize && nbytes != 0); - - dd->eof |= (dd->nbytes == 0); - return OK; -} - -/**************************************************************************** - * Name: dd_infopen - ****************************************************************************/ - -static inline int dd_infopen(FAR const char *name, FAR struct dd_s *dd) -{ - dd->infd = open(name, O_RDONLY); - if (dd->infd < 0) - { - FAR struct nsh_vtbl_s *vtbl = dd->vtbl; - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); - return ERROR; - } - - return OK; -} - -/**************************************************************************** - * Name: dd_outfopen - ****************************************************************************/ - -static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd) -{ - dd->outfd = open(name, dd->oflags, 0644); - if (dd->outfd < 0) - { - FAR struct nsh_vtbl_s *vtbl = dd->vtbl; - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "open", NSH_ERRNO); - return ERROR; - } - - return OK; -} - -static int dd_verify(FAR const char *infile, FAR const char *outfile, - FAR struct dd_s *dd) -{ - FAR struct nsh_vtbl_s *vtbl = dd->vtbl; - FAR uint8_t *buffer; - unsigned sector = 0; - int ret = OK; - - UNUSED(infile); - UNUSED(outfile); - - ret = lseek(dd->infd, dd->skip ? dd->skip * dd->sectsize : 0, SEEK_SET); - if (ret < 0) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "lseek", NSH_ERRNO); - return ret; - } - - dd->eof = 0; - ret = lseek(dd->outfd, 0, SEEK_SET); - if (ret < 0) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "lseek", NSH_ERRNO); - return ret; - } - - buffer = malloc(dd->sectsize); - if (buffer == NULL) - { - return ERROR; - } - - while (!dd->eof && sector < dd->nsectors) - { - ret = dd_read(dd); - if (ret < 0) - { - break; - } - - ret = read(dd->outfd, buffer, dd->nbytes); - if (ret != dd->nbytes) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO); - break; - } - - if (memcmp(dd->buffer, buffer, dd->nbytes) != 0) - { - char msg[32]; - snprintf(msg, sizeof(msg), "infile sector %d", sector); - nsh_dumpbuffer(vtbl, msg, dd->buffer, dd->nbytes); - snprintf(msg, sizeof(msg), "\noutfile sector %d", sector); - nsh_dumpbuffer(vtbl, msg, buffer, dd->nbytes); - nsh_output(vtbl, "\n"); - ret = ERROR; - break; - } - - sector++; - } - - if (ret < 0) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "dd_verify", ret); - } - - free(buffer); - return ret; -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: cmd_dd - * - * At present, redirect of input and output are supported. - * of= and if= arguments are required only when verify enabled. - * - ****************************************************************************/ - -int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv) -{ - FAR struct console_stdio_s *pstate = (FAR struct console_stdio_s *)vtbl; - struct dd_s dd; - FAR char *infile = NULL; - FAR char *outfile = NULL; -#ifdef CONFIG_NSH_CMDOPT_DD_STATS - struct timespec ts0; - struct timespec ts1; - uint64_t elapsed; - uint64_t total; -#endif - uint32_t sector = 0; - int ret = ERROR; - int i; - - /* Initialize the dd structure */ - - memset(&dd, 0, sizeof(struct dd_s)); - dd.vtbl = vtbl; /* For nsh_output */ - dd.sectsize = DEFAULT_SECTSIZE; /* Sector size if 'bs=' not provided */ - dd.nsectors = 0xffffffff; /* MAX_UINT32 */ - dd.oflags = O_WRONLY | O_CREAT | O_TRUNC; - - /* If no IF= option is provided on the command line, then read - * from stdin. - */ - - dd.infd = INFD(pstate); /* stdin */ - - /* If no OF= option is provided on the command line, then write - * to stdout. - */ - - dd.outfd = OUTFD(pstate); /* stdout */ - - /* Parse command line parameters */ - - for (i = 1; i < argc; i++) - { - if (strncmp(argv[i], "if=", 3) == 0) - { - if (infile != NULL) - { - free(infile); - } - - infile = nsh_getfullpath(vtbl, &argv[i][3]); - } - else if (strncmp(argv[i], "of=", 3) == 0) - { - if (outfile != NULL) - { - free(outfile); - } - - outfile = nsh_getfullpath(vtbl, &argv[i][3]); - } - else if (strncmp(argv[i], "bs=", 3) == 0) - { - dd.sectsize = atoi(&argv[i][3]); - } - else if (strncmp(argv[i], "count=", 6) == 0) - { - dd.nsectors = atoi(&argv[i][6]); - } - else if (strncmp(argv[i], "skip=", 5) == 0) - { - dd.skip = atoi(&argv[i][5]); - } - else if (strncmp(argv[i], "seek=", 5) == 0) - { - dd.seek = atoi(&argv[i][5]); - } - else if (strncmp(argv[i], "verify", 6) == 0) - { - dd.oflags |= O_RDONLY; - } - else if (strncmp(argv[i], "conv=", 5) == 0) - { - if (strstr(argv[i], "nocreat") != NULL) - { - dd.oflags &= ~(O_CREAT | O_TRUNC); - } - else if (strstr(argv[i], "notrunc") != NULL) - { - dd.oflags &= ~O_TRUNC; - } - } - } - - /* If verify enabled, infile and outfile are mandatory */ - - if ((dd.oflags & O_RDONLY) && (infile == NULL || outfile == NULL)) - { - nsh_error(vtbl, g_fmtargrequired, g_dd); - goto errout_with_paths; - } - - /* Allocate the I/O buffer */ - - dd.buffer = malloc(dd.sectsize); - if (!dd.buffer) - { - nsh_error(vtbl, g_fmtcmdoutofmemory, g_dd); - goto errout_with_paths; - } - - /* Open the input file */ - - if (infile) - { - ret = dd_infopen(infile, &dd); - if (ret < 0) - { - goto errout_with_alloc; - } - } - - /* Open the output file */ - - if (outfile) - { - ret = dd_outfopen(outfile, &dd); - if (ret < 0) - { - goto errout_with_inf; - } - } - - /* Then perform the data transfer */ - -#ifdef CONFIG_NSH_CMDOPT_DD_STATS - clock_gettime(CLOCK_MONOTONIC, &ts0); -#endif - - if (dd.skip) - { - ret = lseek(dd.infd, dd.skip * dd.sectsize, SEEK_SET); - if (ret < 0) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "skip lseek", NSH_ERRNO); - ret = ERROR; - goto errout_with_outf; - } - } - - if (dd.seek) - { - ret = lseek(dd.outfd, dd.seek * dd.sectsize, SEEK_SET); - if (ret < 0) - { - nsh_error(vtbl, g_fmtcmdfailed, g_dd, "seek lseek", NSH_ERRNO); - ret = ERROR; - goto errout_with_outf; - } - } - - while (!dd.eof && sector < dd.nsectors) - { - /* Read one sector from from the input */ - - ret = dd_read(&dd); - if (ret < 0) - { - goto errout_with_outf; - } - - /* Has the incoming data stream ended? */ - - if (!dd.eof) - { - /* Write one sector to the output file */ - - ret = dd_write(&dd); - if (ret < 0) - { - goto errout_with_outf; - } - - /* Increment the sector number */ - - sector++; - } - } - - ret = OK; - -#ifdef CONFIG_NSH_CMDOPT_DD_STATS - clock_gettime(CLOCK_MONOTONIC, &ts1); - - elapsed = (((uint64_t)ts1.tv_sec * NSEC_PER_SEC) + ts1.tv_nsec); - elapsed -= (((uint64_t)ts0.tv_sec * NSEC_PER_SEC) + ts0.tv_nsec); - elapsed /= NSEC_PER_USEC; /* usec */ - - total = ((uint64_t)sector * (uint64_t)dd.sectsize); - - nsh_output(vtbl, "%" PRIu64 "bytes copied, %" PRIu64 " usec, ", - total, elapsed); - nsh_output(vtbl, "%u KB/s\n" , - (unsigned int)(((double)total / 1024) - / ((double)elapsed / USEC_PER_SEC))); -#endif - - if (ret == 0 && (dd.oflags & O_RDONLY) != 0) - { - ret = dd_verify(infile, outfile, &dd); - } - -errout_with_outf: - if (outfile) - { - close(dd.outfd); - } - -errout_with_inf: - if (infile) - { - close(dd.infd); - } - -errout_with_alloc: - free(dd.buffer); - -errout_with_paths: - if (infile) - { - nsh_freefullpath(infile); - } - - if (outfile) - { - nsh_freefullpath(outfile); - } - - return ret; -} - -#endif /* !CONFIG_NSH_DISABLE_DD */ diff --git a/system/dd/Kconfig b/system/dd/Kconfig index b5fb44cb8d3..3479ad32c21 100644 --- a/system/dd/Kconfig +++ b/system/dd/Kconfig @@ -5,8 +5,7 @@ config SYSTEM_DD tristate "system 'dd' command" - default n - select NSH_DISABLE_DD if NSH_LIBRARY + default !DEFAULT_SMALL ---help--- Enable support for the system 'dd' command. @@ -27,4 +26,8 @@ config SYSTEM_DD_STACKSIZE int "dd stack size" default DEFAULT_TASK_STACKSIZE +config SYSTEM_DD_STATS + bool "dd: Support transfer statistics" + default y + endif diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index fb8005b400c..4ab595b078b 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -78,10 +79,10 @@ struct dd_s uint32_t nsectors; /* Number of sectors to transfer */ uint32_t skip; /* The number of sectors skipped on input */ uint32_t seek; /* The number of sectors seeked on output */ + int oflags; /* The open flags on output deivce */ bool eof; /* true: The end of the input or output file has been hit */ - bool notrunc; /* conv=notrunc */ - uint16_t sectsize; /* Size of one sector */ - uint16_t nbytes; /* Number of valid bytes in the buffer */ + size_t sectsize; /* Size of one sector */ + size_t nbytes; /* Number of valid bytes in the buffer */ FAR uint8_t *buffer; /* Buffer of data to write to the output file */ }; @@ -96,7 +97,7 @@ struct dd_s static int dd_write(FAR struct dd_s *dd) { FAR uint8_t *buffer = dd->buffer; - uint16_t written; + size_t written; ssize_t nbytes; /* Is the out buffer full (or is this the last one)? */ @@ -107,8 +108,7 @@ static int dd_write(FAR struct dd_s *dd) nbytes = write(dd->outfd, buffer, dd->nbytes - written); if (nbytes < 0) { - fprintf(stderr, "%s: failed to write: %s\n", - g_dd, strerror(errno)); + printf("%s: failed to write: %s\n", g_dd, strerror(errno)); return ERROR; } @@ -135,7 +135,12 @@ static int dd_read(FAR struct dd_s *dd) nbytes = read(dd->infd, buffer, dd->sectsize - dd->nbytes); if (nbytes < 0) { - fprintf(stderr, "%s: failed to read: %s\n", g_dd, strerror(errno)); + if (errno == EINTR) + { + continue; + } + + printf("%s: failed to read: %s\n", g_dd, strerror(errno)); return ERROR; } @@ -147,7 +152,7 @@ static int dd_read(FAR struct dd_s *dd) break; } } - while (dd->nbytes < dd->sectsize && nbytes > 0); + while (dd->nbytes < dd->sectsize && nbytes != 0); return OK; } @@ -167,8 +172,7 @@ static inline int dd_infopen(FAR const char *name, FAR struct dd_s *dd) dd->infd = open(name, O_RDONLY); if (dd->infd < 0) { - fprintf(stderr, "%s: failed to open '%s': %s\n", - g_dd, name, strerror(errno)); + printf("%s: failed to open '%s': %s\n", g_dd, name, strerror(errno)); return ERROR; } @@ -187,27 +191,92 @@ static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd) return OK; } - dd->outfd = open(name, O_WRONLY | O_CREAT | (dd->notrunc ? 0 : O_TRUNC), - 0644); + dd->outfd = open(name, dd->oflags, 0644); if (dd->outfd < 0) { - fprintf(stderr, "%s: failed to open '%s': %s\n", - g_dd, name, strerror(errno)); + printf("%s: failed to open '%s': %s\n", g_dd, name, strerror(errno)); return ERROR; } return OK; } +static int dd_verify(FAR struct dd_s *dd) +{ + FAR uint8_t *buffer; + unsigned sector = 0; + int ret = OK; + + ret = lseek(dd->infd, dd->skip ? dd->skip * dd->sectsize : 0, SEEK_SET); + if (ret < 0) + { + printf("%s: failed to infd lseek: %s\n", g_dd, strerror(errno)); + return ret; + } + + dd->eof = 0; + ret = lseek(dd->outfd, 0, SEEK_SET); + if (ret < 0) + { + printf("%s: failed to outfd lseek: %s\n", g_dd, strerror(errno)); + return ret; + } + + buffer = malloc(dd->sectsize); + if (buffer == NULL) + { + return ERROR; + } + + while (!dd->eof && sector < dd->nsectors) + { + ret = dd_read(dd); + if (ret < 0) + { + break; + } + + ret = read(dd->outfd, buffer, dd->nbytes); + if (ret != dd->nbytes) + { + printf("%s: failed to outfd read: %d\n", + g_dd, ret < 0 ? errno : ret); + break; + } + + if (memcmp(dd->buffer, buffer, dd->nbytes) != 0) + { + char msg[32]; + snprintf(msg, sizeof(msg), "infile sector %d", sector); + lib_dumpbuffer(msg, dd->buffer, dd->nbytes); + snprintf(msg, sizeof(msg), "\noutfile sector %d", sector); + lib_dumpbuffer(msg, buffer, dd->nbytes); + ret = ERROR; + break; + } + + sector++; + } + + if (ret < 0) + { + printf("%s: failed to dd verify: %d\n", g_dd, ret); + } + + free(buffer); + return ret; +} + /**************************************************************************** * Name: print_usage ****************************************************************************/ static void print_usage(void) { - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s [if=] [of=] [bs=] " - "[count=] [skip=] [seek=]\n", g_dd); + printf("usage:\n"); + printf(" %s [if=] [of=] [bs=] " + "[count=] [skip=] [seek=] [verify] " + "[conv=]\n", g_dd); } /**************************************************************************** @@ -219,10 +288,12 @@ int main(int argc, FAR char **argv) struct dd_s dd; FAR char *infile = NULL; FAR char *outfile = NULL; +#ifdef CONFIG_SYSTEM_DD_STATS struct timespec ts0; struct timespec ts1; uint64_t elapsed; uint64_t total = 0; +#endif uint32_t sector = 0; int ret = ERROR; int i; @@ -232,6 +303,7 @@ int main(int argc, FAR char **argv) memset(&dd, 0, sizeof(struct dd_s)); dd.sectsize = DEFAULT_SECTSIZE; /* Sector size if 'bs=' not provided */ dd.nsectors = 0xffffffff; /* MAX_UINT32 */ + dd.oflags = O_WRONLY | O_CREAT | O_TRUNC; /* Parse command line parameters */ @@ -261,6 +333,10 @@ int main(int argc, FAR char **argv) { dd.seek = atoi(&argv[i][5]); } + else if (strncmp(argv[i], "verify", 6) == 0) + { + dd.oflags |= O_RDONLY; + } else if (strncmp(argv[i], "conv=", 5) == 0) { const char *cur = &argv[i][5]; @@ -270,12 +346,16 @@ int main(int argc, FAR char **argv) size_t len = next != NULL ? next - cur : strlen(cur); if (len == 7 && !memcmp(cur, "notrunc", 7)) { - dd.notrunc = true; + dd.oflags &= ~O_TRUNC; + } + else if (len == 7 && !memcmp(cur, "nocreat", 7)) + { + dd.oflags &= ~(O_CREAT | O_TRUNC); } else { - fprintf(stderr, "%s: unknown conversion '%.*s'\n", g_dd, - (int)len, cur); + printf("%s: unknown conversion '%.*s'\n", g_dd, + (int)len, cur); goto errout_with_paths; } @@ -294,12 +374,21 @@ int main(int argc, FAR char **argv) } } + /* If verify enabled, infile and outfile are mandatory */ + + if ((dd.oflags & O_RDONLY) && (infile == NULL || outfile == NULL)) + { + printf("%s: invalid parameters: %s\n", g_dd, strerror(EINVAL)); + print_usage(); + goto errout_with_paths; + } + /* Allocate the I/O buffer */ dd.buffer = malloc(dd.sectsize); if (!dd.buffer) { - fprintf(stderr, "%s: failed to malloc: %s\n", g_dd, strerror(errno)); + printf("%s: failed to malloc: %s\n", g_dd, strerror(errno)); goto errout_with_paths; } @@ -324,8 +413,7 @@ int main(int argc, FAR char **argv) ret = lseek(dd.infd, dd.skip * dd.sectsize, SEEK_SET); if (ret < 0) { - fprintf(stderr, "%s: failed to lseek: %s\n", - g_dd, strerror(errno)); + printf("%s: failed to lseek: %s\n", g_dd, strerror(errno)); ret = ERROR; goto errout_with_outf; } @@ -336,8 +424,8 @@ int main(int argc, FAR char **argv) ret = lseek(dd.outfd, dd.seek * dd.sectsize, SEEK_SET); if (ret < 0) { - fprintf(stderr, "%s: failed to lseek on output: %s\n", - g_dd, strerror(errno)); + printf("%s: failed to lseek on output: %s\n", + g_dd, strerror(errno)); ret = ERROR; goto errout_with_outf; } @@ -345,7 +433,9 @@ int main(int argc, FAR char **argv) /* Then perform the data transfer */ +#ifdef CONFIG_SYSTEM_DD_STATS clock_gettime(CLOCK_MONOTONIC, &ts0); +#endif while (!dd.eof && sector < dd.nsectors) { @@ -372,33 +462,56 @@ int main(int argc, FAR char **argv) /* Increment the sector number */ sector++; +#ifdef CONFIG_SYSTEM_DD_STATS total += dd.nbytes; +#endif } } ret = OK; +#ifdef CONFIG_SYSTEM_DD_STATS clock_gettime(CLOCK_MONOTONIC, &ts1); elapsed = (((uint64_t)ts1.tv_sec * NSEC_PER_SEC) + ts1.tv_nsec); elapsed -= (((uint64_t)ts0.tv_sec * NSEC_PER_SEC) + ts0.tv_nsec); elapsed /= NSEC_PER_USEC; /* usec */ - fprintf(stderr, "%" PRIu64 " bytes (%" PRIu32 " blocks) copied, %u usec, ", - total, sector, (unsigned int)elapsed); - fprintf(stderr, "%u KB/s\n" , - (unsigned int)(((double)total / 1024) - / ((double)elapsed / USEC_PER_SEC))); + printf("%" PRIu64 " bytes (%" PRIu32 " blocks) copied, %u usec, ", + total, sector, (unsigned int)elapsed); + printf("%u KB/s\n" , + (unsigned int)(((double)total / 1024) + / ((double)elapsed / USEC_PER_SEC))); +#endif + + if (ret == 0 && (dd.oflags & O_RDONLY) != 0) + { + ret = dd_verify(&dd); + } errout_with_outf: - close(dd.outfd); + if (outfile) + { + dd.outfd = close(dd.outfd); + if (dd.outfd < 0) + { + printf("%s failed to close outfd:%s\n", g_dd, strerror(errno)); + } + } errout_with_inf: - close(dd.infd); + if (infile) + { + dd.infd = close(dd.infd); + if (dd.infd < 0) + { + printf("%s failed to close infd:%s\n", g_dd, strerror(errno)); + } + } errout_with_alloc: free(dd.buffer); errout_with_paths: - return ret; + return ret < 0 ? ret : (dd.outfd < 0 ? dd.outfd : dd.infd); }