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)
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.
29 the output format depends on whether the output
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>. */
44 #include <sys/types.h>
47 # include <inttypes.h>
54 #ifdef GWINSZ_IN_SYS_IOCTL
55 # include <sys/ioctl.h>
58 #ifdef WINSIZE_IN_PTEM
59 # include <sys/stream.h>
60 # include <sys/ptem.h>
83 /* Get mbstate_t, mbrtowc(), mbsinit(), wcwidth(). */
92 #if !defined iswprint && !HAVE_ISWPRINT
93 # define iswprint(wc) 1
96 #ifndef HAVE_DECL_WCWIDTH
97 "this configure-time declaration test was not run"
99 #if !HAVE_DECL_WCWIDTH
103 /* If wcwidth() doesn't exist, assume all printable characters have
107 # define wcwidth(wc) ((wc) == 0 ? 0 : iswprint (wc) ? 1 : -1)
114 #include "argmatch.h"
117 #include "filemode.h"
119 #include "mbswidth.h"
121 #include "path-concat.h"
122 #include "quotearg.h"
123 #include "strverscmp.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
133 #define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \
134 : (ls_mode == LS_MULTI_COL \
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. */
150 # define INODE_DIGITS 7
154 # define HAVE_SYMLINKS 1
156 # define HAVE_SYMLINKS 0
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. */
162 # define S_ISLNK(Mode) 0
166 # define S_ISFIFO(Mode) 0
170 # define S_ISSOCK(Mode) 0
174 # define S_ISCHR(Mode) 0
178 # define S_ISBLK(Mode) 0
182 # define S_ISDOOR(Mode) 0
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
*));
191 # define lstat(Name, Stat_buf) rpl_lstat(Name, Stat_buf)
194 #if defined _DIRENT_HAVE_D_TYPE || defined DTTOIF
195 # define HAVE_STRUCT_DIRENT_D_TYPE 1
196 # define DT_INIT(Val) = Val
198 # define HAVE_STRUCT_DIRENT_D_TYPE 0
199 # define DT_INIT(Val) /* empty */
203 # define TIMESPEC_NS(timespec) ((timespec).ST_MTIM_NSEC)
205 # define TIMESPEC_NS(timespec) 0
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
))
229 /* For symbolic link, name of the file linked to, otherwise zero. */
232 /* For symbolic link and long listing, st_mode of file linked to, otherwise
234 unsigned int linkmode
;
236 /* For symbolic link and color printing, 1 if linked-to file
237 exists, otherwise 0. */
240 enum filetype filetype
;
243 /* For long listings, nonzero if the file has an access control list,
250 # define FILE_HAS_ACL(F) ((F)->have_acl)
252 # define FILE_HAS_ACL(F) 0
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
263 int len
; /* Number of bytes */
264 const char *string
; /* Pointer to the same */
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
,
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
,
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
,
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. */
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. */
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. */
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. */
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
;
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. */
409 long_format
, /* -l */
410 one_per_line
, /* -1 */
411 many_per_line
, /* -C */
416 static enum format format
;
418 /* Type of time to print or sort by. Controlled by -c and -u. */
422 time_mtime
, /* default */
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. */
438 sort_name
, /* default */
439 sort_extension
, /* -X */
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
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. */
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. */
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
;
513 color_never
, /* 0: default or --color=never */
514 color_always
, /* 1: --color=always */
515 color_if_tty
/* 2: --color=tty */
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 */
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
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
579 static int trace_dirs
;
581 /* Nonzero means when an argument is a directory name, display info
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
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 */
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
645 static int format_needs_stat
;
647 /* Similar to `format_needs_stat', but set if only the file type is
650 static int format_needs_type
;
652 /* strftime formats for non-recent and recent files, respectively, in
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. */
665 BLOCK_SIZE_OPTION
= CHAR_MAX
+ 1,
669 INDICATOR_STYLE_OPTION
,
670 QUOTING_STYLE_OPTION
,
671 SHOW_CONTROL_CHARS_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
},
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. */
771 /* Array with information about column filledness. */
772 static struct column_info
*column_info
;
774 /* Maximum number of columns ever possible for this display. */
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() \
802 /* FIXME: remove the `&& format == long_format' clause. */ \
803 if (dired && format == long_format) \
804 DIRED_FPUTS_LITERAL (" ", stdout); \
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) \
822 /* FIXME: remove the `&& format == long_format' clause. */ \
823 if (dired && format == long_format) \
824 obstack_grow ((obs), &dired_pos, sizeof (dired_pos)); \
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. */
833 dired_dump_obstack (const char *prefix
, struct obstack
*os
)
837 n_pos
= obstack_object_size (os
) / sizeof (dired_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
)
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
));
872 i
= decode_switches (argc
, argv
);
874 if (print_with_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
);
898 files
= (struct fileinfo
*) xmalloc (sizeof (struct fileinfo
) * nfiles
);
905 for (; i
< argc
; i
++)
907 gobble_file (argv
[i
], unknown
, 1, "");
913 gobble_file (".", directory
, 1, "");
915 queue_directory (".", 0);
922 extract_dirs_from_files ("", 0);
923 /* `files_index' might be zero now. */
927 print_current_files ();
929 DIRED_PUTCHAR ('\n');
931 else if (pending_dirs
&& pending_dirs
->next
== 0)
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
);
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
]);
966 /* Set all the option flags according to the switches specified.
967 Return the index of the first non-option argument. */
970 decode_switches (int argc
, char **argv
)
972 register char const *p
;
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 */
987 /* This is for the `dir' program. */
988 format
= many_per_line
;
989 set_quoting_style (NULL
, escape_quoting_style
);
993 /* This is for the `vdir' program. */
994 format
= long_format
;
995 set_quoting_style (NULL
, escape_quoting_style
);
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;
1008 format
= one_per_line
;
1009 qmark_funny_chars
= 0;
1017 time_type
= time_mtime
;
1019 sort_type
= sort_name
;
1022 print_block_size
= 0;
1023 indicator_style
= none
;
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
);
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
;
1050 _("ignoring invalid width in environment variable COLUMNS: %s"),
1059 if (ioctl (STDOUT_FILENO
, TIOCGWINSZ
, &ws
) != -1 && ws
.ws_col
!= 0)
1060 line_length
= ws
.ws_col
;
1064 /* Using the TABSIZE environment variable is not POSIX-approved.
1065 Ignore it when POSIXLY_CORRECT is set. */
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
;
1077 _("ignoring invalid tab size in environment variable TABSIZE: %s"),
1082 while ((c
= getopt_long (argc
, argv
,
1083 "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UX1",
1084 long_options
, NULL
)) != -1)
1093 really_all_files
= 1;
1097 set_quoting_style (NULL
, escape_quoting_style
);
1101 time_type
= time_ctime
;
1109 /* Same as enabling -a -U and disabling -l -s. */
1111 really_all_files
= 1;
1112 sort_type
= sort_none
;
1113 sort_type_specified
= 1;
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 */
1122 /* No effect. For BSD compatibility. */
1126 output_block_size
= -1024;
1130 output_block_size
= -1000;
1138 output_block_size
= 1024;
1142 format
= long_format
;
1146 format
= with_commas
;
1153 case 'o': /* Just like -l, but don't display group info. */
1154 format
= long_format
;
1159 indicator_style
= file_type
;
1163 qmark_funny_chars
= 1;
1171 print_block_size
= 1;
1175 sort_type
= sort_time
;
1176 sort_type_specified
= 1;
1180 time_type
= time_atime
;
1184 sort_type
= sort_version
;
1185 sort_type_specified
= 1;
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"),
1193 line_length
= (int) tmp_long
;
1197 format
= horizontal
;
1201 really_all_files
= 0;
1206 add_ignore_pattern ("*~");
1207 add_ignore_pattern (".*~");
1211 format
= many_per_line
;
1219 indicator_style
= classify
;
1222 case 'G': /* inhibit display of group info */
1227 add_ignore_pattern (optarg
);
1235 set_quoting_style (NULL
, literal_quoting_style
);
1239 set_quoting_style (NULL
, c_quoting_style
);
1247 sort_type
= sort_size
;
1248 sort_type_specified
= 1;
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"),
1256 tabsize
= (int) tmp_long
;
1260 sort_type
= sort_none
;
1261 sort_type_specified
= 1;
1265 sort_type
= sort_extension
;
1266 sort_type_specified
= 1;
1270 format
= one_per_line
;
1274 sort_type
= XARGMATCH ("--sort", optarg
, sort_args
, sort_types
);
1275 sort_type_specified
= 1;
1279 time_type
= XARGMATCH ("--time", optarg
, time_args
, time_types
);
1283 format
= XARGMATCH ("--format", optarg
, format_args
, format_types
);
1287 format
= long_format
;
1293 i
= XARGMATCH ("--color", optarg
, color_args
, color_types
);
1295 /* Using --color with no argument is equivalent to using
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. */
1312 case INDICATOR_STYLE_OPTION
:
1313 indicator_style
= XARGMATCH ("--indicator-style", optarg
,
1314 indicator_style_args
,
1315 indicator_style_types
);
1318 case QUOTING_STYLE_OPTION
:
1319 set_quoting_style (NULL
,
1320 XARGMATCH ("--quoting-style", optarg
,
1322 quoting_style_vals
));
1325 case SHOW_CONTROL_CHARS_OPTION
:
1326 qmark_funny_chars
= 0;
1329 case BLOCK_SIZE_OPTION
:
1330 human_block_size (optarg
, 1, &output_block_size
);
1333 case_GETOPT_HELP_CHAR
;
1335 case_GETOPT_VERSION_CHAR (PROGRAM_NAME
, AUTHORS
);
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
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
)
1369 long_time_format
[0] = long_time_format
[1] =
1370 dcgettext (NULL
, "%a %b %d %H:%M:%S %Y", LC_TIME
);
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
);
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
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. */
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 */
1399 ST_GND
, ST_BACKSLASH
, ST_OCTAL
, ST_HEX
, ST_CARET
, ST_END
, ST_ERROR
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. */
1410 state
= ST_GND
; /* Start in ground state. */
1411 while (state
< ST_END
)
1415 case ST_GND
: /* Ground state (no escapes) */
1420 state
= ST_END
; /* End of string */
1423 state
= ST_BACKSLASH
; /* Backslash scape sequence */
1427 state
= ST_CARET
; /* Caret escape */
1433 state
= ST_END
; /* End */
1436 /* else fall through */
1444 case ST_BACKSLASH
: /* Backslash escaped character */
1455 state
= ST_OCTAL
; /* Octal sequence */
1460 state
= ST_HEX
; /* Hex sequence */
1463 case 'a': /* Bell */
1464 num
= 7; /* Not all C compilers know what \a means */
1466 case 'b': /* Backspace */
1469 case 'e': /* Escape */
1472 case 'f': /* Form feed */
1475 case 'n': /* Newline */
1478 case 'r': /* Carriage return */
1484 case 'v': /* Vtab */
1487 case '?': /* Delete */
1490 case '_': /* Space */
1493 case '\0': /* End of string */
1494 state
= ST_ERROR
; /* Error! */
1496 default: /* Escaped character like \ ^ : = */
1500 if (state
== ST_BACKSLASH
)
1509 case ST_OCTAL
: /* Octal sequence */
1510 if (*p
< '0' || *p
> '7')
1517 num
= (num
<< 3) + (*(p
++) - '0');
1520 case ST_HEX
: /* Hex sequence */
1533 num
= (num
<< 4) + (*(p
++) - '0');
1541 num
= (num
<< 4) + (*(p
++) - 'a') + 10;
1549 num
= (num
<< 4) + (*(p
++) - 'A') + 10;
1559 case ST_CARET
: /* Caret escape */
1560 state
= ST_GND
; /* Should be the next state... */
1561 if (*p
>= '@' && *p
<= '~')
1563 *(q
++) = *(p
++) & 037;
1583 return state
== ST_ERROR
? -1 : count
;
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')
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
1606 buf
= color_buf
= xstrdup (p
);
1613 case 1: /* First label character */
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
;
1632 ext
->ext
.string
= buf
;
1634 state
= (ext
->ext
.len
=
1635 get_funky_string (&buf
, &p
, 1)) < 0 ? -1 : 4;
1639 state
= 0; /* Done! */
1642 default: /* Assume it is file type label */
1649 case 2: /* Second label character */
1656 state
= -1; /* Error */
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);
1674 error (0, 0, _("unrecognized prefix: %s"), quotearg (label
));
1678 case 4: /* Equal sign after *.ext */
1681 ext
->seq
.string
= buf
;
1682 state
= (ext
->seq
.len
=
1683 get_funky_string (&buf
, &p
, 0)) < 0 ? -1 : 1;
1693 struct color_ext_type
*e
;
1694 struct color_ext_type
*e2
;
1697 _("unparsable value for LS_COLORS environment variable"));
1699 for (e
= color_ext_list
; e
!= NULL
; /* empty */)
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
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
;
1727 new->name
= xstrdup (name
);
1729 new->realname
= xstrdup (realname
);
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. */
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;
1746 reading
= opendir (name
);
1749 error (0, errno
, "%s", quotearg_colon (name
));
1754 /* Read the directory entries, and insert the subfiles into the `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
;
1770 total_blocks
+= gobble_file (next
->d_name
, type
, 0, name
);
1773 if (CLOSEDIR (reading
))
1775 error (0, errno
, "%s", quotearg_colon (name
));
1777 /* Don't return; print whatever we got. */
1780 /* Sort the directory contents. */
1783 /* If any member files are subdirectories, perhaps they should have their
1784 contents listed rather than being mentioned here as files. */
1787 extract_dirs_from_files (name
, 1);
1789 if (trace_dirs
|| print_dir_name
)
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
)
1802 char buf
[LONGEST_HUMAN_READABLE
+ 1];
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');
1815 print_current_files ();
1818 DIRED_PUTCHAR ('\n');
1821 /* Add `pattern' to the list of patterns for which files that match are
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. */
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)
1847 if (really_all_files
1848 || next
->d_name
[0] != '.'
1850 && next
->d_name
[1] != '\0'
1851 && (next
->d_name
[1] != '.' || next
->d_name
[2] != '\0')))
1857 /* Enter and remove entries in the table `files'. */
1859 /* Empty the table of files. */
1866 for (i
= 0; i
< files_index
; i
++)
1868 free (files
[i
].name
);
1869 if (files
[i
].linkname
)
1870 free (files
[i
].linkname
);
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. */
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
)
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. */
1909 if (name
[0] == '/' || dirname
[0] == 0)
1910 path
= (char *) name
;
1913 path
= (char *) alloca (strlen (name
) + strlen (dirname
) + 2);
1914 attach (path
, dirname
, name
);
1918 ? stat (path
, &files
[files_index
].stat
)
1919 : lstat (path
, &files
[files_index
].stat
));
1923 error (0, errno
, "%s", quotearg_colon (path
));
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
));
1935 if (S_ISLNK (files
[files_index
].stat
.st_mode
)
1936 && (explicit_arg
|| format
== long_format
|| check_symlink_color
))
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. */
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
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
;
1966 linkpath
= files
[files_index
].linkname
;
1967 files
[files_index
].linkname
= (char *) tempname
;
1969 files
[files_index
].stat
= linkstats
;
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;
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
;
1990 files
[files_index
].filetype
= directory
;
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
,
2001 if (block_size_size
< len
)
2002 block_size_size
= len
< 7 ? len
: 7;
2007 files
[files_index
].filetype
= type
;
2008 #if HAVE_STRUCT_DIRENT_D_TYPE
2009 files
[files_index
].stat
.st_mode
= DTTOIF (type
);
2014 files
[files_index
].name
= xstrdup (name
);
2022 /* Put the name of the file that `filename' is a symbolic link to
2023 into the `linkname' field of `f'. */
2026 get_link_name (const char *filename
, struct fileinfo
*f
)
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);
2037 error (0, errno
, "%s", quotearg_colon (filename
));
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. */
2053 make_link_path (const char *path
, const char *linkname
)
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
, '/');
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
);
2078 /* Return nonzero if base_name (NAME) ends in `.' or `..'
2079 This is so we don't try to recurse on `././././. ...' */
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. */
2096 extract_dirs_from_files (const char *dirname
, int recursive
)
2100 /* Queue the directories last one first, because queueing reverses the
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
);
2112 char *path
= path_concat (dirname
, files
[i
].name
, NULL
);
2113 queue_directory (path
, files
[i
].linkname
);
2116 if (files
[i
].filetype
== arg_directory
)
2117 free (files
[i
].name
);
2120 /* Now delete the directories from the table, compacting all the remaining
2123 for (i
= 0, j
= 0; i
< files_index
; i
++)
2124 if (files
[i
].filetype
!= arg_directory
)
2125 files
[j
++] = files
[i
];
2129 /* Sort the files now in the table. */
2144 func
= sort_reverse
? rev_cmp_ctime
: compare_ctime
;
2147 func
= sort_reverse
? rev_cmp_mtime
: compare_mtime
;
2150 func
= sort_reverse
? rev_cmp_atime
: compare_atime
;
2157 func
= sort_reverse
? rev_cmp_name
: compare_name
;
2159 case sort_extension
:
2160 func
= sort_reverse
? rev_cmp_extension
: compare_extension
;
2163 func
= sort_reverse
? rev_cmp_size
: compare_size
;
2166 func
= sort_reverse
? rev_cmp_version
: compare_version
;
2172 qsort (files
, files_index
, sizeof (struct fileinfo
), func
);
2175 /* Comparison routines for sorting the files. */
2178 compare_ctime (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2180 int diff
= CTIME_CMP (file2
->stat
, file1
->stat
);
2182 diff
= strcoll (file1
->name
, file2
->name
);
2187 rev_cmp_ctime (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2189 int diff
= CTIME_CMP (file2
->stat
, file1
->stat
);
2191 diff
= strcoll (file1
->name
, file2
->name
);
2196 compare_mtime (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2198 int diff
= MTIME_CMP (file2
->stat
, file1
->stat
);
2200 diff
= strcoll (file1
->name
, file2
->name
);
2205 rev_cmp_mtime (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2207 int diff
= MTIME_CMP (file2
->stat
, file1
->stat
);
2209 diff
= strcoll (file1
->name
, file2
->name
);
2214 compare_atime (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2216 int diff
= ATIME_CMP (file2
->stat
, file1
->stat
);
2218 diff
= strcoll (file1
->name
, file2
->name
);
2223 rev_cmp_atime (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2225 int diff
= ATIME_CMP (file2
->stat
, file1
->stat
);
2227 diff
= strcoll (file1
->name
, file2
->name
);
2232 compare_size (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2234 int diff
= longdiff (file2
->stat
.st_size
, file1
->stat
.st_size
);
2236 diff
= strcoll (file1
->name
, file2
->name
);
2241 rev_cmp_size (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2243 int diff
= longdiff (file2
->stat
.st_size
, file1
->stat
.st_size
);
2245 diff
= strcoll (file1
->name
, file2
->name
);
2250 compare_version (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2252 return strverscmp (file1
->name
, file2
->name
);
2256 rev_cmp_version (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2258 return strverscmp (file1
->name
, file2
->name
);
2262 compare_name (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2264 return strcoll (file1
->name
, file2
->name
);
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. */
2277 compare_extension (const struct fileinfo
*file1
, const struct fileinfo
*file2
)
2279 register char *base1
, *base2
;
2282 base1
= strrchr (file1
->name
, '.');
2283 base2
= strrchr (file2
->name
, '.');
2284 if (base1
== 0 && base2
== 0)
2285 return strcoll (file1
->name
, file2
->name
);
2290 cmp
= strcoll (base1
, base2
);
2292 return strcoll (file1
->name
, file2
->name
);
2297 rev_cmp_extension (const struct fileinfo
*file2
, const struct fileinfo
*file1
)
2299 register char *base1
, *base2
;
2302 base1
= strrchr (file1
->name
, '.');
2303 base2
= strrchr (file2
->name
, '.');
2304 if (base1
== 0 && base2
== 0)
2305 return strcoll (file1
->name
, file2
->name
);
2310 cmp
= strcoll (base1
, base2
);
2312 return strcoll (file1
->name
, file2
->name
);
2316 /* List all the files now in the table. */
2319 print_current_files (void)
2326 for (i
= 0; i
< files_index
; i
++)
2328 print_file_name_and_frills (files
+ i
);
2334 init_column_info ();
2335 print_many_per_line ();
2339 init_column_info ();
2340 print_horizontal ();
2344 print_with_commas ();
2348 for (i
= 0; i
< files_index
; i
++)
2350 print_long_format (files
+ i
);
2351 DIRED_PUTCHAR ('\n');
2357 /* Return the expected number of columns in a long-format time stamp,
2358 or zero if it cannot be calculated. */
2361 long_time_expected_width (void)
2363 static int width
= -1;
2368 struct tm
const *tm
= localtime (&epoch
);
2369 char const *fmt
= long_time_format
[0];
2371 char *buf
= initbuf
;
2372 size_t bufsize
= sizeof initbuf
;
2378 len
= strftime (buf
, bufsize
, fmt
, tm
);
2381 buf
= alloca (bufsize
*= 2);
2384 width
= mbsnwidth (buf
, len
, 0);
2392 /* Get the current time. */
2395 get_current_time (void)
2397 #if HAVE_CLOCK_GETTIME && defined CLOCK_REALTIME
2399 struct timespec timespec
;
2400 if (clock_gettime (CLOCK_REALTIME
, ×pec
) == 0)
2402 current_time
= timespec
.tv_sec
;
2403 current_time_ns
= timespec
.tv_nsec
;
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;
2427 current_time
= time (NULL
);
2428 current_time_ns
= 999999999;
2432 print_long_format (const struct fileinfo
*f
)
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
)
2445 char *buf
= init_bigbuf
;
2446 size_t bufsize
= sizeof (init_bigbuf
);
2450 int when_ns
IF_LINT (= 0);
2451 struct tm
*when_local
;
2455 /* Cray DMF: look at the file's migrated, not real, status */
2456 mode_string (f
->stat
.st_dm_mode
, modebuf
);
2458 mode_string (f
->stat
.st_mode
, modebuf
);
2461 modebuf
[10] = (FILE_HAS_ACL (f
) ? '+' : ' ');
2467 when
= f
->stat
.st_ctime
;
2468 when_ns
= TIMESPEC_NS (f
->stat
.st_ctim
);
2471 when
= f
->stat
.st_mtime
;
2472 when_ns
= TIMESPEC_NS (f
->stat
.st_mtim
);
2475 when
= f
->stat
.st_atime
;
2476 when_ns
= TIMESPEC_NS (f
->stat
.st_atim
);
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));
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
,
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
);
2505 user_name
= (numeric_ids
? NULL
: getuser (f
->stat
.st_uid
));
2507 sprintf (p
, "%-8.8s ", user_name
);
2509 sprintf (p
, "%-8u ", (unsigned int) f
->stat
.st_uid
);
2514 char *group_name
= (numeric_ids
? NULL
: getgroup (f
->stat
.st_gid
));
2516 sprintf (p
, "%-8.8s ", group_name
);
2518 sprintf (p
, "%-8u ", (unsigned int) f
->stat
.st_gid
);
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
));
2527 char hbuf
[LONGEST_HUMAN_READABLE
+ 1];
2529 human_readable ((uintmax_t) f
->stat
.st_size
, hbuf
, 1,
2530 output_block_size
< 0 ? output_block_size
: 1));
2535 if ((when_local
= localtime (&when
)))
2537 time_t six_months_ago
;
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
];
2562 s
= strftime (p
, buf
+ bufsize
- p
- 1, fmt
, when_local
);
2565 newbuf
= alloca (bufsize
*= 2);
2566 memcpy (newbuf
, buf
, p
- buf
);
2567 p
= newbuf
+ (p
- buf
);
2574 /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it. */
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 ();
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
);
2591 sprintf (p
, "%*s ", width
,
2592 human_readable ((uintmax_t) when
, hbuf
, 1, 1));
2598 DIRED_FPUTS (buf
, stdout
, p
- buf
);
2599 print_name_with_quoting (f
->name
, FILE_OR_LINK_MODE (f
), f
->linkok
,
2602 if (f
->filetype
== symbolic_link
)
2606 DIRED_FPUTS_LITERAL (" -> ", stdout
);
2607 print_name_with_quoting (f
->linkname
, f
->linkmode
, f
->linkok
- 1,
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
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
);
2628 int displayed_width
;
2630 if (len
< sizeof smallbuf
)
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)
2643 const char *p
= buf
;
2644 char *plimit
= buf
+ len
;
2646 displayed_width
= 0;
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 '>':
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':
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. */
2673 displayed_width
+= 1;
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. */
2681 memset (&mbstate
, 0, sizeof mbstate
);
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. */
2697 displayed_width
+= 1;
2701 if (bytes
== (size_t) -2)
2703 /* An incomplete multibyte character
2704 at the end. Replace it entirely with
2708 displayed_width
+= 1;
2713 /* A null wide character was encountered. */
2719 /* A printable multibyte character.
2721 for (; bytes
> 0; --bytes
)
2723 displayed_width
+= w
;
2727 /* An unprintable multibyte character.
2728 Replace it entirely with a question
2732 displayed_width
+= 1;
2735 while (! mbsinit (&mbstate
));
2740 /* The buffer may have shrunk. */
2747 char *plimit
= buf
+ len
;
2751 if (! ISPRINT ((unsigned char) *p
))
2755 displayed_width
= len
;
2760 /* Assume unprintable characters have a displayed_width of 1. */
2761 #if HAVE_MBRTOWC && (MB_LEN_MAX > 1)
2763 displayed_width
= mbsnwidth (buf
, len
,
2764 (MBSW_ACCEPT_INVALID
2765 | MBSW_ACCEPT_UNPRINTABLE
));
2768 displayed_width
= len
;
2772 fwrite (buf
, 1, len
, out
);
2773 return displayed_width
;
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
);
2784 PUSH_CURRENT_DIRED_POS (stack
);
2786 dired_pos
+= quote_name (stdout
, p
, filename_quoting_options
);
2789 PUSH_CURRENT_DIRED_POS (stack
);
2791 if (print_with_color
)
2792 prep_non_filename_text ();
2796 prep_non_filename_text (void)
2798 if (color_indicator
[C_END
].string
!= NULL
)
2799 put_indicator (&color_indicator
[C_END
]);
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. */
2813 print_file_name_and_frills (const struct fileinfo
*f
)
2815 char buf
[LONGEST_HUMAN_READABLE
+ 1];
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
,
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
);
2834 print_type_indicator (unsigned int mode
)
2840 if (indicator_style
== classify
&& (mode
& S_IXUGO
))
2849 else if (S_ISLNK (mode
))
2851 else if (S_ISFIFO (mode
))
2853 else if (S_ISSOCK (mode
))
2855 else if (S_ISDOOR (mode
))
2866 print_color_indicator (const char *name
, unsigned int mode
, int linkok
)
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
)
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
))
2888 else if (S_ISSOCK (mode
))
2890 else if (S_ISBLK (mode
))
2892 else if (S_ISCHR (mode
))
2894 else if (S_ISDOOR (mode
))
2897 if (type
== C_FILE
&& (mode
& S_IXUGO
) != 0)
2900 /* Check the file's suffix only if still classified as 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
,
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). */
2925 put_indicator (const struct bin_str
*ind
)
2928 register const char *p
;
2932 for (i
= ind
->len
; i
> 0; --i
)
2937 length_of_file_name_and_frills (const struct fileinfo
*f
)
2939 register int len
= 0;
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
))
2959 else if (S_ISDIR (filetype
)
2960 || S_ISLNK (filetype
)
2961 || S_ISFIFO (filetype
)
2962 || S_ISSOCK (filetype
)
2963 || S_ISDOOR (filetype
)
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. */
2984 /* Normally the maximum number of columns is determined by the
2985 screen width. But if few files are available this might limit it
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
)
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
)
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
++)
3032 /* Print the next row. */
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
++];
3040 if (filesno
>= files_index
)
3043 indent (pos
+ name_length
, pos
+ max_name_length
);
3044 pos
+= max_name_length
;
3051 print_horizontal (void)
3053 struct column_info
*line_fmt
;
3055 int max_name_length
;
3061 /* Normally the maximum number of columns is determined by the
3062 screen width. But if few files are available this might limit it
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
)
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
)
3099 line_fmt
= &column_info
[cols
- 1];
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];
3109 for (filesno
= 1; filesno
< files_index
; ++filesno
)
3111 int col
= filesno
% cols
;
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
];
3133 print_with_commas (void)
3140 for (filesno
= 0; filesno
< files_index
; filesno
++)
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
)
3154 print_file_name_and_frills (files
+ filesno
);
3155 if (filesno
+ 1 < files_index
)
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. */
3168 indent (int from
, int to
)
3172 if (tabsize
> 0 && to
/ tabsize
> (from
+ 1) / tabsize
)
3175 from
+= tabsize
- from
% tabsize
;
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. */
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)
3198 *dest
++ = *dirnamep
++;
3199 /* Add '/' if `dirname' doesn't already end with it. */
3200 if (dirnamep
> dirname
&& dirnamep
[-1] != '/')
3209 init_column_info (void)
3214 max_idx
= line_length
/ MIN_COLUMN_WIDTH
;
3218 if (column_info
== NULL
)
3220 column_info
= (struct column_info
*) xmalloc (max_idx
3221 * sizeof (struct column_info
));
3225 for (i
= 0; i
< max_idx
; ++i
)
3229 column_info
[i
].valid_len
= 1;
3230 column_info
[i
].line_len
= (i
+ 1) * MIN_COLUMN_WIDTH
;
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
;
3244 fprintf (stderr
, _("Try `%s --help' for more information.\n"),
3248 printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name
);
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"));
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"));
3302 -S sort by file size\n\
3303 --sort=WORD extension -X, none -U, size -S, time -t,\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\
3329 puts (_("\nReport bugs to <bug-fileutils@gnu.org>."));