static int ls_handler()

in nshlib/nsh_fscmds.c [350:598]


static int ls_handler(FAR struct nsh_vtbl_s *vtbl, FAR const char *dirpath,
                      FAR struct dirent *entryp, FAR void *pvarg)
{
  unsigned int lsflags = (unsigned int)((uintptr_t)pvarg);
#ifdef CONFIG_PSEUDOFS_SOFTLINKS
  bool isdir = false;
#endif
  int ret;

  /* Check if any options will require that we stat the file */

  if ((lsflags & (LSFLAGS_SIZE | LSFLAGS_LONG | LSFLAGS_UID_GID)) != 0)
    {
      struct stat buf;

      memset(&buf, 0, sizeof(struct stat));

      /* stat the file */

      if (entryp != NULL)
        {
          FAR char *fullpath = nsh_getdirpath(vtbl, dirpath, entryp->d_name);
          ret = stat(fullpath, &buf);
          free(fullpath);
        }
      else
        {
          /* NULL entry signifies that we are running ls on a single file */

          ret = stat(dirpath, &buf);
        }

      if (ret != 0)
        {
          nsh_error(vtbl, g_fmtcmdfailed, "ls", "stat", NSH_ERRNO);
          return ERROR;
        }

      if ((lsflags & LSFLAGS_LONG) != 0)
        {
          char details[] = "----------";

#ifdef CONFIG_PSEUDOFS_SOFTLINKS
          if (S_ISLNK(buf.st_mode))
            {
              details[0] = 'l';  /* Takes precedence over type of the target */
              isdir = S_ISDIR(buf.st_mode);
            }
          else
#endif
          if (S_ISBLK(buf.st_mode))
            {
              details[0] = 'b';
            }
          else if (S_ISCHR(buf.st_mode))
            {
              details[0] = 'c';
            }
          else if (S_ISDIR(buf.st_mode))
            {
              details[0] = 'd';
            }
#ifdef CONFIG_MTD
          else if (S_ISMTD(buf.st_mode))
            {
              details[0] = 'f';
            }
#endif
#ifdef CONFIG_FS_SHMFS
          else if (S_ISSHM(buf.st_mode))
            {
              details[0] = 'h';
            }
#endif
#ifndef CONFIG_DISABLE_MQUEUE
          else if (S_ISMQ(buf.st_mode))
            {
              details[0] = 'm';
            }
#endif
#ifdef CONFIG_NET
          else if (S_ISSOCK(buf.st_mode))
            {
              details[0] = 'n';
            }
#endif
#ifdef CONFIG_FS_NAMED_SEMAPHORES
          else if (S_ISSEM(buf.st_mode))
            {
              details[0] = 's';
            }
#endif
          else if (!S_ISREG(buf.st_mode))
            {
              details[0] = '?';
            }

          if ((buf.st_mode & S_IRUSR) != 0)
            {
              details[1] = 'r';
            }

          if ((buf.st_mode & S_IWUSR) != 0)
            {
              details[2] = 'w';
            }

          if ((buf.st_mode & S_IXUSR) != 0 && (buf.st_mode & S_ISUID) != 0)
            {
              details[3] = 's';
            }
          else if ((buf.st_mode & S_ISUID) != 0)
            {
              details[3] = 'S';
            }
          else if ((buf.st_mode & S_IXUSR) != 0)
            {
              details[3] = 'x';
            }

          if ((buf.st_mode & S_IRGRP) != 0)
            {
              details[4] = 'r';
            }

          if ((buf.st_mode & S_IWGRP) != 0)
            {
              details[5] = 'w';
            }

          if ((buf.st_mode & S_IXGRP) != 0 && (buf.st_mode & S_ISGID) != 0)
            {
              details[6] = 's';
            }
          else if ((buf.st_mode & S_ISGID) != 0)
            {
              details[6] = 'S';
            }
          else if ((buf.st_mode & S_IXGRP) != 0)
            {
              details[6] = 'x';
            }

          if ((buf.st_mode & S_IROTH) != 0)
            {
              details[7] = 'r';
            }

          if ((buf.st_mode & S_IWOTH) != 0)
            {
              details[8] = 'w';
            }

          if ((buf.st_mode & S_IXOTH) != 0)
            {
              details[9] = 'x';
            }

          nsh_output(vtbl, " %s", details);
        }

#ifdef CONFIG_SCHED_USER_IDENTITY
      if ((lsflags & LSFLAGS_UID_GID) != 0)
        {
          nsh_output(vtbl, "%8d", buf.st_uid);
          nsh_output(vtbl, "%8d", buf.st_gid);
        }
#endif

      if ((lsflags & LSFLAGS_SIZE) != 0)
        {
#ifdef CONFIG_HAVE_FLOAT
          if (lsflags & LSFLAGS_HUMANREADBLE && buf.st_size >= KB)
            {
              if (buf.st_size >= GB)
                {
                  nsh_output(vtbl, "%11.1fG", (float)buf.st_size / GB);
                }
              else if (buf.st_size >= MB)
                {
                  nsh_output(vtbl, "%11.1fM", (float)buf.st_size / MB);
                }
              else
                {
                  nsh_output(vtbl, "%11.1fK", (float)buf.st_size / KB);
                }
            }
          else
#endif
            {
              nsh_output(vtbl, "%12" PRIdOFF, buf.st_size);
            }
        }
    }

  /* Then provide the filename that is common to normal and verbose output */

  if (entryp != NULL)
    {
      nsh_output(vtbl, " %s", entryp->d_name);

#ifdef CONFIG_PSEUDOFS_SOFTLINKS
      if (DIRENT_ISLINK(entryp->d_type))
        {
          FAR char *fullpath;
          ssize_t len;

          /* Get the target of the symbolic link */

          fullpath = nsh_getdirpath(vtbl, dirpath, entryp->d_name);
          len = readlink(fullpath, vtbl->iobuffer, IOBUFFERSIZE);
          free(fullpath);

          if (len < 0)
            {
              nsh_error(vtbl, g_fmtcmdfailed, "ls", "readlink", NSH_ERRNO);
              return ERROR;
            }

          if (isdir)
            {
              nsh_output(vtbl, "/ ->%s\n", vtbl->iobuffer);
            }
          else
            {
              nsh_output(vtbl, " ->%s\n", vtbl->iobuffer);
            }
        }
      else
#endif
      if (DIRENT_ISDIRECTORY(entryp->d_type) &&
          !ls_specialdir(entryp->d_name))
        {
          nsh_output(vtbl, "/\n");
        }
      else
        {
          nsh_output(vtbl, "\n");
        }
    }
  else
    {
      /* A single file */

      nsh_output(vtbl, " %s\n", dirpath);
    }

  return OK;
}