xiaoxiang781216 commented on code in PR #3656:
URL: https://github.com/apache/nuttx-apps/pull/3656#discussion_r3644196262


##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,
+                          int printlimit, int depth)
+{
+  FAR struct dirent *entry;
+  FAR char *child;
+  struct stat st;
+  off_t total;
+  DIR *dp;
+
+  if (pst != NULL)
+    {
+      st = *pst;
+    }
+  else if (lstat(path, &st) < 0)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+      return 0;
+    }
+
+  /* st_size not st_blocks: units differ (NuttX FS=st_blksize, hostfs=512) */
+
+  total = st.st_size;
+
+  /* A file argument (depth 0) is always shown; nested files need -a. */
+
+  if (!S_ISDIR(st.st_mode))
+    {
+      if (depth == 0 ||
+          ((duflags & DU_FLAG_ALL) != 0 && depth <= printlimit))
+        {
+          du_print(vtbl, path, total, duflags);
+        }
+
+      return total;
+    }
+
+  dp = opendir(path);
+  if (dp == NULL)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "opendir", NSH_ERRNO);
+    }
+  else
+    {
+      while ((entry = readdir(dp)) != NULL)
+        {
+          if (strcmp(entry->d_name, ".") == 0 ||
+              strcmp(entry->d_name, "..") == 0)
+            {
+              continue;
+            }
+
+          child = nsh_getdirpath(vtbl, path, entry->d_name);
+          if (child == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdfailed, "du", "nsh_getdirpath",
+                        NSH_ERRNO);
+              continue;
+            }
+
+          total += du_recursive(vtbl, child, NULL, duflags, printlimit,
+                                depth + 1);
+          free(child);
+        }
+
+      closedir(dp);
+    }
+
+  /* Print this directory's cumulative total unless suppressed by -s/-d. */
+
+  if (depth <= printlimit)
+    {
+      du_print(vtbl, path, total, duflags);
+    }
+
+  return total;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_du
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+int cmd_du(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  unsigned int duflags = 0;
+  int printlimit = INT_MAX;
+  bool summary = false;
+  bool d_given = false;
+  bool badarg = false;
+  int option;
+  int i;
+  int ret = OK;
+
+  /* Get the du options */
+
+  while ((option = getopt(argc, argv, "hsad:")) != ERROR)
+    {
+      switch (option)
+        {
+          case 'h':
+            duflags |= DU_FLAG_HUMANREADABLE;
+            break;
+
+          case 's':
+            summary = true;
+            break;
+
+          case 'a':
+            duflags |= DU_FLAG_ALL;
+            break;
+
+          case 'd':
+            {
+              FAR char *endp;
+              long d = strtol(optarg, &endp, 10);

Review Comment:
   atoi to printlimit directly



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)

Review Comment:
   ```suggestion
                        off_t bytes, unsigned int flags)
   ```



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,
+                          int printlimit, int depth)
+{
+  FAR struct dirent *entry;
+  FAR char *child;
+  struct stat st;
+  off_t total;
+  DIR *dp;
+
+  if (pst != NULL)
+    {
+      st = *pst;
+    }
+  else if (lstat(path, &st) < 0)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+      return 0;
+    }
+
+  /* st_size not st_blocks: units differ (NuttX FS=st_blksize, hostfs=512) */
+
+  total = st.st_size;
+
+  /* A file argument (depth 0) is always shown; nested files need -a. */
+
+  if (!S_ISDIR(st.st_mode))
+    {
+      if (depth == 0 ||
+          ((duflags & DU_FLAG_ALL) != 0 && depth <= printlimit))
+        {
+          du_print(vtbl, path, total, duflags);
+        }
+
+      return total;
+    }
+
+  dp = opendir(path);
+  if (dp == NULL)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "opendir", NSH_ERRNO);
+    }
+  else
+    {
+      while ((entry = readdir(dp)) != NULL)
+        {
+          if (strcmp(entry->d_name, ".") == 0 ||
+              strcmp(entry->d_name, "..") == 0)
+            {
+              continue;
+            }
+
+          child = nsh_getdirpath(vtbl, path, entry->d_name);
+          if (child == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdfailed, "du", "nsh_getdirpath",
+                        NSH_ERRNO);
+              continue;
+            }
+
+          total += du_recursive(vtbl, child, NULL, duflags, printlimit,
+                                depth + 1);
+          free(child);
+        }
+
+      closedir(dp);
+    }
+
+  /* Print this directory's cumulative total unless suppressed by -s/-d. */
+
+  if (depth <= printlimit)
+    {
+      du_print(vtbl, path, total, duflags);
+    }
+
+  return total;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_du
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+int cmd_du(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  unsigned int duflags = 0;
+  int printlimit = INT_MAX;
+  bool summary = false;
+  bool d_given = false;
+  bool badarg = false;
+  int option;
+  int i;
+  int ret = OK;
+
+  /* Get the du options */
+
+  while ((option = getopt(argc, argv, "hsad:")) != ERROR)
+    {
+      switch (option)
+        {
+          case 'h':
+            duflags |= DU_FLAG_HUMANREADABLE;
+            break;
+
+          case 's':
+            summary = true;
+            break;
+
+          case 'a':
+            duflags |= DU_FLAG_ALL;
+            break;
+
+          case 'd':
+            {
+              FAR char *endp;
+              long d = strtol(optarg, &endp, 10);
+
+              if (endp == optarg || *endp != '\0' || d < 0)
+                {
+                  nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+                  badarg = true;
+                }
+              else
+                {
+                  printlimit = (int)d;
+                  d_given = true;

Review Comment:
   remove d_give check printlimit != INT_MAX



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,
+                          int printlimit, int depth)
+{
+  FAR struct dirent *entry;
+  FAR char *child;
+  struct stat st;
+  off_t total;
+  DIR *dp;
+
+  if (pst != NULL)
+    {
+      st = *pst;
+    }
+  else if (lstat(path, &st) < 0)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+      return 0;
+    }
+
+  /* st_size not st_blocks: units differ (NuttX FS=st_blksize, hostfs=512) */
+
+  total = st.st_size;
+
+  /* A file argument (depth 0) is always shown; nested files need -a. */
+
+  if (!S_ISDIR(st.st_mode))
+    {
+      if (depth == 0 ||
+          ((duflags & DU_FLAG_ALL) != 0 && depth <= printlimit))
+        {
+          du_print(vtbl, path, total, duflags);
+        }
+
+      return total;
+    }
+
+  dp = opendir(path);
+  if (dp == NULL)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "opendir", NSH_ERRNO);
+    }
+  else
+    {
+      while ((entry = readdir(dp)) != NULL)
+        {
+          if (strcmp(entry->d_name, ".") == 0 ||
+              strcmp(entry->d_name, "..") == 0)
+            {
+              continue;
+            }
+
+          child = nsh_getdirpath(vtbl, path, entry->d_name);
+          if (child == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdfailed, "du", "nsh_getdirpath",
+                        NSH_ERRNO);
+              continue;
+            }
+
+          total += du_recursive(vtbl, child, NULL, duflags, printlimit,
+                                depth + 1);
+          free(child);
+        }
+
+      closedir(dp);
+    }
+
+  /* Print this directory's cumulative total unless suppressed by -s/-d. */
+
+  if (depth <= printlimit)
+    {
+      du_print(vtbl, path, total, duflags);
+    }
+
+  return total;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_du
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+int cmd_du(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  unsigned int duflags = 0;
+  int printlimit = INT_MAX;
+  bool summary = false;
+  bool d_given = false;
+  bool badarg = false;
+  int option;
+  int i;
+  int ret = OK;
+
+  /* Get the du options */
+
+  while ((option = getopt(argc, argv, "hsad:")) != ERROR)
+    {
+      switch (option)
+        {
+          case 'h':
+            duflags |= DU_FLAG_HUMANREADABLE;
+            break;
+
+          case 's':
+            summary = true;
+            break;
+
+          case 'a':
+            duflags |= DU_FLAG_ALL;
+            break;
+
+          case 'd':
+            {
+              FAR char *endp;
+              long d = strtol(optarg, &endp, 10);
+
+              if (endp == optarg || *endp != '\0' || d < 0)
+                {
+                  nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+                  badarg = true;
+                }
+              else
+                {
+                  printlimit = (int)d;
+                  d_given = true;
+                }
+            }
+            break;
+
+          case '?':
+          default:
+            nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+            badarg = true;
+            break;
+        }
+    }
+
+  /* If a bad argument was encountered,
+   * then return without processing the command
+   */
+
+  if (badarg)
+    {
+      return ERROR;
+    }
+
+  /* -s reports only each argument's own total (depth 0); -d N overrides -s
+   * when both are given. -s also suppresses the -a file listing.
+   */
+
+  if (summary)
+    {
+      if (!d_given)
+        {
+          printlimit = 0;
+        }
+
+      duflags &= ~DU_FLAG_ALL;
+    }
+
+  /* Walk each path argument (default: current directory). */
+
+  if (optind >= argc)
+    {
+#ifndef CONFIG_DISABLE_ENVIRON
+      FAR char *fullpath = nsh_getfullpath(vtbl, nsh_getcwd(vtbl));
+      struct stat st;
+
+      if (fullpath == NULL)
+        {
+          nsh_error(vtbl, g_fmtcmdoutofmemory, argv[0]);
+          return ERROR;
+        }
+
+      if (lstat(fullpath, &st) < 0)
+        {
+          nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+          ret = ERROR;
+        }
+      else
+        {
+          du_recursive(vtbl, fullpath, &st, duflags, printlimit, 0);
+        }
+
+      nsh_freefullpath(fullpath);
+#else
+      nsh_error(vtbl, g_fmtargrequired, argv[0]);
+      return ERROR;
+#endif
+    }
+  else
+    {
+      for (i = optind; i < argc; i++)
+        {
+          FAR char *fullpath = nsh_getfullpath(vtbl, argv[i]);
+          struct stat st;
+
+          if (fullpath == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdoutofmemory, argv[0]);
+              ret = ERROR;
+              continue;
+            }
+
+          if (lstat(fullpath, &st) < 0)

Review Comment:
   move into du_recursive and remove pst from du_recursive



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,
+                          int printlimit, int depth)
+{
+  FAR struct dirent *entry;
+  FAR char *child;
+  struct stat st;
+  off_t total;
+  DIR *dp;
+
+  if (pst != NULL)
+    {
+      st = *pst;
+    }
+  else if (lstat(path, &st) < 0)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+      return 0;
+    }
+
+  /* st_size not st_blocks: units differ (NuttX FS=st_blksize, hostfs=512) */
+
+  total = st.st_size;
+
+  /* A file argument (depth 0) is always shown; nested files need -a. */
+
+  if (!S_ISDIR(st.st_mode))
+    {
+      if (depth == 0 ||
+          ((duflags & DU_FLAG_ALL) != 0 && depth <= printlimit))
+        {
+          du_print(vtbl, path, total, duflags);
+        }
+
+      return total;
+    }
+
+  dp = opendir(path);
+  if (dp == NULL)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "opendir", NSH_ERRNO);
+    }
+  else
+    {
+      while ((entry = readdir(dp)) != NULL)
+        {
+          if (strcmp(entry->d_name, ".") == 0 ||
+              strcmp(entry->d_name, "..") == 0)
+            {
+              continue;
+            }
+
+          child = nsh_getdirpath(vtbl, path, entry->d_name);
+          if (child == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdfailed, "du", "nsh_getdirpath",
+                        NSH_ERRNO);
+              continue;
+            }
+
+          total += du_recursive(vtbl, child, NULL, duflags, printlimit,
+                                depth + 1);
+          free(child);
+        }
+
+      closedir(dp);
+    }
+
+  /* Print this directory's cumulative total unless suppressed by -s/-d. */
+
+  if (depth <= printlimit)
+    {
+      du_print(vtbl, path, total, duflags);
+    }
+
+  return total;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_du
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+int cmd_du(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  unsigned int duflags = 0;
+  int printlimit = INT_MAX;
+  bool summary = false;
+  bool d_given = false;
+  bool badarg = false;
+  int option;
+  int i;
+  int ret = OK;
+
+  /* Get the du options */
+
+  while ((option = getopt(argc, argv, "hsad:")) != ERROR)
+    {
+      switch (option)
+        {
+          case 'h':
+            duflags |= DU_FLAG_HUMANREADABLE;
+            break;
+
+          case 's':
+            summary = true;
+            break;
+
+          case 'a':
+            duflags |= DU_FLAG_ALL;
+            break;
+
+          case 'd':
+            {
+              FAR char *endp;
+              long d = strtol(optarg, &endp, 10);
+
+              if (endp == optarg || *endp != '\0' || d < 0)
+                {
+                  nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+                  badarg = true;
+                }
+              else
+                {
+                  printlimit = (int)d;
+                  d_given = true;
+                }
+            }
+            break;
+
+          case '?':
+          default:
+            nsh_error(vtbl, g_fmtarginvalid, argv[0]);
+            badarg = true;
+            break;
+        }
+    }
+
+  /* If a bad argument was encountered,
+   * then return without processing the command
+   */
+
+  if (badarg)
+    {
+      return ERROR;
+    }
+
+  /* -s reports only each argument's own total (depth 0); -d N overrides -s
+   * when both are given. -s also suppresses the -a file listing.
+   */
+
+  if (summary)
+    {
+      if (!d_given)
+        {
+          printlimit = 0;
+        }
+
+      duflags &= ~DU_FLAG_ALL;
+    }
+
+  /* Walk each path argument (default: current directory). */
+
+  if (optind >= argc)
+    {
+#ifndef CONFIG_DISABLE_ENVIRON
+      FAR char *fullpath = nsh_getfullpath(vtbl, nsh_getcwd(vtbl));
+      struct stat st;
+
+      if (fullpath == NULL)
+        {
+          nsh_error(vtbl, g_fmtcmdoutofmemory, argv[0]);
+          return ERROR;
+        }
+
+      if (lstat(fullpath, &st) < 0)

Review Comment:
   move into du_recursive



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,

Review Comment:
   ```suggestion
                             unsigned int flags,
   ```



##########
nshlib/nsh_fscmds.c:
##########
@@ -1855,6 +1855,280 @@ int cmd_ls(FAR struct nsh_vtbl_s *vtbl, int argc, FAR 
char **argv)
 }
 #endif
 
+/****************************************************************************
+ * Name: du_print
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+#define DU_FLAG_HUMANREADABLE (1 << 0)  /* -h: human readable sizes */
+#define DU_FLAG_ALL           (1 << 1)  /* -a: list all files, not only dirs */
+
+static void du_print(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                     off_t bytes, unsigned int duflags)
+{
+  off_t kblocks = (bytes + 1023) / 1024;
+
+  if ((duflags & DU_FLAG_HUMANREADABLE) != 0)
+    {
+      off_t unit;
+      char suffix;
+
+      if (bytes >= GB)
+        {
+          unit = GB;
+          suffix = 'G';
+        }
+      else if (bytes >= MB)
+        {
+          unit = MB;
+          suffix = 'M';
+        }
+      else if (bytes >= KB)
+        {
+          unit = KB;
+          suffix = 'K';
+        }
+      else
+        {
+          nsh_output(vtbl, "%" PRIdOFF "B\t%s\n", bytes, path);
+          return;
+        }
+
+      /* Use integer arithmetic to avoid floating point */
+
+      nsh_output(vtbl, "%" PRIdOFF ".%" PRIdOFF "%c\t%s\n",
+                 bytes / unit, (bytes % unit) * 10 / unit, suffix, path);
+    }
+  else
+    {
+      nsh_output(vtbl, "%" PRIdOFF "\t%s\n", kblocks, path);
+    }
+}
+
+static off_t du_recursive(FAR struct nsh_vtbl_s *vtbl, FAR const char *path,
+                          FAR const struct stat *pst, unsigned int duflags,
+                          int printlimit, int depth)
+{
+  FAR struct dirent *entry;
+  FAR char *child;
+  struct stat st;
+  off_t total;
+  DIR *dp;
+
+  if (pst != NULL)
+    {
+      st = *pst;
+    }
+  else if (lstat(path, &st) < 0)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "stat", NSH_ERRNO);
+      return 0;
+    }
+
+  /* st_size not st_blocks: units differ (NuttX FS=st_blksize, hostfs=512) */
+
+  total = st.st_size;
+
+  /* A file argument (depth 0) is always shown; nested files need -a. */
+
+  if (!S_ISDIR(st.st_mode))
+    {
+      if (depth == 0 ||
+          ((duflags & DU_FLAG_ALL) != 0 && depth <= printlimit))
+        {
+          du_print(vtbl, path, total, duflags);
+        }
+
+      return total;
+    }
+
+  dp = opendir(path);
+  if (dp == NULL)
+    {
+      nsh_error(vtbl, g_fmtcmdfailed, "du", "opendir", NSH_ERRNO);
+    }
+  else
+    {
+      while ((entry = readdir(dp)) != NULL)
+        {
+          if (strcmp(entry->d_name, ".") == 0 ||
+              strcmp(entry->d_name, "..") == 0)
+            {
+              continue;
+            }
+
+          child = nsh_getdirpath(vtbl, path, entry->d_name);
+          if (child == NULL)
+            {
+              nsh_error(vtbl, g_fmtcmdfailed, "du", "nsh_getdirpath",
+                        NSH_ERRNO);
+              continue;
+            }
+
+          total += du_recursive(vtbl, child, NULL, duflags, printlimit,
+                                depth + 1);
+          free(child);
+        }
+
+      closedir(dp);
+    }
+
+  /* Print this directory's cumulative total unless suppressed by -s/-d. */
+
+  if (depth <= printlimit)
+    {
+      du_print(vtbl, path, total, duflags);
+    }
+
+  return total;
+}
+#endif
+
+/****************************************************************************
+ * Name: cmd_du
+ ****************************************************************************/
+
+#ifndef CONFIG_NSH_DISABLE_DU
+int cmd_du(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char **argv)
+{
+  unsigned int duflags = 0;

Review Comment:
   ```suggestion
     unsigned int flags = 0;
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to