*** empty log message ***
[coreutils.git] / src / ls.c
blob13602af2bec5c40b6f927fd30f6823979f0fb3d1
1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
2 Copyright (C) 85, 88, 90, 91, 1995-2002 Free Software Foundation, Inc.
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 2, or (at your option)
7 any later version.
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software Foundation,
16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18 /* If ls_mode is LS_MULTI_COL,
19 the multi-column format is the default regardless
20 of the type of output device.
21 This is for the `dir' program.
23 If ls_mode is LS_LONG_FORMAT,
24 the long format is the default regardless of the
25 type of output device.
26 This is for the `vdir' program.
28 If ls_mode is LS_LS,
29 the output format depends on whether the output
30 device is a terminal.
31 This is for the `ls' program. */
33 /* Written by Richard Stallman and David MacKenzie. */
35 /* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis
36 Flaherty <dennisf@denix.elk.miles.com> based on original patches by
37 Greg Lee <lee@uhunix.uhcc.hawaii.edu>. */
39 #ifdef _AIX
40 #pragma alloca
41 #endif
43 #include <config.h>
44 #include <sys/types.h>
46 #if HAVE_INTTYPES_H
47 # include <inttypes.h>
48 #endif
50 #if HAVE_TERMIOS_H
51 # include <termios.h>
52 #endif
54 #ifdef GWINSZ_IN_SYS_IOCTL
55 # include <sys/ioctl.h>
56 #endif
58 #ifdef WINSIZE_IN_PTEM
59 # include <sys/stream.h>
60 # include <sys/ptem.h>
61 #endif
63 #include <stdio.h>
64 #include <assert.h>
65 #include <setjmp.h>
66 #include <grp.h>
67 #include <pwd.h>
68 #include <getopt.h>
70 /* Get MB_CUR_MAX. */
71 #if HAVE_STDLIB_H
72 # include <stdlib.h>
73 #endif
75 /* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
76 #if HAVE_WCHAR_H
77 # include <wchar.h>
78 #endif
80 /* Get iswprint(). */
81 #if HAVE_WCTYPE_H
82 # include <wctype.h>
83 #endif
84 #if !defined iswprint && !HAVE_ISWPRINT
85 # define iswprint(wc) 1
86 #endif
88 #ifndef HAVE_DECL_WCWIDTH
89 "this configure-time declaration test was not run"
90 #endif
91 #if !HAVE_DECL_WCWIDTH
92 int wcwidth ();
93 #endif
95 /* If wcwidth() doesn't exist, assume all printable characters have
96 width 1. */
97 #ifndef wcwidth
98 # if !HAVE_WCWIDTH
99 # define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
100 # endif
101 #endif
103 #include "system.h"
104 #include <fnmatch.h>
106 #include "acl.h"
107 #include "argmatch.h"
108 #include "dirname.h"
109 #include "dirfd.h"
110 #include "error.h"
111 #include "hard-locale.h"
112 #include "hash.h"
113 #include "human.h"
114 #include "filemode.h"
115 #include "ls.h"
116 #include "mbswidth.h"
117 #include "obstack.h"
118 #include "path-concat.h"
119 #include "quote.h"
120 #include "quotearg.h"
121 #include "same.h"
122 #include "strverscmp.h"
123 #include "xstrtol.h"
124 #include "xreadlink.h"
126 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
127 : (ls_mode == LS_MULTI_COL \
128 ? "dir" : "vdir"))
130 #define AUTHORS N_ ("Richard Stallman and David MacKenzie")
132 #define obstack_chunk_alloc malloc
133 #define obstack_chunk_free free
135 /* Return an int indicating the result of comparing two integers.
136 Subtracting doesn't always work, due to overflow. */
137 #define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
139 /* The field width for inode numbers. On some hosts inode numbers are
140 64 bits, so columns won't line up exactly when a huge inode number
141 is encountered, but in practice 7 digits is usually enough. */
142 #ifndef INODE_DIGITS
143 # define INODE_DIGITS 7
144 #endif
146 #ifdef S_ISLNK
147 # define HAVE_SYMLINKS 1
148 #else
149 # define HAVE_SYMLINKS 0
150 #endif
152 /* Arrange to make lstat calls go through the wrapper function
153 on systems with an lstat function that does not dereference symlinks
154 that are specified with a trailing slash. */
155 #if ! LSTAT_FOLLOWS_SLASHED_SYMLINK
156 int rpl_lstat PARAMS((const char *, struct stat *));
157 # undef lstat
158 # define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
159 #endif
161 #if HAVE_STRUCT_DIRENT_D_TYPE && defined DTTOIF
162 # define DT_INIT(Val) = Val
163 #else
164 # define DT_INIT(Val) /* empty */
165 #endif
167 #ifdef ST_MTIM_NSEC
168 # define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC)
169 #else
170 # define TIMESPEC_NS(timespec) 0
171 #endif
173 #if ! HAVE_STRUCT_STAT_ST_AUTHOR
174 # define st_author st_uid
175 #endif
177 /* Cray/Unicos DMF: use the file's migrated, not real, status */
178 #if HAVE_ST_DM_MODE
179 # define ST_DM_MODE(Stat_buf) ((Stat_buf).st_dm_mode)
180 #else
181 # define ST_DM_MODE(Stat_buf) ((Stat_buf).st_mode)
182 #endif
184 #ifndef LOGIN_NAME_MAX
185 # if _POSIX_LOGIN_NAME_MAX
186 # define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX
187 # else
188 # define LOGIN_NAME_MAX 17
189 # endif
190 #endif
192 /* The maximum length of a string representation of a user or group ID,
193 not counting any terminating NUL byte. */
194 #define ID_LENGTH_MAX \
195 MAX (LOGIN_NAME_MAX - 1, LONGEST_HUMAN_READABLE)
197 enum filetype
199 unknown DT_INIT (DT_UNKNOWN),
200 fifo DT_INIT (DT_FIFO),
201 chardev DT_INIT (DT_CHR),
202 directory DT_INIT (DT_DIR),
203 blockdev DT_INIT (DT_BLK),
204 normal DT_INIT (DT_REG),
205 symbolic_link DT_INIT (DT_LNK),
206 sock DT_INIT (DT_SOCK),
207 arg_directory DT_INIT (2 * (DT_UNKNOWN | DT_FIFO | DT_CHR | DT_DIR | DT_BLK
208 | DT_REG | DT_LNK | DT_SOCK))
211 struct fileinfo
213 /* The file name. */
214 char *name;
216 struct stat stat;
218 /* For symbolic link, name of the file linked to, otherwise zero. */
219 char *linkname;
221 /* For symbolic link and long listing, st_mode of file linked to, otherwise
222 zero. */
223 mode_t linkmode;
225 /* For symbolic link and color printing, 1 if linked-to file
226 exists, otherwise 0. */
227 int linkok;
229 enum filetype filetype;
231 #if HAVE_ACL
232 /* For long listings, true if the file has an access control list. */
233 bool have_acl;
234 #endif
237 #if HAVE_ACL
238 # define FILE_HAS_ACL(F) ((F)->have_acl)
239 #else
240 # define FILE_HAS_ACL(F) 0
241 #endif
243 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
245 /* Null is a valid character in a color indicator (think about Epson
246 printers, for example) so we have to use a length/buffer string
247 type. */
249 struct bin_str
251 int len; /* Number of bytes */
252 const char *string; /* Pointer to the same */
255 #ifndef STDC_HEADERS
256 time_t time ();
257 #endif
259 size_t nstrftime PARAMS ((char *, size_t, char const *,
260 struct tm const *, int, int));
261 char *getgroup ();
262 char *getuser ();
264 static size_t quote_name PARAMS ((FILE *out, const char *name,
265 struct quoting_options const *options));
266 static char *make_link_path PARAMS ((const char *path, const char *linkname));
267 static int decode_switches PARAMS ((int argc, char **argv));
268 static int file_interesting PARAMS ((const struct dirent *next));
269 static uintmax_t gobble_file PARAMS ((const char *name, enum filetype type,
270 int explicit_arg, const char *dirname));
271 static void print_color_indicator PARAMS ((const char *name, mode_t mode,
272 int linkok));
273 static void put_indicator PARAMS ((const struct bin_str *ind));
274 static int length_of_file_name_and_frills PARAMS ((const struct fileinfo *f));
275 static void add_ignore_pattern PARAMS ((const char *pattern));
276 static void attach PARAMS ((char *dest, const char *dirname, const char *name));
277 static void clear_files PARAMS ((void));
278 static void extract_dirs_from_files PARAMS ((const char *dirname,
279 int ignore_dot_and_dot_dot));
280 static void get_link_name PARAMS ((const char *filename, struct fileinfo *f));
281 static void indent PARAMS ((int from, int to));
282 static void init_column_info PARAMS ((void));
283 static void print_current_files PARAMS ((void));
284 static void print_dir PARAMS ((const char *name, const char *realname));
285 static void print_file_name_and_frills PARAMS ((const struct fileinfo *f));
286 static void print_horizontal PARAMS ((void));
287 static void print_long_format PARAMS ((const struct fileinfo *f));
288 static void print_many_per_line PARAMS ((void));
289 static void print_name_with_quoting PARAMS ((const char *p, mode_t mode,
290 int linkok,
291 struct obstack *stack));
292 static void prep_non_filename_text PARAMS ((void));
293 static void print_type_indicator PARAMS ((mode_t mode));
294 static void print_with_commas PARAMS ((void));
295 static void queue_directory PARAMS ((const char *name, const char *realname));
296 static void sort_files PARAMS ((void));
297 static void parse_ls_color PARAMS ((void));
298 void usage PARAMS ((int status));
300 /* The name the program was run with, stripped of any leading path. */
301 char *program_name;
303 /* Initial size of hash table.
304 Most hierarchies are likely to be shallower than this. */
305 #define INITIAL_TABLE_SIZE 30
307 /* The set of `active' directories, from the current command-line argument
308 to the level in the hierarchy at which files are being listed.
309 A directory is represented by its device and inode numbers.
310 A directory is added to this set when ls begins listing it or its
311 entries, and it is removed from the set just after ls has finished
312 processing it. This set is used solely to detect loops, e.g., with
313 mkdir loop; cd loop; ln -s ../loop sub; ls -RL */
314 static Hash_table *active_dir_set;
316 #define LOOP_DETECT (!!active_dir_set)
318 /* An entry in the active_dir_set. */
319 struct dev_ino
321 dev_t st_dev;
322 ino_t st_ino;
325 /* The table of files in the current directory:
327 `files' points to a vector of `struct fileinfo', one per file.
328 `nfiles' is the number of elements space has been allocated for.
329 `files_index' is the number actually in use. */
331 /* Address of block containing the files that are described. */
332 static struct fileinfo *files; /* FIXME: rename this to e.g. cwd_file */
334 /* Length of block that `files' points to, measured in files. */
335 static int nfiles; /* FIXME: rename this to e.g. cwd_n_alloc */
337 /* Index of first unused in `files'. */
338 static int files_index; /* FIXME: rename this to e.g. cwd_n_used */
340 /* When nonzero, in a color listing, color each symlink name according to the
341 type of file it points to. Otherwise, color them according to the `ln'
342 directive in LS_COLORS. Dangling (orphan) symlinks are treated specially,
343 regardless. This is set when `ln=target' appears in LS_COLORS. */
345 static int color_symlink_as_referent;
347 /* mode of appropriate file for colorization */
348 #define FILE_OR_LINK_MODE(File) \
349 ((color_symlink_as_referent && (File)->linkok) \
350 ? (File)->linkmode : (File)->stat.st_mode)
353 /* Record of one pending directory waiting to be listed. */
355 struct pending
357 char *name;
358 /* If the directory is actually the file pointed to by a symbolic link we
359 were told to list, `realname' will contain the name of the symbolic
360 link, otherwise zero. */
361 char *realname;
362 struct pending *next;
365 static struct pending *pending_dirs;
367 /* Current time in seconds and nanoseconds since 1970, updated as
368 needed when deciding whether a file is recent. */
370 static time_t current_time = TYPE_MINIMUM (time_t);
371 static int current_time_ns = -1;
373 /* The number of digits to use for block sizes.
374 4, or more if needed for bigger numbers. */
376 static int block_size_size;
378 /* Option flags */
380 /* long_format for lots of info, one per line.
381 one_per_line for just names, one per line.
382 many_per_line for just names, many per line, sorted vertically.
383 horizontal for just names, many per line, sorted horizontally.
384 with_commas for just names, many per line, separated by commas.
386 -l (and other options that imply -l), -1, -C, -x and -m control
387 this parameter. */
389 enum format
391 long_format, /* -l and other options that imply -l */
392 one_per_line, /* -1 */
393 many_per_line, /* -C */
394 horizontal, /* -x */
395 with_commas /* -m */
398 static enum format format;
400 /* `full-iso' uses full ISO-style dates and times. `long-iso' uses longer
401 ISO-style time stamps, though shorter than `full-iso'. `iso' uses shorter
402 ISO-style time stamps. `locale' uses locale-dependent time stamps. */
403 enum time_style
405 full_iso_time_style, /* --time-style=full-iso */
406 long_iso_time_style, /* --time-style=long-iso */
407 iso_time_style, /* --time-style=iso */
408 locale_time_style /* --time-style=locale */
411 static char const *const time_style_args[] =
413 "full-iso", "long-iso", "iso", "locale", 0
416 static enum time_style const time_style_types[] =
418 full_iso_time_style, long_iso_time_style, iso_time_style,
419 locale_time_style, 0
422 /* Type of time to print or sort by. Controlled by -c and -u. */
424 enum time_type
426 time_mtime, /* default */
427 time_ctime, /* -c */
428 time_atime /* -u */
431 static enum time_type time_type;
433 /* The file characteristic to sort by. Controlled by -t, -S, -U, -X, -v. */
435 enum sort_type
437 sort_none, /* -U */
438 sort_name, /* default */
439 sort_extension, /* -X */
440 sort_time, /* -t */
441 sort_size, /* -S */
442 sort_version /* -v */
445 static enum sort_type sort_type;
447 /* Direction of sort.
448 0 means highest first if numeric,
449 lowest first if alphabetic;
450 these are the defaults.
451 1 means the opposite order in each case. -r */
453 static int sort_reverse;
455 /* Nonzero means to display owner information. -g turns this off. */
457 static int print_owner = 1;
459 /* Nonzero means to display author information. */
461 static bool print_author;
463 /* Nonzero means to display group information. -G and -o turn this off. */
465 static int print_group = 1;
467 /* Nonzero means print the user and group id's as numbers rather
468 than as names. -n */
470 static int numeric_ids;
472 /* Nonzero means mention the size in blocks of each file. -s */
474 static int print_block_size;
476 /* If positive, the units to use when printing sizes;
477 if negative, the human-readable base. */
478 static int output_block_size;
480 /* Precede each line of long output (per file) with a string like `m,n:'
481 where M is the number of characters after the `:' and before the
482 filename and N is the length of the filename. Using this format,
483 Emacs' dired mode starts up twice as fast, and can handle all
484 strange characters in file names. */
485 static int dired;
487 /* `none' means don't mention the type of files.
488 `classify' means mention file types and mark executables.
489 `file_type' means mention only file types.
491 Controlled by -F, -p, and --indicator-style. */
493 enum indicator_style
495 none, /* --indicator-style=none */
496 classify, /* -F, --indicator-style=classify */
497 file_type /* -p, --indicator-style=file-type */
500 static enum indicator_style indicator_style;
502 /* Names of indicator styles. */
503 static char const *const indicator_style_args[] =
505 "none", "classify", "file-type", 0
508 static enum indicator_style const indicator_style_types[]=
510 none, classify, file_type
513 /* Nonzero means use colors to mark types. Also define the different
514 colors as well as the stuff for the LS_COLORS environment variable.
515 The LS_COLORS variable is now in a termcap-like format. */
517 static int print_with_color;
519 enum color_type
521 color_never, /* 0: default or --color=never */
522 color_always, /* 1: --color=always */
523 color_if_tty /* 2: --color=tty */
526 enum Dereference_symlink
528 DEREF_UNDEFINED = 1,
529 DEREF_NEVER,
530 DEREF_COMMAND_LINE_ARGUMENTS, /* -H */
531 DEREF_ALWAYS /* -L */
534 enum indicator_no
536 C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
537 C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR
540 static const char *const indicator_name[]=
542 "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
543 "bd", "cd", "mi", "or", "ex", "do", NULL
546 struct color_ext_type
548 struct bin_str ext; /* The extension we're looking for */
549 struct bin_str seq; /* The sequence to output when we do */
550 struct color_ext_type *next; /* Next in list */
553 static struct bin_str color_indicator[] =
555 { LEN_STR_PAIR ("\033[") }, /* lc: Left of color sequence */
556 { LEN_STR_PAIR ("m") }, /* rc: Right of color sequence */
557 { 0, NULL }, /* ec: End color (replaces lc+no+rc) */
558 { LEN_STR_PAIR ("0") }, /* no: Normal */
559 { LEN_STR_PAIR ("0") }, /* fi: File: default */
560 { LEN_STR_PAIR ("01;34") }, /* di: Directory: bright blue */
561 { LEN_STR_PAIR ("01;36") }, /* ln: Symlink: bright cyan */
562 { LEN_STR_PAIR ("33") }, /* pi: Pipe: yellow/brown */
563 { LEN_STR_PAIR ("01;35") }, /* so: Socket: bright magenta */
564 { LEN_STR_PAIR ("01;33") }, /* bd: Block device: bright yellow */
565 { LEN_STR_PAIR ("01;33") }, /* cd: Char device: bright yellow */
566 { 0, NULL }, /* mi: Missing file: undefined */
567 { 0, NULL }, /* or: Orphanned symlink: undefined */
568 { LEN_STR_PAIR ("01;32") }, /* ex: Executable: bright green */
569 { LEN_STR_PAIR ("01;35") } /* do: Door: bright magenta */
572 /* FIXME: comment */
573 static struct color_ext_type *color_ext_list = NULL;
575 /* Buffer for color sequences */
576 static char *color_buf;
578 /* Nonzero means to check for orphaned symbolic link, for displaying
579 colors. */
581 static int check_symlink_color;
583 /* Nonzero means mention the inode number of each file. -i */
585 static int print_inode;
587 /* What to do with symbolic links. Affected by -d, -F, -H, -l (and
588 other options that imply -l), and -L. */
590 static enum Dereference_symlink dereference;
592 /* Nonzero means when a directory is found, display info on its
593 contents. -R */
595 static int recursive;
597 /* Nonzero means when an argument is a directory name, display info
598 on it itself. -d */
600 static int immediate_dirs;
602 /* Nonzero means don't omit files whose names start with `.'. -A */
604 static int all_files;
606 /* Nonzero means don't omit files `.' and `..'
607 This flag implies `all_files'. -a */
609 static int really_all_files;
611 /* A linked list of shell-style globbing patterns. If a non-argument
612 file name matches any of these patterns, it is omitted.
613 Controlled by -I. Multiple -I options accumulate.
614 The -B option adds `*~' and `.*~' to this list. */
616 struct ignore_pattern
618 const char *pattern;
619 struct ignore_pattern *next;
622 static struct ignore_pattern *ignore_patterns;
624 /* Nonzero means output nongraphic chars in file names as `?'.
625 (-q, --hide-control-chars)
626 qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
627 independent. The algorithm is: first, obey the quoting style to get a
628 string representing the file name; then, if qmark_funny_chars is set,
629 replace all nonprintable chars in that string with `?'. It's necessary
630 to replace nonprintable chars even in quoted strings, because we don't
631 want to mess up the terminal if control chars get sent to it, and some
632 quoting methods pass through control chars as-is. */
633 static int qmark_funny_chars;
635 /* Quoting options for file and dir name output. */
637 static struct quoting_options *filename_quoting_options;
638 static struct quoting_options *dirname_quoting_options;
640 /* The number of chars per hardware tab stop. Setting this to zero
641 inhibits the use of TAB characters for separating columns. -T */
642 static int tabsize;
644 /* Nonzero means we are listing the working directory because no
645 non-option arguments were given. */
647 static int dir_defaulted;
649 /* Nonzero means print each directory name before listing it. */
651 static int print_dir_name;
653 /* The line length to use for breaking lines in many-per-line format.
654 Can be set with -w. */
656 static int line_length;
658 /* If nonzero, the file listing format requires that stat be called on
659 each file. */
661 static int format_needs_stat;
663 /* Similar to `format_needs_stat', but set if only the file type is
664 needed. */
666 static int format_needs_type;
668 /* strftime formats for non-recent and recent files, respectively, in
669 -l output. */
671 static char const *long_time_format[2] =
673 /* strftime format for non-recent files (older than 6 months), in
674 -l output when --time-style=locale is specified. This should
675 contain the year, month and day (at least), in an order that is
676 understood by people in your locale's territory.
677 Please try to keep the number of used screen columns small,
678 because many people work in windows with only 80 columns. But
679 make this as wide as the other string below, for recent files. */
680 N_("%b %e %Y"),
681 /* strftime format for recent files (younger than 6 months), in
682 -l output when --time-style=locale is specified. This should
683 contain the month, day and time (at least), in an order that is
684 understood by people in your locale's territory.
685 Please try to keep the number of used screen columns small,
686 because many people work in windows with only 80 columns. But
687 make this as wide as the other string above, for non-recent files. */
688 N_("%b %e %H:%M")
691 /* The exit status to use if we don't get any fatal errors. */
693 static int exit_status;
695 /* For long options that have no equivalent short option, use a
696 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
697 enum
699 AUTHOR_OPTION = CHAR_MAX + 1,
700 BLOCK_SIZE_OPTION,
701 COLOR_OPTION,
702 FORMAT_OPTION,
703 FULL_TIME_OPTION,
704 INDICATOR_STYLE_OPTION,
705 QUOTING_STYLE_OPTION,
706 SHOW_CONTROL_CHARS_OPTION,
707 SI_OPTION,
708 SORT_OPTION,
709 TIME_OPTION,
710 TIME_STYLE_OPTION
713 static struct option const long_options[] =
715 {"all", no_argument, 0, 'a'},
716 {"escape", no_argument, 0, 'b'},
717 {"directory", no_argument, 0, 'd'},
718 {"dired", no_argument, 0, 'D'},
719 {"full-time", no_argument, 0, FULL_TIME_OPTION},
720 {"human-readable", no_argument, 0, 'h'},
721 {"inode", no_argument, 0, 'i'},
722 {"kilobytes", no_argument, 0, 'k'}, /* long form is obsolescent */
723 {"numeric-uid-gid", no_argument, 0, 'n'},
724 {"no-group", no_argument, 0, 'G'},
725 {"hide-control-chars", no_argument, 0, 'q'},
726 {"reverse", no_argument, 0, 'r'},
727 {"size", no_argument, 0, 's'},
728 {"width", required_argument, 0, 'w'},
729 {"almost-all", no_argument, 0, 'A'},
730 {"ignore-backups", no_argument, 0, 'B'},
731 {"classify", no_argument, 0, 'F'},
732 {"file-type", no_argument, 0, 'p'},
733 {"si", no_argument, 0, SI_OPTION},
734 {"dereference-command-line", no_argument, 0, 'H'},
735 {"ignore", required_argument, 0, 'I'},
736 {"indicator-style", required_argument, 0, INDICATOR_STYLE_OPTION},
737 {"dereference", no_argument, 0, 'L'},
738 {"literal", no_argument, 0, 'N'},
739 {"quote-name", no_argument, 0, 'Q'},
740 {"quoting-style", required_argument, 0, QUOTING_STYLE_OPTION},
741 {"recursive", no_argument, 0, 'R'},
742 {"format", required_argument, 0, FORMAT_OPTION},
743 {"show-control-chars", no_argument, 0, SHOW_CONTROL_CHARS_OPTION},
744 {"sort", required_argument, 0, SORT_OPTION},
745 {"tabsize", required_argument, 0, 'T'},
746 {"time", required_argument, 0, TIME_OPTION},
747 {"time-style", required_argument, 0, TIME_STYLE_OPTION},
748 {"color", optional_argument, 0, COLOR_OPTION},
749 {"block-size", required_argument, 0, BLOCK_SIZE_OPTION},
750 {"author", no_argument, 0, AUTHOR_OPTION},
751 {GETOPT_HELP_OPTION_DECL},
752 {GETOPT_VERSION_OPTION_DECL},
753 {NULL, 0, NULL, 0}
756 static char const *const format_args[] =
758 "verbose", "long", "commas", "horizontal", "across",
759 "vertical", "single-column", 0
762 static enum format const format_types[] =
764 long_format, long_format, with_commas, horizontal, horizontal,
765 many_per_line, one_per_line
768 static char const *const sort_args[] =
770 "none", "time", "size", "extension", "version", 0
773 static enum sort_type const sort_types[] =
775 sort_none, sort_time, sort_size, sort_extension, sort_version
778 static char const *const time_args[] =
780 "atime", "access", "use", "ctime", "status", 0
783 static enum time_type const time_types[] =
785 time_atime, time_atime, time_atime, time_ctime, time_ctime
788 static char const *const color_args[] =
790 /* force and none are for compatibility with another color-ls version */
791 "always", "yes", "force",
792 "never", "no", "none",
793 "auto", "tty", "if-tty", 0
796 static enum color_type const color_types[] =
798 color_always, color_always, color_always,
799 color_never, color_never, color_never,
800 color_if_tty, color_if_tty, color_if_tty
803 /* Information about filling a column. */
804 struct column_info
806 int valid_len;
807 int line_len;
808 int *col_arr;
811 /* Array with information about column filledness. */
812 static struct column_info *column_info;
814 /* Maximum number of columns ever possible for this display. */
815 static int max_idx;
817 /* The minimum width of a colum is 3: 1 character for the name and 2
818 for the separating white space. */
819 #define MIN_COLUMN_WIDTH 3
822 /* This zero-based index is used solely with the --dired option.
823 When that option is in effect, this counter is incremented for each
824 character of output generated by this program so that the beginning
825 and ending indices (in that output) of every file name can be recorded
826 and later output themselves. */
827 static size_t dired_pos;
829 #define DIRED_PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
831 /* Write S to STREAM and increment DIRED_POS by S_LEN. */
832 #define DIRED_FPUTS(s, stream, s_len) \
833 do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
835 /* Like DIRED_FPUTS, but for use when S is a literal string. */
836 #define DIRED_FPUTS_LITERAL(s, stream) \
837 do {fputs ((s), (stream)); dired_pos += sizeof((s)) - 1;} while (0)
839 #define DIRED_INDENT() \
840 do \
842 /* FIXME: remove the `&& format == long_format' clause. */ \
843 if (dired && format == long_format) \
844 DIRED_FPUTS_LITERAL (" ", stdout); \
846 while (0)
848 /* With --dired, store pairs of beginning and ending indices of filenames. */
849 static struct obstack dired_obstack;
851 /* With --dired, store pairs of beginning and ending indices of any
852 directory names that appear as headers (just before `total' line)
853 for lists of directory entries. Such directory names are seen when
854 listing hierarchies using -R and when a directory is listed with at
855 least one other command line argument. */
856 static struct obstack subdired_obstack;
858 /* Save the current index on the specified obstack, OBS. */
859 #define PUSH_CURRENT_DIRED_POS(obs) \
860 do \
862 /* FIXME: remove the `&& format == long_format' clause. */ \
863 if (dired && format == long_format) \
864 obstack_grow ((obs), &dired_pos, sizeof (dired_pos)); \
866 while (0)
868 /* With -R, this stack is used to help detect directory cycles.
869 The device/inode pairs on this stack mirror the pairs in the
870 active_dir_set hash table. */
871 static struct obstack dev_ino_obstack;
873 /* Push a pair onto the device/inode stack. */
874 #define DEV_INO_PUSH(Dev, Ino) \
875 do \
877 struct dev_ino *di; \
878 obstack_blank (&dev_ino_obstack, sizeof (struct dev_ino)); \
879 di = -1 + (struct dev_ino *) obstack_next_free (&dev_ino_obstack); \
880 di->st_dev = (Dev); \
881 di->st_ino = (Ino); \
883 while (0)
885 /* Pop a dev/ino struct off the global dev_ino_obstack
886 and return that struct. */
887 static struct dev_ino
888 dev_ino_pop (void)
890 assert (sizeof (struct dev_ino) <= obstack_object_size (&dev_ino_obstack));
891 obstack_blank (&dev_ino_obstack, -(int) (sizeof (struct dev_ino)));
892 return *(struct dev_ino*) obstack_next_free (&dev_ino_obstack);
895 #define ASSERT_MATCHING_DEV_INO(Name, Di) \
896 do \
898 struct stat sb; \
899 assert (Name); \
900 assert (0 <= stat (Name, &sb)); \
901 assert (sb.st_dev == Di.st_dev); \
902 assert (sb.st_ino == Di.st_ino); \
904 while (0)
907 /* Write to standard output PREFIX, followed by the quoting style and
908 a space-separated list of the integers stored in OS all on one line. */
910 static void
911 dired_dump_obstack (const char *prefix, struct obstack *os)
913 int n_pos;
915 n_pos = obstack_object_size (os) / sizeof (dired_pos);
916 if (n_pos > 0)
918 int i;
919 size_t *pos;
921 pos = (size_t *) obstack_finish (os);
922 fputs (prefix, stdout);
923 for (i = 0; i < n_pos; i++)
924 printf (" %lu", (unsigned long) pos[i]);
925 fputs ("\n", stdout);
929 static unsigned int
930 dev_ino_hash (void const *x, unsigned int table_size)
932 struct dev_ino const *p = x;
933 return (uintmax_t) p->st_ino % table_size;
936 static bool
937 dev_ino_compare (void const *x, void const *y)
939 struct dev_ino const *a = x;
940 struct dev_ino const *b = y;
941 return SAME_INODE (*a, *b) ? true : false;
944 static void
945 dev_ino_free (void *x)
947 free (x);
950 /* Add the device/inode pair (P->st_dev/P->st_ino) to the set of
951 active directories. Return nonzero if there is already a matching
952 entry in the table. Otherwise, return zero. */
954 static int
955 visit_dir (dev_t dev, ino_t ino)
957 struct dev_ino *ent;
958 struct dev_ino *ent_from_table;
959 int found_match;
961 ent = XMALLOC (struct dev_ino, 1);
962 ent->st_ino = ino;
963 ent->st_dev = dev;
965 /* Attempt to insert this entry into the table. */
966 ent_from_table = hash_insert (active_dir_set, ent);
968 if (ent_from_table == NULL)
970 /* Insertion failed due to lack of memory. */
971 xalloc_die ();
974 found_match = (ent_from_table != ent);
976 if (found_match)
978 /* ent was not inserted, so free it. */
979 free (ent);
982 return found_match;
985 static void
986 free_pending_ent (struct pending *p)
988 if (p->name)
989 free (p->name);
990 if (p->realname)
991 free (p->realname);
992 free (p);
996 main (int argc, char **argv)
998 register int i;
999 register struct pending *thispend;
1000 unsigned int n_files;
1002 program_name = argv[0];
1003 setlocale (LC_ALL, "");
1004 bindtextdomain (PACKAGE, LOCALEDIR);
1005 textdomain (PACKAGE);
1007 atexit (close_stdout);
1009 #define N_ENTRIES(Array) (sizeof Array / sizeof *(Array))
1010 assert (N_ENTRIES (color_indicator) + 1 == N_ENTRIES (indicator_name));
1012 exit_status = 0;
1013 dir_defaulted = 1;
1014 print_dir_name = 1;
1015 pending_dirs = 0;
1017 i = decode_switches (argc, argv);
1019 if (print_with_color)
1020 parse_ls_color ();
1022 /* Test print_with_color again, because the call to parse_ls_color
1023 may have just reset it -- e.g., if LS_COLORS is invalid. */
1024 if (print_with_color)
1026 prep_non_filename_text ();
1027 /* Avoid following symbolic links when possible. */
1028 if (color_indicator[C_ORPHAN].string != NULL
1029 || (color_indicator[C_MISSING].string != NULL
1030 && format == long_format))
1031 check_symlink_color = 1;
1034 if (dereference == DEREF_UNDEFINED)
1035 dereference = ((immediate_dirs
1036 || indicator_style == classify
1037 || format == long_format)
1038 ? DEREF_NEVER
1039 : DEREF_COMMAND_LINE_ARGUMENTS);
1041 /* When using -R, initialize a data structure we'll use to
1042 detect any directory cycles. */
1043 if (recursive)
1045 active_dir_set = hash_initialize (INITIAL_TABLE_SIZE, NULL,
1046 dev_ino_hash,
1047 dev_ino_compare,
1048 dev_ino_free);
1049 if (active_dir_set == NULL)
1050 xalloc_die ();
1052 obstack_init (&dev_ino_obstack);
1055 format_needs_stat = sort_type == sort_time || sort_type == sort_size
1056 || format == long_format
1057 || dereference == DEREF_ALWAYS
1058 || recursive || print_block_size || print_inode;
1059 format_needs_type = (format_needs_stat == 0
1060 && (print_with_color || indicator_style != none));
1062 if (dired && format == long_format)
1064 obstack_init (&dired_obstack);
1065 obstack_init (&subdired_obstack);
1068 nfiles = 100;
1069 files = XMALLOC (struct fileinfo, nfiles);
1070 files_index = 0;
1072 clear_files ();
1074 n_files = argc - i;
1075 if (0 < n_files)
1076 dir_defaulted = 0;
1078 for (; i < argc; i++)
1080 gobble_file (argv[i], unknown, 1, "");
1083 if (dir_defaulted)
1085 if (immediate_dirs)
1086 gobble_file (".", directory, 1, "");
1087 else
1088 queue_directory (".", 0);
1091 if (files_index)
1093 sort_files ();
1094 if (!immediate_dirs)
1095 extract_dirs_from_files ("", 0);
1096 /* `files_index' might be zero now. */
1099 /* In the following if/else blocks, it is sufficient to test `pending_dirs'
1100 (and not pending_dirs->name) because there may be no markers in the queue
1101 at this point. A marker may be enqueued when extract_dirs_from_files is
1102 called with a non-empty string or via print_dir. */
1103 if (files_index)
1105 print_current_files ();
1106 if (pending_dirs)
1107 DIRED_PUTCHAR ('\n');
1109 else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0)
1110 print_dir_name = 0;
1112 while (pending_dirs)
1114 thispend = pending_dirs;
1115 pending_dirs = pending_dirs->next;
1117 if (LOOP_DETECT)
1119 if (thispend->name == NULL)
1121 /* thispend->name == NULL means this is a marker entry
1122 indicating we've finished processing the directory.
1123 Use its dev/ino numbers to remove the corresponding
1124 entry from the active_dir_set hash table. */
1125 struct dev_ino di = dev_ino_pop ();
1126 struct dev_ino *found = hash_delete (active_dir_set, &di);
1127 /* ASSERT_MATCHING_DEV_INO (thispend->realname, di); */
1128 assert (found);
1129 dev_ino_free (found);
1130 free_pending_ent (thispend);
1131 continue;
1135 print_dir (thispend->name, thispend->realname);
1137 free_pending_ent (thispend);
1138 print_dir_name = 1;
1141 if (dired && format == long_format)
1143 /* No need to free these since we're about to exit. */
1144 dired_dump_obstack ("//DIRED//", &dired_obstack);
1145 dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
1146 printf ("//DIRED-OPTIONS// --quoting-style=%s\n",
1147 quoting_style_args[get_quoting_style (filename_quoting_options)]);
1150 /* Restore default color before exiting */
1151 if (print_with_color)
1153 put_indicator (&color_indicator[C_LEFT]);
1154 put_indicator (&color_indicator[C_RIGHT]);
1157 if (LOOP_DETECT)
1159 assert (hash_get_n_entries (active_dir_set) == 0);
1160 hash_free (active_dir_set);
1163 exit (exit_status);
1166 /* Set all the option flags according to the switches specified.
1167 Return the index of the first non-option argument. */
1169 static int
1170 decode_switches (int argc, char **argv)
1172 int c;
1173 char *time_style_option = 0;
1175 /* Record whether there is an option specifying sort type. */
1176 int sort_type_specified = 0;
1178 qmark_funny_chars = 0;
1180 /* initialize all switches to default settings */
1182 switch (ls_mode)
1184 case LS_MULTI_COL:
1185 /* This is for the `dir' program. */
1186 format = many_per_line;
1187 set_quoting_style (NULL, escape_quoting_style);
1188 break;
1190 case LS_LONG_FORMAT:
1191 /* This is for the `vdir' program. */
1192 format = long_format;
1193 set_quoting_style (NULL, escape_quoting_style);
1194 break;
1196 case LS_LS:
1197 /* This is for the `ls' program. */
1198 if (isatty (STDOUT_FILENO))
1200 format = many_per_line;
1201 /* See description of qmark_funny_chars, above. */
1202 qmark_funny_chars = 1;
1204 else
1206 format = one_per_line;
1207 qmark_funny_chars = 0;
1209 break;
1211 default:
1212 abort ();
1215 time_type = time_mtime;
1216 sort_type = sort_name;
1217 sort_reverse = 0;
1218 numeric_ids = 0;
1219 print_block_size = 0;
1220 indicator_style = none;
1221 print_inode = 0;
1222 dereference = DEREF_UNDEFINED;
1223 recursive = 0;
1224 immediate_dirs = 0;
1225 all_files = 0;
1226 really_all_files = 0;
1227 ignore_patterns = 0;
1229 /* FIXME: put this in a function. */
1231 char const *q_style = getenv ("QUOTING_STYLE");
1232 if (q_style)
1234 int i = ARGCASEMATCH (q_style, quoting_style_args, quoting_style_vals);
1235 if (0 <= i)
1236 set_quoting_style (NULL, quoting_style_vals[i]);
1237 else
1238 error (0, 0,
1239 _("ignoring invalid value of environment variable QUOTING_STYLE: %s"),
1240 quotearg (q_style));
1244 human_block_size (getenv ("LS_BLOCK_SIZE"), 0, &output_block_size);
1246 line_length = 80;
1248 char const *p = getenv ("COLUMNS");
1249 if (p && *p)
1251 long int tmp_long;
1252 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
1253 && 0 < tmp_long && tmp_long <= INT_MAX)
1255 line_length = (int) tmp_long;
1257 else
1259 error (0, 0,
1260 _("ignoring invalid width in environment variable COLUMNS: %s"),
1261 quotearg (p));
1266 #ifdef TIOCGWINSZ
1268 struct winsize ws;
1270 if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
1271 line_length = ws.ws_col;
1273 #endif
1275 /* Using the TABSIZE environment variable is not POSIX-approved.
1276 Ignore it when POSIXLY_CORRECT is set. */
1278 char const *p;
1279 tabsize = 8;
1280 if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
1282 long int tmp_long;
1283 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
1284 && 0 <= tmp_long && tmp_long <= INT_MAX)
1286 tabsize = (int) tmp_long;
1288 else
1290 error (0, 0,
1291 _("ignoring invalid tab size in environment variable TABSIZE: %s"),
1292 quotearg (p));
1297 while ((c = getopt_long (argc, argv,
1298 "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
1299 long_options, NULL)) != -1)
1301 switch (c)
1303 case 0:
1304 break;
1306 case 'a':
1307 all_files = 1;
1308 really_all_files = 1;
1309 break;
1311 case 'b':
1312 set_quoting_style (NULL, escape_quoting_style);
1313 break;
1315 case 'c':
1316 time_type = time_ctime;
1317 break;
1319 case 'd':
1320 immediate_dirs = 1;
1321 break;
1323 case 'f':
1324 /* Same as enabling -a -U and disabling -l -s. */
1325 all_files = 1;
1326 really_all_files = 1;
1327 sort_type = sort_none;
1328 sort_type_specified = 1;
1329 /* disable -l */
1330 if (format == long_format)
1331 format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
1332 print_block_size = 0; /* disable -s */
1333 print_with_color = 0; /* disable --color */
1334 break;
1336 case 'g':
1337 format = long_format;
1338 print_owner = 0;
1339 break;
1341 case 'h':
1342 output_block_size = -1024;
1343 break;
1345 case 'i':
1346 print_inode = 1;
1347 break;
1349 case 'k':
1350 output_block_size = 1024;
1351 break;
1353 case 'l':
1354 format = long_format;
1355 break;
1357 case 'm':
1358 format = with_commas;
1359 break;
1361 case 'n':
1362 numeric_ids = 1;
1363 format = long_format;
1364 break;
1366 case 'o': /* Just like -l, but don't display group info. */
1367 format = long_format;
1368 print_group = 0;
1369 break;
1371 case 'p':
1372 indicator_style = file_type;
1373 break;
1375 case 'q':
1376 qmark_funny_chars = 1;
1377 break;
1379 case 'r':
1380 sort_reverse = 1;
1381 break;
1383 case 's':
1384 print_block_size = 1;
1385 break;
1387 case 't':
1388 sort_type = sort_time;
1389 sort_type_specified = 1;
1390 break;
1392 case 'u':
1393 time_type = time_atime;
1394 break;
1396 case 'v':
1397 sort_type = sort_version;
1398 sort_type_specified = 1;
1399 break;
1401 case 'w':
1403 long int tmp_long;
1404 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1405 || tmp_long <= 0 || tmp_long > INT_MAX)
1406 error (EXIT_FAILURE, 0, _("invalid line width: %s"),
1407 quotearg (optarg));
1408 line_length = (int) tmp_long;
1409 break;
1412 case 'x':
1413 format = horizontal;
1414 break;
1416 case 'A':
1417 really_all_files = 0;
1418 all_files = 1;
1419 break;
1421 case 'B':
1422 add_ignore_pattern ("*~");
1423 add_ignore_pattern (".*~");
1424 break;
1426 case 'C':
1427 format = many_per_line;
1428 break;
1430 case 'D':
1431 dired = 1;
1432 break;
1434 case 'F':
1435 indicator_style = classify;
1436 break;
1438 case 'G': /* inhibit display of group info */
1439 print_group = 0;
1440 break;
1442 case 'H':
1443 dereference = DEREF_COMMAND_LINE_ARGUMENTS;
1444 break;
1446 case 'I':
1447 add_ignore_pattern (optarg);
1448 break;
1450 case 'L':
1451 dereference = DEREF_ALWAYS;
1452 break;
1454 case 'N':
1455 set_quoting_style (NULL, literal_quoting_style);
1456 break;
1458 case 'Q':
1459 set_quoting_style (NULL, c_quoting_style);
1460 break;
1462 case 'R':
1463 recursive = 1;
1464 break;
1466 case 'S':
1467 sort_type = sort_size;
1468 sort_type_specified = 1;
1469 break;
1471 case 'T':
1473 long int tmp_long;
1474 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1475 || tmp_long < 0 || tmp_long > INT_MAX)
1476 error (EXIT_FAILURE, 0, _("invalid tab size: %s"),
1477 quotearg (optarg));
1478 tabsize = (int) tmp_long;
1479 break;
1482 case 'U':
1483 sort_type = sort_none;
1484 sort_type_specified = 1;
1485 break;
1487 case 'X':
1488 sort_type = sort_extension;
1489 sort_type_specified = 1;
1490 break;
1492 case '1':
1493 /* -1 has no effect after -l. */
1494 if (format != long_format)
1495 format = one_per_line;
1496 break;
1498 case AUTHOR_OPTION:
1499 print_author = true;
1500 break;
1502 case SORT_OPTION:
1503 sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
1504 sort_type_specified = 1;
1505 break;
1507 case TIME_OPTION:
1508 time_type = XARGMATCH ("--time", optarg, time_args, time_types);
1509 break;
1511 case FORMAT_OPTION:
1512 format = XARGMATCH ("--format", optarg, format_args, format_types);
1513 break;
1515 case FULL_TIME_OPTION:
1516 format = long_format;
1517 time_style_option = "full-iso";
1518 break;
1520 case COLOR_OPTION:
1522 int i;
1523 if (optarg)
1524 i = XARGMATCH ("--color", optarg, color_args, color_types);
1525 else
1526 /* Using --color with no argument is equivalent to using
1527 --color=always. */
1528 i = color_always;
1530 print_with_color = (i == color_always
1531 || (i == color_if_tty
1532 && isatty (STDOUT_FILENO)));
1534 if (print_with_color)
1536 /* Don't use TAB characters in output. Some terminal
1537 emulators can't handle the combination of tabs and
1538 color codes on the same line. */
1539 tabsize = 0;
1541 break;
1544 case INDICATOR_STYLE_OPTION:
1545 indicator_style = XARGMATCH ("--indicator-style", optarg,
1546 indicator_style_args,
1547 indicator_style_types);
1548 break;
1550 case QUOTING_STYLE_OPTION:
1551 set_quoting_style (NULL,
1552 XARGMATCH ("--quoting-style", optarg,
1553 quoting_style_args,
1554 quoting_style_vals));
1555 break;
1557 case TIME_STYLE_OPTION:
1558 time_style_option = optarg;
1559 break;
1561 case SHOW_CONTROL_CHARS_OPTION:
1562 qmark_funny_chars = 0;
1563 break;
1565 case BLOCK_SIZE_OPTION:
1566 human_block_size (optarg, 1, &output_block_size);
1567 break;
1569 case SI_OPTION:
1570 output_block_size = -1000;
1571 break;
1573 case_GETOPT_HELP_CHAR;
1575 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1577 default:
1578 usage (EXIT_FAILURE);
1582 filename_quoting_options = clone_quoting_options (NULL);
1583 if (get_quoting_style (filename_quoting_options) == escape_quoting_style)
1584 set_char_quoting (filename_quoting_options, ' ', 1);
1585 if (indicator_style != none)
1587 char const *p;
1588 for (p = "*=@|" + (int) indicator_style - 1; *p; p++)
1589 set_char_quoting (filename_quoting_options, *p, 1);
1592 dirname_quoting_options = clone_quoting_options (NULL);
1593 set_char_quoting (dirname_quoting_options, ':', 1);
1595 /* If -c or -u is specified and not -l (or any other option that implies -l),
1596 and no sort-type was specified, then sort by the ctime (-c) or atime (-u).
1597 The behavior of ls when using either -c or -u but with neither -l nor -t
1598 appears to be unspecified by POSIX. So, with GNU ls, `-u' alone means
1599 sort by atime (this is the one that's not specified by the POSIX spec),
1600 -lu means show atime and sort by name, -lut means show atime and sort
1601 by atime. */
1603 if ((time_type == time_ctime || time_type == time_atime)
1604 && !sort_type_specified && format != long_format)
1606 sort_type = sort_time;
1609 if (format == long_format)
1611 char *style = time_style_option;
1612 static char const posix_prefix[] = "posix-";
1614 if (! style)
1615 if (! (style = getenv ("TIME_STYLE")))
1616 style = "posix-long-iso";
1618 while (strncmp (style, posix_prefix, sizeof posix_prefix - 1) == 0)
1620 if (! hard_locale (LC_TIME))
1621 return optind;
1622 style += sizeof posix_prefix - 1;
1625 if (*style == '+')
1627 char *p0 = style + 1;
1628 char *p1 = strchr (p0, '\n');
1629 if (! p1)
1630 p1 = p0;
1631 else
1633 if (strchr (p1 + 1, '\n'))
1634 error (EXIT_FAILURE, 0, _("invalid time style format %s"),
1635 quote (p0));
1636 *p1++ = '\0';
1638 long_time_format[0] = p0;
1639 long_time_format[1] = p1;
1641 else
1642 switch (XARGMATCH ("time style", style,
1643 time_style_args,
1644 time_style_types))
1646 case full_iso_time_style:
1647 long_time_format[0] = long_time_format[1] =
1648 "%Y-%m-%d %H:%M:%S.%N %z";
1649 break;
1651 case long_iso_time_style:
1652 long_time_format[0] = long_time_format[1] = "%Y-%m-%d %H:%M";
1653 break;
1655 case iso_time_style:
1656 long_time_format[0] = "%Y-%m-%d ";
1657 long_time_format[1] = "%m-%d %H:%M";
1658 break;
1660 case locale_time_style:
1661 if (hard_locale (LC_TIME))
1663 unsigned int i;
1664 for (i = 0; i < 2; i++)
1665 long_time_format[i] =
1666 dcgettext (NULL, long_time_format[i], LC_TIME);
1671 return optind;
1674 /* Parse a string as part of the LS_COLORS variable; this may involve
1675 decoding all kinds of escape characters. If equals_end is set an
1676 unescaped equal sign ends the string, otherwise only a : or \0
1677 does. Returns the number of characters output, or -1 on failure.
1679 The resulting string is *not* null-terminated, but may contain
1680 embedded nulls.
1682 Note that both dest and src are char **; on return they point to
1683 the first free byte after the array and the character that ended
1684 the input string, respectively. */
1686 static int
1687 get_funky_string (char **dest, const char **src, int equals_end)
1689 int num; /* For numerical codes */
1690 int count; /* Something to count with */
1691 enum {
1692 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
1693 } state;
1694 const char *p;
1695 char *q;
1697 p = *src; /* We don't want to double-indirect */
1698 q = *dest; /* the whole darn time. */
1700 count = 0; /* No characters counted in yet. */
1701 num = 0;
1703 state = ST_GND; /* Start in ground state. */
1704 while (state < ST_END)
1706 switch (state)
1708 case ST_GND: /* Ground state (no escapes) */
1709 switch (*p)
1711 case ':':
1712 case '\0':
1713 state = ST_END; /* End of string */
1714 break;
1715 case '\\':
1716 state = ST_BACKSLASH; /* Backslash scape sequence */
1717 ++p;
1718 break;
1719 case '^':
1720 state = ST_CARET; /* Caret escape */
1721 ++p;
1722 break;
1723 case '=':
1724 if (equals_end)
1726 state = ST_END; /* End */
1727 break;
1729 /* else fall through */
1730 default:
1731 *(q++) = *(p++);
1732 ++count;
1733 break;
1735 break;
1737 case ST_BACKSLASH: /* Backslash escaped character */
1738 switch (*p)
1740 case '0':
1741 case '1':
1742 case '2':
1743 case '3':
1744 case '4':
1745 case '5':
1746 case '6':
1747 case '7':
1748 state = ST_OCTAL; /* Octal sequence */
1749 num = *p - '0';
1750 break;
1751 case 'x':
1752 case 'X':
1753 state = ST_HEX; /* Hex sequence */
1754 num = 0;
1755 break;
1756 case 'a': /* Bell */
1757 num = 7; /* Not all C compilers know what \a means */
1758 break;
1759 case 'b': /* Backspace */
1760 num = '\b';
1761 break;
1762 case 'e': /* Escape */
1763 num = 27;
1764 break;
1765 case 'f': /* Form feed */
1766 num = '\f';
1767 break;
1768 case 'n': /* Newline */
1769 num = '\n';
1770 break;
1771 case 'r': /* Carriage return */
1772 num = '\r';
1773 break;
1774 case 't': /* Tab */
1775 num = '\t';
1776 break;
1777 case 'v': /* Vtab */
1778 num = '\v';
1779 break;
1780 case '?': /* Delete */
1781 num = 127;
1782 break;
1783 case '_': /* Space */
1784 num = ' ';
1785 break;
1786 case '\0': /* End of string */
1787 state = ST_ERROR; /* Error! */
1788 break;
1789 default: /* Escaped character like \ ^ : = */
1790 num = *p;
1791 break;
1793 if (state == ST_BACKSLASH)
1795 *(q++) = num;
1796 ++count;
1797 state = ST_GND;
1799 ++p;
1800 break;
1802 case ST_OCTAL: /* Octal sequence */
1803 if (*p < '0' || *p > '7')
1805 *(q++) = num;
1806 ++count;
1807 state = ST_GND;
1809 else
1810 num = (num << 3) + (*(p++) - '0');
1811 break;
1813 case ST_HEX: /* Hex sequence */
1814 switch (*p)
1816 case '0':
1817 case '1':
1818 case '2':
1819 case '3':
1820 case '4':
1821 case '5':
1822 case '6':
1823 case '7':
1824 case '8':
1825 case '9':
1826 num = (num << 4) + (*(p++) - '0');
1827 break;
1828 case 'a':
1829 case 'b':
1830 case 'c':
1831 case 'd':
1832 case 'e':
1833 case 'f':
1834 num = (num << 4) + (*(p++) - 'a') + 10;
1835 break;
1836 case 'A':
1837 case 'B':
1838 case 'C':
1839 case 'D':
1840 case 'E':
1841 case 'F':
1842 num = (num << 4) + (*(p++) - 'A') + 10;
1843 break;
1844 default:
1845 *(q++) = num;
1846 ++count;
1847 state = ST_GND;
1848 break;
1850 break;
1852 case ST_CARET: /* Caret escape */
1853 state = ST_GND; /* Should be the next state... */
1854 if (*p >= '@' && *p <= '~')
1856 *(q++) = *(p++) & 037;
1857 ++count;
1859 else if (*p == '?')
1861 *(q++) = 127;
1862 ++count;
1864 else
1865 state = ST_ERROR;
1866 break;
1868 default:
1869 abort ();
1873 *dest = q;
1874 *src = p;
1876 return state == ST_ERROR ? -1 : count;
1879 static void
1880 parse_ls_color (void)
1882 const char *p; /* Pointer to character being parsed */
1883 char *buf; /* color_buf buffer pointer */
1884 int state; /* State of parser */
1885 int ind_no; /* Indicator number */
1886 char label[3]; /* Indicator label */
1887 struct color_ext_type *ext; /* Extension we are working on */
1889 if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
1890 return;
1892 ext = NULL;
1893 strcpy (label, "??");
1895 /* This is an overly conservative estimate, but any possible
1896 LS_COLORS string will *not* generate a color_buf longer than
1897 itself, so it is a safe way of allocating a buffer in
1898 advance. */
1899 buf = color_buf = xstrdup (p);
1901 state = 1;
1902 while (state > 0)
1904 switch (state)
1906 case 1: /* First label character */
1907 switch (*p)
1909 case ':':
1910 ++p;
1911 break;
1913 case '*':
1914 /* Allocate new extension block and add to head of
1915 linked list (this way a later definition will
1916 override an earlier one, which can be useful for
1917 having terminal-specific defs override global). */
1919 ext = XMALLOC (struct color_ext_type, 1);
1920 ext->next = color_ext_list;
1921 color_ext_list = ext;
1923 ++p;
1924 ext->ext.string = buf;
1926 state = (ext->ext.len =
1927 get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
1928 break;
1930 case '\0':
1931 state = 0; /* Done! */
1932 break;
1934 default: /* Assume it is file type label */
1935 label[0] = *(p++);
1936 state = 2;
1937 break;
1939 break;
1941 case 2: /* Second label character */
1942 if (*p)
1944 label[1] = *(p++);
1945 state = 3;
1947 else
1948 state = -1; /* Error */
1949 break;
1951 case 3: /* Equal sign after indicator label */
1952 state = -1; /* Assume failure... */
1953 if (*(p++) == '=')/* It *should* be... */
1955 for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
1957 if (STREQ (label, indicator_name[ind_no]))
1959 color_indicator[ind_no].string = buf;
1960 state = ((color_indicator[ind_no].len =
1961 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
1962 break;
1965 if (state == -1)
1966 error (0, 0, _("unrecognized prefix: %s"), quotearg (label));
1968 break;
1970 case 4: /* Equal sign after *.ext */
1971 if (*(p++) == '=')
1973 ext->seq.string = buf;
1974 state = (ext->seq.len =
1975 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
1977 else
1978 state = -1;
1979 break;
1983 if (state < 0)
1985 struct color_ext_type *e;
1986 struct color_ext_type *e2;
1988 error (0, 0,
1989 _("unparsable value for LS_COLORS environment variable"));
1990 free (color_buf);
1991 for (e = color_ext_list; e != NULL; /* empty */)
1993 e2 = e;
1994 e = e->next;
1995 free (e2);
1997 print_with_color = 0;
2000 if (color_indicator[C_LINK].len == 6
2001 && !strncmp (color_indicator[C_LINK].string, "target", 6))
2002 color_symlink_as_referent = 1;
2005 /* Request that the directory named NAME have its contents listed later.
2006 If REALNAME is nonzero, it will be used instead of NAME when the
2007 directory name is printed. This allows symbolic links to directories
2008 to be treated as regular directories but still be listed under their
2009 real names. NAME == NULL is used to insert a marker entry for the
2010 directory named in REALNAME.
2011 If F is non-NULL, we use its dev/ino information to save
2012 a call to stat -- when doing a recursive (-R) traversal. */
2014 static void
2015 queue_directory (const char *name, const char *realname)
2017 struct pending *new;
2019 new = XMALLOC (struct pending, 1);
2020 new->realname = realname ? xstrdup (realname) : NULL;
2021 new->name = name ? xstrdup (name) : NULL;
2022 new->next = pending_dirs;
2023 pending_dirs = new;
2026 /* Read directory `name', and list the files in it.
2027 If `realname' is nonzero, print its name instead of `name';
2028 this is used for symbolic links to directories. */
2030 static void
2031 print_dir (const char *name, const char *realname)
2033 register DIR *reading;
2034 register struct dirent *next;
2035 register uintmax_t total_blocks = 0;
2036 static int first = 1;
2038 errno = 0;
2039 reading = opendir (name);
2040 if (!reading)
2042 error (0, errno, "%s", quotearg_colon (name));
2043 exit_status = 1;
2044 return;
2047 if (LOOP_DETECT)
2049 struct stat dir_stat;
2050 int fd = dirfd (reading);
2052 /* If dirfd failed, endure the overhead of using stat. */
2053 if ((0 <= fd
2054 ? fstat (fd, &dir_stat)
2055 : stat (name, &dir_stat)) < 0)
2057 error (0, errno, _("cannot determine device and inode of %s"),
2058 quotearg_colon (name));
2059 exit_status = 1;
2060 return;
2063 /* If we've already visited this dev/inode pair, warn that
2064 we've found a loop, and do not process this directory. */
2065 if (visit_dir (dir_stat.st_dev, dir_stat.st_ino))
2067 error (0, 0, _("not listing already-listed directory: %s"),
2068 quotearg_colon (name));
2069 return;
2072 DEV_INO_PUSH (dir_stat.st_dev, dir_stat.st_ino);
2075 /* Read the directory entries, and insert the subfiles into the `files'
2076 table. */
2078 clear_files ();
2080 while ((next = readdir (reading)) != NULL)
2081 if (file_interesting (next))
2083 enum filetype type = unknown;
2085 #if HAVE_STRUCT_DIRENT_D_TYPE
2086 if (next->d_type == DT_DIR || next->d_type == DT_CHR
2087 || next->d_type == DT_BLK || next->d_type == DT_SOCK
2088 || next->d_type == DT_FIFO)
2089 type = next->d_type;
2090 #endif
2091 total_blocks += gobble_file (next->d_name, type, 0, name);
2094 if (CLOSEDIR (reading))
2096 error (0, errno, "%s", quotearg_colon (name));
2097 exit_status = 1;
2098 /* Don't return; print whatever we got. */
2101 /* Sort the directory contents. */
2102 sort_files ();
2104 /* If any member files are subdirectories, perhaps they should have their
2105 contents listed rather than being mentioned here as files. */
2107 if (recursive)
2108 extract_dirs_from_files (name, 1);
2110 if (recursive || print_dir_name)
2112 if (!first)
2113 DIRED_PUTCHAR ('\n');
2114 first = 0;
2115 DIRED_INDENT ();
2116 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
2117 dired_pos += quote_name (stdout, realname ? realname : name,
2118 dirname_quoting_options);
2119 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
2120 DIRED_FPUTS_LITERAL (":\n", stdout);
2123 if (format == long_format || print_block_size)
2125 const char *p;
2126 char buf[LONGEST_HUMAN_READABLE + 1];
2128 DIRED_INDENT ();
2129 p = _("total");
2130 DIRED_FPUTS (p, stdout, strlen (p));
2131 DIRED_PUTCHAR (' ');
2132 p = human_readable_inexact (total_blocks, buf, ST_NBLOCKSIZE,
2133 output_block_size, human_ceiling);
2134 DIRED_FPUTS (p, stdout, strlen (p));
2135 DIRED_PUTCHAR ('\n');
2138 if (files_index)
2139 print_current_files ();
2142 /* Add `pattern' to the list of patterns for which files that match are
2143 not listed. */
2145 static void
2146 add_ignore_pattern (const char *pattern)
2148 register struct ignore_pattern *ignore;
2150 ignore = XMALLOC (struct ignore_pattern, 1);
2151 ignore->pattern = pattern;
2152 /* Add it to the head of the linked list. */
2153 ignore->next = ignore_patterns;
2154 ignore_patterns = ignore;
2157 /* Return nonzero if the file in `next' should be listed. */
2159 static int
2160 file_interesting (const struct dirent *next)
2162 register struct ignore_pattern *ignore;
2164 for (ignore = ignore_patterns; ignore; ignore = ignore->next)
2165 if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
2166 return 0;
2168 if (really_all_files
2169 || next->d_name[0] != '.'
2170 || (all_files
2171 && next->d_name[1] != '\0'
2172 && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
2173 return 1;
2175 return 0;
2178 /* Enter and remove entries in the table `files'. */
2180 /* Empty the table of files. */
2182 static void
2183 clear_files (void)
2185 register int i;
2187 for (i = 0; i < files_index; i++)
2189 free (files[i].name);
2190 if (files[i].linkname)
2191 free (files[i].linkname);
2194 files_index = 0;
2195 block_size_size = 4;
2198 /* Add a file to the current table of files.
2199 Verify that the file exists, and print an error message if it does not.
2200 Return the number of blocks that the file occupies. */
2202 static uintmax_t
2203 gobble_file (const char *name, enum filetype type, int explicit_arg,
2204 const char *dirname)
2206 register uintmax_t blocks;
2207 register char *path;
2209 if (files_index == nfiles)
2211 nfiles *= 2;
2212 files = XREALLOC (files, struct fileinfo, nfiles);
2215 files[files_index].linkname = 0;
2216 files[files_index].linkmode = 0;
2217 files[files_index].linkok = 0;
2219 /* FIXME: this use of ls: `mkdir a; touch a/{b,c,d}; ls -R a'
2220 shouldn't require that ls stat b, c, and d -- at least
2221 not on systems with usable d_type. The problem is that
2222 format_needs_stat is set, because of the -R. */
2223 if (explicit_arg || format_needs_stat
2224 || (format_needs_type && type == unknown))
2226 /* `path' is the absolute pathname of this file. */
2227 int val;
2229 if (name[0] == '/' || dirname[0] == 0)
2230 path = (char *) name;
2231 else
2233 path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
2234 attach (path, dirname, name);
2237 val = (DEREF_ALWAYS <= dereference + explicit_arg
2238 ? stat (path, &files[files_index].stat)
2239 : lstat (path, &files[files_index].stat));
2241 if (val < 0)
2243 error (0, errno, "%s", quotearg_colon (path));
2244 exit_status = 1;
2245 return 0;
2248 #if HAVE_ACL
2249 if (format == long_format)
2251 int n = file_has_acl (path, &files[files_index].stat);
2252 files[files_index].have_acl = (0 < n);
2253 if (n < 0)
2254 error (0, errno, "%s", quotearg_colon (path));
2256 #endif
2258 if (S_ISLNK (files[files_index].stat.st_mode)
2259 && (format == long_format || check_symlink_color))
2261 char *linkpath;
2262 struct stat linkstats;
2264 get_link_name (path, &files[files_index]);
2265 linkpath = make_link_path (path, files[files_index].linkname);
2267 /* Avoid following symbolic links when possible, ie, when
2268 they won't be traced and when no indicator is needed. */
2269 if (linkpath
2270 && (indicator_style != none || check_symlink_color)
2271 && stat (linkpath, &linkstats) == 0)
2273 files[files_index].linkok = 1;
2275 /* Symbolic links to directories that are mentioned on the
2276 command line are automatically traced if not being
2277 listed as files. */
2278 if (explicit_arg && format != long_format
2279 && S_ISDIR (linkstats.st_mode))
2281 /* Substitute the linked-to directory's name, but
2282 save the real name in `linkname' for printing. */
2283 if (!immediate_dirs)
2285 const char *tempname = name;
2286 name = linkpath;
2287 linkpath = files[files_index].linkname;
2288 files[files_index].linkname = (char *) tempname;
2290 files[files_index].stat = linkstats;
2292 else
2294 /* Get the linked-to file's mode for the filetype indicator
2295 in long listings. */
2296 files[files_index].linkmode = linkstats.st_mode;
2297 files[files_index].linkok = 1;
2300 if (linkpath)
2301 free (linkpath);
2304 if (S_ISLNK (files[files_index].stat.st_mode))
2305 files[files_index].filetype = symbolic_link;
2306 else if (S_ISDIR (files[files_index].stat.st_mode))
2308 if (explicit_arg && !immediate_dirs)
2309 files[files_index].filetype = arg_directory;
2310 else
2311 files[files_index].filetype = directory;
2313 else
2314 files[files_index].filetype = normal;
2316 blocks = ST_NBLOCKS (files[files_index].stat);
2318 char buf[LONGEST_HUMAN_READABLE + 1];
2319 int len = strlen (human_readable_inexact (blocks, buf, ST_NBLOCKSIZE,
2320 output_block_size,
2321 human_ceiling));
2322 if (block_size_size < len)
2323 block_size_size = len < 7 ? len : 7;
2326 else
2328 files[files_index].filetype = type;
2329 #if HAVE_STRUCT_DIRENT_D_TYPE
2330 files[files_index].stat.st_mode = DTTOIF (type);
2331 #endif
2332 blocks = 0;
2335 files[files_index].name = xstrdup (name);
2336 files_index++;
2338 return blocks;
2341 #if HAVE_SYMLINKS
2343 /* Put the name of the file that `filename' is a symbolic link to
2344 into the `linkname' field of `f'. */
2346 static void
2347 get_link_name (const char *filename, struct fileinfo *f)
2349 f->linkname = xreadlink (filename);
2350 if (f->linkname == NULL)
2352 error (0, errno, _("cannot read symbolic link %s"),
2353 quotearg_colon (filename));
2354 exit_status = 1;
2358 /* If `linkname' is a relative path and `path' contains one or more
2359 leading directories, return `linkname' with those directories
2360 prepended; otherwise, return a copy of `linkname'.
2361 If `linkname' is zero, return zero. */
2363 static char *
2364 make_link_path (const char *path, const char *linkname)
2366 char *linkbuf;
2367 size_t bufsiz;
2369 if (linkname == 0)
2370 return 0;
2372 if (*linkname == '/')
2373 return xstrdup (linkname);
2375 /* The link is to a relative path. Prepend any leading path
2376 in `path' to the link name. */
2377 linkbuf = strrchr (path, '/');
2378 if (linkbuf == 0)
2379 return xstrdup (linkname);
2381 bufsiz = linkbuf - path + 1;
2382 linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
2383 strncpy (linkbuf, path, bufsiz);
2384 strcpy (linkbuf + bufsiz, linkname);
2385 return linkbuf;
2387 #endif
2389 /* Return nonzero if base_name (NAME) ends in `.' or `..'
2390 This is so we don't try to recurse on `././././. ...' */
2392 static int
2393 basename_is_dot_or_dotdot (const char *name)
2395 char const *base = base_name (name);
2396 return DOT_OR_DOTDOT (base);
2399 /* Remove any entries from `files' that are for directories,
2400 and queue them to be listed as directories instead.
2401 `dirname' is the prefix to prepend to each dirname
2402 to make it correct relative to ls's working dir.
2403 If IGNORE_DOT_AND_DOT_DOT is nonzero don't treat `.' and `..' as dirs.
2404 This is desirable when processing directories recursively. */
2406 static void
2407 extract_dirs_from_files (const char *dirname, int ignore_dot_and_dot_dot)
2409 register int i, j;
2411 if (*dirname && LOOP_DETECT)
2413 /* Insert a marker entry first. When we dequeue this marker entry,
2414 we'll know that DIRNAME has been processed and may be removed
2415 from the set of active directories. */
2416 queue_directory (NULL, dirname);
2419 /* Queue the directories last one first, because queueing reverses the
2420 order. */
2421 for (i = files_index - 1; i >= 0; i--)
2422 if ((files[i].filetype == directory || files[i].filetype == arg_directory)
2423 && (!ignore_dot_and_dot_dot
2424 || !basename_is_dot_or_dotdot (files[i].name)))
2426 if (files[i].name[0] == '/' || dirname[0] == 0)
2428 queue_directory (files[i].name, files[i].linkname);
2430 else
2432 char *path = path_concat (dirname, files[i].name, NULL);
2433 queue_directory (path, files[i].linkname);
2434 free (path);
2436 if (files[i].filetype == arg_directory)
2437 free (files[i].name);
2440 /* Now delete the directories from the table, compacting all the remaining
2441 entries. */
2443 for (i = 0, j = 0; i < files_index; i++)
2444 if (files[i].filetype != arg_directory)
2445 files[j++] = files[i];
2446 files_index = j;
2449 /* Use strcoll to compare strings in this locale. If an error occurs,
2450 report an error and longjmp to failed_strcoll. */
2452 static jmp_buf failed_strcoll;
2454 static int
2455 xstrcoll (char const *a, char const *b)
2457 int diff;
2458 errno = 0;
2459 diff = strcoll (a, b);
2460 if (errno)
2462 error (0, errno, _("cannot compare file names %s and %s"),
2463 quote_n (0, a), quote_n (1, b));
2464 exit_status = 1;
2465 longjmp (failed_strcoll, 1);
2467 return diff;
2470 /* Comparison routines for sorting the files. */
2472 typedef void const *V;
2474 static inline int
2475 cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,
2476 int (*cmp) PARAMS ((char const *, char const *)))
2478 int diff = CTIME_CMP (b->stat, a->stat);
2479 return diff ? diff : cmp (a->name, b->name);
2481 static int compare_ctime (V a, V b) { return cmp_ctime (a, b, xstrcoll); }
2482 static int compstr_ctime (V a, V b) { return cmp_ctime (a, b, strcmp); }
2483 static int rev_cmp_ctime (V a, V b) { return compare_ctime (b, a); }
2484 static int rev_str_ctime (V a, V b) { return compstr_ctime (b, a); }
2486 static inline int
2487 cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,
2488 int (*cmp) PARAMS((char const *, char const *)))
2490 int diff = MTIME_CMP (b->stat, a->stat);
2491 return diff ? diff : cmp (a->name, b->name);
2493 static int compare_mtime (V a, V b) { return cmp_mtime (a, b, xstrcoll); }
2494 static int compstr_mtime (V a, V b) { return cmp_mtime (a, b, strcmp); }
2495 static int rev_cmp_mtime (V a, V b) { return compare_mtime (b, a); }
2496 static int rev_str_mtime (V a, V b) { return compstr_mtime (b, a); }
2498 static inline int
2499 cmp_atime (struct fileinfo const *a, struct fileinfo const *b,
2500 int (*cmp) PARAMS ((char const *, char const *)))
2502 int diff = ATIME_CMP (b->stat, a->stat);
2503 return diff ? diff : cmp (a->name, b->name);
2505 static int compare_atime (V a, V b) { return cmp_atime (a, b, xstrcoll); }
2506 static int compstr_atime (V a, V b) { return cmp_atime (a, b, strcmp); }
2507 static int rev_cmp_atime (V a, V b) { return compare_atime (b, a); }
2508 static int rev_str_atime (V a, V b) { return compstr_atime (b, a); }
2510 static inline int
2511 cmp_size (struct fileinfo const *a, struct fileinfo const *b,
2512 int (*cmp) PARAMS ((char const *, char const *)))
2514 int diff = longdiff (b->stat.st_size, a->stat.st_size);
2515 return diff ? diff : cmp (a->name, b->name);
2517 static int compare_size (V a, V b) { return cmp_size (a, b, xstrcoll); }
2518 static int compstr_size (V a, V b) { return cmp_size (a, b, strcmp); }
2519 static int rev_cmp_size (V a, V b) { return compare_size (b, a); }
2520 static int rev_str_size (V a, V b) { return compstr_size (b, a); }
2522 static inline int
2523 cmp_version (struct fileinfo const *a, struct fileinfo const *b)
2525 return strverscmp (a->name, b->name);
2527 static int compare_version (V a, V b) { return cmp_version (a, b); }
2528 static int rev_cmp_version (V a, V b) { return compare_version (b, a); }
2530 static inline int
2531 cmp_name (struct fileinfo const *a, struct fileinfo const *b,
2532 int (*cmp) PARAMS ((char const *, char const *)))
2534 return cmp (a->name, b->name);
2536 static int compare_name (V a, V b) { return cmp_name (a, b, xstrcoll); }
2537 static int compstr_name (V a, V b) { return cmp_name (a, b, strcmp); }
2538 static int rev_cmp_name (V a, V b) { return compare_name (b, a); }
2539 static int rev_str_name (V a, V b) { return compstr_name (b, a); }
2541 /* Compare file extensions. Files with no extension are `smallest'.
2542 If extensions are the same, compare by filenames instead. */
2544 static inline int
2545 cmp_extension (struct fileinfo const *a, struct fileinfo const *b,
2546 int (*cmp) PARAMS ((char const *, char const *)))
2548 char const *base1 = strrchr (a->name, '.');
2549 char const *base2 = strrchr (b->name, '.');
2550 int diff = cmp (base1 ? base1 : "", base2 ? base2 : "");
2551 return diff ? diff : cmp (a->name, b->name);
2553 static int compare_extension (V a, V b) { return cmp_extension (a, b, xstrcoll); }
2554 static int compstr_extension (V a, V b) { return cmp_extension (a, b, strcmp); }
2555 static int rev_cmp_extension (V a, V b) { return compare_extension (b, a); }
2556 static int rev_str_extension (V a, V b) { return compstr_extension (b, a); }
2558 /* Sort the files now in the table. */
2560 static void
2561 sort_files (void)
2563 int (*func) PARAMS ((V, V));
2565 switch (sort_type)
2567 case sort_none:
2568 return;
2569 case sort_time:
2570 switch (time_type)
2572 case time_ctime:
2573 func = sort_reverse ? rev_cmp_ctime : compare_ctime;
2574 break;
2575 case time_mtime:
2576 func = sort_reverse ? rev_cmp_mtime : compare_mtime;
2577 break;
2578 case time_atime:
2579 func = sort_reverse ? rev_cmp_atime : compare_atime;
2580 break;
2581 default:
2582 abort ();
2584 break;
2585 case sort_name:
2586 func = sort_reverse ? rev_cmp_name : compare_name;
2587 break;
2588 case sort_extension:
2589 func = sort_reverse ? rev_cmp_extension : compare_extension;
2590 break;
2591 case sort_size:
2592 func = sort_reverse ? rev_cmp_size : compare_size;
2593 break;
2594 case sort_version:
2595 func = sort_reverse ? rev_cmp_version : compare_version;
2596 break;
2597 default:
2598 abort ();
2601 /* Try strcoll. If it fails, fall back on strcmp. We can't safely
2602 ignore strcoll failures, as a failing strcoll might be a
2603 comparison function that is not a total order, and if we ignored
2604 the failure this might cause qsort to dump core. */
2606 if (setjmp (failed_strcoll))
2608 switch (sort_type)
2610 case sort_time:
2611 switch (time_type)
2613 case time_ctime:
2614 func = sort_reverse ? rev_str_ctime : compstr_ctime;
2615 break;
2616 case time_mtime:
2617 func = sort_reverse ? rev_str_mtime : compstr_mtime;
2618 break;
2619 case time_atime:
2620 func = sort_reverse ? rev_str_atime : compstr_atime;
2621 break;
2622 default:
2623 abort ();
2625 break;
2626 case sort_name:
2627 func = sort_reverse ? rev_str_name : compstr_name;
2628 break;
2629 case sort_extension:
2630 func = sort_reverse ? rev_str_extension : compstr_extension;
2631 break;
2632 case sort_size:
2633 func = sort_reverse ? rev_str_size : compstr_size;
2634 break;
2635 default:
2636 abort ();
2640 qsort (files, files_index, sizeof (struct fileinfo), func);
2643 /* List all the files now in the table. */
2645 static void
2646 print_current_files (void)
2648 register int i;
2650 switch (format)
2652 case one_per_line:
2653 for (i = 0; i < files_index; i++)
2655 print_file_name_and_frills (files + i);
2656 putchar ('\n');
2658 break;
2660 case many_per_line:
2661 init_column_info ();
2662 print_many_per_line ();
2663 break;
2665 case horizontal:
2666 init_column_info ();
2667 print_horizontal ();
2668 break;
2670 case with_commas:
2671 print_with_commas ();
2672 break;
2674 case long_format:
2675 for (i = 0; i < files_index; i++)
2677 print_long_format (files + i);
2678 DIRED_PUTCHAR ('\n');
2680 break;
2684 /* Return the expected number of columns in a long-format time stamp,
2685 or zero if it cannot be calculated. */
2687 static int
2688 long_time_expected_width (void)
2690 static int width = -1;
2692 if (width < 0)
2694 time_t epoch = 0;
2695 struct tm const *tm = localtime (&epoch);
2696 char const *fmt = long_time_format[0];
2697 char initbuf[100];
2698 char *buf = initbuf;
2699 size_t bufsize = sizeof initbuf;
2700 size_t len;
2702 for (;;)
2704 *buf = '\1';
2705 len = nstrftime (buf, bufsize, fmt, tm, 0, 0);
2706 if (len || ! *buf)
2707 break;
2708 buf = alloca (bufsize *= 2);
2711 width = mbsnwidth (buf, len, 0);
2712 if (width < 0)
2713 width = 0;
2716 return width;
2719 /* Get the current time. */
2721 static void
2722 get_current_time (void)
2724 #if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
2726 struct timespec timespec;
2727 if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
2729 current_time = timespec.tv_sec;
2730 current_time_ns = timespec.tv_nsec;
2731 return;
2734 #endif
2736 /* The clock does not have nanosecond resolution, so get the maximum
2737 possible value for the current time that is consistent with the
2738 reported clock. That way, files are not considered to be in the
2739 future merely because their time stamps have higher resolution
2740 than the clock resolution. */
2742 #if HAVE_GETTIMEOFDAY
2744 struct timeval timeval;
2745 if (gettimeofday (&timeval, NULL) == 0)
2747 current_time = timeval.tv_sec;
2748 current_time_ns = timeval.tv_usec * 1000 + 999;
2749 return;
2752 #endif
2754 current_time = time (NULL);
2755 current_time_ns = 999999999;
2758 /* Format into BUFFER the name or id of the user with id U. Return
2759 the length of the formatted buffer, not counting the terminating
2760 null. */
2762 static size_t
2763 format_user (char *buffer, uid_t u)
2765 char const *name = (numeric_ids ? NULL : getuser (u));
2766 if (name)
2767 sprintf (buffer, "%-8s ", name);
2768 else
2769 sprintf (buffer, "%-8lu ", (unsigned long) u);
2770 return strlen (buffer);
2773 /* Print information about F in long format. */
2775 static void
2776 print_long_format (const struct fileinfo *f)
2778 char modebuf[12];
2779 char init_bigbuf
2780 [LONGEST_HUMAN_READABLE + 1 /* inode */
2781 + LONGEST_HUMAN_READABLE + 1 /* size in blocks */
2782 + sizeof (modebuf) - 1 + 1 /* mode string */
2783 + LONGEST_HUMAN_READABLE + 1 /* st_nlink */
2784 + ID_LENGTH_MAX + 1 /* owner name */
2785 + ID_LENGTH_MAX + 1 /* group name */
2786 + ID_LENGTH_MAX + 1 /* author name */
2787 + LONGEST_HUMAN_READABLE + 1 /* major device number */
2788 + LONGEST_HUMAN_READABLE + 1 /* minor device number */
2789 + 35 + 1 /* usual length of time/date -- may be longer; see below */
2791 char *buf = init_bigbuf;
2792 size_t bufsize = sizeof (init_bigbuf);
2793 size_t s;
2794 char *p;
2795 time_t when;
2796 int when_ns IF_LINT (= 0);
2797 struct tm *when_local;
2799 /* Compute mode string. On most systems, it's based on st_mode.
2800 On systems with migration (via the stat.st_dm_mode field), use
2801 the file's migrated status. */
2802 mode_string (ST_DM_MODE (f->stat), modebuf);
2804 modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' ');
2805 modebuf[11] = '\0';
2807 switch (time_type)
2809 case time_ctime:
2810 when = f->stat.st_ctime;
2811 when_ns = TIMESPEC_NS (f->stat.st_ctim);
2812 break;
2813 case time_mtime:
2814 when = f->stat.st_mtime;
2815 when_ns = TIMESPEC_NS (f->stat.st_mtim);
2816 break;
2817 case time_atime:
2818 when = f->stat.st_atime;
2819 when_ns = TIMESPEC_NS (f->stat.st_atim);
2820 break;
2823 p = buf;
2825 if (print_inode)
2827 char hbuf[LONGEST_HUMAN_READABLE + 1];
2828 sprintf (p, "%*s ", INODE_DIGITS,
2829 human_readable ((uintmax_t) f->stat.st_ino, hbuf, 1, 1));
2830 p += strlen (p);
2833 if (print_block_size)
2835 char hbuf[LONGEST_HUMAN_READABLE + 1];
2836 sprintf (p, "%*s ", block_size_size,
2837 human_readable_inexact ((uintmax_t) ST_NBLOCKS (f->stat), hbuf,
2838 ST_NBLOCKSIZE, output_block_size,
2839 human_ceiling));
2840 p += strlen (p);
2843 /* The last byte of the mode string is the POSIX
2844 "optional alternate access method flag". */
2845 sprintf (p, "%s %3lu ", modebuf, (unsigned long) f->stat.st_nlink);
2846 p += strlen (p);
2848 if (print_owner)
2849 p += format_user (p, f->stat.st_uid);
2851 if (print_group)
2853 char const *group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid));
2854 if (group_name)
2855 sprintf (p, "%-8s ", group_name);
2856 else
2857 sprintf (p, "%-8lu ", (unsigned long) f->stat.st_gid);
2858 p += strlen (p);
2861 if (print_author)
2862 p += format_user (p, f->stat.st_author);
2864 if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
2865 sprintf (p, "%3lu, %3lu ",
2866 (unsigned long) major (f->stat.st_rdev),
2867 (unsigned long) minor (f->stat.st_rdev));
2868 else
2870 char hbuf[LONGEST_HUMAN_READABLE + 1];
2871 uintmax_t size = f->stat.st_size;
2873 /* POSIX requires that the size be printed without a sign, even
2874 when negative. Assume the typical case where negative sizes
2875 are actually positive values that have wrapped around. */
2876 size += (f->stat.st_size < 0) * ((uintmax_t) OFF_T_MAX - OFF_T_MIN + 1);
2878 sprintf (p, "%8s ",
2879 human_readable (size, hbuf, 1,
2880 output_block_size < 0 ? output_block_size : 1));
2883 p += strlen (p);
2885 if ((when_local = localtime (&when)))
2887 time_t six_months_ago;
2888 int recent;
2889 char const *fmt;
2891 /* If the file appears to be in the future, update the current
2892 time, in case the file happens to have been modified since
2893 the last time we checked the clock. */
2894 if (current_time < when
2895 || (current_time == when && current_time_ns < when_ns))
2897 /* Note that get_current_time calls gettimeofday which, on some non-
2898 compliant systems, clobbers the buffer used for localtime's result.
2899 But it's ok here, because we use a gettimeofday wrapper that
2900 saves and restores the buffer around the gettimeofday call. */
2901 get_current_time ();
2904 /* Consider a time to be recent if it is within the past six
2905 months. A Gregorian year has 365.2425 * 24 * 60 * 60 ==
2906 31556952 seconds on the average. Write this value as an
2907 integer constant to avoid floating point hassles. */
2908 six_months_ago = current_time - 31556952 / 2;
2909 recent = (six_months_ago <= when
2910 && (when < current_time
2911 || (when == current_time && when_ns <= current_time_ns)));
2912 fmt = long_time_format[recent];
2914 for (;;)
2916 char *newbuf;
2917 *p = '\1';
2918 s = nstrftime (p, buf + bufsize - p - 1, fmt,
2919 when_local, 0, when_ns);
2920 if (s || ! *p)
2921 break;
2922 newbuf = alloca (bufsize *= 2);
2923 memcpy (newbuf, buf, p - buf);
2924 p = newbuf + (p - buf);
2925 buf = newbuf;
2928 p += s;
2929 *p++ = ' ';
2931 /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it. */
2932 *p = '\0';
2934 else
2936 /* The time cannot be represented as a local time;
2937 print it as a huge integer number of seconds. */
2938 char hbuf[LONGEST_HUMAN_READABLE + 1];
2939 int width = long_time_expected_width ();
2941 if (when < 0)
2943 const char *num = human_readable (- (uintmax_t) when, hbuf, 1, 1);
2944 int sign_width = width - strlen (num);
2945 sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num);
2947 else
2948 sprintf (p, "%*s ", width,
2949 human_readable ((uintmax_t) when, hbuf, 1, 1));
2951 p += strlen (p);
2954 DIRED_INDENT ();
2955 DIRED_FPUTS (buf, stdout, p - buf);
2956 print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
2957 &dired_obstack);
2959 if (f->filetype == symbolic_link)
2961 if (f->linkname)
2963 DIRED_FPUTS_LITERAL (" -> ", stdout);
2964 print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1,
2965 NULL);
2966 if (indicator_style != none)
2967 print_type_indicator (f->linkmode);
2970 else if (indicator_style != none)
2971 print_type_indicator (f->stat.st_mode);
2974 /* Output to OUT a quoted representation of the file name NAME,
2975 using OPTIONS to control quoting. Produce no output if OUT is NULL.
2976 Return the number of screen columns occupied by NAME's quoted
2977 representation. */
2979 static size_t
2980 quote_name (FILE *out, const char *name, struct quoting_options const *options)
2982 char smallbuf[BUFSIZ];
2983 size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, name, -1, options);
2984 char *buf;
2985 int displayed_width;
2987 if (len < sizeof smallbuf)
2988 buf = smallbuf;
2989 else
2991 buf = (char *) alloca (len + 1);
2992 quotearg_buffer (buf, len + 1, name, -1, options);
2995 if (qmark_funny_chars)
2997 #if HAVE_MBRTOWC
2998 if (MB_CUR_MAX > 1)
3000 char const *p = buf;
3001 char const *plimit = buf + len;
3002 char *q = buf;
3003 displayed_width = 0;
3005 while (p < plimit)
3006 switch (*p)
3008 case ' ': case '!': case '"': case '#': case '%':
3009 case '&': case '\'': case '(': case ')': case '*':
3010 case '+': case ',': case '-': case '.': case '/':
3011 case '0': case '1': case '2': case '3': case '4':
3012 case '5': case '6': case '7': case '8': case '9':
3013 case ':': case ';': case '<': case '=': case '>':
3014 case '?':
3015 case 'A': case 'B': case 'C': case 'D': case 'E':
3016 case 'F': case 'G': case 'H': case 'I': case 'J':
3017 case 'K': case 'L': case 'M': case 'N': case 'O':
3018 case 'P': case 'Q': case 'R': case 'S': case 'T':
3019 case 'U': case 'V': case 'W': case 'X': case 'Y':
3020 case 'Z':
3021 case '[': case '\\': case ']': case '^': case '_':
3022 case 'a': case 'b': case 'c': case 'd': case 'e':
3023 case 'f': case 'g': case 'h': case 'i': case 'j':
3024 case 'k': case 'l': case 'm': case 'n': case 'o':
3025 case 'p': case 'q': case 'r': case 's': case 't':
3026 case 'u': case 'v': case 'w': case 'x': case 'y':
3027 case 'z': case '{': case '|': case '}': case '~':
3028 /* These characters are printable ASCII characters. */
3029 *q++ = *p++;
3030 displayed_width += 1;
3031 break;
3032 default:
3033 /* If we have a multibyte sequence, copy it until we
3034 reach its end, replacing each non-printable multibyte
3035 character with a single question mark. */
3037 mbstate_t mbstate;
3038 memset (&mbstate, 0, sizeof mbstate);
3041 wchar_t wc;
3042 size_t bytes;
3043 int w;
3045 bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
3047 if (bytes == (size_t) -1)
3049 /* An invalid multibyte sequence was
3050 encountered. Skip one input byte, and
3051 put a question mark. */
3052 p++;
3053 *q++ = '?';
3054 displayed_width += 1;
3055 break;
3058 if (bytes == (size_t) -2)
3060 /* An incomplete multibyte character
3061 at the end. Replace it entirely with
3062 a question mark. */
3063 p = plimit;
3064 *q++ = '?';
3065 displayed_width += 1;
3066 break;
3069 if (bytes == 0)
3070 /* A null wide character was encountered. */
3071 bytes = 1;
3073 w = wcwidth (wc);
3074 if (w >= 0)
3076 /* A printable multibyte character.
3077 Keep it. */
3078 for (; bytes > 0; --bytes)
3079 *q++ = *p++;
3080 displayed_width += w;
3082 else
3084 /* An unprintable multibyte character.
3085 Replace it entirely with a question
3086 mark. */
3087 p += bytes;
3088 *q++ = '?';
3089 displayed_width += 1;
3092 while (! mbsinit (&mbstate));
3094 break;
3097 /* The buffer may have shrunk. */
3098 len = q - buf;
3100 else
3101 #endif
3103 char *p = buf;
3104 char const *plimit = buf + len;
3106 while (p < plimit)
3108 if (! ISPRINT ((unsigned char) *p))
3109 *p = '?';
3110 p++;
3112 displayed_width = len;
3115 else
3117 /* Assume unprintable characters have a displayed_width of 1. */
3118 #if HAVE_MBRTOWC
3119 if (MB_CUR_MAX > 1)
3120 displayed_width = mbsnwidth (buf, len, 0);
3121 else
3122 #endif
3123 displayed_width = len;
3126 if (out != NULL)
3127 fwrite (buf, 1, len, out);
3128 return displayed_width;
3131 static void
3132 print_name_with_quoting (const char *p, mode_t mode, int linkok,
3133 struct obstack *stack)
3135 if (print_with_color)
3136 print_color_indicator (p, mode, linkok);
3138 if (stack)
3139 PUSH_CURRENT_DIRED_POS (stack);
3141 dired_pos += quote_name (stdout, p, filename_quoting_options);
3143 if (stack)
3144 PUSH_CURRENT_DIRED_POS (stack);
3146 if (print_with_color)
3147 prep_non_filename_text ();
3150 static void
3151 prep_non_filename_text (void)
3153 if (color_indicator[C_END].string != NULL)
3154 put_indicator (&color_indicator[C_END]);
3155 else
3157 put_indicator (&color_indicator[C_LEFT]);
3158 put_indicator (&color_indicator[C_NORM]);
3159 put_indicator (&color_indicator[C_RIGHT]);
3163 /* Print the file name of `f' with appropriate quoting.
3164 Also print file size, inode number, and filetype indicator character,
3165 as requested by switches. */
3167 static void
3168 print_file_name_and_frills (const struct fileinfo *f)
3170 char buf[LONGEST_HUMAN_READABLE + 1];
3172 if (print_inode)
3173 printf ("%*s ", INODE_DIGITS,
3174 human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1));
3176 if (print_block_size)
3177 printf ("%*s ", block_size_size,
3178 human_readable_inexact ((uintmax_t) ST_NBLOCKS (f->stat), buf,
3179 ST_NBLOCKSIZE, output_block_size,
3180 human_ceiling));
3182 print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok, NULL);
3184 if (indicator_style != none)
3185 print_type_indicator (f->stat.st_mode);
3188 static void
3189 print_type_indicator (mode_t mode)
3191 int c;
3193 if (S_ISREG (mode))
3195 if (indicator_style == classify && (mode & S_IXUGO))
3196 c ='*';
3197 else
3198 c = 0;
3200 else
3202 if (S_ISDIR (mode))
3203 c = '/';
3204 else if (S_ISLNK (mode))
3205 c = '@';
3206 else if (S_ISFIFO (mode))
3207 c = '|';
3208 else if (S_ISSOCK (mode))
3209 c = '=';
3210 else if (S_ISDOOR (mode))
3211 c = '>';
3212 else
3213 c = 0;
3216 if (c)
3217 DIRED_PUTCHAR (c);
3220 static void
3221 print_color_indicator (const char *name, mode_t mode, int linkok)
3223 int type = C_FILE;
3224 struct color_ext_type *ext; /* Color extension */
3225 size_t len; /* Length of name */
3227 /* Is this a nonexistent file? If so, linkok == -1. */
3229 if (linkok == -1 && color_indicator[C_MISSING].string != NULL)
3231 ext = NULL;
3232 type = C_MISSING;
3234 else
3236 if (S_ISDIR (mode))
3237 type = C_DIR;
3238 else if (S_ISLNK (mode))
3239 type = ((!linkok && color_indicator[C_ORPHAN].string)
3240 ? C_ORPHAN : C_LINK);
3241 else if (S_ISFIFO (mode))
3242 type = C_FIFO;
3243 else if (S_ISSOCK (mode))
3244 type = C_SOCK;
3245 else if (S_ISBLK (mode))
3246 type = C_BLK;
3247 else if (S_ISCHR (mode))
3248 type = C_CHR;
3249 else if (S_ISDOOR (mode))
3250 type = C_DOOR;
3252 if (type == C_FILE && (mode & S_IXUGO) != 0)
3253 type = C_EXEC;
3255 /* Check the file's suffix only if still classified as C_FILE. */
3256 ext = NULL;
3257 if (type == C_FILE)
3259 /* Test if NAME has a recognized suffix. */
3261 len = strlen (name);
3262 name += len; /* Pointer to final \0. */
3263 for (ext = color_ext_list; ext != NULL; ext = ext->next)
3265 if ((size_t) ext->ext.len <= len
3266 && strncmp (name - ext->ext.len, ext->ext.string,
3267 ext->ext.len) == 0)
3268 break;
3273 put_indicator (&color_indicator[C_LEFT]);
3274 put_indicator (ext ? &(ext->seq) : &color_indicator[type]);
3275 put_indicator (&color_indicator[C_RIGHT]);
3278 /* Output a color indicator (which may contain nulls). */
3279 static void
3280 put_indicator (const struct bin_str *ind)
3282 register int i;
3283 register const char *p;
3285 p = ind->string;
3287 for (i = ind->len; i > 0; --i)
3288 putchar (*(p++));
3291 static int
3292 length_of_file_name_and_frills (const struct fileinfo *f)
3294 register int len = 0;
3296 if (print_inode)
3297 len += INODE_DIGITS + 1;
3299 if (print_block_size)
3300 len += 1 + block_size_size;
3302 len += quote_name (NULL, f->name, filename_quoting_options);
3304 if (indicator_style != none)
3306 mode_t filetype = f->stat.st_mode;
3308 if (S_ISREG (filetype))
3310 if (indicator_style == classify
3311 && (f->stat.st_mode & S_IXUGO))
3312 len += 1;
3314 else if (S_ISDIR (filetype)
3315 || S_ISLNK (filetype)
3316 || S_ISFIFO (filetype)
3317 || S_ISSOCK (filetype)
3318 || S_ISDOOR (filetype)
3320 len += 1;
3323 return len;
3326 static void
3327 print_many_per_line (void)
3329 struct column_info *line_fmt;
3330 int filesno; /* Index into files. */
3331 int row; /* Current row. */
3332 int max_name_length; /* Length of longest file name + frills. */
3333 int name_length; /* Length of each file name + frills. */
3334 int pos; /* Current character column. */
3335 int cols; /* Number of files across. */
3336 int rows; /* Maximum number of files down. */
3337 int max_cols;
3339 /* Normally the maximum number of columns is determined by the
3340 screen width. But if few files are available this might limit it
3341 as well. */
3342 max_cols = max_idx > files_index ? files_index : max_idx;
3344 /* Compute the maximum number of possible columns. */
3345 for (filesno = 0; filesno < files_index; ++filesno)
3347 int i;
3349 name_length = length_of_file_name_and_frills (files + filesno);
3351 for (i = 0; i < max_cols; ++i)
3353 if (column_info[i].valid_len)
3355 int idx = filesno / ((files_index + i) / (i + 1));
3356 int real_length = name_length + (idx == i ? 0 : 2);
3358 if (real_length > column_info[i].col_arr[idx])
3360 column_info[i].line_len += (real_length
3361 - column_info[i].col_arr[idx]);
3362 column_info[i].col_arr[idx] = real_length;
3363 column_info[i].valid_len = column_info[i].line_len < line_length;
3369 /* Find maximum allowed columns. */
3370 for (cols = max_cols; cols > 1; --cols)
3372 if (column_info[cols - 1].valid_len)
3373 break;
3376 line_fmt = &column_info[cols - 1];
3378 /* Calculate the number of rows that will be in each column except possibly
3379 for a short column on the right. */
3380 rows = files_index / cols + (files_index % cols != 0);
3382 for (row = 0; row < rows; row++)
3384 int col = 0;
3385 filesno = row;
3386 pos = 0;
3387 /* Print the next row. */
3388 while (1)
3390 print_file_name_and_frills (files + filesno);
3391 name_length = length_of_file_name_and_frills (files + filesno);
3392 max_name_length = line_fmt->col_arr[col++];
3394 filesno += rows;
3395 if (filesno >= files_index)
3396 break;
3398 indent (pos + name_length, pos + max_name_length);
3399 pos += max_name_length;
3401 putchar ('\n');
3405 static void
3406 print_horizontal (void)
3408 struct column_info *line_fmt;
3409 int filesno;
3410 int max_name_length;
3411 int name_length;
3412 int cols;
3413 int pos;
3414 int max_cols;
3416 /* Normally the maximum number of columns is determined by the
3417 screen width. But if few files are available this might limit it
3418 as well. */
3419 max_cols = max_idx > files_index ? files_index : max_idx;
3421 /* Compute the maximum file name length. */
3422 max_name_length = 0;
3423 for (filesno = 0; filesno < files_index; ++filesno)
3425 int i;
3427 name_length = length_of_file_name_and_frills (files + filesno);
3429 for (i = 0; i < max_cols; ++i)
3431 if (column_info[i].valid_len)
3433 int idx = filesno % (i + 1);
3434 int real_length = name_length + (idx == i ? 0 : 2);
3436 if (real_length > column_info[i].col_arr[idx])
3438 column_info[i].line_len += (real_length
3439 - column_info[i].col_arr[idx]);
3440 column_info[i].col_arr[idx] = real_length;
3441 column_info[i].valid_len = column_info[i].line_len < line_length;
3447 /* Find maximum allowed columns. */
3448 for (cols = max_cols; cols > 1; --cols)
3450 if (column_info[cols - 1].valid_len)
3451 break;
3454 line_fmt = &column_info[cols - 1];
3456 pos = 0;
3458 /* Print first entry. */
3459 print_file_name_and_frills (files);
3460 name_length = length_of_file_name_and_frills (files);
3461 max_name_length = line_fmt->col_arr[0];
3463 /* Now the rest. */
3464 for (filesno = 1; filesno < files_index; ++filesno)
3466 int col = filesno % cols;
3468 if (col == 0)
3470 putchar ('\n');
3471 pos = 0;
3473 else
3475 indent (pos + name_length, pos + max_name_length);
3476 pos += max_name_length;
3479 print_file_name_and_frills (files + filesno);
3481 name_length = length_of_file_name_and_frills (files + filesno);
3482 max_name_length = line_fmt->col_arr[col];
3484 putchar ('\n');
3487 static void
3488 print_with_commas (void)
3490 int filesno;
3491 int pos, old_pos;
3493 pos = 0;
3495 for (filesno = 0; filesno < files_index; filesno++)
3497 old_pos = pos;
3499 pos += length_of_file_name_and_frills (files + filesno);
3500 if (filesno + 1 < files_index)
3501 pos += 2; /* For the comma and space */
3503 if (old_pos != 0 && pos >= line_length)
3505 putchar ('\n');
3506 pos -= old_pos;
3509 print_file_name_and_frills (files + filesno);
3510 if (filesno + 1 < files_index)
3512 putchar (',');
3513 putchar (' ');
3516 putchar ('\n');
3519 /* Assuming cursor is at position FROM, indent up to position TO.
3520 Use a TAB character instead of two or more spaces whenever possible. */
3522 static void
3523 indent (int from, int to)
3525 while (from < to)
3527 if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
3529 putchar ('\t');
3530 from += tabsize - from % tabsize;
3532 else
3534 putchar (' ');
3535 from++;
3540 /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */
3541 /* FIXME: maybe remove this function someday. See about using a
3542 non-malloc'ing version of path_concat. */
3544 static void
3545 attach (char *dest, const char *dirname, const char *name)
3547 const char *dirnamep = dirname;
3549 /* Copy dirname if it is not ".". */
3550 if (dirname[0] != '.' || dirname[1] != 0)
3552 while (*dirnamep)
3553 *dest++ = *dirnamep++;
3554 /* Add '/' if `dirname' doesn't already end with it. */
3555 if (dirnamep > dirname && dirnamep[-1] != '/')
3556 *dest++ = '/';
3558 while (*name)
3559 *dest++ = *name++;
3560 *dest = 0;
3563 static void
3564 init_column_info (void)
3566 int i;
3567 int allocate = 0;
3569 max_idx = line_length / MIN_COLUMN_WIDTH;
3570 if (max_idx == 0)
3571 max_idx = 1;
3573 if (column_info == NULL)
3575 column_info = XMALLOC (struct column_info, max_idx);
3576 allocate = 1;
3579 for (i = 0; i < max_idx; ++i)
3581 int j;
3583 column_info[i].valid_len = 1;
3584 column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
3586 if (allocate)
3587 column_info[i].col_arr = XMALLOC (int, i + 1);
3589 for (j = 0; j <= i; ++j)
3590 column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
3594 void
3595 usage (int status)
3597 if (status != 0)
3598 fprintf (stderr, _("Try `%s --help' for more information.\n"),
3599 program_name);
3600 else
3602 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
3603 fputs (_("\
3604 List information about the FILEs (the current directory by default).\n\
3605 Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
3607 "), stdout);
3608 fputs (_("\
3609 Mandatory arguments to long options are mandatory for short options too.\n\
3610 "), stdout);
3611 fputs (_("\
3612 -a, --all do not hide entries starting with .\n\
3613 -A, --almost-all do not list implied . and ..\n\
3614 --author print the author of each file\n\
3615 -b, --escape print octal escapes for nongraphic characters\n\
3616 "), stdout);
3617 fputs (_("\
3618 --block-size=SIZE use SIZE-byte blocks\n\
3619 -B, --ignore-backups do not list implied entries ending with ~\n\
3620 -c with -lt: sort by, and show, ctime (time of last\n\
3621 modification of file status information)\n\
3622 with -l: show ctime and sort by name\n\
3623 otherwise: sort by ctime\n\
3624 "), stdout);
3625 fputs (_("\
3626 -C list entries by columns\n\
3627 --color[=WHEN] control whether color is used to distinguish file\n\
3628 types. WHEN may be `never', `always', or `auto'\n\
3629 -d, --directory list directory entries instead of contents\n\
3630 -D, --dired generate output designed for Emacs' dired mode\n\
3631 "), stdout);
3632 fputs (_("\
3633 -f do not sort, enable -aU, disable -lst\n\
3634 -F, --classify append indicator (one of */=@|) to entries\n\
3635 --format=WORD across -x, commas -m, horizontal -x, long -l,\n\
3636 single-column -1, verbose -l, vertical -C\n\
3637 --full-time like -l --time-style=full-iso\n\
3638 "), stdout);
3639 fputs (_("\
3640 -g like -l, but do not list owner\n\
3641 -G, --no-group inhibit display of group information\n\
3642 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
3643 --si likewise, but use powers of 1000 not 1024\n\
3644 -H, --dereference-command-line follow symbolic links on the command line\n\
3645 "), stdout);
3646 fputs (_("\
3647 --indicator-style=WORD append indicator with style WORD to entry names:\n\
3648 none (default), classify (-F), file-type (-p)\n\
3649 -i, --inode print index number of each file\n\
3650 -I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\
3651 -k like --block-size=1K\n\
3652 "), stdout);
3653 fputs (_("\
3654 -l use a long listing format\n\
3655 -L, --dereference when showing file information for a symbolic\n\
3656 link, show information for the file the link\n\
3657 references rather than for the link itself\n\
3658 -m fill width with a comma separated list of entries\n\
3659 "), stdout);
3660 fputs (_("\
3661 -n, --numeric-uid-gid like -l, but list numeric UIDs and GIDs\n\
3662 -N, --literal print raw entry names (don't treat e.g. control\n\
3663 characters specially)\n\
3664 -o like -l, but do not list group information\n\
3665 -p, --file-type append indicator (one of /=@|) to entries\n\
3666 "), stdout);
3667 fputs (_("\
3668 -q, --hide-control-chars print ? instead of non graphic characters\n\
3669 --show-control-chars show non graphic characters as-is (default\n\
3670 unless program is `ls' and output is a terminal)\n\
3671 -Q, --quote-name enclose entry names in double quotes\n\
3672 --quoting-style=WORD use quoting style WORD for entry names:\n\
3673 literal, locale, shell, shell-always, c, escape\n\
3674 "), stdout);
3675 fputs (_("\
3676 -r, --reverse reverse order while sorting\n\
3677 -R, --recursive list subdirectories recursively\n\
3678 -s, --size print size of each file, in blocks\n\
3679 "), stdout);
3680 fputs (_("\
3681 -S sort by file size\n\
3682 --sort=WORD extension -X, none -U, size -S, time -t,\n\
3683 version -v\n\
3684 status -c, time -t, atime -u, access -u, use -u\n\
3685 --time=WORD show time as WORD instead of modification time:\n\
3686 atime, access, use, ctime or status; use\n\
3687 specified time as sort key if --sort=time\n\
3688 "), stdout);
3689 fputs (_("\
3690 --time-style=STYLE show times using style STYLE:\n\
3691 full-iso, long-iso, iso, locale, +FORMAT\n\
3692 FORMAT is interpreted like `date'; if FORMAT is\n\
3693 FORMAT1<newline>FORMAT2, FORMAT1 applies to\n\
3694 non-recent files and FORMAT2 to recent files;\n\
3695 if STYLE is prefixed with `posix-', STYLE\n\
3696 takes effect only outside the POSIX locale\n\
3697 -t sort by modification time\n\
3698 -T, --tabsize=COLS assume tab stops at each COLS instead of 8\n\
3699 "), stdout);
3700 fputs (_("\
3701 -u with -lt: sort by, and show, access time\n\
3702 with -l: show access time and sort by name\n\
3703 otherwise: sort by access time\n\
3704 -U do not sort; list entries in directory order\n\
3705 -v sort by version\n\
3706 "), stdout);
3707 fputs (_("\
3708 -w, --width=COLS assume screen width instead of current value\n\
3709 -x list entries by lines instead of by columns\n\
3710 -X sort alphabetically by entry extension\n\
3711 -1 list one file per line\n\
3712 "), stdout);
3713 fputs (HELP_OPTION_DESCRIPTION, stdout);
3714 fputs (VERSION_OPTION_DESCRIPTION, stdout);
3715 fputs (_("\n\
3716 SIZE may be (or may be an integer optionally followed by) one of following:\n\
3717 kB 1000, K 1024, MB 1,000,000, M 1,048,576, and so on for G, T, P, E, Z, Y.\n\
3718 "), stdout);
3719 fputs (_("\
3721 By default, color is not used to distinguish types of files. That is\n\
3722 equivalent to using --color=none. Using the --color option without the\n\
3723 optional WHEN argument is equivalent to using --color=always. With\n\
3724 --color=auto, color codes are output only if standard output is connected\n\
3725 to a terminal (tty).\n\
3726 "), stdout);
3727 printf (_("\nReport bugs to <%s>.\n"), PACKAGE_BUGREPORT);
3729 exit (status);