File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 #ifdef HAVE_CONFIG_H
0036 #include "config.h"
0037 #endif
0038
0039 #if 0
0040 #include <sys/cdefs.h>
0041 #ifndef lint
0042 __COPYRIGHT("@(#) Copyright (c) 1989, 1993, 1994\n\
0043 The Regents of the University of California. All rights reserved.\n");
0044 #endif
0045
0046 #ifndef lint
0047 #if 0
0048 static char sccsid[] = "@(#)ls.c 8.7 (Berkeley) 8/5/94";
0049 #else
0050 __RCSID("$NetBSD: ls.c,v 1.58 2005/10/26 02:24:22 jschauma Exp $");
0051 #endif
0052 #endif
0053 #endif
0054
0055 #include <rtems.h>
0056 #include <rtems/shell.h>
0057 #include <rtems/shellconfig.h>
0058 #define __need_getopt_newlib
0059 #include <getopt.h>
0060
0061 #include <sys/param.h>
0062 #include <sys/types.h>
0063 #include <sys/stat.h>
0064 #include <sys/ioctl.h>
0065
0066 #include <dirent.h>
0067 #include "err.h"
0068 #include <errno.h>
0069 #include "fts.h"
0070 #include <locale.h>
0071 #include <stdio.h>
0072 #include <stdlib.h>
0073 #include <string.h>
0074 #include <unistd.h>
0075 #include <termios.h>
0076 #include <pwd.h>
0077 #include <grp.h>
0078
0079 #include "internal.h"
0080 #include "extern-ls.h"
0081
0082 static void display(rtems_shell_ls_globals* globals, FTSENT *, FTSENT *);
0083 static int mastercmp_listdir(const FTSENT **, const FTSENT **);
0084 static int mastercmp_no_listdir(const FTSENT **, const FTSENT **);
0085 static void traverse(rtems_shell_ls_globals* globals, int, char **, int);
0086
0087 static void (*printfcn)(rtems_shell_ls_globals* globals, DISPLAY *);
0088 static int (*sortfcn)(const FTSENT *, const FTSENT *);
0089
0090 #define BY_NAME 0
0091 #define BY_SIZE 1
0092 #define BY_TIME 2
0093
0094 #if RTEMS_REMOVED
0095 long blocksize;
0096 int termwidth = 80;
0097 int sortkey = BY_NAME;
0098 int rval = EXIT_SUCCESS;
0099
0100
0101 int f_accesstime;
0102 int f_column;
0103 int f_columnacross;
0104 int f_flags;
0105 int f_grouponly;
0106 int f_humanize;
0107 int f_inode;
0108 int f_listdir;
0109 int f_listdot;
0110 int f_longform;
0111 int f_nonprint;
0112 int f_nosort;
0113 int f_numericonly;
0114 int f_octal;
0115 int f_octal_escape;
0116 int f_recursive;
0117 int f_reversesort;
0118 int f_sectime;
0119 int f_singlecol;
0120 int f_size;
0121 int f_statustime;
0122 int f_stream;
0123 int f_type;
0124 int f_typedir;
0125 int f_whiteout;
0126 #endif
0127
0128 void
0129 rtems_shell_ls_exit (rtems_shell_ls_globals* globals, int code)
0130 {
0131 globals->exit_code = code;
0132 longjmp (globals->exit_jmp, 1);
0133 }
0134
0135 static int main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[]);
0136
0137 static int rtems_shell_main_ls(int argc, char *argv[])
0138 {
0139 rtems_shell_ls_globals ls_globals;
0140 rtems_shell_ls_globals* globals = &ls_globals;
0141 memset (globals, 0, sizeof (ls_globals));
0142 termwidth = 80;
0143 sortkey = BY_NAME;
0144 rval = EXIT_SUCCESS;
0145 ls_globals.exit_code = 1;
0146 if (setjmp (ls_globals.exit_jmp) == 0)
0147 return main_ls (globals, argc, argv);
0148 return ls_globals.exit_code;
0149 }
0150
0151 int
0152 main_ls(rtems_shell_ls_globals* globals, int argc, char *argv[])
0153 {
0154 static char dot[] = ".", *dotav[] = { dot, NULL };
0155
0156 int ch, fts_options;
0157 #if RTEMS_REMOVED
0158 int kflag = 0;
0159 #endif
0160 const char *p;
0161
0162 struct getopt_data getopt_reent;
0163 memset(&getopt_reent, 0, sizeof(getopt_data));
0164
0165 #if RTEMS_REMOVED
0166 setprogname(argv[0]);
0167 #endif
0168 setlocale(LC_ALL, "");
0169
0170
0171 if (isatty(STDOUT_FILENO)) {
0172 #if RTEMS_REMOVED
0173 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) == 0 &&
0174 win.ws_col > 0)
0175 termwidth = win.ws_col;
0176 f_column = f_nonprint = 1;
0177 #endif
0178 } else
0179 f_singlecol = 1;
0180
0181
0182 if (!getuid())
0183 f_listdot = 1;
0184
0185 fts_options = FTS_PHYSICAL;
0186 while ((ch = getopt_r(argc, argv,
0187 "1ABCFLRSTWabcdfghiklmnopqrstuwx", &getopt_reent)) != -1) {
0188 switch (ch) {
0189
0190
0191
0192
0193 case '1':
0194 f_singlecol = 1;
0195 f_column = f_columnacross = f_longform = f_stream = 0;
0196 break;
0197 case 'C':
0198 f_column = 1;
0199 f_columnacross = f_longform = f_singlecol = f_stream =
0200 0;
0201 break;
0202 case 'g':
0203 if (f_grouponly != -1)
0204 f_grouponly = 1;
0205 f_longform = 1;
0206 f_column = f_columnacross = f_singlecol = f_stream = 0;
0207 break;
0208 case 'l':
0209 f_longform = 1;
0210 f_column = f_columnacross = f_singlecol = f_stream = 0;
0211
0212 f_grouponly = -1;
0213 break;
0214 case 'm':
0215 f_stream = 1;
0216 f_column = f_columnacross = f_longform = f_singlecol =
0217 0;
0218 break;
0219 case 'x':
0220 f_columnacross = 1;
0221 f_column = f_longform = f_singlecol = f_stream = 0;
0222 break;
0223
0224 case 'c':
0225 f_statustime = 1;
0226 f_accesstime = 0;
0227 break;
0228 case 'u':
0229 f_accesstime = 1;
0230 f_statustime = 0;
0231 break;
0232 case 'F':
0233 f_type = 1;
0234 break;
0235 case 'L':
0236 fts_options &= ~FTS_PHYSICAL;
0237 fts_options |= FTS_LOGICAL;
0238 break;
0239 case 'R':
0240 f_recursive = 1;
0241 break;
0242 case 'a':
0243 fts_options |= FTS_SEEDOT;
0244
0245 case 'A':
0246 f_listdot = 1;
0247 break;
0248
0249 case 'B':
0250 f_nonprint = 0;
0251 f_octal = 1;
0252 f_octal_escape = 0;
0253 break;
0254
0255 case 'b':
0256 f_nonprint = 0;
0257 f_octal = 0;
0258 f_octal_escape = 1;
0259 break;
0260
0261 case 'd':
0262 f_listdir = 1;
0263 f_recursive = 0;
0264 break;
0265 case 'f':
0266 f_nosort = 1;
0267 break;
0268 case 'i':
0269 f_inode = 1;
0270 break;
0271 case 'k':
0272 blocksize = 1024;
0273 #if RTEMS_REMOVED
0274 kflag = 1;
0275 #endif
0276 break;
0277
0278 case 'h':
0279 f_humanize = 1;
0280 break;
0281 case 'n':
0282 f_numericonly = 1;
0283 break;
0284 case 'o':
0285 f_flags = 1;
0286 break;
0287 case 'p':
0288 f_typedir = 1;
0289 break;
0290
0291 case 'q':
0292 f_nonprint = 1;
0293 f_octal = 0;
0294 f_octal_escape = 0;
0295 break;
0296 case 'r':
0297 f_reversesort = 1;
0298 break;
0299 case 'S':
0300 sortkey = BY_SIZE;
0301 break;
0302 case 's':
0303 f_size = 1;
0304 break;
0305 case 'T':
0306 f_sectime = 1;
0307 break;
0308 case 't':
0309 sortkey = BY_TIME;
0310 break;
0311 case 'W':
0312 f_whiteout = 1;
0313 break;
0314
0315 case 'w':
0316 f_nonprint = 0;
0317 f_octal = 0;
0318 f_octal_escape = 0;
0319 break;
0320 default:
0321 case '?':
0322 usage(globals);
0323 }
0324 }
0325 argc -= getopt_reent.optind;
0326 argv += getopt_reent.optind;
0327
0328 if (f_column || f_columnacross || f_stream) {
0329 if ((p = getenv("COLUMNS")) != NULL)
0330 termwidth = atoi(p);
0331 }
0332
0333
0334
0335
0336 if (f_grouponly == -1)
0337 f_grouponly = 0;
0338
0339
0340
0341
0342
0343 if (!f_inode && !f_longform && !f_size && !f_type && !f_typedir &&
0344 sortkey == BY_NAME)
0345 fts_options |= FTS_NOSTAT;
0346
0347
0348
0349
0350
0351 if (!f_longform && !f_listdir && !f_type)
0352 fts_options |= FTS_COMFOLLOW;
0353
0354
0355
0356
0357 #ifdef FTS_WHITEOUT
0358 if (f_whiteout)
0359 fts_options |= FTS_WHITEOUT;
0360 #endif
0361
0362
0363 if (f_inode || f_longform || f_size) {
0364 #if RTEMS_REMOVED
0365 if (!kflag)
0366 (void)getbsize(NULL, &blocksize);
0367 #else
0368
0369 blocksize = 512;
0370 #endif
0371 blocksize /= 512;
0372 }
0373
0374
0375 if (f_reversesort) {
0376 switch (sortkey) {
0377 case BY_NAME:
0378 sortfcn = revnamecmp;
0379 break;
0380 case BY_SIZE:
0381 sortfcn = revsizecmp;
0382 break;
0383 case BY_TIME:
0384 if (f_accesstime)
0385 sortfcn = revacccmp;
0386 else if (f_statustime)
0387 sortfcn = revstatcmp;
0388 else
0389 sortfcn = revmodcmp;
0390 break;
0391 }
0392 } else {
0393 switch (sortkey) {
0394 case BY_NAME:
0395 sortfcn = namecmp;
0396 break;
0397 case BY_SIZE:
0398 sortfcn = sizecmp;
0399 break;
0400 case BY_TIME:
0401 if (f_accesstime)
0402 sortfcn = acccmp;
0403 else if (f_statustime)
0404 sortfcn = statcmp;
0405 else
0406 sortfcn = modcmp;
0407 break;
0408 }
0409 }
0410
0411
0412 if (f_singlecol)
0413 printfcn = printscol;
0414 else if (f_columnacross)
0415 printfcn = printacol;
0416 else if (f_longform)
0417 printfcn = printlong;
0418 else if (f_stream)
0419 printfcn = printstream;
0420 else
0421 printfcn = printcol;
0422
0423 if (argc)
0424 traverse(globals, argc, argv, fts_options);
0425 else
0426 traverse(globals, 1, dotav, fts_options);
0427 exit(rval);
0428
0429 return 0;
0430 }
0431
0432 #if RTEMS_REMOVED
0433 static int output;
0434 #endif
0435
0436
0437
0438
0439
0440
0441
0442 static void
0443 traverse(rtems_shell_ls_globals* globals, int argc, char *argv[], int options)
0444 {
0445 FTS *ftsp;
0446 FTSENT *p, *chp;
0447 int ch_options;
0448
0449 if ((ftsp =
0450 fts_open(argv, options,
0451 f_nosort ? NULL : f_listdir ?
0452 mastercmp_listdir : mastercmp_no_listdir)) == NULL)
0453 err(exit_jump, EXIT_FAILURE, NULL);
0454
0455 display(globals, NULL, fts_children(ftsp, 0));
0456 if (f_listdir)
0457 {
0458 fts_close(ftsp);
0459 return;
0460 }
0461
0462
0463
0464
0465
0466 ch_options = !f_recursive && options & FTS_NOSTAT ? FTS_NAMEONLY : 0;
0467
0468 while ((p = fts_read(ftsp)) != NULL)
0469 switch (p->fts_info) {
0470 case FTS_DC:
0471 warnx("%s: directory causes a cycle", p->fts_name);
0472 break;
0473 case FTS_DNR:
0474 case FTS_ERR:
0475 warnx("%s: %s", p->fts_name, strerror(p->fts_errno));
0476 rval = EXIT_FAILURE;
0477 break;
0478 case FTS_D:
0479 if (p->fts_level != FTS_ROOTLEVEL &&
0480 p->fts_name[0] == '.' && !f_listdot)
0481 break;
0482
0483
0484
0485
0486
0487
0488 if (output)
0489 (void)printf("\n%s:\n", p->fts_path);
0490 else if (argc > 1) {
0491 (void)printf("%s:\n", p->fts_path);
0492 output = 1;
0493 }
0494
0495 chp = fts_children(ftsp, ch_options);
0496 display(globals, p, chp);
0497
0498 if (!f_recursive && chp != NULL)
0499 (void)fts_set(ftsp, p, FTS_SKIP);
0500 break;
0501 }
0502 fts_close(ftsp);
0503 if (errno)
0504 err(exit_jump, EXIT_FAILURE, "fts_read");
0505 }
0506
0507
0508
0509
0510
0511
0512 static void
0513 display(rtems_shell_ls_globals* globals, FTSENT *p, FTSENT *list)
0514 {
0515 struct stat *sp;
0516 DISPLAY d;
0517 FTSENT *cur;
0518 NAMES *np;
0519 u_int64_t btotal, stotal, maxblock, maxsize;
0520 int maxinode, maxnlink, maxmajor, maxminor;
0521 int bcfile, entries, flen, glen, ulen, maxflags, maxgroup, maxlen;
0522 int maxuser, needstats;
0523 const char *user, *group;
0524 char buf[21];
0525 char nuser[12], ngroup[12];
0526 char *flags = NULL;
0527
0528 #ifdef __GNUC__
0529
0530 (void) &maxsize;
0531 #endif
0532
0533
0534
0535
0536
0537
0538
0539
0540 if (list == NULL)
0541 return;
0542
0543 needstats = f_inode || f_longform || f_size;
0544 flen = 0;
0545 maxinode = maxnlink = 0;
0546 bcfile = 0;
0547 maxuser = maxgroup = maxflags = maxlen = 0;
0548 btotal = stotal = maxblock = maxsize = 0;
0549 maxmajor = maxminor = 0;
0550 for (cur = list, entries = 0; cur; cur = cur->fts_link) {
0551 uint64_t size;
0552 if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) {
0553 warnx("%s: %s",
0554 cur->fts_name, strerror(cur->fts_errno));
0555 cur->fts_number = NO_PRINT;
0556 rval = EXIT_FAILURE;
0557 continue;
0558 }
0559
0560
0561
0562
0563
0564 if (p == NULL) {
0565
0566 if (cur->fts_info == FTS_D && !f_listdir) {
0567 cur->fts_number = NO_PRINT;
0568 continue;
0569 }
0570 } else {
0571
0572 if (cur->fts_name[0] == '.' && !f_listdot) {
0573 cur->fts_number = NO_PRINT;
0574 continue;
0575 }
0576 }
0577 if (cur->fts_namelen > maxlen)
0578 maxlen = cur->fts_namelen;
0579 if (needstats) {
0580 sp = cur->fts_statp;
0581 if (sp->st_size < 0)
0582 size = sp->st_size * -1;
0583 else
0584 size = sp->st_size;
0585 if (sp->st_blocks > maxblock)
0586 maxblock = sp->st_blocks;
0587 if (sp->st_ino > maxinode)
0588 maxinode = sp->st_ino;
0589 if (sp->st_nlink > maxnlink)
0590 maxnlink = sp->st_nlink;
0591 if (size > maxsize)
0592 maxsize = size;
0593 if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) {
0594 bcfile = 1;
0595 if (major(sp->st_rdev) > maxmajor)
0596 maxmajor = major(sp->st_rdev);
0597 if (minor(sp->st_rdev) > maxminor)
0598 maxminor = minor(sp->st_rdev);
0599 }
0600
0601 btotal += sp->st_blocks;
0602 stotal += size;
0603 if (f_longform) {
0604 if (f_numericonly ||
0605 (user = user_from_uid(sp->st_uid, 0)) ==
0606 NULL) {
0607 (void)snprintf(nuser, sizeof(nuser),
0608 "%u", sp->st_uid);
0609 user = nuser;
0610 }
0611 if (f_numericonly ||
0612 (group = group_from_gid(sp->st_gid, 0)) ==
0613 NULL) {
0614 (void)snprintf(ngroup, sizeof(ngroup),
0615 "%u", sp->st_gid);
0616 group = ngroup;
0617 }
0618 if ((ulen = strlen(user)) > maxuser)
0619 maxuser = ulen;
0620 if ((glen = strlen(group)) > maxgroup)
0621 maxgroup = glen;
0622 #if RTEMS_REMOVED
0623 if (f_flags) {
0624 flags =
0625 flags_to_string(sp->st_flags, "-");
0626 if ((flen = strlen(flags)) > maxflags)
0627 maxflags = flen;
0628 } else
0629 #endif
0630 flen = 0;
0631
0632 if ((np = malloc(sizeof(NAMES) +
0633 ulen + glen + flen + 3)) == NULL)
0634 err(exit_jump, EXIT_FAILURE, NULL);
0635
0636 np->user = &np->data[0];
0637 (void)strcpy(np->user, user);
0638 np->group = &np->data[ulen + 1];
0639 (void)strcpy(np->group, group);
0640
0641 if (f_flags && flags) {
0642 np->flags = &np->data[ulen + glen + 2];
0643 (void)strcpy(np->flags, flags);
0644 }
0645 cur->fts_pointer = np;
0646 }
0647 }
0648 ++entries;
0649 }
0650
0651 if (!entries)
0652 return;
0653
0654 d.list = list;
0655 d.entries = entries;
0656 d.maxlen = maxlen;
0657 if (needstats) {
0658 d.btotal = btotal;
0659 d.stotal = stotal;
0660 if (f_humanize) {
0661 d.s_block = 4;
0662 } else {
0663 (void)snprintf(buf, sizeof(buf), "%llu",
0664 (unsigned long long)howmany(maxblock, blocksize));
0665 d.s_block = strlen(buf);
0666 }
0667 d.s_flags = maxflags;
0668 d.s_group = maxgroup;
0669 (void)snprintf(buf, sizeof(buf), "%u", maxinode);
0670 d.s_inode = strlen(buf);
0671 (void)snprintf(buf, sizeof(buf), "%u", maxnlink);
0672 d.s_nlink = strlen(buf);
0673 if (f_humanize) {
0674 d.s_size = 4;
0675 } else {
0676 (void)snprintf(buf, sizeof(buf), "%llu",
0677 (long long)maxsize);
0678 d.s_size = strlen(buf);
0679 }
0680 d.s_user = maxuser;
0681 if (bcfile) {
0682 (void)snprintf(buf, sizeof(buf), "%u", maxmajor);
0683 d.s_major = strlen(buf);
0684 (void)snprintf(buf, sizeof(buf), "%u", maxminor);
0685 d.s_minor = strlen(buf);
0686 if (d.s_major + d.s_minor + 2 > d.s_size)
0687 d.s_size = d.s_major + d.s_minor + 2;
0688 else if (d.s_size - d.s_minor - 2 > d.s_major)
0689 d.s_major = d.s_size - d.s_minor - 2;
0690 } else {
0691 d.s_major = 0;
0692 d.s_minor = 0;
0693 }
0694 }
0695
0696 printfcn(globals, &d);
0697 output = 1;
0698
0699 if (f_longform)
0700 for (cur = list; cur; cur = cur->fts_link)
0701 free(cur->fts_pointer);
0702 }
0703
0704
0705
0706
0707
0708
0709
0710 static int
0711 mastercmp_no_listdir(const FTSENT **a, const FTSENT **b)
0712 {
0713 int a_info, b_info;
0714 int l_f_listdir = 0;
0715
0716 a_info = (*a)->fts_info;
0717 if (a_info == FTS_ERR)
0718 return (0);
0719 b_info = (*b)->fts_info;
0720 if (b_info == FTS_ERR)
0721 return (0);
0722
0723 if (a_info == FTS_NS || b_info == FTS_NS) {
0724 if (b_info != FTS_NS)
0725 return (1);
0726 else if (a_info != FTS_NS)
0727 return (-1);
0728 else
0729 return (namecmp(*a, *b));
0730 }
0731
0732 if (a_info != b_info && !l_f_listdir &&
0733 (*a)->fts_level == FTS_ROOTLEVEL) {
0734 if (a_info == FTS_D)
0735 return (1);
0736 else if (b_info == FTS_D)
0737 return (-1);
0738 }
0739 return (sortfcn(*a, *b));
0740 }
0741
0742 static int
0743 mastercmp_listdir(const FTSENT **a, const FTSENT **b)
0744 {
0745 int a_info, b_info;
0746 int l_f_listdir = 1;
0747
0748 a_info = (*a)->fts_info;
0749 if (a_info == FTS_ERR)
0750 return (0);
0751 b_info = (*b)->fts_info;
0752 if (b_info == FTS_ERR)
0753 return (0);
0754
0755 if (a_info == FTS_NS || b_info == FTS_NS) {
0756 if (b_info != FTS_NS)
0757 return (1);
0758 else if (a_info != FTS_NS)
0759 return (-1);
0760 else
0761 return (namecmp(*a, *b));
0762 }
0763
0764 if (a_info != b_info && !l_f_listdir &&
0765 (*a)->fts_level == FTS_ROOTLEVEL) {
0766 if (a_info == FTS_D)
0767 return (1);
0768 else if (b_info == FTS_D)
0769 return (-1);
0770 }
0771 return (sortfcn(*a, *b));
0772 }
0773
0774 rtems_shell_cmd_t rtems_shell_LS_Command = {
0775 "ls",
0776 "ls [dir] # list files in the directory",
0777 "files",
0778 rtems_shell_main_ls,
0779 NULL,
0780 NULL
0781 };