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