/* 'dir', 'vdir' and 'ls' directory listing programs for GNU.                   This is the ls utility
   Copyright (C) 1985-2018 Free Software Foundation, Inc.                       
                                                                                
   This program is free software: you can redistribute it and/or modify         
   it under the terms of the GNU General Public License as published by         
   the Free Software Foundation, either version 3 of the License, or            
   (at your option) any later version.                                          
                                                                                
   This program is distributed in the hope that it will be useful,              
   but WITHOUT ANY WARRANTY; without even the implied warranty of               
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                
   GNU General Public License for more details.                                 
                                                                                
   You should have received a copy of the GNU General Public License            
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */   The GNUv3 license
                                                                                
/* If ls_mode is LS_MULTI_COL,                                                  
   the multi-column format is the default regardless                            
   of the type of output device.                                                
   This is for the 'dir' program.                                               
                                                                                
   If ls_mode is LS_LONG_FORMAT,                                                
   the long format is the default regardless of the                             
   type of output device.                                                       
   This is for the 'vdir' program.                                              
                                                                                
   If ls_mode is LS_LS,                                                         
   the output format depends on whether the output                              
   device is a terminal.                                                        
   This is for the 'ls' program.  */                                            
                                                                                
/* Written by Richard Stallman and David MacKenzie.  */                         
                                                                                
/* Color support by Peter Anvin <Peter.Anvin@linux.org> and Dennis              
   Flaherty <dennisf@denix.elk.miles.com> based on original patches by          
   Greg Lee <lee@uhunix.uhcc.hawaii.edu>.  */                                   
                                                                                
#include <config.h>                                                             Provides system specific information
#include <sys/types.h>                                                          Provides system data types
                                                                                
#include <termios.h>                                                            ...!includes auto-comment...
#if HAVE_STROPTS_H                                                              Line 42
# include <stropts.h>                                                           Line 43
#endif                                                                          Line 44
#include <sys/ioctl.h>                                                          ...!includes auto-comment...
                                                                                
#ifdef WINSIZE_IN_PTEM                                                          Line 47
# include <sys/stream.h>                                                        Line 48
# include <sys/ptem.h>                                                          Line 49
#endif                                                                          Line 50
                                                                                
#include <stdio.h>                                                              Provides standard I/O capability
#include <assert.h>                                                             ...!includes auto-comment...
#include <setjmp.h>                                                             ...!includes auto-comment...
#include <pwd.h>                                                                ...!includes auto-comment...
#include <getopt.h>                                                             ...!includes auto-comment...
#include <signal.h>                                                             ...!includes auto-comment...
#include <selinux/selinux.h>                                                    ...!includes auto-comment......!includes auto-comment...
#include <wchar.h>                                                              ...!includes auto-comment...
                                                                                
#if HAVE_LANGINFO_CODESET                                                       Line 61
# include <langinfo.h>                                                          ...!includes auto-comment...
#endif                                                                          Line 63
                                                                                
/* Use SA_NOCLDSTOP as a proxy for whether the sigaction machinery is           
   present.  */                                                                 
#ifndef SA_NOCLDSTOP                                                            Line 67
# define SA_NOCLDSTOP 0                                                         Line 68
# define sigprocmask(How, Set, Oset) /* empty */                                Line 69
# define sigset_t int                                                           Line 70
# if ! HAVE_SIGINTERRUPT                                                        Line 71
#  define siginterrupt(sig, flag) /* empty */                                   Line 72
# endif                                                                         Line 73
#endif                                                                          Line 74
                                                                                
/* NonStop circa 2011 lacks both SA_RESTART and siginterrupt, so don't          
   restart syscalls after a signal handler fires.  This may cause               
   colors to get messed up on the screen if 'ls' is interrupted, but            
   that's the best we can do on such a platform.  */                            
#ifndef SA_RESTART                                                              Line 80
# define SA_RESTART 0                                                           Line 81
#endif                                                                          Line 82
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include <fnmatch.h>                                                            ...!includes auto-comment...
                                                                                
#include "acl.h"                                                                ...!includes auto-comment...
#include "argmatch.h"                                                           ...!includes auto-comment...
#include "c-strcase.h"                                                          ...!includes auto-comment...
#include "dev-ino.h"                                                            ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "filenamecat.h"                                                        ...!includes auto-comment...
#include "hard-locale.h"                                                        ...!includes auto-comment...
#include "hash.h"                                                               ...!includes auto-comment...
#include "human.h"                                                              ...!includes auto-comment...
#include "filemode.h"                                                           ...!includes auto-comment...
#include "filevercmp.h"                                                         ...!includes auto-comment...
#include "idcache.h"                                                            ...!includes auto-comment...
#include "ls.h"                                                                 ...!includes auto-comment...
#include "mbswidth.h"                                                           ...!includes auto-comment...
#include "mpsort.h"                                                             ...!includes auto-comment...
#include "obstack.h"                                                            ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
#include "smack.h"                                                              ...!includes auto-comment...
#include "stat-size.h"                                                          ...!includes auto-comment...
#include "stat-time.h"                                                          ...!includes auto-comment...
#include "strftime.h"                                                           ...!includes auto-comment...
#include "xdectoint.h"                                                          ...!includes auto-comment...
#include "xstrtol.h"                                                            ...!includes auto-comment...
#include "areadlink.h"                                                          ...!includes auto-comment...
#include "mbsalign.h"                                                           ...!includes auto-comment...
#include "dircolors.h"                                                          ...!includes auto-comment...
#include "xgethostname.h"                                                       ...!includes auto-comment...
#include "c-ctype.h"                                                            ...!includes auto-comment...
#include "canonicalize.h"                                                       ...!includes auto-comment...
                                                                                
/* Include <sys/capability.h> last to avoid a clash of <sys/types.h>            
   include guards with some premature versions of libcap.                       
   For more details, see <https://bugzilla.redhat.com/483548>.  */              
#ifdef HAVE_CAP                                                                 Line 121
# include <sys/capability.h>                                                    Line 122
#endif                                                                          Line 123
                                                                                
#define PROGRAM_NAME (ls_mode == LS_LS ? "ls" \                                 Line 125
                      : (ls_mode == LS_MULTI_COL \                              Line 126
                         ? "dir" : "vdir"))                                     Line 127
                                                                                
#define AUTHORS \                                                               Line 129
  proper_name ("Richard M. Stallman"), \                                        Line 130
  proper_name ("David MacKenzie")                                               Line 131
                                                                                
#define obstack_chunk_alloc malloc                                              Line 133
#define obstack_chunk_free free                                                 Line 134
                                                                                
/* Return an int indicating the result of comparing two integers.               
   Subtracting doesn't always work, due to overflow.  */                        
#define longdiff(a, b) ((a) < (b) ? -1 : (a) > (b))                             Line 138
                                                                                
/* Unix-based readdir implementations have historically returned a dirent.d_ino 
   value that is sometimes not equal to the stat-obtained st_ino value for      
   that same entry.  This error occurs for a readdir entry that refers          
   to a mount point.  readdir's error is to return the inode number of          
   the underlying directory -- one that typically cannot be stat'ed, as         
   long as a file system is mounted on that directory.  RELIABLE_D_INO          
   encapsulates whether we can use the more efficient approach of relying       
   on readdir-supplied d_ino values, or whether we must incur the cost of       
   calling stat or lstat to obtain each guaranteed-valid inode number.  */      
                                                                                
#ifndef READDIR_LIES_ABOUT_MOUNTPOINT_D_INO                                     Line 150
# define READDIR_LIES_ABOUT_MOUNTPOINT_D_INO 1                                  Line 151
#endif                                                                          Line 152
                                                                                
#if READDIR_LIES_ABOUT_MOUNTPOINT_D_INO                                         Line 154
# define RELIABLE_D_INO(dp) NOT_AN_INODE_NUMBER                                 Line 155
#else                                                                           Line 156
# define RELIABLE_D_INO(dp) D_INO (dp)                                          Line 157
#endif                                                                          Line 158
                                                                                
#if ! HAVE_STRUCT_STAT_ST_AUTHOR                                                Line 160
# define st_author st_uid                                                       Line 161
#endif                                                                          Line 162
                                                                                
enum filetype                                                                   Line 164
  {                                                                             
    unknown,                                                                    Line 166
    fifo,                                                                       Line 167
    chardev,                                                                    Line 168
    directory,                                                                  Line 169
    blockdev,                                                                   Line 170
    normal,                                                                     Line 171
    symbolic_link,                                                              Line 172
    sock,                                                                       Line 173
    whiteout,                                                                   Line 174
    arg_directory                                                               Line 175
  };                                                                            Block 1
                                                                                
/* Display letters and indicators for each filetype.                            
   Keep these in sync with enum filetype.  */                                   
static char const filetype_letter[] = "?pcdb-lswd";                             Line 180
                                                                                
/* Ensure that filetype and filetype_letter have the same                       
   number of elements.  */                                                      
verify (sizeof filetype_letter - 1 == arg_directory + 1);                       Line 184
                                                                                
#define FILETYPE_INDICATORS    \                                                Line 186
  {       \                                                                     Line 187
    C_ORPHAN, C_FIFO, C_CHR, C_DIR, C_BLK, C_FILE, \                            Line 188
    C_LINK, C_SOCK, C_FILE, C_DIR   \                                           Line 189
  }                                                                             Block 2
                                                                                
enum acl_type                                                                   Line 192
  {                                                                             
    ACL_T_NONE,                                                                 Line 194
    ACL_T_LSM_CONTEXT_ONLY,                                                     Line 195
    ACL_T_YES                                                                   Line 196
  };                                                                            Block 3
                                                                                
struct fileinfo                                                                 Line 199
  {                                                                             
    /* The file name.  */                                                       
    char *name;                                                                 Line 202
                                                                                
    /* For symbolic link, name of the file linked to, otherwise zero.  */       
    char *linkname;                                                             Line 205
                                                                                
    /* For terminal hyperlinks. */                                              
    char *absolute_name;                                                        Line 208
                                                                                
    struct stat stat;                                                           Line 210
                                                                                
    enum filetype filetype;                                                     Line 212
                                                                                
    /* For symbolic link and long listing, st_mode of file linked to, otherwise 
       zero.  */                                                                
    mode_t linkmode;                                                            Line 216
                                                                                
    /* security context.  */                                                    
    char *scontext;                                                             Line 219
                                                                                
    bool stat_ok;                                                               Line 221
                                                                                
    /* For symbolic link and color printing, true if linked-to file             
       exists, otherwise false.  */                                             
    bool linkok;                                                                Line 225
                                                                                
    /* For long listings, true if the file has an access control list,          
       or a security context.  */                                               
    enum acl_type acl_type;                                                     Line 229
                                                                                
    /* For color listings, true if a regular file has capability info.  */      
    bool has_capability;                                                        Line 232
                                                                                
    /* Whether file name needs quoting. tri-state with -1 == unknown.  */       
    int quoted;                                                                 Line 235
  };                                                                            
                                                                                
#define LEN_STR_PAIR(s) sizeof (s) - 1, s                                       Line 238
                                                                                
/* Null is a valid character in a color indicator (think about Epson            
   printers, for example) so we have to use a length/buffer string              
   type.  */                                                                    
                                                                                
struct bin_str                                                                  Line 244
  {                                                                             
    size_t len;   /* Number of bytes */                                         Line 246
    const char *string;  /* Pointer to the same */                              Line 247
  };                                                                            Block 5
                                                                                
#if ! HAVE_TCGETPGRP                                                            Line 250
# define tcgetpgrp(Fd) 0                                                        Line 251
#endif                                                                          Line 252
                                                                                
static size_t quote_name (char const *name,                                     Line 254
                          struct quoting_options const *options,                Line 255
                          int needs_general_quoting,                            Line 256
                          const struct bin_str *color,                          Line 257
                          bool allow_pad, struct obstack *stack,                Line 258
                          char const *absolute_name);                           Line 259
static size_t quote_name_buf (char **inbuf, size_t bufsize, char *name,         Line 260
                              struct quoting_options const *options,            Line 261
                              int needs_general_quoting, size_t *width,         Line 262
                              bool *pad);                                       Line 263
static char *make_link_name (char const *name, char const *linkname);           Line 264
static int decode_switches (int argc, char **argv);                             Line 265
static bool file_ignored (char const *name);                                    Line 266
static uintmax_t gobble_file (char const *name, enum filetype type,             Line 267
                              ino_t inode, bool command_line_arg,               Line 268
                              char const *dirname);                             Line 269
static const struct bin_str * get_color_indicator (const struct fileinfo *f,    Line 270
                                                   bool symlink_target);        Line 271
static bool print_color_indicator (const struct bin_str *ind);                  Line 272
static void put_indicator (const struct bin_str *ind);                          Line 273
static void add_ignore_pattern (const char *pattern);                           Line 274
static void attach (char *dest, const char *dirname, const char *name);         Line 275
static void clear_files (void);                                                 Line 276
static void extract_dirs_from_files (char const *dirname,                       Line 277
                                     bool command_line_arg);                    Line 278
static void get_link_name (char const *filename, struct fileinfo *f,            Line 279
                           bool command_line_arg);                              Line 280
static void indent (size_t from, size_t to);                                    Line 281
static size_t calculate_columns (bool by_columns);                              Line 282
static void print_current_files (void);                                         Line 283
static void print_dir (char const *name, char const *realname,                  Line 284
                       bool command_line_arg);                                  Line 285
static size_t print_file_name_and_frills (const struct fileinfo *f,             Line 286
                                          size_t start_col);                    Line 287
static void print_horizontal (void);                                            Line 288
static int format_user_width (uid_t u);                                         Line 289
static int format_group_width (gid_t g);                                        Line 290
static void print_long_format (const struct fileinfo *f);                       Line 291
static void print_many_per_line (void);                                         Line 292
static size_t print_name_with_quoting (const struct fileinfo *f,                Line 293
                                       bool symlink_target,                     Line 294
                                       struct obstack *stack,                   Line 295
                                       size_t start_col);                       Line 296
static void prep_non_filename_text (void);                                      Line 297
static bool print_type_indicator (bool stat_ok, mode_t mode,                    Line 298
                                  enum filetype type);                          Line 299
static void print_with_separator (char sep);                                    Line 300
static void queue_directory (char const *name, char const *realname,            Line 301
                             bool command_line_arg);                            Line 302
static void sort_files (void);                                                  Line 303
static void parse_ls_color (void);                                              Line 304
                                                                                
static void getenv_quoting_style (void);                                        Line 306
                                                                                
/* Initial size of hash table.                                                  
   Most hierarchies are likely to be shallower than this.  */                   
#define INITIAL_TABLE_SIZE 30                                                   Line 310
                                                                                
/* The set of 'active' directories, from the current command-line argument      
   to the level in the hierarchy at which files are being listed.               
   A directory is represented by its device and inode numbers (struct dev_ino). 
   A directory is added to this set when ls begins listing it or its            
   entries, and it is removed from the set just after ls has finished           
   processing it.  This set is used solely to detect loops, e.g., with          
   mkdir loop; cd loop; ln -s ../loop sub; ls -RL  */                           
static Hash_table *active_dir_set;                                              Line 319
                                                                                
#define LOOP_DETECT (!!active_dir_set)                                          Line 321
                                                                                
/* The table of files in the current directory:                                 
                                                                                
   'cwd_file' points to a vector of 'struct fileinfo', one per file.            
   'cwd_n_alloc' is the number of elements space has been allocated for.        
   'cwd_n_used' is the number actually in use.  */                              
                                                                                
/* Address of block containing the files that are described.  */                
static struct fileinfo *cwd_file;                                               Line 330
                                                                                
/* Length of block that 'cwd_file' points to, measured in files.  */            
static size_t cwd_n_alloc;                                                      Line 333
                                                                                
/* Index of first unused slot in 'cwd_file'.  */                                
static size_t cwd_n_used;                                                       Line 336
                                                                                
/* Whether files needs may need padding due to quoting.  */                     
static bool cwd_some_quoted;                                                    Line 339
                                                                                
/* Whether quoting style _may_ add outer quotes,                                
   and whether aligning those is useful.  */                                    
static bool align_variable_outer_quotes;                                        Line 343
                                                                                
/* Vector of pointers to files, in proper sorted order, and the number          
   of entries allocated for it.  */                                             
static void **sorted_file;                                                      Line 347
static size_t sorted_file_alloc;                                                Line 348
                                                                                
/* When true, in a color listing, color each symlink name according to the      
   type of file it points to.  Otherwise, color them according to the 'ln'      
   directive in LS_COLORS.  Dangling (orphan) symlinks are treated specially,   
   regardless.  This is set when 'ln=target' appears in LS_COLORS.  */          
                                                                                
static bool color_symlink_as_referent;                                          Line 355
                                                                                
static char const *hostname;                                                    Line 357
                                                                                
/* mode of appropriate file for colorization */                                 
#define FILE_OR_LINK_MODE(File) \                                               Line 360
    ((color_symlink_as_referent && (File)->linkok) \                            Line 361
     ? (File)->linkmode : (File)->stat.st_mode)                                 Line 362
                                                                                
                                                                                
/* Record of one pending directory waiting to be listed.  */                    
                                                                                
struct pending                                                                  Line 367
  {                                                                             
    char *name;                                                                 Line 369
    /* If the directory is actually the file pointed to by a symbolic link we   
       were told to list, 'realname' will contain the name of the symbolic      
       link, otherwise zero.  */                                                
    char *realname;                                                             Line 373
    bool command_line_arg;                                                      Line 374
    struct pending *next;                                                       Line 375
  };                                                                            Block 6
                                                                                
static struct pending *pending_dirs;                                            Line 378
                                                                                
/* Current time in seconds and nanoseconds since 1970, updated as               
   needed when deciding whether a file is recent.  */                           
                                                                                
static struct timespec current_time;                                            Line 383
                                                                                
static bool print_scontext;                                                     Line 385
static char UNKNOWN_SECURITY_CONTEXT[] = "?";                                   Line 386
                                                                                
/* Whether any of the files has an ACL.  This affects the width of the          
   mode column.  */                                                             
                                                                                
static bool any_has_acl;                                                        Line 391
                                                                                
/* The number of columns to use for columns containing inode numbers,           
   block sizes, link counts, owners, groups, authors, major device              
   numbers, minor device numbers, and file sizes, respectively.  */             
                                                                                
static int inode_number_width;                                                  Line 397
static int block_size_width;                                                    Line 398
static int nlink_width;                                                         Line 399
static int scontext_width;                                                      Line 400
static int owner_width;                                                         Line 401
static int group_width;                                                         Line 402
static int author_width;                                                        Line 403
static int major_device_number_width;                                           Line 404
static int minor_device_number_width;                                           Line 405
static int file_size_width;                                                     Line 406
                                                                                
/* Option flags */                                                              
                                                                                
/* long_format for lots of info, one per line.                                  
   one_per_line for just names, one per line.                                   
   many_per_line for just names, many per line, sorted vertically.              
   horizontal for just names, many per line, sorted horizontally.               
   with_commas for just names, many per line, separated by commas.              
                                                                                
   -l (and other options that imply -l), -1, -C, -x and -m control              
   this parameter.  */                                                          
                                                                                
enum format                                                                     Line 419
  {                                                                             
    long_format,  /* -l and other options that imply -l */                      Line 421
    one_per_line,  /* -1 */                                                     Line 422
    many_per_line,  /* -C */                                                    Line 423
    horizontal,   /* -x */                                                      Line 424
    with_commas   /* -m */                                                      Line 425
  };                                                                            Block 7
                                                                                
static enum format format;                                                      Line 428
                                                                                
/* 'full-iso' uses full ISO-style dates and times.  'long-iso' uses longer      
   ISO-style timestamps, though shorter than 'full-iso'.  'iso' uses shorter    
   ISO-style timestamps.  'locale' uses locale-dependent timestamps.  */        
enum time_style                                                                 Line 433
  {                                                                             
    full_iso_time_style, /* --time-style=full-iso */                            Line 435
    long_iso_time_style, /* --time-style=long-iso */                            Line 436
    iso_time_style,  /* --time-style=iso */                                     Line 437
    locale_time_style  /* --time-style=locale */                                Line 438
  };                                                                            Block 8
                                                                                
static char const *const time_style_args[] =                                    Line 441
{                                                                               
  "full-iso", "long-iso", "iso", "locale", NULL                                 Line 443
};                                                                              Block 9
static enum time_style const time_style_types[] =                               Line 445
{                                                                               
  full_iso_time_style, long_iso_time_style, iso_time_style,                     Line 447
  locale_time_style                                                             Line 448
};                                                                              Block 10
ARGMATCH_VERIFY (time_style_args, time_style_types);                            Line 450
                                                                                
/* Type of time to print or sort by.  Controlled by -c and -u.                  
   The values of each item of this enum are important since they are            
   used as indices in the sort functions array (see sort_files()).  */          
                                                                                
enum time_type                                                                  Line 456
  {                                                                             
    time_mtime,   /* default */                                                 Line 458
    time_ctime,   /* -c */                                                      Line 459
    time_atime,   /* -u */                                                      Line 460
    time_numtypes  /* the number of elements of this enum */                    Line 461
  };                                                                            Block 11
                                                                                
static enum time_type time_type;                                                Line 464
                                                                                
/* The file characteristic to sort by.  Controlled by -t, -S, -U, -X, -v.       
   The values of each item of this enum are important since they are            
   used as indices in the sort functions array (see sort_files()).  */          
                                                                                
enum sort_type                                                                  Line 470
  {                                                                             
    sort_none = -1,  /* -U */                                                   Line 472
    sort_name,   /* default */                                                  Line 473
    sort_extension,  /* -X */                                                   Line 474
    sort_size,   /* -S */                                                       Line 475
    sort_version,  /* -v */                                                     Line 476
    sort_time,   /* -t */                                                       Line 477
    sort_numtypes  /* the number of elements of this enum */                    Line 478
  };                                                                            Block 12
                                                                                
static enum sort_type sort_type;                                                Line 481
                                                                                
/* Direction of sort.                                                           
   false means highest first if numeric,                                        
   lowest first if alphabetic;                                                  
   these are the defaults.                                                      
   true means the opposite order in each case.  -r  */                          
                                                                                
static bool sort_reverse;                                                       Line 489
                                                                                
/* True means to display owner information.  -g turns this off.  */             
                                                                                
static bool print_owner = true;                                                 Line 493
                                                                                
/* True means to display author information.  */                                
                                                                                
static bool print_author;                                                       Line 497
                                                                                
/* True means to display group information.  -G and -o turn this off.  */       
                                                                                
static bool print_group = true;                                                 Line 501
                                                                                
/* True means print the user and group id's as numbers rather                   
   than as names.  -n  */                                                       
                                                                                
static bool numeric_ids;                                                        Line 506
                                                                                
/* True means mention the size in blocks of each file.  -s  */                  
                                                                                
static bool print_block_size;                                                   Line 510
                                                                                
/* Human-readable options for output, when printing block counts.  */           
static int human_output_opts;                                                   Line 513
                                                                                
/* The units to use when printing block counts.  */                             
static uintmax_t output_block_size;                                             Line 516
                                                                                
/* Likewise, but for file sizes.  */                                            
static int file_human_output_opts;                                              Line 519
static uintmax_t file_output_block_size = 1;                                    Line 520
                                                                                
/* Follow the output with a special string.  Using this format,                 
   Emacs' dired mode starts up twice as fast, and can handle all                
   strange characters in file names.  */                                        
static bool dired;                                                              Line 525
                                                                                
/* 'none' means don't mention the type of files.                                
   'slash' means mention directories only, with a '/'.                          
   'file_type' means mention file types.                                        
   'classify' means mention file types and mark executables.                    
                                                                                
   Controlled by -F, -p, and --indicator-style.  */                             
                                                                                
enum indicator_style                                                            Line 534
  {                                                                             
    none, /*     --indicator-style=none */                                      Line 536
    slash, /* -p, --indicator-style=slash */                                    Line 537
    file_type, /*     --indicator-style=file-type */                            Line 538
    classify /* -F, --indicator-style=classify */                               Line 539
  };                                                                            Block 13
                                                                                
static enum indicator_style indicator_style;                                    Line 542
                                                                                
/* Names of indicator styles.  */                                               
static char const *const indicator_style_args[] =                               Line 545
{                                                                               
  "none", "slash", "file-type", "classify", NULL                                Line 547
};                                                                              Block 14
static enum indicator_style const indicator_style_types[] =                     Line 549
{                                                                               
  none, slash, file_type, classify                                              Line 551
};                                                                              Block 15
ARGMATCH_VERIFY (indicator_style_args, indicator_style_types);                  Line 553
                                                                                
/* True means use colors to mark types.  Also define the different              
   colors as well as the stuff for the LS_COLORS environment variable.          
   The LS_COLORS variable is now in a termcap-like format.  */                  
                                                                                
static bool print_with_color;                                                   Line 559
                                                                                
static bool print_hyperlink;                                                    Line 561
                                                                                
/* Whether we used any colors in the output so far.  If so, we will             
   need to restore the default color later.  If not, we will need to            
   call prep_non_filename_text before using color for the first time. */        
                                                                                
static bool used_color = false;                                                 Line 567
                                                                                
enum when_type                                                                  Line 569
  {                                                                             
    when_never,  /* 0: default or --color=never */                              Line 571
    when_always, /* 1: --color=always */                                        Line 572
    when_if_tty  /* 2: --color=tty */                                           Line 573
  };                                                                            Block 16
                                                                                
enum Dereference_symlink                                                        Line 576
  {                                                                             
    DEREF_UNDEFINED = 1,                                                        Line 578
    DEREF_NEVER,                                                                Line 579
    DEREF_COMMAND_LINE_ARGUMENTS, /* -H */                                      Line 580
    DEREF_COMMAND_LINE_SYMLINK_TO_DIR, /* the default, in certain cases */      Line 581
    DEREF_ALWAYS   /* -L */                                                     Line 582
  };                                                                            Block 17
                                                                                
enum indicator_no                                                               Line 585
  {                                                                             
    C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,             Line 587
    C_FIFO, C_SOCK,                                                             Line 588
    C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,      Line 589
    C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP, C_MULTIHARDLINK,Line 590
    C_CLR_TO_EOL                                                                Line 591
  };                                                                            Block 18
                                                                                
static const char *const indicator_name[]=                                      Line 594
  {                                                                             
    "lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",                 Line 596
    "bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",                       Line 597
    "ow", "tw", "ca", "mh", "cl", NULL                                          Line 598
  };                                                                            Block 19
                                                                                
struct color_ext_type                                                           Line 601
  {                                                                             
    struct bin_str ext;  /* The extension we're looking for */                  Line 603
    struct bin_str seq;  /* The sequence to output when we do */                Line 604
    struct color_ext_type *next; /* Next in list */                             Line 605
  };                                                                            Block 20
                                                                                
static struct bin_str color_indicator[] =                                       Line 608
  {                                                                             
    { LEN_STR_PAIR ("\033[") },  /* lc: Left of color sequence */               Line 610
    { LEN_STR_PAIR ("m") },  /* rc: Right of color sequence */                  Line 611
    { 0, NULL },   /* ec: End color (replaces lc+rs+rc) */                      Line 612
    { LEN_STR_PAIR ("0") },  /* rs: Reset to ordinary colors */                 Line 613
    { 0, NULL },   /* no: Normal */                                             Line 614
    { 0, NULL },   /* fi: File: default */                                      Line 615
    { LEN_STR_PAIR ("01;34") },  /* di: Directory: bright blue */               Line 616
    { LEN_STR_PAIR ("01;36") },  /* ln: Symlink: bright cyan */                 Line 617
    { LEN_STR_PAIR ("33") },  /* pi: Pipe: yellow/brown */                      Line 618
    { LEN_STR_PAIR ("01;35") },  /* so: Socket: bright magenta */               Line 619
    { LEN_STR_PAIR ("01;33") },  /* bd: Block device: bright yellow */          Line 620
    { LEN_STR_PAIR ("01;33") },  /* cd: Char device: bright yellow */           Line 621
    { 0, NULL },   /* mi: Missing file: undefined */                            Line 622
    { 0, NULL },   /* or: Orphaned symlink: undefined */                        Line 623
    { LEN_STR_PAIR ("01;32") },  /* ex: Executable: bright green */             Line 624
    { LEN_STR_PAIR ("01;35") },  /* do: Door: bright magenta */                 Line 625
    { LEN_STR_PAIR ("37;41") },  /* su: setuid: white on red */                 Line 626
    { LEN_STR_PAIR ("30;43") },  /* sg: setgid: black on yellow */              Line 627
    { LEN_STR_PAIR ("37;44") },  /* st: sticky: black on blue */                Line 628
    { LEN_STR_PAIR ("34;42") },  /* ow: other-writable: blue on green */        Line 629
    { LEN_STR_PAIR ("30;42") },  /* tw: ow w/ sticky: black on green */         Line 630
    { LEN_STR_PAIR ("30;41") },  /* ca: black on red */                         Line 631
    { 0, NULL },   /* mh: disabled by default */                                Line 632
    { LEN_STR_PAIR ("\033[K") }, /* cl: clear to end of line */                 Line 633
  };                                                                            Block 21
                                                                                
/* FIXME: comment  */                                                           
static struct color_ext_type *color_ext_list = NULL;                            Line 637
                                                                                
/* Buffer for color sequences */                                                
static char *color_buf;                                                         Line 640
                                                                                
/* True means to check for orphaned symbolic link, for displaying               
   colors.  */                                                                  
                                                                                
static bool check_symlink_color;                                                Line 645
                                                                                
/* True means mention the inode number of each file.  -i  */                    
                                                                                
static bool print_inode;                                                        Line 649
                                                                                
/* What to do with symbolic links.  Affected by -d, -F, -H, -l (and             
   other options that imply -l), and -L.  */                                    
                                                                                
static enum Dereference_symlink dereference;                                    Line 654
                                                                                
