(main): `quote' the offending argument.
[coreutils.git] / src / ls.c
blobc5701698c3a37df7a1676a2fb92b0ee6159a6666
1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
2 Copyright (C) 85, 88, 90, 91, 1995-2001 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 #if HAVE_SYS_ACL_H
64 # include <sys/acl.h>
65 #endif
67 #include <stdio.h>
68 #include <assert.h>
69 #include <grp.h>
70 #include <pwd.h>
71 #include <getopt.h>
73 /* Get MB_LEN_MAX. */
74 #if HAVE_LIMITS_H
75 # include <limits.h>
76 #endif
78 /* Get MB_CUR_MAX. */
79 #if HAVE_STDLIB_H
80 # include <stdlib.h>
81 #endif
83 /* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
84 #if HAVE_WCHAR_H
85 # include <wchar.h>
86 #endif
88 /* Get iswprint(). */
89 #if HAVE_WCTYPE_H
90 # include <wctype.h>
91 #endif
92 #if !defined iswprint && !HAVE_ISWPRINT
93 # define iswprint(wc) 1
94 #endif
96 #ifndef HAVE_DECL_WCWIDTH
97 "this configure-time declaration test was not run"
98 #endif
99 #if !HAVE_DECL_WCWIDTH
100 int wcwidth ();
101 #endif
103 /* If wcwidth() doesn't exist, assume all printable characters have
104 width 1. */
105 #ifndef wcwidth
106 # if !HAVE_WCWIDTH
107 # define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
108 # endif
109 #endif
111 #include "system.h"
112 #include <fnmatch.h>
114 #include "argmatch.h"
115 #include "error.h"
116 #include "human.h"
117 #include "filemode.h"
118 #include "ls.h"
119 #include "mbswidth.h"
120 #include "obstack.h"
121 #include "path-concat.h"
122 #include "quotearg.h"
123 #include "strverscmp.h"
124 #include "xstrtol.h"
126 /* Use access control lists only under all the following conditions.
127 Some systems (OSF4, Irix5, Irix6) have the acl function, but not
128 sys/acl.h or don't define the GETACLCNT macro. */
129 #if HAVE_SYS_ACL_H && HAVE_ACL && defined GETACLCNT
130 # define USE_ACL 1
131 #endif
133 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
134 : (ls_mode == LS_MULTI_COL \
135 ? "dir" : "vdir"))
137 #define AUTHORS "Richard Stallman and David MacKenzie"
139 #define obstack_chunk_alloc malloc
140 #define obstack_chunk_free free
142 /* Return an int indicating the result of comparing two integers.
143 Subtracting doesn't always work, due to overflow. */
144 #define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
146 /* The field width for inode numbers. On some hosts inode numbers are
147 64 bits, so columns won't line up exactly when a huge inode number
148 is encountered, but in practice 7 digits is usually enough. */
149 #ifndef INODE_DIGITS
150 # define INODE_DIGITS 7
151 #endif
153 #ifdef S_ISLNK
154 # define HAVE_SYMLINKS 1
155 #else
156 # define HAVE_SYMLINKS 0
157 #endif
159 /* If any of the S_* macros are undefined, define them here so each
160 use doesn't have to be guarded with e.g., #ifdef S_ISLNK. */
161 #ifndef S_ISLNK
162 # define S_ISLNK(Mode) 0
163 #endif
165 #ifndef S_ISFIFO
166 # define S_ISFIFO(Mode) 0
167 #endif
169 #ifndef S_ISSOCK
170 # define S_ISSOCK(Mode) 0
171 #endif
173 #ifndef S_ISCHR
174 # define S_ISCHR(Mode) 0
175 #endif
177 #ifndef S_ISBLK
178 # define S_ISBLK(Mode) 0
179 #endif
181 #ifndef S_ISDOOR
182 # define S_ISDOOR(Mode) 0
183 #endif
185 /* Arrange to make lstat calls go through the wrapper function
186 on systems with an lstat function that does not dereference symlinks
187 that are specified with a trailing slash. */
188 #if ! LSTAT_FOLLOWS_SLASHED_SYMLINK
189 int rpl_lstat PARAMS((const char *, struct stat *));
190 # undef lstat
191 # define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
192 #endif
194 #if defined _DIRENT_HAVE_D_TYPE || defined DTTOIF
195 # define HAVE_STRUCT_DIRENT_D_TYPE 1
196 # define DT_INIT(Val) = Val
197 #else
198 # define HAVE_STRUCT_DIRENT_D_TYPE 0
199 # define DT_INIT(Val) /* empty */
200 #endif
202 #ifdef ST_MTIM_NSEC
203 # define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC)
204 #else
205 # define TIMESPEC_NS(timespec) 0
206 #endif
208 enum filetype
210 unknown DT_INIT (DT_UNKNOWN),
211 fifo DT_INIT (DT_FIFO),
212 chardev DT_INIT (DT_CHR),
213 directory DT_INIT (DT_DIR),
214 blockdev DT_INIT (DT_BLK),
215 normal DT_INIT (DT_REG),
216 symbolic_link DT_INIT (DT_LNK),
217 sock DT_INIT (DT_SOCK),
218 arg_directory DT_INIT (2 * (DT_UNKNOWN | DT_FIFO | DT_CHR | DT_DIR | DT_BLK
219 | DT_REG | DT_LNK | DT_SOCK))
222 struct fileinfo
224 /* The file name. */
225 char *name;
227 struct stat stat;
229 /* For symbolic link, name of the file linked to, otherwise zero. */
230 char *linkname;
232 /* For symbolic link and long listing, st_mode of file linked to, otherwise
233 zero. */
234 unsigned int linkmode;
236 /* For symbolic link and color printing, 1 if linked-to file
237 exists, otherwise 0. */
238 int linkok;
240 enum filetype filetype;
242 #if USE_ACL
243 /* For long listings, nonzero if the file has an access control list,
244 otherwise zero. */
245 int have_acl;
246 #endif
249 #if USE_ACL
250 # define FILE_HAS_ACL(F) ((F)->have_acl)
251 #else
252 # define FILE_HAS_ACL(F) 0
253 #endif
255 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
257 /* Null is a valid character in a color indicator (think about Epson
258 printers, for example) so we have to use a length/buffer string
259 type. */
261 struct bin_str
263 int len; /* Number of bytes */
264 const char *string; /* Pointer to the same */
267 #ifndef STDC_HEADERS
268 time_t time ();
269 #endif
271 char *getgroup ();
272 char *getuser ();
274 static size_t quote_name PARAMS ((FILE *out, const char *name,
275 struct quoting_options const *options));
276 static char *make_link_path PARAMS ((const char *path, const char *linkname));
277 static int compare_atime PARAMS ((const struct fileinfo *file1,
278 const struct fileinfo *file2));
279 static int rev_cmp_atime PARAMS ((const struct fileinfo *file2,
280 const struct fileinfo *file1));
281 static int compare_ctime PARAMS ((const struct fileinfo *file1,
282 const struct fileinfo *file2));
283 static int rev_cmp_ctime PARAMS ((const struct fileinfo *file2,
284 const struct fileinfo *file1));
285 static int compare_mtime PARAMS ((const struct fileinfo *file1,
286 const struct fileinfo *file2));
287 static int rev_cmp_mtime PARAMS ((const struct fileinfo *file2,
288 const struct fileinfo *file1));
289 static int compare_size PARAMS ((const struct fileinfo *file1,
290 const struct fileinfo *file2));
291 static int rev_cmp_size PARAMS ((const struct fileinfo *file2,
292 const struct fileinfo *file1));
293 static int compare_name PARAMS ((const struct fileinfo *file1,
294 const struct fileinfo *file2));
295 static int rev_cmp_name PARAMS ((const struct fileinfo *file2,
296 const struct fileinfo *file1));
297 static int compare_extension PARAMS ((const struct fileinfo *file1,
298 const struct fileinfo *file2));
299 static int rev_cmp_extension PARAMS ((const struct fileinfo *file2,
300 const struct fileinfo *file1));
301 static int compare_version PARAMS ((const struct fileinfo *file1,
302 const struct fileinfo *file2));
303 static int rev_cmp_version PARAMS ((const struct fileinfo *file2,
304 const struct fileinfo *file1));
305 static int decode_switches PARAMS ((int argc, char **argv));
306 static int file_interesting PARAMS ((const struct dirent *next));
307 static uintmax_t gobble_file PARAMS ((const char *name, enum filetype type,
308 int explicit_arg, const char *dirname));
309 static void print_color_indicator PARAMS ((const char *name, unsigned int mode,
310 int linkok));
311 static void put_indicator PARAMS ((const struct bin_str *ind));
312 static int length_of_file_name_and_frills PARAMS ((const struct fileinfo *f));
313 static void add_ignore_pattern PARAMS ((const char *pattern));
314 static void attach PARAMS ((char *dest, const char *dirname, const char *name));
315 static void clear_files PARAMS ((void));
316 static void extract_dirs_from_files PARAMS ((const char *dirname,
317 int recursive));
318 static void get_link_name PARAMS ((const char *filename, struct fileinfo *f));
319 static void indent PARAMS ((int from, int to));
320 static void init_column_info PARAMS ((void));
321 static void print_current_files PARAMS ((void));
322 static void print_dir PARAMS ((const char *name, const char *realname));
323 static void print_file_name_and_frills PARAMS ((const struct fileinfo *f));
324 static void print_horizontal PARAMS ((void));
325 static void print_long_format PARAMS ((const struct fileinfo *f));
326 static void print_many_per_line PARAMS ((void));
327 static void print_name_with_quoting PARAMS ((const char *p, unsigned int mode,
328 int linkok,
329 struct obstack *stack));
330 static void prep_non_filename_text PARAMS ((void));
331 static void print_type_indicator PARAMS ((unsigned int mode));
332 static void print_with_commas PARAMS ((void));
333 static void queue_directory PARAMS ((const char *name, const char *realname));
334 static void sort_files PARAMS ((void));
335 static void parse_ls_color PARAMS ((void));
336 void usage PARAMS ((int status));
338 /* The name the program was run with, stripped of any leading path. */
339 char *program_name;
341 /* The table of files in the current directory:
343 `files' points to a vector of `struct fileinfo', one per file.
344 `nfiles' is the number of elements space has been allocated for.
345 `files_index' is the number actually in use. */
347 /* Address of block containing the files that are described. */
349 static struct fileinfo *files;
351 /* Length of block that `files' points to, measured in files. */
353 static int nfiles;
355 /* Index of first unused in `files'. */
357 static int files_index;
359 /* When nonzero, in a color listing, color each symlink name according to the
360 type of file it points to. Otherwise, color them according to the `ln'
361 directive in LS_COLORS. Dangling (orphan) symlinks are treated specially,
362 regardless. This is set when `ln=target' appears in LS_COLORS. */
364 static int color_symlink_as_referent;
366 /* mode of appropriate file for colorization */
367 #define FILE_OR_LINK_MODE(File) \
368 ((color_symlink_as_referent && (File)->linkok) \
369 ? (File)->linkmode : (File)->stat.st_mode)
372 /* Record of one pending directory waiting to be listed. */
374 struct pending
376 char *name;
377 /* If the directory is actually the file pointed to by a symbolic link we
378 were told to list, `realname' will contain the name of the symbolic
379 link, otherwise zero. */
380 char *realname;
381 struct pending *next;
384 static struct pending *pending_dirs;
386 /* Current time in seconds and nanoseconds since 1970, updated as
387 needed when deciding whether a file is recent. */
389 static time_t current_time = TYPE_MINIMUM (time_t);
390 static int current_time_ns = -1;
392 /* The number of digits to use for block sizes.
393 4, or more if needed for bigger numbers. */
395 static int block_size_size;
397 /* Option flags */
399 /* long_format for lots of info, one per line.
400 one_per_line for just names, one per line.
401 many_per_line for just names, many per line, sorted vertically.
402 horizontal for just names, many per line, sorted horizontally.
403 with_commas for just names, many per line, separated by commas.
405 -l, -1, -C, -x and -m control this parameter. */
407 enum format
409 long_format, /* -l */
410 one_per_line, /* -1 */
411 many_per_line, /* -C */
412 horizontal, /* -x */
413 with_commas /* -m */
416 static enum format format;
418 /* Type of time to print or sort by. Controlled by -c and -u. */
420 enum time_type
422 time_mtime, /* default */
423 time_ctime, /* -c */
424 time_atime /* -u */
427 static enum time_type time_type;
429 /* print the full time, otherwise the standard unix heuristics. */
431 static int full_time;
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 NOT display group information. -G */
457 static int inhibit_group;
459 /* Nonzero means print the user and group id's as numbers rather
460 than as names. -n */
462 static int numeric_ids;
464 /* Nonzero means mention the size in blocks of each file. -s */
466 static int print_block_size;
468 /* If positive, the units to use when printing sizes;
469 if negative, the human-readable base. */
470 static int output_block_size;
472 /* Precede each line of long output (per file) with a string like `m,n:'
473 where M is the number of characters after the `:' and before the
474 filename and N is the length of the filename. Using this format,
475 Emacs' dired mode starts up twice as fast, and can handle all
476 strange characters in file names. */
477 static int dired;
479 /* `none' means don't mention the type of files.
480 `classify' means mention file types and mark executables.
481 `file_type' means mention only file types.
483 Controlled by -F, -p, and --indicator-style. */
485 enum indicator_style
487 none, /* --indicator-style=none */
488 classify, /* -F, --indicator-style=classify */
489 file_type /* -p, --indicator-style=file-type */
492 static enum indicator_style indicator_style;
494 /* Names of indicator styles. */
495 static char const *const indicator_style_args[] =
497 "none", "classify", "file-type", 0
500 static enum indicator_style const indicator_style_types[]=
502 none, classify, file_type
505 /* Nonzero means use colors to mark types. Also define the different
506 colors as well as the stuff for the LS_COLORS environment variable.
507 The LS_COLORS variable is now in a termcap-like format. */
509 static int print_with_color;
511 enum color_type
513 color_never, /* 0: default or --color=never */
514 color_always, /* 1: --color=always */
515 color_if_tty /* 2: --color=tty */
518 enum indicator_no
520 C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
521 C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR
524 static const char *const indicator_name[]=
526 "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
527 "bd", "cd", "mi", "or", "ex", "do", NULL
530 struct color_ext_type
532 struct bin_str ext; /* The extension we're looking for */
533 struct bin_str seq; /* The sequence to output when we do */
534 struct color_ext_type *next; /* Next in list */
537 static struct bin_str color_indicator[] =
539 { LEN_STR_PAIR ("\033[") }, /* lc: Left of color sequence */
540 { LEN_STR_PAIR ("m") }, /* rc: Right of color sequence */
541 { 0, NULL }, /* ec: End color (replaces lc+no+rc) */
542 { LEN_STR_PAIR ("0") }, /* no: Normal */
543 { LEN_STR_PAIR ("0") }, /* fi: File: default */
544 { LEN_STR_PAIR ("01;34") }, /* di: Directory: bright blue */
545 { LEN_STR_PAIR ("01;36") }, /* ln: Symlink: bright cyan */
546 { LEN_STR_PAIR ("33") }, /* pi: Pipe: yellow/brown */
547 { LEN_STR_PAIR ("01;35") }, /* so: Socket: bright magenta */
548 { LEN_STR_PAIR ("01;33") }, /* bd: Block device: bright yellow */
549 { LEN_STR_PAIR ("01;33") }, /* cd: Char device: bright yellow */
550 { 0, NULL }, /* mi: Missing file: undefined */
551 { 0, NULL }, /* or: Orphanned symlink: undefined */
552 { LEN_STR_PAIR ("01;32") }, /* ex: Executable: bright green */
553 { LEN_STR_PAIR ("01;35") } /* do: Door: bright magenta */
556 /* FIXME: comment */
557 static struct color_ext_type *color_ext_list = NULL;
559 /* Buffer for color sequences */
560 static char *color_buf;
562 /* Nonzero means to check for orphaned symbolic link, for displaying
563 colors. */
565 static int check_symlink_color;
567 /* Nonzero means mention the inode number of each file. -i */
569 static int print_inode;
571 /* Nonzero means when a symbolic link is found, display info on
572 the file linked to. -L */
574 static int trace_links;
576 /* Nonzero means when a directory is found, display info on its
577 contents. -R */
579 static int trace_dirs;
581 /* Nonzero means when an argument is a directory name, display info
582 on it itself. -d */
584 static int immediate_dirs;
586 /* Nonzero means don't omit files whose names start with `.'. -A */
588 static int all_files;
590 /* Nonzero means don't omit files `.' and `..'
591 This flag implies `all_files'. -a */
593 static int really_all_files;
595 /* A linked list of shell-style globbing patterns. If a non-argument
596 file name matches any of these patterns, it is omitted.
597 Controlled by -I. Multiple -I options accumulate.
598 The -B option adds `*~' and `.*~' to this list. */
600 struct ignore_pattern
602 const char *pattern;
603 struct ignore_pattern *next;
606 static struct ignore_pattern *ignore_patterns;
608 /* Nonzero means output nongraphic chars in file names as `?'.
609 (-q, --hide-control-chars)
610 qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
611 independent. The algorithm is: first, obey the quoting style to get a
612 string representing the file name; then, if qmark_funny_chars is set,
613 replace all nonprintable chars in that string with `?'. It's necessary
614 to replace nonprintable chars even in quoted strings, because we don't
615 want to mess up the terminal if control chars get sent to it, and some
616 quoting methods pass through control chars as-is. */
617 static int qmark_funny_chars;
619 /* Quoting options for file and dir name output. */
621 static struct quoting_options *filename_quoting_options;
622 static struct quoting_options *dirname_quoting_options;
624 /* The number of chars per hardware tab stop. Setting this to zero
625 inhibits the use of TAB characters for separating columns. -T */
626 static int tabsize;
628 /* Nonzero means we are listing the working directory because no
629 non-option arguments were given. */
631 static int dir_defaulted;
633 /* Nonzero means print each directory name before listing it. */
635 static int print_dir_name;
637 /* The line length to use for breaking lines in many-per-line format.
638 Can be set with -w. */
640 static int line_length;
642 /* If nonzero, the file listing format requires that stat be called on
643 each file. */
645 static int format_needs_stat;
647 /* Similar to `format_needs_stat', but set if only the file type is
648 needed. */
650 static int format_needs_type;
652 /* strftime formats for non-recent and recent files, respectively, in
653 -l output. */
655 static char const *long_time_format[2];
657 /* The exit status to use if we don't get any fatal errors. */
659 static int exit_status;
661 /* For long options that have no equivalent short option, use a
662 non-character as a pseudo short option, starting with CHAR_MAX + 1. */
663 enum
665 BLOCK_SIZE_OPTION = CHAR_MAX + 1,
666 COLOR_OPTION,
667 FORMAT_OPTION,
668 FULL_TIME,
669 INDICATOR_STYLE_OPTION,
670 QUOTING_STYLE_OPTION,
671 SHOW_CONTROL_CHARS_OPTION,
672 SORT_OPTION,
673 TIME_OPTION
676 static struct option const long_options[] =
678 {"all", no_argument, 0, 'a'},
679 {"escape", no_argument, 0, 'b'},
680 {"directory", no_argument, 0, 'd'},
681 {"dired", no_argument, 0, 'D'},
682 {"full-time", no_argument, 0, FULL_TIME},
683 {"human-readable", no_argument, 0, 'h'},
684 {"inode", no_argument, 0, 'i'},
685 {"kilobytes", no_argument, 0, 'k'},
686 {"numeric-uid-gid", no_argument, 0, 'n'},
687 {"no-group", no_argument, 0, 'G'},
688 {"hide-control-chars", no_argument, 0, 'q'},
689 {"reverse", no_argument, 0, 'r'},
690 {"size", no_argument, 0, 's'},
691 {"width", required_argument, 0, 'w'},
692 {"almost-all", no_argument, 0, 'A'},
693 {"ignore-backups", no_argument, 0, 'B'},
694 {"classify", no_argument, 0, 'F'},
695 {"file-type", no_argument, 0, 'p'},
696 {"si", no_argument, 0, 'H'},
697 {"ignore", required_argument, 0, 'I'},
698 {"indicator-style", required_argument, 0, INDICATOR_STYLE_OPTION},
699 {"dereference", no_argument, 0, 'L'},
700 {"literal", no_argument, 0, 'N'},
701 {"quote-name", no_argument, 0, 'Q'},
702 {"quoting-style", required_argument, 0, QUOTING_STYLE_OPTION},
703 {"recursive", no_argument, 0, 'R'},
704 {"format", required_argument, 0, FORMAT_OPTION},
705 {"show-control-chars", no_argument, 0, SHOW_CONTROL_CHARS_OPTION},
706 {"sort", required_argument, 0, SORT_OPTION},
707 {"tabsize", required_argument, 0, 'T'},
708 {"time", required_argument, 0, TIME_OPTION},
709 {"color", optional_argument, 0, COLOR_OPTION},
710 {"block-size", required_argument, 0, BLOCK_SIZE_OPTION},
711 {GETOPT_HELP_OPTION_DECL},
712 {GETOPT_VERSION_OPTION_DECL},
713 {NULL, 0, NULL, 0}
716 static char const *const format_args[] =
718 "verbose", "long", "commas", "horizontal", "across",
719 "vertical", "single-column", 0
722 static enum format const format_types[] =
724 long_format, long_format, with_commas, horizontal, horizontal,
725 many_per_line, one_per_line
728 static char const *const sort_args[] =
730 "none", "time", "size", "extension", "version", 0
733 static enum sort_type const sort_types[] =
735 sort_none, sort_time, sort_size, sort_extension, sort_version
738 static char const *const time_args[] =
740 "atime", "access", "use", "ctime", "status", 0
743 static enum time_type const time_types[] =
745 time_atime, time_atime, time_atime, time_ctime, time_ctime
748 static char const *const color_args[] =
750 /* force and none are for compatibility with another color-ls version */
751 "always", "yes", "force",
752 "never", "no", "none",
753 "auto", "tty", "if-tty", 0
756 static enum color_type const color_types[] =
758 color_always, color_always, color_always,
759 color_never, color_never, color_never,
760 color_if_tty, color_if_tty, color_if_tty
763 /* Information about filling a column. */
764 struct column_info
766 int valid_len;
767 int line_len;
768 int *col_arr;
771 /* Array with information about column filledness. */
772 static struct column_info *column_info;
774 /* Maximum number of columns ever possible for this display. */
775 static int max_idx;
777 /* The minimum width of a colum is 3: 1 character for the name and 2
778 for the separating white space. */
779 #define MIN_COLUMN_WIDTH 3
782 /* This zero-based index is used solely with the --dired option.
783 When that option is in effect, this counter is incremented for each
784 character of output generated by this program so that the beginning
785 and ending indices (in that output) of every file name can be recorded
786 and later output themselves. */
787 static size_t dired_pos;
789 #define DIRED_PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
791 /* Write S to STREAM and increment DIRED_POS by S_LEN. */
792 #define DIRED_FPUTS(s, stream, s_len) \
793 do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
795 /* Like DIRED_FPUTS, but for use when S is a literal string. */
796 #define DIRED_FPUTS_LITERAL(s, stream) \
797 do {fputs ((s), (stream)); dired_pos += sizeof((s)) - 1;} while (0)
799 #define DIRED_INDENT() \
800 do \
802 /* FIXME: remove the `&& format == long_format' clause. */ \
803 if (dired && format == long_format) \
804 DIRED_FPUTS_LITERAL (" ", stdout); \
806 while (0)
808 /* With --dired, store pairs of beginning and ending indices of filenames. */
809 static struct obstack dired_obstack;
811 /* With --dired, store pairs of beginning and ending indices of any
812 directory names that appear as headers (just before `total' line)
813 for lists of directory entries. Such directory names are seen when
814 listing hierarchies using -R and when a directory is listed with at
815 least one other command line argument. */
816 static struct obstack subdired_obstack;
818 /* Save the current index on the specified obstack, OBS. */
819 #define PUSH_CURRENT_DIRED_POS(obs) \
820 do \
822 /* FIXME: remove the `&& format == long_format' clause. */ \
823 if (dired && format == long_format) \
824 obstack_grow ((obs), &dired_pos, sizeof (dired_pos)); \
826 while (0)
829 /* Write to standard output PREFIX, followed by the quoting style and
830 a space-separated list of the integers stored in OS all on one line. */
832 static void
833 dired_dump_obstack (const char *prefix, struct obstack *os)
835 int n_pos;
837 n_pos = obstack_object_size (os) / sizeof (dired_pos);
838 if (n_pos > 0)
840 int i;
841 size_t *pos;
843 pos = (size_t *) obstack_finish (os);
844 fputs (prefix, stdout);
845 for (i = 0; i < n_pos; i++)
846 printf (" %d", (int) pos[i]);
847 fputs ("\n", stdout);
852 main (int argc, char **argv)
854 register int i;
855 register struct pending *thispend;
857 program_name = argv[0];
858 setlocale (LC_ALL, "");
859 bindtextdomain (PACKAGE, LOCALEDIR);
860 textdomain (PACKAGE);
862 atexit (close_stdout);
864 #define N_ENTRIES(Array) (sizeof Array / sizeof *(Array))
865 assert (N_ENTRIES (color_indicator) + 1 == N_ENTRIES (indicator_name));
867 exit_status = 0;
868 dir_defaulted = 1;
869 print_dir_name = 1;
870 pending_dirs = 0;
872 i = decode_switches (argc, argv);
874 if (print_with_color)
876 parse_ls_color ();
877 prep_non_filename_text ();
878 /* Avoid following symbolic links when possible. */
879 if (color_indicator[C_ORPHAN].string != NULL
880 || (color_indicator[C_MISSING].string != NULL
881 && format == long_format))
882 check_symlink_color = 1;
885 format_needs_stat = sort_type == sort_time || sort_type == sort_size
886 || format == long_format
887 || trace_links || trace_dirs || print_block_size || print_inode;
888 format_needs_type = (format_needs_stat == 0
889 && (print_with_color || indicator_style != none));
891 if (dired && format == long_format)
893 obstack_init (&dired_obstack);
894 obstack_init (&subdired_obstack);
897 nfiles = 100;
898 files = (struct fileinfo *) xmalloc (sizeof (struct fileinfo) * nfiles);
899 files_index = 0;
901 clear_files ();
903 if (i < argc)
904 dir_defaulted = 0;
905 for (; i < argc; i++)
907 gobble_file (argv[i], unknown, 1, "");
910 if (dir_defaulted)
912 if (immediate_dirs)
913 gobble_file (".", directory, 1, "");
914 else
915 queue_directory (".", 0);
918 if (files_index)
920 sort_files ();
921 if (!immediate_dirs)
922 extract_dirs_from_files ("", 0);
923 /* `files_index' might be zero now. */
925 if (files_index)
927 print_current_files ();
928 if (pending_dirs)
929 DIRED_PUTCHAR ('\n');
931 else if (pending_dirs && pending_dirs->next == 0)
932 print_dir_name = 0;
934 while (pending_dirs)
936 thispend = pending_dirs;
937 pending_dirs = pending_dirs->next;
938 print_dir (thispend->name, thispend->realname);
939 free (thispend->name);
940 if (thispend->realname)
941 free (thispend->realname);
942 free (thispend);
943 print_dir_name = 1;
946 if (dired && format == long_format)
948 /* No need to free these since we're about to exit. */
949 dired_dump_obstack ("//DIRED//", &dired_obstack);
950 dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
951 printf ("//DIRED-OPTIONS// --quoting-style=%s\n",
952 ARGMATCH_TO_ARGUMENT (filename_quoting_options,
953 quoting_style_args, quoting_style_vals));
956 /* Restore default color before exiting */
957 if (print_with_color)
959 put_indicator (&color_indicator[C_LEFT]);
960 put_indicator (&color_indicator[C_RIGHT]);
963 exit (exit_status);
966 /* Set all the option flags according to the switches specified.
967 Return the index of the first non-option argument. */
969 static int
970 decode_switches (int argc, char **argv)
972 register char const *p;
973 int c;
974 int i;
975 long int tmp_long;
977 /* Record whether there is an option specifying sort type. */
978 int sort_type_specified = 0;
980 qmark_funny_chars = 0;
982 /* initialize all switches to default settings */
984 switch (ls_mode)
986 case LS_MULTI_COL:
987 /* This is for the `dir' program. */
988 format = many_per_line;
989 set_quoting_style (NULL, escape_quoting_style);
990 break;
992 case LS_LONG_FORMAT:
993 /* This is for the `vdir' program. */
994 format = long_format;
995 set_quoting_style (NULL, escape_quoting_style);
996 break;
998 case LS_LS:
999 /* This is for the `ls' program. */
1000 if (isatty (STDOUT_FILENO))
1002 format = many_per_line;
1003 /* See description of qmark_funny_chars, above. */
1004 qmark_funny_chars = 1;
1006 else
1008 format = one_per_line;
1009 qmark_funny_chars = 0;
1011 break;
1013 default:
1014 abort ();
1017 time_type = time_mtime;
1018 full_time = 0;
1019 sort_type = sort_name;
1020 sort_reverse = 0;
1021 numeric_ids = 0;
1022 print_block_size = 0;
1023 indicator_style = none;
1024 print_inode = 0;
1025 trace_links = 0;
1026 trace_dirs = 0;
1027 immediate_dirs = 0;
1028 all_files = 0;
1029 really_all_files = 0;
1030 ignore_patterns = 0;
1032 /* FIXME: Shouldn't we complain on wrong values? */
1033 if ((p = getenv ("QUOTING_STYLE"))
1034 && 0 <= (i = ARGCASEMATCH (p, quoting_style_args, quoting_style_vals)))
1035 set_quoting_style (NULL, quoting_style_vals[i]);
1037 human_block_size (getenv ("LS_BLOCK_SIZE"), 0, &output_block_size);
1039 line_length = 80;
1040 if ((p = getenv ("COLUMNS")) && *p)
1042 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
1043 && 0 < tmp_long && tmp_long <= INT_MAX)
1045 line_length = (int) tmp_long;
1047 else
1049 error (0, 0,
1050 _("ignoring invalid width in environment variable COLUMNS: %s"),
1051 quotearg (p));
1055 #ifdef TIOCGWINSZ
1057 struct winsize ws;
1059 if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
1060 line_length = ws.ws_col;
1062 #endif
1064 /* Using the TABSIZE environment variable is not POSIX-approved.
1065 Ignore it when POSIXLY_CORRECT is set. */
1066 tabsize = 8;
1067 if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
1069 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
1070 && 0 <= tmp_long && tmp_long <= INT_MAX)
1072 tabsize = (int) tmp_long;
1074 else
1076 error (0, 0,
1077 _("ignoring invalid tab size in environment variable TABSIZE: %s"),
1078 quotearg (p));
1082 while ((c = getopt_long (argc, argv,
1083 "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
1084 long_options, NULL)) != -1)
1086 switch (c)
1088 case 0:
1089 break;
1091 case 'a':
1092 all_files = 1;
1093 really_all_files = 1;
1094 break;
1096 case 'b':
1097 set_quoting_style (NULL, escape_quoting_style);
1098 break;
1100 case 'c':
1101 time_type = time_ctime;
1102 break;
1104 case 'd':
1105 immediate_dirs = 1;
1106 break;
1108 case 'f':
1109 /* Same as enabling -a -U and disabling -l -s. */
1110 all_files = 1;
1111 really_all_files = 1;
1112 sort_type = sort_none;
1113 sort_type_specified = 1;
1114 /* disable -l */
1115 if (format == long_format)
1116 format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
1117 print_block_size = 0; /* disable -s */
1118 print_with_color = 0; /* disable --color */
1119 break;
1121 case 'g':
1122 /* No effect. For BSD compatibility. */
1123 break;
1125 case 'h':
1126 output_block_size = -1024;
1127 break;
1129 case 'H':
1130 output_block_size = -1000;
1131 break;
1133 case 'i':
1134 print_inode = 1;
1135 break;
1137 case 'k':
1138 output_block_size = 1024;
1139 break;
1141 case 'l':
1142 format = long_format;
1143 break;
1145 case 'm':
1146 format = with_commas;
1147 break;
1149 case 'n':
1150 numeric_ids = 1;
1151 break;
1153 case 'o': /* Just like -l, but don't display group info. */
1154 format = long_format;
1155 inhibit_group = 1;
1156 break;
1158 case 'p':
1159 indicator_style = file_type;
1160 break;
1162 case 'q':
1163 qmark_funny_chars = 1;
1164 break;
1166 case 'r':
1167 sort_reverse = 1;
1168 break;
1170 case 's':
1171 print_block_size = 1;
1172 break;
1174 case 't':
1175 sort_type = sort_time;
1176 sort_type_specified = 1;
1177 break;
1179 case 'u':
1180 time_type = time_atime;
1181 break;
1183 case 'v':
1184 sort_type = sort_version;
1185 sort_type_specified = 1;
1186 break;
1188 case 'w':
1189 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1190 || tmp_long <= 0 || tmp_long > INT_MAX)
1191 error (EXIT_FAILURE, 0, _("invalid line width: %s"),
1192 quotearg (optarg));
1193 line_length = (int) tmp_long;
1194 break;
1196 case 'x':
1197 format = horizontal;
1198 break;
1200 case 'A':
1201 really_all_files = 0;
1202 all_files = 1;
1203 break;
1205 case 'B':
1206 add_ignore_pattern ("*~");
1207 add_ignore_pattern (".*~");
1208 break;
1210 case 'C':
1211 format = many_per_line;
1212 break;
1214 case 'D':
1215 dired = 1;
1216 break;
1218 case 'F':
1219 indicator_style = classify;
1220 break;
1222 case 'G': /* inhibit display of group info */
1223 inhibit_group = 1;
1224 break;
1226 case 'I':
1227 add_ignore_pattern (optarg);
1228 break;
1230 case 'L':
1231 trace_links = 1;
1232 break;
1234 case 'N':
1235 set_quoting_style (NULL, literal_quoting_style);
1236 break;
1238 case 'Q':
1239 set_quoting_style (NULL, c_quoting_style);
1240 break;
1242 case 'R':
1243 trace_dirs = 1;
1244 break;
1246 case 'S':
1247 sort_type = sort_size;
1248 sort_type_specified = 1;
1249 break;
1251 case 'T':
1252 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1253 || tmp_long < 0 || tmp_long > INT_MAX)
1254 error (EXIT_FAILURE, 0, _("invalid tab size: %s"),
1255 quotearg (optarg));
1256 tabsize = (int) tmp_long;
1257 break;
1259 case 'U':
1260 sort_type = sort_none;
1261 sort_type_specified = 1;
1262 break;
1264 case 'X':
1265 sort_type = sort_extension;
1266 sort_type_specified = 1;
1267 break;
1269 case '1':
1270 format = one_per_line;
1271 break;
1273 case SORT_OPTION:
1274 sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
1275 sort_type_specified = 1;
1276 break;
1278 case TIME_OPTION:
1279 time_type = XARGMATCH ("--time", optarg, time_args, time_types);
1280 break;
1282 case FORMAT_OPTION:
1283 format = XARGMATCH ("--format", optarg, format_args, format_types);
1284 break;
1286 case FULL_TIME:
1287 format = long_format;
1288 full_time = 1;
1289 break;
1291 case COLOR_OPTION:
1292 if (optarg)
1293 i = XARGMATCH ("--color", optarg, color_args, color_types);
1294 else
1295 /* Using --color with no argument is equivalent to using
1296 --color=always. */
1297 i = color_always;
1299 print_with_color = (i == color_always
1300 || (i == color_if_tty
1301 && isatty (STDOUT_FILENO)));
1303 if (print_with_color)
1305 /* Don't use TAB characters in output. Some terminal
1306 emulators can't handle the combination of tabs and
1307 color codes on the same line. */
1308 tabsize = 0;
1310 break;
1312 case INDICATOR_STYLE_OPTION:
1313 indicator_style = XARGMATCH ("--indicator-style", optarg,
1314 indicator_style_args,
1315 indicator_style_types);
1316 break;
1318 case QUOTING_STYLE_OPTION:
1319 set_quoting_style (NULL,
1320 XARGMATCH ("--quoting-style", optarg,
1321 quoting_style_args,
1322 quoting_style_vals));
1323 break;
1325 case SHOW_CONTROL_CHARS_OPTION:
1326 qmark_funny_chars = 0;
1327 break;
1329 case BLOCK_SIZE_OPTION:
1330 human_block_size (optarg, 1, &output_block_size);
1331 break;
1333 case_GETOPT_HELP_CHAR;
1335 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1337 default:
1338 usage (EXIT_FAILURE);
1342 filename_quoting_options = clone_quoting_options (NULL);
1343 if (get_quoting_style (filename_quoting_options) == escape_quoting_style)
1344 set_char_quoting (filename_quoting_options, ' ', 1);
1345 if (indicator_style != none)
1346 for (p = "*=@|" + (int) indicator_style - 1; *p; p++)
1347 set_char_quoting (filename_quoting_options, *p, 1);
1349 dirname_quoting_options = clone_quoting_options (NULL);
1350 set_char_quoting (dirname_quoting_options, ':', 1);
1352 /* If -c or -u is specified and not -l (or any other option that implies -l),
1353 and no sort-type was specified, then sort by the ctime (-c) or atime (-u).
1354 The behavior of ls when using either -c or -u but with neither -l nor -t
1355 appears to be unspecified by POSIX. So, with GNU ls, `-u' alone means
1356 sort by atime (this is the one that's not specified by the POSIX spec),
1357 -lu means show atime and sort by name, -lut means show atime and sort
1358 by atime. */
1360 if ((time_type == time_ctime || time_type == time_atime)
1361 && !sort_type_specified && format != long_format)
1363 sort_type = sort_time;
1366 if (format == long_format)
1368 if (full_time)
1369 long_time_format[0] = long_time_format[1] =
1370 dcgettext (NULL, "%a %b %d %H:%M:%S %Y", LC_TIME);
1371 else
1373 long_time_format[0] = dcgettext (NULL, "%b %e %Y", LC_TIME);
1374 long_time_format[1] = dcgettext (NULL, "%b %e %H:%M", LC_TIME);
1378 return optind;
1381 /* Parse a string as part of the LS_COLORS variable; this may involve
1382 decoding all kinds of escape characters. If equals_end is set an
1383 unescaped equal sign ends the string, otherwise only a : or \0
1384 does. Returns the number of characters output, or -1 on failure.
1386 The resulting string is *not* null-terminated, but may contain
1387 embedded nulls.
1389 Note that both dest and src are char **; on return they point to
1390 the first free byte after the array and the character that ended
1391 the input string, respectively. */
1393 static int
1394 get_funky_string (char **dest, const char **src, int equals_end)
1396 int num; /* For numerical codes */
1397 int count; /* Something to count with */
1398 enum {
1399 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
1400 } state;
1401 const char *p;
1402 char *q;
1404 p = *src; /* We don't want to double-indirect */
1405 q = *dest; /* the whole darn time. */
1407 count = 0; /* No characters counted in yet. */
1408 num = 0;
1410 state = ST_GND; /* Start in ground state. */
1411 while (state < ST_END)
1413 switch (state)
1415 case ST_GND: /* Ground state (no escapes) */
1416 switch (*p)
1418 case ':':
1419 case '\0':
1420 state = ST_END; /* End of string */
1421 break;
1422 case '\\':
1423 state = ST_BACKSLASH; /* Backslash scape sequence */
1424 ++p;
1425 break;
1426 case '^':
1427 state = ST_CARET; /* Caret escape */
1428 ++p;
1429 break;
1430 case '=':
1431 if (equals_end)
1433 state = ST_END; /* End */
1434 break;
1436 /* else fall through */
1437 default:
1438 *(q++) = *(p++);
1439 ++count;
1440 break;
1442 break;
1444 case ST_BACKSLASH: /* Backslash escaped character */
1445 switch (*p)
1447 case '0':
1448 case '1':
1449 case '2':
1450 case '3':
1451 case '4':
1452 case '5':
1453 case '6':
1454 case '7':
1455 state = ST_OCTAL; /* Octal sequence */
1456 num = *p - '0';
1457 break;
1458 case 'x':
1459 case 'X':
1460 state = ST_HEX; /* Hex sequence */
1461 num = 0;
1462 break;
1463 case 'a': /* Bell */
1464 num = 7; /* Not all C compilers know what \a means */
1465 break;
1466 case 'b': /* Backspace */
1467 num = '\b';
1468 break;
1469 case 'e': /* Escape */
1470 num = 27;
1471 break;
1472 case 'f': /* Form feed */
1473 num = '\f';
1474 break;
1475 case 'n': /* Newline */
1476 num = '\n';
1477 break;
1478 case 'r': /* Carriage return */
1479 num = '\r';
1480 break;
1481 case 't': /* Tab */
1482 num = '\t';
1483 break;
1484 case 'v': /* Vtab */
1485 num = '\v';
1486 break;
1487 case '?': /* Delete */
1488 num = 127;
1489 break;
1490 case '_': /* Space */
1491 num = ' ';
1492 break;
1493 case '\0': /* End of string */
1494 state = ST_ERROR; /* Error! */
1495 break;
1496 default: /* Escaped character like \ ^ : = */
1497 num = *p;
1498 break;
1500 if (state == ST_BACKSLASH)
1502 *(q++) = num;
1503 ++count;
1504 state = ST_GND;
1506 ++p;
1507 break;
1509 case ST_OCTAL: /* Octal sequence */
1510 if (*p < '0' || *p > '7')
1512 *(q++) = num;
1513 ++count;
1514 state = ST_GND;
1516 else
1517 num = (num << 3) + (*(p++) - '0');
1518 break;
1520 case ST_HEX: /* Hex sequence */
1521 switch (*p)
1523 case '0':
1524 case '1':
1525 case '2':
1526 case '3':
1527 case '4':
1528 case '5':
1529 case '6':
1530 case '7':
1531 case '8':
1532 case '9':
1533 num = (num << 4) + (*(p++) - '0');
1534 break;
1535 case 'a':
1536 case 'b':
1537 case 'c':
1538 case 'd':
1539 case 'e':
1540 case 'f':
1541 num = (num << 4) + (*(p++) - 'a') + 10;
1542 break;
1543 case 'A':
1544 case 'B':
1545 case 'C':
1546 case 'D':
1547 case 'E':
1548 case 'F':
1549 num = (num << 4) + (*(p++) - 'A') + 10;
1550 break;
1551 default:
1552 *(q++) = num;
1553 ++count;
1554 state = ST_GND;
1555 break;
1557 break;
1559 case ST_CARET: /* Caret escape */
1560 state = ST_GND; /* Should be the next state... */
1561 if (*p >= '@' && *p <= '~')
1563 *(q++) = *(p++) & 037;
1564 ++count;
1566 else if (*p == '?')
1568 *(q++) = 127;
1569 ++count;
1571 else
1572 state = ST_ERROR;
1573 break;
1575 default:
1576 abort ();
1580 *dest = q;
1581 *src = p;
1583 return state == ST_ERROR ? -1 : count;
1586 static void
1587 parse_ls_color (void)
1589 const char *p; /* Pointer to character being parsed */
1590 char *buf; /* color_buf buffer pointer */
1591 int state; /* State of parser */
1592 int ind_no; /* Indicator number */
1593 char label[3]; /* Indicator label */
1594 struct color_ext_type *ext; /* Extension we are working on */
1596 if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
1597 return;
1599 ext = NULL;
1600 strcpy (label, "??");
1602 /* This is an overly conservative estimate, but any possible
1603 LS_COLORS string will *not* generate a color_buf longer than
1604 itself, so it is a safe way of allocating a buffer in
1605 advance. */
1606 buf = color_buf = xstrdup (p);
1608 state = 1;
1609 while (state > 0)
1611 switch (state)
1613 case 1: /* First label character */
1614 switch (*p)
1616 case ':':
1617 ++p;
1618 break;
1620 case '*':
1621 /* Allocate new extension block and add to head of
1622 linked list (this way a later definition will
1623 override an earlier one, which can be useful for
1624 having terminal-specific defs override global). */
1626 ext = (struct color_ext_type *)
1627 xmalloc (sizeof (struct color_ext_type));
1628 ext->next = color_ext_list;
1629 color_ext_list = ext;
1631 ++p;
1632 ext->ext.string = buf;
1634 state = (ext->ext.len =
1635 get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
1636 break;
1638 case '\0':
1639 state = 0; /* Done! */
1640 break;
1642 default: /* Assume it is file type label */
1643 label[0] = *(p++);
1644 state = 2;
1645 break;
1647 break;
1649 case 2: /* Second label character */
1650 if (*p)
1652 label[1] = *(p++);
1653 state = 3;
1655 else
1656 state = -1; /* Error */
1657 break;
1659 case 3: /* Equal sign after indicator label */
1660 state = -1; /* Assume failure... */
1661 if (*(p++) == '=')/* It *should* be... */
1663 for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
1665 if (STREQ (label, indicator_name[ind_no]))
1667 color_indicator[ind_no].string = buf;
1668 state = ((color_indicator[ind_no].len =
1669 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
1670 break;
1673 if (state == -1)
1674 error (0, 0, _("unrecognized prefix: %s"), quotearg (label));
1676 break;
1678 case 4: /* Equal sign after *.ext */
1679 if (*(p++) == '=')
1681 ext->seq.string = buf;
1682 state = (ext->seq.len =
1683 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
1685 else
1686 state = -1;
1687 break;
1691 if (state < 0)
1693 struct color_ext_type *e;
1694 struct color_ext_type *e2;
1696 error (0, 0,
1697 _("unparsable value for LS_COLORS environment variable"));
1698 free (color_buf);
1699 for (e = color_ext_list; e != NULL; /* empty */)
1701 e2 = e;
1702 e = e->next;
1703 free (e2);
1705 print_with_color = 0;
1708 if (color_indicator[C_LINK].len == 6
1709 && !strncmp (color_indicator[C_LINK].string, "target", 6))
1710 color_symlink_as_referent = 1;
1713 /* Request that the directory named `name' have its contents listed later.
1714 If `realname' is nonzero, it will be used instead of `name' when the
1715 directory name is printed. This allows symbolic links to directories
1716 to be treated as regular directories but still be listed under their
1717 real names. */
1719 static void
1720 queue_directory (const char *name, const char *realname)
1722 struct pending *new;
1724 new = (struct pending *) xmalloc (sizeof (struct pending));
1725 new->next = pending_dirs;
1726 pending_dirs = new;
1727 new->name = xstrdup (name);
1728 if (realname)
1729 new->realname = xstrdup (realname);
1730 else
1731 new->realname = 0;
1734 /* Read directory `name', and list the files in it.
1735 If `realname' is nonzero, print its name instead of `name';
1736 this is used for symbolic links to directories. */
1738 static void
1739 print_dir (const char *name, const char *realname)
1741 register DIR *reading;
1742 register struct dirent *next;
1743 register uintmax_t total_blocks = 0;
1745 errno = 0;
1746 reading = opendir (name);
1747 if (!reading)
1749 error (0, errno, "%s", quotearg_colon (name));
1750 exit_status = 1;
1751 return;
1754 /* Read the directory entries, and insert the subfiles into the `files'
1755 table. */
1757 clear_files ();
1759 while ((next = readdir (reading)) != NULL)
1760 if (file_interesting (next))
1762 enum filetype type = unknown;
1764 #if HAVE_STRUCT_DIRENT_D_TYPE
1765 if (next->d_type == DT_DIR || next->d_type == DT_CHR
1766 || next->d_type == DT_BLK || next->d_type == DT_SOCK
1767 || next->d_type == DT_FIFO)
1768 type = next->d_type;
1769 #endif
1770 total_blocks += gobble_file (next->d_name, type, 0, name);
1773 if (CLOSEDIR (reading))
1775 error (0, errno, "%s", quotearg_colon (name));
1776 exit_status = 1;
1777 /* Don't return; print whatever we got. */
1780 /* Sort the directory contents. */
1781 sort_files ();
1783 /* If any member files are subdirectories, perhaps they should have their
1784 contents listed rather than being mentioned here as files. */
1786 if (trace_dirs)
1787 extract_dirs_from_files (name, 1);
1789 if (trace_dirs || print_dir_name)
1791 DIRED_INDENT ();
1792 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1793 dired_pos += quote_name (stdout, realname ? realname : name,
1794 dirname_quoting_options);
1795 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1796 DIRED_FPUTS_LITERAL (":\n", stdout);
1799 if (format == long_format || print_block_size)
1801 const char *p;
1802 char buf[LONGEST_HUMAN_READABLE + 1];
1804 DIRED_INDENT ();
1805 p = _("total");
1806 DIRED_FPUTS (p, stdout, strlen (p));
1807 DIRED_PUTCHAR (' ');
1808 p = human_readable_inexact (total_blocks, buf, ST_NBLOCKSIZE,
1809 output_block_size, human_ceiling);
1810 DIRED_FPUTS (p, stdout, strlen (p));
1811 DIRED_PUTCHAR ('\n');
1814 if (files_index)
1815 print_current_files ();
1817 if (pending_dirs)
1818 DIRED_PUTCHAR ('\n');
1821 /* Add `pattern' to the list of patterns for which files that match are
1822 not listed. */
1824 static void
1825 add_ignore_pattern (const char *pattern)
1827 register struct ignore_pattern *ignore;
1829 ignore = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
1830 ignore->pattern = pattern;
1831 /* Add it to the head of the linked list. */
1832 ignore->next = ignore_patterns;
1833 ignore_patterns = ignore;
1836 /* Return nonzero if the file in `next' should be listed. */
1838 static int
1839 file_interesting (const struct dirent *next)
1841 register struct ignore_pattern *ignore;
1843 for (ignore = ignore_patterns; ignore; ignore = ignore->next)
1844 if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
1845 return 0;
1847 if (really_all_files
1848 || next->d_name[0] != '.'
1849 || (all_files
1850 && next->d_name[1] != '\0'
1851 && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
1852 return 1;
1854 return 0;
1857 /* Enter and remove entries in the table `files'. */
1859 /* Empty the table of files. */
1861 static void
1862 clear_files (void)
1864 register int i;
1866 for (i = 0; i < files_index; i++)
1868 free (files[i].name);
1869 if (files[i].linkname)
1870 free (files[i].linkname);
1873 files_index = 0;
1874 block_size_size = 4;
1877 /* Add a file to the current table of files.
1878 Verify that the file exists, and print an error message if it does not.
1879 Return the number of blocks that the file occupies. */
1881 static uintmax_t
1882 gobble_file (const char *name, enum filetype type, int explicit_arg,
1883 const char *dirname)
1885 register uintmax_t blocks;
1886 register char *path;
1888 if (files_index == nfiles)
1890 nfiles *= 2;
1891 files = (struct fileinfo *) xrealloc ((char *) files,
1892 sizeof (*files) * nfiles);
1895 files[files_index].linkname = 0;
1896 files[files_index].linkmode = 0;
1897 files[files_index].linkok = 0;
1899 /* FIXME: this use of ls: `mkdir a; touch a/{b,c,d}; ls -R a'
1900 shouldn't require that ls stat b, c, and d -- at least
1901 not on systems with usable d_type. The problem is that
1902 format_needs_stat is set, because of the -R. */
1903 if (explicit_arg || format_needs_stat
1904 || (format_needs_type && type == unknown))
1906 /* `path' is the absolute pathname of this file. */
1907 int val;
1909 if (name[0] == '/' || dirname[0] == 0)
1910 path = (char *) name;
1911 else
1913 path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
1914 attach (path, dirname, name);
1917 val = (trace_links
1918 ? stat (path, &files[files_index].stat)
1919 : lstat (path, &files[files_index].stat));
1921 if (val < 0)
1923 error (0, errno, "%s", quotearg_colon (path));
1924 exit_status = 1;
1925 return 0;
1928 #if USE_ACL
1929 if (format == long_format)
1930 files[files_index].have_acl =
1931 (! S_ISLNK (files[files_index].stat.st_mode)
1932 && 4 < acl (path, GETACLCNT, 0, NULL));
1933 #endif
1935 if (S_ISLNK (files[files_index].stat.st_mode)
1936 && (explicit_arg || format == long_format || check_symlink_color))
1938 char *linkpath;
1939 struct stat linkstats;
1941 get_link_name (path, &files[files_index]);
1942 linkpath = make_link_path (path, files[files_index].linkname);
1944 /* Avoid following symbolic links when possible, ie, when
1945 they won't be traced and when no indicator is needed. */
1946 if (linkpath
1947 && ((explicit_arg && format != long_format)
1948 || indicator_style != none
1949 || check_symlink_color)
1950 && stat (linkpath, &linkstats) == 0)
1952 files[files_index].linkok = 1;
1954 /* Symbolic links to directories that are mentioned on the
1955 command line are automatically traced if not being
1956 listed as files. */
1957 if (explicit_arg && format != long_format
1958 && S_ISDIR (linkstats.st_mode))
1960 /* Substitute the linked-to directory's name, but
1961 save the real name in `linkname' for printing. */
1962 if (!immediate_dirs)
1964 const char *tempname = name;
1965 name = linkpath;
1966 linkpath = files[files_index].linkname;
1967 files[files_index].linkname = (char *) tempname;
1969 files[files_index].stat = linkstats;
1971 else
1973 /* Get the linked-to file's mode for the filetype indicator
1974 in long listings. */
1975 files[files_index].linkmode = linkstats.st_mode;
1976 files[files_index].linkok = 1;
1979 if (linkpath)
1980 free (linkpath);
1983 if (S_ISLNK (files[files_index].stat.st_mode))
1984 files[files_index].filetype = symbolic_link;
1985 else if (S_ISDIR (files[files_index].stat.st_mode))
1987 if (explicit_arg && !immediate_dirs)
1988 files[files_index].filetype = arg_directory;
1989 else
1990 files[files_index].filetype = directory;
1992 else
1993 files[files_index].filetype = normal;
1995 blocks = ST_NBLOCKS (files[files_index].stat);
1997 char buf[LONGEST_HUMAN_READABLE + 1];
1998 int len = strlen (human_readable_inexact (blocks, buf, ST_NBLOCKSIZE,
1999 output_block_size,
2000 human_ceiling));
2001 if (block_size_size < len)
2002 block_size_size = len < 7 ? len : 7;
2005 else
2007 files[files_index].filetype = type;
2008 #if HAVE_STRUCT_DIRENT_D_TYPE
2009 files[files_index].stat.st_mode = DTTOIF (type);
2010 #endif
2011 blocks = 0;
2014 files[files_index].name = xstrdup (name);
2015 files_index++;
2017 return blocks;
2020 #if HAVE_SYMLINKS
2022 /* Put the name of the file that `filename' is a symbolic link to
2023 into the `linkname' field of `f'. */
2025 static void
2026 get_link_name (const char *filename, struct fileinfo *f)
2028 char *linkbuf;
2029 register int linksize;
2031 linkbuf = (char *) alloca (PATH_MAX + 2);
2032 /* Some automounters give incorrect st_size for mount points.
2033 I can't think of a good workaround for it, though. */
2034 linksize = readlink (filename, linkbuf, PATH_MAX + 1);
2035 if (linksize < 0)
2037 error (0, errno, "%s", quotearg_colon (filename));
2038 exit_status = 1;
2040 else
2042 linkbuf[linksize] = '\0';
2043 f->linkname = xstrdup (linkbuf);
2047 /* If `linkname' is a relative path and `path' contains one or more
2048 leading directories, return `linkname' with those directories
2049 prepended; otherwise, return a copy of `linkname'.
2050 If `linkname' is zero, return zero. */
2052 static char *
2053 make_link_path (const char *path, const char *linkname)
2055 char *linkbuf;
2056 int bufsiz;
2058 if (linkname == 0)
2059 return 0;
2061 if (*linkname == '/')
2062 return xstrdup (linkname);
2064 /* The link is to a relative path. Prepend any leading path
2065 in `path' to the link name. */
2066 linkbuf = strrchr (path, '/');
2067 if (linkbuf == 0)
2068 return xstrdup (linkname);
2070 bufsiz = linkbuf - path + 1;
2071 linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
2072 strncpy (linkbuf, path, bufsiz);
2073 strcpy (linkbuf + bufsiz, linkname);
2074 return linkbuf;
2076 #endif
2078 /* Return nonzero if base_name (NAME) ends in `.' or `..'
2079 This is so we don't try to recurse on `././././. ...' */
2081 static int
2082 basename_is_dot_or_dotdot (const char *name)
2084 char *base = base_name (name);
2085 return DOT_OR_DOTDOT (base);
2088 /* Remove any entries from `files' that are for directories,
2089 and queue them to be listed as directories instead.
2090 `dirname' is the prefix to prepend to each dirname
2091 to make it correct relative to ls's working dir.
2092 `recursive' is nonzero if we should not treat `.' and `..' as dirs.
2093 This is desirable when processing directories recursively. */
2095 static void
2096 extract_dirs_from_files (const char *dirname, int recursive)
2098 register int i, j;
2100 /* Queue the directories last one first, because queueing reverses the
2101 order. */
2102 for (i = files_index - 1; i >= 0; i--)
2103 if ((files[i].filetype == directory || files[i].filetype == arg_directory)
2104 && (!recursive || !basename_is_dot_or_dotdot (files[i].name)))
2106 if (files[i].name[0] == '/' || dirname[0] == 0)
2108 queue_directory (files[i].name, files[i].linkname);
2110 else
2112 char *path = path_concat (dirname, files[i].name, NULL);
2113 queue_directory (path, files[i].linkname);
2114 free (path);
2116 if (files[i].filetype == arg_directory)
2117 free (files[i].name);
2120 /* Now delete the directories from the table, compacting all the remaining
2121 entries. */
2123 for (i = 0, j = 0; i < files_index; i++)
2124 if (files[i].filetype != arg_directory)
2125 files[j++] = files[i];
2126 files_index = j;
2129 /* Sort the files now in the table. */
2131 static void
2132 sort_files (void)
2134 int (*func) ();
2136 switch (sort_type)
2138 case sort_none:
2139 return;
2140 case sort_time:
2141 switch (time_type)
2143 case time_ctime:
2144 func = sort_reverse ? rev_cmp_ctime : compare_ctime;
2145 break;
2146 case time_mtime:
2147 func = sort_reverse ? rev_cmp_mtime : compare_mtime;
2148 break;
2149 case time_atime:
2150 func = sort_reverse ? rev_cmp_atime : compare_atime;
2151 break;
2152 default:
2153 abort ();
2155 break;
2156 case sort_name:
2157 func = sort_reverse ? rev_cmp_name : compare_name;
2158 break;
2159 case sort_extension:
2160 func = sort_reverse ? rev_cmp_extension : compare_extension;
2161 break;
2162 case sort_size:
2163 func = sort_reverse ? rev_cmp_size : compare_size;
2164 break;
2165 case sort_version:
2166 func = sort_reverse ? rev_cmp_version : compare_version;
2167 break;
2168 default:
2169 abort ();
2172 qsort (files, files_index, sizeof (struct fileinfo), func);
2175 /* Comparison routines for sorting the files. */
2177 static int
2178 compare_ctime (const struct fileinfo *file1, const struct fileinfo *file2)
2180 int diff = CTIME_CMP (file2->stat, file1->stat);
2181 if (diff == 0)
2182 diff = strcoll (file1->name, file2->name);
2183 return diff;
2186 static int
2187 rev_cmp_ctime (const struct fileinfo *file2, const struct fileinfo *file1)
2189 int diff = CTIME_CMP (file2->stat, file1->stat);
2190 if (diff == 0)
2191 diff = strcoll (file1->name, file2->name);
2192 return diff;
2195 static int
2196 compare_mtime (const struct fileinfo *file1, const struct fileinfo *file2)
2198 int diff = MTIME_CMP (file2->stat, file1->stat);
2199 if (diff == 0)
2200 diff = strcoll (file1->name, file2->name);
2201 return diff;
2204 static int
2205 rev_cmp_mtime (const struct fileinfo *file2, const struct fileinfo *file1)
2207 int diff = MTIME_CMP (file2->stat, file1->stat);
2208 if (diff == 0)
2209 diff = strcoll (file1->name, file2->name);
2210 return diff;
2213 static int
2214 compare_atime (const struct fileinfo *file1, const struct fileinfo *file2)
2216 int diff = ATIME_CMP (file2->stat, file1->stat);
2217 if (diff == 0)
2218 diff = strcoll (file1->name, file2->name);
2219 return diff;
2222 static int
2223 rev_cmp_atime (const struct fileinfo *file2, const struct fileinfo *file1)
2225 int diff = ATIME_CMP (file2->stat, file1->stat);
2226 if (diff == 0)
2227 diff = strcoll (file1->name, file2->name);
2228 return diff;
2231 static int
2232 compare_size (const struct fileinfo *file1, const struct fileinfo *file2)
2234 int diff = longdiff (file2->stat.st_size, file1->stat.st_size);
2235 if (diff == 0)
2236 diff = strcoll (file1->name, file2->name);
2237 return diff;
2240 static int
2241 rev_cmp_size (const struct fileinfo *file2, const struct fileinfo *file1)
2243 int diff = longdiff (file2->stat.st_size, file1->stat.st_size);
2244 if (diff == 0)
2245 diff = strcoll (file1->name, file2->name);
2246 return diff;
2249 static int
2250 compare_version (const struct fileinfo *file1, const struct fileinfo *file2)
2252 return strverscmp (file1->name, file2->name);
2255 static int
2256 rev_cmp_version (const struct fileinfo *file2, const struct fileinfo *file1)
2258 return strverscmp (file1->name, file2->name);
2261 static int
2262 compare_name (const struct fileinfo *file1, const struct fileinfo *file2)
2264 return strcoll (file1->name, file2->name);
2267 static int
2268 rev_cmp_name (const struct fileinfo *file2, const struct fileinfo *file1)
2270 return strcoll (file1->name, file2->name);
2273 /* Compare file extensions. Files with no extension are `smallest'.
2274 If extensions are the same, compare by filenames instead. */
2276 static int
2277 compare_extension (const struct fileinfo *file1, const struct fileinfo *file2)
2279 register char *base1, *base2;
2280 register int cmp;
2282 base1 = strrchr (file1->name, '.');
2283 base2 = strrchr (file2->name, '.');
2284 if (base1 == 0 && base2 == 0)
2285 return strcoll (file1->name, file2->name);
2286 if (base1 == 0)
2287 return -1;
2288 if (base2 == 0)
2289 return 1;
2290 cmp = strcoll (base1, base2);
2291 if (cmp == 0)
2292 return strcoll (file1->name, file2->name);
2293 return cmp;
2296 static int
2297 rev_cmp_extension (const struct fileinfo *file2, const struct fileinfo *file1)
2299 register char *base1, *base2;
2300 register int cmp;
2302 base1 = strrchr (file1->name, '.');
2303 base2 = strrchr (file2->name, '.');
2304 if (base1 == 0 && base2 == 0)
2305 return strcoll (file1->name, file2->name);
2306 if (base1 == 0)
2307 return -1;
2308 if (base2 == 0)
2309 return 1;
2310 cmp = strcoll (base1, base2);
2311 if (cmp == 0)
2312 return strcoll (file1->name, file2->name);
2313 return cmp;
2316 /* List all the files now in the table. */
2318 static void
2319 print_current_files (void)
2321 register int i;
2323 switch (format)
2325 case one_per_line:
2326 for (i = 0; i < files_index; i++)
2328 print_file_name_and_frills (files + i);
2329 putchar ('\n');
2331 break;
2333 case many_per_line:
2334 init_column_info ();
2335 print_many_per_line ();
2336 break;
2338 case horizontal:
2339 init_column_info ();
2340 print_horizontal ();
2341 break;
2343 case with_commas:
2344 print_with_commas ();
2345 break;
2347 case long_format:
2348 for (i = 0; i < files_index; i++)
2350 print_long_format (files + i);
2351 DIRED_PUTCHAR ('\n');
2353 break;
2357 /* Return the expected number of columns in a long-format time stamp,
2358 or zero if it cannot be calculated. */
2360 static int
2361 long_time_expected_width (void)
2363 static int width = -1;
2365 if (width < 0)
2367 time_t epoch = 0;
2368 struct tm const *tm = localtime (&epoch);
2369 char const *fmt = long_time_format[0];
2370 char initbuf[100];
2371 char *buf = initbuf;
2372 size_t bufsize = sizeof initbuf;
2373 size_t len;
2375 for (;;)
2377 *buf = '\1';
2378 len = strftime (buf, bufsize, fmt, tm);
2379 if (len || ! *buf)
2380 break;
2381 buf = alloca (bufsize *= 2);
2384 width = mbsnwidth (buf, len, 0);
2385 if (width < 0)
2386 width = 0;
2389 return width;
2392 /* Get the current time. */
2394 static void
2395 get_current_time (void)
2397 #if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
2399 struct timespec timespec;
2400 if (clock_gettime (CLOCK_REALTIME, &timespec) == 0)
2402 current_time = timespec.tv_sec;
2403 current_time_ns = timespec.tv_nsec;
2404 return;
2407 #endif
2409 /* The clock does not have nanosecond resolution, so get the maximum
2410 possible value for the current time that is consistent with the
2411 reported clock. That way, files are not considered to be in the
2412 future merely because their time stamps have higher resolution
2413 than the clock resolution. */
2415 #if HAVE_GETTIMEOFDAY
2417 struct timeval timeval;
2418 if (gettimeofday (&timeval, NULL) == 0)
2420 current_time = timeval.tv_sec;
2421 current_time_ns = timeval.tv_usec * 1000 + 999;
2422 return;
2425 #endif
2427 current_time = time (NULL);
2428 current_time_ns = 999999999;
2431 static void
2432 print_long_format (const struct fileinfo *f)
2434 char modebuf[12];
2436 /* 7 fields that may require LONGEST_HUMAN_READABLE bytes,
2437 1 10-byte mode string,
2438 1 24-byte time string (may be longer in some locales -- see below)
2439 or LONGEST_HUMAN_READABLE integer,
2440 9 spaces, one following each of these fields, and
2441 1 trailing NUL byte. */
2442 char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10
2443 + (LONGEST_HUMAN_READABLE < 24 ? 24 : LONGEST_HUMAN_READABLE)
2444 + 9 + 1];
2445 char *buf = init_bigbuf;
2446 size_t bufsize = sizeof (init_bigbuf);
2447 size_t s;
2448 char *p;
2449 time_t when;
2450 int when_ns IF_LINT (= 0);
2451 struct tm *when_local;
2452 char *user_name;
2454 #if HAVE_ST_DM_MODE
2455 /* Cray DMF: look at the file's migrated, not real, status */
2456 mode_string (f->stat.st_dm_mode, modebuf);
2457 #else
2458 mode_string (f->stat.st_mode, modebuf);
2459 #endif
2461 modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' ');
2462 modebuf[11] = '\0';
2464 switch (time_type)
2466 case time_ctime:
2467 when = f->stat.st_ctime;
2468 when_ns = TIMESPEC_NS (f->stat.st_ctim);
2469 break;
2470 case time_mtime:
2471 when = f->stat.st_mtime;
2472 when_ns = TIMESPEC_NS (f->stat.st_mtim);
2473 break;
2474 case time_atime:
2475 when = f->stat.st_atime;
2476 when_ns = TIMESPEC_NS (f->stat.st_atim);
2477 break;
2480 p = buf;
2482 if (print_inode)
2484 char hbuf[LONGEST_HUMAN_READABLE + 1];
2485 sprintf (p, "%*s ", INODE_DIGITS,
2486 human_readable ((uintmax_t) f->stat.st_ino, hbuf, 1, 1));
2487 p += strlen (p);
2490 if (print_block_size)
2492 char hbuf[LONGEST_HUMAN_READABLE + 1];
2493 sprintf (p, "%*s ", block_size_size,
2494 human_readable_inexact ((uintmax_t) ST_NBLOCKS (f->stat), hbuf,
2495 ST_NBLOCKSIZE, output_block_size,
2496 human_ceiling));
2497 p += strlen (p);
2500 /* The last byte of the mode string is the POSIX
2501 "optional alternate access method flag". */
2502 sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
2503 p += strlen (p);
2505 user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid));
2506 if (user_name)
2507 sprintf (p, "%-8.8s ", user_name);
2508 else
2509 sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
2510 p += strlen (p);
2512 if (!inhibit_group)
2514 char *group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid));
2515 if (group_name)
2516 sprintf (p, "%-8.8s ", group_name);
2517 else
2518 sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
2519 p += strlen (p);
2522 if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
2523 sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
2524 (unsigned) minor (f->stat.st_rdev));
2525 else
2527 char hbuf[LONGEST_HUMAN_READABLE + 1];
2528 sprintf (p, "%8s ",
2529 human_readable ((uintmax_t) f->stat.st_size, hbuf, 1,
2530 output_block_size < 0 ? output_block_size : 1));
2533 p += strlen (p);
2535 if ((when_local = localtime (&when)))
2537 time_t six_months_ago;
2538 int recent;
2539 char const *fmt;
2541 /* If the file appears to be in the future, update the current
2542 time, in case the file happens to have been modified since
2543 the last time we checked the clock. */
2544 if (current_time < when
2545 || (current_time == when && current_time_ns < when_ns))
2546 get_current_time ();
2548 /* Consider a time to be recent if it is within the past six
2549 months. A Gregorian year has 365.2425 * 24 * 60 * 60 ==
2550 31556952 seconds on the average. Write this value as an
2551 integer constant to avoid floating point hassles. */
2552 six_months_ago = current_time - 31556952 / 2;
2553 recent = (six_months_ago <= when
2554 && (when < current_time
2555 || (when == current_time && when_ns <= current_time_ns)));
2556 fmt = long_time_format[recent];
2558 for (;;)
2560 char *newbuf;
2561 *p = '\1';
2562 s = strftime (p, buf + bufsize - p - 1, fmt, when_local);
2563 if (s || ! *p)
2564 break;
2565 newbuf = alloca (bufsize *= 2);
2566 memcpy (newbuf, buf, p - buf);
2567 p = newbuf + (p - buf);
2568 buf = newbuf;
2571 p += s;
2572 *p++ = ' ';
2574 /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it. */
2575 *p = '\0';
2577 else
2579 /* The time cannot be represented as a local time;
2580 print it as a huge integer number of seconds. */
2581 char hbuf[LONGEST_HUMAN_READABLE + 1];
2582 int width = long_time_expected_width ();
2584 if (when < 0)
2586 const char *num = human_readable (- (uintmax_t) when, hbuf, 1, 1);
2587 int sign_width = width - strlen (num);
2588 sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num);
2590 else
2591 sprintf (p, "%*s ", width,
2592 human_readable ((uintmax_t) when, hbuf, 1, 1));
2594 p += strlen (p);
2597 DIRED_INDENT ();
2598 DIRED_FPUTS (buf, stdout, p - buf);
2599 print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok,
2600 &dired_obstack);
2602 if (f->filetype == symbolic_link)
2604 if (f->linkname)
2606 DIRED_FPUTS_LITERAL (" -> ", stdout);
2607 print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1,
2608 NULL);
2609 if (indicator_style != none)
2610 print_type_indicator (f->linkmode);
2613 else if (indicator_style != none)
2614 print_type_indicator (f->stat.st_mode);
2617 /* Output to OUT a quoted representation of the file name NAME,
2618 using OPTIONS to control quoting. Produce no output if OUT is NULL.
2619 Return the number of screen columns occupied by NAME's quoted
2620 representation. */
2622 static size_t
2623 quote_name (FILE *out, const char *name, struct quoting_options const *options)
2625 char smallbuf[BUFSIZ];
2626 size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, name, -1, options);
2627 char *buf;
2628 int displayed_width;
2630 if (len < sizeof smallbuf)
2631 buf = smallbuf;
2632 else
2634 buf = (char *) alloca (len + 1);
2635 quotearg_buffer (buf, len + 1, name, -1, options);
2638 if (qmark_funny_chars)
2640 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
2641 if (MB_CUR_MAX > 1)
2643 const char *p = buf;
2644 char *plimit = buf + len;
2645 char *q = buf;
2646 displayed_width = 0;
2648 while (p < plimit)
2649 switch (*p)
2651 case ' ': case '!': case '"': case '#': case '%':
2652 case '&': case '\'': case '(': case ')': case '*':
2653 case '+': case ',': case '-': case '.': case '/':
2654 case '0': case '1': case '2': case '3': case '4':
2655 case '5': case '6': case '7': case '8': case '9':
2656 case ':': case ';': case '<': case '=': case '>':
2657 case '?':
2658 case 'A': case 'B': case 'C': case 'D': case 'E':
2659 case 'F': case 'G': case 'H': case 'I': case 'J':
2660 case 'K': case 'L': case 'M': case 'N': case 'O':
2661 case 'P': case 'Q': case 'R': case 'S': case 'T':
2662 case 'U': case 'V': case 'W': case 'X': case 'Y':
2663 case 'Z':
2664 case '[': case '\\': case ']': case '^': case '_':
2665 case 'a': case 'b': case 'c': case 'd': case 'e':
2666 case 'f': case 'g': case 'h': case 'i': case 'j':
2667 case 'k': case 'l': case 'm': case 'n': case 'o':
2668 case 'p': case 'q': case 'r': case 's': case 't':
2669 case 'u': case 'v': case 'w': case 'x': case 'y':
2670 case 'z': case '{': case '|': case '}': case '~':
2671 /* These characters are printable ASCII characters. */
2672 *q++ = *p++;
2673 displayed_width += 1;
2674 break;
2675 default:
2676 /* If we have a multibyte sequence, copy it until we
2677 reach its end, replacing each non-printable multibyte
2678 character with a single question mark. */
2680 mbstate_t mbstate;
2681 memset (&mbstate, 0, sizeof mbstate);
2684 wchar_t wc;
2685 size_t bytes;
2686 int w;
2688 bytes = mbrtowc (&wc, p, plimit - p, &mbstate);
2690 if (bytes == (size_t) -1)
2692 /* An invalid multibyte sequence was
2693 encountered. Skip one input byte, and
2694 put a question mark. */
2695 p++;
2696 *q++ = '?';
2697 displayed_width += 1;
2698 break;
2701 if (bytes == (size_t) -2)
2703 /* An incomplete multibyte character
2704 at the end. Replace it entirely with
2705 a question mark. */
2706 p = plimit;
2707 *q++ = '?';
2708 displayed_width += 1;
2709 break;
2712 if (bytes == 0)
2713 /* A null wide character was encountered. */
2714 bytes = 1;
2716 w = wcwidth (wc);
2717 if (w >= 0)
2719 /* A printable multibyte character.
2720 Keep it. */
2721 for (; bytes > 0; --bytes)
2722 *q++ = *p++;
2723 displayed_width += w;
2725 else
2727 /* An unprintable multibyte character.
2728 Replace it entirely with a question
2729 mark. */
2730 p += bytes;
2731 *q++ = '?';
2732 displayed_width += 1;
2735 while (! mbsinit (&mbstate));
2737 break;
2740 /* The buffer may have shrunk. */
2741 len = q - buf;
2743 else
2744 #endif
2746 char *p = buf;
2747 char *plimit = buf + len;
2749 while (p < plimit)
2751 if (! ISPRINT ((unsigned char) *p))
2752 *p = '?';
2753 p++;
2755 displayed_width = len;
2758 else
2760 /* Assume unprintable characters have a displayed_width of 1. */
2761 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
2762 if (MB_CUR_MAX > 1)
2763 displayed_width = mbsnwidth (buf, len,
2764 (MBSW_ACCEPT_INVALID
2765 | MBSW_ACCEPT_UNPRINTABLE));
2766 else
2767 #endif
2768 displayed_width = len;
2771 if (out != NULL)
2772 fwrite (buf, 1, len, out);
2773 return displayed_width;
2776 static void
2777 print_name_with_quoting (const char *p, unsigned int mode, int linkok,
2778 struct obstack *stack)
2780 if (print_with_color)
2781 print_color_indicator (p, mode, linkok);
2783 if (stack)
2784 PUSH_CURRENT_DIRED_POS (stack);
2786 dired_pos += quote_name (stdout, p, filename_quoting_options);
2788 if (stack)
2789 PUSH_CURRENT_DIRED_POS (stack);
2791 if (print_with_color)
2792 prep_non_filename_text ();
2795 static void
2796 prep_non_filename_text (void)
2798 if (color_indicator[C_END].string != NULL)
2799 put_indicator (&color_indicator[C_END]);
2800 else
2802 put_indicator (&color_indicator[C_LEFT]);
2803 put_indicator (&color_indicator[C_NORM]);
2804 put_indicator (&color_indicator[C_RIGHT]);
2808 /* Print the file name of `f' with appropriate quoting.
2809 Also print file size, inode number, and filetype indicator character,
2810 as requested by switches. */
2812 static void
2813 print_file_name_and_frills (const struct fileinfo *f)
2815 char buf[LONGEST_HUMAN_READABLE + 1];
2817 if (print_inode)
2818 printf ("%*s ", INODE_DIGITS,
2819 human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1));
2821 if (print_block_size)
2822 printf ("%*s ", block_size_size,
2823 human_readable_inexact ((uintmax_t) ST_NBLOCKS (f->stat), buf,
2824 ST_NBLOCKSIZE, output_block_size,
2825 human_ceiling));
2827 print_name_with_quoting (f->name, FILE_OR_LINK_MODE (f), f->linkok, NULL);
2829 if (indicator_style != none)
2830 print_type_indicator (f->stat.st_mode);
2833 static void
2834 print_type_indicator (unsigned int mode)
2836 int c;
2838 if (S_ISREG (mode))
2840 if (indicator_style == classify && (mode & S_IXUGO))
2841 c ='*';
2842 else
2843 c = 0;
2845 else
2847 if (S_ISDIR (mode))
2848 c = '/';
2849 else if (S_ISLNK (mode))
2850 c = '@';
2851 else if (S_ISFIFO (mode))
2852 c = '|';
2853 else if (S_ISSOCK (mode))
2854 c = '=';
2855 else if (S_ISDOOR (mode))
2856 c = '>';
2857 else
2858 c = 0;
2861 if (c)
2862 DIRED_PUTCHAR (c);
2865 static void
2866 print_color_indicator (const char *name, unsigned int mode, int linkok)
2868 int type = C_FILE;
2869 struct color_ext_type *ext; /* Color extension */
2870 size_t len; /* Length of name */
2872 /* Is this a nonexistent file? If so, linkok == -1. */
2874 if (linkok == -1 && color_indicator[C_MISSING].string != NULL)
2876 ext = NULL;
2877 type = C_MISSING;
2879 else
2881 if (S_ISDIR (mode))
2882 type = C_DIR;
2883 else if (S_ISLNK (mode))
2884 type = ((!linkok && color_indicator[C_ORPHAN].string)
2885 ? C_ORPHAN : C_LINK);
2886 else if (S_ISFIFO (mode))
2887 type = C_FIFO;
2888 else if (S_ISSOCK (mode))
2889 type = C_SOCK;
2890 else if (S_ISBLK (mode))
2891 type = C_BLK;
2892 else if (S_ISCHR (mode))
2893 type = C_CHR;
2894 else if (S_ISDOOR (mode))
2895 type = C_DOOR;
2897 if (type == C_FILE && (mode & S_IXUGO) != 0)
2898 type = C_EXEC;
2900 /* Check the file's suffix only if still classified as C_FILE. */
2901 ext = NULL;
2902 if (type == C_FILE)
2904 /* Test if NAME has a recognized suffix. */
2906 len = strlen (name);
2907 name += len; /* Pointer to final \0. */
2908 for (ext = color_ext_list; ext != NULL; ext = ext->next)
2910 if ((size_t) ext->ext.len <= len
2911 && strncmp (name - ext->ext.len, ext->ext.string,
2912 ext->ext.len) == 0)
2913 break;
2918 put_indicator (&color_indicator[C_LEFT]);
2919 put_indicator (ext ? &(ext->seq) : &color_indicator[type]);
2920 put_indicator (&color_indicator[C_RIGHT]);
2923 /* Output a color indicator (which may contain nulls). */
2924 static void
2925 put_indicator (const struct bin_str *ind)
2927 register int i;
2928 register const char *p;
2930 p = ind->string;
2932 for (i = ind->len; i > 0; --i)
2933 putchar (*(p++));
2936 static int
2937 length_of_file_name_and_frills (const struct fileinfo *f)
2939 register int len = 0;
2941 if (print_inode)
2942 len += INODE_DIGITS + 1;
2944 if (print_block_size)
2945 len += 1 + block_size_size;
2947 len += quote_name (NULL, f->name, filename_quoting_options);
2949 if (indicator_style != none)
2951 unsigned filetype = f->stat.st_mode;
2953 if (S_ISREG (filetype))
2955 if (indicator_style == classify
2956 && (f->stat.st_mode & S_IXUGO))
2957 len += 1;
2959 else if (S_ISDIR (filetype)
2960 || S_ISLNK (filetype)
2961 || S_ISFIFO (filetype)
2962 || S_ISSOCK (filetype)
2963 || S_ISDOOR (filetype)
2965 len += 1;
2968 return len;
2971 static void
2972 print_many_per_line (void)
2974 struct column_info *line_fmt;
2975 int filesno; /* Index into files. */
2976 int row; /* Current row. */
2977 int max_name_length; /* Length of longest file name + frills. */
2978 int name_length; /* Length of each file name + frills. */
2979 int pos; /* Current character column. */
2980 int cols; /* Number of files across. */
2981 int rows; /* Maximum number of files down. */
2982 int max_cols;
2984 /* Normally the maximum number of columns is determined by the
2985 screen width. But if few files are available this might limit it
2986 as well. */
2987 max_cols = max_idx > files_index ? files_index : max_idx;
2989 /* Compute the maximum number of possible columns. */
2990 for (filesno = 0; filesno < files_index; ++filesno)
2992 int i;
2994 name_length = length_of_file_name_and_frills (files + filesno);
2996 for (i = 0; i < max_cols; ++i)
2998 if (column_info[i].valid_len)
3000 int idx = filesno / ((files_index + i) / (i + 1));
3001 int real_length = name_length + (idx == i ? 0 : 2);
3003 if (real_length > column_info[i].col_arr[idx])
3005 column_info[i].line_len += (real_length
3006 - column_info[i].col_arr[idx]);
3007 column_info[i].col_arr[idx] = real_length;
3008 column_info[i].valid_len = column_info[i].line_len < line_length;
3014 /* Find maximum allowed columns. */
3015 for (cols = max_cols; cols > 1; --cols)
3017 if (column_info[cols - 1].valid_len)
3018 break;
3021 line_fmt = &column_info[cols - 1];
3023 /* Calculate the number of rows that will be in each column except possibly
3024 for a short column on the right. */
3025 rows = files_index / cols + (files_index % cols != 0);
3027 for (row = 0; row < rows; row++)
3029 int col = 0;
3030 filesno = row;
3031 pos = 0;
3032 /* Print the next row. */
3033 while (1)
3035 print_file_name_and_frills (files + filesno);
3036 name_length = length_of_file_name_and_frills (files + filesno);
3037 max_name_length = line_fmt->col_arr[col++];
3039 filesno += rows;
3040 if (filesno >= files_index)
3041 break;
3043 indent (pos + name_length, pos + max_name_length);
3044 pos += max_name_length;
3046 putchar ('\n');
3050 static void
3051 print_horizontal (void)
3053 struct column_info *line_fmt;
3054 int filesno;
3055 int max_name_length;
3056 int name_length;
3057 int cols;
3058 int pos;
3059 int max_cols;
3061 /* Normally the maximum number of columns is determined by the
3062 screen width. But if few files are available this might limit it
3063 as well. */
3064 max_cols = max_idx > files_index ? files_index : max_idx;
3066 /* Compute the maximum file name length. */
3067 max_name_length = 0;
3068 for (filesno = 0; filesno < files_index; ++filesno)
3070 int i;
3072 name_length = length_of_file_name_and_frills (files + filesno);
3074 for (i = 0; i < max_cols; ++i)
3076 if (column_info[i].valid_len)
3078 int idx = filesno % (i + 1);
3079 int real_length = name_length + (idx == i ? 0 : 2);
3081 if (real_length > column_info[i].col_arr[idx])
3083 column_info[i].line_len += (real_length
3084 - column_info[i].col_arr[idx]);
3085 column_info[i].col_arr[idx] = real_length;
3086 column_info[i].valid_len = column_info[i].line_len < line_length;
3092 /* Find maximum allowed columns. */
3093 for (cols = max_cols; cols > 1; --cols)
3095 if (column_info[cols - 1].valid_len)
3096 break;
3099 line_fmt = &column_info[cols - 1];
3101 pos = 0;
3103 /* Print first entry. */
3104 print_file_name_and_frills (files);
3105 name_length = length_of_file_name_and_frills (files);
3106 max_name_length = line_fmt->col_arr[0];
3108 /* Now the rest. */
3109 for (filesno = 1; filesno < files_index; ++filesno)
3111 int col = filesno % cols;
3113 if (col == 0)
3115 putchar ('\n');
3116 pos = 0;
3118 else
3120 indent (pos + name_length, pos + max_name_length);
3121 pos += max_name_length;
3124 print_file_name_and_frills (files + filesno);
3126 name_length = length_of_file_name_and_frills (files + filesno);
3127 max_name_length = line_fmt->col_arr[col];
3129 putchar ('\n');
3132 static void
3133 print_with_commas (void)
3135 int filesno;
3136 int pos, old_pos;
3138 pos = 0;
3140 for (filesno = 0; filesno < files_index; filesno++)
3142 old_pos = pos;
3144 pos += length_of_file_name_and_frills (files + filesno);
3145 if (filesno + 1 < files_index)
3146 pos += 2; /* For the comma and space */
3148 if (old_pos != 0 && pos >= line_length)
3150 putchar ('\n');
3151 pos -= old_pos;
3154 print_file_name_and_frills (files + filesno);
3155 if (filesno + 1 < files_index)
3157 putchar (',');
3158 putchar (' ');
3161 putchar ('\n');
3164 /* Assuming cursor is at position FROM, indent up to position TO.
3165 Use a TAB character instead of two or more spaces whenever possible. */
3167 static void
3168 indent (int from, int to)
3170 while (from < to)
3172 if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
3174 putchar ('\t');
3175 from += tabsize - from % tabsize;
3177 else
3179 putchar (' ');
3180 from++;
3185 /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */
3186 /* FIXME: maybe remove this function someday. See about using a
3187 non-malloc'ing version of path_concat. */
3189 static void
3190 attach (char *dest, const char *dirname, const char *name)
3192 const char *dirnamep = dirname;
3194 /* Copy dirname if it is not ".". */
3195 if (dirname[0] != '.' || dirname[1] != 0)
3197 while (*dirnamep)
3198 *dest++ = *dirnamep++;
3199 /* Add '/' if `dirname' doesn't already end with it. */
3200 if (dirnamep > dirname && dirnamep[-1] != '/')
3201 *dest++ = '/';
3203 while (*name)
3204 *dest++ = *name++;
3205 *dest = 0;
3208 static void
3209 init_column_info (void)
3211 int i;
3212 int allocate = 0;
3214 max_idx = line_length / MIN_COLUMN_WIDTH;
3215 if (max_idx == 0)
3216 max_idx = 1;
3218 if (column_info == NULL)
3220 column_info = (struct column_info *) xmalloc (max_idx
3221 * sizeof (struct column_info));
3222 allocate = 1;
3225 for (i = 0; i < max_idx; ++i)
3227 int j;
3229 column_info[i].valid_len = 1;
3230 column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
3232 if (allocate)
3233 column_info[i].col_arr = (int *) xmalloc ((i + 1) * sizeof (int));
3235 for (j = 0; j <= i; ++j)
3236 column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
3240 void
3241 usage (int status)
3243 if (status != 0)
3244 fprintf (stderr, _("Try `%s --help' for more information.\n"),
3245 program_name);
3246 else
3248 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
3249 printf (_("\
3250 List information about the FILEs (the current directory by default).\n\
3251 Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
3253 -a, --all do not hide entries starting with .\n\
3254 -A, --almost-all do not list implied . and ..\n\
3255 -b, --escape print octal escapes for nongraphic characters\n\
3256 --block-size=SIZE use SIZE-byte blocks\n\
3257 -B, --ignore-backups do not list implied entries ending with ~\n\
3258 -c with -lt: sort by, and show, ctime (time of last\n\
3259 modification of file status information)\n\
3260 with -l: show ctime and sort by name\n\
3261 otherwise: sort by ctime\n\
3262 -C list entries by columns\n\
3263 --color[=WHEN] control whether color is used to distinguish file\n\
3264 types. WHEN may be `never', `always', or `auto'\n\
3265 -d, --directory list directory entries instead of contents\n\
3266 -D, --dired generate output designed for Emacs' dired mode\n\
3267 -f do not sort, enable -aU, disable -lst\n\
3268 -F, --classify append indicator (one of */=@|) to entries\n\
3269 --format=WORD across -x, commas -m, horizontal -x, long -l,\n\
3270 single-column -1, verbose -l, vertical -C\n\
3271 --full-time list both full date and full time\n"));
3273 printf (_("\
3274 -g (ignored)\n\
3275 -G, --no-group inhibit display of group information\n\
3276 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
3277 -H, --si likewise, but use powers of 1000 not 1024\n\
3278 --indicator-style=WORD append indicator with style WORD to entry names:\n\
3279 none (default), classify (-F), file-type (-p)\n\
3280 -i, --inode print index number of each file\n\
3281 -I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\
3282 -k, --kilobytes like --block-size=1024\n\
3283 -l use a long listing format\n\
3284 -L, --dereference list entries pointed to by symbolic links\n\
3285 -m fill width with a comma separated list of entries\n\
3286 -n, --numeric-uid-gid list numeric UIDs and GIDs instead of names\n\
3287 -N, --literal print raw entry names (don't treat e.g. control\n\
3288 characters specially)\n\
3289 -o use long listing format without group info\n\
3290 -p, --file-type append indicator (one of /=@|) to entries\n\
3291 -q, --hide-control-chars print ? instead of non graphic characters\n\
3292 --show-control-chars show non graphic characters as-is (default\n\
3293 unless program is `ls' and output is a terminal)\n\
3294 -Q, --quote-name enclose entry names in double quotes\n\
3295 --quoting-style=WORD use quoting style WORD for entry names:\n\
3296 literal, locale, shell, shell-always, c, escape\n\
3297 -r, --reverse reverse order while sorting\n\
3298 -R, --recursive list subdirectories recursively\n\
3299 -s, --size print size of each file, in blocks\n"));
3301 printf (_("\
3302 -S sort by file size\n\
3303 --sort=WORD extension -X, none -U, size -S, time -t,\n\
3304 version -v\n\
3305 status -c, time -t, atime -u, access -u, use -u\n\
3306 --time=WORD show time as WORD instead of modification time:\n\
3307 atime, access, use, ctime or status; use\n\
3308 specified time as sort key if --sort=time\n\
3309 -t sort by modification time\n\
3310 -T, --tabsize=COLS assume tab stops at each COLS instead of 8\n\
3311 -u with -lt: sort by, and show, access time\n\
3312 with -l: show access time and sort by name\n\
3313 otherwise: sort by access time\n\
3314 -U do not sort; list entries in directory order\n\
3315 -v sort by version\n\
3316 -w, --width=COLS assume screen width instead of current value\n\
3317 -x list entries by lines instead of by columns\n\
3318 -X sort alphabetically by entry extension\n\
3319 -1 list one file per line\n\
3320 --help display this help and exit\n\
3321 --version output version information and exit\n\
3323 By default, color is not used to distinguish types of files. That is\n\
3324 equivalent to using --color=none. Using the --color option without the\n\
3325 optional WHEN argument is equivalent to using --color=always. With\n\
3326 --color=auto, color codes are output only if standard output is connected\n\
3327 to a terminal (tty).\n\
3328 "));
3329 puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
3331 exit (status);