From 29de6e2195ce85db9c354b3e73eda1cd61860924 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sun, 13 Apr 2025 22:06:52 +0800 Subject: [PATCH 1/6] system/dd: support conv=nocreat align nshlib/nsh_cmddd Signed-off-by: dongjiuzhu1 --- system/dd/dd_main.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index fb8005b400c..744f3dbbaad 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -78,8 +78,8 @@ 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 */ FAR uint8_t *buffer; /* Buffer of data to write to the output file */ @@ -187,8 +187,7 @@ 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", @@ -207,7 +206,8 @@ static void print_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, " %s [if=] [of=] [bs=] " - "[count=] [skip=] [seek=]\n", g_dd); + "[count=] [skip=] [seek=] " + "[conv=]\n", g_dd); } /**************************************************************************** @@ -232,6 +232,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 */ @@ -270,7 +271,11 @@ 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 { From 61662af3a617a17b82b1cbfa7ae2592b9fcfb03e Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sat, 12 Apr 2025 18:37:49 +0800 Subject: [PATCH 2/6] system/dd: align nshlib/cmd_dd nshlib/cmd_dd: Retry if read() was interrupted Without this patch nsh> ls /etc/group | dd | dd sh [13:100] sh [14:100] nsh: dd: read failed: 4 nsh> Signed-off-by: wangjianyu3 Signed-off-by: dongjiuzhu1 --- system/dd/dd_main.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index 744f3dbbaad..b92c44233a1 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -135,6 +135,11 @@ static int dd_read(FAR struct dd_s *dd) nbytes = read(dd->infd, buffer, dd->sectsize - dd->nbytes); if (nbytes < 0) { + if (errno == EINTR) + { + continue; + } + fprintf(stderr, "%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; } From 17e53700b7d14e5a138a38693686d28826dcb56f Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sat, 12 Apr 2025 18:57:15 +0800 Subject: [PATCH 3/6] system/dd: align nshlib/cmd_dd cmd_dd:support dd can do verify After writing the file, compare the contents of the two files again Signed-off-by: anjiahao Signed-off-by: dongjiuzhu1 --- system/dd/dd_main.c | 91 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index b92c44233a1..3d6cae02d0d 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -203,6 +204,75 @@ static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd) 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) + { + fprintf(stderr, "%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) + { + fprintf(stderr, "%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) + { + fprintf(stderr, "%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) + { + fprintf(stderr, "%s: failed to dd verify: %d\n", + g_dd, ret); + } + + free(buffer); + return ret; +} + /**************************************************************************** * Name: print_usage ****************************************************************************/ @@ -211,7 +281,7 @@ static void print_usage(void) { fprintf(stderr, "usage:\n"); fprintf(stderr, " %s [if=] [of=] [bs=] " - "[count=] [skip=] [seek=] " + "[count=] [skip=] [seek=] [verify] " "[conv=]\n", g_dd); } @@ -267,6 +337,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]; @@ -304,6 +378,16 @@ int main(int argc, FAR char **argv) } } + /* If verify enabled, infile and outfile are mandatory */ + + if ((dd.oflags & O_RDONLY) && (infile == NULL || outfile == NULL)) + { + fprintf(stderr, "%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); @@ -400,6 +484,11 @@ int main(int argc, FAR char **argv) (unsigned int)(((double)total / 1024) / ((double)elapsed / USEC_PER_SEC))); + if (ret == 0 && (dd.oflags & O_RDONLY) != 0) + { + ret = dd_verify(&dd); + } + errout_with_outf: close(dd.outfd); From bca80749591f01d31d00820bbcd85781bb848487 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sun, 13 Apr 2025 21:48:37 +0800 Subject: [PATCH 4/6] system/dd: check infile/outfile when closing Signed-off-by: dongjiuzhu1 --- system/dd/dd_main.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index 3d6cae02d0d..5c0f9cd16ef 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -490,14 +490,30 @@ int main(int argc, FAR char **argv) } errout_with_outf: - close(dd.outfd); + if (outfile) + { + dd.outfd = close(dd.outfd); + if (dd.outfd < 0) + { + fprintf(stderr, "%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) + { + fprintf(stderr, "%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); } From 4f1249c59bd436c7baa6bfb52f6ff779ceeb8f47 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sun, 13 Apr 2025 22:12:05 +0800 Subject: [PATCH 5/6] system/dd: align nsh dd command nshlib/dd: Increase the integer width for sector size in dd. On some systems, using sector sizes larger than 65536 is needed for profiling performance or testing. Stuart Ianna Signed-off-by: dongjiuzhu1 --- system/dd/dd_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/dd/dd_main.c b/system/dd/dd_main.c index 5c0f9cd16ef..3eba567ffe5 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -81,8 +81,8 @@ struct dd_s 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 */ - 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 */ }; @@ -97,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)? */ From 4ed499db3a344363323208bc798e6131f19a66d5 Mon Sep 17 00:00:00 2001 From: dongjiuzhu1 Date: Sun, 13 Apr 2025 22:20:23 +0800 Subject: [PATCH 6/6] nshlib/dd: remove nsh dd cmd using system/dd to instead nsh dd cmd remove related to config, file. Signed-off-by: dongjiuzhu1 --- nshlib/CMakeLists.txt | 1 - nshlib/Kconfig | 9 - nshlib/Makefile | 2 +- nshlib/nsh.h | 3 - nshlib/nsh_command.c | 6 - nshlib/nsh_ddcmd.c | 505 ------------------------------------------ system/dd/Kconfig | 7 +- system/dd/dd_main.c | 72 +++--- 8 files changed, 41 insertions(+), 564 deletions(-) delete mode 100644 nshlib/nsh_ddcmd.c 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 3eba567ffe5..4ab595b078b 100644 --- a/system/dd/dd_main.c +++ b/system/dd/dd_main.c @@ -108,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; } @@ -141,7 +140,7 @@ static int dd_read(FAR struct dd_s *dd) continue; } - fprintf(stderr, "%s: failed to read: %s\n", g_dd, strerror(errno)); + printf("%s: failed to read: %s\n", g_dd, strerror(errno)); return ERROR; } @@ -173,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; } @@ -196,8 +194,7 @@ 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) { - 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; } @@ -213,8 +210,7 @@ static int dd_verify(FAR struct dd_s *dd) ret = lseek(dd->infd, dd->skip ? dd->skip * dd->sectsize : 0, SEEK_SET); if (ret < 0) { - fprintf(stderr, "%s: failed to infd lseek: %s\n", - g_dd, strerror(errno)); + printf("%s: failed to infd lseek: %s\n", g_dd, strerror(errno)); return ret; } @@ -222,8 +218,7 @@ static int dd_verify(FAR struct dd_s *dd) ret = lseek(dd->outfd, 0, SEEK_SET); if (ret < 0) { - fprintf(stderr, "%s: failed to outfd lseek: %s\n", - g_dd, strerror(errno)); + printf("%s: failed to outfd lseek: %s\n", g_dd, strerror(errno)); return ret; } @@ -244,8 +239,8 @@ static int dd_verify(FAR struct dd_s *dd) ret = read(dd->outfd, buffer, dd->nbytes); if (ret != dd->nbytes) { - fprintf(stderr, "%s: failed to outfd read: %d\n", - g_dd, ret < 0 ? errno : ret); + printf("%s: failed to outfd read: %d\n", + g_dd, ret < 0 ? errno : ret); break; } @@ -265,8 +260,7 @@ static int dd_verify(FAR struct dd_s *dd) if (ret < 0) { - fprintf(stderr, "%s: failed to dd verify: %d\n", - g_dd, ret); + printf("%s: failed to dd verify: %d\n", g_dd, ret); } free(buffer); @@ -279,10 +273,10 @@ static int dd_verify(FAR struct dd_s *dd) static void print_usage(void) { - fprintf(stderr, "usage:\n"); - fprintf(stderr, " %s [if=] [of=] [bs=] " - "[count=] [skip=] [seek=] [verify] " - "[conv=]\n", g_dd); + printf("usage:\n"); + printf(" %s [if=] [of=] [bs=] " + "[count=] [skip=] [seek=] [verify] " + "[conv=]\n", g_dd); } /**************************************************************************** @@ -294,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; @@ -358,8 +354,8 @@ int main(int argc, FAR char **argv) } 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; } @@ -382,8 +378,7 @@ int main(int argc, FAR char **argv) if ((dd.oflags & O_RDONLY) && (infile == NULL || outfile == NULL)) { - fprintf(stderr, "%s: invalid parameters: %s\n", g_dd, - strerror(EINVAL)); + printf("%s: invalid parameters: %s\n", g_dd, strerror(EINVAL)); print_usage(); goto errout_with_paths; } @@ -393,7 +388,7 @@ int main(int argc, FAR char **argv) 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; } @@ -418,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; } @@ -430,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; } @@ -439,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) { @@ -466,23 +462,27 @@ 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) { @@ -495,8 +495,7 @@ int main(int argc, FAR char **argv) dd.outfd = close(dd.outfd); if (dd.outfd < 0) { - fprintf(stderr, "%s failed to close outfd:%s\n", - g_dd, strerror(errno)); + printf("%s failed to close outfd:%s\n", g_dd, strerror(errno)); } } @@ -506,8 +505,7 @@ int main(int argc, FAR char **argv) dd.infd = close(dd.infd); if (dd.infd < 0) { - fprintf(stderr, "%s failed to close infd:%s\n", - g_dd, strerror(errno)); + printf("%s failed to close infd:%s\n", g_dd, strerror(errno)); } }