/* True means when a directory is found, display info on its                    
   contents.  -R  */                                                            
                                                                                
static bool recursive;                                                          Line 659
                                                                                
/* True means when an argument is a directory name, display info                
   on it itself.  -d  */                                                        
                                                                                
static bool immediate_dirs;                                                     Line 664
                                                                                
/* True means that directories are grouped before files. */                     
                                                                                
static bool directories_first;                                                  Line 668
                                                                                
/* Which files to ignore.  */                                                   
                                                                                
static enum                                                                     Line 672
{                                                                               
  /* Ignore files whose names start with '.', and files specified by            
     --hide and --ignore.  */                                                   
  IGNORE_DEFAULT,                                                               Line 676
                                                                                
  /* Ignore '.', '..', and files specified by --ignore.  */                     
  IGNORE_DOT_AND_DOTDOT,                                                        Line 679
                                                                                
  /* Ignore only files specified by --ignore.  */                               
  IGNORE_MINIMAL                                                                Line 682
} ignore_mode;                                                                  Line 683
                                                                                
/* A linked list of shell-style globbing patterns.  If a non-argument           
   file name matches any of these patterns, it is ignored.                      
   Controlled by -I.  Multiple -I options accumulate.                           
   The -B option adds '*~' and '.*~' to this list.  */                          
                                                                                
struct ignore_pattern                                                           Line 690
  {                                                                             
    const char *pattern;                                                        Line 692
    struct ignore_pattern *next;                                                Line 693
  };                                                                            Block 23
                                                                                
static struct ignore_pattern *ignore_patterns;                                  Line 696
                                                                                
/* Similar to IGNORE_PATTERNS, except that -a or -A causes this                 
   variable itself to be ignored.  */                                           
static struct ignore_pattern *hide_patterns;                                    Line 700
                                                                                
/* True means output nongraphic chars in file names as '?'.                     
   (-q, --hide-control-chars)                                                   
   qmark_funny_chars and the quoting style (-Q, --quoting-style=WORD) are       
   independent.  The algorithm is: first, obey the quoting style to get a       
   string representing the file name;  then, if qmark_funny_chars is set,       
   replace all nonprintable chars in that string with '?'.  It's necessary      
   to replace nonprintable chars even in quoted strings, because we don't       
   want to mess up the terminal if control chars get sent to it, and some       
   quoting methods pass through control chars as-is.  */                        
static bool qmark_funny_chars;                                                  Line 711
                                                                                
/* Quoting options for file and dir name output.  */                            
                                                                                
static struct quoting_options *filename_quoting_options;                        Line 715
static struct quoting_options *dirname_quoting_options;                         Line 716
                                                                                
/* The number of chars per hardware tab stop.  Setting this to zero             
   inhibits the use of TAB characters for separating columns.  -T */            
static size_t tabsize;                                                          Line 720
                                                                                
/* True means print each directory name before listing it.  */                  
                                                                                
static bool print_dir_name;                                                     Line 724
                                                                                
/* The line length to use for breaking lines in many-per-line format.           
   Can be set with -w.  */                                                      
                                                                                
static size_t line_length;                                                      Line 729
                                                                                
/* The local time zone rules, as per the TZ environment variable.  */           
                                                                                
static timezone_t localtz;                                                      Line 733
                                                                                
/* If true, the file listing format requires that stat be called on             
   each file.  */                                                               
                                                                                
static bool format_needs_stat;                                                  Line 738
                                                                                
/* Similar to 'format_needs_stat', but set if only the file type is             
   needed.  */                                                                  
                                                                                
static bool format_needs_type;                                                  Line 743
                                                                                
/* An arbitrary limit on the number of bytes in a printed timestamp.            
   This is set to a relatively small value to avoid the need to worry           
   about denial-of-service attacks on servers that run "ls" on behalf           
   of remote clients.  1000 bytes should be enough for any practical            
   timestamp format.  */                                                        
                                                                                
enum { TIME_STAMP_LEN_MAXIMUM = MAX (1000, INT_STRLEN_BOUND (time_t)) };        Line 751
                                                                                
/* strftime formats for non-recent and recent files, respectively, in           
   -l output.  */                                                               
                                                                                
static char const *long_time_format[2] =                                        Line 756
  {                                                                             
    /* strftime format for non-recent files (older than 6 months), in           
       -l output.  This should contain the year, month and day (at              
       least), in an order that is understood by people in your                 
       locale's territory.  Please try to keep the number of used               
       screen columns small, because many people work in windows with           
       only 80 columns.  But make this as wide as the other string              
       below, for recent files.  */                                             
    /* TRANSLATORS: ls output needs to be aligned for ease of reading,          
       so be wary of using variable width fields from the locale.               
       Note %b is handled specially by ls and aligned correctly.                
       Note also that specifying a width as in %5b is erroneous as strftime     
       will count bytes rather than characters in multibyte locales.  */        
    N_("%b %e  %Y"),                                                            Line 770
    /* strftime format for recent files (younger than 6 months), in -l          
       output.  This should contain the month, day and time (at                 
       least), in an order that is understood by people in your                 
       locale's territory.  Please try to keep the number of used               
       screen columns small, because many people work in windows with           
       only 80 columns.  But make this as wide as the other string              
       above, for non-recent files.  */                                         
    /* TRANSLATORS: ls output needs to be aligned for ease of reading,          
       so be wary of using variable width fields from the locale.               
       Note %b is handled specially by ls and aligned correctly.                
       Note also that specifying a width as in %5b is erroneous as strftime     
       will count bytes rather than characters in multibyte locales.  */        
    N_("%b %e %H:%M")                                                           Line 783
  };                                                                            
                                                                                
/* The set of signals that are caught.  */                                      
                                                                                
static sigset_t caught_signals;                                                 Line 788
                                                                                
/* If nonzero, the value of the pending fatal signal.  */                       
                                                                                
static sig_atomic_t volatile interrupt_signal;                                  Line 792
                                                                                
/* A count of the number of pending stop signals that have been received.  */   
                                                                                
static sig_atomic_t volatile stop_signal_count;                                 Line 796
                                                                                
/* Desired exit status.  */                                                     
                                                                                
static int exit_status;                                                         Line 800
                                                                                
/* Exit statuses.  */                                                           
enum                                                                            Line 803
  {                                                                             
    /* "ls" had a minor problem.  E.g., while processing a directory,           
       ls obtained the name of an entry via readdir, yet was later              
       unable to stat that name.  This happens when listing a directory         
       in which entries are actively being removed or renamed.  */              
    LS_MINOR_PROBLEM = 1,                                                       Line 809
                                                                                
    /* "ls" had more serious trouble (e.g., memory exhausted, invalid           
       option or failure to stat a command line argument.  */                   
    LS_FAILURE = 2                                                              Line 813
  };                                                                            
                                                                                
/* For long options that have no equivalent short option, use a                 
   non-character as a pseudo short option, starting with CHAR_MAX + 1.  */      
enum                                                                            Line 818
{                                                                               
  AUTHOR_OPTION = CHAR_MAX + 1,                                                 Line 820
  BLOCK_SIZE_OPTION,                                                            Line 821
  COLOR_OPTION,                                                                 Line 822
  DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION,                               Line 823
  FILE_TYPE_INDICATOR_OPTION,                                                   Line 824
  FORMAT_OPTION,                                                                Line 825
  FULL_TIME_OPTION,                                                             Line 826
  GROUP_DIRECTORIES_FIRST_OPTION,                                               Line 827
  HIDE_OPTION,                                                                  Line 828
  HYPERLINK_OPTION,                                                             Line 829
  INDICATOR_STYLE_OPTION,                                                       Line 830
  QUOTING_STYLE_OPTION,                                                         Line 831
  SHOW_CONTROL_CHARS_OPTION,                                                    Line 832
  SI_OPTION,                                                                    Line 833
  SORT_OPTION,                                                                  Line 834
  TIME_OPTION,                                                                  Line 835
  TIME_STYLE_OPTION                                                             Line 836
};                                                                              Block 27
                                                                                
static struct option const long_options[] =                                     Line 839
{                                                                               
  {"all", no_argument, NULL, 'a'},                                              Line 841
  {"escape", no_argument, NULL, 'b'},                                           Line 842
  {"directory", no_argument, NULL, 'd'},                                        Line 843
  {"dired", no_argument, NULL, 'D'},                                            Line 844
  {"full-time", no_argument, NULL, FULL_TIME_OPTION},                           Line 845
  {"group-directories-first", no_argument, NULL,                                Line 846
   GROUP_DIRECTORIES_FIRST_OPTION},                                             Line 847
  {"human-readable", no_argument, NULL, 'h'},                                   Line 848
  {"inode", no_argument, NULL, 'i'},                                            Line 849
  {"kibibytes", no_argument, NULL, 'k'},                                        Line 850
  {"numeric-uid-gid", no_argument, NULL, 'n'},                                  Line 851
  {"no-group", no_argument, NULL, 'G'},                                         Line 852
  {"hide-control-chars", no_argument, NULL, 'q'},                               Line 853
  {"reverse", no_argument, NULL, 'r'},                                          Line 854
  {"size", no_argument, NULL, 's'},                                             Line 855
  {"width", required_argument, NULL, 'w'},                                      Line 856
  {"almost-all", no_argument, NULL, 'A'},                                       Line 857
  {"ignore-backups", no_argument, NULL, 'B'},                                   Line 858
  {"classify", no_argument, NULL, 'F'},                                         Line 859
  {"file-type", no_argument, NULL, FILE_TYPE_INDICATOR_OPTION},                 Line 860
  {"si", no_argument, NULL, SI_OPTION},                                         Line 861
  {"dereference-command-line", no_argument, NULL, 'H'},                         Line 862
  {"dereference-command-line-symlink-to-dir", no_argument, NULL,                Line 863
   DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION},                             Line 864
  {"hide", required_argument, NULL, HIDE_OPTION},                               Line 865
  {"ignore", required_argument, NULL, 'I'},                                     Line 866
  {"indicator-style", required_argument, NULL, INDICATOR_STYLE_OPTION},         Line 867
  {"dereference", no_argument, NULL, 'L'},                                      Line 868
  {"literal", no_argument, NULL, 'N'},                                          Line 869
  {"quote-name", no_argument, NULL, 'Q'},                                       Line 870
  {"quoting-style", required_argument, NULL, QUOTING_STYLE_OPTION},             Line 871
  {"recursive", no_argument, NULL, 'R'},                                        Line 872
  {"format", required_argument, NULL, FORMAT_OPTION},                           Line 873
  {"show-control-chars", no_argument, NULL, SHOW_CONTROL_CHARS_OPTION},         Line 874
  {"sort", required_argument, NULL, SORT_OPTION},                               Line 875
  {"tabsize", required_argument, NULL, 'T'},                                    Line 876
  {"time", required_argument, NULL, TIME_OPTION},                               Line 877
  {"time-style", required_argument, NULL, TIME_STYLE_OPTION},                   Line 878
  {"color", optional_argument, NULL, COLOR_OPTION},                             Line 879
  {"hyperlink", optional_argument, NULL, HYPERLINK_OPTION},                     Line 880
  {"block-size", required_argument, NULL, BLOCK_SIZE_OPTION},                   Line 881
  {"context", no_argument, 0, 'Z'},                                             Line 882
  {"author", no_argument, NULL, AUTHOR_OPTION},                                 Line 883
  {GETOPT_HELP_OPTION_DECL},                                                    Line 884
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 885
  {NULL, 0, NULL, 0}                                                            Line 886
};                                                                              Block 28
                                                                                
static char const *const format_args[] =                                        Line 889
{                                                                               
  "verbose", "long", "commas", "horizontal", "across",                          Line 891
  "vertical", "single-column", NULL                                             Line 892
};                                                                              Block 29
static enum format const format_types[] =                                       Line 894
{                                                                               
  long_format, long_format, with_commas, horizontal, horizontal,                Line 896
  many_per_line, one_per_line                                                   Line 897
};                                                                              Block 30
ARGMATCH_VERIFY (format_args, format_types);                                    Line 899
                                                                                
static char const *const sort_args[] =                                          Line 901
{                                                                               
  "none", "time", "size", "extension", "version", NULL                          Line 903
};                                                                              Block 31
static enum sort_type const sort_types[] =                                      Line 905
{                                                                               
  sort_none, sort_time, sort_size, sort_extension, sort_version                 Line 907
};                                                                              Block 32
ARGMATCH_VERIFY (sort_args, sort_types);                                        Line 909
                                                                                
static char const *const time_args[] =                                          Line 911
{                                                                               
  "atime", "access", "use", "ctime", "status", NULL                             Line 913
};                                                                              Block 33
static enum time_type const time_types[] =                                      Line 915
{                                                                               
  time_atime, time_atime, time_atime, time_ctime, time_ctime                    Line 917
};                                                                              Block 34
ARGMATCH_VERIFY (time_args, time_types);                                        Line 919
                                                                                
static char const *const when_args[] =                                          Line 921
{                                                                               
  /* force and none are for compatibility with another color-ls version */      
  "always", "yes", "force",                                                     Line 924
  "never", "no", "none",                                                        Line 925
  "auto", "tty", "if-tty", NULL                                                 Line 926
};                                                                              
static enum when_type const when_types[] =                                      Line 928
{                                                                               
  when_always, when_always, when_always,                                        Line 930
  when_never, when_never, when_never,                                           Line 931
  when_if_tty, when_if_tty, when_if_tty                                         Line 932
};                                                                              Block 36
ARGMATCH_VERIFY (when_args, when_types);                                        Line 934
                                                                                
/* Information about filling a column.  */                                      
struct column_info                                                              Line 937
{                                                                               
  bool valid_len;                                                               Line 939
  size_t line_len;                                                              Line 940
  size_t *col_arr;                                                              Line 941
};                                                                              Block 37
                                                                                
/* Array with information about column filledness.  */                          
static struct column_info *column_info;                                         Line 945
                                                                                
/* Maximum number of columns ever possible for this display.  */                
static size_t max_idx;                                                          Line 948
                                                                                
/* The minimum width of a column is 3: 1 character for the name and 2           
   for the separating white space.  */                                          
#define MIN_COLUMN_WIDTH 3                                                      Line 952
                                                                                
                                                                                
/* This zero-based index is used solely with the --dired option.                
   When that option is in effect, this counter is incremented for each          
   byte of output generated by this program so that the beginning               
   and ending indices (in that output) of every file name can be recorded       
   and later output themselves.  */                                             
static size_t dired_pos;                                                        Line 960
                                                                                
#define DIRED_PUTCHAR(c) do {putchar ((c)); ++dired_pos;} while (0)             Line 962
                                                                                
/* Write S to STREAM and increment DIRED_POS by S_LEN.  */                      
#define DIRED_FPUTS(s, stream, s_len) \                                         Line 965
    do {fputs (s, stream); dired_pos += s_len;} while (0)                       Line 966
                                                                                
/* Like DIRED_FPUTS, but for use when S is a literal string.  */                
#define DIRED_FPUTS_LITERAL(s, stream) \                                        Line 969
    do {fputs (s, stream); dired_pos += sizeof (s) - 1;} while (0)              Line 970
                                                                                
#define DIRED_INDENT()       \                                                  Line 972
    do         \                                                                Line 973
      {         \                                                               Line 974
        if (dired)       \                                                      Line 975
          DIRED_FPUTS_LITERAL ("  ", stdout);    \                              Line 976
      }         \                                                               Line 977Block 41
    while (0)                                                                   Line 978
                                                                                
/* With --dired, store pairs of beginning and ending indices of file names.  */ 
static struct obstack dired_obstack;                                            Line 981
                                                                                
/* With --dired, store pairs of beginning and ending indices of any             
   directory names that appear as headers (just before 'total' line)            
   for lists of directory entries.  Such directory names are seen when          
   listing hierarchies using -R and when a directory is listed with at          
   least one other command line argument.  */                                   
static struct obstack subdired_obstack;                                         Line 988
                                                                                
/* Save the current index on the specified obstack, OBS.  */                    
#define PUSH_CURRENT_DIRED_POS(obs)     \                                       Line 991
  do         \                                                                  Line 992
    {         \                                                                 Line 993
      if (dired)       \                                                        Line 994
        obstack_grow (obs, &dired_pos, sizeof (dired_pos));  \                  Line 995
    }         \                                                                 Line 996Block 42
  while (0)                                                                     Line 997
                                                                                
/* With -R, this stack is used to help detect directory cycles.                 
   The device/inode pairs on this stack mirror the pairs in the                 
   active_dir_set hash table.  */                                               
static struct obstack dev_ino_obstack;                                          Line 1002
                                                                                
/* Push a pair onto the device/inode stack.  */                                 
static void                                                                     Line 1005
dev_ino_push (dev_t dev, ino_t ino)                                             Line 1006
{                                                                               
  void *vdi;                                                                    Line 1008
  struct dev_ino *di;                                                           Line 1009
  int dev_ino_size = sizeof *di;                                                Line 1010
  obstack_blank (&dev_ino_obstack, dev_ino_size);                               Line 1011
  vdi = obstack_next_free (&dev_ino_obstack);                                   Line 1012
  di = vdi;                                                                     Line 1013
  di--;                                                                         Line 1014
  di->st_dev = dev;                                                             Line 1015
  di->st_ino = ino;                                                             Line 1016
}                                                                               Block 43
                                                                                
/* Pop a dev/ino struct off the global dev_ino_obstack                          
   and return that struct.  */                                                  
static struct dev_ino                                                           Line 1021
dev_ino_pop (void)                                                              Line 1022
{                                                                               
  void *vdi;                                                                    Line 1024
  struct dev_ino *di;                                                           Line 1025
  int dev_ino_size = sizeof *di;                                                Line 1026
  assert (dev_ino_size <= obstack_object_size (&dev_ino_obstack));              Line 1027
  obstack_blank_fast (&dev_ino_obstack, -dev_ino_size);                         Line 1028
  vdi = obstack_next_free (&dev_ino_obstack);                                   Line 1029
  di = vdi;                                                                     Line 1030
  return *di;                                                                   Line 1031
}                                                                               Block 44
                                                                                
/* Note the use commented out below:                                            
#define ASSERT_MATCHING_DEV_INO(Name, Di) \                                     
  do      \                                                                     
    {      \                                                                    
      struct stat sb;    \                                                      
      assert (Name);    \                                                       
      assert (0 <= stat (Name, &sb));  \                                        
      assert (sb.st_dev == Di.st_dev);  \                                       
      assert (sb.st_ino == Di.st_ino);  \                                       
    }      \                                                                    
  while (0)                                                                     
*/                                                                              
                                                                                
/* Write to standard output PREFIX, followed by the quoting style and           
   a space-separated list of the integers stored in OS all on one line.  */     
                                                                                
static void                                                                     Line 1050
dired_dump_obstack (const char *prefix, struct obstack *os)                     Line 1051
{                                                                               
  size_t n_pos;                                                                 Line 1053
                                                                                
  n_pos = obstack_object_size (os) / sizeof (dired_pos);                        Line 1055
  if (n_pos > 0)                                                                Line 1056
    {                                                                           
      size_t *pos = (size_t *) obstack_finish (os);                             Line 1058
      fputs (prefix, stdout);                                                   Line 1059
      for (size_t i = 0; i < n_pos; i++)                                        Line 1060
        printf (" %lu", (unsigned long int) pos[i]);                            Line 1061
      putchar ('\n');                                                           Line 1062
    }                                                                           
}                                                                               Block 45
                                                                                
/* Return the address of the first plain %b spec in FMT, or NULL if             
   there is no such spec.  %5b etc. do not match, so that user                  
   widths/flags are honored.  */                                                
                                                                                
static char const * _GL_ATTRIBUTE_PURE                                          Line 1070
first_percent_b (char const *fmt)                                               Line 1071
{                                                                               
  for (; *fmt; fmt++)                                                           Line 1073
    if (fmt[0] == '%')                                                          Line 1074
      switch (fmt[1])                                                           Line 1075
        {                                                                       
        case 'b': return fmt;                                                   Line 1077
        case '%': fmt++; break;                                                 Line 1078
        }                                                                       
  return NULL;                                                                  Line 1080
}                                                                               Block 46
                                                                                
static char RFC3986[256];                                                       Line 1083
static void                                                                     Line 1084
file_escape_init (void)                                                         Line 1085
{                                                                               
  for (int i = 0; i < 256; i++)                                                 Line 1087
    RFC3986[i] |= c_isalnum (i) || i == '~' || i == '-' || i == '.' || i == '_';Line 1088
}                                                                               Block 47
                                                                                
/* Read the abbreviated month names from the locale, to align them              
   and to determine the max width of the field and to truncate names            
   greater than our max allowed.                                                
   Note even though this handles multibyte locales correctly                    
   it's not restricted to them as single byte locales can have                  
   variable width abbreviated months and also precomputing/caching              
   the names was seen to increase the performance of ls significantly.  */      
                                                                                
/* max number of display cells to use.                                          
   As of 2018 the abmon for Arabic has entries with width 12.                   
   It doesn't make much sense to support wider than this                        
   and locales should aim for abmon entries of width <= 5.  */                  
enum { MAX_MON_WIDTH = 12 };                                                    Line 1103
/* abformat[RECENT][MON] is the format to use for timestamps with               
   recentness RECENT and month MON.  */                                         
enum { ABFORMAT_SIZE = 128 };                                                   Line 1106Block 49
static char abformat[2][12][ABFORMAT_SIZE];                                     Line 1107
/* True if precomputed formats should be used.  This can be false if            
   nl_langinfo fails, if a format or month abbreviation is unusually            
   long, or if a month abbreviation contains '%'.  */                           
static bool use_abformat;                                                       Line 1111
                                                                                
/* Store into ABMON the abbreviated month names, suitably aligned.              
   Return true if successful.  */                                               
                                                                                
static bool                                                                     Line 1116
abmon_init (char abmon[12][ABFORMAT_SIZE])                                      Line 1117
{                                                                               
#ifndef HAVE_NL_LANGINFO                                                        Line 1119
  return false;                                                                 Line 1120
#else                                                                           Line 1121
  size_t required_mon_width = MAX_MON_WIDTH;                                    Line 1122
  size_t curr_max_width;                                                        Line 1123
  do                                                                            
    {                                                                           
      curr_max_width = required_mon_width;                                      Line 1126
      required_mon_width = 0;                                                   Line 1127
      for (int i = 0; i < 12; i++)                                              Line 1128
        {                                                                       
          size_t width = curr_max_width;                                        Line 1130
          char const *abbr = nl_langinfo (ABMON_1 + i);                         Line 1131
          if (strchr (abbr, '%'))                                               Line 1132
            return false;                                                       Line 1133
          size_t req = mbsalign (abbr, abmon[i], ABFORMAT_SIZE,                 Line 1134
                                 &width, MBS_ALIGN_LEFT, 0);                    Line 1135
          if (! (req < ABFORMAT_SIZE))                                          Line 1136
            return false;                                                       Line 1137
          required_mon_width = MAX (required_mon_width, width);                 Line 1138
        }                                                                       
    }                                                                           
  while (curr_max_width > required_mon_width);                                  Line 1141
                                                                                
  return true;                                                                  Line 1143
#endif                                                                          Line 1144
}                                                                               Block 50
                                                                                
/* Initialize ABFORMAT and USE_ABFORMAT.  */                                    
                                                                                
static void                                                                     Line 1149
abformat_init (void)                                                            Line 1150
{                                                                               
  char const *pb[2];                                                            Line 1152
  for (int recent = 0; recent < 2; recent++)                                    Line 1153
    pb[recent] = first_percent_b (long_time_format[recent]);                    Line 1154
  if (! (pb[0] || pb[1]))                                                       Line 1155
    return;                                                                     Line 1156
                                                                                
  char abmon[12][ABFORMAT_SIZE];                                                Line 1158
  if (! abmon_init (abmon))                                                     Line 1159
    return;                                                                     Line 1160
                                                                                
  for (int recent = 0; recent < 2; recent++)                                    Line 1162
    {                                                                           
      char const *fmt = long_time_format[recent];                               Line 1164
      for (int i = 0; i < 12; i++)                                              Line 1165
        {                                                                       
          char *nfmt = abformat[recent][i];                                     Line 1167
          int nbytes;                                                           Line 1168
                                                                                
          if (! pb[recent])                                                     Line 1170
            nbytes = snprintf (nfmt, ABFORMAT_SIZE, "%s", fmt);                 Line 1171
          else                                                                  Line 1172
            {                                                                   
              if (! (pb[recent] - fmt <= MIN (ABFORMAT_SIZE, INT_MAX)))         Line 1174
                return;                                                         Line 1175
              int prefix_len = pb[recent] - fmt;                                Line 1176
              nbytes = snprintf (nfmt, ABFORMAT_SIZE, "%.*s%s%s",               Line 1177
                                 prefix_len, fmt, abmon[i], pb[recent] + 2);    Line 1178
            }                                                                   
                                                                                
          if (! (0 <= nbytes && nbytes < ABFORMAT_SIZE))                        Line 1181
            return;                                                             Line 1182
        }                                                                       
    }                                                                           
                                                                                
  use_abformat = true;                                                          Line 1186
}                                                                               Block 51
                                                                                
static size_t                                                                   Line 1189
dev_ino_hash (void const *x, size_t table_size)                                 Line 1190
{                                                                               
  struct dev_ino const *p = x;                                                  Line 1192
  return (uintmax_t) p->st_ino % table_size;                                    Line 1193
}                                                                               Block 52
                                                                                
static bool                                                                     Line 1196
dev_ino_compare (void const *x, void const *y)                                  Line 1197
{                                                                               
  struct dev_ino const *a = x;                                                  Line 1199
  struct dev_ino const *b = y;                                                  Line 1200
  return SAME_INODE (*a, *b) ? true : false;                                    Line 1201
}                                                                               Block 53
                                                                                
static void                                                                     Line 1204
dev_ino_free (void *x)                                                          Line 1205
{                                                                               
  free (x);                                                                     Line 1207
}                                                                               Block 54
                                                                                
/* Add the device/inode pair (P->st_dev/P->st_ino) to the set of                
   active directories.  Return true if there is already a matching              
   entry in the table.  */                                                      
                                                                                
static bool                                                                     Line 1214
visit_dir (dev_t dev, ino_t ino)                                                Line 1215
{                                                                               
  struct dev_ino *ent;                                                          Line 1217
  struct dev_ino *ent_from_table;                                               Line 1218
  bool found_match;                                                             Line 1219
                                                                                
  ent = xmalloc (sizeof *ent);                                                  Line 1221
  ent->st_ino = ino;                                                            Line 1222
  ent->st_dev = dev;                                                            Line 1223
                                                                                
  /* Attempt to insert this entry into the table.  */                           
  ent_from_table = hash_insert (active_dir_set, ent);                           Line 1226
                                                                                
  if (ent_from_table == NULL)                                                   Line 1228
    {                                                                           
      /* Insertion failed due to lack of memory.  */                            
      xalloc_die ();                                                            ...!common auto-comment...
    }                                                                           
                                                                                
  found_match = (ent_from_table != ent);                                        Line 1234
                                                                                
  if (found_match)                                                              Line 1236
    {                                                                           
      /* ent was not inserted, so free it.  */                                  
      free (ent);                                                               Line 1239
    }                                                                           
                                                                                
  return found_match;                                                           Line 1242
}                                                                               Block 55
                                                                                
static void                                                                     Line 1245
free_pending_ent (struct pending *p)                                            Line 1246
{                                                                               
  free (p->name);                                                               Line 1248
  free (p->realname);                                                           Line 1249
  free (p);                                                                     Line 1250
}                                                                               Block 56
                                                                                
static bool                                                                     Line 1253
is_colored (enum indicator_no type)                                             Line 1254
{                                                                               
  size_t len = color_indicator[type].len;                                       Line 1256
  char const *s = color_indicator[type].string;                                 Line 1257
  return ! (len == 0                                                            Line 1258
            || (len == 1 && STRNCMP_LIT (s, "0") == 0)                          Line 1259
            || (len == 2 && STRNCMP_LIT (s, "00") == 0));                       Line 1260
}                                                                               Block 57
                                                                                
static void                                                                     Line 1263
restore_default_color (void)                                                    Line 1264
{                                                                               
  put_indicator (&color_indicator[C_LEFT]);                                     Line 1266
  put_indicator (&color_indicator[C_RIGHT]);                                    Line 1267
}                                                                               Block 58
                                                                                
static void                                                                     Line 1270
set_normal_color (void)                                                         Line 1271
{                                                                               
  if (print_with_color && is_colored (C_NORM))                                  Line 1273
    {                                                                           
      put_indicator (&color_indicator[C_LEFT]);                                 Line 1275
      put_indicator (&color_indicator[C_NORM]);                                 Line 1276
      put_indicator (&color_indicator[C_RIGHT]);                                Line 1277
    }                                                                           
}                                                                               Block 59
                                                                                
/* An ordinary signal was received; arrange for the program to exit.  */        
                                                                                
static void                                                                     Line 1283
sighandler (int sig)                                                            Line 1284
{                                                                               
  if (! SA_NOCLDSTOP)                                                           Line 1286
    signal (sig, SIG_IGN);                                                      Line 1287
  if (! interrupt_signal)                                                       Line 1288
    interrupt_signal = sig;                                                     Line 1289
}                                                                               Block 60
                                                                                
/* A SIGTSTP was received; arrange for the program to suspend itself.  */       
                                                                                
static void                                                                     Line 1294
stophandler (int sig)                                                           Line 1295
{                                                                               
  if (! SA_NOCLDSTOP)                                                           Line 1297
    signal (sig, stophandler);                                                  Line 1298
  if (! interrupt_signal)                                                       Line 1299
    stop_signal_count++;                                                        Line 1300
}                                                                               Block 61
                                                                                
/* Process any pending signals.  If signals are caught, this function           
   should be called periodically.  Ideally there should never be an             
   unbounded amount of time when signals are not being processed.               
   Signal handling can restore the default colors, so callers must              
   immediately change colors after invoking this function.  */                  
                                                                                
