int main()

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);
}