in system/dd/dd_main.c [286:517]
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;
/* Initialize the dd structure */
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 */
for (i = 1; i < argc; i++)
{
if (strncmp(argv[i], "if=", 3) == 0)
{
infile = &argv[i][3];
}
else if (strncmp(argv[i], "of=", 3) == 0)
{
outfile = &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)
{
const char *cur = &argv[i][5];
while (true)
{
const char *next = strchr(cur, ',');
size_t len = next != NULL ? next - cur : strlen(cur);
if (len == 7 && !memcmp(cur, "notrunc", 7))
{
dd.oflags &= ~O_TRUNC;
}
else if (len == 7 && !memcmp(cur, "nocreat", 7))
{
dd.oflags &= ~(O_CREAT | O_TRUNC);
}
else
{
printf("%s: unknown conversion '%.*s'\n", g_dd,
(int)len, cur);
goto errout_with_paths;
}
if (next == NULL)
{
break;
}
cur = next + 1;
}
}
else
{
print_usage();
goto errout_with_paths;
}
}
/* 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)
{
printf("%s: failed to malloc: %s\n", g_dd, strerror(errno));
goto errout_with_paths;
}
/* Open the input file */
ret = dd_infopen(infile, &dd);
if (ret < 0)
{
goto errout_with_alloc;
}
/* Open the output file */
ret = dd_outfopen(outfile, &dd);
if (ret < 0)
{
goto errout_with_inf;
}
if (dd.skip)
{
ret = lseek(dd.infd, dd.skip * dd.sectsize, SEEK_SET);
if (ret < 0)
{
printf("%s: failed to lseek: %s\n", g_dd, strerror(errno));
ret = ERROR;
goto errout_with_outf;
}
}
if (dd.seek)
{
ret = lseek(dd.outfd, dd.seek * dd.sectsize, SEEK_SET);
if (ret < 0)
{
printf("%s: failed to lseek on output: %s\n",
g_dd, strerror(errno));
ret = ERROR;
goto errout_with_outf;
}
}
/* Then perform the data transfer */
#ifdef CONFIG_SYSTEM_DD_STATS
clock_gettime(CLOCK_MONOTONIC, &ts0);
#endif
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.nbytes > 0)
{
/* Write one sector to the output file */
ret = dd_write(&dd);
if (ret < 0)
{
goto errout_with_outf;
}
/* 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 */
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:
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:
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 < 0 ? ret : (dd.outfd < 0 ? dd.outfd : dd.infd);
}