#define STRBUF_SIZEOF(t) (1 + CHAR_BIT * sizeof(t) / 3 + 1)
static void display(FTSENT *, FTSENT *);
-static u_quad_t makenines(u_long);
-static int mastercmp(const FTSENT * const *, const FTSENT * const *);
+static u_quad_t makenines(u_quad_t);
+static int mastercmp(const FTSENT **, const FTSENT **);
static void traverse(int, char **, int);
static void (*printfcn)(DISPLAY *);
/* flags */
int f_accesstime; /* use time of last access */
+ int f_birthtime; /* use time of file birth */
int f_flags; /* show flags associated with a file */
int f_humanval; /* show human-readable file sizes */
int f_inode; /* print inode */
int f_nonprint; /* show unprintables as ? */
static int f_nosort; /* don't sort output */
int f_notabs; /* don't use tab-separated multi-col output */
-static int f_numericonly; /* don't convert uid/gid to name */
+ int f_numericonly; /* don't convert uid/gid to name */
int f_octal; /* show unprintables as \xxx */
int f_octal_escape; /* like f_octal but use C escapes if possible */
static int f_recursive; /* ls subdirectories also */
int f_type; /* add type character for non-regular files */
static int f_whiteout; /* show whiteout entries */
int f_acl; /* show ACLs in long listing */
+ int f_xattr; /* show extended attributes in long listing */
int f_group; /* show group */
+ int f_owner; /* show owner */
#ifdef COLORLS
int f_color; /* add type in color for non-regular files */
char *bp = tcapbuf;
#endif
+ if (argc < 1)
+ usage();
(void)setlocale(LC_ALL, "");
/* Terminal defaults to -Cq, non-terminal defaults to -1. */
f_listdot = 1;
fts_options = FTS_PHYSICAL;
- while ((ch = getopt(argc, argv, "1ABCFGHLPRSTWabcdefghiklmnopqrstuvwx"))
+ while ((ch = getopt(argc, argv, "1@ABCFGHLOPRSTUWabcdefghiklmnopqrstuvwx"))
!= -1) {
switch (ch) {
/*
/* The -c and -u options override each other. */
case 'c':
f_statustime = 1;
- f_accesstime = 0;
+ f_accesstime = f_birthtime = 0;
break;
case 'u':
f_accesstime = 1;
- f_statustime = 0;
+ f_statustime = f_birthtime = 0;
+ break;
+ case 'U':
+ f_birthtime = 1;
+ f_statustime = f_accesstime = 0;
break;
case 'F':
f_type = 1;
f_slash = 0;
break;
case 'H':
- fts_options |= FTS_COMFOLLOW;
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ fts_options &= ~FTS_LOGICAL;
+ fts_options |= FTS_PHYSICAL;
+ fts_options |= FTS_COMFOLLOWDIR;
+ } else
+ fts_options |= FTS_COMFOLLOW;
break;
case 'G':
setenv("CLICOLOR", "", 1);
case 'L':
fts_options &= ~FTS_PHYSICAL;
fts_options |= FTS_LOGICAL;
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ fts_options &= ~(FTS_COMFOLLOW|FTS_COMFOLLOWDIR);
+ }
break;
case 'P':
- fts_options &= ~FTS_COMFOLLOW;
+ fts_options &= ~(FTS_COMFOLLOW|FTS_COMFOLLOWDIR);
fts_options &= ~FTS_LOGICAL;
fts_options |= FTS_PHYSICAL;
break;
break;
case 'f':
f_nosort = 1;
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ fts_options |= FTS_SEEDOT;
+ f_listdot = 1;
+ }
break;
case 'g': /* Compatibility with Unix03 */
if (COMPAT_MODE("bin/ls", "Unix2003")) {
break;
case 'n':
f_numericonly = 1;
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ f_longform = 1;
+ f_singlecol = 0;
+ f_stream = 0;
+ }
break;
case 'o':
- f_flags = 1;
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ f_owner = 1;
+ f_longform = 1;
+ f_singlecol = 0;
+ f_stream = 0;
+ } else {
+ f_flags = 1;
+ }
break;
case 'p':
f_slash = 1;
case 'e':
f_acl = 1;
break;
+ case '@':
+ f_xattr = 1;
+ break;
+ case 'O':
+ f_flags = 1;
+ break;
default:
case '?':
usage();
* If not -F, -d or -l options, follow any symbolic links listed on
* the command line.
*/
- if (!f_longform && !f_listdir && !f_type)
+ if (!f_longform && !f_listdir && !f_type && !f_inode)
fts_options |= FTS_COMFOLLOW;
/*
sortfcn = revacccmp;
else if (f_statustime)
sortfcn = revstatcmp;
+ else if (f_birthtime)
+ sortfcn = revbirthcmp;
else /* Use modification time. */
sortfcn = revmodcmp;
} else {
sortfcn = acccmp;
else if (f_statustime)
sortfcn = statcmp;
+ else if (f_birthtime)
+ sortfcn = birthcmp;
else /* Use modification time. */
sortfcn = modcmp;
}
{
FTS *ftsp;
FTSENT *p, *chp;
- int ch_options;
+ int ch_options, error;
if ((ftsp =
fts_open(argv, options, f_nosort ? NULL : mastercmp)) == NULL)
err(1, "fts_open");
display(NULL, fts_children(ftsp, 0));
- if (f_listdir)
+ if (f_listdir) {
+ fts_close(ftsp);
return;
+ }
/*
* If not recursing down this tree and don't need stat info, just get
switch (p->fts_info) {
case FTS_DC:
warnx("%s: directory causes a cycle", p->fts_name);
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ rval = 1;
+ }
break;
case FTS_DNR:
case FTS_ERR:
output = 1;
}
chp = fts_children(ftsp, ch_options);
+ if (COMPAT_MODE("bin/ls", "Unix2003") && ((options & FTS_LOGICAL)!=0)) {
+ FTSENT *curr;
+ for (curr = chp; curr; curr = curr->fts_link) {
+ if (curr->fts_info == FTS_SLNONE)
+ curr->fts_number = NO_PRINT;
+ }
+ }
display(p, chp);
if (!f_recursive && chp != NULL)
(void)fts_set(ftsp, p, FTS_SKIP);
break;
+ case FTS_SLNONE: /* Same as default unless Unix conformance */
+ if (COMPAT_MODE("bin/ls", "Unix2003")) {
+ if ((options & FTS_LOGICAL)!=0) { /* -L was specified */
+ warnx("%s: %s", p->fts_name, strerror(p->fts_errno ?: ENOENT));
+ rval = 1;
+ }
+ }
+ break;
default:
break;
}
+ error = errno;
+ fts_close(ftsp);
+ errno = error;
+
if (errno)
err(1, "fts_read");
}
NAMES *np;
off_t maxsize;
u_int64_t btotal, maxblock;
- u_long lattrlen, maxinode, maxlen, maxnlink, maxlattr;
+ u_long lattrlen, maxlen, maxnlink, maxlattr;
+ ino_t maxinode;
int bcfile, maxflags;
gid_t maxgroup;
uid_t maxuser;
return;
needstats = f_inode || f_longform || f_size;
- flen = 0;
btotal = 0;
initmax = getenv("LS_COLWIDTHS");
/* Fields match -lios order. New ones should be added at the end. */
strcpy(initmax2, "0");
ninitmax = sscanf(jinitmax,
+#if _DARWIN_FEATURE_64_BIT_INODE
+ " %llu : %qu : %lu : %i : %i : %i : %qu : %lu : %lu ",
+#else
" %lu : %qu : %lu : %i : %i : %i : %qu : %lu : %lu ",
+#endif
&maxinode, &maxblock, &maxnlink, &maxuser,
&maxgroup, &maxflags, &maxsize, &maxlen, &maxlattr);
f_notabs = 1;
d.s_flags = maxflags;
d.s_lattr = maxlattr;
d.s_group = maxgroup;
+#if _DARWIN_FEATURE_64_BIT_INODE
+ (void)snprintf(buf, sizeof(buf), "%llu", maxinode);
+#else
(void)snprintf(buf, sizeof(buf), "%lu", maxinode);
+#endif
d.s_inode = strlen(buf);
(void)snprintf(buf, sizeof(buf), "%lu", maxnlink);
d.s_nlink = strlen(buf);
* All other levels use the sort function. Error entries remain unsorted.
*/
static int
-mastercmp(const FTSENT * const *a, const FTSENT * const *b)
+mastercmp(const FTSENT **a, const FTSENT **b)
{
int a_info, b_info;
* into a number that wide in decimal.
*/
static u_quad_t
-makenines(u_long n)
+makenines(u_quad_t n)
{
u_long i;
u_quad_t reg;