static void                                                                     Line 1309
process_signals (void)                                                          Line 1310
{                                                                               
  while (interrupt_signal || stop_signal_count)                                 Line 1312
    {                                                                           
      int sig;                                                                  Line 1314
      int stops;                                                                Line 1315
      sigset_t oldset;                                                          Line 1316
                                                                                
      if (used_color)                                                           Line 1318
        restore_default_color ();                                               Line 1319
      fflush (stdout);                                                          Line 1320
                                                                                
      sigprocmask (SIG_BLOCK, &caught_signals, &oldset);                        Line 1322
                                                                                
      /* Reload interrupt_signal and stop_signal_count, in case a new           
         signal was handled before sigprocmask took effect.  */                 
      sig = interrupt_signal;                                                   Line 1326
      stops = stop_signal_count;                                                Line 1327
                                                                                
      /* SIGTSTP is special, since the application can receive that signal      
         more than once.  In this case, don't set the signal handler to the     
         default.  Instead, just raise the uncatchable SIGSTOP.  */             
      if (stops)                                                                Line 1332
        {                                                                       
          stop_signal_count = stops - 1;                                        Line 1334
          sig = SIGSTOP;                                                        Line 1335
        }                                                                       
      else                                                                      Line 1337
        signal (sig, SIG_DFL);                                                  Line 1338
                                                                                
      /* Exit or suspend the program.  */                                       
      raise (sig);                                                              Line 1341
      sigprocmask (SIG_SETMASK, &oldset, NULL);                                 Line 1342
                                                                                
      /* If execution reaches here, then the program has been                   
         continued (after being suspended).  */                                 
    }                                                                           
}                                                                               Block 62
                                                                                
/* Setup signal handlers if INIT is true,                                       
   otherwise restore to the default.  */                                        
                                                                                
static void                                                                     Line 1352
signal_setup (bool init)                                                        Line 1353
{                                                                               
  /* The signals that are trapped, and the number of such signals.  */          
  static int const sig[] =                                                      Line 1356
    {                                                                           
      /* This one is handled specially.  */                                     
      SIGTSTP,                                                                  Line 1359
                                                                                
      /* The usual suspects.  */                                                
      SIGALRM, SIGHUP, SIGINT, SIGPIPE, SIGQUIT, SIGTERM,                       Line 1362
#ifdef SIGPOLL                                                                  Line 1363
      SIGPOLL,                                                                  Line 1364
#endif                                                                          Line 1365
#ifdef SIGPROF                                                                  Line 1366
      SIGPROF,                                                                  Line 1367
#endif                                                                          Line 1368
#ifdef SIGVTALRM                                                                Line 1369
      SIGVTALRM,                                                                Line 1370
#endif                                                                          Line 1371
#ifdef SIGXCPU                                                                  Line 1372
      SIGXCPU,                                                                  Line 1373
#endif                                                                          Line 1374
#ifdef SIGXFSZ                                                                  Line 1375
      SIGXFSZ,                                                                  Line 1376
#endif                                                                          Line 1377
    };                                                                          
  enum { nsigs = ARRAY_CARDINALITY (sig) };                                     Line 1379
                                                                                
#if ! SA_NOCLDSTOP                                                              Line 1381
  static bool caught_sig[nsigs];                                                Line 1382
#endif                                                                          Line 1383
                                                                                
  int j;                                                                        Line 1385
                                                                                
  if (init)                                                                     Line 1387
    {                                                                           
#if SA_NOCLDSTOP                                                                Line 1389
      struct sigaction act;                                                     Line 1390
                                                                                
      sigemptyset (&caught_signals);                                            Line 1392
      for (j = 0; j < nsigs; j++)                                               Line 1393
        {                                                                       
          sigaction (sig[j], NULL, &act);                                       Line 1395
          if (act.sa_handler != SIG_IGN)                                        Line 1396
            sigaddset (&caught_signals, sig[j]);                                Line 1397
        }                                                                       
                                                                                
      act.sa_mask = caught_signals;                                             Line 1400
      act.sa_flags = SA_RESTART;                                                Line 1401
                                                                                
      for (j = 0; j < nsigs; j++)                                               Line 1403
        if (sigismember (&caught_signals, sig[j]))                              Line 1404
          {                                                                     
            act.sa_handler = sig[j] == SIGTSTP ? stophandler : sighandler;      Line 1406
            sigaction (sig[j], &act, NULL);                                     Line 1407
          }                                                                     
#else                                                                           Line 1409
      for (j = 0; j < nsigs; j++)                                               Line 1410
        {                                                                       
          caught_sig[j] = (signal (sig[j], SIG_IGN) != SIG_IGN);                Line 1412
          if (caught_sig[j])                                                    Line 1413
            {                                                                   
              signal (sig[j], sig[j] == SIGTSTP ? stophandler : sighandler);    Line 1415
              siginterrupt (sig[j], 0);                                         Line 1416
            }                                                                   
        }                                                                       
#endif                                                                          Line 1419
    }                                                                           
  else /* restore.  */                                                          Line 1421
    {                                                                           
#if SA_NOCLDSTOP                                                                Line 1423
      for (j = 0; j < nsigs; j++)                                               Line 1424
        if (sigismember (&caught_signals, sig[j]))                              Line 1425
          signal (sig[j], SIG_DFL);                                             Line 1426
#else                                                                           Line 1427
      for (j = 0; j < nsigs; j++)                                               Line 1428
        if (caught_sig[j])                                                      Line 1429
          signal (sig[j], SIG_DFL);                                             Line 1430
#endif                                                                          Line 1431
    }                                                                           
}                                                                               
                                                                                
static inline void                                                              Line 1435
signal_init (void)                                                              Line 1436
{                                                                               
  signal_setup (true);                                                          Line 1438
}                                                                               Block 64
                                                                                
static inline void                                                              Line 1441
signal_restore (void)                                                           Line 1442
{                                                                               
  signal_setup (false);                                                         Line 1444
}                                                                               Block 65
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 1448
{                                                                               
  int i;                                                                        Line 1450
  struct pending *thispend;                                                     Line 1451
  int n_files;                                                                  Line 1452
                                                                                
  initialize_main (&argc, &argv);                                               VMS-specific entry point handling wildcard expansion
  set_program_name (argv[0]);                                                   Retains program name and discards path
  setlocale (LC_ALL, "");                                                       Sets up internationalization (i18n)
  bindtextdomain (PACKAGE, LOCALEDIR);                                          Assigns i18n directorySets text domain for _() [gettext()] function
  textdomain (PACKAGE);                                                         Sets text domain for _() [gettext()] function
                                                                                
  initialize_exit_failure (LS_FAILURE);                                         Line 1460
  atexit (close_stdout);                                                        Close stdout on exit (see gnulib)
                                                                                
  assert (ARRAY_CARDINALITY (color_indicator) + 1                               Line 1463
          == ARRAY_CARDINALITY (indicator_name));                               Line 1464
                                                                                
  exit_status = EXIT_SUCCESS;                                                   Line 1466
  print_dir_name = true;                                                        Line 1467
  pending_dirs = NULL;                                                          Line 1468
                                                                                
  current_time.tv_sec = TYPE_MINIMUM (time_t);                                  Line 1470
  current_time.tv_nsec = -1;                                                    Line 1471
                                                                                
  i = decode_switches (argc, argv);                                             Line 1473
                                                                                
  if (print_with_color)                                                         Line 1475
    parse_ls_color ();                                                          Line 1476
                                                                                
  /* Test print_with_color again, because the call to parse_ls_color            
     may have just reset it -- e.g., if LS_COLORS is invalid.  */               
  if (print_with_color)                                                         Line 1480
    {                                                                           
      /* Avoid following symbolic links when possible.  */                      
      if (is_colored (C_ORPHAN)                                                 Line 1483
          || (is_colored (C_EXEC) && color_symlink_as_referent)                 Line 1484
          || (is_colored (C_MISSING) && format == long_format))                 Line 1485
        check_symlink_color = true;                                             Line 1486
    }                                                                           
                                                                                
  if (dereference == DEREF_UNDEFINED)                                           Line 1489
    dereference = ((immediate_dirs                                              Line 1490
                    || indicator_style == classify                              Line 1491
                    || format == long_format)                                   Line 1492
                   ? DEREF_NEVER                                                Line 1493
                   : DEREF_COMMAND_LINE_SYMLINK_TO_DIR);                        Line 1494
                                                                                
  /* When using -R, initialize a data structure we'll use to                    
     detect any directory cycles.  */                                           
  if (recursive)                                                                Line 1498
    {                                                                           
      active_dir_set = hash_initialize (INITIAL_TABLE_SIZE, NULL,               Line 1500
                                        dev_ino_hash,                           Line 1501
                                        dev_ino_compare,                        Line 1502
                                        dev_ino_free);                          Line 1503
      if (active_dir_set == NULL)                                               Line 1504
        xalloc_die ();                                                          ...!common auto-comment...
                                                                                
      obstack_init (&dev_ino_obstack);                                          Line 1507
    }                                                                           
                                                                                
  localtz = tzalloc (getenv ("TZ"));                                            Line 1510
                                                                                
  format_needs_stat = sort_type == sort_time || sort_type == sort_size          Line 1512
    || format == long_format                                                    Line 1513
    || print_scontext                                                           Line 1514
    || print_block_size;                                                        Line 1515
  format_needs_type = (! format_needs_stat                                      Line 1516
                       && (recursive                                            Line 1517
                           || print_with_color                                  Line 1518
                           || indicator_style != none                           Line 1519
                           || directories_first));                              Line 1520
                                                                                
  if (dired)                                                                    Line 1522
    {                                                                           
      obstack_init (&dired_obstack);                                            Line 1524
      obstack_init (&subdired_obstack);                                         Line 1525
    }                                                                           
                                                                                
  if (print_hyperlink)                                                          Line 1528
    {                                                                           
      file_escape_init ();                                                      Line 1530
                                                                                
      hostname = xgethostname ();                                               Line 1532
      /* The hostname is generally ignored,                                     
         so ignore failures obtaining it.  */                                   
      if (! hostname)                                                           Line 1535
        hostname = "";                                                          Line 1536
    }                                                                           
                                                                                
  cwd_n_alloc = 100;                                                            Line 1539
  cwd_file = xnmalloc (cwd_n_alloc, sizeof *cwd_file);                          Line 1540
  cwd_n_used = 0;                                                               Line 1541
                                                                                
  clear_files ();                                                               Line 1543
                                                                                
  n_files = argc - i;                                                           Line 1545
                                                                                
  if (n_files <= 0)                                                             Line 1547
    {                                                                           
      if (immediate_dirs)                                                       Line 1549
        gobble_file (".", directory, NOT_AN_INODE_NUMBER, true, "");            Line 1550
      else                                                                      Line 1551
        queue_directory (".", NULL, true);                                      Line 1552
    }                                                                           
  else                                                                          Line 1554
    do                                                                          
      gobble_file (argv[i++], unknown, NOT_AN_INODE_NUMBER, true, "");          Line 1556
    while (i < argc);                                                           Line 1557
                                                                                
  if (cwd_n_used)                                                               Line 1559
    {                                                                           
      sort_files ();                                                            Line 1561
      if (!immediate_dirs)                                                      Line 1562
        extract_dirs_from_files (NULL, true);                                   Line 1563
      /* 'cwd_n_used' might be zero now.  */                                    
    }                                                                           
                                                                                
  /* In the following if/else blocks, it is sufficient to test 'pending_dirs'   
     (and not pending_dirs->name) because there may be no markers in the queue  
     at this point.  A marker may be enqueued when extract_dirs_from_files is   
     called with a non-empty string or via print_dir.  */                       
  if (cwd_n_used)                                                               Line 1571
    {                                                                           
      print_current_files ();                                                   Line 1573
      if (pending_dirs)                                                         Line 1574
        DIRED_PUTCHAR ('\n');                                                   Line 1575
    }                                                                           
  else if (n_files <= 1 && pending_dirs && pending_dirs->next == 0)             Line 1577
    print_dir_name = false;                                                     Line 1578
                                                                                
  while (pending_dirs)                                                          Line 1580
    {                                                                           
      thispend = pending_dirs;                                                  Line 1582
      pending_dirs = pending_dirs->next;                                        Line 1583
                                                                                
      if (LOOP_DETECT)                                                          Line 1585
        {                                                                       
          if (thispend->name == NULL)                                           Line 1587
            {                                                                   
              /* thispend->name == NULL means this is a marker entry            
                 indicating we've finished processing the directory.            
                 Use its dev/ino numbers to remove the corresponding            
                 entry from the active_dir_set hash table.  */                  
              struct dev_ino di = dev_ino_pop ();                               Line 1593
              struct dev_ino *found = hash_delete (active_dir_set, &di);        Line 1594
              /* ASSERT_MATCHING_DEV_INO (thispend->realname, di); */           
              assert (found);                                                   Line 1596
              dev_ino_free (found);                                             Line 1597
              free_pending_ent (thispend);                                      Line 1598
              continue;                                                         Line 1599
            }                                                                   
        }                                                                       
                                                                                
      print_dir (thispend->name, thispend->realname,                            Line 1603
                 thispend->command_line_arg);                                   Line 1604
                                                                                
      free_pending_ent (thispend);                                              Line 1606
      print_dir_name = true;                                                    Line 1607
    }                                                                           
                                                                                
  if (print_with_color && used_color)                                           Line 1610
    {                                                                           
      int j;                                                                    Line 1612
                                                                                
      /* Skip the restore when it would be a no-op, i.e.,                       
         when left is "\033[" and right is "m".  */                             
      if (!(color_indicator[C_LEFT].len == 2                                    Line 1616
            && memcmp (color_indicator[C_LEFT].string, "\033[", 2) == 0         Line 1617
            && color_indicator[C_RIGHT].len == 1                                Line 1618
            && color_indicator[C_RIGHT].string[0] == 'm'))                      Line 1619
        restore_default_color ();                                               Line 1620
                                                                                
      fflush (stdout);                                                          Line 1622
                                                                                
      signal_restore ();                                                        Line 1624
                                                                                
      /* Act on any signals that arrived before the default was restored.       
         This can process signals out of order, but there doesn't seem to       
         be an easy way to do them in order, and the order isn't that           
         important anyway.  */                                                  
      for (j = stop_signal_count; j; j--)                                       Line 1630
        raise (SIGSTOP);                                                        Line 1631
      j = interrupt_signal;                                                     Line 1632
      if (j)                                                                    Line 1633
        raise (j);                                                              Line 1634
    }                                                                           
                                                                                
  if (dired)                                                                    Line 1637
    {                                                                           
      /* No need to free these since we're about to exit.  */                   
      dired_dump_obstack ("//DIRED//", &dired_obstack);                         Line 1640
      dired_dump_obstack ("//SUBDIRED//", &subdired_obstack);                   Line 1641
      printf ("//DIRED-OPTIONS// --quoting-style=%s\n",                         Line 1642
              quoting_style_args[get_quoting_style (filename_quoting_options)]);Line 1643
    }                                                                           
                                                                                
  if (LOOP_DETECT)                                                              Line 1646
    {                                                                           
      assert (hash_get_n_entries (active_dir_set) == 0);                        Line 1648
      hash_free (active_dir_set);                                               Line 1649
    }                                                                           
                                                                                
  return exit_status;                                                           Line 1652
}                                                                               Block 66
                                                                                
/* Set the line length to the value given by SPEC.  Return true if              
   successful.  0 means no limit on line length.  */                            
                                                                                
static bool                                                                     Line 1658
set_line_length (char const *spec)                                              Line 1659
{                                                                               
  uintmax_t val;                                                                Line 1661
                                                                                
  /* Treat too-large values as if they were SIZE_MAX, which is                  
     effectively infinity.  */                                                  
  switch (xstrtoumax (spec, NULL, 0, &val, ""))                                 Line 1665
    {                                                                           
    case LONGINT_OK:                                                            Line 1667
      line_length = MIN (val, SIZE_MAX);                                        Line 1668
      return true;                                                              Line 1669
                                                                                
    case LONGINT_OVERFLOW:                                                      Line 1671
      line_length = SIZE_MAX;                                                   Line 1672
      return true;                                                              Line 1673
                                                                                
    default:                                                                    Line 1675
      return false;                                                             Line 1676
    }                                                                           
}                                                                               Block 67
                                                                                
/* Set all the option flags according to the switches specified.                
   Return the index of the first non-option argument.  */                       
                                                                                
static int                                                                      Line 1683
decode_switches (int argc, char **argv)                                         Line 1684
{                                                                               
  char *time_style_option = NULL;                                               Line 1686
                                                                                
  bool sort_type_specified = false;                                             Line 1688
  bool kibibytes_specified = false;                                             Line 1689
                                                                                
  qmark_funny_chars = false;                                                    Line 1691
                                                                                
  /* initialize all switches to default settings */                             
                                                                                
  switch (ls_mode)                                                              Line 1695
    {                                                                           
    case LS_MULTI_COL:                                                          Line 1697
      /* This is for the 'dir' program.  */                                     
      format = many_per_line;                                                   Line 1699
      set_quoting_style (NULL, escape_quoting_style);                           Line 1700
      break;                                                                    Line 1701
                                                                                
    case LS_LONG_FORMAT:                                                        Line 1703
      /* This is for the 'vdir' program.  */                                    
      format = long_format;                                                     Line 1705
      set_quoting_style (NULL, escape_quoting_style);                           Line 1706
      break;                                                                    Line 1707
                                                                                
    case LS_LS:                                                                 Line 1709
      /* This is for the 'ls' program.  */                                      
      if (isatty (STDOUT_FILENO))                                               Line 1711
        {                                                                       
          format = many_per_line;                                               Line 1713
          set_quoting_style (NULL, shell_escape_quoting_style);                 Line 1714
          /* See description of qmark_funny_chars, above.  */                   
          qmark_funny_chars = true;                                             Line 1716
        }                                                                       
      else                                                                      Line 1718
        {                                                                       
          format = one_per_line;                                                Line 1720
          qmark_funny_chars = false;                                            Line 1721
        }                                                                       
      break;                                                                    Line 1723
                                                                                
    default:                                                                    Line 1725
      abort ();                                                                 ...!common auto-comment...
    }                                                                           
                                                                                
  time_type = time_mtime;                                                       Line 1729
  sort_type = sort_name;                                                        Line 1730
  sort_reverse = false;                                                         Line 1731
  numeric_ids = false;                                                          Line 1732
  print_block_size = false;                                                     Line 1733
  indicator_style = none;                                                       Line 1734
  print_inode = false;                                                          Line 1735
  dereference = DEREF_UNDEFINED;                                                Line 1736
  recursive = false;                                                            Line 1737
  immediate_dirs = false;                                                       Line 1738
  ignore_mode = IGNORE_DEFAULT;                                                 Line 1739
  ignore_patterns = NULL;                                                       Line 1740
  hide_patterns = NULL;                                                         Line 1741
  print_scontext = false;                                                       Line 1742
                                                                                
  getenv_quoting_style ();                                                      Line 1744
                                                                                
  line_length = 80;                                                             Line 1746
  {                                                                             
    char const *p = getenv ("COLUMNS");                                         Line 1748
    if (p && *p && ! set_line_length (p))                                       Line 1749
      error (0, 0,                                                              Line 1750
             _("ignoring invalid width in environment variable COLUMNS: %s"),   Line 1751
             quote (p));                                                        Line 1752
  }                                                                             
                                                                                
#ifdef TIOCGWINSZ                                                               Line 1755
  {                                                                             
    struct winsize ws;                                                          Line 1757
                                                                                
    if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1                            Line 1759...!syscalls auto-comment...
        && 0 < ws.ws_col && ws.ws_col == (size_t) ws.ws_col)                    Line 1760
      line_length = ws.ws_col;                                                  Line 1761
  }                                                                             
