cmd_dd:support dd can do verify

After writing the file, compare the contents of the two files again

Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
anjiahao 2022-11-08 11:53:33 +08:00 committed by Xiang Xiao
parent c2f07a4d5a
commit 14465b85c4
2 changed files with 108 additions and 3 deletions

View File

@ -160,9 +160,9 @@ static const struct cmdmap_s g_cmdmap[] =
#endif
#ifndef CONFIG_NSH_DISABLE_DD
{ "dd", cmd_dd, 3, 6,
{ "dd", cmd_dd, 3, 7,
"if=<infile> of=<outfile> [bs=<sectsize>] [count=<sectors>] "
"[skip=<sectors>]" },
"[skip=<sectors>] [verify]" },
# endif
#if defined(CONFIG_NET) && defined(CONFIG_NET_ROUTE) && !defined(CONFIG_NSH_DISABLE_DELROUTE)

View File

@ -71,6 +71,7 @@ struct dd_s
uint32_t nsectors; /* Number of sectors to transfer */
uint32_t skip; /* The number of sectors skipped on input */
bool eof; /* true: The end of the input or output file has been hit */
bool verify; /* true: Verify infile and outfile correctness */
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 */
@ -171,7 +172,8 @@ static inline int dd_infopen(FAR const char *name, FAR struct dd_s *dd)
static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd)
{
dd->outfd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
dd->outfd = open(name, (dd->verify ? O_RDWR : O_WRONLY) |
O_CREAT | O_TRUNC, 0644);
if (dd->outfd < 0)
{
FAR struct nsh_vtbl_s *vtbl = dd->vtbl;
@ -182,6 +184,100 @@ static inline int dd_outfopen(FAR const char *name, FAR struct dd_s *dd)
return OK;
}
static int dd_verify(FAR const char *infile, FAR const char *outfile,
FAR struct dd_s *dd)
{
FAR uint8_t *buffer;
int sector = 0;
int ret = OK;
ret = lseek(dd->infd, dd->skip ? dd->skip * dd->sectsize : 0, SEEK_SET);
if (ret < 0)
{
nsh_error(dd->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(dd->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(dd->vtbl, g_fmtcmdfailed, g_dd, "read", NSH_ERRNO);
break;
}
if (memcmp(dd->buffer, buffer, dd->nbytes) != 0)
{
int i;
nsh_output(dd->vtbl, "infile sector %d", sector);
for (i = 0; i < dd->nbytes; i++)
{
if (i % 16 == 0)
{
nsh_output(dd->vtbl, "\n");
}
nsh_output(dd->vtbl, "%02x", dd->buffer[i]);
if (i + 1 % 2 == 0)
{
nsh_output(dd->vtbl, " ");
}
}
nsh_output(dd->vtbl, "\noutfile sector %d", sector);
for (i = 0; i < dd->nbytes; i++)
{
if (i % 16 == 0)
{
nsh_output(dd->vtbl, "\n");
}
nsh_output(dd->vtbl, "%02x", dd->buffer[i]);
if (i + 1 % 2 == 0)
{
nsh_output(dd->vtbl, " ");
}
}
nsh_output(dd->vtbl, "\n");
ret = ERROR;
break;
}
sector++;
}
if (ret < 0)
{
nsh_error(dd->vtbl, g_fmtcmdfailed, g_dd, "dd_verify", ret);
}
free(buffer);
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
@ -262,6 +358,10 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
{
dd.skip = atoi(&argv[i][5]);
}
else if (strncmp(argv[i], "verify", 6) == 0)
{
dd.verify = true;
}
}
#ifndef CAN_PIPE_FROM_STD
@ -360,6 +460,11 @@ int cmd_dd(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
/ ((double)elapsed / USEC_PER_SEC)));
#endif
if (ret == 0 && dd.verify)
{
ret = dd_verify(infile, outfile, &dd);
}
errout_with_outf:
close(dd.outfd);