(recheck): Handle a race condition (including <dev,inode>
[coreutils.git] / src / ls.c
blob1b7543b9f1f4c503672f49373002c10a24f1b183
1 /* `dir', `vdir' and `ls' directory listing programs for GNU.
2 Copyright (C) 85, 88, 90, 91, 1995-1999 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 #include "system.h"
74 #include <fnmatch.h>
76 #include "argmatch.h"
77 #include "error.h"
78 #include "human.h"
79 #include "filemode.h"
80 #include "ls.h"
81 #include "obstack.h"
82 #include "path-concat.h"
83 #include "quotearg.h"
84 #include "strverscmp.h"
85 #include "xstrtol.h"
87 /* Use access control lists only under all the following conditions.
88 Some systems (OSF4, Irix5, Irix6) have the acl function, but not
89 sys/acl.h or don't define the GETACLCNT macro. */
90 #if HAVE_SYS_ACL_H && HAVE_ACL && defined GETACLCNT
91 # define USE_ACL 1
92 #endif
94 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
95 : (ls_mode == LS_MULTI_COL \
96 ? "dir" : "vdir"))
98 #define AUTHORS "Richard Stallman and David MacKenzie"
100 #define obstack_chunk_alloc malloc
101 #define obstack_chunk_free free
103 /* Return an int indicating the result of comparing two integers.
104 Subtracting doesn't always work, due to overflow. */
105 #define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))
107 /* The field width for inode numbers. On some hosts inode numbers are
108 64 bits, so columns won't line up exactly when a huge inode number
109 is encountered, but in practice 7 digits is usually enough. */
110 #ifndef INODE_DIGITS
111 # define INODE_DIGITS 7
112 #endif
114 #ifdef S_ISLNK
115 # define HAVE_SYMLINKS 1
116 #else
117 # define HAVE_SYMLINKS 0
118 #endif
120 /* If any of the S_* macros are undefined, define them here so each
121 use doesn't have to be guarded with e.g., #ifdef S_ISLNK. */
122 #ifndef S_ISLNK
123 # define S_ISLNK(Mode) 0
124 #endif
126 #ifndef S_ISFIFO
127 # define S_ISFIFO(Mode) 0
128 #endif
130 #ifndef S_ISSOCK
131 # define S_ISSOCK(Mode) 0
132 #endif
134 #ifndef S_ISCHR
135 # define S_ISCHR(Mode) 0
136 #endif
138 #ifndef S_ISBLK
139 # define S_ISBLK(Mode) 0
140 #endif
142 #ifndef S_ISDOOR
143 # define S_ISDOOR(Mode) 0
144 #endif
146 enum filetype
148 symbolic_link,
149 directory,
150 arg_directory, /* Directory given as command line arg. */
151 normal /* All others. */
154 struct fileinfo
156 /* The file name. */
157 char *name;
159 struct stat stat;
161 /* For symbolic link, name of the file linked to, otherwise zero. */
162 char *linkname;
164 /* For symbolic link and long listing, st_mode of file linked to, otherwise
165 zero. */
166 unsigned int linkmode;
168 /* For symbolic link and color printing, 1 if linked-to file
169 exists, otherwise 0. */
170 int linkok;
172 enum filetype filetype;
174 #if USE_ACL
175 /* For long listings, nonzero if the file has an access control list,
176 otherwise zero. */
177 int have_acl;
178 #endif
181 #if USE_ACL
182 # define FILE_HAS_ACL(F) ((F)->have_acl)
183 #else
184 # define FILE_HAS_ACL(F) 0
185 #endif
187 #define LEN_STR_PAIR(s) sizeof (s) - 1, s
189 /* Null is a valid character in a color indicator (think about Epson
190 printers, for example) so we have to use a length/buffer string
191 type. */
193 struct bin_str
195 int len; /* Number of bytes */
196 char *string; /* Pointer to the same */
199 #ifndef STDC_HEADERS
200 time_t time ();
201 #endif
203 char *getgroup ();
204 char *getuser ();
205 void strip_trailing_slashes ();
207 static size_t quote_name PARAMS ((FILE *out, const char *name,
208 struct quoting_options const *options));
209 static char *make_link_path PARAMS ((const char *path, const char *linkname));
210 static int compare_atime PARAMS ((const struct fileinfo *file1,
211 const struct fileinfo *file2));
212 static int rev_cmp_atime PARAMS ((const struct fileinfo *file2,
213 const struct fileinfo *file1));
214 static int compare_ctime PARAMS ((const struct fileinfo *file1,
215 const struct fileinfo *file2));
216 static int rev_cmp_ctime PARAMS ((const struct fileinfo *file2,
217 const struct fileinfo *file1));
218 static int compare_mtime PARAMS ((const struct fileinfo *file1,
219 const struct fileinfo *file2));
220 static int rev_cmp_mtime PARAMS ((const struct fileinfo *file2,
221 const struct fileinfo *file1));
222 static int compare_size PARAMS ((const struct fileinfo *file1,
223 const struct fileinfo *file2));
224 static int rev_cmp_size PARAMS ((const struct fileinfo *file2,
225 const struct fileinfo *file1));
226 static int compare_name PARAMS ((const struct fileinfo *file1,
227 const struct fileinfo *file2));
228 static int rev_cmp_name PARAMS ((const struct fileinfo *file2,
229 const struct fileinfo *file1));
230 static int compare_extension PARAMS ((const struct fileinfo *file1,
231 const struct fileinfo *file2));
232 static int rev_cmp_extension PARAMS ((const struct fileinfo *file2,
233 const struct fileinfo *file1));
234 static int compare_version PARAMS ((const struct fileinfo *file1,
235 const struct fileinfo *file2));
236 static int rev_cmp_version PARAMS ((const struct fileinfo *file2,
237 const struct fileinfo *file1));
238 static int decode_switches PARAMS ((int argc, char **argv));
239 static int file_interesting PARAMS ((const struct dirent *next));
240 static uintmax_t gobble_file PARAMS ((const char *name, int explicit_arg,
241 const char *dirname));
242 static void print_color_indicator PARAMS ((const char *name, unsigned int mode,
243 int linkok));
244 static void put_indicator PARAMS ((const struct bin_str *ind));
245 static int length_of_file_name_and_frills PARAMS ((const struct fileinfo *f));
246 static void add_ignore_pattern PARAMS ((const char *pattern));
247 static void attach PARAMS ((char *dest, const char *dirname, const char *name));
248 static void clear_files PARAMS ((void));
249 static void extract_dirs_from_files PARAMS ((const char *dirname,
250 int recursive));
251 static void get_link_name PARAMS ((const char *filename, struct fileinfo *f));
252 static void indent PARAMS ((int from, int to));
253 static void init_column_info PARAMS ((void));
254 static void print_current_files PARAMS ((void));
255 static void print_dir PARAMS ((const char *name, const char *realname));
256 static void print_file_name_and_frills PARAMS ((const struct fileinfo *f));
257 static void print_horizontal PARAMS ((void));
258 static void print_long_format PARAMS ((const struct fileinfo *f));
259 static void print_many_per_line PARAMS ((void));
260 static void print_name_with_quoting PARAMS ((const char *p, unsigned int mode,
261 int linkok,
262 struct obstack *stack));
263 static void prep_non_filename_text PARAMS ((void));
264 static void print_type_indicator PARAMS ((unsigned int mode));
265 static void print_with_commas PARAMS ((void));
266 static void queue_directory PARAMS ((const char *name, const char *realname));
267 static void sort_files PARAMS ((void));
268 static void parse_ls_color PARAMS ((void));
269 void usage PARAMS ((int status));
271 /* The name the program was run with, stripped of any leading path. */
272 char *program_name;
274 /* The table of files in the current directory:
276 `files' points to a vector of `struct fileinfo', one per file.
277 `nfiles' is the number of elements space has been allocated for.
278 `files_index' is the number actually in use. */
280 /* Address of block containing the files that are described. */
282 static struct fileinfo *files;
284 /* Length of block that `files' points to, measured in files. */
286 static int nfiles;
288 /* Index of first unused in `files'. */
290 static int files_index;
292 /* Record of one pending directory waiting to be listed. */
294 struct pending
296 char *name;
297 /* If the directory is actually the file pointed to by a symbolic link we
298 were told to list, `realname' will contain the name of the symbolic
299 link, otherwise zero. */
300 char *realname;
301 struct pending *next;
304 static struct pending *pending_dirs;
306 /* Current time (seconds since 1970). When we are printing a file's time,
307 include the year if it is more than 6 months before this time. */
309 static time_t current_time;
311 /* The number of digits to use for block sizes.
312 4, or more if needed for bigger numbers. */
314 static int block_size_size;
316 /* Option flags */
318 /* long_format for lots of info, one per line.
319 one_per_line for just names, one per line.
320 many_per_line for just names, many per line, sorted vertically.
321 horizontal for just names, many per line, sorted horizontally.
322 with_commas for just names, many per line, separated by commas.
324 -l, -1, -C, -x and -m control this parameter. */
326 enum format
328 long_format, /* -l */
329 one_per_line, /* -1 */
330 many_per_line, /* -C */
331 horizontal, /* -x */
332 with_commas /* -m */
335 static enum format format;
337 /* Type of time to print or sort by. Controlled by -c and -u. */
339 enum time_type
341 time_mtime, /* default */
342 time_ctime, /* -c */
343 time_atime /* -u */
346 static enum time_type time_type;
348 /* print the full time, otherwise the standard unix heuristics. */
350 static int full_time;
352 /* The file characteristic to sort by. Controlled by -t, -S, -U, -X, -v. */
354 enum sort_type
356 sort_none, /* -U */
357 sort_name, /* default */
358 sort_extension, /* -X */
359 sort_time, /* -t */
360 sort_size, /* -S */
361 sort_version /* -v */
364 static enum sort_type sort_type;
366 /* Direction of sort.
367 0 means highest first if numeric,
368 lowest first if alphabetic;
369 these are the defaults.
370 1 means the opposite order in each case. -r */
372 static int sort_reverse;
374 /* Nonzero means to NOT display group information. -G */
376 static int inhibit_group;
378 /* Nonzero means print the user and group id's as numbers rather
379 than as names. -n */
381 static int numeric_ids;
383 /* Nonzero means mention the size in blocks of each file. -s */
385 static int print_block_size;
387 /* If positive, the units to use when printing sizes;
388 if negative, the human-readable base. */
389 static int output_block_size;
391 /* Precede each line of long output (per file) with a string like `m,n:'
392 where M is the number of characters after the `:' and before the
393 filename and N is the length of the filename. Using this format,
394 Emacs' dired mode starts up twice as fast, and can handle all
395 strange characters in file names. */
396 static int dired;
398 /* `none' means don't mention the type of files.
399 `classify' means mention file types and mark executables.
400 `file_type' means mention only file types.
402 Controlled by -F, -p, and --indicator-style. */
404 enum indicator_style
406 none, /* --indicator-style=none */
407 classify, /* -F, --indicator-style=classify */
408 file_type /* -p, --indicator-style=file-type */
411 static enum indicator_style indicator_style;
413 /* Names of indicator styles. */
414 static char const *const indicator_style_args[] =
416 "none", "classify", "file-type", 0
419 static enum indicator_style const indicator_style_types[]=
421 none, classify, file_type
424 /* Nonzero means use colors to mark types. Also define the different
425 colors as well as the stuff for the LS_COLORS environment variable.
426 The LS_COLORS variable is now in a termcap-like format. */
428 static int print_with_color;
430 enum color_type
432 color_never, /* 0: default or --color=never */
433 color_always, /* 1: --color=always */
434 color_if_tty /* 2: --color=tty */
437 enum indicator_no
439 C_LEFT, C_RIGHT, C_END, C_NORM, C_FILE, C_DIR, C_LINK, C_FIFO, C_SOCK,
440 C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR
443 static const char *const indicator_name[]=
445 "lc", "rc", "ec", "no", "fi", "di", "ln", "pi", "so",
446 "bd", "cd", "mi", "or", "ex", "do", NULL
449 struct color_ext_type
451 struct bin_str ext; /* The extension we're looking for */
452 struct bin_str seq; /* The sequence to output when we do */
453 struct color_ext_type *next; /* Next in list */
456 static struct bin_str color_indicator[] =
458 { LEN_STR_PAIR ("\033[") }, /* lc: Left of color sequence */
459 { LEN_STR_PAIR ("m") }, /* rc: Right of color sequence */
460 { 0, NULL }, /* ec: End color (replaces lc+no+rc) */
461 { LEN_STR_PAIR ("0") }, /* no: Normal */
462 { LEN_STR_PAIR ("0") }, /* fi: File: default */
463 { LEN_STR_PAIR ("01;34") }, /* di: Directory: bright blue */
464 { LEN_STR_PAIR ("01;36") }, /* ln: Symlink: bright cyan */
465 { LEN_STR_PAIR ("33") }, /* pi: Pipe: yellow/brown */
466 { LEN_STR_PAIR ("01;35") }, /* so: Socket: bright magenta */
467 { LEN_STR_PAIR ("01;33") }, /* bd: Block device: bright yellow */
468 { LEN_STR_PAIR ("01;33") }, /* cd: Char device: bright yellow */
469 { 0, NULL }, /* mi: Missing file: undefined */
470 { 0, NULL }, /* or: Orphanned symlink: undefined */
471 { LEN_STR_PAIR ("01;32") }, /* ex: Executable: bright green */
472 { LEN_STR_PAIR ("01;35") } /* do: Door: bright magenta */
475 /* FIXME: comment */
476 static struct color_ext_type *color_ext_list = NULL;
478 /* Buffer for color sequences */
479 static char *color_buf;
481 /* Nonzero means mention the inode number of each file. -i */
483 static int print_inode;
485 /* Nonzero means when a symbolic link is found, display info on
486 the file linked to. -L */
488 static int trace_links;
490 /* Nonzero means when a directory is found, display info on its
491 contents. -R */
493 static int trace_dirs;
495 /* Nonzero means when an argument is a directory name, display info
496 on it itself. -d */
498 static int immediate_dirs;
500 /* Nonzero means don't omit files whose names start with `.'. -A */
502 static int all_files;
504 /* Nonzero means don't omit files `.' and `..'
505 This flag implies `all_files'. -a */
507 static int really_all_files;
509 /* A linked list of shell-style globbing patterns. If a non-argument
510 file name matches any of these patterns, it is omitted.
511 Controlled by -I. Multiple -I options accumulate.
512 The -B option adds `*~' and `.*~' to this list. */
514 struct ignore_pattern
516 const char *pattern;
517 struct ignore_pattern *next;
520 static struct ignore_pattern *ignore_patterns;
522 /* Nonzero means output nongraphic chars in file names as `?'.
523 (-q, --hide-control-chars)
524 qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are
525 independent. The algorithm is: first, obey the quoting style to get a
526 string representing the file name; then, if qmark_funny_chars is set,
527 replace all nonprintable chars in that string with `?'. It's necessary
528 to replace nonprintable chars even in quoted strings, because we don't
529 want to mess up the terminal if control chars get sent to it, and some
530 quoting methods pass through control chars as-is. */
531 static int qmark_funny_chars;
533 /* Quoting options for file and dir name output. */
535 static struct quoting_options *filename_quoting_options;
536 static struct quoting_options *dirname_quoting_options;
538 /* The number of chars per hardware tab stop. Setting this to zero
539 inhibits the use of TAB characters for separating columns. -T */
540 static int tabsize;
542 /* Nonzero means we are listing the working directory because no
543 non-option arguments were given. */
545 static int dir_defaulted;
547 /* Nonzero means print each directory name before listing it. */
549 static int print_dir_name;
551 /* The line length to use for breaking lines in many-per-line format.
552 Can be set with -w. */
554 static int line_length;
556 /* If nonzero, the file listing format requires that stat be called on
557 each file. */
559 static int format_needs_stat;
561 /* The exit status to use if we don't get any fatal errors. */
563 static int exit_status;
565 static struct option const long_options[] =
567 {"all", no_argument, 0, 'a'},
568 {"escape", no_argument, 0, 'b'},
569 {"directory", no_argument, 0, 'd'},
570 {"dired", no_argument, 0, 'D'},
571 {"full-time", no_argument, &full_time, 1},
572 {"human-readable", no_argument, 0, 'h'},
573 {"inode", no_argument, 0, 'i'},
574 {"kilobytes", no_argument, 0, 'k'},
575 {"numeric-uid-gid", no_argument, 0, 'n'},
576 {"no-group", no_argument, 0, 'G'},
577 {"hide-control-chars", no_argument, 0, 'q'},
578 {"reverse", no_argument, 0, 'r'},
579 {"size", no_argument, 0, 's'},
580 {"width", required_argument, 0, 'w'},
581 {"almost-all", no_argument, 0, 'A'},
582 {"ignore-backups", no_argument, 0, 'B'},
583 {"classify", no_argument, 0, 'F'},
584 {"file-type", no_argument, 0, 'p'},
585 {"si", no_argument, 0, 'H'},
586 {"ignore", required_argument, 0, 'I'},
587 {"indicator-style", required_argument, 0, 14},
588 {"dereference", no_argument, 0, 'L'},
589 {"literal", no_argument, 0, 'N'},
590 {"quote-name", no_argument, 0, 'Q'},
591 {"quoting-style", required_argument, 0, 15},
592 {"recursive", no_argument, 0, 'R'},
593 {"format", required_argument, 0, 12},
594 {"show-control-chars", no_argument, 0, 16},
595 {"sort", required_argument, 0, 10},
596 {"tabsize", required_argument, 0, 'T'},
597 {"time", required_argument, 0, 11},
598 {"color", optional_argument, 0, 13},
599 {"block-size", required_argument, 0, 17},
600 {GETOPT_HELP_OPTION_DECL},
601 {GETOPT_VERSION_OPTION_DECL},
602 {NULL, 0, NULL, 0}
605 static char const *const format_args[] =
607 "verbose", "long", "commas", "horizontal", "across",
608 "vertical", "single-column", 0
611 static enum format const format_types[] =
613 long_format, long_format, with_commas, horizontal, horizontal,
614 many_per_line, one_per_line
617 static char const *const sort_args[] =
619 "none", "time", "size", "extension", "version", 0
622 static enum sort_type const sort_types[] =
624 sort_none, sort_time, sort_size, sort_extension, sort_version
627 static char const *const time_args[] =
629 "atime", "access", "use", "ctime", "status", 0
632 static enum time_type const time_types[] =
634 time_atime, time_atime, time_atime, time_ctime, time_ctime
637 static char const *const color_args[] =
639 /* force and none are for compatibility with another color-ls version */
640 "always", "yes", "force",
641 "never", "no", "none",
642 "auto", "tty", "if-tty", 0
645 static enum color_type const color_types[] =
647 color_always, color_always, color_always,
648 color_never, color_never, color_never,
649 color_if_tty, color_if_tty, color_if_tty
652 /* Information about filling a column. */
653 struct column_info
655 int valid_len;
656 int line_len;
657 int *col_arr;
660 /* Array with information about column filledness. */
661 static struct column_info *column_info;
663 /* Maximum number of columns ever possible for this display. */
664 static int max_idx;
666 /* The minimum width of a colum is 3: 1 character for the name and 2
667 for the separating white space. */
668 #define MIN_COLUMN_WIDTH 3
671 /* This zero-based index is used solely with the --dired option.
672 When that option is in effect, this counter is incremented for each
673 character of output generated by this program so that the beginning
674 and ending indices (in that output) of every file name can be recorded
675 and later output themselves. */
676 static size_t dired_pos;
678 #define DIRED_PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)
680 /* Write S to STREAM and increment DIRED_POS by S_LEN. */
681 #define DIRED_FPUTS(s, stream, s_len) \
682 do {fputs ((s), (stream)); dired_pos += s_len;} while (0)
684 /* Like DIRED_FPUTS, but for use when S is a literal string. */
685 #define DIRED_FPUTS_LITERAL(s, stream) \
686 do {fputs ((s), (stream)); dired_pos += sizeof((s)) - 1;} while (0)
688 #define DIRED_INDENT() \
689 do \
691 /* FIXME: remove the `&& format == long_format' clause. */ \
692 if (dired && format == long_format) \
693 DIRED_FPUTS_LITERAL (" ", stdout); \
695 while (0)
697 /* With --dired, store pairs of beginning and ending indices of filenames. */
698 static struct obstack dired_obstack;
700 /* With --dired, store pairs of beginning and ending indices of any
701 directory names that appear as headers (just before `total' line)
702 for lists of directory entries. Such directory names are seen when
703 listing hierarchies using -R and when a directory is listed with at
704 least one other command line argument. */
705 static struct obstack subdired_obstack;
707 /* Save the current index on the specified obstack, OBS. */
708 #define PUSH_CURRENT_DIRED_POS(obs) \
709 do \
711 /* FIXME: remove the `&& format == long_format' clause. */ \
712 if (dired && format == long_format) \
713 obstack_grow ((obs), &dired_pos, sizeof (dired_pos)); \
715 while (0)
718 /* Write to standard output PREFIX, followed by the quoting style and
719 a space-separated list of the integers stored in OS all on one line. */
721 static void
722 dired_dump_obstack (const char *prefix, struct obstack *os)
724 int n_pos;
726 n_pos = obstack_object_size (os) / sizeof (dired_pos);
727 if (n_pos > 0)
729 int i;
730 size_t *pos;
732 pos = (size_t *) obstack_finish (os);
733 fputs (prefix, stdout);
734 for (i = 0; i < n_pos; i++)
735 printf (" %d", (int) pos[i]);
736 fputs ("\n", stdout);
741 main (int argc, char **argv)
743 register int i;
744 register struct pending *thispend;
746 program_name = argv[0];
747 setlocale (LC_ALL, "");
748 bindtextdomain (PACKAGE, LOCALEDIR);
749 textdomain (PACKAGE);
751 #define N_ENTRIES(Array) (sizeof Array / sizeof *(Array))
752 assert (N_ENTRIES (color_indicator) + 1 == N_ENTRIES (indicator_name));
754 exit_status = 0;
755 dir_defaulted = 1;
756 print_dir_name = 1;
757 pending_dirs = 0;
758 current_time = time ((time_t *) 0);
760 i = decode_switches (argc, argv);
762 if (print_with_color)
764 parse_ls_color ();
765 prep_non_filename_text ();
768 format_needs_stat = sort_type == sort_time || sort_type == sort_size
769 || format == long_format
770 || trace_links || trace_dirs || indicator_style != none
771 || print_block_size || print_inode || print_with_color;
773 if (dired && format == long_format)
775 obstack_init (&dired_obstack);
776 obstack_init (&subdired_obstack);
779 nfiles = 100;
780 files = (struct fileinfo *) xmalloc (sizeof (struct fileinfo) * nfiles);
781 files_index = 0;
783 clear_files ();
785 if (i < argc)
786 dir_defaulted = 0;
787 for (; i < argc; i++)
789 strip_trailing_slashes (argv[i]);
790 gobble_file (argv[i], 1, "");
793 if (dir_defaulted)
795 if (immediate_dirs)
796 gobble_file (".", 1, "");
797 else
798 queue_directory (".", 0);
801 if (files_index)
803 sort_files ();
804 if (!immediate_dirs)
805 extract_dirs_from_files ("", 0);
806 /* `files_index' might be zero now. */
808 if (files_index)
810 print_current_files ();
811 if (pending_dirs)
812 DIRED_PUTCHAR ('\n');
814 else if (pending_dirs && pending_dirs->next == 0)
815 print_dir_name = 0;
817 while (pending_dirs)
819 thispend = pending_dirs;
820 pending_dirs = pending_dirs->next;
821 print_dir (thispend->name, thispend->realname);
822 free (thispend->name);
823 if (thispend->realname)
824 free (thispend->realname);
825 free (thispend);
826 print_dir_name = 1;
829 if (dired && format == long_format)
831 /* No need to free these since we're about to exit. */
832 dired_dump_obstack ("//DIRED//", &dired_obstack);
833 dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);
834 printf ("//DIRED-OPTIONS// --quoting-style=%s\n",
835 ARGMATCH_TO_ARGUMENT (filename_quoting_options,
836 quoting_style_args, quoting_style_vals));
839 /* Restore default color before exiting */
840 if (print_with_color)
842 put_indicator (&color_indicator[C_LEFT]);
843 put_indicator (&color_indicator[C_RIGHT]);
846 close_stdout ();
847 exit (exit_status);
850 /* Set all the option flags according to the switches specified.
851 Return the index of the first non-option argument. */
853 static int
854 decode_switches (int argc, char **argv)
856 register char const *p;
857 int c;
858 int i;
859 long int tmp_long;
861 qmark_funny_chars = 0;
863 /* initialize all switches to default settings */
865 switch (ls_mode)
867 case LS_MULTI_COL:
868 /* This is for the `dir' program. */
869 format = many_per_line;
870 set_quoting_style (NULL, escape_quoting_style);
871 break;
873 case LS_LONG_FORMAT:
874 /* This is for the `vdir' program. */
875 format = long_format;
876 set_quoting_style (NULL, escape_quoting_style);
877 break;
879 case LS_LS:
880 /* This is for the `ls' program. */
881 if (isatty (STDOUT_FILENO))
883 format = many_per_line;
884 /* See description of qmark_funny_chars, above. */
885 qmark_funny_chars = 1;
887 else
889 format = one_per_line;
890 qmark_funny_chars = 0;
892 break;
894 default:
895 abort ();
898 time_type = time_mtime;
899 full_time = 0;
900 sort_type = sort_name;
901 sort_reverse = 0;
902 numeric_ids = 0;
903 print_block_size = 0;
904 indicator_style = none;
905 print_inode = 0;
906 trace_links = 0;
907 trace_dirs = 0;
908 immediate_dirs = 0;
909 all_files = 0;
910 really_all_files = 0;
911 ignore_patterns = 0;
913 /* FIXME: Shouldn't we complain on wrong values? */
914 if ((p = getenv ("QUOTING_STYLE"))
915 && 0 <= (i = ARGCASEMATCH (p, quoting_style_args, quoting_style_vals)))
916 set_quoting_style (NULL, quoting_style_vals[i]);
918 human_block_size (getenv ("LS_BLOCK_SIZE"), 0, &output_block_size);
920 line_length = 80;
921 if ((p = getenv ("COLUMNS")) && *p)
923 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
924 && 0 < tmp_long && tmp_long <= INT_MAX)
926 line_length = (int) tmp_long;
928 else
930 error (0, 0,
931 _("ignoring invalid width in environment variable COLUMNS: %s"),
932 quotearg (p));
936 #ifdef TIOCGWINSZ
938 struct winsize ws;
940 if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1 && ws.ws_col != 0)
941 line_length = ws.ws_col;
943 #endif
945 /* Using the TABSIZE environment variable is not POSIX-approved.
946 Ignore it when POSIXLY_CORRECT is set. */
947 tabsize = 8;
948 if (!getenv ("POSIXLY_CORRECT") && (p = getenv ("TABSIZE")))
950 if (xstrtol (p, NULL, 0, &tmp_long, NULL) == LONGINT_OK
951 && 0 <= tmp_long && tmp_long <= INT_MAX)
953 tabsize = (int) tmp_long;
955 else
957 error (0, 0,
958 _("ignoring invalid tab size in environment variable TABSIZE: %s"),
959 quotearg (p));
963 while ((c = getopt_long (argc, argv,
964 "abcdefghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
965 long_options, NULL)) != -1)
967 switch (c)
969 case 0:
970 break;
972 case 'a':
973 all_files = 1;
974 really_all_files = 1;
975 break;
977 case 'b':
978 set_quoting_style (NULL, escape_quoting_style);
979 break;
981 case 'c':
982 time_type = time_ctime;
983 sort_type = sort_time;
984 break;
986 case 'd':
987 immediate_dirs = 1;
988 break;
990 case 'f':
991 /* Same as enabling -a -U and disabling -l -s. */
992 all_files = 1;
993 really_all_files = 1;
994 sort_type = sort_none;
995 /* disable -l */
996 if (format == long_format)
997 format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);
998 print_block_size = 0; /* disable -s */
999 print_with_color = 0; /* disable --color */
1000 break;
1002 case 'g':
1003 /* No effect. For BSD compatibility. */
1004 break;
1006 case 'h':
1007 output_block_size = -1024;
1008 break;
1010 case 'H':
1011 output_block_size = -1000;
1012 break;
1014 case 'i':
1015 print_inode = 1;
1016 break;
1018 case 'k':
1019 output_block_size = 1024;
1020 break;
1022 case 'l':
1023 format = long_format;
1024 break;
1026 case 'm':
1027 format = with_commas;
1028 break;
1030 case 'n':
1031 numeric_ids = 1;
1032 break;
1034 case 'o': /* Just like -l, but don't display group info. */
1035 format = long_format;
1036 inhibit_group = 1;
1037 break;
1039 case 'p':
1040 indicator_style = file_type;
1041 break;
1043 case 'q':
1044 qmark_funny_chars = 1;
1045 break;
1047 case 'r':
1048 sort_reverse = 1;
1049 break;
1051 case 's':
1052 print_block_size = 1;
1053 break;
1055 case 't':
1056 sort_type = sort_time;
1057 break;
1059 case 'u':
1060 sort_type = sort_time;
1061 time_type = time_atime;
1062 break;
1064 case 'v':
1065 sort_type = sort_version;
1066 break;
1068 case 'w':
1069 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1070 || tmp_long <= 0 || tmp_long > INT_MAX)
1071 error (EXIT_FAILURE, 0, _("invalid line width: %s"),
1072 quotearg (optarg));
1073 line_length = (int) tmp_long;
1074 break;
1076 case 'x':
1077 format = horizontal;
1078 break;
1080 case 'A':
1081 really_all_files = 0;
1082 all_files = 1;
1083 break;
1085 case 'B':
1086 add_ignore_pattern ("*~");
1087 add_ignore_pattern (".*~");
1088 break;
1090 case 'C':
1091 format = many_per_line;
1092 break;
1094 case 'D':
1095 dired = 1;
1096 break;
1098 case 'F':
1099 indicator_style = classify;
1100 break;
1102 case 'G': /* inhibit display of group info */
1103 inhibit_group = 1;
1104 break;
1106 case 'I':
1107 add_ignore_pattern (optarg);
1108 break;
1110 case 'L':
1111 trace_links = 1;
1112 break;
1114 case 'N':
1115 set_quoting_style (NULL, literal_quoting_style);
1116 break;
1118 case 'Q':
1119 set_quoting_style (NULL, c_quoting_style);
1120 break;
1122 case 'R':
1123 trace_dirs = 1;
1124 break;
1126 case 'S':
1127 sort_type = sort_size;
1128 break;
1130 case 'T':
1131 if (xstrtol (optarg, NULL, 0, &tmp_long, NULL) != LONGINT_OK
1132 || tmp_long < 0 || tmp_long > INT_MAX)
1133 error (EXIT_FAILURE, 0, _("invalid tab size: %s"),
1134 quotearg (optarg));
1135 tabsize = (int) tmp_long;
1136 break;
1138 case 'U':
1139 sort_type = sort_none;
1140 break;
1142 case 'X':
1143 sort_type = sort_extension;
1144 break;
1146 case '1':
1147 format = one_per_line;
1148 break;
1150 case 10: /* --sort */
1151 sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);
1152 break;
1154 case 11: /* --time */
1155 time_type = XARGMATCH ("--time", optarg, time_args, time_types);
1156 break;
1158 case 12: /* --format */
1159 format = XARGMATCH ("--format", optarg, format_args, format_types);
1160 break;
1162 case 13: /* --color */
1163 if (optarg)
1164 i = XARGMATCH ("--color", optarg, color_args, color_types);
1165 else
1166 /* Using --color with no argument is equivalent to using
1167 --color=always. */
1168 i = color_always;
1170 print_with_color = (i == color_always
1171 || (i == color_if_tty
1172 && isatty (STDOUT_FILENO)));
1174 if (print_with_color)
1176 /* Don't use TAB characters in output. Some terminal
1177 emulators can't handle the combination of tabs and
1178 color codes on the same line. */
1179 tabsize = 0;
1181 break;
1183 case 14: /* --indicator-style */
1184 indicator_style = XARGMATCH ("--indicator-style", optarg,
1185 indicator_style_args,
1186 indicator_style_types);
1187 break;
1189 case 15: /* --quoting-style */
1190 set_quoting_style (NULL,
1191 XARGMATCH ("--quoting-style", optarg,
1192 quoting_style_args,
1193 quoting_style_vals));
1194 break;
1196 case 16:
1197 qmark_funny_chars = 0;
1198 break;
1200 case 17:
1201 human_block_size (optarg, 1, &output_block_size);
1202 break;
1204 case_GETOPT_HELP_CHAR;
1206 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
1208 default:
1209 usage (EXIT_FAILURE);
1213 filename_quoting_options = clone_quoting_options (NULL);
1214 if (get_quoting_style (filename_quoting_options) == escape_quoting_style)
1215 set_char_quoting (filename_quoting_options, ' ', 1);
1216 if (indicator_style != none)
1217 for (p = "*=@|" + (int) indicator_style - 1; *p; p++)
1218 set_char_quoting (filename_quoting_options, *p, 1);
1220 dirname_quoting_options = clone_quoting_options (NULL);
1221 set_char_quoting (dirname_quoting_options, ':', 1);
1223 return optind;
1226 /* Parse a string as part of the LS_COLORS variable; this may involve
1227 decoding all kinds of escape characters. If equals_end is set an
1228 unescaped equal sign ends the string, otherwise only a : or \0
1229 does. Returns the number of characters output, or -1 on failure.
1231 The resulting string is *not* null-terminated, but may contain
1232 embedded nulls.
1234 Note that both dest and src are char **; on return they point to
1235 the first free byte after the array and the character that ended
1236 the input string, respectively. */
1238 static int
1239 get_funky_string (char **dest, const char **src, int equals_end)
1241 int num; /* For numerical codes */
1242 int count; /* Something to count with */
1243 enum {
1244 ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR
1245 } state;
1246 const char *p;
1247 char *q;
1249 p = *src; /* We don't want to double-indirect */
1250 q = *dest; /* the whole darn time. */
1252 count = 0; /* No characters counted in yet. */
1253 num = 0;
1255 state = ST_GND; /* Start in ground state. */
1256 while (state < ST_END)
1258 switch (state)
1260 case ST_GND: /* Ground state (no escapes) */
1261 switch (*p)
1263 case ':':
1264 case '\0':
1265 state = ST_END; /* End of string */
1266 break;
1267 case '\\':
1268 state = ST_BACKSLASH; /* Backslash scape sequence */
1269 ++p;
1270 break;
1271 case '^':
1272 state = ST_CARET; /* Caret escape */
1273 ++p;
1274 break;
1275 case '=':
1276 if (equals_end)
1278 state = ST_END; /* End */
1279 break;
1281 /* else fall through */
1282 default:
1283 *(q++) = *(p++);
1284 ++count;
1285 break;
1287 break;
1289 case ST_BACKSLASH: /* Backslash escaped character */
1290 switch (*p)
1292 case '0':
1293 case '1':
1294 case '2':
1295 case '3':
1296 case '4':
1297 case '5':
1298 case '6':
1299 case '7':
1300 state = ST_OCTAL; /* Octal sequence */
1301 num = *p - '0';
1302 break;
1303 case 'x':
1304 case 'X':
1305 state = ST_HEX; /* Hex sequence */
1306 num = 0;
1307 break;
1308 case 'a': /* Bell */
1309 num = 7; /* Not all C compilers know what \a means */
1310 break;
1311 case 'b': /* Backspace */
1312 num = '\b';
1313 break;
1314 case 'e': /* Escape */
1315 num = 27;
1316 break;
1317 case 'f': /* Form feed */
1318 num = '\f';
1319 break;
1320 case 'n': /* Newline */
1321 num = '\n';
1322 break;
1323 case 'r': /* Carriage return */
1324 num = '\r';
1325 break;
1326 case 't': /* Tab */
1327 num = '\t';
1328 break;
1329 case 'v': /* Vtab */
1330 num = '\v';
1331 break;
1332 case '?': /* Delete */
1333 num = 127;
1334 break;
1335 case '_': /* Space */
1336 num = ' ';
1337 break;
1338 case '\0': /* End of string */
1339 state = ST_ERROR; /* Error! */
1340 break;
1341 default: /* Escaped character like \ ^ : = */
1342 num = *p;
1343 break;
1345 if (state == ST_BACKSLASH)
1347 *(q++) = num;
1348 ++count;
1349 state = ST_GND;
1351 ++p;
1352 break;
1354 case ST_OCTAL: /* Octal sequence */
1355 if (*p < '0' || *p > '7')
1357 *(q++) = num;
1358 ++count;
1359 state = ST_GND;
1361 else
1362 num = (num << 3) + (*(p++) - '0');
1363 break;
1365 case ST_HEX: /* Hex sequence */
1366 switch (*p)
1368 case '0':
1369 case '1':
1370 case '2':
1371 case '3':
1372 case '4':
1373 case '5':
1374 case '6':
1375 case '7':
1376 case '8':
1377 case '9':
1378 num = (num << 4) + (*(p++) - '0');
1379 break;
1380 case 'a':
1381 case 'b':
1382 case 'c':
1383 case 'd':
1384 case 'e':
1385 case 'f':
1386 num = (num << 4) + (*(p++) - 'a') + 10;
1387 break;
1388 case 'A':
1389 case 'B':
1390 case 'C':
1391 case 'D':
1392 case 'E':
1393 case 'F':
1394 num = (num << 4) + (*(p++) - 'A') + 10;
1395 break;
1396 default:
1397 *(q++) = num;
1398 ++count;
1399 state = ST_GND;
1400 break;
1402 break;
1404 case ST_CARET: /* Caret escape */
1405 state = ST_GND; /* Should be the next state... */
1406 if (*p >= '@' && *p <= '~')
1408 *(q++) = *(p++) & 037;
1409 ++count;
1411 else if (*p == '?')
1413 *(q++) = 127;
1414 ++count;
1416 else
1417 state = ST_ERROR;
1418 break;
1420 default:
1421 abort ();
1425 *dest = q;
1426 *src = p;
1428 return state == ST_ERROR ? -1 : count;
1431 static void
1432 parse_ls_color (void)
1434 const char *p; /* Pointer to character being parsed */
1435 char *buf; /* color_buf buffer pointer */
1436 int state; /* State of parser */
1437 int ind_no; /* Indicator number */
1438 char label[3]; /* Indicator label */
1439 struct color_ext_type *ext; /* Extension we are working on */
1441 if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
1442 return;
1444 ext = NULL;
1445 strcpy (label, "??");
1447 /* This is an overly conservative estimate, but any possible
1448 LS_COLORS string will *not* generate a color_buf longer than
1449 itself, so it is a safe way of allocating a buffer in
1450 advance. */
1451 buf = color_buf = xstrdup (p);
1453 state = 1;
1454 while (state > 0)
1456 switch (state)
1458 case 1: /* First label character */
1459 switch (*p)
1461 case ':':
1462 ++p;
1463 break;
1465 case '*':
1466 /* Allocate new extension block and add to head of
1467 linked list (this way a later definition will
1468 override an earlier one, which can be useful for
1469 having terminal-specific defs override global). */
1471 ext = (struct color_ext_type *)
1472 xmalloc (sizeof (struct color_ext_type));
1473 ext->next = color_ext_list;
1474 color_ext_list = ext;
1476 ++p;
1477 ext->ext.string = buf;
1479 state = (ext->ext.len =
1480 get_funky_string (&buf, &p, 1)) < 0 ? -1 : 4;
1481 break;
1483 case '\0':
1484 state = 0; /* Done! */
1485 break;
1487 default: /* Assume it is file type label */
1488 label[0] = *(p++);
1489 state = 2;
1490 break;
1492 break;
1494 case 2: /* Second label character */
1495 if (*p)
1497 label[1] = *(p++);
1498 state = 3;
1500 else
1501 state = -1; /* Error */
1502 break;
1504 case 3: /* Equal sign after indicator label */
1505 state = -1; /* Assume failure... */
1506 if (*(p++) == '=')/* It *should* be... */
1508 for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)
1510 if (STREQ (label, indicator_name[ind_no]))
1512 color_indicator[ind_no].string = buf;
1513 state = ((color_indicator[ind_no].len =
1514 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1);
1515 break;
1518 if (state == -1)
1519 error (0, 0, _("unrecognized prefix: %s"), quotearg (label));
1521 break;
1523 case 4: /* Equal sign after *.ext */
1524 if (*(p++) == '=')
1526 ext->seq.string = buf;
1527 state = (ext->seq.len =
1528 get_funky_string (&buf, &p, 0)) < 0 ? -1 : 1;
1530 else
1531 state = -1;
1532 break;
1536 if (state < 0)
1538 struct color_ext_type *e;
1539 struct color_ext_type *e2;
1541 error (0, 0,
1542 _("unparsable value for LS_COLORS environment variable"));
1543 free (color_buf);
1544 for (e = color_ext_list; e != NULL; /* empty */)
1546 e2 = e;
1547 e = e->next;
1548 free (e2);
1550 print_with_color = 0;
1554 /* Request that the directory named `name' have its contents listed later.
1555 If `realname' is nonzero, it will be used instead of `name' when the
1556 directory name is printed. This allows symbolic links to directories
1557 to be treated as regular directories but still be listed under their
1558 real names. */
1560 static void
1561 queue_directory (const char *name, const char *realname)
1563 struct pending *new;
1565 new = (struct pending *) xmalloc (sizeof (struct pending));
1566 new->next = pending_dirs;
1567 pending_dirs = new;
1568 new->name = xstrdup (name);
1569 if (realname)
1570 new->realname = xstrdup (realname);
1571 else
1572 new->realname = 0;
1575 /* Read directory `name', and list the files in it.
1576 If `realname' is nonzero, print its name instead of `name';
1577 this is used for symbolic links to directories. */
1579 static void
1580 print_dir (const char *name, const char *realname)
1582 register DIR *reading;
1583 register struct dirent *next;
1584 register uintmax_t total_blocks = 0;
1586 errno = 0;
1587 reading = opendir (name);
1588 if (!reading)
1590 error (0, errno, "%s", quotearg_colon (name));
1591 exit_status = 1;
1592 return;
1595 /* Read the directory entries, and insert the subfiles into the `files'
1596 table. */
1598 clear_files ();
1600 while ((next = readdir (reading)) != NULL)
1601 if (file_interesting (next))
1602 total_blocks += gobble_file (next->d_name, 0, name);
1604 if (CLOSEDIR (reading))
1606 error (0, errno, "%s", quotearg_colon (name));
1607 exit_status = 1;
1608 /* Don't return; print whatever we got. */
1611 /* Sort the directory contents. */
1612 sort_files ();
1614 /* If any member files are subdirectories, perhaps they should have their
1615 contents listed rather than being mentioned here as files. */
1617 if (trace_dirs)
1618 extract_dirs_from_files (name, 1);
1620 if (trace_dirs || print_dir_name)
1622 DIRED_INDENT ();
1623 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1624 dired_pos += quote_name (stdout, realname ? realname : name,
1625 dirname_quoting_options);
1626 PUSH_CURRENT_DIRED_POS (&subdired_obstack);
1627 DIRED_FPUTS_LITERAL (":\n", stdout);
1630 if (format == long_format || print_block_size)
1632 const char *p;
1633 char buf[LONGEST_HUMAN_READABLE + 1];
1635 DIRED_INDENT ();
1636 p = _("total");
1637 DIRED_FPUTS (p, stdout, strlen (p));
1638 DIRED_PUTCHAR (' ');
1639 p = human_readable (total_blocks, buf, ST_NBLOCKSIZE, output_block_size);
1640 DIRED_FPUTS (p, stdout, strlen (p));
1641 DIRED_PUTCHAR ('\n');
1644 if (files_index)
1645 print_current_files ();
1647 if (pending_dirs)
1648 DIRED_PUTCHAR ('\n');
1651 /* Add `pattern' to the list of patterns for which files that match are
1652 not listed. */
1654 static void
1655 add_ignore_pattern (const char *pattern)
1657 register struct ignore_pattern *ignore;
1659 ignore = (struct ignore_pattern *) xmalloc (sizeof (struct ignore_pattern));
1660 ignore->pattern = pattern;
1661 /* Add it to the head of the linked list. */
1662 ignore->next = ignore_patterns;
1663 ignore_patterns = ignore;
1666 /* Return nonzero if the file in `next' should be listed. */
1668 static int
1669 file_interesting (const struct dirent *next)
1671 register struct ignore_pattern *ignore;
1673 for (ignore = ignore_patterns; ignore; ignore = ignore->next)
1674 if (fnmatch (ignore->pattern, next->d_name, FNM_PERIOD) == 0)
1675 return 0;
1677 if (really_all_files
1678 || next->d_name[0] != '.'
1679 || (all_files
1680 && next->d_name[1] != '\0'
1681 && (next->d_name[1] != '.' || next->d_name[2] != '\0')))
1682 return 1;
1684 return 0;
1687 /* Enter and remove entries in the table `files'. */
1689 /* Empty the table of files. */
1691 static void
1692 clear_files (void)
1694 register int i;
1696 for (i = 0; i < files_index; i++)
1698 free (files[i].name);
1699 if (files[i].linkname)
1700 free (files[i].linkname);
1703 files_index = 0;
1704 block_size_size = 4;
1707 /* Add a file to the current table of files.
1708 Verify that the file exists, and print an error message if it does not.
1709 Return the number of blocks that the file occupies. */
1711 static uintmax_t
1712 gobble_file (const char *name, int explicit_arg, const char *dirname)
1714 register uintmax_t blocks;
1715 register int val;
1716 register char *path;
1718 if (files_index == nfiles)
1720 nfiles *= 2;
1721 files = (struct fileinfo *) xrealloc ((char *) files,
1722 sizeof (*files) * nfiles);
1725 files[files_index].linkname = 0;
1726 files[files_index].linkmode = 0;
1727 files[files_index].linkok = 0;
1729 if (explicit_arg || format_needs_stat)
1731 /* `path' is the absolute pathname of this file. */
1733 if (name[0] == '/' || dirname[0] == 0)
1734 path = (char *) name;
1735 else
1737 path = (char *) alloca (strlen (name) + strlen (dirname) + 2);
1738 attach (path, dirname, name);
1741 if (trace_links)
1743 val = stat (path, &files[files_index].stat);
1744 if (val < 0)
1746 /* Perhaps a symbolically-linked to file doesn't exist; stat
1747 the link instead. */
1748 val = lstat (path, &files[files_index].stat);
1751 else
1753 val = lstat (path, &files[files_index].stat);
1754 #if USE_ACL
1755 files[files_index].have_acl = (acl (path, GETACLCNT, 0, NULL) > 4);
1756 #endif
1759 if (val < 0)
1761 error (0, errno, "%s", quotearg_colon (path));
1762 exit_status = 1;
1763 return 0;
1766 if (S_ISLNK (files[files_index].stat.st_mode)
1767 && (explicit_arg || format == long_format || print_with_color))
1769 char *linkpath;
1770 struct stat linkstats;
1772 get_link_name (path, &files[files_index]);
1773 linkpath = make_link_path (path, files[files_index].linkname);
1775 /* Avoid following symbolic links when possible, ie, when
1776 they won't be traced and when no indicator is needed. */
1777 if (linkpath
1778 && ((explicit_arg && format != long_format)
1779 || indicator_style != none
1780 || print_with_color)
1781 && stat (linkpath, &linkstats) == 0)
1783 files[files_index].linkok = 1;
1785 /* Symbolic links to directories that are mentioned on the
1786 command line are automatically traced if not being
1787 listed as files. */
1788 if (explicit_arg && format != long_format
1789 && S_ISDIR (linkstats.st_mode))
1791 /* Substitute the linked-to directory's name, but
1792 save the real name in `linkname' for printing. */
1793 if (!immediate_dirs)
1795 const char *tempname = name;
1796 name = linkpath;
1797 linkpath = files[files_index].linkname;
1798 files[files_index].linkname = (char *) tempname;
1800 files[files_index].stat = linkstats;
1802 else
1804 /* Get the linked-to file's mode for the filetype indicator
1805 in long listings. */
1806 files[files_index].linkmode = linkstats.st_mode;
1807 files[files_index].linkok = 1;
1810 if (linkpath)
1811 free (linkpath);
1814 if (S_ISLNK (files[files_index].stat.st_mode))
1815 files[files_index].filetype = symbolic_link;
1816 else if (S_ISDIR (files[files_index].stat.st_mode))
1818 if (explicit_arg && !immediate_dirs)
1819 files[files_index].filetype = arg_directory;
1820 else
1821 files[files_index].filetype = directory;
1823 else
1824 files[files_index].filetype = normal;
1826 blocks = ST_NBLOCKS (files[files_index].stat);
1828 char buf[LONGEST_HUMAN_READABLE + 1];
1829 int len = strlen (human_readable (blocks, buf, ST_NBLOCKSIZE,
1830 output_block_size));
1831 if (block_size_size < len)
1832 block_size_size = len < 7 ? len : 7;
1835 else
1836 blocks = 0;
1838 files[files_index].name = xstrdup (name);
1839 files_index++;
1841 return blocks;
1844 #if HAVE_SYMLINKS
1846 /* Put the name of the file that `filename' is a symbolic link to
1847 into the `linkname' field of `f'. */
1849 static void
1850 get_link_name (const char *filename, struct fileinfo *f)
1852 char *linkbuf;
1853 register int linksize;
1855 linkbuf = (char *) alloca (PATH_MAX + 2);
1856 /* Some automounters give incorrect st_size for mount points.
1857 I can't think of a good workaround for it, though. */
1858 linksize = readlink (filename, linkbuf, PATH_MAX + 1);
1859 if (linksize < 0)
1861 error (0, errno, "%s", quotearg_colon (filename));
1862 exit_status = 1;
1864 else
1866 linkbuf[linksize] = '\0';
1867 f->linkname = xstrdup (linkbuf);
1871 /* If `linkname' is a relative path and `path' contains one or more
1872 leading directories, return `linkname' with those directories
1873 prepended; otherwise, return a copy of `linkname'.
1874 If `linkname' is zero, return zero. */
1876 static char *
1877 make_link_path (const char *path, const char *linkname)
1879 char *linkbuf;
1880 int bufsiz;
1882 if (linkname == 0)
1883 return 0;
1885 if (*linkname == '/')
1886 return xstrdup (linkname);
1888 /* The link is to a relative path. Prepend any leading path
1889 in `path' to the link name. */
1890 linkbuf = strrchr (path, '/');
1891 if (linkbuf == 0)
1892 return xstrdup (linkname);
1894 bufsiz = linkbuf - path + 1;
1895 linkbuf = xmalloc (bufsiz + strlen (linkname) + 1);
1896 strncpy (linkbuf, path, bufsiz);
1897 strcpy (linkbuf + bufsiz, linkname);
1898 return linkbuf;
1900 #endif
1902 /* Return nonzero if base_name (NAME) ends in `.' or `..'
1903 This is so we don't try to recurse on `././././. ...' */
1905 static int
1906 basename_is_dot_or_dotdot (const char *name)
1908 char *base = base_name (name);
1909 return DOT_OR_DOTDOT (base);
1912 /* Remove any entries from `files' that are for directories,
1913 and queue them to be listed as directories instead.
1914 `dirname' is the prefix to prepend to each dirname
1915 to make it correct relative to ls's working dir.
1916 `recursive' is nonzero if we should not treat `.' and `..' as dirs.
1917 This is desirable when processing directories recursively. */
1919 static void
1920 extract_dirs_from_files (const char *dirname, int recursive)
1922 register int i, j;
1923 int dirlen;
1925 dirlen = strlen (dirname) + 2;
1926 /* Queue the directories last one first, because queueing reverses the
1927 order. */
1928 for (i = files_index - 1; i >= 0; i--)
1929 if ((files[i].filetype == directory || files[i].filetype == arg_directory)
1930 && (!recursive || !basename_is_dot_or_dotdot (files[i].name)))
1932 if (files[i].name[0] == '/' || dirname[0] == 0)
1934 queue_directory (files[i].name, files[i].linkname);
1936 else
1938 char *path = path_concat (dirname, files[i].name, NULL);
1939 queue_directory (path, files[i].linkname);
1940 free (path);
1942 if (files[i].filetype == arg_directory)
1943 free (files[i].name);
1946 /* Now delete the directories from the table, compacting all the remaining
1947 entries. */
1949 for (i = 0, j = 0; i < files_index; i++)
1950 if (files[i].filetype != arg_directory)
1951 files[j++] = files[i];
1952 files_index = j;
1955 /* Sort the files now in the table. */
1957 static void
1958 sort_files (void)
1960 int (*func) ();
1962 switch (sort_type)
1964 case sort_none:
1965 return;
1966 case sort_time:
1967 switch (time_type)
1969 case time_ctime:
1970 func = sort_reverse ? rev_cmp_ctime : compare_ctime;
1971 break;
1972 case time_mtime:
1973 func = sort_reverse ? rev_cmp_mtime : compare_mtime;
1974 break;
1975 case time_atime:
1976 func = sort_reverse ? rev_cmp_atime : compare_atime;
1977 break;
1978 default:
1979 abort ();
1981 break;
1982 case sort_name:
1983 func = sort_reverse ? rev_cmp_name : compare_name;
1984 break;
1985 case sort_extension:
1986 func = sort_reverse ? rev_cmp_extension : compare_extension;
1987 break;
1988 case sort_size:
1989 func = sort_reverse ? rev_cmp_size : compare_size;
1990 break;
1991 case sort_version:
1992 func = sort_reverse ? rev_cmp_version : compare_version;
1993 break;
1994 default:
1995 abort ();
1998 qsort (files, files_index, sizeof (struct fileinfo), func);
2001 /* Comparison routines for sorting the files. */
2003 static int
2004 compare_ctime (const struct fileinfo *file1, const struct fileinfo *file2)
2006 int diff = CTIME_CMP (file2->stat, file1->stat);
2007 if (diff == 0)
2008 diff = strcmp (file1->name, file2->name);
2009 return diff;
2012 static int
2013 rev_cmp_ctime (const struct fileinfo *file2, const struct fileinfo *file1)
2015 int diff = CTIME_CMP (file2->stat, file1->stat);
2016 if (diff == 0)
2017 diff = strcmp (file1->name, file2->name);
2018 return diff;
2021 static int
2022 compare_mtime (const struct fileinfo *file1, const struct fileinfo *file2)
2024 int diff = MTIME_CMP (file2->stat, file1->stat);
2025 if (diff == 0)
2026 diff = strcmp (file1->name, file2->name);
2027 return diff;
2030 static int
2031 rev_cmp_mtime (const struct fileinfo *file2, const struct fileinfo *file1)
2033 int diff = MTIME_CMP (file2->stat, file1->stat);
2034 if (diff == 0)
2035 diff = strcmp (file1->name, file2->name);
2036 return diff;
2039 static int
2040 compare_atime (const struct fileinfo *file1, const struct fileinfo *file2)
2042 int diff = ATIME_CMP (file2->stat, file1->stat);
2043 if (diff == 0)
2044 diff = strcmp (file1->name, file2->name);
2045 return diff;
2048 static int
2049 rev_cmp_atime (const struct fileinfo *file2, const struct fileinfo *file1)
2051 int diff = ATIME_CMP (file2->stat, file1->stat);
2052 if (diff == 0)
2053 diff = strcmp (file1->name, file2->name);
2054 return diff;
2057 static int
2058 compare_size (const struct fileinfo *file1, const struct fileinfo *file2)
2060 int diff = longdiff (file2->stat.st_size, file1->stat.st_size);
2061 if (diff == 0)
2062 diff = strcmp (file1->name, file2->name);
2063 return diff;
2066 static int
2067 rev_cmp_size (const struct fileinfo *file2, const struct fileinfo *file1)
2069 int diff = longdiff (file2->stat.st_size, file1->stat.st_size);
2070 if (diff == 0)
2071 diff = strcmp (file1->name, file2->name);
2072 return diff;
2075 static int
2076 compare_version (const struct fileinfo *file1, const struct fileinfo *file2)
2078 return strverscmp (file1->name, file2->name);
2081 static int
2082 rev_cmp_version (const struct fileinfo *file2, const struct fileinfo *file1)
2084 return strverscmp (file1->name, file2->name);
2087 static int
2088 compare_name (const struct fileinfo *file1, const struct fileinfo *file2)
2090 return strcmp (file1->name, file2->name);
2093 static int
2094 rev_cmp_name (const struct fileinfo *file2, const struct fileinfo *file1)
2096 return strcmp (file1->name, file2->name);
2099 /* Compare file extensions. Files with no extension are `smallest'.
2100 If extensions are the same, compare by filenames instead. */
2102 static int
2103 compare_extension (const struct fileinfo *file1, const struct fileinfo *file2)
2105 register char *base1, *base2;
2106 register int cmp;
2108 base1 = strrchr (file1->name, '.');
2109 base2 = strrchr (file2->name, '.');
2110 if (base1 == 0 && base2 == 0)
2111 return strcmp (file1->name, file2->name);
2112 if (base1 == 0)
2113 return -1;
2114 if (base2 == 0)
2115 return 1;
2116 cmp = strcmp (base1, base2);
2117 if (cmp == 0)
2118 return strcmp (file1->name, file2->name);
2119 return cmp;
2122 static int
2123 rev_cmp_extension (const struct fileinfo *file2, const struct fileinfo *file1)
2125 register char *base1, *base2;
2126 register int cmp;
2128 base1 = strrchr (file1->name, '.');
2129 base2 = strrchr (file2->name, '.');
2130 if (base1 == 0 && base2 == 0)
2131 return strcmp (file1->name, file2->name);
2132 if (base1 == 0)
2133 return -1;
2134 if (base2 == 0)
2135 return 1;
2136 cmp = strcmp (base1, base2);
2137 if (cmp == 0)
2138 return strcmp (file1->name, file2->name);
2139 return cmp;
2142 /* List all the files now in the table. */
2144 static void
2145 print_current_files (void)
2147 register int i;
2149 switch (format)
2151 case one_per_line:
2152 for (i = 0; i < files_index; i++)
2154 print_file_name_and_frills (files + i);
2155 putchar ('\n');
2157 break;
2159 case many_per_line:
2160 init_column_info ();
2161 print_many_per_line ();
2162 break;
2164 case horizontal:
2165 init_column_info ();
2166 print_horizontal ();
2167 break;
2169 case with_commas:
2170 print_with_commas ();
2171 break;
2173 case long_format:
2174 for (i = 0; i < files_index; i++)
2176 print_long_format (files + i);
2177 DIRED_PUTCHAR ('\n');
2179 break;
2183 static void
2184 print_long_format (const struct fileinfo *f)
2186 char modebuf[12];
2188 /* 7 fields that may require LONGEST_HUMAN_READABLE bytes,
2189 1 10-byte mode string,
2190 1 24-byte time string (may be longer in some locales -- see below)
2191 or LONGEST_HUMAN_READABLE integer,
2192 9 spaces, one following each of these fields, and
2193 1 trailing NUL byte. */
2194 char init_bigbuf[7 * LONGEST_HUMAN_READABLE + 10
2195 + (LONGEST_HUMAN_READABLE < 24 ? 24 : LONGEST_HUMAN_READABLE)
2196 + 9 + 1];
2197 char *buf = init_bigbuf;
2198 size_t bufsize = sizeof (init_bigbuf);
2199 size_t s;
2200 char *p;
2201 time_t when;
2202 struct tm *when_local;
2203 const char *fmt;
2204 char *user_name;
2206 #if HAVE_ST_DM_MODE
2207 /* Cray DMF: look at the file's migrated, not real, status */
2208 mode_string (f->stat.st_dm_mode, modebuf);
2209 #else
2210 mode_string (f->stat.st_mode, modebuf);
2211 #endif
2213 modebuf[10] = (FILE_HAS_ACL (f) ? '+' : ' ');
2214 modebuf[11] = '\0';
2216 switch (time_type)
2218 case time_ctime:
2219 when = f->stat.st_ctime;
2220 break;
2221 case time_mtime:
2222 when = f->stat.st_mtime;
2223 break;
2224 case time_atime:
2225 when = f->stat.st_atime;
2226 break;
2229 if (full_time)
2231 fmt = "%a %b %d %H:%M:%S %Y";
2233 else
2235 if (current_time > when + 6L * 30L * 24L * 60L * 60L /* Old. */
2236 || current_time < when - 60L * 60L) /* In the future. */
2238 /* The file is fairly old or in the future.
2239 POSIX says the cutoff is 6 months old;
2240 approximate this by 6*30 days.
2241 Allow a 1 hour slop factor for what is considered "the future",
2242 to allow for NFS server/client clock disagreement.
2243 Show the year instead of the time of day. */
2244 fmt = "%b %e %Y";
2246 else
2248 fmt = "%b %e %H:%M";
2252 p = buf;
2254 if (print_inode)
2256 char hbuf[LONGEST_HUMAN_READABLE + 1];
2257 sprintf (p, "%*s ", INODE_DIGITS,
2258 human_readable ((uintmax_t) f->stat.st_ino, hbuf, 1, 1));
2259 p += strlen (p);
2262 if (print_block_size)
2264 char hbuf[LONGEST_HUMAN_READABLE + 1];
2265 sprintf (p, "%*s ", block_size_size,
2266 human_readable ((uintmax_t) ST_NBLOCKS (f->stat), hbuf,
2267 ST_NBLOCKSIZE, output_block_size));
2268 p += strlen (p);
2271 /* The last byte of the mode string is the POSIX
2272 "optional alternate access method flag". */
2273 sprintf (p, "%s %3u ", modebuf, (unsigned int) f->stat.st_nlink);
2274 p += strlen (p);
2276 user_name = (numeric_ids ? NULL : getuser (f->stat.st_uid));
2277 if (user_name)
2278 sprintf (p, "%-8.8s ", user_name);
2279 else
2280 sprintf (p, "%-8u ", (unsigned int) f->stat.st_uid);
2281 p += strlen (p);
2283 if (!inhibit_group)
2285 char *group_name = (numeric_ids ? NULL : getgroup (f->stat.st_gid));
2286 if (group_name)
2287 sprintf (p, "%-8.8s ", group_name);
2288 else
2289 sprintf (p, "%-8u ", (unsigned int) f->stat.st_gid);
2290 p += strlen (p);
2293 if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))
2294 sprintf (p, "%3u, %3u ", (unsigned) major (f->stat.st_rdev),
2295 (unsigned) minor (f->stat.st_rdev));
2296 else
2298 char hbuf[LONGEST_HUMAN_READABLE + 1];
2299 sprintf (p, "%8s ",
2300 human_readable ((uintmax_t) f->stat.st_size, hbuf, 1,
2301 output_block_size < 0 ? output_block_size : 1));
2304 p += strlen (p);
2306 /* Use strftime rather than ctime, because the former can produce
2307 locale-dependent names for the weekday (%a) and month (%b). */
2309 if ((when_local = localtime (&when)))
2311 while (! (s = strftime (p, buf + bufsize - p - 1, fmt, when_local)))
2313 char *newbuf = (char *) alloca (bufsize *= 2);
2314 memcpy (newbuf, buf, p - buf);
2315 p = newbuf + (p - buf);
2316 buf = newbuf;
2319 p += s;
2320 *p++ = ' ';
2322 /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it. */
2323 *p = '\0';
2325 else
2327 /* The time cannot be represented as a local time;
2328 print it as a huge integer number of seconds. */
2329 char hbuf[LONGEST_HUMAN_READABLE + 1];
2330 int width = full_time ? 24 : 12;
2332 if (when < 0)
2334 const char *num = human_readable (- (uintmax_t) when, hbuf, 1, 1);
2335 int sign_width = width - strlen (num);
2336 sprintf (p, "%*s%s ", sign_width < 0 ? 0 : sign_width, "-", num);
2338 else
2339 sprintf (p, "%*s ", width,
2340 human_readable ((uintmax_t) when, hbuf, 1, 1));
2342 p += strlen (p);
2345 DIRED_INDENT ();
2346 DIRED_FPUTS (buf, stdout, p - buf);
2347 print_name_with_quoting (f->name, f->stat.st_mode, f->linkok,
2348 &dired_obstack);
2350 if (f->filetype == symbolic_link)
2352 if (f->linkname)
2354 DIRED_FPUTS_LITERAL (" -> ", stdout);
2355 print_name_with_quoting (f->linkname, f->linkmode, f->linkok - 1,
2356 NULL);
2357 if (indicator_style != none)
2358 print_type_indicator (f->linkmode);
2361 else if (indicator_style != none)
2362 print_type_indicator (f->stat.st_mode);
2365 /* Output to OUT a quoted representation of the file name P,
2366 using OPTIONS to control quoting.
2367 Return the number of characters in P's quoted representation. */
2369 static size_t
2370 quote_name (FILE *out, const char *p, struct quoting_options const *options)
2372 char smallbuf[BUFSIZ];
2373 size_t len = quotearg_buffer (smallbuf, sizeof smallbuf, p, -1, options);
2374 char *buf;
2376 if (len < sizeof smallbuf)
2377 buf = smallbuf;
2378 else
2380 buf = (char *) alloca (len + 1);
2381 quotearg_buffer (buf, len + 1, p, -1, options);
2384 if (qmark_funny_chars)
2386 size_t i;
2387 for (i = 0; i < len; i++)
2388 if (! ISPRINT ((unsigned char) buf[i]))
2389 buf[i] = '?';
2392 fwrite (buf, 1, len, out);
2393 return len;
2396 static void
2397 print_name_with_quoting (const char *p, unsigned int mode, int linkok,
2398 struct obstack *stack)
2400 if (print_with_color)
2401 print_color_indicator (p, mode, linkok);
2403 if (stack)
2404 PUSH_CURRENT_DIRED_POS (stack);
2406 dired_pos += quote_name (stdout, p, filename_quoting_options);
2408 if (stack)
2409 PUSH_CURRENT_DIRED_POS (stack);
2411 if (print_with_color)
2412 prep_non_filename_text ();
2415 static void
2416 prep_non_filename_text (void)
2418 if (color_indicator[C_END].string != NULL)
2419 put_indicator (&color_indicator[C_END]);
2420 else
2422 put_indicator (&color_indicator[C_LEFT]);
2423 put_indicator (&color_indicator[C_NORM]);
2424 put_indicator (&color_indicator[C_RIGHT]);
2428 /* Print the file name of `f' with appropriate quoting.
2429 Also print file size, inode number, and filetype indicator character,
2430 as requested by switches. */
2432 static void
2433 print_file_name_and_frills (const struct fileinfo *f)
2435 char buf[LONGEST_HUMAN_READABLE + 1];
2437 if (print_inode)
2438 printf ("%*s ", INODE_DIGITS,
2439 human_readable ((uintmax_t) f->stat.st_ino, buf, 1, 1));
2441 if (print_block_size)
2442 printf ("%*s ", block_size_size,
2443 human_readable ((uintmax_t) ST_NBLOCKS (f->stat), buf,
2444 ST_NBLOCKSIZE, output_block_size));
2446 print_name_with_quoting (f->name, f->stat.st_mode, f->linkok, NULL);
2448 if (indicator_style != none)
2449 print_type_indicator (f->stat.st_mode);
2452 static void
2453 print_type_indicator (unsigned int mode)
2455 int c;
2457 if (S_ISREG (mode))
2459 if (indicator_style == classify && (mode & S_IXUGO))
2460 c ='*';
2461 else
2462 c = 0;
2464 else
2466 if (S_ISDIR (mode))
2467 c = '/';
2468 else if (S_ISLNK (mode))
2469 c = '@';
2470 else if (S_ISFIFO (mode))
2471 c = '|';
2472 else if (S_ISSOCK (mode))
2473 c = '=';
2474 else if (S_ISDOOR (mode))
2475 c = '>';
2476 else
2477 c = 0;
2480 if (c)
2481 DIRED_PUTCHAR (c);
2484 static void
2485 print_color_indicator (const char *name, unsigned int mode, int linkok)
2487 int type = C_FILE;
2488 struct color_ext_type *ext; /* Color extension */
2489 size_t len; /* Length of name */
2491 /* Is this a nonexistent file? If so, linkok == -1. */
2493 if (linkok == -1 && color_indicator[C_MISSING].string != NULL)
2495 ext = NULL;
2496 type = C_MISSING;
2498 else
2500 if (S_ISDIR (mode))
2501 type = C_DIR;
2502 else if (S_ISLNK (mode))
2503 type = ((!linkok && color_indicator[C_ORPHAN].string)
2504 ? C_ORPHAN : C_LINK);
2505 else if (S_ISFIFO (mode))
2506 type = C_FIFO;
2507 else if (S_ISSOCK (mode))
2508 type = C_SOCK;
2509 else if (S_ISBLK (mode))
2510 type = C_BLK;
2511 else if (S_ISCHR (mode))
2512 type = C_CHR;
2513 else if (S_ISDOOR (mode))
2514 type = C_DOOR;
2516 if (type == C_FILE && (mode & S_IXUGO) != 0)
2517 type = C_EXEC;
2519 /* Check the file's suffix only if still classified as C_FILE. */
2520 ext = NULL;
2521 if (type == C_FILE)
2523 /* Test if NAME has a recognized suffix. */
2525 len = strlen (name);
2526 name += len; /* Pointer to final \0. */
2527 for (ext = color_ext_list; ext != NULL; ext = ext->next)
2529 if ((size_t) ext->ext.len <= len
2530 && strncmp (name - ext->ext.len, ext->ext.string,
2531 ext->ext.len) == 0)
2532 break;
2537 put_indicator (&color_indicator[C_LEFT]);
2538 put_indicator (ext ? &(ext->seq) : &color_indicator[type]);
2539 put_indicator (&color_indicator[C_RIGHT]);
2542 /* Output a color indicator (which may contain nulls). */
2543 static void
2544 put_indicator (const struct bin_str *ind)
2546 register int i;
2547 register char *p;
2549 p = ind->string;
2551 for (i = ind->len; i > 0; --i)
2552 putchar (*(p++));
2555 static int
2556 length_of_file_name_and_frills (const struct fileinfo *f)
2558 register int len = 0;
2560 if (print_inode)
2561 len += INODE_DIGITS + 1;
2563 if (print_block_size)
2564 len += 1 + block_size_size;
2566 len += quotearg_buffer (0, 0, f->name, -1, filename_quoting_options);
2568 if (indicator_style != none)
2570 unsigned filetype = f->stat.st_mode;
2572 if (S_ISREG (filetype))
2574 if (indicator_style == classify
2575 && (f->stat.st_mode & S_IXUGO))
2576 len += 1;
2578 else if (S_ISDIR (filetype)
2579 || S_ISLNK (filetype)
2580 || S_ISFIFO (filetype)
2581 || S_ISSOCK (filetype)
2582 || S_ISDOOR (filetype)
2584 len += 1;
2587 return len;
2590 static void
2591 print_many_per_line (void)
2593 struct column_info *line_fmt;
2594 int filesno; /* Index into files. */
2595 int row; /* Current row. */
2596 int max_name_length; /* Length of longest file name + frills. */
2597 int name_length; /* Length of each file name + frills. */
2598 int pos; /* Current character column. */
2599 int cols; /* Number of files across. */
2600 int rows; /* Maximum number of files down. */
2601 int max_cols;
2603 /* Normally the maximum number of columns is determined by the
2604 screen width. But if few files are available this might limit it
2605 as well. */
2606 max_cols = max_idx > files_index ? files_index : max_idx;
2608 /* Compute the maximum number of possible columns. */
2609 for (filesno = 0; filesno < files_index; ++filesno)
2611 int i;
2613 name_length = length_of_file_name_and_frills (files + filesno);
2615 for (i = 0; i < max_cols; ++i)
2617 if (column_info[i].valid_len)
2619 int idx = filesno / ((files_index + i) / (i + 1));
2620 int real_length = name_length + (idx == i ? 0 : 2);
2622 if (real_length > column_info[i].col_arr[idx])
2624 column_info[i].line_len += (real_length
2625 - column_info[i].col_arr[idx]);
2626 column_info[i].col_arr[idx] = real_length;
2627 column_info[i].valid_len = column_info[i].line_len < line_length;
2633 /* Find maximum allowed columns. */
2634 for (cols = max_cols; cols > 1; --cols)
2636 if (column_info[cols - 1].valid_len)
2637 break;
2640 line_fmt = &column_info[cols - 1];
2642 /* Calculate the number of rows that will be in each column except possibly
2643 for a short column on the right. */
2644 rows = files_index / cols + (files_index % cols != 0);
2646 for (row = 0; row < rows; row++)
2648 int col = 0;
2649 filesno = row;
2650 pos = 0;
2651 /* Print the next row. */
2652 while (1)
2654 print_file_name_and_frills (files + filesno);
2655 name_length = length_of_file_name_and_frills (files + filesno);
2656 max_name_length = line_fmt->col_arr[col++];
2658 filesno += rows;
2659 if (filesno >= files_index)
2660 break;
2662 indent (pos + name_length, pos + max_name_length);
2663 pos += max_name_length;
2665 putchar ('\n');
2669 static void
2670 print_horizontal (void)
2672 struct column_info *line_fmt;
2673 int filesno;
2674 int max_name_length;
2675 int name_length;
2676 int cols;
2677 int pos;
2678 int max_cols;
2680 /* Normally the maximum number of columns is determined by the
2681 screen width. But if few files are available this might limit it
2682 as well. */
2683 max_cols = max_idx > files_index ? files_index : max_idx;
2685 /* Compute the maximum file name length. */
2686 max_name_length = 0;
2687 for (filesno = 0; filesno < files_index; ++filesno)
2689 int i;
2691 name_length = length_of_file_name_and_frills (files + filesno);
2693 for (i = 0; i < max_cols; ++i)
2695 if (column_info[i].valid_len)
2697 int idx = filesno % (i + 1);
2698 int real_length = name_length + (idx == i ? 0 : 2);
2700 if (real_length > column_info[i].col_arr[idx])
2702 column_info[i].line_len += (real_length
2703 - column_info[i].col_arr[idx]);
2704 column_info[i].col_arr[idx] = real_length;
2705 column_info[i].valid_len = column_info[i].line_len < line_length;
2711 /* Find maximum allowed columns. */
2712 for (cols = max_cols; cols > 1; --cols)
2714 if (column_info[cols - 1].valid_len)
2715 break;
2718 line_fmt = &column_info[cols - 1];
2720 pos = 0;
2722 /* Print first entry. */
2723 print_file_name_and_frills (files);
2724 name_length = length_of_file_name_and_frills (files);
2725 max_name_length = line_fmt->col_arr[0];
2727 /* Now the rest. */
2728 for (filesno = 1; filesno < files_index; ++filesno)
2730 int col = filesno % cols;
2732 if (col == 0)
2734 putchar ('\n');
2735 pos = 0;
2737 else
2739 indent (pos + name_length, pos + max_name_length);
2740 pos += max_name_length;
2743 print_file_name_and_frills (files + filesno);
2745 name_length = length_of_file_name_and_frills (files + filesno);
2746 max_name_length = line_fmt->col_arr[col];
2748 putchar ('\n');
2751 static void
2752 print_with_commas (void)
2754 int filesno;
2755 int pos, old_pos;
2757 pos = 0;
2759 for (filesno = 0; filesno < files_index; filesno++)
2761 old_pos = pos;
2763 pos += length_of_file_name_and_frills (files + filesno);
2764 if (filesno + 1 < files_index)
2765 pos += 2; /* For the comma and space */
2767 if (old_pos != 0 && pos >= line_length)
2769 putchar ('\n');
2770 pos -= old_pos;
2773 print_file_name_and_frills (files + filesno);
2774 if (filesno + 1 < files_index)
2776 putchar (',');
2777 putchar (' ');
2780 putchar ('\n');
2783 /* Assuming cursor is at position FROM, indent up to position TO.
2784 Use a TAB character instead of two or more spaces whenever possible. */
2786 static void
2787 indent (int from, int to)
2789 while (from < to)
2791 if (tabsize > 0 && to / tabsize > (from + 1) / tabsize)
2793 putchar ('\t');
2794 from += tabsize - from % tabsize;
2796 else
2798 putchar (' ');
2799 from++;
2804 /* Put DIRNAME/NAME into DEST, handling `.' and `/' properly. */
2805 /* FIXME: maybe remove this function someday. See about using a
2806 non-malloc'ing version of path_concat. */
2808 static void
2809 attach (char *dest, const char *dirname, const char *name)
2811 const char *dirnamep = dirname;
2813 /* Copy dirname if it is not ".". */
2814 if (dirname[0] != '.' || dirname[1] != 0)
2816 while (*dirnamep)
2817 *dest++ = *dirnamep++;
2818 /* Add '/' if `dirname' doesn't already end with it. */
2819 if (dirnamep > dirname && dirnamep[-1] != '/')
2820 *dest++ = '/';
2822 while (*name)
2823 *dest++ = *name++;
2824 *dest = 0;
2827 static void
2828 init_column_info (void)
2830 int i;
2831 int allocate = 0;
2833 max_idx = line_length / MIN_COLUMN_WIDTH;
2834 if (max_idx == 0)
2835 max_idx = 1;
2837 if (column_info == NULL)
2839 column_info = (struct column_info *) xmalloc (max_idx
2840 * sizeof (struct column_info));
2841 allocate = 1;
2844 for (i = 0; i < max_idx; ++i)
2846 int j;
2848 column_info[i].valid_len = 1;
2849 column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;
2851 if (allocate)
2852 column_info[i].col_arr = (int *) xmalloc ((i + 1) * sizeof (int));
2854 for (j = 0; j <= i; ++j)
2855 column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;
2859 void
2860 usage (int status)
2862 if (status != 0)
2863 fprintf (stderr, _("Try `%s --help' for more information.\n"),
2864 program_name);
2865 else
2867 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);
2868 printf (_("\
2869 List information about the FILEs (the current directory by default).\n\
2870 Sort entries alphabetically if none of -cftuSUX nor --sort.\n\
2872 -a, --all do not hide entries starting with .\n\
2873 -A, --almost-all do not list implied . and ..\n\
2874 -b, --escape print octal escapes for nongraphic characters\n\
2875 --block-size=SIZE use SIZE-byte blocks\n\
2876 -B, --ignore-backups do not list implied entries ending with ~\n\
2877 -c sort by change time; with -l: show ctime\n\
2878 -C list entries by columns\n\
2879 --color[=WHEN] control whether color is used to distinguish file\n\
2880 types. WHEN may be `never', `always', or `auto'\n\
2881 -d, --directory list directory entries instead of contents\n\
2882 -D, --dired generate output designed for Emacs' dired mode\n\
2883 -f do not sort, enable -aU, disable -lst\n\
2884 -F, --classify append indicator (one of */=@|) to entries\n\
2885 --format=WORD across -x, commas -m, horizontal -x, long -l,\n\
2886 single-column -1, verbose -l, vertical -C\n\
2887 --full-time list both full date and full time\n"));
2889 printf (_("\
2890 -g (ignored)\n\
2891 -G, --no-group inhibit display of group information\n\
2892 -h, --human-readable print sizes in human readable format (e.g., 1K 234M 2G)\n\
2893 -H, --si likewise, but use powers of 1000 not 1024\n\
2894 --indicator-style=WORD append indicator with style WORD to entry names:\n\
2895 none (default), classify (-F), file-type (-p)\n\
2896 -i, --inode print index number of each file\n\
2897 -I, --ignore=PATTERN do not list implied entries matching shell PATTERN\n\
2898 -k, --kilobytes like --block-size=1024\n\
2899 -l use a long listing format\n\
2900 -L, --dereference list entries pointed to by symbolic links\n\
2901 -m fill width with a comma separated list of entries\n\
2902 -n, --numeric-uid-gid list numeric UIDs and GIDs instead of names\n\
2903 -N, --literal print raw entry names (don't treat e.g. control\n\
2904 characters specially)\n\
2905 -o use long listing format without group info\n\
2906 -p, --file-type append indicator (one of /=@|) to entries\n\
2907 -q, --hide-control-chars print ? instead of non graphic characters\n\
2908 (This is the default unless the output is a\n\
2909 terminal and the program is `ls'; otherwise,\n\
2910 the default is --show-control-chars)\n\
2911 --show-control-chars show non graphic characters as-is (default)\n\
2912 -Q, --quote-name enclose entry names in double quotes\n\
2913 --quoting-style=WORD use quoting style WORD for entry names:\n\
2914 literal, locale, shell, shell-always, c, escape\n\
2915 -r, --reverse reverse order while sorting\n\
2916 -R, --recursive list subdirectories recursively\n\
2917 -s, --size print size of each file, in blocks\n"));
2919 printf (_("\
2920 -S sort by file size\n\
2921 --sort=WORD extension -X, none -U, size -S, time -t,\n\
2922 version -v\n\
2923 status -c, time -t, atime -u, access -u, use -u\n\
2924 --time=WORD show time as WORD instead of modification time:\n\
2925 atime, access, use, ctime or status; use\n\
2926 specified time as sort key if --sort=time\n\
2927 -t sort by modification time\n\
2928 -T, --tabsize=COLS assume tab stops at each COLS instead of 8\n\
2929 -u sort by last access time; with -l: show atime\n\
2930 -U do not sort; list entries in directory order\n\
2931 -v sort by version\n\
2932 -w, --width=COLS assume screen width instead of current value\n\
2933 -x list entries by lines instead of by columns\n\
2934 -X sort alphabetically by entry extension\n\
2935 -1 list one file per line\n\
2936 --help display this help and exit\n\
2937 --version output version information and exit\n\
2939 By default, color is not used to distinguish types of files. That is\n\
2940 equivalent to using --color=none. Using the --color option without the\n\
2941 optional WHEN argument is equivalent to using --color=always. With\n\
2942 --color=auto, color codes are output only if standard output is connected\n\
2943 to a terminal (tty).\n\
2944 "));
2945 puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));
2946 close_stdout ();
2948 exit (status);