#endif                                                                          Line 1763
                                                                                
  {                                                                             
    char const *p = getenv ("TABSIZE");                                         Line 1766
    tabsize = 8;                                                                Line 1767
    if (p)                                                                      Line 1768
      {                                                                         
        unsigned long int tmp_ulong;                                            Line 1770
        if (xstrtoul (p, NULL, 0, &tmp_ulong, NULL) == LONGINT_OK               Line 1771
            && tmp_ulong <= SIZE_MAX)                                           Line 1772
          {                                                                     
            tabsize = tmp_ulong;                                                Line 1774
          }                                                                     
        else                                                                    Line 1776
          {                                                                     
            error (0, 0,                                                        Line 1778
             _("ignoring invalid tab size in environment variable TABSIZE: %s"),Line 1779
                   quote (p));                                                  Line 1780
          }                                                                     
      }                                                                         
  }                                                                             
                                                                                
  while (true)                                                                  Line 1785
    {                                                                           
      int oi = -1;                                                              Line 1787
      int c = getopt_long (argc, argv,                                          Line 1788
                           "abcdfghiklmnopqrstuvw:xABCDFGHI:LNQRST:UXZ1",       Line 1789
                           long_options, &oi);                                  Line 1790
      if (c == -1)                                                              Line 1791
        break;                                                                  Line 1792
                                                                                
      switch (c)                                                                Line 1794
        {                                                                       
        case 'a':                                                               Line 1796
          ignore_mode = IGNORE_MINIMAL;                                         Line 1797
          break;                                                                Line 1798
                                                                                
        case 'b':                                                               Line 1800
          set_quoting_style (NULL, escape_quoting_style);                       Line 1801
          break;                                                                Line 1802
                                                                                
        case 'c':                                                               Line 1804
          time_type = time_ctime;                                               Line 1805
          break;                                                                Line 1806
                                                                                
        case 'd':                                                               Line 1808
          immediate_dirs = true;                                                Line 1809
          break;                                                                Line 1810
                                                                                
        case 'f':                                                               Line 1812
          /* Same as enabling -a -U and disabling -l -s.  */                    
          ignore_mode = IGNORE_MINIMAL;                                         Line 1814
          sort_type = sort_none;                                                Line 1815
          sort_type_specified = true;                                           Line 1816
          /* disable -l */                                                      
          if (format == long_format)                                            Line 1818
            format = (isatty (STDOUT_FILENO) ? many_per_line : one_per_line);   Line 1819
          print_block_size = false; /* disable -s */                            Line 1820
          print_with_color = false; /* disable --color */                       Line 1821
          print_hyperlink = false; /* disable --hyperlink */                    Line 1822
          break;                                                                Line 1823
                                                                                
        case FILE_TYPE_INDICATOR_OPTION: /* --file-type */                      Line 1825
          indicator_style = file_type;                                          Line 1826
          break;                                                                Line 1827
                                                                                
        case 'g':                                                               Line 1829
          format = long_format;                                                 Line 1830
          print_owner = false;                                                  Line 1831
          break;                                                                Line 1832
                                                                                
        case 'h':                                                               Line 1834
          file_human_output_opts = human_output_opts =                          Line 1835
            human_autoscale | human_SI | human_base_1024;                       Line 1836
          file_output_block_size = output_block_size = 1;                       Line 1837
          break;                                                                Line 1838
                                                                                
        case 'i':                                                               Line 1840
          print_inode = true;                                                   Line 1841
          break;                                                                Line 1842
                                                                                
        case 'k':                                                               Line 1844
          kibibytes_specified = true;                                           Line 1845
          break;                                                                Line 1846
                                                                                
        case 'l':                                                               Line 1848
          format = long_format;                                                 Line 1849
          break;                                                                Line 1850
                                                                                
        case 'm':                                                               Line 1852
          format = with_commas;                                                 Line 1853
          break;                                                                Line 1854
                                                                                
        case 'n':                                                               Line 1856
          numeric_ids = true;                                                   Line 1857
          format = long_format;                                                 Line 1858
          break;                                                                Line 1859
                                                                                
        case 'o':  /* Just like -l, but don't display group info.  */           Line 1861
          format = long_format;                                                 Line 1862
          print_group = false;                                                  Line 1863
          break;                                                                Line 1864
                                                                                
        case 'p':                                                               Line 1866
          indicator_style = slash;                                              Line 1867
          break;                                                                Line 1868
                                                                                
        case 'q':                                                               Line 1870
          qmark_funny_chars = true;                                             Line 1871
          break;                                                                Line 1872
                                                                                
        case 'r':                                                               Line 1874
          sort_reverse = true;                                                  Line 1875
          break;                                                                Line 1876
                                                                                
        case 's':                                                               Line 1878
          print_block_size = true;                                              Line 1879
          break;                                                                Line 1880
                                                                                
        case 't':                                                               Line 1882
          sort_type = sort_time;                                                Line 1883
          sort_type_specified = true;                                           Line 1884
          break;                                                                Line 1885
                                                                                
        case 'u':                                                               Line 1887
          time_type = time_atime;                                               Line 1888
          break;                                                                Line 1889
                                                                                
        case 'v':                                                               Line 1891
          sort_type = sort_version;                                             Line 1892
          sort_type_specified = true;                                           Line 1893
          break;                                                                Line 1894
                                                                                
        case 'w':                                                               Line 1896
          if (! set_line_length (optarg))                                       Line 1897
            die (LS_FAILURE, 0, "%s: %s", _("invalid line width"),              Line 1898
                 quote (optarg));                                               Line 1899
          break;                                                                Line 1900
                                                                                
        case 'x':                                                               Line 1902
          format = horizontal;                                                  Line 1903
          break;                                                                Line 1904
                                                                                
        case 'A':                                                               Line 1906
          ignore_mode = IGNORE_DOT_AND_DOTDOT;                                  Line 1907
          break;                                                                Line 1908
                                                                                
        case 'B':                                                               Line 1910
          add_ignore_pattern ("*~");                                            Line 1911
          add_ignore_pattern (".*~");                                           Line 1912
          break;                                                                Line 1913
                                                                                
        case 'C':                                                               Line 1915
          format = many_per_line;                                               Line 1916
          break;                                                                Line 1917
                                                                                
        case 'D':                                                               Line 1919
          dired = true;                                                         Line 1920
          break;                                                                Line 1921
                                                                                
        case 'F':                                                               Line 1923
          indicator_style = classify;                                           Line 1924
          break;                                                                Line 1925
                                                                                
        case 'G':  /* inhibit display of group info */                          Line 1927
          print_group = false;                                                  Line 1928
          break;                                                                Line 1929
                                                                                
        case 'H':                                                               Line 1931
          dereference = DEREF_COMMAND_LINE_ARGUMENTS;                           Line 1932
          break;                                                                Line 1933
                                                                                
        case DEREFERENCE_COMMAND_LINE_SYMLINK_TO_DIR_OPTION:                    Line 1935
          dereference = DEREF_COMMAND_LINE_SYMLINK_TO_DIR;                      Line 1936
          break;                                                                Line 1937
                                                                                
        case 'I':                                                               Line 1939
          add_ignore_pattern (optarg);                                          Line 1940
          break;                                                                Line 1941
                                                                                
        case 'L':                                                               Line 1943
          dereference = DEREF_ALWAYS;                                           Line 1944
          break;                                                                Line 1945
                                                                                
        case 'N':                                                               Line 1947
          set_quoting_style (NULL, literal_quoting_style);                      Line 1948
          break;                                                                Line 1949
                                                                                
        case 'Q':                                                               Line 1951
          set_quoting_style (NULL, c_quoting_style);                            Line 1952
          break;                                                                Line 1953
                                                                                
        case 'R':                                                               Line 1955
          recursive = true;                                                     Line 1956
          break;                                                                Line 1957
                                                                                
        case 'S':                                                               Line 1959
          sort_type = sort_size;                                                Line 1960
          sort_type_specified = true;                                           Line 1961
          break;                                                                Line 1962
                                                                                
        case 'T':                                                               Line 1964
          tabsize = xnumtoumax (optarg, 0, 0, SIZE_MAX, "",                     Line 1965
                                _("invalid tab size"), LS_FAILURE);             Line 1966
          break;                                                                Line 1967
                                                                                
        case 'U':                                                               Line 1969
          sort_type = sort_none;                                                Line 1970
          sort_type_specified = true;                                           Line 1971
          break;                                                                Line 1972
                                                                                
        case 'X':                                                               Line 1974
          sort_type = sort_extension;                                           Line 1975
          sort_type_specified = true;                                           Line 1976
          break;                                                                Line 1977
                                                                                
        case '1':                                                               Line 1979
          /* -1 has no effect after -l.  */                                     
          if (format != long_format)                                            Line 1981
            format = one_per_line;                                              Line 1982
          break;                                                                Line 1983
                                                                                
        case AUTHOR_OPTION:                                                     Line 1985
          print_author = true;                                                  Line 1986
          break;                                                                Line 1987
                                                                                
        case HIDE_OPTION:                                                       Line 1989
          {                                                                     
            struct ignore_pattern *hide = xmalloc (sizeof *hide);               Line 1991
            hide->pattern = optarg;                                             Line 1992
            hide->next = hide_patterns;                                         Line 1993
            hide_patterns = hide;                                               Line 1994
          }                                                                     
          break;                                                                Line 1996
                                                                                
        case SORT_OPTION:                                                       Line 1998
          sort_type = XARGMATCH ("--sort", optarg, sort_args, sort_types);      Line 1999
          sort_type_specified = true;                                           Line 2000
          break;                                                                Line 2001
                                                                                
        case GROUP_DIRECTORIES_FIRST_OPTION:                                    Line 2003
          directories_first = true;                                             Line 2004
          break;                                                                Line 2005
                                                                                
        case TIME_OPTION:                                                       Line 2007
          time_type = XARGMATCH ("--time", optarg, time_args, time_types);      Line 2008
          break;                                                                Line 2009
                                                                                
        case FORMAT_OPTION:                                                     Line 2011
          format = XARGMATCH ("--format", optarg, format_args, format_types);   Line 2012
          break;                                                                Line 2013
                                                                                
        case FULL_TIME_OPTION:                                                  Line 2015
          format = long_format;                                                 Line 2016
          time_style_option = bad_cast ("full-iso");                            Line 2017
          break;                                                                Line 2018
                                                                                
        case COLOR_OPTION:                                                      Line 2020
          {                                                                     
            int i;                                                              Line 2022
            if (optarg)                                                         Line 2023
              i = XARGMATCH ("--color", optarg, when_args, when_types);         Line 2024
            else                                                                Line 2025
              /* Using --color with no argument is equivalent to using          
                 --color=always.  */                                            
              i = when_always;                                                  Line 2028
                                                                                
            print_with_color = (i == when_always                                Line 2030
                                || (i == when_if_tty                            Line 2031
                                    && isatty (STDOUT_FILENO)));                Line 2032
                                                                                
            if (print_with_color)                                               Line 2034
              {                                                                 
                /* Don't use TAB characters in output.  Some terminal           
                   emulators can't handle the combination of tabs and           
                   color codes on the same line.  */                            
                tabsize = 0;                                                    Line 2039
              }                                                                 
            break;                                                              Line 2041
          }                                                                     
                                                                                
        case HYPERLINK_OPTION:                                                  Line 2044
          {                                                                     
            int i;                                                              Line 2046
            if (optarg)                                                         Line 2047
              i = XARGMATCH ("--hyperlink", optarg, when_args, when_types);     Line 2048
            else                                                                Line 2049
              /* Using --hyperlink with no argument is equivalent to using      
                 --hyperlink=always.  */                                        
              i = when_always;                                                  Line 2052
                                                                                
            print_hyperlink = (i == when_always                                 Line 2054
                               || (i == when_if_tty                             Line 2055
                                   && isatty (STDOUT_FILENO)));                 Line 2056
            break;                                                              Line 2057
          }                                                                     
                                                                                
        case INDICATOR_STYLE_OPTION:                                            Line 2060
          indicator_style = XARGMATCH ("--indicator-style", optarg,             Line 2061
                                       indicator_style_args,                    Line 2062
                                       indicator_style_types);                  Line 2063
          break;                                                                Line 2064
                                                                                
        case QUOTING_STYLE_OPTION:                                              Line 2066
          set_quoting_style (NULL,                                              Line 2067
                             XARGMATCH ("--quoting-style", optarg,              Line 2068
                                        quoting_style_args,                     Line 2069
                                        quoting_style_vals));                   Line 2070
          break;                                                                Line 2071
                                                                                
        case TIME_STYLE_OPTION:                                                 Line 2073
          time_style_option = optarg;                                           Line 2074
          break;                                                                Line 2075
                                                                                
        case SHOW_CONTROL_CHARS_OPTION:                                         Line 2077
          qmark_funny_chars = false;                                            Line 2078
          break;                                                                Line 2079
                                                                                
        case BLOCK_SIZE_OPTION:                                                 Line 2081
          {                                                                     
            enum strtol_error e = human_options (optarg, &human_output_opts,    Line 2083
                                                 &output_block_size);           Line 2084
            if (e != LONGINT_OK)                                                Line 2085
              xstrtol_fatal (e, oi, 0, long_options, optarg);                   Line 2086
            file_human_output_opts = human_output_opts;                         Line 2087
            file_output_block_size = output_block_size;                         Line 2088
          }                                                                     
          break;                                                                Line 2090
                                                                                
        case SI_OPTION:                                                         Line 2092
          file_human_output_opts = human_output_opts =                          Line 2093
            human_autoscale | human_SI;                                         Line 2094
          file_output_block_size = output_block_size = 1;                       Line 2095
          break;                                                                Line 2096
                                                                                
        case 'Z':                                                               Line 2098
          print_scontext = true;                                                Line 2099
          break;                                                                Line 2100
                                                                                
        case_GETOPT_HELP_CHAR;                                                  Line 2102
                                                                                
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 2104
                                                                                
        default:                                                                Line 2106
          usage (LS_FAILURE);                                                   Line 2107
        }                                                                       
    }                                                                           
                                                                                
  if (! output_block_size)                                                      Line 2111
    {                                                                           
      char const *ls_block_size = getenv ("LS_BLOCK_SIZE");                     Line 2113
      human_options (ls_block_size,                                             Line 2114
                     &human_output_opts, &output_block_size);                   Line 2115
      if (ls_block_size || getenv ("BLOCK_SIZE"))                               Line 2116
        {                                                                       
          file_human_output_opts = human_output_opts;                           Line 2118
          file_output_block_size = output_block_size;                           Line 2119
        }                                                                       
      if (kibibytes_specified)                                                  Line 2121
        {                                                                       
          human_output_opts = 0;                                                Line 2123
          output_block_size = 1024;                                             Line 2124
        }                                                                       
    }                                                                           
                                                                                
  /* Determine the max possible number of display columns.  */                  
  max_idx = line_length / MIN_COLUMN_WIDTH;                                     Line 2129
  /* Account for first display column not having a separator,                   
     or line_lengths shorter than MIN_COLUMN_WIDTH.  */                         
  max_idx += line_length % MIN_COLUMN_WIDTH != 0;                               Line 2132
                                                                                
  enum quoting_style qs = get_quoting_style (NULL);                             Line 2134
  align_variable_outer_quotes = format != with_commas                           Line 2135
                                && format != one_per_line                       Line 2136
                                && (line_length || format == long_format)       Line 2137
                                && (qs == shell_quoting_style                   Line 2138
                                    || qs == shell_escape_quoting_style         Line 2139
                                    || qs == c_maybe_quoting_style);            Line 2140
  filename_quoting_options = clone_quoting_options (NULL);                      Line 2141
  if (qs == escape_quoting_style)                                               Line 2142
    set_char_quoting (filename_quoting_options, ' ', 1);                        Line 2143
  if (file_type <= indicator_style)                                             Line 2144
    {                                                                           
      char const *p;                                                            Line 2146
      for (p = &"*=>@|"[indicator_style - file_type]; *p; p++)                  Line 2147
        set_char_quoting (filename_quoting_options, *p, 1);                     Line 2148
    }                                                                           
                                                                                
  dirname_quoting_options = clone_quoting_options (NULL);                       Line 2151
  set_char_quoting (dirname_quoting_options, ':', 1);                           Line 2152
                                                                                
  /* --dired is meaningful only with --format=long (-l).                        
     Otherwise, ignore it.  FIXME: warn about this?                             
     Alternatively, make --dired imply --format=long?  */                       
  if (dired && (format != long_format || print_hyperlink))                      Line 2157
    dired = false;                                                              Line 2158
                                                                                
  /* If -c or -u is specified and not -l (or any other option that implies -l), 
     and no sort-type was specified, then sort by the ctime (-c) or atime (-u). 
     The behavior of ls when using either -c or -u but with neither -l nor -t   
     appears to be unspecified by POSIX.  So, with GNU ls, '-u' alone means     
     sort by atime (this is the one that's not specified by the POSIX spec),    
     -lu means show atime and sort by name, -lut means show atime and sort      
     by atime.  */                                                              
                                                                                
  if ((time_type == time_ctime || time_type == time_atime)                      Line 2168
      && !sort_type_specified && format != long_format)                         Line 2169
    {                                                                           
      sort_type = sort_time;                                                    Line 2171
    }                                                                           
                                                                                
  if (format == long_format)                                                    Line 2174
    {                                                                           
      char *style = time_style_option;                                          Line 2176
      static char const posix_prefix[] = "posix-";                              Line 2177
                                                                                
      if (! style)                                                              Line 2179
        if (! (style = getenv ("TIME_STYLE")))                                  Line 2180
          style = bad_cast ("locale");                                          Line 2181
                                                                                
      while (STREQ_LEN (style, posix_prefix, sizeof posix_prefix - 1))          Line 2183
        {                                                                       
          if (! hard_locale (LC_TIME))                                          Line 2185
            return optind;                                                      Line 2186
          style += sizeof posix_prefix - 1;                                     Line 2187
        }                                                                       
                                                                                
      if (*style == '+')                                                        Line 2190
        {                                                                       
          char *p0 = style + 1;                                                 Line 2192
          char *p1 = strchr (p0, '\n');                                         Line 2193
          if (! p1)                                                             Line 2194
            p1 = p0;                                                            Line 2195
          else                                                                  Line 2196
            {                                                                   
              if (strchr (p1 + 1, '\n'))                                        Line 2198
                die (LS_FAILURE, 0, _("invalid time style format %s"),          Line 2199
                     quote (p0));                                               Line 2200
              *p1++ = '\0';                                                     Line 2201
            }                                                                   
          long_time_format[0] = p0;                                             Line 2203
          long_time_format[1] = p1;                                             Line 2204
        }                                                                       
      else                                                                      Line 2206
        {                                                                       
          ptrdiff_t res = argmatch (style, time_style_args,                     Line 2208
                                    (char const *) time_style_types,            Line 2209
                                    sizeof (*time_style_types));                Line 2210
          if (res < 0)                                                          Line 2211
            {                                                                   
              /* This whole block used to be a simple use of XARGMATCH.         
                 but that didn't print the "posix-"-prefixed variants or        
                 the "+"-prefixed format string option upon failure.  */        
              argmatch_invalid ("time style", style, res);                      Line 2216
                                                                                
              /* The following is a manual expansion of argmatch_valid,         
                 but with the added "+ ..." description and the [posix-]        
                 prefixes prepended.  Note that this simplification works       
                 only because all four existing time_style_types values         
                 are distinct.  */                                              
              fputs (_("Valid arguments are:\n"), stderr);                      Line 2223
              char const *const *p = time_style_args;                           Line 2224
              while (*p)                                                        Line 2225
                fprintf (stderr, "  - [posix-]%s\n", *p++);                     Line 2226
              fputs (_("  - +FORMAT (e.g., +%H:%M) for a 'date'-style"          Line 2227
                       " format\n"), stderr);                                   Line 2228
              usage (LS_FAILURE);                                               Line 2229
            }                                                                   
          switch (res)                                                          Line 2231
            {                                                                   
            case full_iso_time_style:                                           Line 2233
              long_time_format[0] = long_time_format[1] =                       Line 2234
                "%Y-%m-%d %H:%M:%S.%N %z";                                      Line 2235
              break;                                                            Line 2236
                                                                                
            case long_iso_time_style:                                           Line 2238
              long_time_format[0] = long_time_format[1] = "%Y-%m-%d %H:%M";     Line 2239
              break;                                                            Line 2240
                                                                                
            case iso_time_style:                                                Line 2242
              long_time_format[0] = "%Y-%m-%d ";                                Line 2243
              long_time_format[1] = "%m-%d %H:%M";                              Line 2244
              break;                                                            Line 2245
                                                                                
            case locale_time_style:                                             Line 2247
              if (hard_locale (LC_TIME))                                        Line 2248
                {                                                               
                  for (int i = 0; i < 2; i++)                                   Line 2250
                    long_time_format[i] =                                       Line 2251
                      dcgettext (NULL, long_time_format[i], LC_TIME);           Line 2252
                }                                                               
            }                                                                   
        }                                                                       
                                                                                
      abformat_init ();                                                         Line 2257
    }                                                                           
                                                                                
  return optind;                                                                Line 2260
}                                                                               Block 68
                                                                                
/* Parse a string as part of the LS_COLORS variable; this may involve           
   decoding all kinds of escape characters.  If equals_end is set an            
   unescaped equal sign ends the string, otherwise only a : or \0               
   does.  Set *OUTPUT_COUNT to the number of bytes output.  Return              
   true if successful.                                                          
                                                                                
   The resulting string is *not* null-terminated, but may contain               
   embedded nulls.                                                              
                                                                                
   Note that both dest and src are char **; on return they point to             
   the first free byte after the array and the character that ended             
   the input string, respectively.  */                                          
                                                                                
static bool                                                                     Line 2276
get_funky_string (char **dest, const char **src, bool equals_end,               Line 2277
                  size_t *output_count)                                         Line 2278
{                                                                               
  char num;   /* For numerical codes */                                         Line 2280
  size_t count;   /* Something to count with */                                 Line 2281
  enum {                                                                        Line 2282
    ST_GND, ST_BACKSLASH, ST_OCTAL, ST_HEX, ST_CARET, ST_END, ST_ERROR          Line 2283
  } state;                                                                      Line 2284
  const char *p;                                                                Line 2285
  char *q;                                                                      Line 2286
                                                                                
  p = *src;   /* We don't want to double-indirect */                            Line 2288
  q = *dest;   /* the whole darn time.  */                                      Line 2289
                                                                                
  count = 0;   /* No characters counted in yet.  */                             Line 2291
  num = 0;                                                                      Line 2292
                                                                                
  state = ST_GND;  /* Start in ground state.  */                                Line 2294
  while (state < ST_END)                                                        Line 2295
    {                                                                           
      switch (state)                                                            Line 2297
        {                                                                       
        case ST_GND:  /* Ground state (no escapes) */                           Line 2299
          switch (*p)                                                           Line 2300
            {                                                                   
            case ':':                                                           Line 2302
            case '\0':                                                          Line 2303
              state = ST_END; /* End of string */                               Line 2304
              break;                                                            Line 2305
            case '\\':                                                          Line 2306
              state = ST_BACKSLASH; /* Backslash escape sequence */             Line 2307
              ++p;                                                              Line 2308
              break;                                                            Line 2309
            case '^':                                                           Line 2310
              state = ST_CARET; /* Caret escape */                              Line 2311
              ++p;                                                              Line 2312
              break;                                                            Line 2313
            case '=':                                                           Line 2314
              if (equals_end)                                                   Line 2315
                {                                                               
                  state = ST_END; /* End */                                     Line 2317
                  break;                                                        Line 2318
                }                                                               
              FALLTHROUGH;                                                      Line 2320
            default:                                                            Line 2321
              *(q++) = *(p++);                                                  Line 2322
              ++count;                                                          Line 2323
              break;                                                            Line 2324
            }                                                                   
          break;                                                                Line 2326
                                                                                
        case ST_BACKSLASH: /* Backslash escaped character */                    Line 2328
          switch (*p)                                                           Line 2329
            {                                                                   
            case '0':                                                           Line 2331
            case '1':                                                           Line 2332
            case '2':                                                           Line 2333
            case '3':                                                           Line 2334
            case '4':                                                           Line 2335
            case '5':                                                           Line 2336
            case '6':                                                           Line 2337
            case '7':                                                           Line 2338
              state = ST_OCTAL; /* Octal sequence */                            Line 2339
              num = *p - '0';                                                   Line 2340
              break;                                                            Line 2341
            case 'x':                                                           Line 2342
            case 'X':                                                           Line 2343
              state = ST_HEX; /* Hex sequence */                                Line 2344
              num = 0;                                                          Line 2345
              break;                                                            Line 2346
            case 'a':  /* Bell */                                               Line 2347
              num = '\a';                                                       Line 2348
              break;                                                            Line 2349
            case 'b':  /* Backspace */                                          Line 2350
              num = '\b';                                                       Line 2351
              break;                                                            Line 2352
            case 'e':  /* Escape */                                             Line 2353
              num = 27;                                                         Line 2354
              break;                                                            Line 2355
            case 'f':  /* Form feed */                                          Line 2356
              num = '\f';                                                       Line 2357
              break;                                                            Line 2358
            case 'n':  /* Newline */                                            Line 2359
              num = '\n';                                                       Line 2360
              break;                                                            Line 2361
            case 'r':  /* Carriage return */                                    Line 2362
              num = '\r';                                                       Line 2363
              break;                                                            Line 2364
            case 't':  /* Tab */                                                Line 2365
              num = '\t';                                                       Line 2366
              break;                                                            Line 2367
            case 'v':  /* Vtab */                                               Line 2368
              num = '\v';                                                       Line 2369
              break;                                                            Line 2370
            case '?':  /* Delete */                                             Line 2371
              num = 127;                                                        Line 2372
              break;                                                            Line 2373
            case '_':  /* Space */                                              Line 2374
              num = ' ';                                                        Line 2375
              break;                                                            Line 2376
            case '\0':  /* End of string */                                     Line 2377
              state = ST_ERROR; /* Error! */                                    Line 2378
              break;                                                            Line 2379
            default:  /* Escaped character like \ ^ : = */                      Line 2380
              num = *p;                                                         Line 2381
              break;                                                            Line 2382
            }                                                                   
          if (state == ST_BACKSLASH)                                            Line 2384
            {                                                                   
              *(q++) = num;                                                     Line 2386
              ++count;                                                          Line 2387
              state = ST_GND;                                                   Line 2388
            }                                                                   
          ++p;                                                                  Line 2390
          break;                                                                Line 2391
                                                                                
        case ST_OCTAL:  /* Octal sequence */                                    Line 2393
          if (*p < '0' || *p > '7')                                             Line 2394
            {                                                                   
              *(q++) = num;                                                     Line 2396
              ++count;                                                          Line 2397
              state = ST_GND;                                                   Line 2398
            }                                                                   
          else                                                                  Line 2400
            num = (num << 3) + (*(p++) - '0');                                  Line 2401
          break;                                                                Line 2402
                                                                                
        case ST_HEX:  /* Hex sequence */                                        Line 2404
          switch (*p)                                                           Line 2405
            {                                                                   
            case '0':                                                           Line 2407
            case '1':                                                           Line 2408
            case '2':                                                           Line 2409
            case '3':                                                           Line 2410
            case '4':                                                           Line 2411
            case '5':                                                           Line 2412
            case '6':                                                           Line 2413
            case '7':                                                           Line 2414
            case '8':                                                           Line 2415
            case '9':                                                           Line 2416
              num = (num << 4) + (*(p++) - '0');                                Line 2417
              break;                                                            Line 2418
            case 'a':                                                           Line 2419
            case 'b':                                                           Line 2420
            case 'c':                                                           Line 2421
            case 'd':                                                           Line 2422
            case 'e':                                                           Line 2423
            case 'f':                                                           Line 2424
              num = (num << 4) + (*(p++) - 'a') + 10;                           Line 2425
              break;                                                            Line 2426
            case 'A':                                                           Line 2427
            case 'B':                                                           Line 2428
            case 'C':                                                           Line 2429
            case 'D':                                                           Line 2430
            case 'E':                                                           Line 2431
            case 'F':                                                           Line 2432
              num = (num << 4) + (*(p++) - 'A') + 10;                           Line 2433
              break;                                                            Line 2434
            default:                                                            Line 2435
              *(q++) = num;                                                     Line 2436
              ++count;                                                          Line 2437
              state = ST_GND;                                                   Line 2438
              break;                                                            Line 2439
            }                                                                   
          break;                                                                Line 2441
                                                                                
        case ST_CARET:  /* Caret escape */                                      Line 2443
          state = ST_GND; /* Should be the next state... */                     Line 2444
          if (*p >= '@' && *p <= '~')                                           Line 2445
            {                                                                   
              *(q++) = *(p++) & 037;                                            Line 2447
              ++count;                                                          Line 2448
            }                                                                   
          else if (*p == '?')                                                   Line 2450
            {                                                                   
              *(q++) = 127;                                                     Line 2452
              ++count;                                                          Line 2453
            }                                                                   
          else                                                                  Line 2455
            state = ST_ERROR;                                                   Line 2456
          break;                                                                Line 2457
                                                                                
        default:                                                                Line 2459
          abort ();                                                             ...!common auto-comment...
        }                                                                       
    }                                                                           
                                                                                
  *dest = q;                                                                    Line 2464
  *src = p;                                                                     Line 2465
  *output_count = count;                                                        Line 2466
                                                                                
  return state != ST_ERROR;                                                     Line 2468
}                                                                               Block 69
                                                                                
enum parse_state                                                                Line 2471
  {                                                                             
    PS_START = 1,                                                               Line 2473
    PS_2,                                                                       Line 2474
    PS_3,                                                                       Line 2475
    PS_4,                                                                       Line 2476
    PS_DONE,                                                                    Line 2477
    PS_FAIL                                                                     Line 2478
  };                                                                            Block 70
                                                                                
                                                                                
/* Check if the content of TERM is a valid name in dircolors.  */               
                                                                                
static bool                                                                     Line 2484
known_term_type (void)                                                          Line 2485
{                                                                               
  char const *term = getenv ("TERM");                                           Line 2487
  if (! term || ! *term)                                                        Line 2488
    return false;                                                               Line 2489
                                                                                
  char const *line = G_line;                                                    Line 2491
  while (line - G_line < sizeof (G_line))                                       Line 2492
    {                                                                           
      if (STRNCMP_LIT (line, "TERM ") == 0)                                     Line 2494
        {                                                                       
          if (fnmatch (line + 5, term, 0) == 0)                                 Line 2496
            return true;                                                        Line 2497
        }                                                                       
      line += strlen (line) + 1;                                                Line 2499
    }                                                                           
                                                                                
  return false;                                                                 Line 2502
}                                                                               Block 71
                                                                                
static void                                                                     Line 2505
parse_ls_color (void)                                                           Line 2506
{                                                                               
  const char *p;  /* Pointer to character being parsed */                       Line 2508
  char *buf;   /* color_buf buffer pointer */                                   Line 2509
  int ind_no;   /* Indicator number */                                          Line 2510
  char label[3];  /* Indicator label */                                         Line 2511
  struct color_ext_type *ext; /* Extension we are working on */                 Line 2512
                                                                                
  if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')                         Line 2514
    {                                                                           
      /* LS_COLORS takes precedence, but if that's not set then                 
         honor the COLORTERM and TERM env variables so that                     
         we only go with the internal ANSI color codes if the                   
         former is non empty or the latter is set to a known value.  */         
      char const *colorterm = getenv ("COLORTERM");                             Line 2520
      if (! (colorterm && *colorterm) && ! known_term_type ())                  Line 2521
        print_with_color = false;                                               Line 2522
      return;                                                                   Line 2523
    }                                                                           
                                                                                
  ext = NULL;                                                                   Line 2526
  strcpy (label, "??");                                                         Line 2527
                                                                                
  /* This is an overly conservative estimate, but any possible                  
     LS_COLORS string will *not* generate a color_buf longer than               
     itself, so it is a safe way of allocating a buffer in                      
     advance.  */                                                               
  buf = color_buf = xstrdup (p);                                                Line 2533
                                                                                
  enum parse_state state = PS_START;                                            Line 2535
  while (true)                                                                  Line 2536
    {                                                                           
      switch (state)                                                            Line 2538
        {                                                                       
        case PS_START:  /* First label character */                             Line 2540
          switch (*p)                                                           Line 2541
            {                                                                   
            case ':':                                                           Line 2543
              ++p;                                                              Line 2544
              break;                                                            Line 2545
                                                                                
            case '*':                                                           Line 2547
              /* Allocate new extension block and add to head of                
                 linked list (this way a later definition will                  
                 override an earlier one, which can be useful for               
                 having terminal-specific defs override global).  */            
                                                                                
              ext = xmalloc (sizeof *ext);                                      Line 2553
              ext->next = color_ext_list;                                       Line 2554
              color_ext_list = ext;                                             Line 2555
                                                                                
              ++p;                                                              Line 2557
              ext->ext.string = buf;                                            Line 2558
                                                                                
              state = (get_funky_string (&buf, &p, true, &ext->ext.len)         Line 2560
                       ? PS_4 : PS_FAIL);                                       Line 2561
              break;                                                            Line 2562
                                                                                
            case '\0':                                                          Line 2564
              state = PS_DONE; /* Done! */                                      Line 2565
              goto done;                                                        Line 2566
                                                                                
            default: /* Assume it is file type label */                         Line 2568
              label[0] = *(p++);                                                Line 2569
              state = PS_2;                                                     Line 2570
              break;                                                            Line 2571
            }                                                                   
          break;                                                                Line 2573
                                                                                
        case PS_2:  /* Second label character */                                Line 2575
          if (*p)                                                               Line 2576
            {                                                                   
              label[1] = *(p++);                                                Line 2578
              state = PS_3;                                                     Line 2579
            }                                                                   
          else                                                                  Line 2581
            state = PS_FAIL; /* Error */                                        Line 2582
          break;                                                                Line 2583
                                                                                
        case PS_3:  /* Equal sign after indicator label */                      Line 2585
          state = PS_FAIL; /* Assume failure...  */                             Line 2586
          if (*(p++) == '=')/* It *should* be...  */                            Line 2587
            {                                                                   
              for (ind_no = 0; indicator_name[ind_no] != NULL; ++ind_no)        Line 2589
                {                                                               
                  if (STREQ (label, indicator_name[ind_no]))                    Line 2591
                    {                                                           
                      color_indicator[ind_no].string = buf;                     Line 2593
                      state = (get_funky_string (&buf, &p, false,               Line 2594
                                                 &color_indicator[ind_no].len)  Line 2595
                               ? PS_START : PS_FAIL);                           Line 2596
                      break;                                                    Line 2597
                    }                                                           
                }                                                               
              if (state == PS_FAIL)                                             Line 2600
                error (0, 0, _("unrecognized prefix: %s"), quote (label));      Line 2601
            }                                                                   
          break;                                                                Line 2603
                                                                                
        case PS_4:  /* Equal sign after *.ext */                                Line 2605
          if (*(p++) == '=')                                                    Line 2606
            {                                                                   
              ext->seq.string = buf;                                            Line 2608
              state = (get_funky_string (&buf, &p, false, &ext->seq.len)        Line 2609
                       ? PS_START : PS_FAIL);                                   Line 2610
            }                                                                   
          else                                                                  Line 2612
            state = PS_FAIL;                                                    Line 2613
          break;                                                                Line 2614
                                                                                
        case PS_FAIL:                                                           Line 2616
          goto done;                                                            Line 2617
                                                                                
        default:                                                                Line 2619
          abort ();                                                             ...!common auto-comment...
        }                                                                       
    }                                                                           
 done:                                                                          Line 2623
                                                                                
  if (state == PS_FAIL)                                                         Line 2625
    {                                                                           
      struct color_ext_type *e;                                                 Line 2627
      struct color_ext_type *e2;                                                Line 2628
                                                                                
      error (0, 0,                                                              Line 2630
             _("unparsable value for LS_COLORS environment variable"));         Line 2631
      free (color_buf);                                                         Line 2632
      for (e = color_ext_list; e != NULL; /* empty */)                          Line 2633
        {                                                                       
          e2 = e;                                                               Line 2635
          e = e->next;                                                          Line 2636
          free (e2);                                                            Line 2637
        }                                                                       
      print_with_color = false;                                                 Line 2639
    }                                                                           
                                                                                
  if (color_indicator[C_LINK].len == 6                                          Line 2642
      && !STRNCMP_LIT (color_indicator[C_LINK].string, "target"))               Line 2643
    color_symlink_as_referent = true;                                           Line 2644
}                                                                               Block 72
                                                                                
/* Set the quoting style default if the environment variable                    
   QUOTING_STYLE is set.  */                                                    
                                                                                
static void                                                                     Line 2650
getenv_quoting_style (void)                                                     Line 2651
{                                                                               
  char const *q_style = getenv ("QUOTING_STYLE");                               Line 2653
  if (q_style)                                                                  Line 2654
    {                                                                           
      int i = ARGMATCH (q_style, quoting_style_args, quoting_style_vals);       Line 2656
      if (0 <= i)                                                               Line 2657
        set_quoting_style (NULL, quoting_style_vals[i]);                        Line 2658
      else                                                                      Line 2659
        error (0, 0,                                                            Line 2660
       _("ignoring invalid value of environment variable QUOTING_STYLE: %s"),   Line 2661
               quote (q_style));                                                Line 2662
    }                                                                           
}                                                                               Block 73
                                                                                
/* Set the exit status to report a failure.  If SERIOUS, it is a                
   serious failure; otherwise, it is merely a minor problem.  */                
                                                                                
static void                                                                     Line 2669
set_exit_status (bool serious)                                                  Line 2670
{                                                                               
  if (serious)                                                                  Line 2672
    exit_status = LS_FAILURE;                                                   Line 2673
  else if (exit_status == EXIT_SUCCESS)                                         Line 2674
    exit_status = LS_MINOR_PROBLEM;                                             Line 2675
}                                                                               Block 74
                                                                                
/* Assuming a failure is serious if SERIOUS, use the printf-style               
   MESSAGE to report the failure to access a file named FILE.  Assume           
   errno is set appropriately for the failure.  */                              
                                                                                
static void                                                                     Line 2682
file_failure (bool serious, char const *message, char const *file)              Line 2683
{                                                                               
  error (0, errno, message, quoteaf (file));                                    Line 2685
  set_exit_status (serious);                                                    Line 2686
}                                                                               Block 75
                                                                                
/* Request that the directory named NAME have its contents listed later.        
   If REALNAME is nonzero, it will be used instead of NAME when the             
   directory name is printed.  This allows symbolic links to directories        
   to be treated as regular directories but still be listed under their         
   real names.  NAME == NULL is used to insert a marker entry for the           
   directory named in REALNAME.                                                 
   If NAME is non-NULL, we use its dev/ino information to save                  
   a call to stat -- when doing a recursive (-R) traversal.                     
   COMMAND_LINE_ARG means this directory was mentioned on the command line.  */ 
                                                                                
static void                                                                     Line 2699
queue_directory (char const *name, char const *realname, bool command_line_arg) Line 2700
{                                                                               
  struct pending *new = xmalloc (sizeof *new);                                  Line 2702
  new->realname = realname ? xstrdup (realname) : NULL;                         Line 2703
  new->name = name ? xstrdup (name) : NULL;                                     Line 2704
  new->command_line_arg = command_line_arg;                                     Line 2705
  new->next = pending_dirs;                                                     Line 2706
  pending_dirs = new;                                                           Line 2707
}                                                                               Block 76
                                                                                
/* Read directory NAME, and list the files in it.                               
   If REALNAME is nonzero, print its name instead of NAME;                      
   this is used for symbolic links to directories.                              
   COMMAND_LINE_ARG means this directory was mentioned on the command line.  */ 
                                                                                
