1 /* 'dir', 'vdir' and 'ls' directory listing programs for GNU.
2    Copyright (C) 1985-2023 Free Software Foundation, Inc.
3 
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
16 
17 /* If ls_mode is LS_MULTI_COL,
18    the multi-column format is the default regardless
19    of the type of output device.
20    This is for the 'dir' program.
21 
22    If ls_mode is LS_LONG_FORMAT,
23    the long format is the default regardless of the
24    type of output device.
25    This is for the 'vdir' program.
26 
27    If ls_mode is LS_LS,
28    the output format depends on whether the output
29    device is a terminal.
30    This is for the 'ls' program.  */
31 
32 /* Written by Richard Stallman and David MacKenzie.  */
33 
34 /* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
35    Flaherty <dennisf@denix.elk.miles.com> based on original patches by
36    Greg Lee <lee@uhunix.uhcc.hawaii.edu>.  */
37 
38 #include <config.h>
39 #include <sys/types.h>
40 
41 #include <termios.h>
42 #if HAVE_STROPTS_H
43 # include <stropts.h>
44 #endif
45 #include <sys/ioctl.h>
46 
47 #ifdef WINSIZE_IN_PTEM
48 # include <sys/stream.h>
49 # include <sys/ptem.h>
50 #endif
51 
52 #include <stdio.h>
53 #include <setjmp.h>
54 #include <pwd.h>
55 #include <getopt.h>
56 #include <signal.h>
57 #include <selinux/selinux.h>
58 #include <uchar.h>
59 
60 #if HAVE_LANGINFO_CODESET
61 # include <langinfo.h>
62 #endif
63 
64 /* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is
65    present.  */
66 #ifndef SA_NOCLDSTOP
67 # define SA_NOCLDSTOP 0
68 # define sigprocmask(How, Set, Oset) /* empty */
69 # define sigset_t int
70 # if ! HAVE_SIGINTERRUPT
71 #  define siginterrupt(sig, flag) /* empty */
72 # endif
73 #endif
74 
75 /* NonStop circa 2011 lacks both SA_RESTART and siginterrupt, so don't
76    restart syscalls after a signal handler fires.  This may cause
77    colors to get messed up on the screen if 'ls' is interrupted, but
78    that's the best we can do on such a platform.  */
79 #ifndef SA_RESTART
80 # define SA_RESTART 0
81 #endif
82 
83 #include "system.h"
84 #include <fnmatch.h>
85 
86 #include "acl.h"
87 #include "argmatch.h"
88 #include "assure.h"
89 #include "c-strcase.h"
90 #include "dev-ino.h"
91 #include "filenamecat.h"
92 #include "hard-locale.h"
93 #include "hash.h"
94 #include "human.h"
95 #include "filemode.h"
96 #include "filevercmp.h"
97 #include "idcache.h"
98 #include "ls.h"
99 #include "mbswidth.h"
100 #include "mpsort.h"
101 #include "obstack.h"
102 #include "quote.h"
103 #include "smack.h"
104 #include "stat-size.h"
105 #include "stat-time.h"
106 #include "strftime.h"
107 #include "xdectoint.h"
108 #include "xstrtol.h"
109 #include "xstrtol-error.h"
110 #include "areadlink.h"
111 #include "dircolors.h"
112 #include "xgethostname.h"
113 #include "c-ctype.h"
114 #include "canonicalize.h"
115 #include "statx.h"
116 
117 /* Include <sys/capability.h> last to avoid a clash of <sys/types.h>
118    include guards with some premature versions of libcap.
119    For more details, see <https://bugzilla.redhat.com/483548>.  */
120 #ifdef HAVE_CAP
121 # include <sys/capability.h>
122 #endif
123 
124 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
125                       : (ls_mode == LS_MULTI_COL \
126                          ? "dir" : "vdir"))
127 
128 #define AUTHORS \
129   proper_name ("Richard M. Stallman"), \
130   proper_name ("David MacKenzie")
131 
132 #define obstack_chunk_alloc malloc
133 #define obstack_chunk_free free
134 
135 /* Unix-based readdir implementations have historically returned a dirent.d_ino
136    value that is sometimes not equal to the stat-obtained st_ino value for
137    that same entry.  This error occurs for a readdir entry that refers
138    to a mount point.  readdir's error is to return the inode number of
139    the underlying directory -- one that typically cannot be stat'ed, as
140    long as a file system is mounted on that directory.  RELIABLE_D_INO
141    encapsulates whether we can use the more efficient approach of relying
142    on readdir-supplied d_ino values, or whether we must incur the cost of
143    calling stat or lstat to obtain each guaranteed-valid inode number.  */
144 
145 #ifndef READDIR_LIES_ABOUT_MOUNTPOINT_D_INO
146 # define READDIR_LIES_ABOUT_MOUNTPOINT_D_INO 1
147 #endif
148 
149 #if READDIR_LIES_ABOUT_MOUNTPOINT_D_INO
150 # define RELIABLE_D_INO(dp) NOT_AN_INODE_NUMBER
151 #else
152 # define RELIABLE_D_INO(dp) D_INO (dp)
153 #endif
154 
155 #if ! HAVE_STRUCT_STAT_ST_AUTHOR
156 # define st_author st_uid
157 #endif
158 
159 enum filetype
160   {
161     unknown,
162     fifo,
163     chardev,
164     directory,
165     blockdev,
166     normal,
167     symbolic_link,
168     sock,
169     whiteout,
170     arg_directory
171   };
172 
173 /* Display letters and indicators for each filetype.
174    Keep these in sync with enum filetype.  */
175 static char const filetype_letter[] = "?pcdb-lswd";
176 
177 /* Ensure that filetype and filetype_letter have the same
178    number of elements.  */
179 static_assert (sizeof filetype_letter - 1 == arg_directory + 1);
180 
181 #define FILETYPE_INDICATORS				\
182   {							\
183     C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE,	\
184     C_LINK, C_SOCK, C_FILE, C_DIR			\
185   }
186 
187 enum acl_type
188   {
189     ACL_T_NONE,
190     ACL_T_LSM_CONTEXT_ONLY,
191     ACL_T_YES
192   };
193 
194 struct fileinfo
195   {
196     /* The file name.  */
197     char *name;
198 
199     /* For symbolic link, name of the file linked to, otherwise zero.  */
200     char *linkname;
201 
202     /* For terminal hyperlinks. */
203     char *absolute_name;
204 
205     struct stat stat;
206 
207     enum filetype filetype;
208 
209     /* For symbolic link and long listing, st_mode of file linked to, otherwise
210        zero.  */
211     mode_t linkmode;
212 
213     /* security context.  */
214     char *scontext;
215 
216     bool stat_ok;
217 
218     /* For symbolic link and color printing, true if linked-to file
219        exists, otherwise false.  */
220     bool linkok;
221 
222     /* For long listings, true if the file has an access control list,
223        or a security context.  */
224     enum acl_type acl_type;
225 
226     /* For color listings, true if a regular file has capability info.  */
227     bool has_capability;
228 
229     /* Whether file name needs quoting. tri-state with -1 == unknown.  */
230     int quoted;
231 
232     /* Cached screen width (including quoting).  */
233     size_t width;
234   };
235 
236 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
237 
238 /* Null is a valid character in a color indicator (think about Epson
239    printers, for example) so we have to use a length/buffer string
240    type.  */
241 
242 struct bin_str
243   {
244     size_t len;			/* Number of bytes */
245     char const *string;		/* Pointer to the same */
246   };
247 
248 #if ! HAVE_TCGETPGRP
249 # define tcgetpgrp(Fd) 0
250 #endif
251 
252 static size_t quote_name (char const *name,
253                           struct quoting_options const *options,
254                           int needs_general_quoting,
255                           const struct bin_str *color,
256                           bool allow_pad, struct obstack *stack,
257                           char const *absolute_name);
258 static size_t quote_name_buf (char **inbuf, size_t bufsize, char *name,
259                               struct quoting_options const *options,
260                               int needs_general_quoting, size_t *width,
261                               bool *pad);
262 static int decode_switches (int argc, char **argv);
263 static bool file_ignored (char const *name);
264 static uintmax_t gobble_file (char const *name, enum filetype type,
265                               ino_t inode, bool command_line_arg,
266                               char const *dirname);
267 static const struct bin_str * get_color_indicator (const struct fileinfo *f,
268                                                    bool symlink_target);
269 static bool print_color_indicator (const struct bin_str *ind);
270 static void put_indicator (const struct bin_str *ind);
271 static void add_ignore_pattern (char const *pattern);
272 static void attach (char *dest, char const *dirname, char const *name);
273 static void clear_files (void);
274 static void extract_dirs_from_files (char const *dirname,
275                                      bool command_line_arg);
276 static void get_link_name (char const *filename, struct fileinfo *f,
277                            bool command_line_arg);
278 static void indent (size_t from, size_t to);
279 static size_t calculate_columns (bool by_columns);
280 static void print_current_files (void);
281 static void print_dir (char const *name, char const *realname,
282                        bool command_line_arg);
283 static size_t print_file_name_and_frills (const struct fileinfo *f,
284                                           size_t start_col);
285 static void print_horizontal (void);
286 static int format_user_width (uid_t u);
287 static int format_group_width (gid_t g);
288 static void print_long_format (const struct fileinfo *f);
289 static void print_many_per_line (void);
290 static size_t print_name_with_quoting (const struct fileinfo *f,
291                                        bool symlink_target,
292                                        struct obstack *stack,
293                                        size_t start_col);
294 static void prep_non_filename_text (void);
295 static bool print_type_indicator (bool stat_ok, mode_t mode,
296                                   enum filetype type);
297 static void print_with_separator (char sep);
298 static void queue_directory (char const *name, char const *realname,
299                              bool command_line_arg);
300 static void sort_files (void);
301 static void parse_ls_color (void);
302 
303 static int getenv_quoting_style (void);
304 
305 static size_t quote_name_width (char const *name,
306                                 struct quoting_options const *options,
307                                 int needs_general_quoting);
308 
309 /* Initial size of hash table.
310    Most hierarchies are likely to be shallower than this.  */
311 enum { INITIAL_TABLE_SIZE = 30 };
312 
313 /* The set of 'active' directories, from the current command-line argument
314    to the level in the hierarchy at which files are being listed.
315    A directory is represented by its device and inode numbers (struct dev_ino).
316    A directory is added to this set when ls begins listing it or its
317    entries, and it is removed from the set just after ls has finished
318    processing it.  This set is used solely to detect loops, e.g., with
319    mkdir loop; cd loop; ln -s ../loop sub; ls -RL  */
320 static Hash_table *active_dir_set;
321 
322 #define LOOP_DETECT (!!active_dir_set)
323 
324 /* The table of files in the current directory:
325 
326    'cwd_file' points to a vector of 'struct fileinfo', one per file.
327    'cwd_n_alloc' is the number of elements space has been allocated for.
328    'cwd_n_used' is the number actually in use.  */
329 
330 /* Address of block containing the files that are described.  */
331 static struct fileinfo *cwd_file;
332 
333 /* Length of block that 'cwd_file' points to, measured in files.  */
334 static size_t cwd_n_alloc;
335 
336 /* Index of first unused slot in 'cwd_file'.  */
337 static size_t cwd_n_used;
338 
339 /* Whether files needs may need padding due to quoting.  */
340 static bool cwd_some_quoted;
341 
342 /* Whether quoting style _may_ add outer quotes,
343    and whether aligning those is useful.  */
344 static bool align_variable_outer_quotes;
345 
346 /* Vector of pointers to files, in proper sorted order, and the number
347    of entries allocated for it.  */
348 static void **sorted_file;
349 static size_t sorted_file_alloc;
350 
351 /* When true, in a color listing, color each symlink name according to the
352    type of file it points to.  Otherwise, color them according to the 'ln'
353    directive in LS_COLORS.  Dangling (orphan) symlinks are treated specially,
354    regardless.  This is set when 'ln=target' appears in LS_COLORS.  */
355 
356 static bool color_symlink_as_referent;
357 
358 static char const *hostname;
359 
360 /* Mode of appropriate file for coloring.  */
361 static mode_t
file_or_link_mode(struct fileinfo const * file)362 file_or_link_mode (struct fileinfo const *file)
363 {
364   return (color_symlink_as_referent && file->linkok
365           ? file->linkmode : file->stat.st_mode);
366 }
367 
368 
369 /* Record of one pending directory waiting to be listed.  */
370 
371 struct pending
372   {
373     char *name;
374     /* If the directory is actually the file pointed to by a symbolic link we
375        were told to list, 'realname' will contain the name of the symbolic
376        link, otherwise zero.  */
377     char *realname;
378     bool command_line_arg;
379     struct pending *next;
380   };
381 
382 static struct pending *pending_dirs;
383 
384 /* Current time in seconds and nanoseconds since 1970, updated as
385    needed when deciding whether a file is recent.  */
386 
387 static struct timespec current_time;
388 
389 static bool print_scontext;
390 static char UNKNOWN_SECURITY_CONTEXT[] = "?";
391 
392 /* Whether any of the files has an ACL.  This affects the width of the
393    mode column.  */
394 
395 static bool any_has_acl;
396 
397 /* The number of columns to use for columns containing inode numbers,
398    block sizes, link counts, owners, groups, authors, major device
399    numbers, minor device numbers, and file sizes, respectively.  */
400 
401 static int inode_number_width;
402 static int block_size_width;
403 static int nlink_width;
404 static int scontext_width;
405 static int owner_width;
406 static int group_width;
407 static int author_width;
408 static int major_device_number_width;
409 static int minor_device_number_width;
410 static int file_size_width;
411 
412 /* Option flags */
413 
414 /* long_format for lots of info, one per line.
415    one_per_line for just names, one per line.
416    many_per_line for just names, many per line, sorted vertically.
417    horizontal for just names, many per line, sorted horizontally.
418    with_commas for just names, many per line, separated by commas.
419 
420    -l (and other options that imply -l), -1, -C, -x and -m control
421    this parameter.  */
422 
423 enum format
424   {
425     long_format,		/* -l and other options that imply -l */
426     one_per_line,		/* -1 */
427     many_per_line,		/* -C */
428     horizontal,			/* -x */
429     with_commas			/* -m */
430   };
431 
432 static enum format format;
433 
434 /* 'full-iso' uses full ISO-style dates and times.  'long-iso' uses longer
435    ISO-style timestamps, though shorter than 'full-iso'.  'iso' uses shorter
436    ISO-style timestamps.  'locale' uses locale-dependent timestamps.  */
437 enum time_style
438   {
439     full_iso_time_style,	/* --time-style=full-iso */
440     long_iso_time_style,	/* --time-style=long-iso */
441     iso_time_style,		/* --time-style=iso */
442     locale_time_style		/* --time-style=locale */
443   };
444 
445 static char const *const time_style_args[] =
446 {
447   "full-iso", "long-iso", "iso", "locale", nullptr
448 };
449 static enum time_style const time_style_types[] =
450 {
451   full_iso_time_style, long_iso_time_style, iso_time_style,
452   locale_time_style
453 };
454 ARGMATCH_VERIFY (time_style_args, time_style_types);
455 
456 /* Type of time to print or sort by.  Controlled by -c and -u.
457    The values of each item of this enum are important since they are
458    used as indices in the sort functions array (see sort_files()).  */
459 
460 enum time_type
461   {
462     time_mtime = 0,		/* default */
463     time_ctime,			/* -c */
464     time_atime,			/* -u */
465     time_btime,                 /* birth time */
466     time_numtypes		/* the number of elements of this enum */
467   };
468 
469 static enum time_type time_type;
470 
471 /* The file characteristic to sort by.  Controlled by -t, -S, -U, -X, -v.
472    The values of each item of this enum are important since they are
473    used as indices in the sort functions array (see sort_files()).  */
474 
475 enum sort_type
476   {
477     sort_name = 0,		/* default */
478     sort_extension,		/* -X */
479     sort_width,
480     sort_size,			/* -S */
481     sort_version,		/* -v */
482     sort_time,			/* -t; must be second to last */
483     sort_none,			/* -U; must be last */
484     sort_numtypes		/* the number of elements of this enum */
485   };
486 
487 static enum sort_type sort_type;
488 
489 /* Direction of sort.
490    false means highest first if numeric,
491    lowest first if alphabetic;
492    these are the defaults.
493    true means the opposite order in each case.  -r  */
494 
495 static bool sort_reverse;
496 
497 /* True means to display owner information.  -g turns this off.  */
498 
499 static bool print_owner = true;
500 
501 /* True means to display author information.  */
502 
503 static bool print_author;
504 
505 /* True means to display group information.  -G and -o turn this off.  */
506 
507 static bool print_group = true;
508 
509 /* True means print the user and group id's as numbers rather
510    than as names.  -n  */
511 
512 static bool numeric_ids;
513 
514 /* True means mention the size in blocks of each file.  -s  */
515 
516 static bool print_block_size;
517 
518 /* Human-readable options for output, when printing block counts.  */
519 static int human_output_opts;
520 
521 /* The units to use when printing block counts.  */
522 static uintmax_t output_block_size;
523 
524 /* Likewise, but for file sizes.  */
525 static int file_human_output_opts;
526 static uintmax_t file_output_block_size = 1;
527 
528 /* Follow the output with a special string.  Using this format,
529    Emacs' dired mode starts up twice as fast, and can handle all
530    strange characters in file names.  */
531 static bool dired;
532 
533 /* 'none' means don't mention the type of files.
534    'slash' means mention directories only, with a '/'.
535    'file_type' means mention file types.
536    'classify' means mention file types and mark executables.
537 
538    Controlled by -F, -p, and --indicator-style.  */
539 
540 enum indicator_style
541   {
542     none = 0,	/*     --indicator-style=none (default) */
543     slash,	/* -p, --indicator-style=slash */
544     file_type,	/*     --indicator-style=file-type */
545     classify	/* -F, --indicator-style=classify */
546   };
547 
548 static enum indicator_style indicator_style;
549 
550 /* Names of indicator styles.  */
551 static char const *const indicator_style_args[] =
552 {
553   "none", "slash", "file-type", "classify", nullptr
554 };
555 static enum indicator_style const indicator_style_types[] =
556 {
557   none, slash, file_type, classify
558 };
559 ARGMATCH_VERIFY (indicator_style_args, indicator_style_types);
560 
561 /* True means use colors to mark types.  Also define the different
562    colors as well as the stuff for the LS_COLORS environment variable.
563    The LS_COLORS variable is now in a termcap-like format.  */
564 
565 static bool print_with_color;
566 
567 static bool print_hyperlink;
568 
569 /* Whether we used any colors in the output so far.  If so, we will
570    need to restore the default color later.  If not, we will need to
571    call prep_non_filename_text before using color for the first time. */
572 
573 static bool used_color = false;
574 
575 enum when_type
576   {
577     when_never,		/* 0: default or --color=never */
578     when_always,	/* 1: --color=always */
579     when_if_tty		/* 2: --color=tty */
580   };
581 
582 enum Dereference_symlink
583   {
584     DEREF_UNDEFINED = 0,		/* default */
585     DEREF_NEVER,
586     DEREF_COMMAND_LINE_ARGUMENTS,	/* -H */
587     DEREF_COMMAND_LINE_SYMLINK_TO_DIR,	/* the default, in certain cases */
588     DEREF_ALWAYS			/* -L */
589   };
590 
591 enum indicator_no
592   {
593     C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
594     C_FIFO, C_SOCK,
595     C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
596     C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_MULTIHARDLINK,
597     C_CLR_TO_EOL
598   };
599 
600 static char const *const indicator_name[]=
601   {
602     "lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",
603     "bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
604     "ow", "tw", "ca", "mh", "cl", nullptr
605   };
606 
607 struct color_ext_type
608   {
609     struct bin_str ext;		/* The extension we're looking for */
610     struct bin_str seq;		/* The sequence to output when we do */
611     bool   exact_match;		/* Whether to compare case insensitively */
612     struct color_ext_type *next;	/* Next in list */
613   };
614 
615 static struct bin_str color_indicator[] =
616   {
617     { LEN_STR_PAIR ("\033[") },		/* lc: Left of color sequence */
618     { LEN_STR_PAIR ("m") },		/* rc: Right of color sequence */
619     { 0, nullptr },			/* ec: End color (replaces lc+rs+rc) */
620     { LEN_STR_PAIR ("0") },		/* rs: Reset to ordinary colors */
621     { 0, nullptr },			/* no: Normal */
622     { 0, nullptr },			/* fi: File: default */
623     { LEN_STR_PAIR ("01;34") },		/* di: Directory: bright blue */
624     { LEN_STR_PAIR ("01;36") },		/* ln: Symlink: bright cyan */
625     { LEN_STR_PAIR ("33") },		/* pi: Pipe: yellow/brown */
626     { LEN_STR_PAIR ("01;35") },		/* so: Socket: bright magenta */
627     { LEN_STR_PAIR ("01;33") },		/* bd: Block device: bright yellow */
628     { LEN_STR_PAIR ("01;33") },		/* cd: Char device: bright yellow */
629     { 0, nullptr },			/* mi: Missing file: undefined */
630     { 0, nullptr },			/* or: Orphaned symlink: undefined */
631     { LEN_STR_PAIR ("01;32") },		/* ex: Executable: bright green */
632     { LEN_STR_PAIR ("01;35") },		/* do: Door: bright magenta */
633     { LEN_STR_PAIR ("37;41") },		/* su: setuid: white on red */
634     { LEN_STR_PAIR ("30;43") },		/* sg: setgid: black on yellow */
635     { LEN_STR_PAIR ("37;44") },		/* st: sticky: black on blue */
636     { LEN_STR_PAIR ("34;42") },		/* ow: other-writable: blue on green */
637     { LEN_STR_PAIR ("30;42") },		/* tw: ow w/ sticky: black on green */
638     { 0, nullptr },			/* ca: disabled by default */
639     { 0, nullptr },			/* mh: disabled by default */
640     { LEN_STR_PAIR ("\033[K") },	/* cl: clear to end of line */
641   };
642 
643 /* A list mapping file extensions to corresponding display sequence.  */
644 static struct color_ext_type *color_ext_list = nullptr;
645 
646 /* Buffer for color sequences */
647 static char *color_buf;
648 
649 /* True means to check for orphaned symbolic link, for displaying
650    colors, or to group symlink to directories with other dirs.  */
651 
652 static bool check_symlink_mode;
653 
654 /* True means mention the inode number of each file.  -i  */
655 
656 static bool print_inode;
657 
658 /* What to do with symbolic links.  Affected by -d, -F, -H, -l (and
659    other options that imply -l), and -L.  */
660 
661 static enum Dereference_symlink dereference;
662 
663 /* True means when a directory is found, display info on its
664    contents.  -R  */
665 
666 static bool recursive;
667 
668 /* True means when an argument is a directory name, display info
669    on it itself.  -d  */
670 
671 static bool immediate_dirs;
672 
673 /* True means that directories are grouped before files. */
674 
675 static bool directories_first;
676 
677 /* Which files to ignore.  */
678 
679 static enum
680 {
681   /* Ignore files whose names start with '.', and files specified by
682      --hide and --ignore.  */
683   IGNORE_DEFAULT = 0,
684 
685   /* Ignore '.', '..', and files specified by --ignore.  */
686   IGNORE_DOT_AND_DOTDOT,
687 
688   /* Ignore only files specified by --ignore.  */
689   IGNORE_MINIMAL
690 } ignore_mode;
691 
692 /* A linked list of shell-style globbing patterns.  If a non-argument
693    file name matches any of these patterns, it is ignored.
694    Controlled by -I.  Multiple -I options accumulate.
695    The -B option adds '*~' and '.*~' to this list.  */
696 
697 struct ignore_pattern
698   {
699     char const *pattern;
700     struct ignore_pattern *next;
701   };
702 
703 static struct ignore_pattern *ignore_patterns;
704 
705 /* Similar to IGNORE_PATTERNS, except that -a or -A causes this
706    variable itself to be ignored.  */
707 static struct ignore_pattern *hide_patterns;
708 
709 /* True means output nongraphic chars in file names as '?'.
710    (-q, --hide-control-chars)
711    qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
712    independent.  The algorithm is: first, obey the quoting style to get a
713    string representing the file name;  then, if qmark_funny_chars is set,
714    replace all nonprintable chars in that string with '?'.  It's necessary
715    to replace nonprintable chars even in quoted strings, because we don't
716    want to mess up the terminal if control chars get sent to it, and some
717    quoting methods pass through control chars as-is.  */
718 static bool qmark_funny_chars;
719 
720 /* Quoting options for file and dir name output.  */
721 
722 static struct quoting_options *filename_quoting_options;
723 static struct quoting_options *dirname_quoting_options;
724 
725 /* The number of chars per hardware tab stop.  Setting this to zero
726    inhibits the use of TAB characters for separating columns.  -T */
727 static size_t tabsize;
728 
729 /* True means print each directory name before listing it.  */
730 
731 static bool print_dir_name;
732 
733 /* The line length to use for breaking lines in many-per-line format.
734    Can be set with -w.  If zero, there is no limit.  */
735 
736 static size_t line_length;
737 
738 /* The local time zone rules, as per the TZ environment variable.  */
739 
740 static timezone_t localtz;
741 
742 /* If true, the file listing format requires that stat be called on
743    each file.  */
744 
745 static bool format_needs_stat;
746 
747 /* Similar to 'format_needs_stat', but set if only the file type is
748    needed.  */
749 
750 static bool format_needs_type;
751 
752 /* An arbitrary limit on the number of bytes in a printed timestamp.
753    This is set to a relatively small value to avoid the need to worry
754    about denial-of-service attacks on servers that run "ls" on behalf
755    of remote clients.  1000 bytes should be enough for any practical
756    timestamp format.  */
757 
758 enum { TIME_STAMP_LEN_MAXIMUM = MAX (1000, INT_STRLEN_BOUND (time_t)) };
759 
760 /* strftime formats for non-recent and recent files, respectively, in
761    -l output.  */
762 
763 static char const *long_time_format[2] =
764   {
765     /* strftime format for non-recent files (older than 6 months), in
766        -l output.  This should contain the year, month and day (at
767        least), in an order that is understood by people in your
768        locale's territory.  Please try to keep the number of used
769        screen columns small, because many people work in windows with
770        only 80 columns.  But make this as wide as the other string
771        below, for recent files.  */
772     /* TRANSLATORS: ls output needs to be aligned for ease of reading,
773        so be wary of using variable width fields from the locale.
774        Note %b is handled specially by ls and aligned correctly.
775        Note also that specifying a width as in %5b is erroneous as strftime
776        will count bytes rather than characters in multibyte locales.  */
777     N_("%b %e  %Y"),
778     /* strftime format for recent files (younger than 6 months), in -l
779        output.  This should contain the month, day and time (at
780        least), in an order that is understood by people in your
781        locale's territory.  Please try to keep the number of used
782        screen columns small, because many people work in windows with
783        only 80 columns.  But make this as wide as the other string
784        above, for non-recent files.  */
785     /* TRANSLATORS: ls output needs to be aligned for ease of reading,
786        so be wary of using variable width fields from the locale.
787        Note %b is handled specially by ls and aligned correctly.
788        Note also that specifying a width as in %5b is erroneous as strftime
789        will count bytes rather than characters in multibyte locales.  */
790     N_("%b %e %H:%M")
791   };
792 
793 /* The set of signals that are caught.  */
794 
795 static sigset_t caught_signals;
796 
797 /* If nonzero, the value of the pending fatal signal.  */
798 
799 static sig_atomic_t volatile interrupt_signal;
800 
801 /* A count of the number of pending stop signals that have been received.  */
802 
803 static sig_atomic_t volatile stop_signal_count;
804 
805 /* Desired exit status.  */
806 
807 static int exit_status;
808 
809 /* Exit statuses.  */
810 enum
811   {
812     /* "ls" had a minor problem.  E.g., while processing a directory,
813        ls obtained the name of an entry via readdir, yet was later
814        unable to stat that name.  This happens when listing a directory
815        in which entries are actively being removed or renamed.  */
816     LS_MINOR_PROBLEM = 1,
817 
818     /* "ls" had more serious trouble (e.g., memory exhausted, invalid
819        option or failure to stat a command line argument.  */
820     LS_FAILURE = 2
821   };
822 
823 /* For long options that have no equivalent short option, use a
824    non-character as a pseudo short option, starting with CHAR_MAX + 1.  */
825 enum
826 {
827   AUTHOR_OPTION = CHAR_MAX + 1,
828   BLOCK_SIZE_OPTION,
829   COLOR_OPTION,
830   DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,
831   FILE_TYPE_INDICATOR_OPTION,
832   FORMAT_OPTION,
833   FULL_TIME_OPTION,
834   GROUP_DIRECTORIES_FIRST_OPTION,
835   HIDE_OPTION,
836   HYPERLINK_OPTION,
837   INDICATOR_STYLE_OPTION,
838   QUOTING_STYLE_OPTION,
839   SHOW_CONTROL_CHARS_OPTION,
840   SI_OPTION,
841   SORT_OPTION,
842   TIME_OPTION,
843   TIME_STYLE_OPTION,
844   ZERO_OPTION,
845 };
846 
847 static struct option const long_options[] =
848 {
849   {"all", no_argument, nullptr, 'a'},
850   {"escape", no_argument, nullptr, 'b'},
851   {"directory", no_argument, nullptr, 'd'},
852   {"dired", no_argument, nullptr, 'D'},
853   {"full-time", no_argument, nullptr, FULL_TIME_OPTION},
854   {"group-directories-first", no_argument, nullptr,
855    GROUP_DIRECTORIES_FIRST_OPTION},
856   {"human-readable", no_argument, nullptr, 'h'},
857   {"inode", no_argument, nullptr, 'i'},
858   {"kibibytes", no_argument, nullptr, 'k'},
859   {"numeric-uid-gid", no_argument, nullptr, 'n'},
860   {"no-group", no_argument, nullptr, 'G'},
861   {"hide-control-chars", no_argument, nullptr, 'q'},
862   {"reverse", no_argument, nullptr, 'r'},
863   {"size", no_argument, nullptr, 's'},
864   {"width", required_argument, nullptr, 'w'},
865   {"almost-all", no_argument, nullptr, 'A'},
866   {"ignore-backups", no_argument, nullptr, 'B'},
867   {"classify", optional_argument, nullptr, 'F'},
868   {"file-type", no_argument, nullptr, FILE_TYPE_INDICATOR_OPTION},
869   {"si", no_argument, nullptr, SI_OPTION},
870   {"dereference-command-line", no_argument, nullptr, 'H'},
871   {"dereference-command-line-symlink-to-dir", no_argument, nullptr,
872    DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION},
873   {"hide", required_argument, nullptr, HIDE_OPTION},
874   {"ignore", required_argument, nullptr, 'I'},
875   {"indicator-style", required_argument, nullptr, INDICATOR_STYLE_OPTION},
876   {"dereference", no_argument, nullptr, 'L'},
877   {"literal", no_argument, nullptr, 'N'},
878   {"quote-name", no_argument, nullptr, 'Q'},
879   {"quoting-style", required_argument, nullptr, QUOTING_STYLE_OPTION},
880   {"recursive", no_argument, nullptr, 'R'},
881   {"format", required_argument, nullptr, FORMAT_OPTION},
882   {"show-control-chars", no_argument, nullptr, SHOW_CONTROL_CHARS_OPTION},
883   {"sort", required_argument, nullptr, SORT_OPTION},
884   {"tabsize", required_argument, nullptr, 'T'},
885   {"time", required_argument, nullptr, TIME_OPTION},
886   {"time-style", required_argument, nullptr, TIME_STYLE_OPTION},
887   {"zero", no_argument, nullptr, ZERO_OPTION},
888   {"color", optional_argument, nullptr, COLOR_OPTION},
889   {"hyperlink", optional_argument, nullptr, HYPERLINK_OPTION},
890   {"block-size", required_argument, nullptr, BLOCK_SIZE_OPTION},
891   {"context", no_argument, 0, 'Z'},
892   {"author", no_argument, nullptr, AUTHOR_OPTION},
893   {GETOPT_HELP_OPTION_DECL},
894   {GETOPT_VERSION_OPTION_DECL},
895   {nullptr, 0, nullptr, 0}
896 };
897 
898 static char const *const format_args[] =
899 {
900   "verbose", "long", "commas", "horizontal", "across",
901   "vertical", "single-column", nullptr
902 };
903 static enum format const format_types[] =
904 {
905   long_format, long_format, with_commas, horizontal, horizontal,
906   many_per_line, one_per_line
907 };
908 ARGMATCH_VERIFY (format_args, format_types);
909 
910 static char const *const sort_args[] =
911 {
912   "none", "time", "size", "extension", "version", "width", nullptr
913 };
914 static enum sort_type const sort_types[] =
915 {
916   sort_none, sort_time, sort_size, sort_extension, sort_version, sort_width
917 };
918 ARGMATCH_VERIFY (sort_args, sort_types);
919 
920 static char const *const time_args[] =
921 {
922   "atime", "access", "use",
923   "ctime", "status",
924   "mtime", "modification",
925   "birth", "creation",
926   nullptr
927 };
928 static enum time_type const time_types[] =
929 {
930   time_atime, time_atime, time_atime,
931   time_ctime, time_ctime,
932   time_mtime, time_mtime,
933   time_btime, time_btime,
934 };
935 ARGMATCH_VERIFY (time_args, time_types);
936 
937 static char const *const when_args[] =
938 {
939   /* force and none are for compatibility with another color-ls version */
940   "always", "yes", "force",
941   "never", "no", "none",
942   "auto", "tty", "if-tty", nullptr
943 };
944 static enum when_type const when_types[] =
945 {
946   when_always, when_always, when_always,
947   when_never, when_never, when_never,
948   when_if_tty, when_if_tty, when_if_tty
949 };
950 ARGMATCH_VERIFY (when_args, when_types);
951 
952 /* Information about filling a column.  */
953 struct column_info
954 {
955   bool valid_len;
956   size_t line_len;
957   size_t *col_arr;
958 };
959 
960 /* Array with information about column fullness.  */
961 static struct column_info *column_info;
962 
963 /* Maximum number of columns ever possible for this display.  */
964 static size_t max_idx;
965 
966 /* The minimum width of a column is 3: 1 character for the name and 2
967    for the separating white space.  */
968 enum { MIN_COLUMN_WIDTH = 3 };
969 
970 
971 /* This zero-based index is for the --dired option.  It is incremented
972    for each byte of output generated by this program so that the beginning
973    and ending indices (in that output) of every file name can be recorded
974    and later output themselves.  */
975 static off_t dired_pos;
976 
977 static void
dired_outbyte(char c)978 dired_outbyte (char c)
979 {
980   dired_pos++;
981   putchar (c);
982 }
983 
984 /* Output the buffer S, of length S_LEN, and increment DIRED_POS by S_LEN.  */
985 static void
dired_outbuf(char const * s,size_t s_len)986 dired_outbuf (char const *s, size_t s_len)
987 {
988   dired_pos += s_len;
989   fwrite (s, sizeof *s, s_len, stdout);
990 }
991 
992 /* Output the string S, and increment DIRED_POS by its length.  */
993 static void
dired_outstring(char const * s)994 dired_outstring (char const *s)
995 {
996   dired_outbuf (s, strlen (s));
997 }
998 
999 static void
dired_indent(void)1000 dired_indent (void)
1001 {
1002   if (dired)
1003     dired_outstring ("  ");
1004 }
1005 
1006 /* With --dired, store pairs of beginning and ending indices of file names.  */
1007 static struct obstack dired_obstack;
1008 
1009 /* With --dired, store pairs of beginning and ending indices of any
1010    directory names that appear as headers (just before 'total' line)
1011    for lists of directory entries.  Such directory names are seen when
1012    listing hierarchies using -R and when a directory is listed with at
1013    least one other command line argument.  */
1014 static struct obstack subdired_obstack;
1015 
1016 /* Save the current index on the specified obstack, OBS.  */
1017 static void
push_current_dired_pos(struct obstack * obs)1018 push_current_dired_pos (struct obstack *obs)
1019 {
1020   if (dired)
1021     obstack_grow (obs, &dired_pos, sizeof dired_pos);
1022 }
1023 
1024 /* With -R, this stack is used to help detect directory cycles.
1025    The device/inode pairs on this stack mirror the pairs in the
1026    active_dir_set hash table.  */
1027 static struct obstack dev_ino_obstack;
1028 
1029 /* Push a pair onto the device/inode stack.  */
1030 static void
dev_ino_push(dev_t dev,ino_t ino)1031 dev_ino_push (dev_t dev, ino_t ino)
1032 {
1033   void *vdi;
1034   struct dev_ino *di;
1035   int dev_ino_size = sizeof *di;
1036   obstack_blank (&dev_ino_obstack, dev_ino_size);
1037   vdi = obstack_next_free (&dev_ino_obstack);
1038   di = vdi;
1039   di--;
1040   di->st_dev = dev;
1041   di->st_ino = ino;
1042 }
1043 
1044 /* Pop a dev/ino struct off the global dev_ino_obstack
1045    and return that struct.  */
1046 static struct dev_ino
dev_ino_pop(void)1047 dev_ino_pop (void)
1048 {
1049   void *vdi;
1050   struct dev_ino *di;
1051   int dev_ino_size = sizeof *di;
1052   affirm (dev_ino_size <= obstack_object_size (&dev_ino_obstack));
1053   obstack_blank_fast (&dev_ino_obstack, -dev_ino_size);
1054   vdi = obstack_next_free (&dev_ino_obstack);
1055   di = vdi;
1056   return *di;
1057 }
1058 
1059 static void
assert_matching_dev_ino(char const * name,struct dev_ino di)1060 assert_matching_dev_ino (char const *name, struct dev_ino di)
1061 {
1062   MAYBE_UNUSED struct stat sb;
1063   assure (0 <= stat (name, &sb));
1064   assure (sb.st_dev == di.st_dev);
1065   assure (sb.st_ino == di.st_ino);
1066 }
1067 
1068 static char eolbyte = '\n';
1069 
1070 /* Write to standard output PREFIX, followed by the quoting style and
1071    a space-separated list of the integers stored in OS all on one line.  */
1072 
1073 static void
dired_dump_obstack(char const * prefix,struct obstack * os)1074 dired_dump_obstack (char const *prefix, struct obstack *os)
1075 {
1076   size_t n_pos;
1077 
1078   n_pos = obstack_object_size (os) / sizeof (dired_pos);
1079   if (n_pos > 0)
1080     {
1081       off_t *pos = obstack_finish (os);
1082       fputs (prefix, stdout);
1083       for (size_t i = 0; i < n_pos; i++)
1084         {
1085           intmax_t p = pos[i];
1086           printf (" %jd", p);
1087         }
1088       putchar ('\n');
1089     }
1090 }
1091 
1092 /* Return the platform birthtime member of the stat structure,
1093    or fallback to the mtime member, which we have populated
1094    from the statx structure or reset to an invalid timestamp
1095    where birth time is not supported.  */
1096 static struct timespec
get_stat_btime(struct stat const * st)1097 get_stat_btime (struct stat const *st)
1098 {
1099   struct timespec btimespec;
1100 
1101 #if HAVE_STATX && defined STATX_INO
1102   btimespec = get_stat_mtime (st);
1103 #else
1104   btimespec = get_stat_birthtime (st);
1105 #endif
1106 
1107   return btimespec;
1108 }
1109 
1110 #if HAVE_STATX && defined STATX_INO
1111 ATTRIBUTE_PURE
1112 static unsigned int
time_type_to_statx(void)1113 time_type_to_statx (void)
1114 {
1115   switch (time_type)
1116     {
1117     case time_ctime:
1118       return STATX_CTIME;
1119     case time_mtime:
1120       return STATX_MTIME;
1121     case time_atime:
1122       return STATX_ATIME;
1123     case time_btime:
1124       return STATX_BTIME;
1125     default:
1126       unreachable ();
1127     }
1128     return 0;
1129 }
1130 
1131 ATTRIBUTE_PURE
1132 static unsigned int
calc_req_mask(void)1133 calc_req_mask (void)
1134 {
1135   unsigned int mask = STATX_MODE;
1136 
1137   if (print_inode)
1138     mask |= STATX_INO;
1139 
1140   if (print_block_size)
1141     mask |= STATX_BLOCKS;
1142 
1143   if (format == long_format) {
1144     mask |= STATX_NLINK | STATX_SIZE | time_type_to_statx ();
1145     if (print_owner || print_author)
1146       mask |= STATX_UID;
1147     if (print_group)
1148       mask |= STATX_GID;
1149   }
1150 
1151   switch (sort_type)
1152     {
1153     case sort_none:
1154     case sort_name:
1155     case sort_version:
1156     case sort_extension:
1157     case sort_width:
1158       break;
1159     case sort_time:
1160       mask |= time_type_to_statx ();
1161       break;
1162     case sort_size:
1163       mask |= STATX_SIZE;
1164       break;
1165     default:
1166       unreachable ();
1167     }
1168 
1169   return mask;
1170 }
1171 
1172 static int
do_statx(int fd,char const * name,struct stat * st,int flags,unsigned int mask)1173 do_statx (int fd, char const *name, struct stat *st, int flags,
1174           unsigned int mask)
1175 {
1176   struct statx stx;
1177   bool want_btime = mask & STATX_BTIME;
1178   int ret = statx (fd, name, flags | AT_NO_AUTOMOUNT, mask, &stx);
1179   if (ret >= 0)
1180     {
1181       statx_to_stat (&stx, st);
1182       /* Since we only need one timestamp type,
1183          store birth time in st_mtim.  */
1184       if (want_btime)
1185         {
1186           if (stx.stx_mask & STATX_BTIME)
1187             st->st_mtim = statx_timestamp_to_timespec (stx.stx_btime);
1188           else
1189             st->st_mtim.tv_sec = st->st_mtim.tv_nsec = -1;
1190         }
1191     }
1192 
1193   return ret;
1194 }
1195 
1196 static int
do_stat(char const * name,struct stat * st)1197 do_stat (char const *name, struct stat *st)
1198 {
1199   return do_statx (AT_FDCWD, name, st, 0, calc_req_mask ());
1200 }
1201 
1202 static int
do_lstat(char const * name,struct stat * st)1203 do_lstat (char const *name, struct stat *st)
1204 {
1205   return do_statx (AT_FDCWD, name, st, AT_SYMLINK_NOFOLLOW, calc_req_mask ());
1206 }
1207 
1208 static int
stat_for_mode(char const * name,struct stat * st)1209 stat_for_mode (char const *name, struct stat *st)
1210 {
1211   return do_statx (AT_FDCWD, name, st, 0, STATX_MODE);
1212 }
1213 
1214 /* dev+ino should be static, so no need to sync with backing store */
1215 static int
stat_for_ino(char const * name,struct stat * st)1216 stat_for_ino (char const *name, struct stat *st)
1217 {
1218   return do_statx (AT_FDCWD, name, st, 0, STATX_INO);
1219 }
1220 
1221 static int
fstat_for_ino(int fd,struct stat * st)1222 fstat_for_ino (int fd, struct stat *st)
1223 {
1224   return do_statx (fd, "", st, AT_EMPTY_PATH, STATX_INO);
1225 }
1226 #else
1227 static int
do_stat(char const * name,struct stat * st)1228 do_stat (char const *name, struct stat *st)
1229 {
1230   return stat (name, st);
1231 }
1232 
1233 static int
do_lstat(char const * name,struct stat * st)1234 do_lstat (char const *name, struct stat *st)
1235 {
1236   return lstat (name, st);
1237 }
1238 
1239 static int
stat_for_mode(char const * name,struct stat * st)1240 stat_for_mode (char const *name, struct stat *st)
1241 {
1242   return stat (name, st);
1243 }
1244 
1245 static int
stat_for_ino(char const * name,struct stat * st)1246 stat_for_ino (char const *name, struct stat *st)
1247 {
1248   return stat (name, st);
1249 }
1250 
1251 static int
fstat_for_ino(int fd,struct stat * st)1252 fstat_for_ino (int fd, struct stat *st)
1253 {
1254   return fstat (fd, st);
1255 }
1256 #endif
1257 
1258 /* Return the address of the first plain %b spec in FMT, or nullptr if
1259    there is no such spec.  %5b etc. do not match, so that user
1260    widths/flags are honored.  */
1261 
1262 ATTRIBUTE_PURE
1263 static char const *
first_percent_b(char const * fmt)1264 first_percent_b (char const *fmt)
1265 {
1266   for (; *fmt; fmt++)
1267     if (fmt[0] == '%')
1268       switch (fmt[1])
1269         {
1270         case 'b': return fmt;
1271         case '%': fmt++; break;
1272         }
1273   return nullptr;
1274 }
1275 
1276 static char RFC3986[256];
1277 static void
file_escape_init(void)1278 file_escape_init (void)
1279 {
1280   for (int i = 0; i < 256; i++)
1281     RFC3986[i] |= c_isalnum (i) || i == '~' || i == '-' || i == '.' || i == '_';
1282 }
1283 
1284 enum { MBSWIDTH_FLAGS = MBSW_REJECT_INVALID | MBSW_REJECT_UNPRINTABLE };
1285 
1286 /* Read the abbreviated month names from the locale, to align them
1287    and to determine the max width of the field and to truncate names
1288    greater than our max allowed.
1289    Note even though this handles multibyte locales correctly
1290    it's not restricted to them as single byte locales can have
1291    variable width abbreviated months and also precomputing/caching
1292    the names was seen to increase the performance of ls significantly.  */
1293 
1294 /* abformat[RECENT][MON] is the format to use for timestamps with
1295    recentness RECENT and month MON.  */
1296 enum { ABFORMAT_SIZE = 128 };
1297 static char abformat[2][12][ABFORMAT_SIZE];
1298 /* True if precomputed formats should be used.  This can be false if
1299    nl_langinfo fails, if a format or month abbreviation is unusually
1300    long, or if a month abbreviation contains '%'.  */
1301 static bool use_abformat;
1302 
1303 /* Store into ABMON the abbreviated month names, suitably aligned.
1304    Return true if successful.  */
1305 
1306 static bool
abmon_init(char abmon[12][ABFORMAT_SIZE])1307 abmon_init (char abmon[12][ABFORMAT_SIZE])
1308 {
1309 #ifndef HAVE_NL_LANGINFO
1310   return false;
1311 #else
1312   int max_mon_width = 0;
1313   int mon_width[12];
1314   int mon_len[12];
1315 
1316   for (int i = 0; i < 12; i++)
1317     {
1318       char const *abbr = nl_langinfo (ABMON_1 + i);
1319       mon_len[i] = strnlen (abbr, ABFORMAT_SIZE);
1320       if (mon_len[i] == ABFORMAT_SIZE)
1321         return false;
1322       if (strchr (abbr, '%'))
1323         return false;
1324       mon_width[i] = mbswidth (strcpy (abmon[i], abbr), MBSWIDTH_FLAGS);
1325       if (mon_width[i] < 0)
1326         return false;
1327       max_mon_width = MAX (max_mon_width, mon_width[i]);
1328     }
1329 
1330   for (int i = 0; i < 12; i++)
1331     {
1332       int fill = max_mon_width - mon_width[i];
1333       if (ABFORMAT_SIZE - mon_len[i] <= fill)
1334         return false;
1335       bool align_left = !isdigit (to_uchar (abmon[i][0]));
1336       int fill_offset;
1337       if (align_left)
1338         fill_offset = mon_len[i];
1339       else
1340         {
1341           memmove (abmon[i] + fill, abmon[i], mon_len[i]);
1342           fill_offset = 0;
1343         }
1344       memset (abmon[i] + fill_offset, ' ', fill);
1345       abmon[i][mon_len[i] + fill] = '\0';
1346     }
1347 
1348   return true;
1349 #endif
1350 }
1351 
1352 /* Initialize ABFORMAT and USE_ABFORMAT.  */
1353 
1354 static void
abformat_init(void)1355 abformat_init (void)
1356 {
1357   char const *pb[2];
1358   for (int recent = 0; recent < 2; recent++)
1359     pb[recent] = first_percent_b (long_time_format[recent]);
1360   if (! (pb[0] || pb[1]))
1361     return;
1362 
1363   char abmon[12][ABFORMAT_SIZE];
1364   if (! abmon_init (abmon))
1365     return;
1366 
1367   for (int recent = 0; recent < 2; recent++)
1368     {
1369       char const *fmt = long_time_format[recent];
1370       for (int i = 0; i < 12; i++)
1371         {
1372           char *nfmt = abformat[recent][i];
1373           int nbytes;
1374 
1375           if (! pb[recent])
1376             nbytes = snprintf (nfmt, ABFORMAT_SIZE, "%s", fmt);
1377           else
1378             {
1379               if (! (pb[recent] - fmt <= MIN (ABFORMAT_SIZE, INT_MAX)))
1380                 return;
1381               int prefix_len = pb[recent] - fmt;
1382               nbytes = snprintf (nfmt, ABFORMAT_SIZE, "%.*s%s%s",
1383                                  prefix_len, fmt, abmon[i], pb[recent] + 2);
1384             }
1385 
1386           if (! (0 <= nbytes && nbytes < ABFORMAT_SIZE))
1387             return;
1388         }
1389     }
1390 
1391   use_abformat = true;
1392 }
1393 
1394 static size_t
dev_ino_hash(void const * x,size_t table_size)1395 dev_ino_hash (void const *x, size_t table_size)
1396 {
1397   struct dev_ino const *p = x;
1398   return (uintmax_t) p->st_ino % table_size;
1399 }
1400 
1401 static bool
dev_ino_compare(void const * x,void const * y)1402 dev_ino_compare (void const *x, void const *y)
1403 {
1404   struct dev_ino const *a = x;
1405   struct dev_ino const *b = y;
1406   return PSAME_INODE (a, b);
1407 }
1408 
1409 static void
dev_ino_free(void * x)1410 dev_ino_free (void *x)
1411 {
1412   free (x);
1413 }
1414 
1415 /* Add the device/inode pair (P->st_dev/P->st_ino) to the set of
1416    active directories.  Return true if there is already a matching
1417    entry in the table.  */
1418 
1419 static bool
visit_dir(dev_t dev,ino_t ino)1420 visit_dir (dev_t dev, ino_t ino)
1421 {
1422   struct dev_ino *ent;
1423   struct dev_ino *ent_from_table;
1424   bool found_match;
1425 
1426   ent = xmalloc (sizeof *ent);
1427   ent->st_ino = ino;
1428   ent->st_dev = dev;
1429 
1430   /* Attempt to insert this entry into the table.  */
1431   ent_from_table = hash_insert (active_dir_set, ent);
1432 
1433   if (ent_from_table == nullptr)
1434     {
1435       /* Insertion failed due to lack of memory.  */
1436       xalloc_die ();
1437     }
1438 
1439   found_match = (ent_from_table != ent);
1440 
1441   if (found_match)
1442     {
1443       /* ent was not inserted, so free it.  */
1444       free (ent);
1445     }
1446 
1447   return found_match;
1448 }
1449 
1450 static void
free_pending_ent(struct pending * p)1451 free_pending_ent (struct pending *p)
1452 {
1453   free (p->name);
1454   free (p->realname);
1455   free (p);
1456 }
1457 
1458 static bool
is_colored(enum indicator_no type)1459 is_colored (enum indicator_no type)
1460 {
1461   size_t len = color_indicator[type].len;
1462   char const *s = color_indicator[type].string;
1463   return ! (len == 0
1464             || (len == 1 && STRNCMP_LIT (s, "0") == 0)
1465             || (len == 2 && STRNCMP_LIT (s, "00") == 0));
1466 }
1467 
1468 static void
restore_default_color(void)1469 restore_default_color (void)
1470 {
1471   put_indicator (&color_indicator[C_LEFT]);
1472   put_indicator (&color_indicator[C_RIGHT]);
1473 }
1474 
1475 static void
set_normal_color(void)1476 set_normal_color (void)
1477 {
1478   if (print_with_color && is_colored (C_NORM))
1479     {
1480       put_indicator (&color_indicator[C_LEFT]);
1481       put_indicator (&color_indicator[C_NORM]);
1482       put_indicator (&color_indicator[C_RIGHT]);
1483     }
1484 }
1485 
1486 /* An ordinary signal was received; arrange for the program to exit.  */
1487 
1488 static void
sighandler(int sig)1489 sighandler (int sig)
1490 {
1491   if (! SA_NOCLDSTOP)
1492     signal (sig, SIG_IGN);
1493   if (! interrupt_signal)
1494     interrupt_signal = sig;
1495 }
1496 
1497 /* A SIGTSTP was received; arrange for the program to suspend itself.  */
1498 
1499 static void
stophandler(int sig)1500 stophandler (int sig)
1501 {
1502   if (! SA_NOCLDSTOP)
1503     signal (sig, stophandler);
1504   if (! interrupt_signal)
1505     stop_signal_count++;
1506 }
1507 
1508 /* Process any pending signals.  If signals are caught, this function
1509    should be called periodically.  Ideally there should never be an
1510    unbounded amount of time when signals are not being processed.
1511    Signal handling can restore the default colors, so callers must
1512    immediately change colors after invoking this function.  */
1513 
1514 static void
process_signals(void)1515 process_signals (void)
1516 {
1517   while (interrupt_signal || stop_signal_count)
1518     {
1519       int sig;
1520       int stops;
1521       sigset_t oldset;
1522 
1523       if (used_color)
1524         restore_default_color ();
1525       fflush (stdout);
1526 
1527       sigprocmask (SIG_BLOCK, &caught_signals, &oldset);
1528 
1529       /* Reload interrupt_signal and stop_signal_count, in case a new
1530          signal was handled before sigprocmask took effect.  */
1531       sig = interrupt_signal;
1532       stops = stop_signal_count;
1533 
1534       /* SIGTSTP is special, since the application can receive that signal
1535          more than once.  In this case, don't set the signal handler to the
1536          default.  Instead, just raise the uncatchable SIGSTOP.  */
1537       if (stops)
1538         {
1539           stop_signal_count = stops - 1;
1540           sig = SIGSTOP;
1541         }
1542       else
1543         signal (sig, SIG_DFL);
1544 
1545       /* Exit or suspend the program.  */
1546       raise (sig);
1547       sigprocmask (SIG_SETMASK, &oldset, nullptr);
1548 
1549       /* If execution reaches here, then the program has been
1550          continued (after being suspended).  */
1551     }
1552 }
1553 
1554 /* Setup signal handlers if INIT is true,
1555    otherwise restore to the default.  */
1556 
1557 static void
signal_setup(bool init)1558 signal_setup (bool init)
1559 {
1560   /* The signals that are trapped, and the number of such signals.  */
1561   static int const sig[] =
1562     {
1563       /* This one is handled specially.  */
1564       SIGTSTP,
1565 
1566       /* The usual suspects.  */
1567       SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM,
1568 #ifdef SIGPOLL
1569       SIGPOLL,
1570 #endif
1571 #ifdef SIGPROF
1572       SIGPROF,
1573 #endif
1574 #ifdef SIGVTALRM
1575       SIGVTALRM,
1576 #endif
1577 #ifdef SIGXCPU
1578       SIGXCPU,
1579 #endif
1580 #ifdef SIGXFSZ
1581       SIGXFSZ,
1582 #endif
1583     };
1584   enum { nsigs = ARRAY_CARDINALITY (sig) };
1585 
1586 #if ! SA_NOCLDSTOP
1587   static bool caught_sig[nsigs];
1588 #endif
1589 
1590   int j;
1591 
1592   if (init)
1593     {
1594 #if SA_NOCLDSTOP
1595       struct sigaction act;
1596 
1597       sigemptyset (&caught_signals);
1598       for (j = 0; j < nsigs; j++)
1599         {
1600           sigaction (sig[j], nullptr, &act);
1601           if (act.sa_handler != SIG_IGN)
1602             sigaddset (&caught_signals, sig[j]);
1603         }
1604 
1605       act.sa_mask = caught_signals;
1606       act.sa_flags = SA_RESTART;
1607 
1608       for (j = 0; j < nsigs; j++)
1609         if (sigismember (&caught_signals, sig[j]))
1610           {
1611             act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;
1612             sigaction (sig[j], &act, nullptr);
1613           }
1614 #else
1615       for (j = 0; j < nsigs; j++)
1616         {
1617           caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);
1618           if (caught_sig[j])
1619             {
1620               signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);
1621               siginterrupt (sig[j], 0);
1622             }
1623         }
1624 #endif
1625     }
1626   else /* restore.  */
1627     {
1628 #if SA_NOCLDSTOP
1629       for (j = 0; j < nsigs; j++)
1630         if (sigismember (&caught_signals, sig[j]))
1631           signal (sig[j], SIG_DFL);
1632 #else
1633       for (j = 0; j < nsigs; j++)
1634         if (caught_sig[j])
1635           signal (sig[j], SIG_DFL);
1636 #endif
1637     }
1638 }
1639 
1640 static void
signal_init(void)1641 signal_init (void)
1642 {
1643   signal_setup (true);
1644 }
1645 
1646 static void
signal_restore(void)1647 signal_restore (void)
1648 {
1649   signal_setup (false);
1650 }
1651 
1652 int
main(int argc,char ** argv)1653 main (int argc, char **argv)
1654 {
1655   int i;
1656   struct pending *thispend;
1657   int n_files;
1658 
1659   initialize_main (&argc, &argv);
1660   set_program_name (argv[0]);
1661   setlocale (LC_ALL, "");
1662   bindtextdomain (PACKAGE, LOCALEDIR);
1663   textdomain (PACKAGE);
1664 
1665   initialize_exit_failure (LS_FAILURE);
1666   atexit (close_stdout);
1667 
1668   static_assert (ARRAY_CARDINALITY (color_indicator) + 1
1669                  == ARRAY_CARDINALITY (indicator_name));
1670 
1671   exit_status = EXIT_SUCCESS;
1672   print_dir_name = true;
1673   pending_dirs = nullptr;
1674 
1675   current_time.tv_sec = TYPE_MINIMUM (time_t);
1676   current_time.tv_nsec = -1;
1677 
1678   i = decode_switches (argc, argv);
1679 
1680   if (print_with_color)
1681     parse_ls_color ();
1682 
1683   /* Test print_with_color again, because the call to parse_ls_color
1684      may have just reset it -- e.g., if LS_COLORS is invalid.  */
1685 
1686   if (print_with_color)
1687     {
1688       /* Don't use TAB characters in output.  Some terminal
1689          emulators can't handle the combination of tabs and
1690          color codes on the same line.  */
1691       tabsize = 0;
1692     }
1693 
1694   if (directories_first)
1695     check_symlink_mode = true;
1696   else if (print_with_color)
1697     {
1698       /* Avoid following symbolic links when possible.  */
1699       if (is_colored (C_ORPHAN)
1700           || (is_colored (C_EXEC) && color_symlink_as_referent)
1701           || (is_colored (C_MISSING) && format == long_format))
1702         check_symlink_mode = true;
1703     }
1704 
1705   if (dereference == DEREF_UNDEFINED)
1706     dereference = ((immediate_dirs
1707                     || indicator_style == classify
1708                     || format == long_format)
1709                    ? DEREF_NEVER
1710                    : DEREF_COMMAND_LINE_SYMLINK_TO_DIR);
1711 
1712   /* When using -R, initialize a data structure we'll use to
1713      detect any directory cycles.  */
1714   if (recursive)
1715     {
1716       active_dir_set = hash_initialize (INITIAL_TABLE_SIZE, nullptr,
1717                                         dev_ino_hash,
1718                                         dev_ino_compare,
1719                                         dev_ino_free);
1720       if (active_dir_set == nullptr)
1721         xalloc_die ();
1722 
1723       obstack_init (&dev_ino_obstack);
1724     }
1725 
1726   localtz = tzalloc (getenv ("TZ"));
1727 
1728   format_needs_stat = sort_type == sort_time || sort_type == sort_size
1729     || format == long_format
1730     || print_scontext
1731     || print_block_size;
1732   format_needs_type = (! format_needs_stat
1733                        && (recursive
1734                            || print_with_color
1735                            || indicator_style != none
1736                            || directories_first));
1737 
1738   if (dired)
1739     {
1740       obstack_init (&dired_obstack);
1741       obstack_init (&subdired_obstack);
1742     }
1743 
1744   if (print_hyperlink)
1745     {
1746       file_escape_init ();
1747 
1748       hostname = xgethostname ();
1749       /* The hostname is generally ignored,
1750          so ignore failures obtaining it.  */
1751       if (! hostname)
1752         hostname = "";
1753     }
1754 
1755   cwd_n_alloc = 100;
1756   cwd_file = xnmalloc (cwd_n_alloc, sizeof *cwd_file);
1757   cwd_n_used = 0;
1758 
1759   clear_files ();
1760 
1761   n_files = argc - i;
1762 
1763   if (n_files <= 0)
1764     {
1765       if (immediate_dirs)
1766         gobble_file (".", directory, NOT_AN_INODE_NUMBER, true, "");
1767       else
1768         queue_directory (".", nullptr, true);
1769     }
1770   else
1771     do
1772       gobble_file (argv[i++], unknown, NOT_AN_INODE_NUMBER, true, "");
1773     while (i < argc);
1774 
1775   if (cwd_n_used)
1776     {
1777       sort_files ();
1778       if (!immediate_dirs)
1779         extract_dirs_from_files (nullptr, true);
1780       /* 'cwd_n_used' might be zero now.  */
1781     }
1782 
1783   /* In the following if/else blocks, it is sufficient to test 'pending_dirs'
1784      (and not pending_dirs->name) because there may be no markers in the queue
1785      at this point.  A marker may be enqueued when extract_dirs_from_files is
1786      called with a non-empty string or via print_dir.  */
1787   if (cwd_n_used)
1788     {
1789       print_current_files ();
1790       if (pending_dirs)
1791         dired_outbyte ('\n');
1792     }
1793   else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0)
1794     print_dir_name = false;
1795 
1796   while (pending_dirs)
1797     {
1798       thispend = pending_dirs;
1799       pending_dirs = pending_dirs->next;
1800 
1801       if (LOOP_DETECT)
1802         {
1803           if (thispend->name == nullptr)
1804             {
1805               /* thispend->name == nullptr means this is a marker entry
1806                  indicating we've finished processing the directory.
1807                  Use its dev/ino numbers to remove the corresponding
1808                  entry from the active_dir_set hash table.  */
1809               struct dev_ino di = dev_ino_pop ();
1810               struct dev_ino *found = hash_remove (active_dir_set, &di);
1811               if (false)
1812                 assert_matching_dev_ino (thispend->realname, di);
1813               affirm (found);
1814               dev_ino_free (found);
1815               free_pending_ent (thispend);
1816               continue;
1817             }
1818         }
1819 
1820       print_dir (thispend->name, thispend->realname,
1821                  thispend->command_line_arg);
1822 
1823       free_pending_ent (thispend);
1824       print_dir_name = true;
1825     }
1826 
1827   if (print_with_color && used_color)
1828     {
1829       int j;
1830 
1831       /* Skip the restore when it would be a no-op, i.e.,
1832          when left is "\033[" and right is "m".  */
1833       if (!(color_indicator[C_LEFT].len == 2
1834             && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0
1835             && color_indicator[C_RIGHT].len == 1
1836             && color_indicator[C_RIGHT].string[0] == 'm'))
1837         restore_default_color ();
1838 
1839       fflush (stdout);
1840 
1841       signal_restore ();
1842 
1843       /* Act on any signals that arrived before the default was restored.
1844          This can process signals out of order, but there doesn't seem to
1845          be an easy way to do them in order, and the order isn't that
1846          important anyway.  */
1847       for (j = stop_signal_count; j; j--)
1848         raise (SIGSTOP);
1849       j = interrupt_signal;
1850       if (j)
1851         raise (j);
1852     }
1853 
1854   if (dired)
1855     {
1856       /* No need to free these since we're about to exit.  */
1857       dired_dump_obstack ("//DIRED//", &dired_obstack);
1858       dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
1859       printf ("//DIRED-OPTIONS// --quoting-style=%s\n",
1860               quoting_style_args[get_quoting_style (filename_quoting_options)]);
1861     }
1862 
1863   if (LOOP_DETECT)
1864     {
1865       assure (hash_get_n_entries (active_dir_set) == 0);
1866       hash_free (active_dir_set);
1867     }
1868 
1869   return exit_status;
1870 }
1871 
1872 /* Return the line length indicated by the value given by SPEC, or -1
1873    if unsuccessful.  0 means no limit on line length.  */
1874 
1875 static ptrdiff_t
decode_line_length(char const * spec)1876 decode_line_length (char const *spec)
1877 {
1878   uintmax_t val;
1879 
1880   /* Treat too-large values as if they were 0, which is
1881      effectively infinity.  */
1882   switch (xstrtoumax (spec, nullptr, 0, &val, ""))
1883     {
1884     case LONGINT_OK:
1885       return val <= MIN (PTRDIFF_MAX, SIZE_MAX) ? val : 0;
1886 
1887     case LONGINT_OVERFLOW:
1888       return 0;
1889 
1890     default:
1891       return -1;
1892     }
1893 }
1894 
1895 /* Return true if standard output is a tty, caching the result.  */
1896 
1897 static bool
stdout_isatty(void)1898 stdout_isatty (void)
1899 {
1900   static signed char out_tty = -1;
1901   if (out_tty < 0)
1902     out_tty = isatty (STDOUT_FILENO);
1903   assume (out_tty == 0 || out_tty == 1);
1904   return out_tty;
1905 }
1906 
1907 /* Set all the option flags according to the switches specified.
1908    Return the index of the first non-option argument.  */
1909 
1910 static int
decode_switches(int argc,char ** argv)1911 decode_switches (int argc, char **argv)
1912 {
1913   char *time_style_option = nullptr;
1914 
1915   /* These variables are false or -1 unless a switch says otherwise.  */
1916   bool kibibytes_specified = false;
1917   int format_opt = -1;
1918   int hide_control_chars_opt = -1;
1919   int quoting_style_opt = -1;
1920   int sort_opt = -1;
1921   ptrdiff_t tabsize_opt = -1;
1922   ptrdiff_t width_opt = -1;
1923 
1924   while (true)
1925     {
1926       int oi = -1;
1927       int c = getopt_long (argc, argv,
1928                            "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",
1929                            long_options, &oi);
1930       if (c == -1)
1931         break;
1932 
1933       switch (c)
1934         {
1935         case 'a':
1936           ignore_mode = IGNORE_MINIMAL;
1937           break;
1938 
1939         case 'b':
1940           quoting_style_opt = escape_quoting_style;
1941           break;
1942 
1943         case 'c':
1944           time_type = time_ctime;
1945           break;
1946 
1947         case 'd':
1948           immediate_dirs = true;
1949           break;
1950 
1951         case 'f':
1952           /* Same as -a -U -1 --color=none --hyperlink=none,
1953              while disabling -s.  */
1954           ignore_mode = IGNORE_MINIMAL;
1955           sort_opt = sort_none;
1956           if (format_opt == long_format)
1957             format_opt = -1;
1958           print_with_color = false;
1959           print_hyperlink = false;
1960           print_block_size = false;
1961           break;
1962 
1963         case FILE_TYPE_INDICATOR_OPTION: /* --file-type */
1964           indicator_style = file_type;
1965           break;
1966 
1967         case 'g':
1968           format_opt = long_format;
1969           print_owner = false;
1970           break;
1971 
1972         case 'h':
1973           file_human_output_opts = human_output_opts =
1974             human_autoscale | human_SI | human_base_1024;
1975           file_output_block_size = output_block_size = 1;
1976           break;
1977 
1978         case 'i':
1979           print_inode = true;
1980           break;
1981 
1982         case 'k':
1983           kibibytes_specified = true;
1984           break;
1985 
1986         case 'l':
1987           format_opt = long_format;
1988           break;
1989 
1990         case 'm':
1991           format_opt = with_commas;
1992           break;
1993 
1994         case 'n':
1995           numeric_ids = true;
1996           format_opt = long_format;
1997           break;
1998 
1999         case 'o':  /* Just like -l, but don't display group info.  */
2000           format_opt = long_format;
2001           print_group = false;
2002           break;
2003 
2004         case 'p':
2005           indicator_style = slash;
2006           break;
2007 
2008         case 'q':
2009           hide_control_chars_opt = true;
2010           break;
2011 
2012         case 'r':
2013           sort_reverse = true;
2014           break;
2015 
2016         case 's':
2017           print_block_size = true;
2018           break;
2019 
2020         case 't':
2021           sort_opt = sort_time;
2022           break;
2023 
2024         case 'u':
2025           time_type = time_atime;
2026           break;
2027 
2028         case 'v':
2029           sort_opt = sort_version;
2030           break;
2031 
2032         case 'w':
2033           width_opt = decode_line_length (optarg);
2034           if (width_opt < 0)
2035             error (LS_FAILURE, 0, "%s: %s", _("invalid line width"),
2036                    quote (optarg));
2037           break;
2038 
2039         case 'x':
2040           format_opt = horizontal;
2041           break;
2042 
2043         case 'A':
2044           ignore_mode = IGNORE_DOT_AND_DOTDOT;
2045           break;
2046 
2047         case 'B':
2048           add_ignore_pattern ("*~");
2049           add_ignore_pattern (".*~");
2050           break;
2051 
2052         case 'C':
2053           format_opt = many_per_line;
2054           break;
2055 
2056         case 'D':
2057           format_opt = long_format;
2058           print_hyperlink = false;
2059           dired = true;
2060           break;
2061 
2062         case 'F':
2063           {
2064             int i;
2065             if (optarg)
2066               i = XARGMATCH ("--classify", optarg, when_args, when_types);
2067             else
2068               /* Using --classify with no argument is equivalent to using
2069                  --classify=always.  */
2070               i = when_always;
2071 
2072             if (i == when_always || (i == when_if_tty && stdout_isatty ()))
2073               indicator_style = classify;
2074             break;
2075           }
2076 
2077         case 'G':		/* inhibit display of group info */
2078           print_group = false;
2079           break;
2080 
2081         case 'H':
2082           dereference = DEREF_COMMAND_LINE_ARGUMENTS;
2083           break;
2084 
2085         case DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION:
2086           dereference = DEREF_COMMAND_LINE_SYMLINK_TO_DIR;
2087           break;
2088 
2089         case 'I':
2090           add_ignore_pattern (optarg);
2091           break;
2092 
2093         case 'L':
2094           dereference = DEREF_ALWAYS;
2095           break;
2096 
2097         case 'N':
2098           quoting_style_opt = literal_quoting_style;
2099           break;
2100 
2101         case 'Q':
2102           quoting_style_opt = c_quoting_style;
2103           break;
2104 
2105         case 'R':
2106           recursive = true;
2107           break;
2108 
2109         case 'S':
2110           sort_opt = sort_size;
2111           break;
2112 
2113         case 'T':
2114           tabsize_opt = xnumtoumax (optarg, 0, 0, MIN (PTRDIFF_MAX, SIZE_MAX),
2115                                     "", _("invalid tab size"), LS_FAILURE);
2116           break;
2117 
2118         case 'U':
2119           sort_opt = sort_none;
2120           break;
2121 
2122         case 'X':
2123           sort_opt = sort_extension;
2124           break;
2125 
2126         case '1':
2127           /* -1 has no effect after -l.  */
2128           if (format_opt != long_format)
2129             format_opt = one_per_line;
2130           break;
2131 
2132         case AUTHOR_OPTION:
2133           print_author = true;
2134           break;
2135 
2136         case HIDE_OPTION:
2137           {
2138             struct ignore_pattern *hide = xmalloc (sizeof *hide);
2139             hide->pattern = optarg;
2140             hide->next = hide_patterns;
2141             hide_patterns = hide;
2142           }
2143           break;
2144 
2145         case SORT_OPTION:
2146           sort_opt = XARGMATCH ("--sort", optarg, sort_args, sort_types);
2147           break;
2148 
2149         case GROUP_DIRECTORIES_FIRST_OPTION:
2150           directories_first = true;
2151           break;
2152 
2153         case TIME_OPTION:
2154           time_type = XARGMATCH ("--time", optarg, time_args, time_types);
2155           break;
2156 
2157         case FORMAT_OPTION:
2158           format_opt = XARGMATCH ("--format", optarg, format_args,
2159                                   format_types);
2160           break;
2161 
2162         case FULL_TIME_OPTION:
2163           format_opt = long_format;
2164           time_style_option = bad_cast ("full-iso");
2165           break;
2166 
2167         case COLOR_OPTION:
2168           {
2169             int i;
2170             if (optarg)
2171               i = XARGMATCH ("--color", optarg, when_args, when_types);
2172             else
2173               /* Using --color with no argument is equivalent to using
2174                  --color=always.  */
2175               i = when_always;
2176 
2177             print_with_color = (i == when_always
2178                                 || (i == when_if_tty && stdout_isatty ()));
2179             break;
2180           }
2181 
2182         case HYPERLINK_OPTION:
2183           {
2184             int i;
2185             if (optarg)
2186               i = XARGMATCH ("--hyperlink", optarg, when_args, when_types);
2187             else
2188               /* Using --hyperlink with no argument is equivalent to using
2189                  --hyperlink=always.  */
2190               i = when_always;
2191 
2192             print_hyperlink = (i == when_always
2193                                || (i == when_if_tty && stdout_isatty ()));
2194             break;
2195           }
2196 
2197         case INDICATOR_STYLE_OPTION:
2198           indicator_style = XARGMATCH ("--indicator-style", optarg,
2199                                        indicator_style_args,
2200                                        indicator_style_types);
2201           break;
2202 
2203         case QUOTING_STYLE_OPTION:
2204           quoting_style_opt = XARGMATCH ("--quoting-style", optarg,
2205                                          quoting_style_args,
2206                                          quoting_style_vals);
2207           break;
2208 
2209         case TIME_STYLE_OPTION:
2210           time_style_option = optarg;
2211           break;
2212 
2213         case SHOW_CONTROL_CHARS_OPTION:
2214           hide_control_chars_opt = false;
2215           break;
2216 
2217         case BLOCK_SIZE_OPTION:
2218           {
2219             enum strtol_error e = human_options (optarg, &human_output_opts,
2220                                                  &output_block_size);
2221             if (e != LONGINT_OK)
2222               xstrtol_fatal (e, oi, 0, long_options, optarg);
2223             file_human_output_opts = human_output_opts;
2224             file_output_block_size = output_block_size;
2225           }
2226           break;
2227 
2228         case SI_OPTION:
2229           file_human_output_opts = human_output_opts =
2230             human_autoscale | human_SI;
2231           file_output_block_size = output_block_size = 1;
2232           break;
2233 
2234         case 'Z':
2235           print_scontext = true;
2236           break;
2237 
2238         case ZERO_OPTION:
2239           eolbyte = 0;
2240           hide_control_chars_opt = false;
2241           if (format_opt != long_format)
2242             format_opt = one_per_line;
2243           print_with_color = false;
2244           quoting_style_opt = literal_quoting_style;
2245           break;
2246 
2247         case_GETOPT_HELP_CHAR;
2248 
2249         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
2250 
2251         default:
2252           usage (LS_FAILURE);
2253         }
2254     }
2255 
2256   if (! output_block_size)
2257     {
2258       char const *ls_block_size = getenv ("LS_BLOCK_SIZE");
2259       human_options (ls_block_size,
2260                      &human_output_opts, &output_block_size);
2261       if (ls_block_size || getenv ("BLOCK_SIZE"))
2262         {
2263           file_human_output_opts = human_output_opts;
2264           file_output_block_size = output_block_size;
2265         }
2266       if (kibibytes_specified)
2267         {
2268           human_output_opts = 0;
2269           output_block_size = 1024;
2270         }
2271     }
2272 
2273   format = (0 <= format_opt ? format_opt
2274             : ls_mode == LS_LS ? (stdout_isatty ()
2275                                   ? many_per_line : one_per_line)
2276             : ls_mode == LS_MULTI_COL ? many_per_line
2277             : /* ls_mode == LS_LONG_FORMAT */ long_format);
2278 
2279   /* If the line length was not set by a switch but is needed to determine
2280      output, go to the work of obtaining it from the environment.  */
2281   ptrdiff_t linelen = width_opt;
2282   if (format == many_per_line || format == horizontal || format == with_commas
2283       || print_with_color)
2284     {
2285 #ifdef TIOCGWINSZ
2286       if (linelen < 0)
2287         {
2288           /* Suppress bogus warning re comparing ws.ws_col to big integer.  */
2289 # if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
2290 #  pragma GCC diagnostic push
2291 #  pragma GCC diagnostic ignored "-Wtype-limits"
2292 # endif
2293           struct winsize ws;
2294           if (stdout_isatty ()
2295               && 0 <= ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws)
2296               && 0 < ws.ws_col)
2297             linelen = ws.ws_col <= MIN (PTRDIFF_MAX, SIZE_MAX) ? ws.ws_col : 0;
2298 # if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
2299 #  pragma GCC diagnostic pop
2300 # endif
2301         }
2302 #endif
2303       if (linelen < 0)
2304         {
2305           char const *p = getenv ("COLUMNS");
2306           if (p && *p)
2307             {
2308               linelen = decode_line_length (p);
2309               if (linelen < 0)
2310                 error (0, 0,
2311                        _("ignoring invalid width"
2312                          " in environment variable COLUMNS: %s"),
2313                        quote (p));
2314             }
2315         }
2316     }
2317 
2318   line_length = linelen < 0 ? 80 : linelen;
2319 
2320   /* Determine the max possible number of display columns.  */
2321   max_idx = line_length / MIN_COLUMN_WIDTH;
2322   /* Account for first display column not having a separator,
2323      or line_lengths shorter than MIN_COLUMN_WIDTH.  */
2324   max_idx += line_length % MIN_COLUMN_WIDTH != 0;
2325 
2326   if (format == many_per_line || format == horizontal || format == with_commas)
2327     {
2328       if (0 <= tabsize_opt)
2329         tabsize = tabsize_opt;
2330       else
2331         {
2332           tabsize = 8;
2333           char const *p = getenv ("TABSIZE");
2334           if (p)
2335             {
2336               uintmax_t tmp;
2337               if (xstrtoumax (p, nullptr, 0, &tmp, "") == LONGINT_OK
2338                   && tmp <= SIZE_MAX)
2339                 tabsize = tmp;
2340               else
2341                 error (0, 0,
2342                        _("ignoring invalid tab size"
2343                          " in environment variable TABSIZE: %s"),
2344                        quote (p));
2345             }
2346         }
2347     }
2348 
2349   qmark_funny_chars = (hide_control_chars_opt < 0
2350                        ? ls_mode == LS_LS && stdout_isatty ()
2351                        : hide_control_chars_opt);
2352 
2353   int qs = quoting_style_opt;
2354   if (qs < 0)
2355     qs = getenv_quoting_style ();
2356   if (qs < 0)
2357     qs = (ls_mode == LS_LS
2358           ? (stdout_isatty () ? shell_escape_quoting_style : -1)
2359           : escape_quoting_style);
2360   if (0 <= qs)
2361     set_quoting_style (nullptr, qs);
2362   qs = get_quoting_style (nullptr);
2363   align_variable_outer_quotes
2364     = ((format == long_format
2365         || ((format == many_per_line || format == horizontal) && line_length))
2366        && (qs == shell_quoting_style
2367            || qs == shell_escape_quoting_style
2368            || qs == c_maybe_quoting_style));
2369   filename_quoting_options = clone_quoting_options (nullptr);
2370   if (qs == escape_quoting_style)
2371     set_char_quoting (filename_quoting_options, ' ', 1);
2372   if (file_type <= indicator_style)
2373     {
2374       char const *p;
2375       for (p = &"*=>@|"[indicator_style - file_type]; *p; p++)
2376         set_char_quoting (filename_quoting_options, *p, 1);
2377     }
2378 
2379   dirname_quoting_options = clone_quoting_options (nullptr);
2380   set_char_quoting (dirname_quoting_options, ':', 1);
2381 
2382   /* --dired implies --format=long (-l) and sans --hyperlink.
2383      So ignore it if those overridden.  */
2384   dired &= (format == long_format) & !print_hyperlink;
2385 
2386   if (eolbyte < dired)
2387     error (LS_FAILURE, 0, _("--dired and --zero are incompatible"));
2388 
2389   /* If -c or -u is specified and not -l (or any other option that implies -l),
2390      and no sort-type was specified, then sort by the ctime (-c) or atime (-u).
2391      The behavior of ls when using either -c or -u but with neither -l nor -t
2392      appears to be unspecified by POSIX.  So, with GNU ls, '-u' alone means
2393      sort by atime (this is the one that's not specified by the POSIX spec),
2394      -lu means show atime and sort by name, -lut means show atime and sort
2395      by atime.  */
2396 
2397   sort_type = (0 <= sort_opt ? sort_opt
2398                : (format != long_format
2399                   && (time_type == time_ctime || time_type == time_atime
2400                       || time_type == time_btime))
2401                ? sort_time : sort_name);
2402 
2403   if (format == long_format)
2404     {
2405       char *style = time_style_option;
2406       static char const posix_prefix[] = "posix-";
2407 
2408       if (! style)
2409         if (! (style = getenv ("TIME_STYLE")))
2410           style = bad_cast ("locale");
2411 
2412       while (STREQ_LEN (style, posix_prefix, sizeof posix_prefix - 1))
2413         {
2414           if (! hard_locale (LC_TIME))
2415             return optind;
2416           style += sizeof posix_prefix - 1;
2417         }
2418 
2419       if (*style == '+')
2420         {
2421           char *p0 = style + 1;
2422           char *p1 = strchr (p0, '\n');
2423           if (! p1)
2424             p1 = p0;
2425           else
2426             {
2427               if (strchr (p1 + 1, '\n'))
2428                 error (LS_FAILURE, 0, _("invalid time style format %s"),
2429                        quote (p0));
2430               *p1++ = '\0';
2431             }
2432           long_time_format[0] = p0;
2433           long_time_format[1] = p1;
2434         }
2435       else
2436         {
2437           ptrdiff_t res = argmatch (style, time_style_args,
2438                                     (char const *) time_style_types,
2439                                     sizeof (*time_style_types));
2440           if (res < 0)
2441             {
2442               /* This whole block used to be a simple use of XARGMATCH.
2443                  but that didn't print the "posix-"-prefixed variants or
2444                  the "+"-prefixed format string option upon failure.  */
2445               argmatch_invalid ("time style", style, res);
2446 
2447               /* The following is a manual expansion of argmatch_valid,
2448                  but with the added "+ ..." description and the [posix-]
2449                  prefixes prepended.  Note that this simplification works
2450                  only because all four existing time_style_types values
2451                  are distinct.  */
2452               fputs (_("Valid arguments are:\n"), stderr);
2453               char const *const *p = time_style_args;
2454               while (*p)
2455                 fprintf (stderr, "  - [posix-]%s\n", *p++);
2456               fputs (_("  - +FORMAT (e.g., +%H:%M) for a 'date'-style"
2457                        " format\n"), stderr);
2458               usage (LS_FAILURE);
2459             }
2460           switch (res)
2461             {
2462             case full_iso_time_style:
2463               long_time_format[0] = long_time_format[1] =
2464                 "%Y-%m-%d %H:%M:%S.%N %z";
2465               break;
2466 
2467             case long_iso_time_style:
2468               long_time_format[0] = long_time_format[1] = "%Y-%m-%d %H:%M";
2469               break;
2470 
2471             case iso_time_style:
2472               long_time_format[0] = "%Y-%m-%d ";
2473               long_time_format[1] = "%m-%d %H:%M";
2474               break;
2475 
2476             case locale_time_style:
2477               if (hard_locale (LC_TIME))
2478                 {
2479                   for (int i = 0; i < 2; i++)
2480                     long_time_format[i] =
2481                       dcgettext (nullptr, long_time_format[i], LC_TIME);
2482                 }
2483             }
2484         }
2485 
2486       abformat_init ();
2487     }
2488 
2489   return optind;
2490 }
2491 
2492 /* Parse a string as part of the LS_COLORS variable; this may involve
2493    decoding all kinds of escape characters.  If equals_end is set an
2494    unescaped equal sign ends the string, otherwise only a : or \0
2495    does.  Set *OUTPUT_COUNT to the number of bytes output.  Return
2496    true if successful.
2497 
2498    The resulting string is *not* null-terminated, but may contain
2499    embedded nulls.
2500 
2501    Note that both dest and src are char **; on return they point to
2502    the first free byte after the array and the character that ended
2503    the input string, respectively.  */
2504 
2505 static bool
get_funky_string(char ** dest,char const ** src,bool equals_end,size_t * output_count)2506 get_funky_string (char **dest, char const **src, bool equals_end,
2507                   size_t *output_count)
2508 {
2509   char num;			/* For numerical codes */
2510   size_t count;			/* Something to count with */
2511   enum {
2512     ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
2513   } state;
2514   char const *p;
2515   char *q;
2516 
2517   p = *src;			/* We don't want to double-indirect */
2518   q = *dest;			/* the whole darn time.  */
2519 
2520   count = 0;			/* No characters counted in yet.  */
2521   num = 0;
2522 
2523   state = ST_GND;		/* Start in ground state.  */
2524   while (state < ST_END)
2525     {
2526       switch (state)
2527         {
2528         case ST_GND:		/* Ground state (no escapes) */
2529           switch (*p)
2530             {
2531             case ':':
2532             case '\0':
2533               state = ST_END;	/* End of string */
2534               break;
2535             case '\\':
2536               state = ST_BACKSLASH; /* Backslash escape sequence */
2537               ++p;
2538               break;
2539             case '^':
2540               state = ST_CARET; /* Caret escape */
2541               ++p;
2542               break;
2543             case '=':
2544               if (equals_end)
2545                 {
2546                   state = ST_END; /* End */
2547                   break;
2548                 }
2549               FALLTHROUGH;
2550             default:
2551               *(q++) = *(p++);
2552               ++count;
2553               break;
2554             }
2555           break;
2556 
2557         case ST_BACKSLASH:	/* Backslash escaped character */
2558           switch (*p)
2559             {
2560             case '0':
2561             case '1':
2562             case '2':
2563             case '3':
2564             case '4':
2565             case '5':
2566             case '6':
2567             case '7':
2568               state = ST_OCTAL;	/* Octal sequence */
2569               num = *p - '0';
2570               break;
2571             case 'x':
2572             case 'X':
2573               state = ST_HEX;	/* Hex sequence */
2574               num = 0;
2575               break;
2576             case 'a':		/* Bell */
2577               num = '\a';
2578               break;
2579             case 'b':		/* Backspace */
2580               num = '\b';
2581               break;
2582             case 'e':		/* Escape */
2583               num = 27;
2584               break;
2585             case 'f':		/* Form feed */
2586               num = '\f';
2587               break;
2588             case 'n':		/* Newline */
2589               num = '\n';
2590               break;
2591             case 'r':		/* Carriage return */
2592               num = '\r';
2593               break;
2594             case 't':		/* Tab */
2595               num = '\t';
2596               break;
2597             case 'v':		/* Vtab */
2598               num = '\v';
2599               break;
2600             case '?':		/* Delete */
2601               num = 127;
2602               break;
2603             case '_':		/* Space */
2604               num = ' ';
2605               break;
2606             case '\0':		/* End of string */
2607               state = ST_ERROR;	/* Error! */
2608               break;
2609             default:		/* Escaped character like \ ^ : = */
2610               num = *p;
2611               break;
2612             }
2613           if (state == ST_BACKSLASH)
2614             {
2615               *(q++) = num;
2616               ++count;
2617               state = ST_GND;
2618             }
2619           ++p;
2620           break;
2621 
2622         case ST_OCTAL:		/* Octal sequence */
2623           if (*p < '0' || *p > '7')
2624             {
2625               *(q++) = num;
2626               ++count;
2627               state = ST_GND;
2628             }
2629           else
2630             num = (num << 3) + (*(p++) - '0');
2631           break;
2632 
2633         case ST_HEX:		/* Hex sequence */
2634           switch (*p)
2635             {
2636             case '0':
2637             case '1':
2638             case '2':
2639             case '3':
2640             case '4':
2641             case '5':
2642             case '6':
2643             case '7':
2644             case '8':
2645             case '9':
2646               num = (num << 4) + (*(p++) - '0');
2647               break;
2648             case 'a':
2649             case 'b':
2650             case 'c':
2651             case 'd':
2652             case 'e':
2653             case 'f':
2654               num = (num << 4) + (*(p++) - 'a') + 10;
2655               break;
2656             case 'A':
2657             case 'B':
2658             case 'C':
2659             case 'D':
2660             case 'E':
2661             case 'F':
2662               num = (num << 4) + (*(p++) - 'A') + 10;
2663               break;
2664             default:
2665               *(q++) = num;
2666               ++count;
2667               state = ST_GND;
2668               break;
2669             }
2670           break;
2671 
2672         case ST_CARET:		/* Caret escape */
2673           state = ST_GND;	/* Should be the next state... */
2674           if (*p >= '@' && *p <= '~')
2675             {
2676               *(q++) = *(p++) & 037;
2677               ++count;
2678             }
2679           else if (*p == '?')
2680             {
2681               *(q++) = 127;
2682               ++count;
2683             }
2684           else
2685             state = ST_ERROR;
2686           break;
2687 
2688         default:
2689           unreachable ();
2690         }
2691     }
2692 
2693   *dest = q;
2694   *src = p;
2695   *output_count = count;
2696 
2697   return state != ST_ERROR;
2698 }
2699 
2700 enum parse_state
2701   {
2702     PS_START = 1,
2703     PS_2,
2704     PS_3,
2705     PS_4,
2706     PS_DONE,
2707     PS_FAIL
2708   };
2709 
2710 
2711 /* Check if the content of TERM is a valid name in dircolors.  */
2712 
2713 static bool
known_term_type(void)2714 known_term_type (void)
2715 {
2716   char const *term = getenv ("TERM");
2717   if (! term || ! *term)
2718     return false;
2719 
2720   char const *line = G_line;
2721   while (line - G_line < sizeof (G_line))
2722     {
2723       if (STRNCMP_LIT (line, "TERM ") == 0)
2724         {
2725           if (fnmatch (line + 5, term, 0) == 0)
2726             return true;
2727         }
2728       line += strlen (line) + 1;
2729     }
2730 
2731   return false;
2732 }
2733 
2734 static void
parse_ls_color(void)2735 parse_ls_color (void)
2736 {
2737   char const *p;		/* Pointer to character being parsed */
2738   char *buf;			/* color_buf buffer pointer */
2739   int ind_no;			/* Indicator number */
2740   char label[3];		/* Indicator label */
2741   struct color_ext_type *ext;	/* Extension we are working on */
2742 
2743   if ((p = getenv ("LS_COLORS")) == nullptr || *p == '\0')
2744     {
2745       /* LS_COLORS takes precedence, but if that's not set then
2746          honor the COLORTERM and TERM env variables so that
2747          we only go with the internal ANSI color codes if the
2748          former is non empty or the latter is set to a known value.  */
2749       char const *colorterm = getenv ("COLORTERM");
2750       if (! (colorterm && *colorterm) && ! known_term_type ())
2751         print_with_color = false;
2752       return;
2753     }
2754 
2755   ext = nullptr;
2756   strcpy (label, "??");
2757 
2758   /* This is an overly conservative estimate, but any possible
2759      LS_COLORS string will *not* generate a color_buf longer than
2760      itself, so it is a safe way of allocating a buffer in
2761      advance.  */
2762   buf = color_buf = xstrdup (p);
2763 
2764   enum parse_state state = PS_START;
2765   while (true)
2766     {
2767       switch (state)
2768         {
2769         case PS_START:		/* First label character */
2770           switch (*p)
2771             {
2772             case ':':
2773               ++p;
2774               break;
2775 
2776             case '*':
2777               /* Allocate new extension block and add to head of
2778                  linked list (this way a later definition will
2779                  override an earlier one, which can be useful for
2780                  having terminal-specific defs override global).  */
2781 
2782               ext = xmalloc (sizeof *ext);
2783               ext->next = color_ext_list;
2784               color_ext_list = ext;
2785               ext->exact_match = false;
2786 
2787               ++p;
2788               ext->ext.string = buf;
2789 
2790               state = (get_funky_string (&buf, &p, true, &ext->ext.len)
2791                        ? PS_4 : PS_FAIL);
2792               break;
2793 
2794             case '\0':
2795               state = PS_DONE;	/* Done! */
2796               goto done;
2797 
2798             default:	/* Assume it is file type label */
2799               label[0] = *(p++);
2800               state = PS_2;
2801               break;
2802             }
2803           break;
2804 
2805         case PS_2:		/* Second label character */
2806           if (*p)
2807             {
2808               label[1] = *(p++);
2809               state = PS_3;
2810             }
2811           else
2812             state = PS_FAIL;	/* Error */
2813           break;
2814 
2815         case PS_3:		/* Equal sign after indicator label */
2816           state = PS_FAIL;	/* Assume failure...  */
2817           if (*(p++) == '=')/* It *should* be...  */
2818             {
2819               for (ind_no = 0; indicator_name[ind_no] != nullptr; ++ind_no)
2820                 {
2821                   if (STREQ (label, indicator_name[ind_no]))
2822                     {
2823                       color_indicator[ind_no].string = buf;
2824                       state = (get_funky_string (&buf, &p, false,
2825                                                  &color_indicator[ind_no].len)
2826                                ? PS_START : PS_FAIL);
2827                       break;
2828                     }
2829                 }
2830               if (state == PS_FAIL)
2831                 error (0, 0, _("unrecognized prefix: %s"), quote (label));
2832             }
2833           break;
2834 
2835         case PS_4:		/* Equal sign after *.ext */
2836           if (*(p++) == '=')
2837             {
2838               ext->seq.string = buf;
2839               state = (get_funky_string (&buf, &p, false, &ext->seq.len)
2840                        ? PS_START : PS_FAIL);
2841             }
2842           else
2843             state = PS_FAIL;
2844           break;
2845 
2846         case PS_FAIL:
2847           goto done;
2848 
2849         default:
2850           affirm (false);
2851         }
2852     }
2853  done:
2854 
2855   if (state == PS_FAIL)
2856     {
2857       struct color_ext_type *e;
2858       struct color_ext_type *e2;
2859 
2860       error (0, 0,
2861              _("unparsable value for LS_COLORS environment variable"));
2862       free (color_buf);
2863       for (e = color_ext_list; e != nullptr; /* empty */)
2864         {
2865           e2 = e;
2866           e = e->next;
2867           free (e2);
2868         }
2869       print_with_color = false;
2870     }
2871   else
2872     {
2873       /* Postprocess list to set EXACT_MATCH on entries where there are
2874          different cased extensions with separate sequences defined.
2875          Also set ext.len to SIZE_MAX on any entries that can't
2876          match due to precedence, to avoid redundant string compares.  */
2877       struct color_ext_type *e1;
2878 
2879       for (e1 = color_ext_list; e1 != nullptr; e1 = e1->next)
2880         {
2881           struct color_ext_type *e2;
2882           bool case_ignored = false;
2883 
2884           for (e2 = e1->next; e2 != nullptr; e2 = e2->next)
2885             {
2886               if (e2->ext.len < SIZE_MAX && e1->ext.len == e2->ext.len)
2887                 {
2888                   if (memcmp (e1->ext.string, e2->ext.string, e1->ext.len) == 0)
2889                     e2->ext.len = SIZE_MAX; /* Ignore */
2890                   else if (c_strncasecmp (e1->ext.string, e2->ext.string,
2891                                           e1->ext.len) == 0)
2892                     {
2893                       if (case_ignored)
2894                         {
2895                           e2->ext.len = SIZE_MAX; /* Ignore */
2896                         }
2897                       else if (e1->seq.len == e2->seq.len
2898                                && memcmp (e1->seq.string, e2->seq.string,
2899                                           e1->seq.len) == 0)
2900                         {
2901                           e2->ext.len = SIZE_MAX; /* Ignore */
2902                           case_ignored = true;    /* Ignore all subsequent */
2903                         }
2904                       else
2905                         {
2906                           e1->exact_match = true;
2907                           e2->exact_match = true;
2908                         }
2909                     }
2910                 }
2911             }
2912         }
2913     }
2914 
2915   if (color_indicator[C_LINK].len == 6
2916       && !STRNCMP_LIT (color_indicator[C_LINK].string, "target"))
2917     color_symlink_as_referent = true;
2918 }
2919 
2920 /* Return the quoting style specified by the environment variable
2921    QUOTING_STYLE if set and valid, -1 otherwise.  */
2922 
2923 static int
getenv_quoting_style(void)2924 getenv_quoting_style (void)
2925 {
2926   char const *q_style = getenv ("QUOTING_STYLE");
2927   if (!q_style)
2928     return -1;
2929   int i = ARGMATCH (q_style, quoting_style_args, quoting_style_vals);
2930   if (i < 0)
2931     {
2932       error (0, 0,
2933              _("ignoring invalid value"
2934                " of environment variable QUOTING_STYLE: %s"),
2935              quote (q_style));
2936       return -1;
2937     }
2938   return quoting_style_vals[i];
2939 }
2940 
2941 /* Set the exit status to report a failure.  If SERIOUS, it is a
2942    serious failure; otherwise, it is merely a minor problem.  */
2943 
2944 static void
set_exit_status(bool serious)2945 set_exit_status (bool serious)
2946 {
2947   if (serious)
2948     exit_status = LS_FAILURE;
2949   else if (exit_status == EXIT_SUCCESS)
2950     exit_status = LS_MINOR_PROBLEM;
2951 }
2952 
2953 /* Assuming a failure is serious if SERIOUS, use the printf-style
2954    MESSAGE to report the failure to access a file named FILE.  Assume
2955    errno is set appropriately for the failure.  */
2956 
2957 static void
file_failure(bool serious,char const * message,char const * file)2958 file_failure (bool serious, char const *message, char const *file)
2959 {
2960   error (0, errno, message, quoteaf (file));
2961   set_exit_status (serious);
2962 }
2963 
2964 /* Request that the directory named NAME have its contents listed later.
2965    If REALNAME is nonzero, it will be used instead of NAME when the
2966    directory name is printed.  This allows symbolic links to directories
2967    to be treated as regular directories but still be listed under their
2968    real names.  NAME == nullptr is used to insert a marker entry for the
2969    directory named in REALNAME.
2970    If NAME is non-null, we use its dev/ino information to save
2971    a call to stat -- when doing a recursive (-R) traversal.
2972    COMMAND_LINE_ARG means this directory was mentioned on the command line.  */
2973 
2974 static void
queue_directory(char const * name,char const * realname,bool command_line_arg)2975 queue_directory (char const *name, char const *realname, bool command_line_arg)
2976 {
2977   struct pending *new = xmalloc (sizeof *new);
2978   new->realname = realname ? xstrdup (realname) : nullptr;
2979   new->name = name ? xstrdup (name) : nullptr;
2980   new->command_line_arg = command_line_arg;
2981   new->next = pending_dirs;
2982   pending_dirs = new;
2983 }
2984 
2985 /* Read directory NAME, and list the files in it.
2986    If REALNAME is nonzero, print its name instead of NAME;
2987    this is used for symbolic links to directories.
2988    COMMAND_LINE_ARG means this directory was mentioned on the command line.  */
2989 
2990 static void
print_dir(char const * name,char const * realname,bool command_line_arg)2991 print_dir (char const *name, char const *realname, bool command_line_arg)
2992 {
2993   DIR *dirp;
2994   struct dirent *next;
2995   uintmax_t total_blocks = 0;
2996   static bool first = true;
2997 
2998   errno = 0;
2999   dirp = opendir (name);
3000   if (!dirp)
3001     {
3002       file_failure (command_line_arg, _("cannot open directory %s"), name);
3003       return;
3004     }
3005 
3006   if (LOOP_DETECT)
3007     {
3008       struct stat dir_stat;
3009       int fd = dirfd (dirp);
3010 
3011       /* If dirfd failed, endure the overhead of stat'ing by path  */
3012       if ((0 <= fd
3013            ? fstat_for_ino (fd, &dir_stat)
3014            : stat_for_ino (name, &dir_stat)) < 0)
3015         {
3016           file_failure (command_line_arg,
3017                         _("cannot determine device and inode of %s"), name);
3018           closedir (dirp);
3019           return;
3020         }
3021 
3022       /* If we've already visited this dev/inode pair, warn that
3023          we've found a loop, and do not process this directory.  */
3024       if (visit_dir (dir_stat.st_dev, dir_stat.st_ino))
3025         {
3026           error (0, 0, _("%s: not listing already-listed directory"),
3027                  quotef (name));
3028           closedir (dirp);
3029           set_exit_status (true);
3030           return;
3031         }
3032 
3033       dev_ino_push (dir_stat.st_dev, dir_stat.st_ino);
3034     }
3035 
3036   clear_files ();
3037 
3038   if (recursive || print_dir_name)
3039     {
3040       if (!first)
3041         dired_outbyte ('\n');
3042       first = false;
3043       dired_indent ();
3044 
3045       char *absolute_name = nullptr;
3046       if (print_hyperlink)
3047         {
3048           absolute_name = canonicalize_filename_mode (name, CAN_MISSING);
3049           if (! absolute_name)
3050             file_failure (command_line_arg,
3051                           _("error canonicalizing %s"), name);
3052         }
3053       quote_name (realname ? realname : name, dirname_quoting_options, -1,
3054                   nullptr, true, &subdired_obstack, absolute_name);
3055 
3056       free (absolute_name);
3057 
3058       dired_outstring (":\n");
3059     }
3060 
3061   /* Read the directory entries, and insert the subfiles into the 'cwd_file'
3062      table.  */
3063 
3064   while (true)
3065     {
3066       /* Set errno to zero so we can distinguish between a readdir failure
3067          and when readdir simply finds that there are no more entries.  */
3068       errno = 0;
3069       next = readdir (dirp);
3070       if (next)
3071         {
3072           if (! file_ignored (next->d_name))
3073             {
3074               enum filetype type = unknown;
3075 
3076 #if HAVE_STRUCT_DIRENT_D_TYPE
3077               switch (next->d_type)
3078                 {
3079                 case DT_BLK:  type = blockdev;		break;
3080                 case DT_CHR:  type = chardev;		break;
3081                 case DT_DIR:  type = directory;		break;
3082                 case DT_FIFO: type = fifo;		break;
3083                 case DT_LNK:  type = symbolic_link;	break;
3084                 case DT_REG:  type = normal;		break;
3085                 case DT_SOCK: type = sock;		break;
3086 # ifdef DT_WHT
3087                 case DT_WHT:  type = whiteout;		break;
3088 # endif
3089                 }
3090 #endif
3091               total_blocks += gobble_file (next->d_name, type,
3092                                            RELIABLE_D_INO (next),
3093                                            false, name);
3094 
3095               /* In this narrow case, print out each name right away, so
3096                  ls uses constant memory while processing the entries of
3097                  this directory.  Useful when there are many (millions)
3098                  of entries in a directory.  */
3099               if (format == one_per_line && sort_type == sort_none
3100                       && !print_block_size && !recursive)
3101                 {
3102                   /* We must call sort_files in spite of
3103                      "sort_type == sort_none" for its initialization
3104                      of the sorted_file vector.  */
3105                   sort_files ();
3106                   print_current_files ();
3107                   clear_files ();
3108                 }
3109             }
3110         }
3111       else if (errno != 0)
3112         {
3113           file_failure (command_line_arg, _("reading directory %s"), name);
3114           if (errno != EOVERFLOW)
3115             break;
3116         }
3117       else
3118         break;
3119 
3120       /* When processing a very large directory, and since we've inhibited
3121          interrupts, this loop would take so long that ls would be annoyingly
3122          uninterruptible.  This ensures that it handles signals promptly.  */
3123       process_signals ();
3124     }
3125 
3126   if (closedir (dirp) != 0)
3127     {
3128       file_failure (command_line_arg, _("closing directory %s"), name);
3129       /* Don't return; print whatever we got.  */
3130     }
3131 
3132   /* Sort the directory contents.  */
3133   sort_files ();
3134 
3135   /* If any member files are subdirectories, perhaps they should have their
3136      contents listed rather than being mentioned here as files.  */
3137 
3138   if (recursive)
3139     extract_dirs_from_files (name, false);
3140 
3141   if (format == long_format || print_block_size)
3142     {
3143       char buf[LONGEST_HUMAN_READABLE + 3];
3144       char *p = human_readable (total_blocks, buf + 1, human_output_opts,
3145                                 ST_NBLOCKSIZE, output_block_size);
3146       char *pend = p + strlen (p);
3147       *--p = ' ';
3148       *pend++ = eolbyte;
3149       dired_indent ();
3150       dired_outstring (_("total"));
3151       dired_outbuf (p, pend - p);
3152     }
3153 
3154   if (cwd_n_used)
3155     print_current_files ();
3156 }
3157 
3158 /* Add 'pattern' to the list of patterns for which files that match are
3159    not listed.  */
3160 
3161 static void
add_ignore_pattern(char const * pattern)3162 add_ignore_pattern (char const *pattern)
3163 {
3164   struct ignore_pattern *ignore;
3165 
3166   ignore = xmalloc (sizeof *ignore);
3167   ignore->pattern = pattern;
3168   /* Add it to the head of the linked list.  */
3169   ignore->next = ignore_patterns;
3170   ignore_patterns = ignore;
3171 }
3172 
3173 /* Return true if one of the PATTERNS matches FILE.  */
3174 
3175 static bool
patterns_match(struct ignore_pattern const * patterns,char const * file)3176 patterns_match (struct ignore_pattern const *patterns, char const *file)
3177 {
3178   struct ignore_pattern const *p;
3179   for (p = patterns; p; p = p->next)
3180     if (fnmatch (p->pattern, file, FNM_PERIOD) == 0)
3181       return true;
3182   return false;
3183 }
3184 
3185 /* Return true if FILE should be ignored.  */
3186 
3187 static bool
file_ignored(char const * name)3188 file_ignored (char const *name)
3189 {
3190   return ((ignore_mode != IGNORE_MINIMAL
3191            && name[0] == '.'
3192            && (ignore_mode == IGNORE_DEFAULT || ! name[1 + (name[1] == '.')]))
3193           || (ignore_mode == IGNORE_DEFAULT
3194               && patterns_match (hide_patterns, name))
3195           || patterns_match (ignore_patterns, name));
3196 }
3197 
3198 /* POSIX requires that a file size be printed without a sign, even
3199    when negative.  Assume the typical case where negative sizes are
3200    actually positive values that have wrapped around.  */
3201 
3202 static uintmax_t
unsigned_file_size(off_t size)3203 unsigned_file_size (off_t size)
3204 {
3205   return size + (size < 0) * ((uintmax_t) OFF_T_MAX - OFF_T_MIN + 1);
3206 }
3207 
3208 #ifdef HAVE_CAP
3209 /* Return true if NAME has a capability (see linux/capability.h) */
3210 static bool
has_capability(char const * name)3211 has_capability (char const *name)
3212 {
3213   char *result;
3214   bool has_cap;
3215 
3216   cap_t cap_d = cap_get_file (name);
3217   if (cap_d == nullptr)
3218     return false;
3219 
3220   result = cap_to_text (cap_d, nullptr);
3221   cap_free (cap_d);
3222   if (!result)
3223     return false;
3224 
3225   /* check if human-readable capability string is empty */
3226   has_cap = !!*result;
3227 
3228   cap_free (result);
3229   return has_cap;
3230 }
3231 #else
3232 static bool
has_capability(MAYBE_UNUSED char const * name)3233 has_capability (MAYBE_UNUSED char const *name)
3234 {
3235   errno = ENOTSUP;
3236   return false;
3237 }
3238 #endif
3239 
3240 /* Enter and remove entries in the table 'cwd_file'.  */
3241 
3242 static void
free_ent(struct fileinfo * f)3243 free_ent (struct fileinfo *f)
3244 {
3245   free (f->name);
3246   free (f->linkname);
3247   free (f->absolute_name);
3248   if (f->scontext != UNKNOWN_SECURITY_CONTEXT)
3249     {
3250       if (is_smack_enabled ())
3251         free (f->scontext);
3252       else
3253         freecon (f->scontext);
3254     }
3255 }
3256 
3257 /* Empty the table of files.  */
3258 static void
clear_files(void)3259 clear_files (void)
3260 {
3261   for (size_t i = 0; i < cwd_n_used; i++)
3262     {
3263       struct fileinfo *f = sorted_file[i];
3264       free_ent (f);
3265     }
3266 
3267   cwd_n_used = 0;
3268   cwd_some_quoted = false;
3269   any_has_acl = false;
3270   inode_number_width = 0;
3271   block_size_width = 0;
3272   nlink_width = 0;
3273   owner_width = 0;
3274   group_width = 0;
3275   author_width = 0;
3276   scontext_width = 0;
3277   major_device_number_width = 0;
3278   minor_device_number_width = 0;
3279   file_size_width = 0;
3280 }
3281 
3282 /* Return true if ERR implies lack-of-support failure by a
3283    getxattr-calling function like getfilecon or file_has_acl.  */
3284 static bool
errno_unsupported(int err)3285 errno_unsupported (int err)
3286 {
3287   return (err == EINVAL || err == ENOSYS || is_ENOTSUP (err));
3288 }
3289 
3290 /* Cache *getfilecon failure, when it's trivial to do so.
3291    Like getfilecon/lgetfilecon, but when F's st_dev says it's doesn't
3292    support getting the security context, fail with ENOTSUP immediately.  */
3293 static int
getfilecon_cache(char const * file,struct fileinfo * f,bool deref)3294 getfilecon_cache (char const *file, struct fileinfo *f, bool deref)
3295 {
3296   /* st_dev of the most recently processed device for which we've
3297      found that [l]getfilecon fails indicating lack of support.  */
3298   static dev_t unsupported_device;
3299 
3300   if (f->stat.st_dev == unsupported_device)
3301     {
3302       errno = ENOTSUP;
3303       return -1;
3304     }
3305   int r = 0;
3306 #ifdef HAVE_SMACK
3307   if (is_smack_enabled ())
3308     r = smack_new_label_from_path (file, "security.SMACK64", deref,
3309                                    &f->scontext);
3310   else
3311 #endif
3312     r = (deref
3313          ? getfilecon (file, &f->scontext)
3314          : lgetfilecon (file, &f->scontext));
3315   if (r < 0 && errno_unsupported (errno))
3316     unsupported_device = f->stat.st_dev;
3317   return r;
3318 }
3319 
3320 /* Cache file_has_acl failure, when it's trivial to do.
3321    Like file_has_acl, but when F's st_dev says it's on a file
3322    system lacking ACL support, return 0 with ENOTSUP immediately.  */
3323 static int
file_has_acl_cache(char const * file,struct fileinfo * f)3324 file_has_acl_cache (char const *file, struct fileinfo *f)
3325 {
3326   /* st_dev of the most recently processed device for which we've
3327      found that file_has_acl fails indicating lack of support.  */
3328   static dev_t unsupported_device;
3329 
3330   if (f->stat.st_dev == unsupported_device)
3331     {
3332       errno = ENOTSUP;
3333       return 0;
3334     }
3335 
3336   /* Zero errno so that we can distinguish between two 0-returning cases:
3337      "has-ACL-support, but only a default ACL" and "no ACL support". */
3338   errno = 0;
3339   int n = file_has_acl (file, &f->stat);
3340   if (n <= 0 && errno_unsupported (errno))
3341     unsupported_device = f->stat.st_dev;
3342   return n;
3343 }
3344 
3345 /* Cache has_capability failure, when it's trivial to do.
3346    Like has_capability, but when F's st_dev says it's on a file
3347    system lacking capability support, return 0 with ENOTSUP immediately.  */
3348 static bool
has_capability_cache(char const * file,struct fileinfo * f)3349 has_capability_cache (char const *file, struct fileinfo *f)
3350 {
3351   /* st_dev of the most recently processed device for which we've
3352      found that has_capability fails indicating lack of support.  */
3353   static dev_t unsupported_device;
3354 
3355   if (f->stat.st_dev == unsupported_device)
3356     {
3357       errno = ENOTSUP;
3358       return 0;
3359     }
3360 
3361   bool b = has_capability (file);
3362   if ( !b && errno_unsupported (errno))
3363     unsupported_device = f->stat.st_dev;
3364   return b;
3365 }
3366 
3367 static bool
needs_quoting(char const * name)3368 needs_quoting (char const *name)
3369 {
3370   char test[2];
3371   size_t len = quotearg_buffer (test, sizeof test , name, -1,
3372                                 filename_quoting_options);
3373   return *name != *test || strlen (name) != len;
3374 }
3375 
3376 /* Add a file to the current table of files.
3377    Verify that the file exists, and print an error message if it does not.
3378    Return the number of blocks that the file occupies.  */
3379 static uintmax_t
gobble_file(char const * name,enum filetype type,ino_t inode,bool command_line_arg,char const * dirname)3380 gobble_file (char const *name, enum filetype type, ino_t inode,
3381              bool command_line_arg, char const *dirname)
3382 {
3383   uintmax_t blocks = 0;
3384   struct fileinfo *f;
3385 
3386   /* An inode value prior to gobble_file necessarily came from readdir,
3387      which is not used for command line arguments.  */
3388   affirm (! command_line_arg || inode == NOT_AN_INODE_NUMBER);
3389 
3390   if (cwd_n_used == cwd_n_alloc)
3391     {
3392       cwd_file = xnrealloc (cwd_file, cwd_n_alloc, 2 * sizeof *cwd_file);
3393       cwd_n_alloc *= 2;
3394     }
3395 
3396   f = &cwd_file[cwd_n_used];
3397   memset (f, '\0', sizeof *f);
3398   f->stat.st_ino = inode;
3399   f->filetype = type;
3400 
3401   f->quoted = -1;
3402   if ((! cwd_some_quoted) && align_variable_outer_quotes)
3403     {
3404       /* Determine if any quoted for padding purposes.  */
3405       f->quoted = needs_quoting (name);
3406       if (f->quoted)
3407         cwd_some_quoted = 1;
3408     }
3409 
3410   if (command_line_arg
3411       || print_hyperlink
3412       || format_needs_stat
3413       /* When coloring a directory (we may know the type from
3414          direct.d_type), we have to stat it in order to indicate
3415          sticky and/or other-writable attributes.  */
3416       || (type == directory && print_with_color
3417           && (is_colored (C_OTHER_WRITABLE)
3418               || is_colored (C_STICKY)
3419               || is_colored (C_STICKY_OTHER_WRITABLE)))
3420       /* When dereferencing symlinks, the inode and type must come from
3421          stat, but readdir provides the inode and type of lstat.  */
3422       || ((print_inode || format_needs_type)
3423           && (type == symbolic_link || type == unknown)
3424           && (dereference == DEREF_ALWAYS
3425               || color_symlink_as_referent || check_symlink_mode))
3426       /* Command line dereferences are already taken care of by the above
3427          assertion that the inode number is not yet known.  */
3428       || (print_inode && inode == NOT_AN_INODE_NUMBER)
3429       || (format_needs_type
3430           && (type == unknown || command_line_arg
3431               /* --indicator-style=classify (aka -F)
3432                  requires that we stat each regular file
3433                  to see if it's executable.  */
3434               || (type == normal && (indicator_style == classify
3435                                      /* This is so that --color ends up
3436                                         highlighting files with these mode
3437                                         bits set even when options like -F are
3438                                         not specified.  Note we do a redundant
3439                                         stat in the very unlikely case where
3440                                         C_CAP is set but not the others. */
3441                                      || (print_with_color
3442                                          && (is_colored (C_EXEC)
3443                                              || is_colored (C_SETUID)
3444                                              || is_colored (C_SETGID)
3445                                              || is_colored (C_CAP)))
3446                                      )))))
3447 
3448     {
3449       /* Absolute name of this file.  */
3450       char *full_name;
3451       bool do_deref;
3452       int err;
3453 
3454       if (name[0] == '/' || dirname[0] == 0)
3455         full_name = (char *) name;
3456       else
3457         {
3458           full_name = alloca (strlen (name) + strlen (dirname) + 2);
3459           attach (full_name, dirname, name);
3460         }
3461 
3462       if (print_hyperlink)
3463         {
3464           f->absolute_name = canonicalize_filename_mode (full_name,
3465                                                          CAN_MISSING);
3466           if (! f->absolute_name)
3467             file_failure (command_line_arg,
3468                           _("error canonicalizing %s"), full_name);
3469         }
3470 
3471       switch (dereference)
3472         {
3473         case DEREF_ALWAYS:
3474           err = do_stat (full_name, &f->stat);
3475           do_deref = true;
3476           break;
3477 
3478         case DEREF_COMMAND_LINE_ARGUMENTS:
3479         case DEREF_COMMAND_LINE_SYMLINK_TO_DIR:
3480           if (command_line_arg)
3481             {
3482               bool need_lstat;
3483               err = do_stat (full_name, &f->stat);
3484               do_deref = true;
3485 
3486               if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)
3487                 break;
3488 
3489               need_lstat = (err < 0
3490                             ? (errno == ENOENT || errno == ELOOP)
3491                             : ! S_ISDIR (f->stat.st_mode));
3492               if (!need_lstat)
3493                 break;
3494 
3495               /* stat failed because of ENOENT || ELOOP, maybe indicating a
3496                  non-traversable symlink.  Or stat succeeded,
3497                  FULL_NAME does not refer to a directory,
3498                  and --dereference-command-line-symlink-to-dir is in effect.
3499                  Fall through so that we call lstat instead.  */
3500             }
3501           FALLTHROUGH;
3502 
3503         default: /* DEREF_NEVER */
3504           err = do_lstat (full_name, &f->stat);
3505           do_deref = false;
3506           break;
3507         }
3508 
3509       if (err != 0)
3510         {
3511           /* Failure to stat a command line argument leads to
3512              an exit status of 2.  For other files, stat failure
3513              provokes an exit status of 1.  */
3514           file_failure (command_line_arg,
3515                         _("cannot access %s"), full_name);
3516 
3517           f->scontext = UNKNOWN_SECURITY_CONTEXT;
3518 
3519           if (command_line_arg)
3520             return 0;
3521 
3522           f->name = xstrdup (name);
3523           cwd_n_used++;
3524 
3525           return 0;
3526         }
3527 
3528       f->stat_ok = true;
3529 
3530       /* Note has_capability() adds around 30% runtime to 'ls --color'  */
3531       if ((type == normal || S_ISREG (f->stat.st_mode))
3532           && print_with_color && is_colored (C_CAP))
3533         f->has_capability = has_capability_cache (full_name, f);
3534 
3535       if (format == long_format || print_scontext)
3536         {
3537           bool have_scontext = false;
3538           bool have_acl = false;
3539           int attr_len = getfilecon_cache (full_name, f, do_deref);
3540           err = (attr_len < 0);
3541 
3542           if (err == 0)
3543             {
3544               if (is_smack_enabled ())
3545                 have_scontext = ! STREQ ("_", f->scontext);
3546               else
3547                 have_scontext = ! STREQ ("unlabeled", f->scontext);
3548             }
3549           else
3550             {
3551               f->scontext = UNKNOWN_SECURITY_CONTEXT;
3552 
3553               /* When requesting security context information, don't make
3554                  ls fail just because the file (even a command line argument)
3555                  isn't on the right type of file system.  I.e., a getfilecon
3556                  failure isn't in the same class as a stat failure.  */
3557               if (is_ENOTSUP (errno) || errno == ENODATA)
3558                 err = 0;
3559             }
3560 
3561           if (err == 0 && format == long_format)
3562             {
3563               int n = file_has_acl_cache (full_name, f);
3564               err = (n < 0);
3565               have_acl = (0 < n);
3566             }
3567 
3568           f->acl_type = (!have_scontext && !have_acl
3569                          ? ACL_T_NONE
3570                          : (have_scontext && !have_acl
3571                             ? ACL_T_LSM_CONTEXT_ONLY
3572                             : ACL_T_YES));
3573           any_has_acl |= f->acl_type != ACL_T_NONE;
3574 
3575           if (err)
3576             error (0, errno, "%s", quotef (full_name));
3577         }
3578 
3579       if (S_ISLNK (f->stat.st_mode)
3580           && (format == long_format || check_symlink_mode))
3581         {
3582           struct stat linkstats;
3583 
3584           get_link_name (full_name, f, command_line_arg);
3585 
3586           /* Use the slower quoting path for this entry, though
3587              don't update CWD_SOME_QUOTED since alignment not affected.  */
3588           if (f->linkname && f->quoted == 0 && needs_quoting (f->linkname))
3589             f->quoted = -1;
3590 
3591           /* Avoid following symbolic links when possible, i.e., when
3592              they won't be traced and when no indicator is needed.  */
3593           if (f->linkname
3594               && (file_type <= indicator_style || check_symlink_mode)
3595               && stat_for_mode (full_name, &linkstats) == 0)
3596             {
3597               f->linkok = true;
3598               f->linkmode = linkstats.st_mode;
3599             }
3600         }
3601 
3602       if (S_ISLNK (f->stat.st_mode))
3603         f->filetype = symbolic_link;
3604       else if (S_ISDIR (f->stat.st_mode))
3605         {
3606           if (command_line_arg && !immediate_dirs)
3607             f->filetype = arg_directory;
3608           else
3609             f->filetype = directory;
3610         }
3611       else
3612         f->filetype = normal;
3613 
3614       blocks = STP_NBLOCKS (&f->stat);
3615       if (format == long_format || print_block_size)
3616         {
3617           char buf[LONGEST_HUMAN_READABLE + 1];
3618           int len = mbswidth (human_readable (blocks, buf, human_output_opts,
3619                                               ST_NBLOCKSIZE, output_block_size),
3620                               MBSWIDTH_FLAGS);
3621           if (block_size_width < len)
3622             block_size_width = len;
3623         }
3624 
3625       if (format == long_format)
3626         {
3627           if (print_owner)
3628             {
3629               int len = format_user_width (f->stat.st_uid);
3630               if (owner_width < len)
3631                 owner_width = len;
3632             }
3633 
3634           if (print_group)
3635             {
3636               int len = format_group_width (f->stat.st_gid);
3637               if (group_width < len)
3638                 group_width = len;
3639             }
3640 
3641           if (print_author)
3642             {
3643               int len = format_user_width (f->stat.st_author);
3644               if (author_width < len)
3645                 author_width = len;
3646             }
3647         }
3648 
3649       if (print_scontext)
3650         {
3651           int len = strlen (f->scontext);
3652           if (scontext_width < len)
3653             scontext_width = len;
3654         }
3655 
3656       if (format == long_format)
3657         {
3658           char b[INT_BUFSIZE_BOUND (uintmax_t)];
3659           int b_len = strlen (umaxtostr (f->stat.st_nlink, b));
3660           if (nlink_width < b_len)
3661             nlink_width = b_len;
3662 
3663           if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
3664             {
3665               char buf[INT_BUFSIZE_BOUND (uintmax_t)];
3666               int len = strlen (umaxtostr (major (f->stat.st_rdev), buf));
3667               if (major_device_number_width < len)
3668                 major_device_number_width = len;
3669               len = strlen (umaxtostr (minor (f->stat.st_rdev), buf));
3670               if (minor_device_number_width < len)
3671                 minor_device_number_width = len;
3672               len = major_device_number_width + 2 + minor_device_number_width;
3673               if (file_size_width < len)
3674                 file_size_width = len;
3675             }
3676           else
3677             {
3678               char buf[LONGEST_HUMAN_READABLE + 1];
3679               uintmax_t size = unsigned_file_size (f->stat.st_size);
3680               int len = mbswidth (human_readable (size, buf,
3681                                                   file_human_output_opts,
3682                                                   1, file_output_block_size),
3683                                   MBSWIDTH_FLAGS);
3684               if (file_size_width < len)
3685                 file_size_width = len;
3686             }
3687         }
3688     }
3689 
3690   if (print_inode)
3691     {
3692       char buf[INT_BUFSIZE_BOUND (uintmax_t)];
3693       int len = strlen (umaxtostr (f->stat.st_ino, buf));
3694       if (inode_number_width < len)
3695         inode_number_width = len;
3696     }
3697 
3698   f->name = xstrdup (name);
3699   cwd_n_used++;
3700 
3701   return blocks;
3702 }
3703 
3704 /* Return true if F refers to a directory.  */
3705 static bool
is_directory(const struct fileinfo * f)3706 is_directory (const struct fileinfo *f)
3707 {
3708   return f->filetype == directory || f->filetype == arg_directory;
3709 }
3710 
3711 /* Return true if F refers to a (symlinked) directory.  */
3712 static bool
is_linked_directory(const struct fileinfo * f)3713 is_linked_directory (const struct fileinfo *f)
3714 {
3715   return f->filetype == directory || f->filetype == arg_directory
3716          || S_ISDIR (f->linkmode);
3717 }
3718 
3719 /* Put the name of the file that FILENAME is a symbolic link to
3720    into the LINKNAME field of 'f'.  COMMAND_LINE_ARG indicates whether
3721    FILENAME is a command-line argument.  */
3722 
3723 static void
get_link_name(char const * filename,struct fileinfo * f,bool command_line_arg)3724 get_link_name (char const *filename, struct fileinfo *f, bool command_line_arg)
3725 {
3726   f->linkname = areadlink_with_size (filename, f->stat.st_size);
3727   if (f->linkname == nullptr)
3728     file_failure (command_line_arg, _("cannot read symbolic link %s"),
3729                   filename);
3730 }
3731 
3732 /* Return true if the last component of NAME is '.' or '..'
3733    This is so we don't try to recurse on '././././. ...' */
3734 
3735 static bool
basename_is_dot_or_dotdot(char const * name)3736 basename_is_dot_or_dotdot (char const *name)
3737 {
3738   char const *base = last_component (name);
3739   return dot_or_dotdot (base);
3740 }
3741 
3742 /* Remove any entries from CWD_FILE that are for directories,
3743    and queue them to be listed as directories instead.
3744    DIRNAME is the prefix to prepend to each dirname
3745    to make it correct relative to ls's working dir;
3746    if it is null, no prefix is needed and "." and ".." should not be ignored.
3747    If COMMAND_LINE_ARG is true, this directory was mentioned at the top level,
3748    This is desirable when processing directories recursively.  */
3749 
3750 static void
extract_dirs_from_files(char const * dirname,bool command_line_arg)3751 extract_dirs_from_files (char const *dirname, bool command_line_arg)
3752 {
3753   size_t i;
3754   size_t j;
3755   bool ignore_dot_and_dot_dot = (dirname != nullptr);
3756 
3757   if (dirname && LOOP_DETECT)
3758     {
3759       /* Insert a marker entry first.  When we dequeue this marker entry,
3760          we'll know that DIRNAME has been processed and may be removed
3761          from the set of active directories.  */
3762       queue_directory (nullptr, dirname, false);
3763     }
3764 
3765   /* Queue the directories last one first, because queueing reverses the
3766      order.  */
3767   for (i = cwd_n_used; i-- != 0; )
3768     {
3769       struct fileinfo *f = sorted_file[i];
3770 
3771       if (is_directory (f)
3772           && (! ignore_dot_and_dot_dot
3773               || ! basename_is_dot_or_dotdot (f->name)))
3774         {
3775           if (!dirname || f->name[0] == '/')
3776             queue_directory (f->name, f->linkname, command_line_arg);
3777           else
3778             {
3779               char *name = file_name_concat (dirname, f->name, nullptr);
3780               queue_directory (name, f->linkname, command_line_arg);
3781               free (name);
3782             }
3783           if (f->filetype == arg_directory)
3784             free_ent (f);
3785         }
3786     }
3787 
3788   /* Now delete the directories from the table, compacting all the remaining
3789      entries.  */
3790 
3791   for (i = 0, j = 0; i < cwd_n_used; i++)
3792     {
3793       struct fileinfo *f = sorted_file[i];
3794       sorted_file[j] = f;
3795       j += (f->filetype != arg_directory);
3796     }
3797   cwd_n_used = j;
3798 }
3799 
3800 /* Use strcoll to compare strings in this locale.  If an error occurs,
3801    report an error and longjmp to failed_strcoll.  */
3802 
3803 static jmp_buf failed_strcoll;
3804 
3805 static int
xstrcoll(char const * a,char const * b)3806 xstrcoll (char const *a, char const *b)
3807 {
3808   int diff;
3809   errno = 0;
3810   diff = strcoll (a, b);
3811   if (errno)
3812     {
3813       error (0, errno, _("cannot compare file names %s and %s"),
3814              quote_n (0, a), quote_n (1, b));
3815       set_exit_status (false);
3816       longjmp (failed_strcoll, 1);
3817     }
3818   return diff;
3819 }
3820 
3821 /* Comparison routines for sorting the files.  */
3822 
3823 typedef void const *V;
3824 typedef int (*qsortFunc)(V a, V b);
3825 
3826 /* Used below in DEFINE_SORT_FUNCTIONS for _df_ sort function variants.  */
3827 static int
dirfirst_check(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(V,V))3828 dirfirst_check (struct fileinfo const *a, struct fileinfo const *b,
3829                 int (*cmp) (V, V))
3830 {
3831   int diff = is_linked_directory (b) - is_linked_directory (a);
3832   return diff ? diff : cmp (a, b);
3833 }
3834 
3835 /* Define the 8 different sort function variants required for each sortkey.
3836    KEY_NAME is a token describing the sort key, e.g., ctime, atime, size.
3837    KEY_CMP_FUNC is a function to compare records based on that key, e.g.,
3838    ctime_cmp, atime_cmp, size_cmp.  Append KEY_NAME to the string,
3839    '[rev_][x]str{cmp|coll}[_df]_', to create each function name.  */
3840 #define DEFINE_SORT_FUNCTIONS(key_name, key_cmp_func)			\
3841   /* direct, non-dirfirst versions */					\
3842   static int xstrcoll_##key_name (V a, V b)				\
3843   { return key_cmp_func (a, b, xstrcoll); }				\
3844   ATTRIBUTE_PURE static int strcmp_##key_name (V a, V b)		\
3845   { return key_cmp_func (a, b, strcmp); }				\
3846                                                                         \
3847   /* reverse, non-dirfirst versions */					\
3848   static int rev_xstrcoll_##key_name (V a, V b)				\
3849   { return key_cmp_func (b, a, xstrcoll); }				\
3850   ATTRIBUTE_PURE static int rev_strcmp_##key_name (V a, V b)	\
3851   { return key_cmp_func (b, a, strcmp); }				\
3852                                                                         \
3853   /* direct, dirfirst versions */					\
3854   static int xstrcoll_df_##key_name (V a, V b)				\
3855   { return dirfirst_check (a, b, xstrcoll_##key_name); }		\
3856   ATTRIBUTE_PURE static int strcmp_df_##key_name (V a, V b)		\
3857   { return dirfirst_check (a, b, strcmp_##key_name); }			\
3858                                                                         \
3859   /* reverse, dirfirst versions */					\
3860   static int rev_xstrcoll_df_##key_name (V a, V b)			\
3861   { return dirfirst_check (a, b, rev_xstrcoll_##key_name); }		\
3862   ATTRIBUTE_PURE static int rev_strcmp_df_##key_name (V a, V b)	\
3863   { return dirfirst_check (a, b, rev_strcmp_##key_name); }
3864 
3865 static int
cmp_ctime(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3866 cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,
3867            int (*cmp) (char const *, char const *))
3868 {
3869   int diff = timespec_cmp (get_stat_ctime (&b->stat),
3870                            get_stat_ctime (&a->stat));
3871   return diff ? diff : cmp (a->name, b->name);
3872 }
3873 
3874 static int
cmp_mtime(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3875 cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,
3876            int (*cmp) (char const *, char const *))
3877 {
3878   int diff = timespec_cmp (get_stat_mtime (&b->stat),
3879                            get_stat_mtime (&a->stat));
3880   return diff ? diff : cmp (a->name, b->name);
3881 }
3882 
3883 static int
cmp_atime(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3884 cmp_atime (struct fileinfo const *a, struct fileinfo const *b,
3885            int (*cmp) (char const *, char const *))
3886 {
3887   int diff = timespec_cmp (get_stat_atime (&b->stat),
3888                            get_stat_atime (&a->stat));
3889   return diff ? diff : cmp (a->name, b->name);
3890 }
3891 
3892 static int
cmp_btime(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3893 cmp_btime (struct fileinfo const *a, struct fileinfo const *b,
3894            int (*cmp) (char const *, char const *))
3895 {
3896   int diff = timespec_cmp (get_stat_btime (&b->stat),
3897                            get_stat_btime (&a->stat));
3898   return diff ? diff : cmp (a->name, b->name);
3899 }
3900 
3901 static int
off_cmp(off_t a,off_t b)3902 off_cmp (off_t a, off_t b)
3903 {
3904   return (a > b) - (a < b);
3905 }
3906 
3907 static int
cmp_size(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3908 cmp_size (struct fileinfo const *a, struct fileinfo const *b,
3909           int (*cmp) (char const *, char const *))
3910 {
3911   int diff = off_cmp (b->stat.st_size, a->stat.st_size);
3912   return diff ? diff : cmp (a->name, b->name);
3913 }
3914 
3915 static int
cmp_name(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3916 cmp_name (struct fileinfo const *a, struct fileinfo const *b,
3917           int (*cmp) (char const *, char const *))
3918 {
3919   return cmp (a->name, b->name);
3920 }
3921 
3922 /* Compare file extensions.  Files with no extension are 'smallest'.
3923    If extensions are the same, compare by file names instead.  */
3924 
3925 static int
cmp_extension(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3926 cmp_extension (struct fileinfo const *a, struct fileinfo const *b,
3927                int (*cmp) (char const *, char const *))
3928 {
3929   char const *base1 = strrchr (a->name, '.');
3930   char const *base2 = strrchr (b->name, '.');
3931   int diff = cmp (base1 ? base1 : "", base2 ? base2 : "");
3932   return diff ? diff : cmp (a->name, b->name);
3933 }
3934 
3935 /* Return the (cached) screen width,
3936    for the NAME associated with the passed fileinfo F.  */
3937 
3938 static size_t
fileinfo_name_width(struct fileinfo const * f)3939 fileinfo_name_width (struct fileinfo const *f)
3940 {
3941   return f->width
3942          ? f->width
3943          : quote_name_width (f->name, filename_quoting_options, f->quoted);
3944 }
3945 
3946 static int
cmp_width(struct fileinfo const * a,struct fileinfo const * b,int (* cmp)(char const *,char const *))3947 cmp_width (struct fileinfo const *a, struct fileinfo const *b,
3948           int (*cmp) (char const *, char const *))
3949 {
3950   int diff = fileinfo_name_width (a) - fileinfo_name_width (b);
3951   return diff ? diff : cmp (a->name, b->name);
3952 }
3953 
DEFINE_SORT_FUNCTIONS(ctime,cmp_ctime)3954 DEFINE_SORT_FUNCTIONS (ctime, cmp_ctime)
3955 DEFINE_SORT_FUNCTIONS (mtime, cmp_mtime)
3956 DEFINE_SORT_FUNCTIONS (atime, cmp_atime)
3957 DEFINE_SORT_FUNCTIONS (btime, cmp_btime)
3958 DEFINE_SORT_FUNCTIONS (size, cmp_size)
3959 DEFINE_SORT_FUNCTIONS (name, cmp_name)
3960 DEFINE_SORT_FUNCTIONS (extension, cmp_extension)
3961 DEFINE_SORT_FUNCTIONS (width, cmp_width)
3962 
3963 /* Compare file versions.
3964    Unlike the other compare functions, cmp_version does not fail
3965    because filevercmp and strcmp do not fail; cmp_version uses strcmp
3966    instead of xstrcoll because filevercmp is locale-independent so
3967    strcmp is its appropriate secondary.
3968 
3969    All the other sort options need xstrcoll and strcmp variants,
3970    because they all use xstrcoll (either as the primary or secondary
3971    sort key), and xstrcoll has the ability to do a longjmp if strcoll fails for
3972    locale reasons.  */
3973 static int
3974 cmp_version (struct fileinfo const *a, struct fileinfo const *b)
3975 {
3976   int diff = filevercmp (a->name, b->name);
3977   return diff ? diff : strcmp (a->name, b->name);
3978 }
3979 
3980 static int
xstrcoll_version(V a,V b)3981 xstrcoll_version (V a, V b)
3982 {
3983   return cmp_version (a, b);
3984 }
3985 static int
rev_xstrcoll_version(V a,V b)3986 rev_xstrcoll_version (V a, V b)
3987 {
3988   return cmp_version (b, a);
3989 }
3990 static int
xstrcoll_df_version(V a,V b)3991 xstrcoll_df_version (V a, V b)
3992 {
3993   return dirfirst_check (a, b, xstrcoll_version);
3994 }
3995 static int
rev_xstrcoll_df_version(V a,V b)3996 rev_xstrcoll_df_version (V a, V b)
3997 {
3998   return dirfirst_check (a, b, rev_xstrcoll_version);
3999 }
4000 
4001 
4002 /* We have 2^3 different variants for each sort-key function
4003    (for 3 independent sort modes).
4004    The function pointers stored in this array must be dereferenced as:
4005 
4006     sort_variants[sort_key][use_strcmp][reverse][dirs_first]
4007 
4008    Note that the order in which sort keys are listed in the function pointer
4009    array below is defined by the order of the elements in the time_type and
4010    sort_type enums!  */
4011 
4012 #define LIST_SORTFUNCTION_VARIANTS(key_name)                        \
4013   {                                                                 \
4014     {                                                               \
4015       { xstrcoll_##key_name, xstrcoll_df_##key_name },              \
4016       { rev_xstrcoll_##key_name, rev_xstrcoll_df_##key_name },      \
4017     },                                                              \
4018     {                                                               \
4019       { strcmp_##key_name, strcmp_df_##key_name },                  \
4020       { rev_strcmp_##key_name, rev_strcmp_df_##key_name },          \
4021     }                                                               \
4022   }
4023 
4024 static qsortFunc const sort_functions[][2][2][2] =
4025   {
4026     LIST_SORTFUNCTION_VARIANTS (name),
4027     LIST_SORTFUNCTION_VARIANTS (extension),
4028     LIST_SORTFUNCTION_VARIANTS (width),
4029     LIST_SORTFUNCTION_VARIANTS (size),
4030 
4031     {
4032       {
4033         { xstrcoll_version, xstrcoll_df_version },
4034         { rev_xstrcoll_version, rev_xstrcoll_df_version },
4035       },
4036 
4037       /* We use nullptr for the strcmp variants of version comparison
4038          since as explained in cmp_version definition, version comparison
4039          does not rely on xstrcoll, so it will never longjmp, and never
4040          need to try the strcmp fallback. */
4041       {
4042         { nullptr, nullptr },
4043         { nullptr, nullptr },
4044       }
4045     },
4046 
4047     /* last are time sort functions */
4048     LIST_SORTFUNCTION_VARIANTS (mtime),
4049     LIST_SORTFUNCTION_VARIANTS (ctime),
4050     LIST_SORTFUNCTION_VARIANTS (atime),
4051     LIST_SORTFUNCTION_VARIANTS (btime)
4052   };
4053 
4054 /* The number of sort keys is calculated as the sum of
4055      the number of elements in the sort_type enum (i.e., sort_numtypes)
4056      -2 because neither sort_time nor sort_none use entries themselves
4057      the number of elements in the time_type enum (i.e., time_numtypes)
4058    This is because when sort_type==sort_time, we have up to
4059    time_numtypes possible sort keys.
4060 
4061    This line verifies at compile-time that the array of sort functions has been
4062    initialized for all possible sort keys. */
4063 static_assert (ARRAY_CARDINALITY (sort_functions)
4064                == sort_numtypes - 2 + time_numtypes);
4065 
4066 /* Set up SORTED_FILE to point to the in-use entries in CWD_FILE, in order.  */
4067 
4068 static void
initialize_ordering_vector(void)4069 initialize_ordering_vector (void)
4070 {
4071   for (size_t i = 0; i < cwd_n_used; i++)
4072     sorted_file[i] = &cwd_file[i];
4073 }
4074 
4075 /* Cache values based on attributes global to all files.  */
4076 
4077 static void
update_current_files_info(void)4078 update_current_files_info (void)
4079 {
4080   /* Cache screen width of name, if needed multiple times.  */
4081   if (sort_type == sort_width
4082       || (line_length && (format == many_per_line || format == horizontal)))
4083     {
4084       size_t i;
4085       for (i = 0; i < cwd_n_used; i++)
4086         {
4087           struct fileinfo *f = sorted_file[i];
4088           f->width = fileinfo_name_width (f);
4089         }
4090     }
4091 }
4092 
4093 /* Sort the files now in the table.  */
4094 
4095 static void
sort_files(void)4096 sort_files (void)
4097 {
4098   bool use_strcmp;
4099 
4100   if (sorted_file_alloc < cwd_n_used + cwd_n_used / 2)
4101     {
4102       free (sorted_file);
4103       sorted_file = xnmalloc (cwd_n_used, 3 * sizeof *sorted_file);
4104       sorted_file_alloc = 3 * cwd_n_used;
4105     }
4106 
4107   initialize_ordering_vector ();
4108 
4109   update_current_files_info ();
4110 
4111   if (sort_type == sort_none)
4112     return;
4113 
4114   /* Try strcoll.  If it fails, fall back on strcmp.  We can't safely
4115      ignore strcoll failures, as a failing strcoll might be a
4116      comparison function that is not a total order, and if we ignored
4117      the failure this might cause qsort to dump core.  */
4118 
4119   if (! setjmp (failed_strcoll))
4120     use_strcmp = false;      /* strcoll() succeeded */
4121   else
4122     {
4123       use_strcmp = true;
4124       affirm (sort_type != sort_version);
4125       initialize_ordering_vector ();
4126     }
4127 
4128   /* When sort_type == sort_time, use time_type as subindex.  */
4129   mpsort ((void const **) sorted_file, cwd_n_used,
4130           sort_functions[sort_type + (sort_type == sort_time ? time_type : 0)]
4131                         [use_strcmp][sort_reverse]
4132                         [directories_first]);
4133 }
4134 
4135 /* List all the files now in the table.  */
4136 
4137 static void
print_current_files(void)4138 print_current_files (void)
4139 {
4140   size_t i;
4141 
4142   switch (format)
4143     {
4144     case one_per_line:
4145       for (i = 0; i < cwd_n_used; i++)
4146         {
4147           print_file_name_and_frills (sorted_file[i], 0);
4148           putchar (eolbyte);
4149         }
4150       break;
4151 
4152     case many_per_line:
4153       if (! line_length)
4154         print_with_separator (' ');
4155       else
4156         print_many_per_line ();
4157       break;
4158 
4159     case horizontal:
4160       if (! line_length)
4161         print_with_separator (' ');
4162       else
4163         print_horizontal ();
4164       break;
4165 
4166     case with_commas:
4167       print_with_separator (',');
4168       break;
4169 
4170     case long_format:
4171       for (i = 0; i < cwd_n_used; i++)
4172         {
4173           set_normal_color ();
4174           print_long_format (sorted_file[i]);
4175           dired_outbyte (eolbyte);
4176         }
4177       break;
4178     }
4179 }
4180 
4181 /* Replace the first %b with precomputed aligned month names.
4182    Note on glibc-2.7 at least, this speeds up the whole 'ls -lU'
4183    process by around 17%, compared to letting strftime() handle the %b.  */
4184 
4185 static size_t
align_nstrftime(char * buf,size_t size,bool recent,struct tm const * tm,timezone_t tz,int ns)4186 align_nstrftime (char *buf, size_t size, bool recent, struct tm const *tm,
4187                  timezone_t tz, int ns)
4188 {
4189   char const *nfmt = (use_abformat
4190                       ? abformat[recent][tm->tm_mon]
4191                       : long_time_format[recent]);
4192   return nstrftime (buf, size, nfmt, tm, tz, ns);
4193 }
4194 
4195 /* Return the expected number of columns in a long-format timestamp,
4196    or zero if it cannot be calculated.  */
4197 
4198 static int
long_time_expected_width(void)4199 long_time_expected_width (void)
4200 {
4201   static int width = -1;
4202 
4203   if (width < 0)
4204     {
4205       time_t epoch = 0;
4206       struct tm tm;
4207       char buf[TIME_STAMP_LEN_MAXIMUM + 1];
4208 
4209       /* In case you're wondering if localtime_rz can fail with an input time_t
4210          value of 0, let's just say it's very unlikely, but not inconceivable.
4211          The TZ environment variable would have to specify a time zone that
4212          is 2**31-1900 years or more ahead of UTC.  This could happen only on
4213          a 64-bit system that blindly accepts e.g., TZ=UTC+20000000000000.
4214          However, this is not possible with Solaris 10 or glibc-2.3.5, since
4215          their implementations limit the offset to 167:59 and 24:00, resp.  */
4216       if (localtime_rz (localtz, &epoch, &tm))
4217         {
4218           size_t len = align_nstrftime (buf, sizeof buf, false,
4219                                         &tm, localtz, 0);
4220           if (len != 0)
4221             width = mbsnwidth (buf, len, MBSWIDTH_FLAGS);
4222         }
4223 
4224       if (width < 0)
4225         width = 0;
4226     }
4227 
4228   return width;
4229 }
4230 
4231 /* Print the user or group name NAME, with numeric id ID, using a
4232    print width of WIDTH columns.  */
4233 
4234 static void
format_user_or_group(char const * name,uintmax_t id,int width)4235 format_user_or_group (char const *name, uintmax_t id, int width)
4236 {
4237   if (name)
4238     {
4239       int name_width = mbswidth (name, MBSWIDTH_FLAGS);
4240       int width_gap = name_width < 0 ? 0 : width - name_width;
4241       int pad = MAX (0, width_gap);
4242       dired_outstring (name);
4243 
4244       do
4245         dired_outbyte (' ');
4246       while (pad--);
4247     }
4248   else
4249     dired_pos += printf ("%*ju ", width, id);
4250 }
4251 
4252 /* Print the name or id of the user with id U, using a print width of
4253    WIDTH.  */
4254 
4255 static void
format_user(uid_t u,int width,bool stat_ok)4256 format_user (uid_t u, int width, bool stat_ok)
4257 {
4258   format_user_or_group (! stat_ok ? "?" :
4259                         (numeric_ids ? nullptr : getuser (u)), u, width);
4260 }
4261 
4262 /* Likewise, for groups.  */
4263 
4264 static void
format_group(gid_t g,int width,bool stat_ok)4265 format_group (gid_t g, int width, bool stat_ok)
4266 {
4267   format_user_or_group (! stat_ok ? "?" :
4268                         (numeric_ids ? nullptr : getgroup (g)), g, width);
4269 }
4270 
4271 /* Return the number of columns that format_user_or_group will print,
4272    or -1 if unknown.  */
4273 
4274 static int
format_user_or_group_width(char const * name,uintmax_t id)4275 format_user_or_group_width (char const *name, uintmax_t id)
4276 {
4277   return (name
4278           ? mbswidth (name, MBSWIDTH_FLAGS)
4279           : snprintf (nullptr, 0, "%ju", id));
4280 }
4281 
4282 /* Return the number of columns that format_user will print,
4283    or -1 if unknown.  */
4284 
4285 static int
format_user_width(uid_t u)4286 format_user_width (uid_t u)
4287 {
4288   return format_user_or_group_width (numeric_ids ? nullptr : getuser (u), u);
4289 }
4290 
4291 /* Likewise, for groups.  */
4292 
4293 static int
format_group_width(gid_t g)4294 format_group_width (gid_t g)
4295 {
4296   return format_user_or_group_width (numeric_ids ? nullptr : getgroup (g), g);
4297 }
4298 
4299 /* Return a pointer to a formatted version of F->stat.st_ino,
4300    possibly using buffer, which must be at least
4301    INT_BUFSIZE_BOUND (uintmax_t) bytes.  */
4302 static char *
format_inode(char buf[INT_BUFSIZE_BOUND (uintmax_t)],const struct fileinfo * f)4303 format_inode (char buf[INT_BUFSIZE_BOUND (uintmax_t)],
4304               const struct fileinfo *f)
4305 {
4306   return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER
4307           ? umaxtostr (f->stat.st_ino, buf)
4308           : (char *) "?");
4309 }
4310 
4311 /* Print information about F in long format.  */
4312 static void
print_long_format(const struct fileinfo * f)4313 print_long_format (const struct fileinfo *f)
4314 {
4315   char modebuf[12];
4316   char buf
4317     [LONGEST_HUMAN_READABLE + 1		/* inode */
4318      + LONGEST_HUMAN_READABLE + 1	/* size in blocks */
4319      + sizeof (modebuf) - 1 + 1		/* mode string */
4320      + INT_BUFSIZE_BOUND (uintmax_t)	/* st_nlink */
4321      + LONGEST_HUMAN_READABLE + 2	/* major device number */
4322      + LONGEST_HUMAN_READABLE + 1	/* minor device number */
4323      + TIME_STAMP_LEN_MAXIMUM + 1	/* max length of time/date */
4324      ];
4325   size_t s;
4326   char *p;
4327   struct timespec when_timespec;
4328   struct tm when_local;
4329   bool btime_ok = true;
4330 
4331   /* Compute the mode string, except remove the trailing space if no
4332      file in this directory has an ACL or security context.  */
4333   if (f->stat_ok)
4334     filemodestring (&f->stat, modebuf);
4335   else
4336     {
4337       modebuf[0] = filetype_letter[f->filetype];
4338       memset (modebuf + 1, '?', 10);
4339       modebuf[11] = '\0';
4340     }
4341   if (! any_has_acl)
4342     modebuf[10] = '\0';
4343   else if (f->acl_type == ACL_T_LSM_CONTEXT_ONLY)
4344     modebuf[10] = '.';
4345   else if (f->acl_type == ACL_T_YES)
4346     modebuf[10] = '+';
4347 
4348   switch (time_type)
4349     {
4350     case time_ctime:
4351       when_timespec = get_stat_ctime (&f->stat);
4352       break;
4353     case time_mtime:
4354       when_timespec = get_stat_mtime (&f->stat);
4355       break;
4356     case time_atime:
4357       when_timespec = get_stat_atime (&f->stat);
4358       break;
4359     case time_btime:
4360       when_timespec = get_stat_btime (&f->stat);
4361       if (when_timespec.tv_sec == -1 && when_timespec.tv_nsec == -1)
4362         btime_ok = false;
4363       break;
4364     default:
4365       unreachable ();
4366     }
4367 
4368   p = buf;
4369 
4370   if (print_inode)
4371     {
4372       char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
4373       p += sprintf (p, "%*s ", inode_number_width, format_inode (hbuf, f));
4374     }
4375 
4376   if (print_block_size)
4377     {
4378       char hbuf[LONGEST_HUMAN_READABLE + 1];
4379       char const *blocks =
4380         (! f->stat_ok
4381          ? "?"
4382          : human_readable (STP_NBLOCKS (&f->stat), hbuf, human_output_opts,
4383                            ST_NBLOCKSIZE, output_block_size));
4384       int blocks_width = mbswidth (blocks, MBSWIDTH_FLAGS);
4385       for (int pad = blocks_width < 0 ? 0 : block_size_width - blocks_width;
4386            0 < pad; pad--)
4387         *p++ = ' ';
4388       while ((*p++ = *blocks++))
4389         continue;
4390       p[-1] = ' ';
4391     }
4392 
4393   /* The last byte of the mode string is the POSIX
4394      "optional alternate access method flag".  */
4395   {
4396     char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];
4397     p += sprintf (p, "%s %*s ", modebuf, nlink_width,
4398                   ! f->stat_ok ? "?" : umaxtostr (f->stat.st_nlink, hbuf));
4399   }
4400 
4401   dired_indent ();
4402 
4403   if (print_owner || print_group || print_author || print_scontext)
4404     {
4405       dired_outbuf (buf, p - buf);
4406 
4407       if (print_owner)
4408         format_user (f->stat.st_uid, owner_width, f->stat_ok);
4409 
4410       if (print_group)
4411         format_group (f->stat.st_gid, group_width, f->stat_ok);
4412 
4413       if (print_author)
4414         format_user (f->stat.st_author, author_width, f->stat_ok);
4415 
4416       if (print_scontext)
4417         format_user_or_group (f->scontext, 0, scontext_width);
4418 
4419       p = buf;
4420     }
4421 
4422   if (f->stat_ok
4423       && (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)))
4424     {
4425       char majorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
4426       char minorbuf[INT_BUFSIZE_BOUND (uintmax_t)];
4427       int blanks_width = (file_size_width
4428                           - (major_device_number_width + 2
4429                              + minor_device_number_width));
4430       p += sprintf (p, "%*s, %*s ",
4431                     major_device_number_width + MAX (0, blanks_width),
4432                     umaxtostr (major (f->stat.st_rdev), majorbuf),
4433                     minor_device_number_width,
4434                     umaxtostr (minor (f->stat.st_rdev), minorbuf));
4435     }
4436   else
4437     {
4438       char hbuf[LONGEST_HUMAN_READABLE + 1];
4439       char const *size =
4440         (! f->stat_ok
4441          ? "?"
4442          : human_readable (unsigned_file_size (f->stat.st_size),
4443                            hbuf, file_human_output_opts, 1,
4444                            file_output_block_size));
4445       int size_width = mbswidth (size, MBSWIDTH_FLAGS);
4446       for (int pad = size_width < 0 ? 0 : block_size_width - size_width;
4447            0 < pad; pad--)
4448         *p++ = ' ';
4449       while ((*p++ = *size++))
4450         continue;
4451       p[-1] = ' ';
4452     }
4453 
4454   s = 0;
4455   *p = '\1';
4456 
4457   if (f->stat_ok && btime_ok
4458       && localtime_rz (localtz, &when_timespec.tv_sec, &when_local))
4459     {
4460       struct timespec six_months_ago;
4461       bool recent;
4462 
4463       /* If the file appears to be in the future, update the current
4464          time, in case the file happens to have been modified since
4465          the last time we checked the clock.  */
4466       if (timespec_cmp (current_time, when_timespec) < 0)
4467         gettime (&current_time);
4468 
4469       /* Consider a time to be recent if it is within the past six months.
4470          A Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds
4471          on the average.  Write this value as an integer constant to
4472          avoid floating point hassles.  */
4473       six_months_ago.tv_sec = current_time.tv_sec - 31556952 / 2;
4474       six_months_ago.tv_nsec = current_time.tv_nsec;
4475 
4476       recent = (timespec_cmp (six_months_ago, when_timespec) < 0
4477                 && timespec_cmp (when_timespec, current_time) < 0);
4478 
4479       /* We assume here that all time zones are offset from UTC by a
4480          whole number of seconds.  */
4481       s = align_nstrftime (p, TIME_STAMP_LEN_MAXIMUM + 1, recent,
4482                            &when_local, localtz, when_timespec.tv_nsec);
4483     }
4484 
4485   if (s || !*p)
4486     {
4487       p += s;
4488       *p++ = ' ';
4489     }
4490   else
4491     {
4492       /* The time cannot be converted using the desired format, so
4493          print it as a huge integer number of seconds.  */
4494       char hbuf[INT_BUFSIZE_BOUND (intmax_t)];
4495       p += sprintf (p, "%*s ", long_time_expected_width (),
4496                     (! f->stat_ok || ! btime_ok
4497                      ? "?"
4498                      : timetostr (when_timespec.tv_sec, hbuf)));
4499       /* FIXME: (maybe) We discarded when_timespec.tv_nsec. */
4500     }
4501 
4502   dired_outbuf (buf, p - buf);
4503   size_t w = print_name_with_quoting (f, false, &dired_obstack, p - buf);
4504 
4505   if (f->filetype == symbolic_link)
4506     {
4507       if (f->linkname)
4508         {
4509           dired_outstring (" -> ");
4510           print_name_with_quoting (f, true, nullptr, (p - buf) + w + 4);
4511           if (indicator_style != none)
4512             print_type_indicator (true, f->linkmode, unknown);
4513         }
4514     }
4515   else if (indicator_style != none)
4516     print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);
4517 }
4518 
4519 /* Write to *BUF a quoted representation of the file name NAME, if non-null,
4520    using OPTIONS to control quoting.  *BUF is set to NAME if no quoting
4521    is required.  *BUF is allocated if more space required (and the original
4522    *BUF is not deallocated).
4523    Store the number of screen columns occupied by NAME's quoted
4524    representation into WIDTH, if non-null.
4525    Store into PAD whether an initial space is needed for padding.
4526    Return the number of bytes in *BUF.  */
4527 
4528 static size_t
quote_name_buf(char ** inbuf,size_t bufsize,char * name,struct quoting_options const * options,int needs_general_quoting,size_t * width,bool * pad)4529 quote_name_buf (char **inbuf, size_t bufsize, char *name,
4530                 struct quoting_options const *options,
4531                 int needs_general_quoting, size_t *width, bool *pad)
4532 {
4533   char *buf = *inbuf;
4534   size_t displayed_width IF_LINT ( = 0);
4535   size_t len = 0;
4536   bool quoted;
4537 
4538   enum quoting_style qs = get_quoting_style (options);
4539   bool needs_further_quoting = qmark_funny_chars
4540                                && (qs == shell_quoting_style
4541                                    || qs == shell_always_quoting_style
4542                                    || qs == literal_quoting_style);
4543 
4544   if (needs_general_quoting != 0)
4545     {
4546       len = quotearg_buffer (buf, bufsize, name, -1, options);
4547       if (bufsize <= len)
4548         {
4549           buf = xmalloc (len + 1);
4550           quotearg_buffer (buf, len + 1, name, -1, options);
4551         }
4552 
4553       quoted = (*name != *buf) || strlen (name) != len;
4554     }
4555   else if (needs_further_quoting)
4556     {
4557       len = strlen (name);
4558       if (bufsize <= len)
4559         buf = xmalloc (len + 1);
4560       memcpy (buf, name, len + 1);
4561 
4562       quoted = false;
4563     }
4564   else
4565     {
4566       len = strlen (name);
4567       buf = name;
4568       quoted = false;
4569     }
4570 
4571   if (needs_further_quoting)
4572     {
4573       if (MB_CUR_MAX > 1)
4574         {
4575           char const *p = buf;
4576           char const *plimit = buf + len;
4577           char *q = buf;
4578           displayed_width = 0;
4579 
4580           while (p < plimit)
4581             switch (*p)
4582               {
4583                 case ' ': case '!': case '"': case '#': case '%':
4584                 case '&': case '\'': case '(': case ')': case '*':
4585                 case '+': case ',': case '-': case '.': case '/':
4586                 case '0': case '1': case '2': case '3': case '4':
4587                 case '5': case '6': case '7': case '8': case '9':
4588                 case ':': case ';': case '<': case '=': case '>':
4589                 case '?':
4590                 case 'A': case 'B': case 'C': case 'D': case 'E':
4591                 case 'F': case 'G': case 'H': case 'I': case 'J':
4592                 case 'K': case 'L': case 'M': case 'N': case 'O':
4593                 case 'P': case 'Q': case 'R': case 'S': case 'T':
4594                 case 'U': case 'V': case 'W': case 'X': case 'Y':
4595                 case 'Z':
4596                 case '[': case '\\': case ']': case '^': case '_':
4597                 case 'a': case 'b': case 'c': case 'd': case 'e':
4598                 case 'f': case 'g': case 'h': case 'i': case 'j':
4599                 case 'k': case 'l': case 'm': case 'n': case 'o':
4600                 case 'p': case 'q': case 'r': case 's': case 't':
4601                 case 'u': case 'v': case 'w': case 'x': case 'y':
4602                 case 'z': case '{': case '|': case '}': case '~':
4603                   /* These characters are printable ASCII characters.  */
4604                   *q++ = *p++;
4605                   displayed_width += 1;
4606                   break;
4607                 default:
4608                   /* If we have a multibyte sequence, copy it until we
4609                      reach its end, replacing each non-printable multibyte
4610                      character with a single question mark.  */
4611                   {
4612                     mbstate_t mbstate; mbszero (&mbstate);
4613                     do
4614                       {
4615                         char32_t wc;
4616                         size_t bytes;
4617                         int w;
4618 
4619                         bytes = mbrtoc32 (&wc, p, plimit - p, &mbstate);
4620 
4621                         if (bytes == (size_t) -1)
4622                           {
4623                             /* An invalid multibyte sequence was
4624                                encountered.  Skip one input byte, and
4625                                put a question mark.  */
4626                             p++;
4627                             *q++ = '?';
4628                             displayed_width += 1;
4629                             break;
4630                           }
4631 
4632                         if (bytes == (size_t) -2)
4633                           {
4634                             /* An incomplete multibyte character
4635                                at the end.  Replace it entirely with
4636                                a question mark.  */
4637                             p = plimit;
4638                             *q++ = '?';
4639                             displayed_width += 1;
4640                             break;
4641                           }
4642 
4643                         if (bytes == 0)
4644                           /* A null wide character was encountered.  */
4645                           bytes = 1;
4646 
4647                         w = c32width (wc);
4648                         if (w >= 0)
4649                           {
4650                             /* A printable multibyte character.
4651                                Keep it.  */
4652                             for (; bytes > 0; --bytes)
4653                               *q++ = *p++;
4654                             displayed_width += w;
4655                           }
4656                         else
4657                           {
4658                             /* An nonprintable multibyte character.
4659                                Replace it entirely with a question
4660                                mark.  */
4661                             p += bytes;
4662                             *q++ = '?';
4663                             displayed_width += 1;
4664                           }
4665                       }
4666                     while (! mbsinit (&mbstate));
4667                   }
4668                   break;
4669               }
4670 
4671           /* The buffer may have shrunk.  */
4672           len = q - buf;
4673         }
4674       else
4675         {
4676           char *p = buf;
4677           char const *plimit = buf + len;
4678 
4679           while (p < plimit)
4680             {
4681               if (! isprint (to_uchar (*p)))
4682                 *p = '?';
4683               p++;
4684             }
4685           displayed_width = len;
4686         }
4687     }
4688   else if (width != nullptr)
4689     {
4690       if (MB_CUR_MAX > 1)
4691         {
4692           displayed_width = mbsnwidth (buf, len, MBSWIDTH_FLAGS);
4693           displayed_width = MAX (0, displayed_width);
4694         }
4695       else
4696         {
4697           char const *p = buf;
4698           char const *plimit = buf + len;
4699 
4700           displayed_width = 0;
4701           while (p < plimit)
4702             {
4703               if (isprint (to_uchar (*p)))
4704                 displayed_width++;
4705               p++;
4706             }
4707         }
4708     }
4709 
4710   /* Set padding to better align quoted items,
4711      and also give a visual indication that quotes are
4712      not actually part of the name.  */
4713   *pad = (align_variable_outer_quotes && cwd_some_quoted && ! quoted);
4714 
4715   if (width != nullptr)
4716     *width = displayed_width;
4717 
4718   *inbuf = buf;
4719 
4720   return len;
4721 }
4722 
4723 static size_t
quote_name_width(char const * name,struct quoting_options const * options,int needs_general_quoting)4724 quote_name_width (char const *name, struct quoting_options const *options,
4725                   int needs_general_quoting)
4726 {
4727   char smallbuf[BUFSIZ];
4728   char *buf = smallbuf;
4729   size_t width;
4730   bool pad;
4731 
4732   quote_name_buf (&buf, sizeof smallbuf, (char *) name, options,
4733                   needs_general_quoting, &width, &pad);
4734 
4735   if (buf != smallbuf && buf != name)
4736     free (buf);
4737 
4738   width += pad;
4739 
4740   return width;
4741 }
4742 
4743 /* %XX escape any input out of range as defined in RFC3986,
4744    and also if PATH, convert all path separators to '/'.  */
4745 static char *
file_escape(char const * str,bool path)4746 file_escape (char const *str, bool path)
4747 {
4748   char *esc = xnmalloc (3, strlen (str) + 1);
4749   char *p = esc;
4750   while (*str)
4751     {
4752       if (path && ISSLASH (*str))
4753         {
4754           *p++ = '/';
4755           str++;
4756         }
4757       else if (RFC3986[to_uchar (*str)])
4758         *p++ = *str++;
4759       else
4760         p += sprintf (p, "%%%02x", to_uchar (*str++));
4761     }
4762   *p = '\0';
4763   return esc;
4764 }
4765 
4766 static size_t
quote_name(char const * name,struct quoting_options const * options,int needs_general_quoting,const struct bin_str * color,bool allow_pad,struct obstack * stack,char const * absolute_name)4767 quote_name (char const *name, struct quoting_options const *options,
4768             int needs_general_quoting, const struct bin_str *color,
4769             bool allow_pad, struct obstack *stack, char const *absolute_name)
4770 {
4771   char smallbuf[BUFSIZ];
4772   char *buf = smallbuf;
4773   size_t len;
4774   bool pad;
4775 
4776   len = quote_name_buf (&buf, sizeof smallbuf, (char *) name, options,
4777                         needs_general_quoting, nullptr, &pad);
4778 
4779   if (pad && allow_pad)
4780     dired_outbyte (' ');
4781 
4782   if (color)
4783     print_color_indicator (color);
4784 
4785   /* If we're padding, then don't include the outer quotes in
4786      the --hyperlink, to improve the alignment of those links.  */
4787   bool skip_quotes = false;
4788 
4789   if (absolute_name)
4790     {
4791       if (align_variable_outer_quotes && cwd_some_quoted && ! pad)
4792         {
4793           skip_quotes = true;
4794           putchar (*buf);
4795         }
4796       char *h = file_escape (hostname, /* path= */ false);
4797       char *n = file_escape (absolute_name, /* path= */ true);
4798       /* TODO: It would be good to be able to define parameters
4799          to give hints to the terminal as how best to render the URI.
4800          For example since ls is outputting a dense block of URIs
4801          it would be best to not underline by default, and only
4802          do so upon hover etc.  */
4803       printf ("\033]8;;file://%s%s%s\a", h, *n == '/' ? "" : "/", n);
4804       free (h);
4805       free (n);
4806     }
4807 
4808   if (stack)
4809     push_current_dired_pos (stack);
4810 
4811   fwrite (buf + skip_quotes, 1, len - (skip_quotes * 2), stdout);
4812 
4813   dired_pos += len;
4814 
4815   if (stack)
4816     push_current_dired_pos (stack);
4817 
4818   if (absolute_name)
4819     {
4820       fputs ("\033]8;;\a", stdout);
4821       if (skip_quotes)
4822         putchar (*(buf + len - 1));
4823     }
4824 
4825   if (buf != smallbuf && buf != name)
4826     free (buf);
4827 
4828   return len + pad;
4829 }
4830 
4831 static size_t
print_name_with_quoting(const struct fileinfo * f,bool symlink_target,struct obstack * stack,size_t start_col)4832 print_name_with_quoting (const struct fileinfo *f,
4833                          bool symlink_target,
4834                          struct obstack *stack,
4835                          size_t start_col)
4836 {
4837   char const *name = symlink_target ? f->linkname : f->name;
4838 
4839   const struct bin_str *color
4840     = print_with_color ? get_color_indicator (f, symlink_target) : nullptr;
4841 
4842   bool used_color_this_time = (print_with_color
4843                                && (color || is_colored (C_NORM)));
4844 
4845   size_t len = quote_name (name, filename_quoting_options, f->quoted,
4846                            color, !symlink_target, stack, f->absolute_name);
4847 
4848   process_signals ();
4849   if (used_color_this_time)
4850     {
4851       prep_non_filename_text ();
4852 
4853       /* We use the byte length rather than display width here as
4854          an optimization to avoid accurately calculating the width,
4855          because we only output the clear to EOL sequence if the name
4856          _might_ wrap to the next line.  This may output a sequence
4857          unnecessarily in multi-byte locales for example,
4858          but in that case it's inconsequential to the output.  */
4859       if (line_length
4860           && (start_col / line_length != (start_col + len - 1) / line_length))
4861         put_indicator (&color_indicator[C_CLR_TO_EOL]);
4862     }
4863 
4864   return len;
4865 }
4866 
4867 static void
prep_non_filename_text(void)4868 prep_non_filename_text (void)
4869 {
4870   if (color_indicator[C_END].string != nullptr)
4871     put_indicator (&color_indicator[C_END]);
4872   else
4873     {
4874       put_indicator (&color_indicator[C_LEFT]);
4875       put_indicator (&color_indicator[C_RESET]);
4876       put_indicator (&color_indicator[C_RIGHT]);
4877     }
4878 }
4879 
4880 /* Print the file name of 'f' with appropriate quoting.
4881    Also print file size, inode number, and filetype indicator character,
4882    as requested by switches.  */
4883 
4884 static size_t
print_file_name_and_frills(const struct fileinfo * f,size_t start_col)4885 print_file_name_and_frills (const struct fileinfo *f, size_t start_col)
4886 {
4887   char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
4888 
4889   set_normal_color ();
4890 
4891   if (print_inode)
4892     printf ("%*s ", format == with_commas ? 0 : inode_number_width,
4893             format_inode (buf, f));
4894 
4895   if (print_block_size)
4896     printf ("%*s ", format == with_commas ? 0 : block_size_width,
4897             ! f->stat_ok ? "?"
4898             : human_readable (STP_NBLOCKS (&f->stat), buf, human_output_opts,
4899                               ST_NBLOCKSIZE, output_block_size));
4900 
4901   if (print_scontext)
4902     printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);
4903 
4904   size_t width = print_name_with_quoting (f, false, nullptr, start_col);
4905 
4906   if (indicator_style != none)
4907     width += print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);
4908 
4909   return width;
4910 }
4911 
4912 /* Given these arguments describing a file, return the single-byte
4913    type indicator, or 0.  */
4914 static char
get_type_indicator(bool stat_ok,mode_t mode,enum filetype type)4915 get_type_indicator (bool stat_ok, mode_t mode, enum filetype type)
4916 {
4917   char c;
4918 
4919   if (stat_ok ? S_ISREG (mode) : type == normal)
4920     {
4921       if (stat_ok && indicator_style == classify && (mode & S_IXUGO))
4922         c = '*';
4923       else
4924         c = 0;
4925     }
4926   else
4927     {
4928       if (stat_ok ? S_ISDIR (mode) : type == directory || type == arg_directory)
4929         c = '/';
4930       else if (indicator_style == slash)
4931         c = 0;
4932       else if (stat_ok ? S_ISLNK (mode) : type == symbolic_link)
4933         c = '@';
4934       else if (stat_ok ? S_ISFIFO (mode) : type == fifo)
4935         c = '|';
4936       else if (stat_ok ? S_ISSOCK (mode) : type == sock)
4937         c = '=';
4938       else if (stat_ok && S_ISDOOR (mode))
4939         c = '>';
4940       else
4941         c = 0;
4942     }
4943   return c;
4944 }
4945 
4946 static bool
print_type_indicator(bool stat_ok,mode_t mode,enum filetype type)4947 print_type_indicator (bool stat_ok, mode_t mode, enum filetype type)
4948 {
4949   char c = get_type_indicator (stat_ok, mode, type);
4950   if (c)
4951     dired_outbyte (c);
4952   return !!c;
4953 }
4954 
4955 /* Returns if color sequence was printed.  */
4956 static bool
print_color_indicator(const struct bin_str * ind)4957 print_color_indicator (const struct bin_str *ind)
4958 {
4959   if (ind)
4960     {
4961       /* Need to reset so not dealing with attribute combinations */
4962       if (is_colored (C_NORM))
4963         restore_default_color ();
4964       put_indicator (&color_indicator[C_LEFT]);
4965       put_indicator (ind);
4966       put_indicator (&color_indicator[C_RIGHT]);
4967     }
4968 
4969   return ind != nullptr;
4970 }
4971 
4972 /* Returns color indicator or nullptr if none.  */
4973 ATTRIBUTE_PURE
4974 static const struct bin_str*
get_color_indicator(const struct fileinfo * f,bool symlink_target)4975 get_color_indicator (const struct fileinfo *f, bool symlink_target)
4976 {
4977   enum indicator_no type;
4978   struct color_ext_type *ext;	/* Color extension */
4979   size_t len;			/* Length of name */
4980 
4981   char const *name;
4982   mode_t mode;
4983   int linkok;
4984   if (symlink_target)
4985     {
4986       name = f->linkname;
4987       mode = f->linkmode;
4988       linkok = f->linkok ? 0 : -1;
4989     }
4990   else
4991     {
4992       name = f->name;
4993       mode = file_or_link_mode (f);
4994       linkok = f->linkok;
4995     }
4996 
4997   /* Is this a nonexistent file?  If so, linkok == -1.  */
4998 
4999   if (linkok == -1 && is_colored (C_MISSING))
5000     type = C_MISSING;
5001   else if (!f->stat_ok)
5002     {
5003       static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;
5004       type = filetype_indicator[f->filetype];
5005     }
5006   else
5007     {
5008       if (S_ISREG (mode))
5009         {
5010           type = C_FILE;
5011 
5012           if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))
5013             type = C_SETUID;
5014           else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))
5015             type = C_SETGID;
5016           else if (is_colored (C_CAP) && f->has_capability)
5017             type = C_CAP;
5018           else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))
5019             type = C_EXEC;
5020           else if ((1 < f->stat.st_nlink) && is_colored (C_MULTIHARDLINK))
5021             type = C_MULTIHARDLINK;
5022         }
5023       else if (S_ISDIR (mode))
5024         {
5025           type = C_DIR;
5026 
5027           if ((mode & S_ISVTX) && (mode & S_IWOTH)
5028               && is_colored (C_STICKY_OTHER_WRITABLE))
5029             type = C_STICKY_OTHER_WRITABLE;
5030           else if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))
5031             type = C_OTHER_WRITABLE;
5032           else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))
5033             type = C_STICKY;
5034         }
5035       else if (S_ISLNK (mode))
5036         type = C_LINK;
5037       else if (S_ISFIFO (mode))
5038         type = C_FIFO;
5039       else if (S_ISSOCK (mode))
5040         type = C_SOCK;
5041       else if (S_ISBLK (mode))
5042         type = C_BLK;
5043       else if (S_ISCHR (mode))
5044         type = C_CHR;
5045       else if (S_ISDOOR (mode))
5046         type = C_DOOR;
5047       else
5048         {
5049           /* Classify a file of some other type as C_ORPHAN.  */
5050           type = C_ORPHAN;
5051         }
5052     }
5053 
5054   /* Check the file's suffix only if still classified as C_FILE.  */
5055   ext = nullptr;
5056   if (type == C_FILE)
5057     {
5058       /* Test if NAME has a recognized suffix.  */
5059 
5060       len = strlen (name);
5061       name += len;		/* Pointer to final \0.  */
5062       for (ext = color_ext_list; ext != nullptr; ext = ext->next)
5063         {
5064           if (ext->ext.len <= len)
5065             {
5066               if (ext->exact_match)
5067                 {
5068                   if (STREQ_LEN (name - ext->ext.len, ext->ext.string,
5069                                  ext->ext.len))
5070                     break;
5071                 }
5072               else
5073                 {
5074                   if (c_strncasecmp (name - ext->ext.len, ext->ext.string,
5075                                      ext->ext.len) == 0)
5076                     break;
5077                 }
5078             }
5079         }
5080     }
5081 
5082   /* Adjust the color for orphaned symlinks.  */
5083   if (type == C_LINK && !linkok)
5084     {
5085       if (color_symlink_as_referent || is_colored (C_ORPHAN))
5086         type = C_ORPHAN;
5087     }
5088 
5089   const struct bin_str *const s
5090     = ext ? &(ext->seq) : &color_indicator[type];
5091 
5092   return s->string ? s : nullptr;
5093 }
5094 
5095 /* Output a color indicator (which may contain nulls).  */
5096 static void
put_indicator(const struct bin_str * ind)5097 put_indicator (const struct bin_str *ind)
5098 {
5099   if (! used_color)
5100     {
5101       used_color = true;
5102 
5103       /* If the standard output is a controlling terminal, watch out
5104          for signals, so that the colors can be restored to the
5105          default state if "ls" is suspended or interrupted.  */
5106 
5107       if (0 <= tcgetpgrp (STDOUT_FILENO))
5108         signal_init ();
5109 
5110       prep_non_filename_text ();
5111     }
5112 
5113   fwrite (ind->string, ind->len, 1, stdout);
5114 }
5115 
5116 static size_t
length_of_file_name_and_frills(const struct fileinfo * f)5117 length_of_file_name_and_frills (const struct fileinfo *f)
5118 {
5119   size_t len = 0;
5120   char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];
5121 
5122   if (print_inode)
5123     len += 1 + (format == with_commas
5124                 ? strlen (umaxtostr (f->stat.st_ino, buf))
5125                 : inode_number_width);
5126 
5127   if (print_block_size)
5128     len += 1 + (format == with_commas
5129                 ? strlen (! f->stat_ok ? "?"
5130                           : human_readable (STP_NBLOCKS (&f->stat), buf,
5131                                             human_output_opts, ST_NBLOCKSIZE,
5132                                             output_block_size))
5133                 : block_size_width);
5134 
5135   if (print_scontext)
5136     len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width);
5137 
5138   len += fileinfo_name_width (f);
5139 
5140   if (indicator_style != none)
5141     {
5142       char c = get_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);
5143       len += (c != 0);
5144     }
5145 
5146   return len;
5147 }
5148 
5149 static void
print_many_per_line(void)5150 print_many_per_line (void)
5151 {
5152   size_t row;			/* Current row.  */
5153   size_t cols = calculate_columns (true);
5154   struct column_info const *line_fmt = &column_info[cols - 1];
5155 
5156   /* Calculate the number of rows that will be in each column except possibly
5157      for a short column on the right.  */
5158   size_t rows = cwd_n_used / cols + (cwd_n_used % cols != 0);
5159 
5160   for (row = 0; row < rows; row++)
5161     {
5162       size_t col = 0;
5163       size_t filesno = row;
5164       size_t pos = 0;
5165 
5166       /* Print the next row.  */
5167       while (true)
5168         {
5169           struct fileinfo const *f = sorted_file[filesno];
5170           size_t name_length = length_of_file_name_and_frills (f);
5171           size_t max_name_length = line_fmt->col_arr[col++];
5172           print_file_name_and_frills (f, pos);
5173 
5174           filesno += rows;
5175           if (filesno >= cwd_n_used)
5176             break;
5177 
5178           indent (pos + name_length, pos + max_name_length);
5179           pos += max_name_length;
5180         }
5181       putchar (eolbyte);
5182     }
5183 }
5184 
5185 static void
print_horizontal(void)5186 print_horizontal (void)
5187 {
5188   size_t filesno;
5189   size_t pos = 0;
5190   size_t cols = calculate_columns (false);
5191   struct column_info const *line_fmt = &column_info[cols - 1];
5192   struct fileinfo const *f = sorted_file[0];
5193   size_t name_length = length_of_file_name_and_frills (f);
5194   size_t max_name_length = line_fmt->col_arr[0];
5195 
5196   /* Print first entry.  */
5197   print_file_name_and_frills (f, 0);
5198 
5199   /* Now the rest.  */
5200   for (filesno = 1; filesno < cwd_n_used; ++filesno)
5201     {
5202       size_t col = filesno % cols;
5203 
5204       if (col == 0)
5205         {
5206           putchar (eolbyte);
5207           pos = 0;
5208         }
5209       else
5210         {
5211           indent (pos + name_length, pos + max_name_length);
5212           pos += max_name_length;
5213         }
5214 
5215       f = sorted_file[filesno];
5216       print_file_name_and_frills (f, pos);
5217 
5218       name_length = length_of_file_name_and_frills (f);
5219       max_name_length = line_fmt->col_arr[col];
5220     }
5221   putchar (eolbyte);
5222 }
5223 
5224 /* Output name + SEP + ' '.  */
5225 
5226 static void
print_with_separator(char sep)5227 print_with_separator (char sep)
5228 {
5229   size_t filesno;
5230   size_t pos = 0;
5231 
5232   for (filesno = 0; filesno < cwd_n_used; filesno++)
5233     {
5234       struct fileinfo const *f = sorted_file[filesno];
5235       size_t len = line_length ? length_of_file_name_and_frills (f) : 0;
5236 
5237       if (filesno != 0)
5238         {
5239           char separator;
5240 
5241           if (! line_length
5242               || ((pos + len + 2 < line_length)
5243                   && (pos <= SIZE_MAX - len - 2)))
5244             {
5245               pos += 2;
5246               separator = ' ';
5247             }
5248           else
5249             {
5250               pos = 0;
5251               separator = eolbyte;
5252             }
5253 
5254           putchar (sep);
5255           putchar (separator);
5256         }
5257 
5258       print_file_name_and_frills (f, pos);
5259       pos += len;
5260     }
5261   putchar (eolbyte);
5262 }
5263 
5264 /* Assuming cursor is at position FROM, indent up to position TO.
5265    Use a TAB character instead of two or more spaces whenever possible.  */
5266 
5267 static void
indent(size_t from,size_t to)5268 indent (size_t from, size_t to)
5269 {
5270   while (from < to)
5271     {
5272       if (tabsize != 0 && to / tabsize > (from + 1) / tabsize)
5273         {
5274           putchar ('\t');
5275           from += tabsize - from % tabsize;
5276         }
5277       else
5278         {
5279           putchar (' ');
5280           from++;
5281         }
5282     }
5283 }
5284 
5285 /* Put DIRNAME/NAME into DEST, handling '.' and '/' properly.  */
5286 /* FIXME: maybe remove this function someday.  See about using a
5287    non-malloc'ing version of file_name_concat.  */
5288 
5289 static void
attach(char * dest,char const * dirname,char const * name)5290 attach (char *dest, char const *dirname, char const *name)
5291 {
5292   char const *dirnamep = dirname;
5293 
5294   /* Copy dirname if it is not ".".  */
5295   if (dirname[0] != '.' || dirname[1] != 0)
5296     {
5297       while (*dirnamep)
5298         *dest++ = *dirnamep++;
5299       /* Add '/' if 'dirname' doesn't already end with it.  */
5300       if (dirnamep > dirname && dirnamep[-1] != '/')
5301         *dest++ = '/';
5302     }
5303   while (*name)
5304     *dest++ = *name++;
5305   *dest = 0;
5306 }
5307 
5308 /* Allocate enough column info suitable for the current number of
5309    files and display columns, and initialize the info to represent the
5310    narrowest possible columns.  */
5311 
5312 static void
init_column_info(size_t max_cols)5313 init_column_info (size_t max_cols)
5314 {
5315   size_t i;
5316 
5317   /* Currently allocated columns in column_info.  */
5318   static size_t column_info_alloc;
5319 
5320   if (column_info_alloc < max_cols)
5321     {
5322       size_t new_column_info_alloc;
5323       size_t *p;
5324 
5325       if (!max_idx || max_cols < max_idx / 2)
5326         {
5327           /* The number of columns is far less than the display width
5328              allows.  Grow the allocation, but only so that it's
5329              double the current requirements.  If the display is
5330              extremely wide, this avoids allocating a lot of memory
5331              that is never needed.  */
5332           column_info = xnrealloc (column_info, max_cols,
5333                                    2 * sizeof *column_info);
5334           new_column_info_alloc = 2 * max_cols;
5335         }
5336       else
5337         {
5338           column_info = xnrealloc (column_info, max_idx, sizeof *column_info);
5339           new_column_info_alloc = max_idx;
5340         }
5341 
5342       /* Allocate the new size_t objects by computing the triangle
5343          formula n * (n + 1) / 2, except that we don't need to
5344          allocate the part of the triangle that we've already
5345          allocated.  Check for address arithmetic overflow.  */
5346       {
5347         size_t column_info_growth = new_column_info_alloc - column_info_alloc;
5348         size_t s = column_info_alloc + 1 + new_column_info_alloc;
5349         size_t t = s * column_info_growth;
5350         if (s < new_column_info_alloc || t / column_info_growth != s)
5351           xalloc_die ();
5352         p = xnmalloc (t / 2, sizeof *p);
5353       }
5354 
5355       /* Grow the triangle by parceling out the cells just allocated.  */
5356       for (i = column_info_alloc; i < new_column_info_alloc; i++)
5357         {
5358           column_info[i].col_arr = p;
5359           p += i + 1;
5360         }
5361 
5362       column_info_alloc = new_column_info_alloc;
5363     }
5364 
5365   for (i = 0; i < max_cols; ++i)
5366     {
5367       size_t j;
5368 
5369       column_info[i].valid_len = true;
5370       column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
5371       for (j = 0; j <= i; ++j)
5372         column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
5373     }
5374 }
5375 
5376 /* Calculate the number of columns needed to represent the current set
5377    of files in the current display width.  */
5378 
5379 static size_t
calculate_columns(bool by_columns)5380 calculate_columns (bool by_columns)
5381 {
5382   size_t filesno;		/* Index into cwd_file.  */
5383   size_t cols;			/* Number of files across.  */
5384 
5385   /* Normally the maximum number of columns is determined by the
5386      screen width.  But if few files are available this might limit it
5387      as well.  */
5388   size_t max_cols = 0 < max_idx && max_idx < cwd_n_used ? max_idx : cwd_n_used;
5389 
5390   init_column_info (max_cols);
5391 
5392   /* Compute the maximum number of possible columns.  */
5393   for (filesno = 0; filesno < cwd_n_used; ++filesno)
5394     {
5395       struct fileinfo const *f = sorted_file[filesno];
5396       size_t name_length = length_of_file_name_and_frills (f);
5397 
5398       for (size_t i = 0; i < max_cols; ++i)
5399         {
5400           if (column_info[i].valid_len)
5401             {
5402               size_t idx = (by_columns
5403                             ? filesno / ((cwd_n_used + i) / (i + 1))
5404                             : filesno % (i + 1));
5405               size_t real_length = name_length + (idx == i ? 0 : 2);
5406 
5407               if (column_info[i].col_arr[idx] < real_length)
5408                 {
5409                   column_info[i].line_len += (real_length
5410                                               - column_info[i].col_arr[idx]);
5411                   column_info[i].col_arr[idx] = real_length;
5412                   column_info[i].valid_len = (column_info[i].line_len
5413                                               < line_length);
5414                 }
5415             }
5416         }
5417     }
5418 
5419   /* Find maximum allowed columns.  */
5420   for (cols = max_cols; 1 < cols; --cols)
5421     {
5422       if (column_info[cols - 1].valid_len)
5423         break;
5424     }
5425 
5426   return cols;
5427 }
5428 
5429 void
usage(int status)5430 usage (int status)
5431 {
5432   if (status != EXIT_SUCCESS)
5433     emit_try_help ();
5434   else
5435     {
5436       printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
5437       fputs (_("\
5438 List information about the FILEs (the current directory by default).\n\
5439 Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
5440 "), stdout);
5441 
5442       emit_mandatory_arg_note ();
5443 
5444       fputs (_("\
5445   -a, --all                  do not ignore entries starting with .\n\
5446   -A, --almost-all           do not list implied . and ..\n\
5447       --author               with -l, print the author of each file\n\
5448   -b, --escape               print C-style escapes for nongraphic characters\n\
5449 "), stdout);
5450       fputs (_("\
5451       --block-size=SIZE      with -l, scale sizes by SIZE when printing them;\n\
5452                              e.g., '--block-size=M'; see SIZE format below\n\
5453 \n\
5454 "), stdout);
5455       fputs (_("\
5456   -B, --ignore-backups       do not list implied entries ending with ~\n\
5457 "), stdout);
5458       fputs (_("\
5459   -c                         with -lt: sort by, and show, ctime (time of last\n\
5460                              change of file status information);\n\
5461                              with -l: show ctime and sort by name;\n\
5462                              otherwise: sort by ctime, newest first\n\
5463 \n\
5464 "), stdout);
5465       fputs (_("\
5466   -C                         list entries by columns\n\
5467       --color[=WHEN]         color the output WHEN; more info below\n\
5468   -d, --directory            list directories themselves, not their contents\n\
5469   -D, --dired                generate output designed for Emacs' dired mode\n\
5470 "), stdout);
5471       fputs (_("\
5472   -f                         list all entries in directory order\n\
5473   -F, --classify[=WHEN]      append indicator (one of */=>@|) to entries WHEN\n\
5474       --file-type            likewise, except do not append '*'\n\
5475 "), stdout);
5476       fputs (_("\
5477       --format=WORD          across -x, commas -m, horizontal -x, long -l,\n\
5478                              single-column -1, verbose -l, vertical -C\n\
5479 \n\
5480 "), stdout);
5481       fputs (_("\
5482       --full-time            like -l --time-style=full-iso\n\
5483 "), stdout);
5484       fputs (_("\
5485   -g                         like -l, but do not list owner\n\
5486 "), stdout);
5487       fputs (_("\
5488       --group-directories-first\n\
5489                              group directories before files;\n\
5490                              can be augmented with a --sort option, but any\n\
5491                              use of --sort=none (-U) disables grouping\n\
5492 \n\
5493 "), stdout);
5494       fputs (_("\
5495   -G, --no-group             in a long listing, don't print group names\n\
5496 "), stdout);
5497       fputs (_("\
5498   -h, --human-readable       with -l and -s, print sizes like 1K 234M 2G etc.\n\
5499       --si                   likewise, but use powers of 1000 not 1024\n\
5500 "), stdout);
5501       fputs (_("\
5502   -H, --dereference-command-line\n\
5503                              follow symbolic links listed on the command line\n\
5504 "), stdout);
5505       fputs (_("\
5506       --dereference-command-line-symlink-to-dir\n\
5507                              follow each command line symbolic link\n\
5508                              that points to a directory\n\
5509 \n\
5510 "), stdout);
5511       fputs (_("\
5512       --hide=PATTERN         do not list implied entries matching shell PATTERN\
5513 \n\
5514                              (overridden by -a or -A)\n\
5515 \n\
5516 "), stdout);
5517       fputs (_("\
5518       --hyperlink[=WHEN]     hyperlink file names WHEN\n\
5519 "), stdout);
5520       fputs (_("\
5521       --indicator-style=WORD\n\
5522                              append indicator with style WORD to entry names:\n\
5523                              none (default), slash (-p),\n\
5524                              file-type (--file-type), classify (-F)\n\
5525 \n\
5526 "), stdout);
5527       fputs (_("\
5528   -i, --inode                print the index number of each file\n\
5529   -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\
5530 \n\
5531 "), stdout);
5532       fputs (_("\
5533   -k, --kibibytes            default to 1024-byte blocks for file system usage;\
5534 \n\
5535                              used only with -s and per directory totals\n\
5536 \n\
5537 "), stdout);
5538       fputs (_("\
5539   -l                         use a long listing format\n\
5540 "), stdout);
5541       fputs (_("\
5542   -L, --dereference          when showing file information for a symbolic\n\
5543                              link, show information for the file the link\n\
5544                              references rather than for the link itself\n\
5545 \n\
5546 "), stdout);
5547       fputs (_("\
5548   -m                         fill width with a comma separated list of entries\
5549 \n\
5550 "), stdout);
5551       fputs (_("\
5552   -n, --numeric-uid-gid      like -l, but list numeric user and group IDs\n\
5553   -N, --literal              print entry names without quoting\n\
5554   -o                         like -l, but do not list group information\n\
5555   -p, --indicator-style=slash\n\
5556                              append / indicator to directories\n\
5557 "), stdout);
5558       fputs (_("\
5559   -q, --hide-control-chars   print ? instead of nongraphic characters\n\
5560 "), stdout);
5561       fputs (_("\
5562       --show-control-chars   show nongraphic characters as-is (the default,\n\
5563                              unless program is 'ls' and output is a terminal)\
5564 \n\
5565 \n\
5566 "), stdout);
5567       fputs (_("\
5568   -Q, --quote-name           enclose entry names in double quotes\n\
5569 "), stdout);
5570       fputs (_("\
5571       --quoting-style=WORD   use quoting style WORD for entry names:\n\
5572                              literal, locale, shell, shell-always,\n\
5573                              shell-escape, shell-escape-always, c, escape\n\
5574                              (overrides QUOTING_STYLE environment variable)\n\
5575 \n\
5576 "), stdout);
5577       fputs (_("\
5578   -r, --reverse              reverse order while sorting\n\
5579   -R, --recursive            list subdirectories recursively\n\
5580   -s, --size                 print the allocated size of each file, in blocks\n\
5581 "), stdout);
5582       fputs (_("\
5583   -S                         sort by file size, largest first\n\
5584 "), stdout);
5585       fputs (_("\
5586       --sort=WORD            sort by WORD instead of name: none (-U), size (-S)\
5587 ,\n\
5588                              time (-t), version (-v), extension (-X), width\n\
5589 \n\
5590 "), stdout);
5591       fputs (_("\
5592       --time=WORD            select which timestamp used to display or sort;\n\
5593                                access time (-u): atime, access, use;\n\
5594                                metadata change time (-c): ctime, status;\n\
5595                                modified time (default): mtime, modification;\n\
5596                                birth time: birth, creation;\n\
5597                              with -l, WORD determines which time to show;\n\
5598                              with --sort=time, sort by WORD (newest first)\n\
5599 \n\
5600 "), stdout);
5601       fputs (_("\
5602       --time-style=TIME_STYLE\n\
5603                              time/date format with -l; see TIME_STYLE below\n\
5604 "), stdout);
5605       fputs (_("\
5606   -t                         sort by time, newest first; see --time\n\
5607   -T, --tabsize=COLS         assume tab stops at each COLS instead of 8\n\
5608 "), stdout);
5609       fputs (_("\
5610   -u                         with -lt: sort by, and show, access time;\n\
5611                              with -l: show access time and sort by name;\n\
5612                              otherwise: sort by access time, newest first\n\
5613 \n\
5614 "), stdout);
5615       fputs (_("\
5616   -U                         do not sort; list entries in directory order\n\
5617 "), stdout);
5618       fputs (_("\
5619   -v                         natural sort of (version) numbers within text\n\
5620 "), stdout);
5621       fputs (_("\
5622   -w, --width=COLS           set output width to COLS.  0 means no limit\n\
5623   -x                         list entries by lines instead of by columns\n\
5624   -X                         sort alphabetically by entry extension\n\
5625   -Z, --context              print any security context of each file\n\
5626       --zero                 end each output line with NUL, not newline\n\
5627   -1                         list one file per line\n\
5628 "), stdout);
5629       fputs (HELP_OPTION_DESCRIPTION, stdout);
5630       fputs (VERSION_OPTION_DESCRIPTION, stdout);
5631       emit_size_note ();
5632       fputs (_("\
5633 \n\
5634 The TIME_STYLE argument can be full-iso, long-iso, iso, locale, or +FORMAT.\n\
5635 FORMAT is interpreted like in date(1).  If FORMAT is FORMAT1<newline>FORMAT2,\n\
5636 then FORMAT1 applies to non-recent files and FORMAT2 to recent files.\n\
5637 TIME_STYLE prefixed with 'posix-' takes effect only outside the POSIX locale.\n\
5638 Also the TIME_STYLE environment variable sets the default style to use.\n\
5639 "), stdout);
5640       fputs (_("\
5641 \n\
5642 The WHEN argument defaults to 'always' and can also be 'auto' or 'never'.\n\
5643 "), stdout);
5644       fputs (_("\
5645 \n\
5646 Using color to distinguish file types is disabled both by default and\n\
5647 with --color=never.  With --color=auto, ls emits color codes only when\n\
5648 standard output is connected to a terminal.  The LS_COLORS environment\n\
5649 variable can change the settings.  Use the dircolors(1) command to set it.\n\
5650 "), stdout);
5651       fputs (_("\
5652 \n\
5653 Exit status:\n\
5654  0  if OK,\n\
5655  1  if minor problems (e.g., cannot access subdirectory),\n\
5656  2  if serious trouble (e.g., cannot access command-line argument).\n\
5657 "), stdout);
5658       emit_ancillary_info (PROGRAM_NAME);
5659     }
5660   exit (status);
5661 }
5662