static void                                                                     Line 2715
print_dir (char const *name, char const *realname, bool command_line_arg)       Line 2716
{                                                                               
  DIR *dirp;                                                                    Line 2718
  struct dirent *next;                                                          Line 2719
  uintmax_t total_blocks = 0;                                                   Line 2720
  static bool first = true;                                                     Line 2721
                                                                                
  errno = 0;                                                                    Line 2723
  dirp = opendir (name);                                                        Line 2724
  if (!dirp)                                                                    Line 2725
    {                                                                           
      file_failure (command_line_arg, _("cannot open directory %s"), name);     Line 2727
      return;                                                                   Line 2728
    }                                                                           
                                                                                
  if (LOOP_DETECT)                                                              Line 2731
    {                                                                           
      struct stat dir_stat;                                                     Line 2733
      int fd = dirfd (dirp);                                                    Line 2734
                                                                                
      /* If dirfd failed, endure the overhead of using stat.  */                
      if ((0 <= fd                                                              Line 2737
           ? fstat (fd, &dir_stat)                                              Line 2738...!syscalls auto-comment......!syscalls auto-comment...
           : stat (name, &dir_stat)) < 0)                                       Line 2739...!syscalls auto-comment...
        {                                                                       
          file_failure (command_line_arg,                                       Line 2741
                        _("cannot determine device and inode of %s"), name);    Line 2742
          closedir (dirp);                                                      Line 2743
          return;                                                               Line 2744
        }                                                                       
                                                                                
      /* If we've already visited this dev/inode pair, warn that                
         we've found a loop, and do not process this directory.  */             
      if (visit_dir (dir_stat.st_dev, dir_stat.st_ino))                         Line 2749
        {                                                                       
          error (0, 0, _("%s: not listing already-listed directory"),           Line 2751
                 quotef (name));                                                Line 2752
          closedir (dirp);                                                      Line 2753
          set_exit_status (true);                                               Line 2754
          return;                                                               Line 2755
        }                                                                       
                                                                                
      dev_ino_push (dir_stat.st_dev, dir_stat.st_ino);                          Line 2758
    }                                                                           
                                                                                
  clear_files ();                                                               Line 2761
                                                                                
  if (recursive || print_dir_name)                                              Line 2763
    {                                                                           
      if (!first)                                                               Line 2765
        DIRED_PUTCHAR ('\n');                                                   Line 2766
      first = false;                                                            Line 2767
      DIRED_INDENT ();                                                          Line 2768
                                                                                
      char *absolute_name = NULL;                                               Line 2770
      if (print_hyperlink)                                                      Line 2771
        {                                                                       
          absolute_name = canonicalize_filename_mode (name, CAN_MISSING);       Line 2773
          if (! absolute_name)                                                  Line 2774
            file_failure (command_line_arg,                                     Line 2775
                          _("error canonicalizing %s"), name);                  Line 2776
        }                                                                       
      quote_name (realname ? realname : name, dirname_quoting_options, -1,      Line 2778
                  NULL, true, &subdired_obstack, absolute_name);                Line 2779
                                                                                
      free (absolute_name);                                                     Line 2781
                                                                                
      DIRED_FPUTS_LITERAL (":\n", stdout);                                      Line 2783
    }                                                                           
                                                                                
  /* Read the directory entries, and insert the subfiles into the 'cwd_file'    
     table.  */                                                                 
                                                                                
  while (1)                                                                     Line 2789
    {                                                                           
      /* Set errno to zero so we can distinguish between a readdir failure      
         and when readdir simply finds that there are no more entries.  */      
      errno = 0;                                                                Line 2793
      next = readdir (dirp);                                                    Line 2794
      if (next)                                                                 Line 2795
        {                                                                       
          if (! file_ignored (next->d_name))                                    Line 2797
            {                                                                   
              enum filetype type = unknown;                                     Line 2799
                                                                                
#if HAVE_STRUCT_DIRENT_D_TYPE                                                   Line 2801
              switch (next->d_type)                                             Line 2802
                {                                                               
                case DT_BLK:  type = blockdev;  break;                          Line 2804
                case DT_CHR:  type = chardev;  break;                           Line 2805
                case DT_DIR:  type = directory;  break;                         Line 2806
                case DT_FIFO: type = fifo;  break;                              Line 2807
                case DT_LNK:  type = symbolic_link; break;                      Line 2808
                case DT_REG:  type = normal;  break;                            Line 2809
                case DT_SOCK: type = sock;  break;                              Line 2810
# ifdef DT_WHT                                                                  Line 2811
                case DT_WHT:  type = whiteout;  break;                          Line 2812
# endif                                                                         Line 2813
                }                                                               
#endif                                                                          Line 2815
              total_blocks += gobble_file (next->d_name, type,                  Line 2816
                                           RELIABLE_D_INO (next),               Line 2817
                                           false, name);                        Line 2818
                                                                                
              /* In this narrow case, print out each name right away, so        
                 ls uses constant memory while processing the entries of        
                 this directory.  Useful when there are many (millions)         
                 of entries in a directory.  */                                 
              if (format == one_per_line && sort_type == sort_none              Line 2824
                      && !print_block_size && !recursive)                       Line 2825
                {                                                               
                  /* We must call sort_files in spite of                        
                     "sort_type == sort_none" for its initialization            
                     of the sorted_file vector.  */                             
                  sort_files ();                                                Line 2830
                  print_current_files ();                                       Line 2831
                  clear_files ();                                               Line 2832
                }                                                               
            }                                                                   
        }                                                                       
      else if (errno != 0)                                                      Line 2836
        {                                                                       
          file_failure (command_line_arg, _("reading directory %s"), name);     Line 2838
          if (errno != EOVERFLOW)                                               Line 2839
            break;                                                              Line 2840
        }                                                                       
      else                                                                      Line 2842
        break;                                                                  Line 2843
                                                                                
      /* When processing a very large directory, and since we've inhibited      
         interrupts, this loop would take so long that ls would be annoyingly   
         uninterruptible.  This ensures that it handles signals promptly.  */   
      process_signals ();                                                       Line 2848
    }                                                                           
                                                                                
  if (closedir (dirp) != 0)                                                     Line 2851
    {                                                                           
      file_failure (command_line_arg, _("closing directory %s"), name);         Line 2853
      /* Don't return; print whatever we got.  */                               
    }                                                                           
                                                                                
  /* Sort the directory contents.  */                                           
  sort_files ();                                                                Line 2858
                                                                                
  /* If any member files are subdirectories, perhaps they should have their     
     contents listed rather than being mentioned here as files.  */             
                                                                                
  if (recursive)                                                                Line 2863
    extract_dirs_from_files (name, false);                                      Line 2864
                                                                                
  if (format == long_format || print_block_size)                                Line 2866
    {                                                                           
      const char *p;                                                            Line 2868
      char buf[LONGEST_HUMAN_READABLE + 1];                                     Line 2869
                                                                                
      DIRED_INDENT ();                                                          Line 2871
      p = _("total");                                                           Line 2872
      DIRED_FPUTS (p, stdout, strlen (p));                                      Line 2873
      DIRED_PUTCHAR (' ');                                                      Line 2874
      p = human_readable (total_blocks, buf, human_output_opts,                 Line 2875
                          ST_NBLOCKSIZE, output_block_size);                    Line 2876
      DIRED_FPUTS (p, stdout, strlen (p));                                      Line 2877
      DIRED_PUTCHAR ('\n');                                                     Line 2878
    }                                                                           
                                                                                
  if (cwd_n_used)                                                               Line 2881
    print_current_files ();                                                     Line 2882
}                                                                               Block 77
                                                                                
/* Add 'pattern' to the list of patterns for which files that match are         
   not listed.  */                                                              
                                                                                
static void                                                                     Line 2888
add_ignore_pattern (const char *pattern)                                        Line 2889
{                                                                               
  struct ignore_pattern *ignore;                                                Line 2891
                                                                                
  ignore = xmalloc (sizeof *ignore);                                            Line 2893
  ignore->pattern = pattern;                                                    Line 2894
  /* Add it to the head of the linked list.  */                                 
  ignore->next = ignore_patterns;                                               Line 2896
  ignore_patterns = ignore;                                                     Line 2897
}                                                                               Block 78
                                                                                
/* Return true if one of the PATTERNS matches FILE.  */                         
                                                                                
static bool                                                                     Line 2902
patterns_match (struct ignore_pattern const *patterns, char const *file)        Line 2903
{                                                                               
  struct ignore_pattern const *p;                                               Line 2905
  for (p = patterns; p; p = p->next)                                            Line 2906
    if (fnmatch (p->pattern, file, FNM_PERIOD) == 0)                            Line 2907
      return true;                                                              Line 2908
  return false;                                                                 Line 2909
}                                                                               Block 79
                                                                                
/* Return true if FILE should be ignored.  */                                   
                                                                                
static bool                                                                     Line 2914
file_ignored (char const *name)                                                 Line 2915
{                                                                               
  return ((ignore_mode != IGNORE_MINIMAL                                        Line 2917
           && name[0] == '.'                                                    Line 2918
           && (ignore_mode == IGNORE_DEFAULT || ! name[1 + (name[1] == '.')]))  Line 2919
          || (ignore_mode == IGNORE_DEFAULT                                     Line 2920
              && patterns_match (hide_patterns, name))                          Line 2921
          || patterns_match (ignore_patterns, name));                           Line 2922
}                                                                               Block 80
                                                                                
/* POSIX requires that a file size be printed without a sign, even              
   when negative.  Assume the typical case where negative sizes are             
   actually positive values that have wrapped around.  */                       
                                                                                
static uintmax_t                                                                Line 2929
unsigned_file_size (off_t size)                                                 Line 2930
{                                                                               
  return size + (size < 0) * ((uintmax_t) OFF_T_MAX - OFF_T_MIN + 1);           Line 2932
}                                                                               Block 81
                                                                                
#ifdef HAVE_CAP                                                                 Line 2935
/* Return true if NAME has a capability (see linux/capability.h) */             
static bool                                                                     Line 2937
has_capability (char const *name)                                               Line 2938
{                                                                               
  char *result;                                                                 Line 2940
  bool has_cap;                                                                 Line 2941
                                                                                
  cap_t cap_d = cap_get_file (name);                                            Line 2943
  if (cap_d == NULL)                                                            Line 2944
    return false;                                                               Line 2945
                                                                                
  result = cap_to_text (cap_d, NULL);                                           Line 2947
  cap_free (cap_d);                                                             Line 2948
  if (!result)                                                                  Line 2949
    return false;                                                               Line 2950
                                                                                
  /* check if human-readable capability string is empty */                      
  has_cap = !!*result;                                                          Line 2953
                                                                                
  cap_free (result);                                                            Line 2955
  return has_cap;                                                               Line 2956
}                                                                               Block 82
#else                                                                           Line 2958
static bool                                                                     Line 2959
has_capability (char const *name _GL_UNUSED)                                    Line 2960
{                                                                               
  errno = ENOTSUP;                                                              Line 2962
  return false;                                                                 Line 2963
}                                                                               Block 83
#endif                                                                          Line 2965
                                                                                
/* Enter and remove entries in the table 'cwd_file'.  */                        
                                                                                
static void                                                                     Line 2969
free_ent (struct fileinfo *f)                                                   Line 2970
{                                                                               
  free (f->name);                                                               Line 2972
  free (f->linkname);                                                           Line 2973
  free (f->absolute_name);                                                      Line 2974
  if (f->scontext != UNKNOWN_SECURITY_CONTEXT)                                  Line 2975
    {                                                                           
      if (is_smack_enabled ())                                                  ...!common auto-comment...
        free (f->scontext);                                                     Line 2978
      else                                                                      Line 2979
        freecon (f->scontext);                                                  Line 2980
    }                                                                           
}                                                                               Block 84
                                                                                
/* Empty the table of files.  */                                                
static void                                                                     Line 2985
clear_files (void)                                                              Line 2986
{                                                                               
  for (size_t i = 0; i < cwd_n_used; i++)                                       Line 2988
    {                                                                           
      struct fileinfo *f = sorted_file[i];                                      Line 2990
      free_ent (f);                                                             Line 2991
    }                                                                           
                                                                                
  cwd_n_used = 0;                                                               Line 2994
  cwd_some_quoted = false;                                                      Line 2995
  any_has_acl = false;                                                          Line 2996
  inode_number_width = 0;                                                       Line 2997
  block_size_width = 0;                                                         Line 2998
  nlink_width = 0;                                                              Line 2999
  owner_width = 0;                                                              Line 3000
  group_width = 0;                                                              Line 3001
  author_width = 0;                                                             Line 3002
  scontext_width = 0;                                                           Line 3003
  major_device_number_width = 0;                                                Line 3004
  minor_device_number_width = 0;                                                Line 3005
  file_size_width = 0;                                                          Line 3006
}                                                                               Block 85
                                                                                
/* Return true if ERR implies lack-of-support failure by a                      
   getxattr-calling function like getfilecon or file_has_acl.  */               
static bool                                                                     Line 3011
errno_unsupported (int err)                                                     Line 3012
{                                                                               
  return (err == EINVAL || err == ENOSYS || is_ENOTSUP (err));                  Line 3014
}                                                                               Block 86
                                                                                
/* Cache *getfilecon failure, when it's trivial to do so.                       
   Like getfilecon/lgetfilecon, but when F's st_dev says it's doesn't           
   support getting the security context, fail with ENOTSUP immediately.  */     
static int                                                                      Line 3020
getfilecon_cache (char const *file, struct fileinfo *f, bool deref)             Line 3021
{                                                                               
  /* st_dev of the most recently processed device for which we've               
     found that [l]getfilecon fails indicating lack of support.  */             
  static dev_t unsupported_device;                                              Line 3025
                                                                                
  if (f->stat.st_dev == unsupported_device)                                     Line 3027
    {                                                                           
      errno = ENOTSUP;                                                          Line 3029
      return -1;                                                                Line 3030
    }                                                                           
  int r = 0;                                                                    Line 3032
#ifdef HAVE_SMACK                                                               Line 3033
  if (is_smack_enabled ())                                                      ...!common auto-comment...
    r = smack_new_label_from_path (file, "security.SMACK64", deref,             Line 3035
                                   &f->scontext);                               Line 3036
  else                                                                          Line 3037
#endif                                                                          Line 3038
    r = (deref                                                                  Line 3039
         ? getfilecon (file, &f->scontext)                                      Line 3040
         : lgetfilecon (file, &f->scontext));                                   Line 3041
  if (r < 0 && errno_unsupported (errno))                                       Line 3042
    unsupported_device = f->stat.st_dev;                                        Line 3043
  return r;                                                                     Line 3044
}                                                                               
                                                                                
/* Cache file_has_acl failure, when it's trivial to do.                         
   Like file_has_acl, but when F's st_dev says it's on a file                   
   system lacking ACL support, return 0 with ENOTSUP immediately.  */           
static int                                                                      Line 3050
file_has_acl_cache (char const *file, struct fileinfo *f)                       Line 3051
{                                                                               
  /* st_dev of the most recently processed device for which we've               
     found that file_has_acl fails indicating lack of support.  */              
  static dev_t unsupported_device;                                              Line 3055
                                                                                
  if (f->stat.st_dev == unsupported_device)                                     Line 3057
    {                                                                           
      errno = ENOTSUP;                                                          Line 3059
      return 0;                                                                 Line 3060
    }                                                                           
                                                                                
  /* Zero errno so that we can distinguish between two 0-returning cases:       
     "has-ACL-support, but only a default ACL" and "no ACL support". */         
  errno = 0;                                                                    Line 3065
  int n = file_has_acl (file, &f->stat);                                        Line 3066
  if (n <= 0 && errno_unsupported (errno))                                      Line 3067
    unsupported_device = f->stat.st_dev;                                        Line 3068
  return n;                                                                     Line 3069
}                                                                               
                                                                                
/* Cache has_capability failure, when it's trivial to do.                       
   Like has_capability, but when F's st_dev says it's on a file                 
   system lacking capability support, return 0 with ENOTSUP immediately.  */    
static bool                                                                     Line 3075
has_capability_cache (char const *file, struct fileinfo *f)                     Line 3076
{                                                                               
  /* st_dev of the most recently processed device for which we've               
     found that has_capability fails indicating lack of support.  */            
  static dev_t unsupported_device;                                              Line 3080
                                                                                
  if (f->stat.st_dev == unsupported_device)                                     Line 3082
    {                                                                           
      errno = ENOTSUP;                                                          Line 3084
      return 0;                                                                 Line 3085
    }                                                                           
                                                                                
  bool b = has_capability (file);                                               Line 3088
  if ( !b && errno_unsupported (errno))                                         Line 3089
    unsupported_device = f->stat.st_dev;                                        Line 3090
  return b;                                                                     Line 3091
}                                                                               
                                                                                
static bool                                                                     Line 3094
needs_quoting (char const* name)                                                Line 3095
{                                                                               
  char test[2];                                                                 Line 3097
  size_t len = quotearg_buffer (test, sizeof test , name, -1,                   Line 3098
                                filename_quoting_options);                      Line 3099
  return *name != *test || strlen (name) != len;                                Line 3100
}                                                                               Block 90
                                                                                
/* Add a file to the current table of files.                                    
   Verify that the file exists, and print an error message if it does not.      
   Return the number of blocks that the file occupies.  */                      
static uintmax_t                                                                Line 3106
gobble_file (char const *name, enum filetype type, ino_t inode,                 Line 3107
             bool command_line_arg, char const *dirname)                        Line 3108
{                                                                               
  uintmax_t blocks = 0;                                                         Line 3110
  struct fileinfo *f;                                                           Line 3111
                                                                                
  /* An inode value prior to gobble_file necessarily came from readdir,         
     which is not used for command line arguments.  */                          
  assert (! command_line_arg || inode == NOT_AN_INODE_NUMBER);                  Line 3115
                                                                                
  if (cwd_n_used == cwd_n_alloc)                                                Line 3117
    {                                                                           
      cwd_file = xnrealloc (cwd_file, cwd_n_alloc, 2 * sizeof *cwd_file);       Line 3119
      cwd_n_alloc *= 2;                                                         Line 3120
    }                                                                           
                                                                                
  f = &cwd_file[cwd_n_used];                                                    Line 3123
  memset (f, '\0', sizeof *f);                                                  Line 3124
  f->stat.st_ino = inode;                                                       Line 3125
  f->filetype = type;                                                           Line 3126
                                                                                
  f->quoted = -1;                                                               Line 3128
  if ((! cwd_some_quoted) && align_variable_outer_quotes)                       Line 3129
    {                                                                           
      /* Determine if any quoted for padding purposes.  */                      
      f->quoted = needs_quoting (name);                                         Line 3132
      if (f->quoted)                                                            Line 3133
        cwd_some_quoted = 1;                                                    Line 3134
    }                                                                           
                                                                                
  if (command_line_arg                                                          Line 3137
      || print_hyperlink                                                        Line 3138
      || format_needs_stat                                                      Line 3139
      /* When coloring a directory (we may know the type from                   
         direct.d_type), we have to stat it in order to indicate                
         sticky and/or other-writable attributes.  */                           
      || (type == directory && print_with_color                                 Line 3143
          && (is_colored (C_OTHER_WRITABLE)                                     Line 3144
              || is_colored (C_STICKY)                                          Line 3145
              || is_colored (C_STICKY_OTHER_WRITABLE)))                         Line 3146
      /* When dereferencing symlinks, the inode and type must come from         
         stat, but readdir provides the inode and type of lstat.  */            
      || ((print_inode || format_needs_type)                                    Line 3149
          && (type == symbolic_link || type == unknown)                         Line 3150
          && (dereference == DEREF_ALWAYS                                       Line 3151
              || color_symlink_as_referent || check_symlink_color))             Line 3152
      /* Command line dereferences are already taken care of by the above       
         assertion that the inode number is not yet known.  */                  
      || (print_inode && inode == NOT_AN_INODE_NUMBER)                          Line 3155
      || (format_needs_type                                                     Line 3156
          && (type == unknown || command_line_arg                               Line 3157
              /* --indicator-style=classify (aka -F)                            
                 requires that we stat each regular file                        
                 to see if it's executable.  */                                 
              || (type == normal && (indicator_style == classify                Line 3161
                                     /* This is so that --color ends up         
                                        highlighting files with these mode      
                                        bits set even when options like -F are  
                                        not specified.  Note we do a redundant  
                                        stat in the very unlikely case where    
                                        C_CAP is set but not the others. */     
                                     || (print_with_color                       Line 3168
                                         && (is_colored (C_EXEC)                Line 3169
                                             || is_colored (C_SETUID)           Line 3170
                                             || is_colored (C_SETGID)           Line 3171
                                             || is_colored (C_CAP)))            Line 3172
                                     )))))                                      Line 3173
                                                                                
    {                                                                           
      /* Absolute name of this file.  */                                        
      char *full_name;                                                          Line 3177
      bool do_deref;                                                            Line 3178
      int err;                                                                  Line 3179
                                                                                
      if (name[0] == '/' || dirname[0] == 0)                                    Line 3181
        full_name = (char *) name;                                              Line 3182
      else                                                                      Line 3183
        {                                                                       
          full_name = alloca (strlen (name) + strlen (dirname) + 2);            Line 3185
          attach (full_name, dirname, name);                                    Line 3186
        }                                                                       
                                                                                
      if (print_hyperlink)                                                      Line 3189
        {                                                                       
          f->absolute_name = canonicalize_filename_mode (full_name,             Line 3191
                                                         CAN_MISSING);          Line 3192
          if (! f->absolute_name)                                               Line 3193
            file_failure (command_line_arg,                                     Line 3194
                          _("error canonicalizing %s"), full_name);             Line 3195
        }                                                                       
                                                                                
      switch (dereference)                                                      Line 3198
        {                                                                       
        case DEREF_ALWAYS:                                                      Line 3200
          err = stat (full_name, &f->stat);                                     Line 3201...!syscalls auto-comment...
          do_deref = true;                                                      Line 3202
          break;                                                                Line 3203
                                                                                
        case DEREF_COMMAND_LINE_ARGUMENTS:                                      Line 3205
        case DEREF_COMMAND_LINE_SYMLINK_TO_DIR:                                 Line 3206
          if (command_line_arg)                                                 Line 3207
            {                                                                   
              bool need_lstat;                                                  Line 3209
              err = stat (full_name, &f->stat);                                 Line 3210...!syscalls auto-comment...
              do_deref = true;                                                  Line 3211
                                                                                
              if (dereference == DEREF_COMMAND_LINE_ARGUMENTS)                  Line 3213
                break;                                                          Line 3214
                                                                                
              need_lstat = (err < 0                                             Line 3216
                            ? errno == ENOENT                                   Line 3217
                            : ! S_ISDIR (f->stat.st_mode));                     Line 3218
              if (!need_lstat)                                                  Line 3219
                break;                                                          Line 3220
                                                                                
              /* stat failed because of ENOENT, maybe indicating a dangling     
                 symlink.  Or stat succeeded, FULL_NAME does not refer to a     
                 directory, and --dereference-command-line-symlink-to-dir is    
                 in effect.  Fall through so that we call lstat instead.  */    
            }                                                                   
          FALLTHROUGH;                                                          Line 3227
                                                                                
        default: /* DEREF_NEVER */                                              Line 3229
          err = lstat (full_name, &f->stat);                                    Line 3230...!syscalls auto-comment...
          do_deref = false;                                                     Line 3231
          break;                                                                Line 3232
        }                                                                       
                                                                                
      if (err != 0)                                                             Line 3235
        {                                                                       
          /* Failure to stat a command line argument leads to                   
             an exit status of 2.  For other files, stat failure                
             provokes an exit status of 1.  */                                  
          file_failure (command_line_arg,                                       Line 3240
                        _("cannot access %s"), full_name);                      Line 3241
          if (command_line_arg)                                                 Line 3242
            return 0;                                                           Line 3243
                                                                                
          f->name = xstrdup (name);                                             Line 3245
          cwd_n_used++;                                                         Line 3246
                                                                                
          return 0;                                                             Line 3248
        }                                                                       
                                                                                
      f->stat_ok = true;                                                        Line 3251
                                                                                
      /* Note has_capability() adds around 30% runtime to 'ls --color'  */      
      if ((type == normal || S_ISREG (f->stat.st_mode))                         Line 3254
          && print_with_color && is_colored (C_CAP))                            Line 3255
        f->has_capability = has_capability_cache (full_name, f);                Line 3256
                                                                                
      if (format == long_format || print_scontext)                              Line 3258
        {                                                                       
          bool have_scontext = false;                                           Line 3260
          bool have_acl = false;                                                Line 3261
          int attr_len = getfilecon_cache (full_name, f, do_deref);             Line 3262
          err = (attr_len < 0);                                                 Line 3263
                                                                                
          if (err == 0)                                                         Line 3265
            {                                                                   
              if (is_smack_enabled ())                                          ...!common auto-comment...
                have_scontext = ! STREQ ("_", f->scontext);                     Line 3268
              else                                                              Line 3269
                have_scontext = ! STREQ ("unlabeled", f->scontext);             Line 3270
            }                                                                   
          else                                                                  Line 3272
            {                                                                   
              f->scontext = UNKNOWN_SECURITY_CONTEXT;                           Line 3274
                                                                                
              /* When requesting security context information, don't make       
                 ls fail just because the file (even a command line argument)   
                 isn't on the right type of file system.  I.e., a getfilecon    
                 failure isn't in the same class as a stat failure.  */         
              if (is_ENOTSUP (errno) || errno == ENODATA)                       Line 3280
                err = 0;                                                        Line 3281
            }                                                                   
                                                                                
          if (err == 0 && format == long_format)                                Line 3284
            {                                                                   
              int n = file_has_acl_cache (full_name, f);                        Line 3286
              err = (n < 0);                                                    Line 3287
              have_acl = (0 < n);                                               Line 3288
            }                                                                   
                                                                                
          f->acl_type = (!have_scontext && !have_acl                            Line 3291
                         ? ACL_T_NONE                                           Line 3292
                         : (have_scontext && !have_acl                          Line 3293
                            ? ACL_T_LSM_CONTEXT_ONLY                            Line 3294
                            : ACL_T_YES));                                      Line 3295
          any_has_acl |= f->acl_type != ACL_T_NONE;                             Line 3296
                                                                                
          if (err)                                                              Line 3298
            error (0, errno, "%s", quotef (full_name));                         Line 3299
        }                                                                       
                                                                                
      if (S_ISLNK (f->stat.st_mode)                                             Line 3302
          && (format == long_format || check_symlink_color))                    Line 3303
        {                                                                       
          struct stat linkstats;                                                Line 3305
                                                                                
          get_link_name (full_name, f, command_line_arg);                       Line 3307
          char *linkname = make_link_name (full_name, f->linkname);             Line 3308
                                                                                
          /* Use the slower quoting path for this entry, though                 
             don't update CWD_SOME_QUOTED since alignment not affected.  */     
          if (linkname && f->quoted == 0 && needs_quoting (f->linkname))        Line 3312
            f->quoted = -1;                                                     Line 3313
                                                                                
          /* Avoid following symbolic links when possible, ie, when             
             they won't be traced and when no indicator is needed.  */          
          if (linkname                                                          Line 3317
              && (file_type <= indicator_style || check_symlink_color)          Line 3318
              && stat (linkname, &linkstats) == 0)                              Line 3319...!syscalls auto-comment...
            {                                                                   
              f->linkok = true;                                                 Line 3321
                                                                                
              /* Symbolic links to directories that are mentioned on the        
                 command line are automatically traced if not being             
                 listed as files.  */                                           
              if (!command_line_arg || format == long_format                    Line 3326
                  || !S_ISDIR (linkstats.st_mode))                              Line 3327
                {                                                               
                  /* Get the linked-to file's mode for the filetype indicator   
                     in long listings.  */                                      
                  f->linkmode = linkstats.st_mode;                              Line 3331
                }                                                               
            }                                                                   
          free (linkname);                                                      Line 3334
        }                                                                       
                                                                                
      if (S_ISLNK (f->stat.st_mode))                                            Line 3337
        f->filetype = symbolic_link;                                            Line 3338
      else if (S_ISDIR (f->stat.st_mode))                                       Line 3339
        {                                                                       
          if (command_line_arg && !immediate_dirs)                              Line 3341
            f->filetype = arg_directory;                                        Line 3342
          else                                                                  Line 3343
            f->filetype = directory;                                            Line 3344
        }                                                                       
      else                                                                      Line 3346
        f->filetype = normal;                                                   Line 3347
                                                                                
      blocks = ST_NBLOCKS (f->stat);                                            Line 3349
      if (format == long_format || print_block_size)                            Line 3350
        {                                                                       
          char buf[LONGEST_HUMAN_READABLE + 1];                                 Line 3352
          int len = mbswidth (human_readable (blocks, buf, human_output_opts,   Line 3353
                                              ST_NBLOCKSIZE, output_block_size),Line 3354
                              0);                                               
          if (block_size_width < len)                                           Line 3356
            block_size_width = len;                                             Line 3357
        }                                                                       
                                                                                
      if (format == long_format)                                                Line 3360
        {                                                                       
          if (print_owner)                                                      Line 3362
            {                                                                   
              int len = format_user_width (f->stat.st_uid);                     Line 3364
              if (owner_width < len)                                            Line 3365
                owner_width = len;                                              Line 3366
            }                                                                   
                                                                                
          if (print_group)                                                      Line 3369
            {                                                                   
              int len = format_group_width (f->stat.st_gid);                    Line 3371
              if (group_width < len)                                            Line 3372
                group_width = len;                                              Line 3373
            }                                                                   
                                                                                
          if (print_author)                                                     Line 3376
            {                                                                   
              int len = format_user_width (f->stat.st_author);                  Line 3378
              if (author_width < len)                                           Line 3379
                author_width = len;                                             Line 3380
            }                                                                   
        }                                                                       
                                                                                
      if (print_scontext)                                                       Line 3384
        {                                                                       
          int len = strlen (f->scontext);                                       Line 3386
          if (scontext_width < len)                                             Line 3387
            scontext_width = len;                                               Line 3388
        }                                                                       
                                                                                
      if (format == long_format)                                                Line 3391
        {                                                                       
          char b[INT_BUFSIZE_BOUND (uintmax_t)];                                Line 3393
          int b_len = strlen (umaxtostr (f->stat.st_nlink, b));                 Line 3394
          if (nlink_width < b_len)                                              Line 3395
            nlink_width = b_len;                                                Line 3396
                                                                                
          if (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode))           Line 3398
            {                                                                   
              char buf[INT_BUFSIZE_BOUND (uintmax_t)];                          Line 3400
              int len = strlen (umaxtostr (major (f->stat.st_rdev), buf));      Line 3401
              if (major_device_number_width < len)                              Line 3402
                major_device_number_width = len;                                Line 3403
              len = strlen (umaxtostr (minor (f->stat.st_rdev), buf));          Line 3404
              if (minor_device_number_width < len)                              Line 3405
                minor_device_number_width = len;                                Line 3406
              len = major_device_number_width + 2 + minor_device_number_width;  Line 3407
              if (file_size_width < len)                                        Line 3408
                file_size_width = len;                                          Line 3409
            }                                                                   
          else                                                                  Line 3411
            {                                                                   
              char buf[LONGEST_HUMAN_READABLE + 1];                             Line 3413
              uintmax_t size = unsigned_file_size (f->stat.st_size);            Line 3414
              int len = mbswidth (human_readable (size, buf,                    Line 3415
                                                  file_human_output_opts,       Line 3416
                                                  1, file_output_block_size),   Line 3417
                                  0);                                           
              if (file_size_width < len)                                        Line 3419
                file_size_width = len;                                          Line 3420
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  if (print_inode)                                                              Line 3425
    {                                                                           
      char buf[INT_BUFSIZE_BOUND (uintmax_t)];                                  Line 3427
      int len = strlen (umaxtostr (f->stat.st_ino, buf));                       Line 3428
      if (inode_number_width < len)                                             Line 3429
        inode_number_width = len;                                               Line 3430
    }                                                                           
                                                                                
  f->name = xstrdup (name);                                                     Line 3433
  cwd_n_used++;                                                                 Line 3434
                                                                                
  return blocks;                                                                Line 3436
}                                                                               Block 91
                                                                                
/* Return true if F refers to a directory.  */                                  
static bool                                                                     Line 3440
is_directory (const struct fileinfo *f)                                         Line 3441
{                                                                               
  return f->filetype == directory || f->filetype == arg_directory;              Line 3443
}                                                                               Block 92
                                                                                
/* Put the name of the file that FILENAME is a symbolic link to                 
   into the LINKNAME field of 'f'.  COMMAND_LINE_ARG indicates whether          
   FILENAME is a command-line argument.  */                                     
                                                                                
static void                                                                     Line 3450
get_link_name (char const *filename, struct fileinfo *f, bool command_line_arg) Line 3451
{                                                                               
  f->linkname = areadlink_with_size (filename, f->stat.st_size);                Line 3453
  if (f->linkname == NULL)                                                      Line 3454
    file_failure (command_line_arg, _("cannot read symbolic link %s"),          Line 3455
                  filename);                                                    Line 3456
}                                                                               Block 93
                                                                                
/* If LINKNAME is a relative name and NAME contains one or more                 
   leading directories, return LINKNAME with those directories                  
   prepended; otherwise, return a copy of LINKNAME.                             
   If LINKNAME is NULL, return NULL.  */                                        
                                                                                
static char *                                                                   Line 3464
make_link_name (char const *name, char const *linkname)                         Line 3465
{                                                                               
  if (!linkname)                                                                Line 3467
    return NULL;                                                                Line 3468
                                                                                
  if (IS_ABSOLUTE_FILE_NAME (linkname))                                         Line 3470
    return xstrdup (linkname);                                                  Line 3471
                                                                                
  /* The link is to a relative name.  Prepend any leading directory             
     in 'name' to the link name.  */                                            
  size_t prefix_len = dir_len (name);                                           Line 3475
  if (prefix_len == 0)                                                          Line 3476
    return xstrdup (linkname);                                                  Line 3477
                                                                                
  char *p = xmalloc (prefix_len + 1 + strlen (linkname) + 1);                   Line 3479
                                                                                
  /* PREFIX_LEN usually specifies a string not ending in slash.                 
     In that case, extend it by one, since the next byte *is* a slash.          
     Otherwise, the prefix is "/", so leave the length unchanged.  */           
  if ( ! ISSLASH (name[prefix_len - 1]))                                        Line 3484
    ++prefix_len;                                                               Line 3485
                                                                                
  stpcpy (stpncpy (p, name, prefix_len), linkname);                             Line 3487
  return p;                                                                     Line 3488
}                                                                               Block 94
                                                                                
/* Return true if the last component of NAME is '.' or '..'                     
   This is so we don't try to recurse on '././././. ...' */                     
                                                                                
static bool                                                                     Line 3494
basename_is_dot_or_dotdot (const char *name)                                    Line 3495
{                                                                               
  char const *base = last_component (name);                                     Line 3497
  return dot_or_dotdot (base);                                                  Line 3498
}                                                                               Block 95
                                                                                
/* Remove any entries from CWD_FILE that are for directories,                   
   and queue them to be listed as directories instead.                          
   DIRNAME is the prefix to prepend to each dirname                             
   to make it correct relative to ls's working dir;                             
   if it is null, no prefix is needed and "." and ".." should not be ignored.   
   If COMMAND_LINE_ARG is true, this directory was mentioned at the top level,  
   This is desirable when processing directories recursively.  */               
                                                                                
static void                                                                     Line 3509
extract_dirs_from_files (char const *dirname, bool command_line_arg)            Line 3510
{                                                                               
  size_t i;                                                                     Line 3512
  size_t j;                                                                     Line 3513
  bool ignore_dot_and_dot_dot = (dirname != NULL);                              Line 3514
                                                                                
  if (dirname && LOOP_DETECT)                                                   Line 3516
    {                                                                           
      /* Insert a marker entry first.  When we dequeue this marker entry,       
         we'll know that DIRNAME has been processed and may be removed          
         from the set of active directories.  */                                
      queue_directory (NULL, dirname, false);                                   Line 3521
    }                                                                           
                                                                                
  /* Queue the directories last one first, because queueing reverses the        
     order.  */                                                                 
  for (i = cwd_n_used; i-- != 0; )                                              Line 3526
    {                                                                           
      struct fileinfo *f = sorted_file[i];                                      Line 3528
                                                                                
      if (is_directory (f)                                                      Line 3530
          && (! ignore_dot_and_dot_dot                                          Line 3531
              || ! basename_is_dot_or_dotdot (f->name)))                        Line 3532
        {                                                                       
          if (!dirname || f->name[0] == '/')                                    Line 3534
            queue_directory (f->name, f->linkname, command_line_arg);           Line 3535
          else                                                                  Line 3536
            {                                                                   
              char *name = file_name_concat (dirname, f->name, NULL);           Line 3538
              queue_directory (name, f->linkname, command_line_arg);            Line 3539
              free (name);                                                      Line 3540
            }                                                                   
          if (f->filetype == arg_directory)                                     Line 3542
            free_ent (f);                                                       Line 3543
        }                                                                       
    }                                                                           
                                                                                
  /* Now delete the directories from the table, compacting all the remaining    
     entries.  */                                                               
                                                                                
  for (i = 0, j = 0; i < cwd_n_used; i++)                                       Line 3550
    {                                                                           
      struct fileinfo *f = sorted_file[i];                                      Line 3552
      sorted_file[j] = f;                                                       Line 3553
      j += (f->filetype != arg_directory);                                      Line 3554
    }                                                                           
  cwd_n_used = j;                                                               Line 3556
}                                                                               Block 96
                                                                                
/* Use strcoll to compare strings in this locale.  If an error occurs,          
   report an error and longjmp to failed_strcoll.  */                           
                                                                                
static jmp_buf failed_strcoll;                                                  Line 3562
                                                                                
static int                                                                      Line 3564
xstrcoll (char const *a, char const *b)                                         Line 3565
{                                                                               
  int diff;                                                                     Line 3567
  errno = 0;                                                                    Line 3568
  diff = strcoll (a, b);                                                        Line 3569
  if (errno)                                                                    Line 3570
    {                                                                           
      error (0, errno, _("cannot compare file names %s and %s"),                Line 3572
             quote_n (0, a), quote_n (1, b));                                   Line 3573
      set_exit_status (false);                                                  Line 3574
      longjmp (failed_strcoll, 1);                                              Line 3575
    }                                                                           
  return diff;                                                                  Line 3577
}                                                                               Block 97
                                                                                
/* Comparison routines for sorting the files.  */                               
                                                                                
typedef void const *V;                                                          Line 3582
typedef int (*qsortFunc)(V a, V b);                                             Line 3583
                                                                                
/* Used below in DEFINE_SORT_FUNCTIONS for _df_ sort function variants.         
   The do { ... } while(0) makes it possible to use the macro more like         
   a statement, without violating C89 rules: */                                 
#define DIRFIRST_CHECK(a, b)      \                                             Line 3588
  do         \                                                                  Line 3589
    {         \                                                                 Line 3590
      bool a_is_dir = is_directory ((struct fileinfo const *) a); \             Line 3591
      bool b_is_dir = is_directory ((struct fileinfo const *) b); \             Line 3592
      if (a_is_dir && !b_is_dir)     \                                          Line 3593
        return -1;         /* a goes before b */   \                            Line 3594
      if (!a_is_dir && b_is_dir)     \                                          Line 3595
        return 1;          /* b goes before a */   \                            Line 3596
    }         \                                                                 Line 3597Block 98
  while (0)                                                                     Line 3598
                                                                                
/* Define the 8 different sort function variants required for each sortkey.     
   KEY_NAME is a token describing the sort key, e.g., ctime, atime, size.       
   KEY_CMP_FUNC is a function to compare records based on that key, e.g.,       
   ctime_cmp, atime_cmp, size_cmp.  Append KEY_NAME to the string,              
   '[rev_][x]str{cmp|coll}[_df]_', to create each function name.  */            
#define DEFINE_SORT_FUNCTIONS(key_name, key_cmp_func)   \                       Line 3605
  /* direct, non-dirfirst versions */     \                                     
  static int xstrcoll_##key_name (V a, V b)    \                                Line 3607
  { return key_cmp_func (a, b, xstrcoll); }    \                                Line 3608Block 99
  static int _GL_ATTRIBUTE_PURE strcmp_##key_name (V a, V b)  \                 Line 3609
  { return key_cmp_func (a, b, strcmp); }    \                                  Line 3610
                                                                        \       
  /* reverse, non-dirfirst versions */     \                                    
  static int rev_xstrcoll_##key_name (V a, V b)    \                            Line 3613
  { return key_cmp_func (b, a, xstrcoll); }    \                                Line 3614Block 101
  static int _GL_ATTRIBUTE_PURE rev_strcmp_##key_name (V a, V b) \              Line 3615
  { return key_cmp_func (b, a, strcmp); }    \                                  Line 3616
                                                                        \       
  /* direct, dirfirst versions */     \                                         
  static int xstrcoll_df_##key_name (V a, V b)    \                             Line 3619
  { DIRFIRST_CHECK (a, b); return key_cmp_func (a, b, xstrcoll); } \            Line 3620Block 103
  static int _GL_ATTRIBUTE_PURE strcmp_df_##key_name (V a, V b)  \              Line 3621
  { DIRFIRST_CHECK (a, b); return key_cmp_func (a, b, strcmp); } \              Line 3622
                                                                        \       
  /* reverse, dirfirst versions */     \                                        
  static int rev_xstrcoll_df_##key_name (V a, V b)   \                          Line 3625
  { DIRFIRST_CHECK (a, b); return key_cmp_func (b, a, xstrcoll); } \            Line 3626Block 105
  static int _GL_ATTRIBUTE_PURE rev_strcmp_df_##key_name (V a, V b) \           Line 3627
  { DIRFIRST_CHECK (a, b); return key_cmp_func (b, a, strcmp); }                Line 3628
                                                                                
static inline int                                                               Line 3630
cmp_ctime (struct fileinfo const *a, struct fileinfo const *b,                  Line 3631
           int (*cmp) (char const *, char const *))                             Line 3632
{                                                                               
  int diff = timespec_cmp (get_stat_ctime (&b->stat),                           Line 3634
                           get_stat_ctime (&a->stat));                          Line 3635
  return diff ? diff : cmp (a->name, b->name);                                  Line 3636
}                                                                               Block 107
                                                                                
static inline int                                                               Line 3639
cmp_mtime (struct fileinfo const *a, struct fileinfo const *b,                  Line 3640
           int (*cmp) (char const *, char const *))                             Line 3641
{                                                                               
  int diff = timespec_cmp (get_stat_mtime (&b->stat),                           Line 3643
                           get_stat_mtime (&a->stat));                          Line 3644
  return diff ? diff : cmp (a->name, b->name);                                  Line 3645
}                                                                               Block 108
                                                                                
static inline int                                                               Line 3648
cmp_atime (struct fileinfo const *a, struct fileinfo const *b,                  Line 3649
           int (*cmp) (char const *, char const *))                             Line 3650
{                                                                               
  int diff = timespec_cmp (get_stat_atime (&b->stat),                           Line 3652
                           get_stat_atime (&a->stat));                          Line 3653
  return diff ? diff : cmp (a->name, b->name);                                  Line 3654
}                                                                               Block 109
                                                                                
static inline int                                                               Line 3657
cmp_size (struct fileinfo const *a, struct fileinfo const *b,                   Line 3658
          int (*cmp) (char const *, char const *))                              Line 3659
{                                                                               
  int diff = longdiff (b->stat.st_size, a->stat.st_size);                       Line 3661
  return diff ? diff : cmp (a->name, b->name);                                  Line 3662
}                                                                               Block 110
                                                                                
static inline int                                                               Line 3665
cmp_name (struct fileinfo const *a, struct fileinfo const *b,                   Line 3666
          int (*cmp) (char const *, char const *))                              Line 3667
{                                                                               
  return cmp (a->name, b->name);                                                Line 3669
}                                                                               Block 111
                                                                                
/* Compare file extensions.  Files with no extension are 'smallest'.            
   If extensions are the same, compare by file names instead.  */               
                                                                                
static inline int                                                               Line 3675
cmp_extension (struct fileinfo const *a, struct fileinfo const *b,              Line 3676
               int (*cmp) (char const *, char const *))                         Line 3677
{                                                                               
  char const *base1 = strrchr (a->name, '.');                                   Line 3679
  char const *base2 = strrchr (b->name, '.');                                   Line 3680
  int diff = cmp (base1 ? base1 : "", base2 ? base2 : "");                      Line 3681
  return diff ? diff : cmp (a->name, b->name);                                  Line 3682
}                                                                               Block 112
                                                                                
DEFINE_SORT_FUNCTIONS (ctime, cmp_ctime)                                        Line 3685
DEFINE_SORT_FUNCTIONS (mtime, cmp_mtime)                                        Line 3686
DEFINE_SORT_FUNCTIONS (atime, cmp_atime)                                        Line 3687
DEFINE_SORT_FUNCTIONS (size, cmp_size)                                          Line 3688
DEFINE_SORT_FUNCTIONS (name, cmp_name)                                          Line 3689
DEFINE_SORT_FUNCTIONS (extension, cmp_extension)                                Line 3690
                                                                                
/* Compare file versions.                                                       
   Unlike all other compare functions above, cmp_version depends only           
   on filevercmp, which does not fail (even for locale reasons), and does not   
   need a secondary sort key. See lib/filevercmp.h for function description.    
                                                                                
   All the other sort options, in fact, need xstrcoll and strcmp variants,      
   because they all use a string comparison (either as the primary or secondary 
   sort key), and xstrcoll has the ability to do a longjmp if strcoll fails for 
   locale reasons.  Lastly, filevercmp is ALWAYS available with gnulib.  */     
static inline int                                                               Line 3701
cmp_version (struct fileinfo const *a, struct fileinfo const *b)                Line 3702
{                                                                               
  return filevercmp (a->name, b->name);                                         Line 3704
}                                                                               Block 113
                                                                                
static int xstrcoll_version (V a, V b)                                          Line 3707
{ return cmp_version (a, b); }                                                  Line 3708Block 114
static int rev_xstrcoll_version (V a, V b)                                      Line 3709
{ return cmp_version (b, a); }                                                  Line 3710Block 115
static int xstrcoll_df_version (V a, V b)                                       Line 3711
{ DIRFIRST_CHECK (a, b); return cmp_version (a, b); }                           Line 3712Block 116
static int rev_xstrcoll_df_version (V a, V b)                                   Line 3713
{ DIRFIRST_CHECK (a, b); return cmp_version (b, a); }                           Line 3714
                                                                                
                                                                                
/* We have 2^3 different variants for each sort-key function                    
   (for 3 independent sort modes).                                              
   The function pointers stored in this array must be dereferenced as:          
                                                                                
    sort_variants[sort_key][use_strcmp][reverse][dirs_first]                    
                                                                                
   Note that the order in which sort keys are listed in the function pointer    
   array below is defined by the order of the elements in the time_type and     
   sort_type enums!  */                                                         
                                                                                
#define LIST_SORTFUNCTION_VARIANTS(key_name)                        \           Line 3727
  {                                                                 \           Line 3728
    {                                                               \           Line 3729
      { xstrcoll_##key_name, xstrcoll_df_##key_name },              \           Line 3730
      { rev_xstrcoll_##key_name, rev_xstrcoll_df_##key_name },      \           Line 3731
    },                                                              \           Line 3732
    {                                                               \           Line 3733
      { strcmp_##key_name, strcmp_df_##key_name },                  \           Line 3734
      { rev_strcmp_##key_name, rev_strcmp_df_##key_name },          \           Line 3735
    }                                                               \           Line 3736
  }                                                                             Block 118
                                                                                
static qsortFunc const sort_functions[][2][2][2] =                              Line 3739
  {                                                                             
    LIST_SORTFUNCTION_VARIANTS (name),                                          Line 3741
    LIST_SORTFUNCTION_VARIANTS (extension),                                     Line 3742
    LIST_SORTFUNCTION_VARIANTS (size),                                          Line 3743
                                                                                
    {                                                                           
      {                                                                         
        { xstrcoll_version, xstrcoll_df_version },                              Line 3747
        { rev_xstrcoll_version, rev_xstrcoll_df_version },                      Line 3748
      },                                                                        
                                                                                
      /* We use NULL for the strcmp variants of version comparison              
         since as explained in cmp_version definition, version comparison       
         does not rely on xstrcoll, so it will never longjmp, and never         
         need to try the strcmp fallback. */                                    
      {                                                                         
        { NULL, NULL },                                                         Line 3756
        { NULL, NULL },                                                         Line 3757
      }                                                                         
    },                                                                          
                                                                                
    /* last are time sort functions */                                          
    LIST_SORTFUNCTION_VARIANTS (mtime),                                         Line 3762
    LIST_SORTFUNCTION_VARIANTS (ctime),                                         Line 3763
    LIST_SORTFUNCTION_VARIANTS (atime)                                          Line 3764
  };                                                                            Block 119
                                                                                
/* The number of sort keys is calculated as the sum of                          
     the number of elements in the sort_type enum (i.e., sort_numtypes)         
     the number of elements in the time_type enum (i.e., time_numtypes) - 1     
   This is because when sort_type==sort_time, we have up to                     
   time_numtypes possible sort keys.                                            
                                                                                
   This line verifies at compile-time that the array of sort functions has been 
   initialized for all possible sort keys. */                                   
verify (ARRAY_CARDINALITY (sort_functions)                                      Line 3775
        == sort_numtypes + time_numtypes - 1 );                                 Line 3776
                                                                                
/* Set up SORTED_FILE to point to the in-use entries in CWD_FILE, in order.  */ 
                                                                                
static void                                                                     Line 3780
initialize_ordering_vector (void)                                               Line 3781
{                                                                               
  for (size_t i = 0; i < cwd_n_used; i++)                                       Line 3783
    sorted_file[i] = &cwd_file[i];                                              Line 3784
}                                                                               Block 120
                                                                                
/* Sort the files now in the table.  */                                         
                                                                                
static void                                                                     Line 3789
sort_files (void)                                                               Line 3790
{                                                                               
  bool use_strcmp;                                                              Line 3792
                                                                                
  if (sorted_file_alloc < cwd_n_used + cwd_n_used / 2)                          Line 3794
    {                                                                           
      free (sorted_file);                                                       Line 3796
      sorted_file = xnmalloc (cwd_n_used, 3 * sizeof *sorted_file);             Line 3797
      sorted_file_alloc = 3 * cwd_n_used;                                       Line 3798
    }                                                                           
                                                                                
  initialize_ordering_vector ();                                                Line 3801
                                                                                
  if (sort_type == sort_none)                                                   Line 3803
    return;                                                                     Line 3804
                                                                                
  /* Try strcoll.  If it fails, fall back on strcmp.  We can't safely           
     ignore strcoll failures, as a failing strcoll might be a                   
     comparison function that is not a total order, and if we ignored           
     the failure this might cause qsort to dump core.  */                       
                                                                                
  if (! setjmp (failed_strcoll))                                                Line 3811
    use_strcmp = false;      /* strcoll() succeeded */                          Line 3812
  else                                                                          Line 3813
    {                                                                           
      use_strcmp = true;                                                        Line 3815
      assert (sort_type != sort_version);                                       Line 3816
      initialize_ordering_vector ();                                            Line 3817
    }                                                                           
                                                                                
  /* When sort_type == sort_time, use time_type as subindex.  */                
  mpsort ((void const **) sorted_file, cwd_n_used,                              Line 3821
          sort_functions[sort_type + (sort_type == sort_time ? time_type : 0)]  Line 3822
                        [use_strcmp][sort_reverse]                              Line 3823
                        [directories_first]);                                   Line 3824
}                                                                               Block 121
                                                                                
/* List all the files now in the table.  */                                     
                                                                                
static void                                                                     Line 3829
print_current_files (void)                                                      Line 3830
{                                                                               
  size_t i;                                                                     Line 3832
                                                                                
  switch (format)                                                               Line 3834
    {                                                                           
    case one_per_line:                                                          Line 3836
      for (i = 0; i < cwd_n_used; i++)                                          Line 3837
        {                                                                       
          print_file_name_and_frills (sorted_file[i], 0);                       Line 3839
          putchar ('\n');                                                       Line 3840
        }                                                                       
      break;                                                                    Line 3842
                                                                                
    case many_per_line:                                                         Line 3844
      if (! line_length)                                                        Line 3845
        print_with_separator (' ');                                             Line 3846
      else                                                                      Line 3847
        print_many_per_line ();                                                 Line 3848
      break;                                                                    Line 3849
                                                                                
    case horizontal:                                                            Line 3851
      if (! line_length)                                                        Line 3852
        print_with_separator (' ');                                             Line 3853
      else                                                                      Line 3854
        print_horizontal ();                                                    Line 3855
      break;                                                                    Line 3856
                                                                                
    case with_commas:                                                           Line 3858
      print_with_separator (',');                                               Line 3859
      break;                                                                    Line 3860
                                                                                
    case long_format:                                                           Line 3862
      for (i = 0; i < cwd_n_used; i++)                                          Line 3863
        {                                                                       
          set_normal_color ();                                                  Line 3865
          print_long_format (sorted_file[i]);                                   Line 3866
          DIRED_PUTCHAR ('\n');                                                 Line 3867
        }                                                                       
      break;                                                                    Line 3869
    }                                                                           
}                                                                               Block 122
                                                                                
/* Replace the first %b with precomputed aligned month names.                   
   Note on glibc-2.7 at least, this speeds up the whole 'ls -lU'                
   process by around 17%, compared to letting strftime() handle the %b.  */     
                                                                                
static size_t                                                                   Line 3877
align_nstrftime (char *buf, size_t size, bool recent, struct tm const *tm,      Line 3878
                 timezone_t tz, int ns)                                         Line 3879
{                                                                               
  char const *nfmt = (use_abformat                                              Line 3881
                      ? abformat[recent][tm->tm_mon]                            Line 3882
                      : long_time_format[recent]);                              Line 3883
  return nstrftime (buf, size, nfmt, tm, tz, ns);                               Line 3884
}                                                                               Block 123
                                                                                
/* Return the expected number of columns in a long-format timestamp,            
   or zero if it cannot be calculated.  */                                      
                                                                                
static int                                                                      Line 3890
long_time_expected_width (void)                                                 Line 3891
{                                                                               
  static int width = -1;                                                        Line 3893
                                                                                
  if (width < 0)                                                                Line 3895
    {                                                                           
      time_t epoch = 0;                                                         Line 3897
      struct tm tm;                                                             Line 3898
      char buf[TIME_STAMP_LEN_MAXIMUM + 1];                                     Line 3899
                                                                                
      /* In case you're wondering if localtime_rz can fail with an input time_t 
         value of 0, let's just say it's very unlikely, but not inconceivable.  
         The TZ environment variable would have to specify a time zone that     
         is 2**31-1900 years or more ahead of UTC.  This could happen only on   
         a 64-bit system that blindly accepts e.g., TZ=UTC+20000000000000.      
         However, this is not possible with Solaris 10 or glibc-2.3.5, since    
         their implementations limit the offset to 167:59 and 24:00, resp.  */  
      if (localtime_rz (localtz, &epoch, &tm))                                  Line 3908
        {                                                                       
          size_t len = align_nstrftime (buf, sizeof buf, false,                 Line 3910
                                        &tm, localtz, 0);                       Line 3911
          if (len != 0)                                                         Line 3912
            width = mbsnwidth (buf, len, 0);                                    Line 3913
        }                                                                       
                                                                                
      if (width < 0)                                                            Line 3916
        width = 0;                                                              Line 3917
    }                                                                           
                                                                                
  return width;                                                                 Line 3920
}                                                                               Block 124
                                                                                
/* Print the user or group name NAME, with numeric id ID, using a               
   print width of WIDTH columns.  */                                            
                                                                                
static void                                                                     Line 3926
format_user_or_group (char const *name, unsigned long int id, int width)        Line 3927
{                                                                               
  size_t len;                                                                   Line 3929
                                                                                
  if (name)                                                                     Line 3931
    {                                                                           
      int width_gap = width - mbswidth (name, 0);                               Line 3933
      int pad = MAX (0, width_gap);                                             Line 3934
      fputs (name, stdout);                                                     Line 3935
      len = strlen (name) + pad;                                                Line 3936
                                                                                
      do                                                                        
        putchar (' ');                                                          Line 3939
      while (pad--);                                                            Line 3940
    }                                                                           
  else                                                                          Line 3942
    {                                                                           
      printf ("%*lu ", width, id);                                              Line 3944
      len = width;                                                              Line 3945
    }                                                                           
                                                                                
  dired_pos += len + 1;                                                         Line 3948
}                                                                               Block 125
                                                                                
/* Print the name or id of the user with id U, using a print width of           
   WIDTH.  */                                                                   
                                                                                
static void                                                                     Line 3954
format_user (uid_t u, int width, bool stat_ok)                                  Line 3955
{                                                                               
  format_user_or_group (! stat_ok ? "?" :                                       Line 3957
                        (numeric_ids ? NULL : getuser (u)), u, width);          Line 3958
}                                                                               Block 126
                                                                                
/* Likewise, for groups.  */                                                    
                                                                                
static void                                                                     Line 3963
format_group (gid_t g, int width, bool stat_ok)                                 Line 3964
{                                                                               
  format_user_or_group (! stat_ok ? "?" :                                       Line 3966
                        (numeric_ids ? NULL : getgroup (g)), g, width);         Line 3967
}                                                                               Block 127
                                                                                
/* Return the number of columns that format_user_or_group will print.  */       
                                                                                
static int                                                                      Line 3972
format_user_or_group_width (char const *name, unsigned long int id)             Line 3973
{                                                                               
  if (name)                                                                     Line 3975
    {                                                                           
      int len = mbswidth (name, 0);                                             Line 3977
      return MAX (0, len);                                                      Line 3978
    }                                                                           
  else                                                                          Line 3980
    {                                                                           
      char buf[INT_BUFSIZE_BOUND (id)];                                         Line 3982
      sprintf (buf, "%lu", id);                                                 Line 3983
      return strlen (buf);                                                      Line 3984
    }                                                                           
}                                                                               Block 128
                                                                                
/* Return the number of columns that format_user will print.  */                
                                                                                
static int                                                                      Line 3990
format_user_width (uid_t u)                                                     Line 3991
{                                                                               
  return format_user_or_group_width (numeric_ids ? NULL : getuser (u), u);      Line 3993
}                                                                               Block 129
                                                                                
/* Likewise, for groups.  */                                                    
                                                                                
static int                                                                      Line 3998
format_group_width (gid_t g)                                                    Line 3999
{                                                                               
  return format_user_or_group_width (numeric_ids ? NULL : getgroup (g), g);     Line 4001
}                                                                               Block 130
                                                                                
/* Return a pointer to a formatted version of F->stat.st_ino,                   
   possibly using buffer, BUF, of length BUFLEN, which must be at least         
   INT_BUFSIZE_BOUND (uintmax_t) bytes.  */                                     
static char *                                                                   Line 4007
format_inode (char *buf, size_t buflen, const struct fileinfo *f)               Line 4008
{                                                                               
  assert (INT_BUFSIZE_BOUND (uintmax_t) <= buflen);                             Line 4010
  return (f->stat_ok && f->stat.st_ino != NOT_AN_INODE_NUMBER                   Line 4011
          ? umaxtostr (f->stat.st_ino, buf)                                     Line 4012
          : (char *) "?");                                                      Line 4013
}                                                                               Block 131
                                                                                
/* Print information about F in long format.  */                                
static void                                                                     Line 4017
print_long_format (const struct fileinfo *f)                                    Line 4018
{                                                                               
  char modebuf[12];                                                             Line 4020
  char buf                                                                      Line 4021
    [LONGEST_HUMAN_READABLE + 1  /* inode */                                    Line 4022
     + LONGEST_HUMAN_READABLE + 1 /* size in blocks */                          Line 4023
     + sizeof (modebuf) - 1 + 1  /* mode string */                              Line 4024
     + INT_BUFSIZE_BOUND (uintmax_t) /* st_nlink */                             Line 4025
     + LONGEST_HUMAN_READABLE + 2 /* major device number */                     Line 4026
     + LONGEST_HUMAN_READABLE + 1 /* minor device number */                     Line 4027
     + TIME_STAMP_LEN_MAXIMUM + 1 /* max length of time/date */                 Line 4028
     ];                                                                         
  size_t s;                                                                     Line 4030
  char *p;                                                                      Line 4031
  struct timespec when_timespec;                                                Line 4032
  struct tm when_local;                                                         Line 4033
                                                                                
  /* Compute the mode string, except remove the trailing space if no            
     file in this directory has an ACL or security context.  */                 
  if (f->stat_ok)                                                               Line 4037
    filemodestring (&f->stat, modebuf);                                         Line 4038
  else                                                                          Line 4039
    {                                                                           
      modebuf[0] = filetype_letter[f->filetype];                                Line 4041
      memset (modebuf + 1, '?', 10);                                            Line 4042
      modebuf[11] = '\0';                                                       Line 4043
    }                                                                           
  if (! any_has_acl)                                                            Line 4045
    modebuf[10] = '\0';                                                         Line 4046
  else if (f->acl_type == ACL_T_LSM_CONTEXT_ONLY)                               Line 4047
    modebuf[10] = '.';                                                          Line 4048
  else if (f->acl_type == ACL_T_YES)                                            Line 4049
    modebuf[10] = '+';                                                          Line 4050
                                                                                
  switch (time_type)                                                            Line 4052
    {                                                                           
    case time_ctime:                                                            Line 4054
      when_timespec = get_stat_ctime (&f->stat);                                Line 4055
      break;                                                                    Line 4056
    case time_mtime:                                                            Line 4057
      when_timespec = get_stat_mtime (&f->stat);                                Line 4058
      break;                                                                    Line 4059
    case time_atime:                                                            Line 4060
      when_timespec = get_stat_atime (&f->stat);                                Line 4061
      break;                                                                    Line 4062
    default:                                                                    Line 4063
      abort ();                                                                 ...!common auto-comment...
    }                                                                           
                                                                                
  p = buf;                                                                      Line 4067
                                                                                
  if (print_inode)                                                              Line 4069
    {                                                                           
      char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];                                 Line 4071
      sprintf (p, "%*s ", inode_number_width,                                   Line 4072
               format_inode (hbuf, sizeof hbuf, f));                            Line 4073
      /* Increment by strlen (p) here, rather than by inode_number_width + 1.   
         The latter is wrong when inode_number_width is zero.  */               
      p += strlen (p);                                                          Line 4076
    }                                                                           
                                                                                
  if (print_block_size)                                                         Line 4079
    {                                                                           
      char hbuf[LONGEST_HUMAN_READABLE + 1];                                    Line 4081
      char const *blocks =                                                      Line 4082
        (! f->stat_ok                                                           Line 4083
         ? "?"                                                                  Line 4084
         : human_readable (ST_NBLOCKS (f->stat), hbuf, human_output_opts,       Line 4085
                           ST_NBLOCKSIZE, output_block_size));                  Line 4086
      int pad;                                                                  Line 4087
      for (pad = block_size_width - mbswidth (blocks, 0); 0 < pad; pad--)       Line 4088
        *p++ = ' ';                                                             Line 4089
      while ((*p++ = *blocks++))                                                Line 4090
        continue;                                                               Line 4091
      p[-1] = ' ';                                                              Line 4092
    }                                                                           
                                                                                
  /* The last byte of the mode string is the POSIX                              
     "optional alternate access method flag".  */                               
  {                                                                             
    char hbuf[INT_BUFSIZE_BOUND (uintmax_t)];                                   Line 4098
    sprintf (p, "%s %*s ", modebuf, nlink_width,                                Line 4099
             ! f->stat_ok ? "?" : umaxtostr (f->stat.st_nlink, hbuf));          Line 4100
  }                                                                             
  /* Increment by strlen (p) here, rather than by, e.g.,                        
     sizeof modebuf - 2 + any_has_acl + 1 + nlink_width + 1.                    
     The latter is wrong when nlink_width is zero.  */                          
  p += strlen (p);                                                              Line 4105
                                                                                
  DIRED_INDENT ();                                                              Line 4107
                                                                                
  if (print_owner || print_group || print_author || print_scontext)             Line 4109
    {                                                                           
      DIRED_FPUTS (buf, stdout, p - buf);                                       Line 4111
                                                                                
      if (print_owner)                                                          Line 4113
        format_user (f->stat.st_uid, owner_width, f->stat_ok);                  Line 4114
                                                                                
      if (print_group)                                                          Line 4116
        format_group (f->stat.st_gid, group_width, f->stat_ok);                 Line 4117
                                                                                
      if (print_author)                                                         Line 4119
        format_user (f->stat.st_author, author_width, f->stat_ok);              Line 4120
                                                                                
      if (print_scontext)                                                       Line 4122
        format_user_or_group (f->scontext, 0, scontext_width);                  Line 4123
                                                                                
      p = buf;                                                                  Line 4125
    }                                                                           
                                                                                
  if (f->stat_ok                                                                Line 4128
      && (S_ISCHR (f->stat.st_mode) || S_ISBLK (f->stat.st_mode)))              Line 4129
    {                                                                           
      char majorbuf[INT_BUFSIZE_BOUND (uintmax_t)];                             Line 4131
      char minorbuf[INT_BUFSIZE_BOUND (uintmax_t)];                             Line 4132
      int blanks_width = (file_size_width                                       Line 4133
                          - (major_device_number_width + 2                      Line 4134
                             + minor_device_number_width));                     Line 4135
      sprintf (p, "%*s, %*s ",                                                  Line 4136
               major_device_number_width + MAX (0, blanks_width),               Line 4137
               umaxtostr (major (f->stat.st_rdev), majorbuf),                   Line 4138
               minor_device_number_width,                                       Line 4139
               umaxtostr (minor (f->stat.st_rdev), minorbuf));                  Line 4140
      p += file_size_width + 1;                                                 Line 4141
    }                                                                           
  else                                                                          Line 4143
    {                                                                           
      char hbuf[LONGEST_HUMAN_READABLE + 1];                                    Line 4145
      char const *size =                                                        Line 4146
        (! f->stat_ok                                                           Line 4147
         ? "?"                                                                  Line 4148
         : human_readable (unsigned_file_size (f->stat.st_size),                Line 4149
                           hbuf, file_human_output_opts, 1,                     Line 4150
                           file_output_block_size));                            Line 4151
      int pad;                                                                  Line 4152
      for (pad = file_size_width - mbswidth (size, 0); 0 < pad; pad--)          Line 4153
        *p++ = ' ';                                                             Line 4154
      while ((*p++ = *size++))                                                  Line 4155
        continue;                                                               Line 4156
      p[-1] = ' ';                                                              Line 4157
    }                                                                           
                                                                                
  s = 0;                                                                        Line 4160
  *p = '\1';                                                                    Line 4161
                                                                                
  if (f->stat_ok && localtime_rz (localtz, &when_timespec.tv_sec, &when_local)) Line 4163
    {                                                                           
      struct timespec six_months_ago;                                           Line 4165
      bool recent;                                                              Line 4166
                                                                                
      /* If the file appears to be in the future, update the current            
         time, in case the file happens to have been modified since             
         the last time we checked the clock.  */                                
      if (timespec_cmp (current_time, when_timespec) < 0)                       Line 4171
        gettime (¤t_time);                                                Line 4172
                                                                                
      /* Consider a time to be recent if it is within the past six months.      
         A Gregorian year has 365.2425 * 24 * 60 * 60 == 31556952 seconds       
         on the average.  Write this value as an integer constant to            
         avoid floating point hassles.  */                                      
      six_months_ago.tv_sec = current_time.tv_sec - 31556952 / 2;               Line 4178
      six_months_ago.tv_nsec = current_time.tv_nsec;                            Line 4179
                                                                                
      recent = (timespec_cmp (six_months_ago, when_timespec) < 0                Line 4181
                && (timespec_cmp (when_timespec, current_time) < 0));           Line 4182
                                                                                
      /* We assume here that all time zones are offset from UTC by a            
         whole number of seconds.  */                                           
      s = align_nstrftime (p, TIME_STAMP_LEN_MAXIMUM + 1, recent,               Line 4186
                           &when_local, localtz, when_timespec.tv_nsec);        Line 4187
    }                                                                           
                                                                                
  if (s || !*p)                                                                 Line 4190
    {                                                                           
      p += s;                                                                   Line 4192
      *p++ = ' ';                                                               Line 4193
                                                                                
      /* NUL-terminate the string -- fputs (via DIRED_FPUTS) requires it.  */   
      *p = '\0';                                                                Line 4196
    }                                                                           
  else                                                                          Line 4198
    {                                                                           
      /* The time cannot be converted using the desired format, so              
         print it as a huge integer number of seconds.  */                      
      char hbuf[INT_BUFSIZE_BOUND (intmax_t)];                                  Line 4202
      sprintf (p, "%*s ", long_time_expected_width (),                          Line 4203
               (! f->stat_ok                                                    Line 4204
                ? "?"                                                           Line 4205
                : timetostr (when_timespec.tv_sec, hbuf)));                     Line 4206
      /* FIXME: (maybe) We discarded when_timespec.tv_nsec. */                  
      p += strlen (p);                                                          Line 4208
    }                                                                           
                                                                                
  DIRED_FPUTS (buf, stdout, p - buf);                                           Line 4211
  size_t w = print_name_with_quoting (f, false, &dired_obstack, p - buf);       Line 4212
                                                                                
  if (f->filetype == symbolic_link)                                             Line 4214
    {                                                                           
      if (f->linkname)                                                          Line 4216
        {                                                                       
          DIRED_FPUTS_LITERAL (" -> ", stdout);                                 Line 4218
          print_name_with_quoting (f, true, NULL, (p - buf) + w + 4);           Line 4219
          if (indicator_style != none)                                          Line 4220
            print_type_indicator (true, f->linkmode, unknown);                  Line 4221
        }                                                                       
    }                                                                           
  else if (indicator_style != none)                                             Line 4224
    print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);            Line 4225
}                                                                               Block 132
                                                                                
/* Write to *BUF a quoted representation of the file name NAME, if non-NULL,    
   using OPTIONS to control quoting.  *BUF is set to NAME if no quoting         
   is required.  *BUF is allocated if more space required (and the original     
   *BUF is not deallocated).                                                    
   Store the number of screen columns occupied by NAME's quoted                 
   representation into WIDTH, if non-NULL.                                      
   Store into PAD whether an initial space is needed for padding.               
   Return the number of bytes in *BUF.  */                                      
                                                                                
static size_t                                                                   Line 4237
quote_name_buf (char **inbuf, size_t bufsize, char *name,                       Line 4238
                struct quoting_options const *options,                          Line 4239
                int needs_general_quoting, size_t *width, bool *pad)            Line 4240
{                                                                               
  char *buf = *inbuf;                                                           Line 4242
  size_t displayed_width IF_LINT ( = 0);                                        Line 4243
  size_t len = 0;                                                               Line 4244
  bool quoted;                                                                  Line 4245
                                                                                
  enum quoting_style qs = get_quoting_style (options);                          Line 4247
  bool needs_further_quoting = qmark_funny_chars                                Line 4248
                               && (qs == shell_quoting_style                    Line 4249
                                   || qs == shell_always_quoting_style          Line 4250
                                   || qs == literal_quoting_style);             Line 4251
                                                                                
  if (needs_general_quoting != 0)                                               Line 4253
    {                                                                           
      len = quotearg_buffer (buf, bufsize, name, -1, options);                  Line 4255
      if (bufsize <= len)                                                       Line 4256
        {                                                                       
          buf = xmalloc (len + 1);                                              Line 4258
          quotearg_buffer (buf, len + 1, name, -1, options);                    Line 4259
        }                                                                       
                                                                                
      quoted = (*name != *buf) || strlen (name) != len;                         Line 4262
    }                                                                           
  else if (needs_further_quoting)                                               Line 4264
    {                                                                           
      len = strlen (name);                                                      Line 4266
      if (bufsize <= len)                                                       Line 4267
        buf = xmalloc (len + 1);                                                Line 4268
      memcpy (buf, name, len + 1);                                              Line 4269
                                                                                
      quoted = false;                                                           Line 4271
    }                                                                           
  else                                                                          Line 4273
    {                                                                           
      len = strlen (name);                                                      Line 4275
      buf = name;                                                               Line 4276
      quoted = false;                                                           Line 4277
    }                                                                           
                                                                                
  if (needs_further_quoting)                                                    Line 4280
    {                                                                           
      if (MB_CUR_MAX > 1)                                                       Line 4282
        {                                                                       
          char const *p = buf;                                                  Line 4284
          char const *plimit = buf + len;                                       Line 4285
          char *q = buf;                                                        Line 4286
          displayed_width = 0;                                                  Line 4287
                                                                                
          while (p < plimit)                                                    Line 4289
            switch (*p)                                                         Line 4290
              {                                                                 
                case ' ': case '!': case '"': case '#': case '%':               Line 4292
                case '&': case '\'': case '(': case ')': case '*':              Line 4293
                case '+': case ',': case '-': case '.': case '/':               Line 4294
                case '0': case '1': case '2': case '3': case '4':               Line 4295
                case '5': case '6': case '7': case '8': case '9':               Line 4296
                case ':': case ';': case '<': case '=': case '>':               Line 4297
                case '?':                                                       Line 4298
                case 'A': case 'B': case 'C': case 'D': case 'E':               Line 4299
                case 'F': case 'G': case 'H': case 'I': case 'J':               Line 4300
                case 'K': case 'L': case 'M': case 'N': case 'O':               Line 4301
                case 'P': case 'Q': case 'R': case 'S': case 'T':               Line 4302
                case 'U': case 'V': case 'W': case 'X': case 'Y':               Line 4303
                case 'Z':                                                       Line 4304
                case '[': case '\\': case ']': case '^': case '_':              Line 4305
                case 'a': case 'b': case 'c': case 'd': case 'e':               Line 4306
                case 'f': case 'g': case 'h': case 'i': case 'j':               Line 4307
                case 'k': case 'l': case 'm': case 'n': case 'o':               Line 4308
                case 'p': case 'q': case 'r': case 's': case 't':               Line 4309
                case 'u': case 'v': case 'w': case 'x': case 'y':               Line 4310
                case 'z': case '{': case '|': case '}': case '~':               Line 4311
                  /* These characters are printable ASCII characters.  */       
                  *q++ = *p++;                                                  Line 4313
                  displayed_width += 1;                                         Line 4314
                  break;                                                        Line 4315
                default:                                                        Line 4316
                  /* If we have a multibyte sequence, copy it until we          
                     reach its end, replacing each non-printable multibyte      
                     character with a single question mark.  */                 
                  {                                                             
                    mbstate_t mbstate = { 0, };                                 Line 4321
                    do                                                          
                      {                                                         
                        wchar_t wc;                                             Line 4324
                        size_t bytes;                                           Line 4325
                        int w;                                                  Line 4326
                                                                                
                        bytes = mbrtowc (&wc, p, plimit - p, &mbstate);         Line 4328
                                                                                
                        if (bytes == (size_t) -1)                               Line 4330
                          {                                                     
                            /* An invalid multibyte sequence was                
                               encountered.  Skip one input byte, and           
                               put a question mark.  */                         
                            p++;                                                Line 4335
                            *q++ = '?';                                         Line 4336
                            displayed_width += 1;                               Line 4337
                            break;                                              Line 4338
                          }                                                     
                                                                                
                        if (bytes == (size_t) -2)                               Line 4341
                          {                                                     
                            /* An incomplete multibyte character                
                               at the end.  Replace it entirely with            
                               a question mark.  */                             
                            p = plimit;                                         Line 4346
                            *q++ = '?';                                         Line 4347
                            displayed_width += 1;                               Line 4348
                            break;                                              Line 4349
                          }                                                     
                                                                                
                        if (bytes == 0)                                         Line 4352
                          /* A null wide character was encountered.  */         
                          bytes = 1;                                            Line 4354
                                                                                
                        w = wcwidth (wc);                                       Line 4356
                        if (w >= 0)                                             Line 4357
                          {                                                     
                            /* A printable multibyte character.                 
                               Keep it.  */                                     
                            for (; bytes > 0; --bytes)                          Line 4361
                              *q++ = *p++;                                      Line 4362
                            displayed_width += w;                               Line 4363
                          }                                                     
                        else                                                    Line 4365
                          {                                                     
                            /* An unprintable multibyte character.              
                               Replace it entirely with a question              
                               mark.  */                                        
                            p += bytes;                                         Line 4370
                            *q++ = '?';                                         Line 4371
                            displayed_width += 1;                               Line 4372
                          }                                                     
                      }                                                         
                    while (! mbsinit (&mbstate));                               Line 4375
                  }                                                             
                  break;                                                        Line 4377
              }                                                                 
                                                                                
          /* The buffer may have shrunk.  */                                    
          len = q - buf;                                                        Line 4381
        }                                                                       
      else                                                                      Line 4383
        {                                                                       
          char *p = buf;                                                        Line 4385
          char const *plimit = buf + len;                                       Line 4386
                                                                                
          while (p < plimit)                                                    Line 4388
            {                                                                   
              if (! isprint (to_uchar (*p)))                                    Line 4390
                *p = '?';                                                       Line 4391
              p++;                                                              Line 4392
            }                                                                   
          displayed_width = len;                                                Line 4394
        }                                                                       
    }                                                                           
  else if (width != NULL)                                                       Line 4397
    {                                                                           
      if (MB_CUR_MAX > 1)                                                       Line 4399
        displayed_width = mbsnwidth (buf, len, 0);                              Line 4400
      else                                                                      Line 4401
        {                                                                       
          char const *p = buf;                                                  Line 4403
          char const *plimit = buf + len;                                       Line 4404
                                                                                
          displayed_width = 0;                                                  Line 4406
          while (p < plimit)                                                    Line 4407
            {                                                                   
              if (isprint (to_uchar (*p)))                                      Line 4409
                displayed_width++;                                              Line 4410
              p++;                                                              Line 4411
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  /* Set padding to better align quoted items,                                  
     and also give a visual indication that quotes are                          
     not actually part of the name.  */                                         
  *pad = (align_variable_outer_quotes && cwd_some_quoted && ! quoted);          Line 4419
                                                                                
  if (width != NULL)                                                            Line 4421
    *width = displayed_width;                                                   Line 4422
                                                                                
  *inbuf = buf;                                                                 Line 4424
                                                                                
  return len;                                                                   Line 4426
}                                                                               Block 133
                                                                                
static size_t                                                                   Line 4429
quote_name_width (const char *name, struct quoting_options const *options,      Line 4430
                  int needs_general_quoting)                                    Line 4431
{                                                                               
  char smallbuf[BUFSIZ];                                                        Line 4433
  char *buf = smallbuf;                                                         Line 4434
  size_t width;                                                                 Line 4435
  bool pad;                                                                     Line 4436
                                                                                
  quote_name_buf (&buf, sizeof smallbuf, (char *) name, options,                Line 4438
                  needs_general_quoting, &width, &pad);                         Line 4439
                                                                                
  if (buf != smallbuf && buf != name)                                           Line 4441
    free (buf);                                                                 Line 4442
                                                                                
  width += pad;                                                                 Line 4444
                                                                                
  return width;                                                                 Line 4446
}                                                                               Block 134
                                                                                
/* %XX escape any input out of range as defined in RFC3986,                     
   and also if PATH, convert all path separators to '/'.  */                    
static char *                                                                   Line 4451
file_escape (const char *str, bool path)                                        Line 4452
{                                                                               
  char *esc = xnmalloc (3, strlen (str) + 1);                                   Line 4454
  char *p = esc;                                                                Line 4455
  while (*str)                                                                  Line 4456
    {                                                                           
      if (path && ISSLASH (*str))                                               Line 4458
        {                                                                       
          *p++ = '/';                                                           Line 4460
          str++;                                                                Line 4461
        }                                                                       
      else if (RFC3986[to_uchar (*str)])                                        Line 4463
        *p++ = *str++;                                                          Line 4464
      else                                                                      Line 4465
        p += sprintf (p, "%%%02x", to_uchar (*str++));                          Line 4466
    }                                                                           
  *p = '\0';                                                                    Line 4468
  return esc;                                                                   Line 4469
}                                                                               Block 135
                                                                                
static size_t                                                                   Line 4472
quote_name (char const *name, struct quoting_options const *options,            Line 4473
            int needs_general_quoting, const struct bin_str *color,             Line 4474
            bool allow_pad, struct obstack *stack, char const *absolute_name)   Line 4475
{                                                                               
  char smallbuf[BUFSIZ];                                                        Line 4477
  char *buf = smallbuf;                                                         Line 4478
  size_t len;                                                                   Line 4479
  bool pad;                                                                     Line 4480
                                                                                
  len = quote_name_buf (&buf, sizeof smallbuf, (char *) name, options,          Line 4482
                        needs_general_quoting, NULL, &pad);                     Line 4483
                                                                                
  if (pad && allow_pad)                                                         Line 4485
      DIRED_PUTCHAR (' ');                                                      Line 4486
                                                                                
  if (color)                                                                    Line 4488
    print_color_indicator (color);                                              Line 4489
                                                                                
  /* If we're padding, then don't include the outer quotes in                   
     the --hyperlink, to improve the alignment of those links.  */              
  bool skip_quotes = false;                                                     Line 4493
                                                                                
  if (absolute_name)                                                            Line 4495
    {                                                                           
      if (align_variable_outer_quotes && cwd_some_quoted && ! pad)              Line 4497
        {                                                                       
          skip_quotes = true;                                                   Line 4499
          putchar (*buf);                                                       Line 4500
        }                                                                       
      char *h = file_escape (hostname, /* path= */ false);                      Line 4502
      char *n = file_escape (absolute_name, /* path= */ true);                  Line 4503
      /* TODO: It would be good to be able to define parameters                 
         to give hints to the terminal as how best to render the URI.           
         For example since ls is outputting a dense block of URIs               
         it would be best to not underline by default, and only                 
         do so upon hover etc.  */                                              
      printf ("\033]8;;file://%s%s%s\a", h, *n == '/' ? "" : "/", n);           Line 4509
      free (h);                                                                 Line 4510
      free (n);                                                                 Line 4511
    }                                                                           
                                                                                
  if (stack)                                                                    Line 4514
    PUSH_CURRENT_DIRED_POS (stack);                                             Line 4515
                                                                                
  fwrite (buf + skip_quotes, 1, len - (skip_quotes * 2), stdout);               Line 4517...!syscalls auto-comment...
                                                                                
  dired_pos += len;                                                             Line 4519
                                                                                
  if (stack)                                                                    Line 4521
    PUSH_CURRENT_DIRED_POS (stack);                                             Line 4522
                                                                                
  if (absolute_name)                                                            Line 4524
    {                                                                           
      fputs ("\033]8;;\a", stdout);                                             Line 4526
      if (skip_quotes)                                                          Line 4527
        putchar (*(buf + len - 1));                                             Line 4528
    }                                                                           
                                                                                
  if (buf != smallbuf && buf != name)                                           Line 4531
    free (buf);                                                                 Line 4532
                                                                                
  return len + pad;                                                             Line 4534
}                                                                               Block 136
                                                                                
static size_t                                                                   Line 4537
print_name_with_quoting (const struct fileinfo *f,                              Line 4538
                         bool symlink_target,                                   Line 4539
                         struct obstack *stack,                                 Line 4540
                         size_t start_col)                                      Line 4541
{                                                                               
  const char* name = symlink_target ? f->linkname : f->name;                    Line 4543
                                                                                
  const struct bin_str *color = print_with_color ?                              Line 4545
                                get_color_indicator (f, symlink_target) : NULL; Line 4546
                                                                                
  bool used_color_this_time = (print_with_color                                 Line 4548
                               && (color || is_colored (C_NORM)));              Line 4549
                                                                                
  size_t len = quote_name (name, filename_quoting_options, f->quoted,           Line 4551
                           color, !symlink_target, stack, f->absolute_name);    Line 4552
                                                                                
  process_signals ();                                                           Line 4554
  if (used_color_this_time)                                                     Line 4555
    {                                                                           
      prep_non_filename_text ();                                                Line 4557
                                                                                
      /* We use the byte length rather than display width here as               
         an optimization to avoid accurately calculating the width,             
         because we only output the clear to EOL sequence if the name           
         _might_ wrap to the next line.  This may output a sequence             
         unnecessarily in multi-byte locales for example,                       
         but in that case it's inconsequential to the output.  */               
      if (line_length                                                           Line 4565
          && (start_col / line_length != (start_col + len - 1) / line_length))  Line 4566
        put_indicator (&color_indicator[C_CLR_TO_EOL]);                         Line 4567
    }                                                                           
                                                                                
  return len;                                                                   Line 4570
}                                                                               Block 137
                                                                                
static void                                                                     Line 4573
prep_non_filename_text (void)                                                   Line 4574
{                                                                               
  if (color_indicator[C_END].string != NULL)                                    Line 4576
    put_indicator (&color_indicator[C_END]);                                    Line 4577
  else                                                                          Line 4578
    {                                                                           
      put_indicator (&color_indicator[C_LEFT]);                                 Line 4580
      put_indicator (&color_indicator[C_RESET]);                                Line 4581
      put_indicator (&color_indicator[C_RIGHT]);                                Line 4582
    }                                                                           
}                                                                               Block 138
                                                                                
/* Print the file name of 'f' with appropriate quoting.                         
   Also print file size, inode number, and filetype indicator character,        
   as requested by switches.  */                                                
                                                                                
static size_t                                                                   Line 4590
print_file_name_and_frills (const struct fileinfo *f, size_t start_col)         Line 4591
{                                                                               
  char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];    Line 4593
                                                                                
  set_normal_color ();                                                          Line 4595
                                                                                
  if (print_inode)                                                              Line 4597
    printf ("%*s ", format == with_commas ? 0 : inode_number_width,             Line 4598
            format_inode (buf, sizeof buf, f));                                 Line 4599
                                                                                
  if (print_block_size)                                                         Line 4601
    printf ("%*s ", format == with_commas ? 0 : block_size_width,               Line 4602
            ! f->stat_ok ? "?"                                                  Line 4603
            : human_readable (ST_NBLOCKS (f->stat), buf, human_output_opts,     Line 4604
                              ST_NBLOCKSIZE, output_block_size));               Line 4605
                                                                                
  if (print_scontext)                                                           Line 4607
    printf ("%*s ", format == with_commas ? 0 : scontext_width, f->scontext);   Line 4608
                                                                                
  size_t width = print_name_with_quoting (f, false, NULL, start_col);           Line 4610
                                                                                
  if (indicator_style != none)                                                  Line 4612
    width += print_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);   Line 4613
                                                                                
  return width;                                                                 Line 4615
}                                                                               Block 139
                                                                                
/* Given these arguments describing a file, return the single-byte              
   type indicator, or 0.  */                                                    
static char                                                                     Line 4620
get_type_indicator (bool stat_ok, mode_t mode, enum filetype type)              Line 4621
{                                                                               
  char c;                                                                       Line 4623
                                                                                
  if (stat_ok ? S_ISREG (mode) : type == normal)                                Line 4625
    {                                                                           
      if (stat_ok && indicator_style == classify && (mode & S_IXUGO))           Line 4627
        c = '*';                                                                Line 4628
      else                                                                      Line 4629
        c = 0;                                                                  Line 4630
    }                                                                           
  else                                                                          Line 4632
    {                                                                           
      if (stat_ok ? S_ISDIR (mode) : type == directory || type == arg_directory)Line 4634
        c = '/';                                                                Line 4635
      else if (indicator_style == slash)                                        Line 4636
        c = 0;                                                                  Line 4637
      else if (stat_ok ? S_ISLNK (mode) : type == symbolic_link)                Line 4638
        c = '@';                                                                Line 4639
      else if (stat_ok ? S_ISFIFO (mode) : type == fifo)                        Line 4640
        c = '|';                                                                Line 4641
      else if (stat_ok ? S_ISSOCK (mode) : type == sock)                        Line 4642
        c = '=';                                                                Line 4643
      else if (stat_ok && S_ISDOOR (mode))                                      Line 4644
        c = '>';                                                                Line 4645
      else                                                                      Line 4646
        c = 0;                                                                  Line 4647
    }                                                                           
  return c;                                                                     Line 4649
}                                                                               Block 140
                                                                                
static bool                                                                     Line 4652
print_type_indicator (bool stat_ok, mode_t mode, enum filetype type)            Line 4653
{                                                                               
  char c = get_type_indicator (stat_ok, mode, type);                            Line 4655
  if (c)                                                                        Line 4656
    DIRED_PUTCHAR (c);                                                          Line 4657
  return !!c;                                                                   Line 4658
}                                                                               Block 141
                                                                                
/* Returns if color sequence was printed.  */                                   
static bool                                                                     Line 4662
print_color_indicator (const struct bin_str *ind)                               Line 4663
{                                                                               
  if (ind)                                                                      Line 4665
    {                                                                           
      /* Need to reset so not dealing with attribute combinations */            
      if (is_colored (C_NORM))                                                  Line 4668
        restore_default_color ();                                               Line 4669
      put_indicator (&color_indicator[C_LEFT]);                                 Line 4670
      put_indicator (ind);                                                      Line 4671
      put_indicator (&color_indicator[C_RIGHT]);                                Line 4672
    }                                                                           
                                                                                
  return ind != NULL;                                                           Line 4675
}                                                                               Block 142
                                                                                
/* Returns color indicator or NULL if none.  */                                 
static const struct bin_str* _GL_ATTRIBUTE_PURE                                 Line 4679
get_color_indicator (const struct fileinfo *f, bool symlink_target)             Line 4680
{                                                                               
  enum indicator_no type;                                                       Line 4682
  struct color_ext_type *ext; /* Color extension */                             Line 4683
  size_t len;   /* Length of name */                                            Line 4684
                                                                                
  const char* name;                                                             Line 4686
  mode_t mode;                                                                  Line 4687
  int linkok;                                                                   Line 4688
  if (symlink_target)                                                           Line 4689
    {                                                                           
      name = f->linkname;                                                       Line 4691
      mode = f->linkmode;                                                       Line 4692
      linkok = f->linkok ? 0 : -1;                                              Line 4693
    }                                                                           
  else                                                                          Line 4695
    {                                                                           
      name = f->name;                                                           Line 4697
      mode = FILE_OR_LINK_MODE (f);                                             Line 4698
      linkok = f->linkok;                                                       Line 4699
    }                                                                           
                                                                                
  /* Is this a nonexistent file?  If so, linkok == -1.  */                      
                                                                                
  if (linkok == -1 && is_colored (C_MISSING))                                   Line 4704
    type = C_MISSING;                                                           Line 4705
  else if (!f->stat_ok)                                                         Line 4706
    {                                                                           
      static enum indicator_no filetype_indicator[] = FILETYPE_INDICATORS;      Line 4708
      type = filetype_indicator[f->filetype];                                   Line 4709
    }                                                                           
  else                                                                          Line 4711
    {                                                                           
      if (S_ISREG (mode))                                                       Line 4713
        {                                                                       
          type = C_FILE;                                                        Line 4715
                                                                                
          if ((mode & S_ISUID) != 0 && is_colored (C_SETUID))                   Line 4717
            type = C_SETUID;                                                    Line 4718
          else if ((mode & S_ISGID) != 0 && is_colored (C_SETGID))              Line 4719
            type = C_SETGID;                                                    Line 4720
          else if (is_colored (C_CAP) && f->has_capability)                     Line 4721
            type = C_CAP;                                                       Line 4722
          else if ((mode & S_IXUGO) != 0 && is_colored (C_EXEC))                Line 4723
            type = C_EXEC;                                                      Line 4724
          else if ((1 < f->stat.st_nlink) && is_colored (C_MULTIHARDLINK))      Line 4725
            type = C_MULTIHARDLINK;                                             Line 4726
        }                                                                       
      else if (S_ISDIR (mode))                                                  Line 4728
        {                                                                       
          type = C_DIR;                                                         Line 4730
                                                                                
          if ((mode & S_ISVTX) && (mode & S_IWOTH)                              Line 4732
              && is_colored (C_STICKY_OTHER_WRITABLE))                          Line 4733
            type = C_STICKY_OTHER_WRITABLE;                                     Line 4734
          else if ((mode & S_IWOTH) != 0 && is_colored (C_OTHER_WRITABLE))      Line 4735
            type = C_OTHER_WRITABLE;                                            Line 4736
          else if ((mode & S_ISVTX) != 0 && is_colored (C_STICKY))              Line 4737
            type = C_STICKY;                                                    Line 4738
        }                                                                       
      else if (S_ISLNK (mode))                                                  Line 4740
        type = C_LINK;                                                          Line 4741
      else if (S_ISFIFO (mode))                                                 Line 4742
        type = C_FIFO;                                                          Line 4743
      else if (S_ISSOCK (mode))                                                 Line 4744
        type = C_SOCK;                                                          Line 4745
      else if (S_ISBLK (mode))                                                  Line 4746
        type = C_BLK;                                                           Line 4747
      else if (S_ISCHR (mode))                                                  Line 4748
        type = C_CHR;                                                           Line 4749
      else if (S_ISDOOR (mode))                                                 Line 4750
        type = C_DOOR;                                                          Line 4751
      else                                                                      Line 4752
        {                                                                       
          /* Classify a file of some other type as C_ORPHAN.  */                
          type = C_ORPHAN;                                                      Line 4755
        }                                                                       
    }                                                                           
                                                                                
  /* Check the file's suffix only if still classified as C_FILE.  */            
  ext = NULL;                                                                   Line 4760
  if (type == C_FILE)                                                           Line 4761
    {                                                                           
      /* Test if NAME has a recognized suffix.  */                              
                                                                                
      len = strlen (name);                                                      Line 4765
      name += len;  /* Pointer to final \0.  */                                 Line 4766
      for (ext = color_ext_list; ext != NULL; ext = ext->next)                  Line 4767
        {                                                                       
          if (ext->ext.len <= len                                               Line 4769
              && c_strncasecmp (name - ext->ext.len, ext->ext.string,           Line 4770
                                ext->ext.len) == 0)                             Line 4771
            break;                                                              Line 4772
        }                                                                       
    }                                                                           
                                                                                
  /* Adjust the color for orphaned symlinks.  */                                
  if (type == C_LINK && !linkok)                                                Line 4777
    {                                                                           
      if (color_symlink_as_referent || is_colored (C_ORPHAN))                   Line 4779
        type = C_ORPHAN;                                                        Line 4780
    }                                                                           
                                                                                
  const struct bin_str *const s                                                 Line 4783
    = ext ? &(ext->seq) : &color_indicator[type];                               Line 4784
                                                                                
  return s->string ? s : NULL;                                                  Line 4786
}                                                                               Block 143
                                                                                
/* Output a color indicator (which may contain nulls).  */                      
static void                                                                     Line 4790
put_indicator (const struct bin_str *ind)                                       Line 4791
{                                                                               
  if (! used_color)                                                             Line 4793
    {                                                                           
      used_color = true;                                                        Line 4795
                                                                                
      /* If the standard output is a controlling terminal, watch out            
         for signals, so that the colors can be restored to the                 
         default state if "ls" is suspended or interrupted.  */                 
                                                                                
      if (0 <= tcgetpgrp (STDOUT_FILENO))                                       Line 4801
        signal_init ();                                                         Line 4802
                                                                                
      prep_non_filename_text ();                                                Line 4804
    }                                                                           
                                                                                
  fwrite (ind->string, ind->len, 1, stdout);                                    Line 4807...!syscalls auto-comment...
}                                                                               Block 144
                                                                                
static size_t                                                                   Line 4810
length_of_file_name_and_frills (const struct fileinfo *f)                       Line 4811
{                                                                               
  size_t len = 0;                                                               Line 4813
  char buf[MAX (LONGEST_HUMAN_READABLE + 1, INT_BUFSIZE_BOUND (uintmax_t))];    Line 4814
                                                                                
  if (print_inode)                                                              Line 4816
    len += 1 + (format == with_commas                                           Line 4817
                ? strlen (umaxtostr (f->stat.st_ino, buf))                      Line 4818
                : inode_number_width);                                          Line 4819
                                                                                
  if (print_block_size)                                                         Line 4821
    len += 1 + (format == with_commas                                           Line 4822
                ? strlen (! f->stat_ok ? "?"                                    Line 4823
                          : human_readable (ST_NBLOCKS (f->stat), buf,          Line 4824
                                            human_output_opts, ST_NBLOCKSIZE,   Line 4825
                                            output_block_size))                 Line 4826
                : block_size_width);                                            Line 4827
                                                                                
  if (print_scontext)                                                           Line 4829
    len += 1 + (format == with_commas ? strlen (f->scontext) : scontext_width); Line 4830
                                                                                
  len += quote_name_width (f->name, filename_quoting_options, f->quoted);       Line 4832
                                                                                
  if (indicator_style != none)                                                  Line 4834
    {                                                                           
      char c = get_type_indicator (f->stat_ok, f->stat.st_mode, f->filetype);   Line 4836
      len += (c != 0);                                                          Line 4837
    }                                                                           
                                                                                
  return len;                                                                   Line 4840
}                                                                               Block 145
                                                                                
static void                                                                     Line 4843
print_many_per_line (void)                                                      Line 4844
{                                                                               
  size_t row;   /* Current row.  */                                             Line 4846
  size_t cols = calculate_columns (true);                                       Line 4847
  struct column_info const *line_fmt = &column_info[cols - 1];                  Line 4848
                                                                                
  /* Calculate the number of rows that will be in each column except possibly   
     for a short column on the right.  */                                       
  size_t rows = cwd_n_used / cols + (cwd_n_used % cols != 0);                   Line 4852
                                                                                
  for (row = 0; row < rows; row++)                                              Line 4854
    {                                                                           
      size_t col = 0;                                                           Line 4856
      size_t filesno = row;                                                     Line 4857
      size_t pos = 0;                                                           Line 4858
                                                                                
      /* Print the next row.  */                                                
      while (1)                                                                 Line 4861
        {                                                                       
          struct fileinfo const *f = sorted_file[filesno];                      Line 4863
          size_t name_length = length_of_file_name_and_frills (f);              Line 4864
          size_t max_name_length = line_fmt->col_arr[col++];                    Line 4865
          print_file_name_and_frills (f, pos);                                  Line 4866
                                                                                
          filesno += rows;                                                      Line 4868
          if (filesno >= cwd_n_used)                                            Line 4869
            break;                                                              Line 4870
                                                                                
          indent (pos + name_length, pos + max_name_length);                    Line 4872
          pos += max_name_length;                                               Line 4873
        }                                                                       
      putchar ('\n');                                                           Line 4875
    }                                                                           
}                                                                               Block 146
                                                                                
static void                                                                     Line 4879
print_horizontal (void)                                                         Line 4880
{                                                                               
  size_t filesno;                                                               Line 4882
  size_t pos = 0;                                                               Line 4883
  size_t cols = calculate_columns (false);                                      Line 4884
  struct column_info const *line_fmt = &column_info[cols - 1];                  Line 4885
  struct fileinfo const *f = sorted_file[0];                                    Line 4886
  size_t name_length = length_of_file_name_and_frills (f);                      Line 4887
  size_t max_name_length = line_fmt->col_arr[0];                                Line 4888
                                                                                
  /* Print first entry.  */                                                     
  print_file_name_and_frills (f, 0);                                            Line 4891
                                                                                
  /* Now the rest.  */                                                          
  for (filesno = 1; filesno < cwd_n_used; ++filesno)                            Line 4894
    {                                                                           
      size_t col = filesno % cols;                                              Line 4896
                                                                                
      if (col == 0)                                                             Line 4898
        {                                                                       
          putchar ('\n');                                                       Line 4900
          pos = 0;                                                              Line 4901
        }                                                                       
      else                                                                      Line 4903
        {                                                                       
          indent (pos + name_length, pos + max_name_length);                    Line 4905
          pos += max_name_length;                                               Line 4906
        }                                                                       
                                                                                
      f = sorted_file[filesno];                                                 Line 4909
      print_file_name_and_frills (f, pos);                                      Line 4910
                                                                                
      name_length = length_of_file_name_and_frills (f);                         Line 4912
      max_name_length = line_fmt->col_arr[col];                                 Line 4913
    }                                                                           
  putchar ('\n');                                                               Line 4915
}                                                                               Block 147
                                                                                
/* Output name + SEP + ' '.  */                                                 
                                                                                
static void                                                                     Line 4920
print_with_separator (char sep)                                                 Line 4921
{                                                                               
  size_t filesno;                                                               Line 4923
  size_t pos = 0;                                                               Line 4924
                                                                                
  for (filesno = 0; filesno < cwd_n_used; filesno++)                            Line 4926
    {                                                                           
      struct fileinfo const *f = sorted_file[filesno];                          Line 4928
      size_t len = line_length ? length_of_file_name_and_frills (f) : 0;        Line 4929
                                                                                
      if (filesno != 0)                                                         Line 4931
        {                                                                       
          char separator;                                                       Line 4933
                                                                                
          if (! line_length                                                     Line 4935
              || ((pos + len + 2 < line_length)                                 Line 4936
                  && (pos <= SIZE_MAX - len - 2)))                              Line 4937
            {                                                                   
              pos += 2;                                                         Line 4939
              separator = ' ';                                                  Line 4940
            }                                                                   
          else                                                                  Line 4942
            {                                                                   
              pos = 0;                                                          Line 4944
              separator = '\n';                                                 Line 4945
            }                                                                   
                                                                                
          putchar (sep);                                                        Line 4948
          putchar (separator);                                                  Line 4949
        }                                                                       
                                                                                
      print_file_name_and_frills (f, pos);                                      Line 4952
      pos += len;                                                               Line 4953
    }                                                                           
  putchar ('\n');                                                               Line 4955
}                                                                               Block 148
                                                                                
/* Assuming cursor is at position FROM, indent up to position TO.               
   Use a TAB character instead of two or more spaces whenever possible.  */     
                                                                                
static void                                                                     Line 4961
indent (size_t from, size_t to)                                                 Line 4962
{                                                                               
  while (from < to)                                                             Line 4964
    {                                                                           
      if (tabsize != 0 && to / tabsize > (from + 1) / tabsize)                  Line 4966
        {                                                                       
          putchar ('\t');                                                       Line 4968
          from += tabsize - from % tabsize;                                     Line 4969
        }                                                                       
      else                                                                      Line 4971
        {                                                                       
          putchar (' ');                                                        Line 4973
          from++;                                                               Line 4974
        }                                                                       
    }                                                                           
}                                                                               Block 149
                                                                                
/* Put DIRNAME/NAME into DEST, handling '.' and '/' properly.  */               
/* FIXME: maybe remove this function someday.  See about using a                
   non-malloc'ing version of file_name_concat.  */                              
                                                                                
static void                                                                     Line 4983
attach (char *dest, const char *dirname, const char *name)                      Line 4984
{                                                                               
  const char *dirnamep = dirname;                                               Line 4986
                                                                                
  /* Copy dirname if it is not ".".  */                                         
  if (dirname[0] != '.' || dirname[1] != 0)                                     Line 4989
    {                                                                           
      while (*dirnamep)                                                         Line 4991
        *dest++ = *dirnamep++;                                                  Line 4992
      /* Add '/' if 'dirname' doesn't already end with it.  */                  
      if (dirnamep > dirname && dirnamep[-1] != '/')                            Line 4994
        *dest++ = '/';                                                          Line 4995
    }                                                                           
  while (*name)                                                                 Line 4997
    *dest++ = *name++;                                                          Line 4998
  *dest = 0;                                                                    Line 4999
}                                                                               Block 150
                                                                                
/* Allocate enough column info suitable for the current number of               
   files and display columns, and initialize the info to represent the          
   narrowest possible columns.  */                                              
                                                                                
static void                                                                     Line 5006
init_column_info (void)                                                         Line 5007
{                                                                               
  size_t i;                                                                     Line 5009
  size_t max_cols = MIN (max_idx, cwd_n_used);                                  Line 5010
                                                                                
  /* Currently allocated columns in column_info.  */                            
  static size_t column_info_alloc;                                              Line 5013
                                                                                
  if (column_info_alloc < max_cols)                                             Line 5015
    {                                                                           
      size_t new_column_info_alloc;                                             Line 5017
      size_t *p;                                                                Line 5018
                                                                                
      if (max_cols < max_idx / 2)                                               Line 5020
        {                                                                       
          /* The number of columns is far less than the display width           
             allows.  Grow the allocation, but only so that it's                
             double the current requirements.  If the display is                
             extremely wide, this avoids allocating a lot of memory             
             that is never needed.  */                                          
          column_info = xnrealloc (column_info, max_cols,                       Line 5027
                                   2 * sizeof *column_info);                    Line 5028
          new_column_info_alloc = 2 * max_cols;                                 Line 5029
        }                                                                       
      else                                                                      Line 5031
        {                                                                       
          column_info = xnrealloc (column_info, max_idx, sizeof *column_info);  Line 5033
          new_column_info_alloc = max_idx;                                      Line 5034
        }                                                                       
                                                                                
      /* Allocate the new size_t objects by computing the triangle              
         formula n * (n + 1) / 2, except that we don't need to                  
         allocate the part of the triangle that we've already                   
         allocated.  Check for address arithmetic overflow.  */                 
      {                                                                         
        size_t column_info_growth = new_column_info_alloc - column_info_alloc;  Line 5042
        size_t s = column_info_alloc + 1 + new_column_info_alloc;               Line 5043
        size_t t = s * column_info_growth;                                      Line 5044
        if (s < new_column_info_alloc || t / column_info_growth != s)           Line 5045
          xalloc_die ();                                                        ...!common auto-comment...
        p = xnmalloc (t / 2, sizeof *p);                                        Line 5047
      }                                                                         
                                                                                
      /* Grow the triangle by parceling out the cells just allocated.  */       
      for (i = column_info_alloc; i < new_column_info_alloc; i++)               Line 5051
        {                                                                       
          column_info[i].col_arr = p;                                           Line 5053
          p += i + 1;                                                           Line 5054
        }                                                                       
                                                                                
      column_info_alloc = new_column_info_alloc;                                Line 5057
    }                                                                           
                                                                                
  for (i = 0; i < max_cols; ++i)                                                Line 5060
    {                                                                           
      size_t j;                                                                 Line 5062
                                                                                
      column_info[i].valid_len = true;                                          Line 5064
      column_info[i].line_len = (i + 1) * MIN_COLUMN_WIDTH;                     Line 5065
      for (j = 0; j <= i; ++j)                                                  Line 5066
        column_info[i].col_arr[j] = MIN_COLUMN_WIDTH;                           Line 5067
    }                                                                           
}                                                                               Block 151
                                                                                
/* Calculate the number of columns needed to represent the current set          
   of files in the current display width.  */                                   
                                                                                
static size_t                                                                   Line 5074
calculate_columns (bool by_columns)                                             Line 5075
{                                                                               
  size_t filesno;  /* Index into cwd_file.  */                                  Line 5077
  size_t cols;   /* Number of files across.  */                                 Line 5078
                                                                                
  /* Normally the maximum number of columns is determined by the                
     screen width.  But if few files are available this might limit it          
     as well.  */                                                               
  size_t max_cols = MIN (max_idx, cwd_n_used);                                  Line 5083
                                                                                
  init_column_info ();                                                          Line 5085
                                                                                
  /* Compute the maximum number of possible columns.  */                        
  for (filesno = 0; filesno < cwd_n_used; ++filesno)                            Line 5088
    {                                                                           
      struct fileinfo const *f = sorted_file[filesno];                          Line 5090
      size_t name_length = length_of_file_name_and_frills (f);                  Line 5091
                                                                                
      for (size_t i = 0; i < max_cols; ++i)                                     Line 5093
        {                                                                       
          if (column_info[i].valid_len)                                         Line 5095
            {                                                                   
              size_t idx = (by_columns                                          Line 5097
                            ? filesno / ((cwd_n_used + i) / (i + 1))            Line 5098
                            : filesno % (i + 1));                               Line 5099
              size_t real_length = name_length + (idx == i ? 0 : 2);            Line 5100
                                                                                
              if (column_info[i].col_arr[idx] < real_length)                    Line 5102
                {                                                               
                  column_info[i].line_len += (real_length                       Line 5104
                                              - column_info[i].col_arr[idx]);   Line 5105
                  column_info[i].col_arr[idx] = real_length;                    Line 5106
                  column_info[i].valid_len = (column_info[i].line_len           Line 5107
                                              < line_length);                   Line 5108
                }                                                               
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  /* Find maximum allowed columns.  */                                          
  for (cols = max_cols; 1 < cols; --cols)                                       Line 5115
    {                                                                           
      if (column_info[cols - 1].valid_len)                                      Line 5117
        break;                                                                  Line 5118
    }                                                                           
                                                                                
  return cols;                                                                  Line 5121
}                                                                               Block 152
                                                                                
void                                                                            Line 5124
usage (int status)                                                              Line 5125
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 5127
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 5129
    {                                                                           
      printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);            Line 5131
      fputs (_("\                                                               Line 5132
List information about the FILEs (the current directory by default).\n\         Line 5133
Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\    Line 5134
"), stdout);                                                                    Line 5135
                                                                                
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      fputs (_("\                                                               Line 5139
  -a, --all                  do not ignore entries starting with .\n\           Line 5140
  -A, --almost-all           do not list implied . and ..\n\                    Line 5141
      --author               with -l, print the author of each file\n\          Line 5142
  -b, --escape               print C-style escapes for nongraphic characters\n\ Line 5143
"), stdout);                                                                    Line 5144
      fputs (_("\                                                               Line 5145
      --block-size=SIZE      with -l, scale sizes by SIZE when printing them;\n\Line 5146
                               e.g., '--block-size=M'; see SIZE format below\n\ Line 5147
"), stdout);                                                                    Line 5148
      fputs (_("\                                                               Line 5149
  -B, --ignore-backups       do not list implied entries ending with ~\n\       Line 5150
  -c                         with -lt: sort by, and show, ctime (time of last\n\Line 5151
                               modification of file status information);\n\     Line 5152
                               with -l: show ctime and sort by name;\n\         Line 5153
                               otherwise: sort by ctime, newest first\n\        Line 5154
"), stdout);                                                                    Line 5155
      fputs (_("\                                                               Line 5156
  -C                         list entries by columns\n\                         Line 5157
      --color[=WHEN]         colorize the output; WHEN can be 'always' (default\Line 5158
\n\                                                                             
                               if omitted), 'auto', or 'never'; more info below\Line 5160
\n\                                                                             
  -d, --directory            list directories themselves, not their contents\n\ Line 5162
  -D, --dired                generate output designed for Emacs' dired mode\n\  Line 5163
"), stdout);                                                                    Line 5164
      fputs (_("\                                                               Line 5165
  -f                         do not sort, enable -aU, disable -ls --color\n\    Line 5166
  -F, --classify             append indicator (one of */=>@|) to entries\n\     
      --file-type            likewise, except do not append '*'\n\              Line 5168
      --format=WORD          across -x, commas -m, horizontal -x, long -l,\n\   Line 5169
                               single-column -1, verbose -l, vertical -C\n\     Line 5170
      --full-time            like -l --time-style=full-iso\n\                   Line 5171
"), stdout);                                                                    Line 5172
      fputs (_("\                                                               Line 5173
  -g                         like -l, but do not list owner\n\                  Line 5174
"), stdout);                                                                    Line 5175
      fputs (_("\                                                               Line 5176
      --group-directories-first\n\                                              Line 5177
                             group directories before files;\n\                 Line 5178
                               can be augmented with a --sort option, but any\n\Line 5179
                               use of --sort=none (-U) disables grouping\n\     Line 5180
"), stdout);                                                                    Line 5181
      fputs (_("\                                                               Line 5182
  -G, --no-group             in a long listing, don't print group names\n\      Line 5183
"), stdout);                                                                    Line 5184
      fputs (_("\                                                               Line 5185
  -h, --human-readable       with -l and -s, print sizes like 1K 234M 2G etc.\n\Line 5186
      --si                   likewise, but use powers of 1000 not 1024\n\       Line 5187
"), stdout);                                                                    Line 5188
      fputs (_("\                                                               Line 5189
  -H, --dereference-command-line\n\                                             Line 5190
                             follow symbolic links listed on the command line\n\Line 5191
      --dereference-command-line-symlink-to-dir\n\                              Line 5192
                             follow each command line symbolic link\n\          Line 5193
                               that points to a directory\n\                    Line 5194
      --hide=PATTERN         do not list implied entries matching shell PATTERN\Line 5195
\n\                                                                             
                               (overridden by -a or -A)\n\                      Line 5197
"), stdout);                                                                    Line 5198
      fputs (_("\                                                               Line 5199
      --hyperlink[=WHEN]     hyperlink file names; WHEN can be 'always'\n\      Line 5200
                               (default if omitted), 'auto', or 'never'\n\      Line 5201
"), stdout);                                                                    Line 5202
      fputs (_("\                                                               Line 5203
      --indicator-style=WORD  append indicator with style WORD to entry names:\ Line 5204
\n\                                                                             
                               none (default), slash (-p),\n\                   Line 5206
                               file-type (--file-type), classify (-F)\n\        Line 5207
  -i, --inode                print the index number of each file\n\             Line 5208
  -I, --ignore=PATTERN       do not list implied entries matching shell PATTERN\Line 5209
\n\                                                                             
"), stdout);                                                                    Line 5211
      fputs (_("\                                                               Line 5212
  -k, --kibibytes            default to 1024-byte blocks for disk usage;\n\     Line 5213
                               used only with -s and per directory totals\n\    Line 5214
"), stdout);                                                                    Line 5215
      fputs (_("\                                                               Line 5216
  -l                         use a long listing format\n\                       Line 5217
  -L, --dereference          when showing file information for a symbolic\n\    Line 5218
                               link, show information for the file the link\n\  Line 5219
                               references rather than for the link itself\n\    Line 5220
  -m                         fill width with a comma separated list of entries\ Line 5221
\n\                                                                             
"), stdout);                                                                    Line 5223
      fputs (_("\                                                               Line 5224
  -n, --numeric-uid-gid      like -l, but list numeric user and group IDs\n\    Line 5225
  -N, --literal              print entry names without quoting\n\               Line 5226
  -o                         like -l, but do not list group information\n\      Line 5227
  -p, --indicator-style=slash\n\                                                Line 5228
                             append / indicator to directories\n\               Line 5229
"), stdout);                                                                    Line 5230
      fputs (_("\                                                               Line 5231
  -q, --hide-control-chars   print ? instead of nongraphic characters\n\        Line 5232
      --show-control-chars   show nongraphic characters as-is (the default,\n\  Line 5233
                               unless program is 'ls' and output is a terminal)\Line 5234
\n\                                                                             
  -Q, --quote-name           enclose entry names in double quotes\n\            Line 5236
      --quoting-style=WORD   use quoting style WORD for entry names:\n\         Line 5237
                               literal, locale, shell, shell-always,\n\         Line 5238
                               shell-escape, shell-escape-always, c, escape\n\  Line 5239
                               (overrides QUOTING_STYLE environment variable)\n\Line 5240
"), stdout);                                                                    Line 5241
      fputs (_("\                                                               Line 5242
  -r, --reverse              reverse order while sorting\n\                     Line 5243
  -R, --recursive            list subdirectories recursively\n\                 Line 5244
  -s, --size                 print the allocated size of each file, in blocks\n\Line 5245
"), stdout);                                                                    Line 5246
      fputs (_("\                                                               Line 5247
  -S                         sort by file size, largest first\n\                Line 5248
      --sort=WORD            sort by WORD instead of name: none (-U), size (-S)\Line 5249
,\n\                                                                            Line 5250
                               time (-t), version (-v), extension (-X)\n\       Line 5251
      --time=WORD            with -l, show time as WORD instead of default\n\   Line 5252
                               modification time: atime or access or use (-u);\ Line 5253
\n\                                                                             
                               ctime or status (-c); also use specified time\n\ Line 5255
                               as sort key if --sort=time (newest first)\n\     Line 5256
"), stdout);                                                                    Line 5257
      fputs (_("\                                                               Line 5258
      --time-style=TIME_STYLE  time/date format with -l; see TIME_STYLE below\n\Line 5259
"), stdout);                                                                    Line 5260
      fputs (_("\                                                               Line 5261
  -t                         sort by modification time, newest first\n\         Line 5262
  -T, --tabsize=COLS         assume tab stops at each COLS instead of 8\n\      Line 5263
"), stdout);                                                                    Line 5264
      fputs (_("\                                                               Line 5265
  -u                         with -lt: sort by, and show, access time;\n\       Line 5266
                               with -l: show access time and sort by name;\n\   Line 5267
                               otherwise: sort by access time, newest first\n\  Line 5268
  -U                         do not sort; list entries in directory order\n\    Line 5269
  -v                         natural sort of (version) numbers within text\n\   Line 5270
"), stdout);                                                                    Line 5271
      fputs (_("\                                                               Line 5272
  -w, --width=COLS           set output width to COLS.  0 means no limit\n\     Line 5273
  -x                         list entries by lines instead of by columns\n\     Line 5274
  -X                         sort alphabetically by entry extension\n\          Line 5275
  -Z, --context              print any security context of each file\n\         Line 5276
  -1                         list one file per line.  Avoid '\\n' with -q or -b\Line 5277
\n\                                                                             
"), stdout);                                                                    Line 5279
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 5280
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 5281
      emit_size_note ();                                                        Line 5282
      fputs (_("\                                                               Line 5283
\n\                                                                             
The TIME_STYLE argument can be full-iso, long-iso, iso, locale, or +FORMAT.\n\  Line 5285
FORMAT is interpreted like in date(1).  If FORMAT is FORMAT1<newline>FORMAT2,\n\Line 5286
then FORMAT1 applies to non-recent files and FORMAT2 to recent files.\n\        Line 5287
TIME_STYLE prefixed with 'posix-' takes effect only outside the POSIX locale.\n\Line 5288
Also the TIME_STYLE environment variable sets the default style to use.\n\      Line 5289
"), stdout);                                                                    Line 5290
      fputs (_("\                                                               Line 5291
\n\                                                                             
Using color to distinguish file types is disabled both by default and\n\        Line 5293
with --color=never.  With --color=auto, ls emits color codes only when\n\       Line 5294
standard output is connected to a terminal.  The LS_COLORS environment\n\       Line 5295
variable can change the settings.  Use the dircolors command to set it.\n\      Line 5296
"), stdout);                                                                    Line 5297
      fputs (_("\                                                               Line 5298
\n\                                                                             
Exit status:\n\                                                                 Line 5300
 0  if OK,\n\                                                                   Line 5301
 1  if minor problems (e.g., cannot access subdirectory),\n\                    Line 5302
 2  if serious trouble (e.g., cannot access command-line argument).\n\          Line 5303
"), stdout);                                                                    Line 5304
      emit_ancillary_info (PROGRAM_NAME);                                       Line 5305
    }                                                                           
  exit (status);                                                                Line 5307
}                                                                               Block 153