/* df - summarize free disk space                                               This is the df utility
   Copyright (C) 1991-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
                                                                                
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.                             
   --human-readable option added by lm@sgi.com.                                 
   --si and large file support added by eggert@twinsun.com.  */                 
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <sys/types.h>                                                          Provides system data types
#include <getopt.h>                                                             ...!includes auto-comment...
#include <assert.h>                                                             ...!includes auto-comment...
#include <wchar.h>                                                              ...!includes auto-comment...
#include <wctype.h>                                                             ...!includes auto-comment...
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "canonicalize.h"                                                       ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "fsusage.h"                                                            ...!includes auto-comment...
#include "human.h"                                                              ...!includes auto-comment...
#include "mbsalign.h"                                                           ...!includes auto-comment...
#include "mbswidth.h"                                                           ...!includes auto-comment...
#include "mountlist.h"                                                          ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
#include "find-mount-point.h"                                                   ...!includes auto-comment...
#include "hash.h"                                                               ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "df"                                                       Line 43
                                                                                
#define AUTHORS \                                                               Line 45
  proper_name ("Torbjorn Granlund"), \                                          Line 46
  proper_name ("David MacKenzie"), \                                            Line 47
  proper_name ("Paul Eggert")                                                   Line 48
                                                                                
struct devlist                                                                  Line 50
{                                                                               
  dev_t dev_num;                                                                Line 52
  struct mount_entry *me;                                                       Line 53
  struct devlist *next;                                                         Line 54
};                                                                              Block 1
                                                                                
/* Filled with device numbers of examined file systems to avoid                 
   duplicates in output.  */                                                    
static Hash_table *devlist_table;                                               Line 59
                                                                                
/* If true, show even file systems with zero size or                            
   uninteresting types.  */                                                     
static bool show_all_fs;                                                        Line 63
                                                                                
/* If true, show only local file systems.  */                                   
static bool show_local_fs;                                                      Line 66
                                                                                
/* If true, output data for each file system corresponding to a                 
   command line argument -- even if it's a dummy (automounter) entry.  */       
static bool show_listed_fs;                                                     Line 70
                                                                                
/* Human-readable options for output.  */                                       
static int human_output_opts;                                                   Line 73
                                                                                
/* The units to use when printing sizes.  */                                    
static uintmax_t output_block_size;                                             Line 76
                                                                                
/* True if a file system has been processed for output.  */                     
static bool file_systems_processed;                                             Line 79
                                                                                
/* If true, invoke the 'sync' system call before getting any usage data.        
   Using this option can make df very slow, especially with many or very        
   busy disks.  Note that this may make a difference on some systems --         
   SunOS 4.1.3, for one.  It is *not* necessary on GNU/Linux.  */               
static bool require_sync;                                                       Line 85
                                                                                
/* Desired exit status.  */                                                     
static int exit_status;                                                         Line 88
                                                                                
/* A file system type to display.  */                                           
                                                                                
struct fs_type_list                                                             Line 92
{                                                                               
  char *fs_name;                                                                Line 94
  struct fs_type_list *fs_next;                                                 Line 95
};                                                                              Block 2
                                                                                
/* Linked list of file system types to display.                                 
   If 'fs_select_list' is NULL, list all types.                                 
   This table is generated dynamically from command-line options,               
   rather than hardcoding into the program what it thinks are the               
   valid file system types; let the user specify any file system type           
   they want to, and if there are any file systems of that type, they           
   will be shown.                                                               
                                                                                
   Some file system types:                                                      
   4.2 4.3 ufs nfs swap ignore io vm efs dbg */                                 
                                                                                
static struct fs_type_list *fs_select_list;                                     Line 109
                                                                                
/* Linked list of file system types to omit.                                    
   If the list is empty, don't exclude any types.  */                           
                                                                                
static struct fs_type_list *fs_exclude_list;                                    Line 114
                                                                                
/* Linked list of mounted file systems.  */                                     
static struct mount_entry *mount_list;                                          Line 117
                                                                                
/* If true, print file system type as well.  */                                 
static bool print_type;                                                         Line 120
                                                                                
/* If true, print a grand total at the end.  */                                 
static bool print_grand_total;                                                  Line 123
                                                                                
/* Grand total data.  */                                                        
static struct fs_usage grand_fsu;                                               Line 126
                                                                                
/* Display modes.  */                                                           
enum                                                                            Line 129
{                                                                               
  DEFAULT_MODE,                                                                 Line 131
  INODES_MODE,                                                                  Line 132
  HUMAN_MODE,                                                                   Line 133
  POSIX_MODE,                                                                   Line 134
  OUTPUT_MODE                                                                   Line 135
};                                                                              Block 3
static int header_mode = DEFAULT_MODE;                                          Line 137
                                                                                
/* Displayable fields.  */                                                      
typedef enum                                                                    Line 140
{                                                                               
  SOURCE_FIELD, /* file system */                                               Line 142
  FSTYPE_FIELD, /* FS type */                                                   Line 143
  SIZE_FIELD,   /* FS size */                                                   Line 144
  USED_FIELD,   /* FS size used  */                                             Line 145
  AVAIL_FIELD,  /* FS size available */                                         Line 146
  PCENT_FIELD,  /* percent used */                                              Line 147
  ITOTAL_FIELD, /* inode total */                                               Line 148
  IUSED_FIELD,  /* inodes used */                                               Line 149
  IAVAIL_FIELD, /* inodes available */                                          Line 150
  IPCENT_FIELD, /* inodes used in percent */                                    Line 151
  TARGET_FIELD, /* mount point */                                               Line 152
  FILE_FIELD,   /* specified file name */                                       Line 153
  INVALID_FIELD /* validation marker */                                         Line 154
} display_field_t;                                                              Line 155Block 4
                                                                                
/* Flag if a field contains a block, an inode or another value.  */             
typedef enum                                                                    Line 158
{                                                                               
  BLOCK_FLD, /* Block values field */                                           Line 160
  INODE_FLD, /* Inode values field */                                           Line 161
  OTHER_FLD  /* Neutral field, e.g. target */                                   Line 162
} field_type_t;                                                                 Line 163Block 5
                                                                                
/* Attributes of a display field.  */                                           
struct field_data_t                                                             Line 166
{                                                                               
  display_field_t field;                                                        Line 168
  char const *arg;                                                              Line 169
  field_type_t field_type;                                                      Line 170
  const char *caption;/* NULL means to use the default header of this field.  */Line 171
  size_t width;       /* Auto adjusted (up) widths used to align columns.  */   Line 172
  mbs_align_t align;  /* Alignment for this field.  */                          Line 173
  bool used;                                                                    Line 174
};                                                                              Block 6
                                                                                
/* Header strings, minimum width and alignment for the above fields.  */        
static struct field_data_t field_data[] = {                                     Line 178
  [SOURCE_FIELD] = { SOURCE_FIELD,                                              Line 179
    "source", OTHER_FLD, N_("Filesystem"), 14, MBS_ALIGN_LEFT,  false },        Line 180
                                                                                
  [FSTYPE_FIELD] = { FSTYPE_FIELD,                                              Line 182
    "fstype", OTHER_FLD, N_("Type"),        4, MBS_ALIGN_LEFT,  false },        Line 183
                                                                                
  [SIZE_FIELD] = { SIZE_FIELD,                                                  Line 185
    "size",   BLOCK_FLD, N_("blocks"),      5, MBS_ALIGN_RIGHT, false },        Line 186
                                                                                
  [USED_FIELD] = { USED_FIELD,                                                  Line 188
    "used",   BLOCK_FLD, N_("Used"),        5, MBS_ALIGN_RIGHT, false },        Line 189
                                                                                
  [AVAIL_FIELD] = { AVAIL_FIELD,                                                Line 191
    "avail",  BLOCK_FLD, N_("Available"),   5, MBS_ALIGN_RIGHT, false },        Line 192
                                                                                
  [PCENT_FIELD] = { PCENT_FIELD,                                                Line 194
    "pcent",  BLOCK_FLD, N_("Use%"),        4, MBS_ALIGN_RIGHT, false },        Line 195
                                                                                
  [ITOTAL_FIELD] = { ITOTAL_FIELD,                                              Line 197
    "itotal", INODE_FLD, N_("Inodes"),      5, MBS_ALIGN_RIGHT, false },        Line 198
                                                                                
  [IUSED_FIELD] = { IUSED_FIELD,                                                Line 200
    "iused",  INODE_FLD, N_("IUsed"),       5, MBS_ALIGN_RIGHT, false },        Line 201
                                                                                
  [IAVAIL_FIELD] = { IAVAIL_FIELD,                                              Line 203
    "iavail", INODE_FLD, N_("IFree"),       5, MBS_ALIGN_RIGHT, false },        Line 204
                                                                                
  [IPCENT_FIELD] = { IPCENT_FIELD,                                              Line 206
    "ipcent", INODE_FLD, N_("IUse%"),       4, MBS_ALIGN_RIGHT, false },        Line 207
                                                                                
  [TARGET_FIELD] = { TARGET_FIELD,                                              Line 209
    "target", OTHER_FLD, N_("Mounted on"),  0, MBS_ALIGN_LEFT,  false },        Line 210
                                                                                
  [FILE_FIELD] = { FILE_FIELD,                                                  Line 212
    "file",   OTHER_FLD, N_("File"),        0, MBS_ALIGN_LEFT,  false }         Line 213
};                                                                              Block 7
                                                                                
static char const *all_args_string =                                            Line 216
  "source,fstype,itotal,iused,iavail,ipcent,size,"                              Line 217
  "used,avail,pcent,file,target";                                               Line 218
                                                                                
/* Storage for the definition of output columns.  */                            
static struct field_data_t **columns;                                           Line 221
                                                                                
/* The current number of output columns.  */                                    
static size_t ncolumns;                                                         Line 224
                                                                                
/* Field values.  */                                                            
struct field_values_t                                                           Line 227
{                                                                               
  uintmax_t input_units;                                                        Line 229
  uintmax_t output_units;                                                       Line 230
  uintmax_t total;                                                              Line 231
  uintmax_t available;                                                          Line 232
  bool negate_available;                                                        Line 233
  uintmax_t available_to_root;                                                  Line 234
  uintmax_t used;                                                               Line 235
  bool negate_used;                                                             Line 236
};                                                                              Block 8
                                                                                
/* Storage for pointers for each string (cell of table).  */                    
static char ***table;                                                           Line 240
                                                                                
/* The current number of processed rows (including header).  */                 
static size_t nrows;                                                            Line 243
                                                                                
/* 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 247
{                                                                               
  NO_SYNC_OPTION = CHAR_MAX + 1,                                                Line 249
  SYNC_OPTION,                                                                  Line 250
  TOTAL_OPTION,                                                                 Line 251
  OUTPUT_OPTION                                                                 Line 252
};                                                                              Block 9
                                                                                
static struct option const long_options[] =                                     Line 255
{                                                                               
  {"all", no_argument, NULL, 'a'},                                              Line 257
  {"block-size", required_argument, NULL, 'B'},                                 Line 258
  {"inodes", no_argument, NULL, 'i'},                                           Line 259
  {"human-readable", no_argument, NULL, 'h'},                                   Line 260
  {"si", no_argument, NULL, 'H'},                                               Line 261
  {"local", no_argument, NULL, 'l'},                                            Line 262
  {"output", optional_argument, NULL, OUTPUT_OPTION},                           Line 263
  {"portability", no_argument, NULL, 'P'},                                      Line 264
  {"print-type", no_argument, NULL, 'T'},                                       Line 265
  {"sync", no_argument, NULL, SYNC_OPTION},                                     Line 266
  {"no-sync", no_argument, NULL, NO_SYNC_OPTION},                               Line 267
  {"total", no_argument, NULL, TOTAL_OPTION},                                   Line 268
  {"type", required_argument, NULL, 't'},                                       Line 269
  {"exclude-type", required_argument, NULL, 'x'},                               Line 270
  {GETOPT_HELP_OPTION_DECL},                                                    Line 271
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 272
  {NULL, 0, NULL, 0}                                                            Line 273
};                                                                              Block 10
                                                                                
/* Replace problematic chars with '?'.  */                                      
                                                                                
static void                                                                     Line 278
hide_problematic_chars (char *cell)                                             Line 279
{                                                                               
  char *srcend = cell + strlen (cell);                                          Line 281
  char *dst = cell;                                                             Line 282
  mbstate_t mbstate = { 0, };                                                   Line 283
  size_t n;                                                                     Line 284
                                                                                
  for (char *src = cell; src != srcend; src += n)                               Line 286
    {                                                                           
      wchar_t wc;                                                               Line 288
      size_t srcbytes = srcend - src;                                           Line 289
      n = mbrtowc (&wc, src, srcbytes, &mbstate);                               Line 290
      bool ok = n <= srcbytes;                                                  Line 291
                                                                                
      if (ok)                                                                   Line 293
        ok = !iswcntrl (wc);                                                    Line 294
      else                                                                      Line 295
        n = 1;                                                                  Line 296
                                                                                
      if (ok)                                                                   Line 298
        {                                                                       
          memmove (dst, src, n);                                                Line 300
          dst += n;                                                             Line 301
        }                                                                       
      else                                                                      Line 303
        {                                                                       
          *dst++ = '?';                                                         Line 305
          memset (&mbstate, 0, sizeof mbstate);                                 Line 306
        }                                                                       
    }                                                                           
                                                                                
  *dst = '\0';                                                                  Line 310
}                                                                               Block 11
                                                                                
/* Dynamically allocate a row of pointers in TABLE, which                       
   can then be accessed with standard 2D array notation.  */                    
                                                                                
static void                                                                     Line 316
alloc_table_row (void)                                                          Line 317
{                                                                               
  nrows++;                                                                      Line 319
  table = xnrealloc (table, nrows, sizeof (char **));                           Line 320
  table[nrows - 1] = xnmalloc (ncolumns, sizeof (char *));                      Line 321
}                                                                               Block 12
                                                                                
/* Output each cell in the table, accounting for the                            
   alignment and max width of each column.  */                                  
                                                                                
static void                                                                     Line 327
print_table (void)                                                              Line 328
{                                                                               
  size_t row;                                                                   Line 330
                                                                                
  for (row = 0; row < nrows; row++)                                             Line 332
    {                                                                           
      size_t col;                                                               Line 334
      for (col = 0; col < ncolumns; col++)                                      Line 335
        {                                                                       
          char *cell = table[row][col];                                         Line 337
                                                                                
          /* Note the SOURCE_FIELD used to be displayed on it's own line        
             if (!posix_format && mbswidth (cell) > 20), but that               
             functionality was probably more problematic than helpful,          
             hence changed in commit v8.10-40-g99679ff.  */                     
          if (col != 0)                                                         Line 343
            putchar (' ');                                                      Line 344
                                                                                
          int flags = 0;                                                        Line 346
          if (col == ncolumns - 1) /* The last one.  */                         Line 347
            flags = MBA_NO_RIGHT_PAD;                                           Line 348
                                                                                
          size_t width = columns[col]->width;                                   Line 350
          cell = ambsalign (cell, &width, columns[col]->align, flags);          Line 351
          /* When ambsalign fails, output unaligned data.  */                   
          fputs (cell ? cell : table[row][col], stdout);                        Line 353
          free (cell);                                                          Line 354
                                                                                
          IF_LINT (free (table[row][col]));                                     Line 356
        }                                                                       
      putchar ('\n');                                                           Line 358
      IF_LINT (free (table[row]));                                              Line 359
    }                                                                           
                                                                                
  IF_LINT (free (table));                                                       Line 362
}                                                                               Block 13
                                                                                
/* Dynamically allocate a struct field_t in COLUMNS, which                      
   can then be accessed with standard array notation.  */                       
                                                                                
static void                                                                     Line 368
alloc_field (int f, const char *c)                                              Line 369
{                                                                               
  ncolumns++;                                                                   Line 371
  columns = xnrealloc (columns, ncolumns, sizeof (struct field_data_t *));      Line 372
  columns[ncolumns - 1] = &field_data[f];                                       Line 373
  if (c != NULL)                                                                Line 374
    columns[ncolumns - 1]->caption = c;                                         Line 375
                                                                                
  if (field_data[f].used)                                                       Line 377
    assert (!"field used");                                                     Line 378
                                                                                
  /* Mark field as used.  */                                                    
  field_data[f].used = true;                                                    Line 381
}                                                                               Block 14
                                                                                
                                                                                
/* Given a string, ARG, containing a comma-separated list of arguments          
   to the --output option, add the appropriate fields to columns.  */           
static void                                                                     Line 387
decode_output_arg (char const *arg)                                             Line 388
{                                                                               
  char *arg_writable = xstrdup (arg);                                           Line 390
  char *s = arg_writable;                                                       Line 391
  do                                                                            
    {                                                                           
      /* find next comma */                                                     
      char *comma = strchr (s, ',');                                            Line 395
                                                                                
      /* If we found a comma, put a NUL in its place and advance.  */           
      if (comma)                                                                Line 398
        *comma++ = 0;                                                           Line 399
                                                                                
      /* process S.  */                                                         
      display_field_t field = INVALID_FIELD;                                    Line 402
      for (unsigned int i = 0; i < ARRAY_CARDINALITY (field_data); i++)         Line 403
        {                                                                       
          if (STREQ (field_data[i].arg, s))                                     Line 405
            {                                                                   
              field = i;                                                        Line 407
              break;                                                            Line 408
            }                                                                   
        }                                                                       
      if (field == INVALID_FIELD)                                               Line 411
        {                                                                       
          error (0, 0, _("option --output: field %s unknown"), quote (s));      Line 413
          usage (EXIT_FAILURE);                                                 Line 414
        }                                                                       
                                                                                
      if (field_data[field].used)                                               Line 417
        {                                                                       
          /* Prevent the fields from being used more than once.  */             
          error (0, 0, _("option --output: field %s used more than once"),      Line 420
                 quote (field_data[field].arg));                                Line 421
          usage (EXIT_FAILURE);                                                 Line 422
        }                                                                       
                                                                                
      switch (field)                                                            Line 425
        {                                                                       
        case SOURCE_FIELD:                                                      Line 427
        case FSTYPE_FIELD:                                                      Line 428
        case USED_FIELD:                                                        Line 429
        case PCENT_FIELD:                                                       Line 430
        case ITOTAL_FIELD:                                                      Line 431
        case IUSED_FIELD:                                                       Line 432
        case IAVAIL_FIELD:                                                      Line 433
        case IPCENT_FIELD:                                                      Line 434
        case TARGET_FIELD:                                                      Line 435
        case FILE_FIELD:                                                        Line 436
          alloc_field (field, NULL);                                            Line 437
          break;                                                                Line 438
                                                                                
        case SIZE_FIELD:                                                        Line 440
          alloc_field (field, N_("Size"));                                      Line 441
          break;                                                                Line 442
                                                                                
        case AVAIL_FIELD:                                                       Line 444
          alloc_field (field, N_("Avail"));                                     Line 445
          break;                                                                Line 446
                                                                                
        default:                                                                Line 448
          assert (!"invalid field");                                            Line 449
        }                                                                       
      s = comma;                                                                Line 451
    }                                                                           
  while (s);                                                                    Line 453
                                                                                
  free (arg_writable);                                                          Line 455
}                                                                               Block 15
                                                                                
/* Get the appropriate columns for the mode.  */                                
static void                                                                     Line 459
get_field_list (void)                                                           Line 460
{                                                                               
  switch (header_mode)                                                          Line 462
    {                                                                           
    case DEFAULT_MODE:                                                          Line 464
      alloc_field (SOURCE_FIELD, NULL);                                         Line 465
      if (print_type)                                                           Line 466
        alloc_field (FSTYPE_FIELD, NULL);                                       Line 467
      alloc_field (SIZE_FIELD,   NULL);                                         Line 468
      alloc_field (USED_FIELD,   NULL);                                         Line 469
      alloc_field (AVAIL_FIELD,  NULL);                                         Line 470
      alloc_field (PCENT_FIELD,  NULL);                                         Line 471
      alloc_field (TARGET_FIELD, NULL);                                         Line 472
      break;                                                                    Line 473
                                                                                
    case HUMAN_MODE:                                                            Line 475
      alloc_field (SOURCE_FIELD, NULL);                                         Line 476
      if (print_type)                                                           Line 477
        alloc_field (FSTYPE_FIELD, NULL);                                       Line 478
                                                                                
      alloc_field (SIZE_FIELD,   N_("Size"));                                   Line 480
      alloc_field (USED_FIELD,   NULL);                                         Line 481
      alloc_field (AVAIL_FIELD,  N_("Avail"));                                  Line 482
      alloc_field (PCENT_FIELD,  NULL);                                         Line 483
      alloc_field (TARGET_FIELD, NULL);                                         Line 484
      break;                                                                    Line 485
                                                                                
    case INODES_MODE:                                                           Line 487
      alloc_field (SOURCE_FIELD, NULL);                                         Line 488
      if (print_type)                                                           Line 489
        alloc_field (FSTYPE_FIELD, NULL);                                       Line 490
      alloc_field (ITOTAL_FIELD,  NULL);                                        Line 491
      alloc_field (IUSED_FIELD,   NULL);                                        Line 492
      alloc_field (IAVAIL_FIELD,  NULL);                                        Line 493
      alloc_field (IPCENT_FIELD,  NULL);                                        Line 494
      alloc_field (TARGET_FIELD,  NULL);                                        Line 495
      break;                                                                    Line 496
                                                                                
    case POSIX_MODE:                                                            Line 498
      alloc_field (SOURCE_FIELD, NULL);                                         Line 499
      if (print_type)                                                           Line 500
        alloc_field (FSTYPE_FIELD, NULL);                                       Line 501
      alloc_field (SIZE_FIELD,   NULL);                                         Line 502
      alloc_field (USED_FIELD,   NULL);                                         Line 503
      alloc_field (AVAIL_FIELD,  NULL);                                         Line 504
      alloc_field (PCENT_FIELD,  N_("Capacity"));                               Line 505
      alloc_field (TARGET_FIELD, NULL);                                         Line 506
      break;                                                                    Line 507
                                                                                
    case OUTPUT_MODE:                                                           Line 509
      if (!ncolumns)                                                            Line 510
        {                                                                       
          /* Add all fields if --output was given without a field list.  */     
          decode_output_arg (all_args_string);                                  Line 513
        }                                                                       
      break;                                                                    Line 515
                                                                                
    default:                                                                    Line 517
      assert (!"invalid header_mode");                                          Line 518
    }                                                                           
}                                                                               Block 16
                                                                                
/* Obtain the appropriate header entries.  */                                   
                                                                                
static void                                                                     Line 524
get_header (void)                                                               Line 525
{                                                                               
  size_t col;                                                                   Line 527
                                                                                
  alloc_table_row ();                                                           Line 529
                                                                                
  for (col = 0; col < ncolumns; col++)                                          Line 531
    {                                                                           
      char *cell = NULL;                                                        Line 533
      char const *header = _(columns[col]->caption);                            Line 534
                                                                                
      if (columns[col]->field == SIZE_FIELD                                     Line 536
          && (header_mode == DEFAULT_MODE                                       Line 537
              || (header_mode == OUTPUT_MODE                                    Line 538
                  && !(human_output_opts & human_autoscale))))                  Line 539
        {                                                                       
          char buf[LONGEST_HUMAN_READABLE + 1];                                 Line 541
                                                                                
          int opts = (human_suppress_point_zero                                 Line 543
                      | human_autoscale | human_SI                              Line 544
                      | (human_output_opts                                      Line 545
                         & (human_group_digits | human_base_1024 | human_B)));  Line 546
                                                                                
          /* Prefer the base that makes the human-readable value more exact,    
             if there is a difference.  */                                      
                                                                                
          uintmax_t q1000 = output_block_size;                                  Line 551
          uintmax_t q1024 = output_block_size;                                  Line 552
          bool divisible_by_1000;                                               Line 553
          bool divisible_by_1024;                                               Line 554
                                                                                
          do                                                                    
            {                                                                   
              divisible_by_1000 = q1000 % 1000 == 0;  q1000 /= 1000;            Line 558
              divisible_by_1024 = q1024 % 1024 == 0;  q1024 /= 1024;            Line 559
            }                                                                   
          while (divisible_by_1000 & divisible_by_1024);                        Line 561
                                                                                
          if (divisible_by_1000 < divisible_by_1024)                            Line 563
            opts |= human_base_1024;                                            Line 564
          if (divisible_by_1024 < divisible_by_1000)                            Line 565
            opts &= ~human_base_1024;                                           Line 566
          if (! (opts & human_base_1024))                                       Line 567
            opts |= human_B;                                                    Line 568
                                                                                
          char *num = human_readable (output_block_size, buf, opts, 1, 1);      Line 570
                                                                                
          /* Reset the header back to the default in OUTPUT_MODE.  */           
          header = _("blocks");                                                 Line 573
                                                                                
          /* TRANSLATORS: this is the "1K-blocks" header in "df" output.  */    
          if (asprintf (&cell, _("%s-%s"), num, header) == -1)                  Line 576
            cell = NULL;                                                        Line 577
        }                                                                       
      else if (header_mode == POSIX_MODE && columns[col]->field == SIZE_FIELD)  Line 579
        {                                                                       
          char buf[INT_BUFSIZE_BOUND (uintmax_t)];                              Line 581
          char *num = umaxtostr (output_block_size, buf);                       Line 582
                                                                                
          /* TRANSLATORS: this is the "1024-blocks" header in "df -P".  */      
          if (asprintf (&cell, _("%s-%s"), num, header) == -1)                  Line 585
            cell = NULL;                                                        Line 586
        }                                                                       
      else                                                                      Line 588
        cell = strdup (header);                                                 Line 589
                                                                                
      if (!cell)                                                                Line 591
        xalloc_die ();                                                          ...!common auto-comment...
                                                                                
      hide_problematic_chars (cell);                                            Line 594
                                                                                
      table[nrows - 1][col] = cell;                                             Line 596
                                                                                
      size_t cell_width = mbswidth (cell, 0);                                   Line 598
      columns[col]->width = MAX (columns[col]->width, cell_width);              Line 599
    }                                                                           
}                                                                               Block 17
                                                                                
/* Is FSTYPE a type of file system that should be listed?  */                   
                                                                                
static bool _GL_ATTRIBUTE_PURE                                                  Line 605
selected_fstype (const char *fstype)                                            Line 606
{                                                                               
  const struct fs_type_list *fsp;                                               Line 608
                                                                                
  if (fs_select_list == NULL || fstype == NULL)                                 Line 610
    return true;                                                                Line 611
  for (fsp = fs_select_list; fsp; fsp = fsp->fs_next)                           Line 612
    if (STREQ (fstype, fsp->fs_name))                                           Line 613
      return true;                                                              Line 614
  return false;                                                                 Line 615
}                                                                               Block 18
                                                                                
/* Is FSTYPE a type of file system that should be omitted?  */                  
                                                                                
static bool _GL_ATTRIBUTE_PURE                                                  Line 620
excluded_fstype (const char *fstype)                                            Line 621
{                                                                               
  const struct fs_type_list *fsp;                                               Line 623
                                                                                
  if (fs_exclude_list == NULL || fstype == NULL)                                Line 625
    return false;                                                               Line 626
  for (fsp = fs_exclude_list; fsp; fsp = fsp->fs_next)                          Line 627
    if (STREQ (fstype, fsp->fs_name))                                           Line 628
      return true;                                                              Line 629
  return false;                                                                 Line 630
}                                                                               Block 19
                                                                                
static size_t                                                                   Line 633
devlist_hash (void const *x, size_t table_size)                                 Line 634
{                                                                               
  struct devlist const *p = x;                                                  Line 636
  return (uintmax_t) p->dev_num % table_size;                                   Line 637
}                                                                               Block 20
                                                                                
static bool                                                                     Line 640
devlist_compare (void const *x, void const *y)                                  Line 641
{                                                                               
  struct devlist const *a = x;                                                  Line 643
  struct devlist const *b = y;                                                  Line 644
  return a->dev_num == b->dev_num;                                              Line 645
}                                                                               Block 21
                                                                                
static struct devlist *                                                         Line 648
devlist_for_dev (dev_t dev)                                                     Line 649
{                                                                               
  if (devlist_table == NULL)                                                    Line 651
    return NULL;                                                                Line 652
  struct devlist dev_entry;                                                     Line 653
  dev_entry.dev_num = dev;                                                      Line 654
  return hash_lookup (devlist_table, &dev_entry);                               Line 655
}                                                                               Block 22
                                                                                
static void                                                                     Line 658
devlist_free (void *p)                                                          Line 659
{                                                                               
  free (p);                                                                     Line 661
}                                                                               Block 23
                                                                                
/* Filter mount list by skipping duplicate entries.                             
   In the case of duplicates - based on the device number - the mount entry     
   with a '/' in its me_devname (i.e., not pseudo name like tmpfs) wins.        
   If both have a real devname (e.g. bind mounts), then that with the shorter   
   me_mountdir wins.  With DEVICES_ONLY == true (set with df -a), only update   
   the global devlist_table, rather than filtering the global mount_list.  */   
                                                                                
static void                                                                     Line 671
filter_mount_list (bool devices_only)                                           Line 672
{                                                                               
  struct mount_entry *me;                                                       Line 674
                                                                                
  /* Temporary list to keep entries ordered.  */                                
  struct devlist *device_list = NULL;                                           Line 677
  int mount_list_size = 0;                                                      Line 678
                                                                                
  for (me = mount_list; me; me = me->me_next)                                   Line 680
    mount_list_size++;                                                          Line 681
                                                                                
  devlist_table = hash_initialize (mount_list_size, NULL,                       Line 683
                                 devlist_hash,                                  Line 684
                                 devlist_compare,                               Line 685
                                 devlist_free);                                 Line 686
  if (devlist_table == NULL)                                                    Line 687
    xalloc_die ();                                                              ...!common auto-comment...
                                                                                
  /* Sort all 'wanted' entries into the list device_list.  */                   
  for (me = mount_list; me;)                                                    Line 691
    {                                                                           
      struct stat buf;                                                          Line 693
      struct mount_entry *discard_me = NULL;                                    Line 694
                                                                                
      /* Avoid stating remote file systems as that may hang.                    
         On Linux we probably have me_dev populated from /proc/self/mountinfo,  
         however we still stat() in case another device was mounted later.  */  
      if ((me->me_remote && show_local_fs)                                      Line 699
          || (me->me_dummy && !show_all_fs && !show_listed_fs)                  Line 700
          || (!selected_fstype (me->me_type) || excluded_fstype (me->me_type))  Line 701
          || -1 == stat (me->me_mountdir, &buf))                                Line 702...!syscalls auto-comment...
        {                                                                       
          /* If remote, and showing just local, or FS type is excluded,         
             add ME for filtering later.                                        
             If stat failed; add ME to be able to complain about it later.  */  
          buf.st_dev = me->me_dev;                                              Line 707
        }                                                                       
      else                                                                      Line 709
        {                                                                       
          /* If we've already seen this device...  */                           
          struct devlist *seen_dev = devlist_for_dev (buf.st_dev);              Line 712
                                                                                
          if (seen_dev)                                                         Line 714
            {                                                                   
              bool target_nearer_root = strlen (seen_dev->me->me_mountdir)      Line 716
                                        > strlen (me->me_mountdir);             Line 717
              /* With bind mounts, prefer items nearer the root of the source */
              bool source_below_root = seen_dev->me->me_mntroot != NULL         Line 719
                                       && me->me_mntroot != NULL                Line 720
                                       && (strlen (seen_dev->me->me_mntroot)    Line 721
                                           < strlen (me->me_mntroot));          Line 722
              if (! print_grand_total                                           Line 723
                  && me->me_remote && seen_dev->me->me_remote                   Line 724
                  && ! STREQ (seen_dev->me->me_devname, me->me_devname))        Line 725
                {                                                               
                  /* Don't discard remote entries with different locations,     
                     as these are more likely to be explicitly mounted.         
                     However avoid this when producing a total to give          
                     a more accurate value in that case.  */                    
                }                                                               
              else if ((strchr (me->me_devname, '/')                            Line 732
                       /* let "real" devices with '/' in the name win.  */      
                        && ! strchr (seen_dev->me->me_devname, '/'))            Line 734
                       /* let points towards the root of the device win.  */    
                       || (target_nearer_root && ! source_below_root)           Line 736
                       /* let an entry overmounted on a new device win...  */   
                       || (! STREQ (seen_dev->me->me_devname, me->me_devname)   Line 738
                           /* ... but only when matching an existing mnt point, 
                              to avoid problematic replacement when given       
                              inaccurate mount lists, seen with some chroot     
                              environments for example.  */                     
                           && STREQ (me->me_mountdir,                           Line 743
                                     seen_dev->me->me_mountdir)))               Line 744
                {                                                               
                  /* Discard mount entry for existing device.  */               
                  discard_me = seen_dev->me;                                    Line 747
                  seen_dev->me = me;                                            Line 748
                }                                                               
              else                                                              Line 750
                {                                                               
                  /* Discard mount entry currently being processed.  */         
                  discard_me = me;                                              Line 753
                }                                                               
                                                                                
            }                                                                   
        }                                                                       
                                                                                
      if (discard_me)                                                           Line 759
        {                                                                       
          me = me->me_next;                                                     Line 761
          if (! devices_only)                                                   Line 762
            free_mount_entry (discard_me);                                      Line 763
        }                                                                       
      else                                                                      Line 765
        {                                                                       
          /* Add the device number to the device_table.  */                     
          struct devlist *devlist = xmalloc (sizeof *devlist);                  Line 768
          devlist->me = me;                                                     Line 769
          devlist->dev_num = buf.st_dev;                                        Line 770
          devlist->next = device_list;                                          Line 771
          device_list = devlist;                                                Line 772
          if (hash_insert (devlist_table, devlist) == NULL)                     Line 773
            xalloc_die ();                                                      ...!common auto-comment...
                                                                                
          me = me->me_next;                                                     Line 776
        }                                                                       
    }                                                                           
                                                                                
  /* Finally rebuild the mount_list from the devlist.  */                       
  if (! devices_only) {                                                         Line 781
    mount_list = NULL;                                                          Line 782
    while (device_list)                                                         Line 783
      {                                                                         
        /* Add the mount entry.  */                                             
        me = device_list->me;                                                   Line 786
        me->me_next = mount_list;                                               Line 787
        mount_list = me;                                                        Line 788
        device_list = device_list->next;                                        Line 789
      }                                                                         
                                                                                
      hash_free (devlist_table);                                                Line 792
      devlist_table = NULL;                                                     Line 793
  }                                                                             
}                                                                               Block 24
                                                                                
                                                                                
/* Search a mount entry list for device id DEV.                                 
   Return the corresponding mount entry if found or NULL if not.  */            
                                                                                
static struct mount_entry const * _GL_ATTRIBUTE_PURE                            Line 801
me_for_dev (dev_t dev)                                                          Line 802
{                                                                               
  struct devlist *dl = devlist_for_dev (dev);                                   Line 804
  if (dl)                                                                       Line 805
        return dl->me;                                                          Line 806
                                                                                
  return NULL;                                                                  Line 808
}                                                                               Block 25
                                                                                
/* Return true if N is a known integer value.  On many file systems,            
   UINTMAX_MAX represents an unknown value; on AIX, UINTMAX_MAX - 1             
   represents unknown.  Use a rule that works on AIX file systems, and          
   that almost-always works on other types.  */                                 
static bool                                                                     Line 815
known_value (uintmax_t n)                                                       Line 816
{                                                                               
  return n < UINTMAX_MAX - 1;                                                   Line 818
}                                                                               Block 26
                                                                                
/* Like human_readable (N, BUF, human_output_opts, INPUT_UNITS, OUTPUT_UNITS),  
   except:                                                                      
                                                                                
    - If NEGATIVE, then N represents a negative number,                         
      expressed in two's complement.                                            
    - Otherwise, return "-" if N is unknown.  */                                
                                                                                
static char const *                                                             Line 828
df_readable (bool negative, uintmax_t n, char *buf,                             Line 829
             uintmax_t input_units, uintmax_t output_units)                     Line 830
{                                                                               
  if (! known_value (n) && !negative)                                           Line 832
    return "-";                                                                 Line 833
  else                                                                          Line 834
    {                                                                           
      char *p = human_readable (negative ? -n : n, buf + negative,              Line 836
                                human_output_opts, input_units, output_units);  Line 837
      if (negative)                                                             Line 838
        *--p = '-';                                                             Line 839
      return p;                                                                 Line 840
    }                                                                           
}                                                                               Block 27
                                                                                
/* Logical equivalence */                                                       
#define LOG_EQ(a, b) (!(a) == !(b))                                             Line 845
                                                                                
/* Add integral value while using uintmax_t for value part and separate         
   negation flag.  It adds value of SRC and SRC_NEG to DEST and DEST_NEG.       
   The result will be in DEST and DEST_NEG.  See df_readable to understand      
   how the negation flag is used.  */                                           
static void                                                                     Line 851
add_uint_with_neg_flag (uintmax_t *dest, bool *dest_neg,                        Line 852
                        uintmax_t src, bool src_neg)                            Line 853
{                                                                               
  if (LOG_EQ (*dest_neg, src_neg))                                              Line 855
    {                                                                           
      *dest += src;                                                             Line 857
      return;                                                                   Line 858
    }                                                                           
                                                                                
  if (*dest_neg)                                                                Line 861
    *dest = -*dest;                                                             Line 862
                                                                                
  if (src_neg)                                                                  Line 864
    src = -src;                                                                 Line 865
                                                                                
  if (src < *dest)                                                              Line 867
    *dest -= src;                                                               Line 868
  else                                                                          Line 869
    {                                                                           
      *dest = src - *dest;                                                      Line 871
      *dest_neg = src_neg;                                                      Line 872
    }                                                                           
                                                                                
  if (*dest_neg)                                                                Line 875
    *dest = -*dest;                                                             Line 876
}                                                                               Block 28
                                                                                
/* Return true if S ends in a string that may be a 36-byte UUID,                
   i.e., of the form HHHHHHHH-HHHH-HHHH-HHHH-HHHHHHHHHHHH, where                
   each H is an upper or lower case hexadecimal digit.  */                      
static bool _GL_ATTRIBUTE_PURE                                                  Line 882
has_uuid_suffix (char const *s)                                                 Line 883
{                                                                               
  size_t len = strlen (s);                                                      Line 885
  return (36 < len                                                              Line 886
          && strspn (s + len - 36, "-0123456789abcdefABCDEF") == 36);           Line 887
}                                                                               Block 29
                                                                                
/* Obtain the block values BV and inode values IV                               
   from the file system usage FSU.  */                                          
static void                                                                     Line 892
get_field_values (struct field_values_t *bv,                                    Line 893
                  struct field_values_t *iv,                                    Line 894
                  const struct fs_usage *fsu)                                   Line 895
{                                                                               
  /* Inode values.  */                                                          
  iv->input_units = iv->output_units = 1;                                       Line 898
  iv->total = fsu->fsu_files;                                                   Line 899
  iv->available = iv->available_to_root = fsu->fsu_ffree;                       Line 900
  iv->negate_available = false;                                                 Line 901
                                                                                
  iv->used = UINTMAX_MAX;                                                       Line 903
  iv->negate_used = false;                                                      Line 904
  if (known_value (iv->total) && known_value (iv->available_to_root))           Line 905
    {                                                                           
      iv->used = iv->total - iv->available_to_root;                             Line 907
      iv->negate_used = (iv->total < iv->available_to_root);                    Line 908
    }                                                                           
                                                                                
  /* Block values.  */                                                          
  bv->input_units = fsu->fsu_blocksize;                                         Line 912
  bv->output_units = output_block_size;                                         Line 913
  bv->total = fsu->fsu_blocks;                                                  Line 914
  bv->available = fsu->fsu_bavail;                                              Line 915
  bv->available_to_root = fsu->fsu_bfree;                                       Line 916
  bv->negate_available = (fsu->fsu_bavail_top_bit_set                           Line 917
                         && known_value (fsu->fsu_bavail));                     Line 918
                                                                                
  bv->used = UINTMAX_MAX;                                                       Line 920
  bv->negate_used = false;                                                      Line 921
  if (known_value (bv->total) && known_value (bv->available_to_root))           Line 922
    {                                                                           
      bv->used = bv->total - bv->available_to_root;                             Line 924
      bv->negate_used = (bv->total < bv->available_to_root);                    Line 925
    }                                                                           
}                                                                               
                                                                                
/* Add block and inode values to grand total.  */                               
static void                                                                     Line 930
add_to_grand_total (struct field_values_t *bv, struct field_values_t *iv)       Line 931
{                                                                               
  if (known_value (iv->total))                                                  Line 933
    grand_fsu.fsu_files += iv->total;                                           Line 934
  if (known_value (iv->available))                                              Line 935
    grand_fsu.fsu_ffree += iv->available;                                       Line 936
                                                                                
  if (known_value (bv->total))                                                  Line 938
    grand_fsu.fsu_blocks += bv->input_units * bv->total;                        Line 939
  if (known_value (bv->available_to_root))                                      Line 940
    grand_fsu.fsu_bfree += bv->input_units * bv->available_to_root;             Line 941
  if (known_value (bv->available))                                              Line 942
    add_uint_with_neg_flag (&grand_fsu.fsu_bavail,                              Line 943
                            &grand_fsu.fsu_bavail_top_bit_set,                  Line 944
                            bv->input_units * bv->available,                    Line 945
                            bv->negate_available);                              Line 946
}                                                                               Block 31
                                                                                
/* Obtain a space listing for the disk device with absolute file name DISK.     
   If MOUNT_POINT is non-NULL, it is the name of the root of the                
   file system on DISK.                                                         
   If STAT_FILE is non-null, it is the name of a file within the file           
   system that the user originally asked for; this provides better              
   diagnostics, and sometimes it provides better results on networked           
   file systems that give different free-space results depending on             
   where in the file system you probe.                                          
   If FSTYPE is non-NULL, it is the type of the file system on DISK.            
   If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may     
   not be able to produce statistics in this case.                              
   ME_DUMMY and ME_REMOTE are the mount entry flags.                            
   Caller must set PROCESS_ALL to true when iterating over all entries, as      
   when df is invoked with no non-option argument.  See below for details.  */  
                                                                                
static void                                                                     Line 964
get_dev (char const *disk, char const *mount_point, char const* file,           Line 965
         char const *stat_file, char const *fstype,                             Line 966
         bool me_dummy, bool me_remote,                                         Line 967
         const struct fs_usage *force_fsu,                                      Line 968
         bool process_all)                                                      Line 969
{                                                                               
  if (me_remote && show_local_fs)                                               Line 971
    return;                                                                     Line 972
                                                                                
  if (me_dummy && !show_all_fs && !show_listed_fs)                              Line 974
    return;                                                                     Line 975
                                                                                
  if (!selected_fstype (fstype) || excluded_fstype (fstype))                    Line 977
    return;                                                                     Line 978
                                                                                
  /* Ignore relative MOUNT_POINTs, which are present for example                
     in /proc/mounts on Linux with network namespaces.  */                      
  if (!force_fsu && mount_point && ! IS_ABSOLUTE_FILE_NAME (mount_point))       Line 982
    return;                                                                     Line 983
                                                                                
  /* If MOUNT_POINT is NULL, then the file system is not mounted, and this      
     program reports on the file system that the special file is on.            
     It would be better to report on the unmounted file system,                 
     but statfs doesn't do that on most systems.  */                            
  if (!stat_file)                                                               Line 989
    stat_file = mount_point ? mount_point : disk;                               Line 990
                                                                                
  struct fs_usage fsu;                                                          Line 992
  if (force_fsu)                                                                Line 993
    fsu = *force_fsu;                                                           Line 994
  else if (get_fs_usage (stat_file, disk, &fsu))                                Line 995
    {                                                                           
      /* If we can't access a system provided entry due                         
         to it not being present (now), or due to permissions,                  
         just output placeholder values rather than failing.  */                
      if (process_all && (errno == EACCES || errno == ENOENT))                  Line 1000
        {                                                                       
          if (! show_all_fs)                                                    Line 1002
            return;                                                             Line 1003
                                                                                
          fstype = "-";                                                         Line 1005
          fsu.fsu_bavail_top_bit_set = false;                                   Line 1006
          fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =                  Line 1007
          fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;         Line 1008
        }                                                                       
      else                                                                      Line 1010
        {                                                                       
          error (0, errno, "%s", quotef (stat_file));                           Line 1012
          exit_status = EXIT_FAILURE;                                           Line 1013
          return;                                                               Line 1014
        }                                                                       
    }                                                                           
  else if (process_all && show_all_fs)                                          Line 1017
    {                                                                           
      /* Ensure we don't output incorrect stats for over-mounted directories.   
         Discard stats when the device name doesn't match.  Though don't        
         discard when used and current mount entries are both remote due        
         to the possibility of aliased host names or exports.  */               
      struct stat sb;                                                           Line 1023
      if (stat (stat_file, &sb) == 0)                                           Line 1024...!syscalls auto-comment...
        {                                                                       
          struct mount_entry const * dev_me = me_for_dev (sb.st_dev);           Line 1026
          if (dev_me && ! STREQ (dev_me->me_devname, disk)                      Line 1027
              && (! dev_me->me_remote || ! me_remote))                          Line 1028
            {                                                                   
              fstype = "-";                                                     Line 1030
              fsu.fsu_bavail_top_bit_set = false;                               Line 1031
              fsu.fsu_blocksize = fsu.fsu_blocks = fsu.fsu_bfree =              Line 1032
              fsu.fsu_bavail = fsu.fsu_files = fsu.fsu_ffree = UINTMAX_MAX;     Line 1033
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  if (fsu.fsu_blocks == 0 && !show_all_fs && !show_listed_fs)                   Line 1038
    return;                                                                     Line 1039
                                                                                
  if (! force_fsu)                                                              Line 1041
    file_systems_processed = true;                                              Line 1042
                                                                                
  alloc_table_row ();                                                           Line 1044
                                                                                
  if (! disk)                                                                   Line 1046
    disk = "-";   /* unknown */                                                 Line 1047
                                                                                
  if (! file)                                                                   Line 1049
    file = "-";   /* unspecified */                                             Line 1050
                                                                                
  char *dev_name = xstrdup (disk);                                              Line 1052
  char *resolved_dev;                                                           Line 1053
                                                                                
  /* On some systems, dev_name is a long-named symlink like                     
     /dev/disk/by-uuid/828fc648-9f30-43d8-a0b1-f7196a2edb66 pointing to a       
     much shorter and more useful name like /dev/sda1.  It may also look        
     like /dev/mapper/luks-828fc648-9f30-43d8-a0b1-f7196a2edb66 and point to    
     /dev/dm-0.  When process_all is true and dev_name is a symlink whose       
     name ends with a UUID use the resolved name instead.  */                   
  if (process_all                                                               Line 1061
      && has_uuid_suffix (dev_name)                                             Line 1062
      && (resolved_dev = canonicalize_filename_mode (dev_name, CAN_EXISTING)))  Line 1063
    {                                                                           
      free (dev_name);                                                          Line 1065
      dev_name = resolved_dev;                                                  Line 1066
    }                                                                           
                                                                                
  if (! fstype)                                                                 Line 1069
    fstype = "-";  /* unknown */                                                Line 1070
                                                                                
  struct field_values_t block_values;                                           Line 1072
  struct field_values_t inode_values;                                           Line 1073
  get_field_values (&block_values, &inode_values, &fsu);                        Line 1074
                                                                                
  /* Add to grand total unless processing grand total line.  */                 
  if (print_grand_total && ! force_fsu)                                         Line 1077
    add_to_grand_total (&block_values, &inode_values);                          Line 1078
                                                                                
  size_t col;                                                                   Line 1080
  for (col = 0; col < ncolumns; col++)                                          Line 1081
    {                                                                           
      char buf[LONGEST_HUMAN_READABLE + 2];                                     Line 1083
      char *cell;                                                               Line 1084
                                                                                
      struct field_values_t *v;                                                 Line 1086
      switch (columns[col]->field_type)                                         Line 1087
        {                                                                       
        case BLOCK_FLD:                                                         Line 1089
          v = &block_values;                                                    Line 1090
          break;                                                                Line 1091
        case INODE_FLD:                                                         Line 1092
          v = &inode_values;                                                    Line 1093
          break;                                                                Line 1094
        case OTHER_FLD:                                                         Line 1095
          v = NULL;                                                             Line 1096
          break;                                                                Line 1097
        default:                                                                Line 1098
          v = NULL; /* Avoid warnings where assert() is not __noreturn__.  */   Line 1099
          assert (!"bad field_type");                                           Line 1100
        }                                                                       
                                                                                
      switch (columns[col]->field)                                              Line 1103
        {                                                                       
        case SOURCE_FIELD:                                                      Line 1105
          cell = xstrdup (dev_name);                                            Line 1106
          break;                                                                Line 1107
                                                                                
        case FSTYPE_FIELD:                                                      Line 1109
          cell = xstrdup (fstype);                                              Line 1110
          break;                                                                Line 1111
                                                                                
        case SIZE_FIELD:                                                        Line 1113
        case ITOTAL_FIELD:                                                      Line 1114
          cell = xstrdup (df_readable (false, v->total, buf,                    Line 1115
                                       v->input_units, v->output_units));       Line 1116
          break;                                                                Line 1117
                                                                                
        case USED_FIELD:                                                        Line 1119
        case IUSED_FIELD:                                                       Line 1120
          cell = xstrdup (df_readable (v->negate_used, v->used, buf,            Line 1121
                                       v->input_units, v->output_units));       Line 1122
          break;                                                                Line 1123
                                                                                
        case AVAIL_FIELD:                                                       Line 1125
        case IAVAIL_FIELD:                                                      Line 1126
          cell = xstrdup (df_readable (v->negate_available, v->available, buf,  Line 1127
                                       v->input_units, v->output_units));       Line 1128
          break;                                                                Line 1129
                                                                                
        case PCENT_FIELD:                                                       Line 1131
        case IPCENT_FIELD:                                                      Line 1132
          {                                                                     
            double pct = -1;                                                    Line 1134
            if (! known_value (v->used) || ! known_value (v->available))        Line 1135
              ;                                                                 
            else if (!v->negate_used                                            Line 1137
                     && v->used <= TYPE_MAXIMUM (uintmax_t) / 100               Line 1138
                     && v->used + v->available != 0                             Line 1139
                     && (v->used + v->available < v->used)                      Line 1140
                     == v->negate_available)                                    Line 1141
              {                                                                 
                uintmax_t u100 = v->used * 100;                                 Line 1143
                uintmax_t nonroot_total = v->used + v->available;               Line 1144
                pct = u100 / nonroot_total + (u100 % nonroot_total != 0);       Line 1145
              }                                                                 
            else                                                                Line 1147
              {                                                                 
                /* The calculation cannot be done easily with integer           
                   arithmetic.  Fall back on floating point.  This can suffer   
                   from minor rounding errors, but doing it exactly requires    
                   multiple precision arithmetic, and it's not worth the        
                   aggravation.  */                                             
                double u = v->negate_used ? - (double) - v->used : v->used;     Line 1154
                double a = v->negate_available                                  Line 1155
                           ? - (double) - v->available : v->available;          Line 1156
                double nonroot_total = u + a;                                   Line 1157
                if (nonroot_total)                                              Line 1158
                  {                                                             
                    long int lipct = pct = u * 100 / nonroot_total;             Line 1160
                    double ipct = lipct;                                        Line 1161
                                                                                
                    /* Like 'pct = ceil (dpct);', but avoid ceil so that        
                       the math library needn't be linked.  */                  
                    if (ipct - 1 < pct && pct <= ipct + 1)                      Line 1165
                      pct = ipct + (ipct < pct);                                Line 1166
                  }                                                             
              }                                                                 
                                                                                
            if (0 <= pct)                                                       Line 1170
              {                                                                 
                if (asprintf (&cell, "%.0f%%", pct) == -1)                      Line 1172
                  cell = NULL;                                                  Line 1173
              }                                                                 
            else                                                                Line 1175
              cell = strdup ("-");                                              Line 1176
                                                                                
            if (!cell)                                                          Line 1178
              xalloc_die ();                                                    ...!common auto-comment...
                                                                                
            break;                                                              Line 1181
          }                                                                     
                                                                                
        case FILE_FIELD:                                                        Line 1184
          cell = xstrdup (file);                                                Line 1185
          break;                                                                Line 1186
                                                                                
        case TARGET_FIELD:                                                      Line 1188
#ifdef HIDE_AUTOMOUNT_PREFIX                                                    Line 1189
          /* Don't print the first directory name in MOUNT_POINT if it's an     
             artifact of an automounter.  This is a bit too aggressive to be    
             the default.  */                                                   
          if (STRNCMP_LIT (mount_point, "/auto/") == 0)                         Line 1193
            mount_point += 5;                                                   Line 1194
          else if (STRNCMP_LIT (mount_point, "/tmp_mnt/") == 0)                 Line 1195
            mount_point += 8;                                                   Line 1196
#endif                                                                          Line 1197
          cell = xstrdup (mount_point);                                         Line 1198
          break;                                                                Line 1199
                                                                                
        default:                                                                Line 1201
          assert (!"unhandled field");                                          Line 1202
        }                                                                       
                                                                                
      if (!cell)                                                                Line 1205
        assert (!"empty cell");                                                 Line 1206
                                                                                
      hide_problematic_chars (cell);                                            Line 1208
      size_t cell_width = mbswidth (cell, 0);                                   Line 1209
      columns[col]->width = MAX (columns[col]->width, cell_width);              Line 1210
      table[nrows - 1][col] = cell;                                             Line 1211
    }                                                                           
  free (dev_name);                                                              Line 1213
}                                                                               Block 32
                                                                                
/* Scan the mount list returning the _last_ device found for MOUNT.             
   NULL is returned if MOUNT not found.  The result is malloced.  */            
static char *                                                                   Line 1218
last_device_for_mount (char const* mount)                                       Line 1219
{                                                                               
  struct mount_entry const *me;                                                 Line 1221
  struct mount_entry const *le = NULL;                                          Line 1222
                                                                                
  for (me = mount_list; me; me = me->me_next)                                   Line 1224
    {                                                                           
      if (STREQ (me->me_mountdir, mount))                                       Line 1226
        le = me;                                                                Line 1227
    }                                                                           
                                                                                
  if (le)                                                                       Line 1230
    {                                                                           
      char *devname = le->me_devname;                                           Line 1232
      char *canon_dev = canonicalize_file_name (devname);                       Line 1233
      if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))                       Line 1234
        return canon_dev;                                                       Line 1235
      free (canon_dev);                                                         Line 1236
      return xstrdup (le->me_devname);                                          Line 1237
    }                                                                           
  else                                                                          Line 1239
    return NULL;                                                                Line 1240
}                                                                               Block 33
                                                                                
/* If DISK corresponds to a mount point, show its usage                         
   and return true.  Otherwise, return false.  */                               
static bool                                                                     Line 1245
get_disk (char const *disk)                                                     Line 1246
{                                                                               
  struct mount_entry const *me;                                                 Line 1248
  struct mount_entry const *best_match = NULL;                                  Line 1249
  bool best_match_accessible = false;                                           Line 1250
  bool eclipsed_device = false;                                                 Line 1251
  char const *file = disk;                                                      Line 1252
                                                                                
  char *resolved = canonicalize_file_name (disk);                               Line 1254
  if (resolved && IS_ABSOLUTE_FILE_NAME (resolved))                             Line 1255
    disk = resolved;                                                            Line 1256
                                                                                
  size_t best_match_len = SIZE_MAX;                                             Line 1258
  for (me = mount_list; me; me = me->me_next)                                   Line 1259
    {                                                                           
      /* TODO: Should cache canon_dev in the mount_entry struct.  */            
      char *devname = me->me_devname;                                           Line 1262
      char *canon_dev = canonicalize_file_name (me->me_devname);                Line 1263
      if (canon_dev && IS_ABSOLUTE_FILE_NAME (canon_dev))                       Line 1264
        devname = canon_dev;                                                    Line 1265
                                                                                
      if (STREQ (disk, devname))                                                Line 1267
        {                                                                       
          char *last_device = last_device_for_mount (me->me_mountdir);          Line 1269
          eclipsed_device = last_device && ! STREQ (last_device, devname);      Line 1270
          size_t len = strlen (me->me_mountdir);                                Line 1271
                                                                                
          if (! eclipsed_device                                                 Line 1273
              && (! best_match_accessible || len < best_match_len))             Line 1274
            {                                                                   
              struct stat disk_stats;                                           Line 1276
              bool this_match_accessible = false;                               Line 1277
                                                                                
              if (stat (me->me_mountdir, &disk_stats) == 0)                     Line 1279...!syscalls auto-comment...
                best_match_accessible = this_match_accessible = true;           Line 1280
                                                                                
              if (this_match_accessible                                         Line 1282
                  || (! best_match_accessible && len < best_match_len))         Line 1283
                {                                                               
                  best_match = me;                                              Line 1285
                  if (len == 1) /* Traditional root.  */                        Line 1286
                    {                                                           
                      free (last_device);                                       Line 1288
                      free (canon_dev);                                         Line 1289
                      break;                                                    Line 1290
                    }                                                           
                  else                                                          Line 1292
                    best_match_len = len;                                       Line 1293
                }                                                               
            }                                                                   
                                                                                
          free (last_device);                                                   Line 1297
        }                                                                       
                                                                                
      free (canon_dev);                                                         Line 1300
    }                                                                           
                                                                                
  free (resolved);                                                              Line 1303
                                                                                
  if (best_match)                                                               Line 1305
    {                                                                           
      get_dev (best_match->me_devname, best_match->me_mountdir, file, NULL,     Line 1307
               best_match->me_type, best_match->me_dummy,                       Line 1308
               best_match->me_remote, NULL, false);                             Line 1309
      return true;                                                              Line 1310
    }                                                                           
  else if (eclipsed_device)                                                     Line 1312
    {                                                                           
      error (0, 0, _("cannot access %s: over-mounted by another device"),       Line 1314
             quoteaf (file));                                                   Line 1315
      exit_status = EXIT_FAILURE;                                               Line 1316
      return true;                                                              Line 1317
    }                                                                           
                                                                                
  return false;                                                                 Line 1320
}                                                                               Block 34
                                                                                
/* Figure out which device file or directory POINT is mounted on                
   and show its disk usage.                                                     
   STATP must be the result of 'stat (POINT, STATP)'.  */                       
static void                                                                     Line 1326
get_point (const char *point, const struct stat *statp)                         Line 1327
{                                                                               
  struct stat disk_stats;                                                       Line 1329
  struct mount_entry *me;                                                       Line 1330
  struct mount_entry const *best_match = NULL;                                  Line 1331
                                                                                
  /* Calculate the real absolute file name for POINT, and use that to find      
     the mount point.  This avoids statting unavailable mount points,           
     which can hang df.  */                                                     
  char *resolved = canonicalize_file_name (point);                              Line 1336
  if (resolved && resolved[0] == '/')                                           Line 1337
    {                                                                           
      size_t resolved_len = strlen (resolved);                                  Line 1339
      size_t best_match_len = 0;                                                Line 1340
                                                                                
      for (me = mount_list; me; me = me->me_next)                               Line 1342
        {                                                                       
          if (!STREQ (me->me_type, "lofs")                                      Line 1344
              && (!best_match || best_match->me_dummy || !me->me_dummy))        Line 1345
            {                                                                   
              size_t len = strlen (me->me_mountdir);                            Line 1347
              if (best_match_len <= len && len <= resolved_len                  Line 1348
                  && (len == 1 /* root file system */                           Line 1349
                      || ((len == resolved_len || resolved[len] == '/')         Line 1350
                          && STREQ_LEN (me->me_mountdir, resolved, len))))      Line 1351
                {                                                               
                  best_match = me;                                              Line 1353
                  best_match_len = len;                                         Line 1354
                }                                                               
            }                                                                   
        }                                                                       
    }                                                                           
  free (resolved);                                                              Line 1359
  if (best_match                                                                Line 1360
      && (stat (best_match->me_mountdir, &disk_stats) != 0                      Line 1361...!syscalls auto-comment...
          || disk_stats.st_dev != statp->st_dev))                               Line 1362
    best_match = NULL;                                                          Line 1363
                                                                                
  if (! best_match)                                                             Line 1365
    for (me = mount_list; me; me = me->me_next)                                 Line 1366
      {                                                                         
        if (me->me_dev == (dev_t) -1)                                           Line 1368
          {                                                                     
            if (stat (me->me_mountdir, &disk_stats) == 0)                       Line 1370...!syscalls auto-comment...
              me->me_dev = disk_stats.st_dev;                                   Line 1371
            else                                                                Line 1372
              {                                                                 
                /* Report only I/O errors.  Other errors might be               
                   caused by shadowed mount points, which means POINT           
                   can't possibly be on this file system.  */                   
                if (errno == EIO)                                               Line 1377
                  {                                                             
                    error (0, errno, "%s", quotef (me->me_mountdir));           Line 1379
                    exit_status = EXIT_FAILURE;                                 Line 1380
                  }                                                             
                                                                                
                /* So we won't try and fail repeatedly.  */                     
                me->me_dev = (dev_t) -2;                                        Line 1384
              }                                                                 
          }                                                                     
                                                                                
        if (statp->st_dev == me->me_dev                                         Line 1388
            && !STREQ (me->me_type, "lofs")                                     Line 1389
            && (!best_match || best_match->me_dummy || !me->me_dummy))          Line 1390
          {                                                                     
            /* Skip bogus mtab entries.  */                                     
            if (stat (me->me_mountdir, &disk_stats) != 0                        Line 1393...!syscalls auto-comment...
                || disk_stats.st_dev != me->me_dev)                             Line 1394
              me->me_dev = (dev_t) -2;                                          Line 1395
            else                                                                Line 1396
              best_match = me;                                                  Line 1397
          }                                                                     
      }                                                                         
                                                                                
  if (best_match)                                                               Line 1401
    get_dev (best_match->me_devname, best_match->me_mountdir, point, point,     Line 1402
             best_match->me_type, best_match->me_dummy, best_match->me_remote,  Line 1403
             NULL, false);                                                      Line 1404
  else                                                                          Line 1405
    {                                                                           
      /* We couldn't find the mount entry corresponding to POINT.  Go ahead and 
         print as much info as we can; methods that require the device to be    
         present will fail at a later point.  */                                
                                                                                
      /* Find the actual mount point.  */                                       
      char *mp = find_mount_point (point, statp);                               Line 1412
      if (mp)                                                                   Line 1413
        {                                                                       
          get_dev (NULL, mp, point, NULL, NULL, false, false, NULL, false);     Line 1415
          free (mp);                                                            Line 1416
        }                                                                       
    }                                                                           
}                                                                               Block 35
                                                                                
/* Determine what kind of node NAME is and show the disk usage                  
   for it.  STATP is the results of 'stat' on NAME.  */                         
                                                                                
static void                                                                     Line 1424
get_entry (char const *name, struct stat const *statp)                          Line 1425
{                                                                               
  if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))                    Line 1427
      && get_disk (name))                                                       Line 1428
    return;                                                                     Line 1429
                                                                                
  get_point (name, statp);                                                      Line 1431
}                                                                               Block 36
                                                                                
/* Show all mounted file systems, except perhaps those that are of              
   an unselected type or are empty.  */                                         
                                                                                
static void                                                                     Line 1437
get_all_entries (void)                                                          Line 1438
{                                                                               
  struct mount_entry *me;                                                       Line 1440
                                                                                
  filter_mount_list (show_all_fs);                                              Line 1442
                                                                                
  for (me = mount_list; me; me = me->me_next)                                   Line 1444
    get_dev (me->me_devname, me->me_mountdir, NULL, NULL, me->me_type,          Line 1445
             me->me_dummy, me->me_remote, NULL, true);                          Line 1446
}                                                                               Block 37
                                                                                
/* Add FSTYPE to the list of file system types to display.  */                  
                                                                                
static void                                                                     Line 1451
add_fs_type (const char *fstype)                                                Line 1452
{                                                                               
  struct fs_type_list *fsp;                                                     Line 1454
                                                                                
  fsp = xmalloc (sizeof *fsp);                                                  Line 1456
  fsp->fs_name = (char *) fstype;                                               Line 1457
  fsp->fs_next = fs_select_list;                                                Line 1458
  fs_select_list = fsp;                                                         Line 1459
}                                                                               Block 38
                                                                                
/* Add FSTYPE to the list of file system types to be omitted.  */               
                                                                                
static void                                                                     Line 1464
add_excluded_fs_type (const char *fstype)                                       Line 1465
{                                                                               
  struct fs_type_list *fsp;                                                     Line 1467
                                                                                
  fsp = xmalloc (sizeof *fsp);                                                  Line 1469
  fsp->fs_name = (char *) fstype;                                               Line 1470
  fsp->fs_next = fs_exclude_list;                                               Line 1471
  fs_exclude_list = fsp;                                                        Line 1472
}                                                                               Block 39
                                                                                
void                                                                            Line 1475
usage (int status)                                                              Line 1476
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 1478
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 1480
    {                                                                           
      printf (_("Usage: %s [OPTION]... [FILE]...\n"), program_name);            Line 1482
      fputs (_("\                                                               Line 1483
Show information about the file system on which each FILE resides,\n\           Line 1484
or all file systems by default.\n\                                              Line 1485
"), stdout);                                                                    Line 1486
                                                                                
      emit_mandatory_arg_note ();                                               ...!common auto-comment...
                                                                                
      /* TRANSLATORS: The thousands and decimal separators are best             
         adjusted to an appropriate default for your locale.  */                
      fputs (_("\                                                               Line 1492
  -a, --all             include pseudo, duplicate, inaccessible file systems\n\ Line 1493
  -B, --block-size=SIZE  scale sizes by SIZE before printing them; e.g.,\n\     Line 1494
                           '-BM' prints sizes in units of 1,048,576 bytes;\n\   Line 1495
                           see SIZE format below\n\                             Line 1496
  -h, --human-readable  print sizes in powers of 1024 (e.g., 1023M)\n\          Line 1497
  -H, --si              print sizes in powers of 1000 (e.g., 1.1G)\n\           Line 1498
"), stdout);                                                                    Line 1499
      fputs (_("\                                                               Line 1500
  -i, --inodes          list inode information instead of block usage\n\        Line 1501
  -k                    like --block-size=1K\n\                                 Line 1502
  -l, --local           limit listing to local file systems\n\                  Line 1503
      --no-sync         do not invoke sync before getting usage info (default)\ Line 1504
\n\                                                                             
"), stdout);                                                                    Line 1506
      fputs (_("\                                                               Line 1507
      --output[=FIELD_LIST]  use the output format defined by FIELD_LIST,\n\    Line 1508
                               or print all fields if FIELD_LIST is omitted.\n\ Line 1509
  -P, --portability     use the POSIX output format\n\                          Line 1510
      --sync            invoke sync before getting usage info\n\                Line 1511
"), stdout);                                                                    Line 1512
      fputs (_("\                                                               Line 1513
      --total           elide all entries insignificant to available space,\n\  Line 1514
                          and produce a grand total\n\                          Line 1515
"), stdout);                                                                    Line 1516
      fputs (_("\                                                               Line 1517
  -t, --type=TYPE       limit listing to file systems of type TYPE\n\           Line 1518
  -T, --print-type      print file system type\n\                               Line 1519
  -x, --exclude-type=TYPE   limit listing to file systems not of type TYPE\n\   Line 1520
  -v                    (ignored)\n\                                            Line 1521
"), stdout);                                                                    Line 1522
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 1523
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 1524
      emit_blocksize_note ("DF");                                               Line 1525
      emit_size_note ();                                                        Line 1526
      fputs (_("\n\                                                             Line 1527
FIELD_LIST is a comma-separated list of columns to be included.  Valid\n\       Line 1528
field names are: 'source', 'fstype', 'itotal', 'iused', 'iavail', 'ipcent',\n\  Line 1529
'size', 'used', 'avail', 'pcent', 'file' and 'target' (see info page).\n\       Line 1530
"), stdout);                                                                    Line 1531
      emit_ancillary_info (PROGRAM_NAME);                                       Line 1532
    }                                                                           
  exit (status);                                                                Line 1534
}                                                                               Block 40
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 1538
{                                                                               
  struct stat *stats IF_LINT ( = 0);                                            Line 1540
                                                                                
  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
                                                                                
  atexit (close_stdout);                                                        Close stdout on exit (see gnulib)
                                                                                
  fs_select_list = NULL;                                                        Line 1550
  fs_exclude_list = NULL;                                                       Line 1551
  show_all_fs = false;                                                          Line 1552
  show_listed_fs = false;                                                       Line 1553
  human_output_opts = -1;                                                       Line 1554
  print_type = false;                                                           Line 1555
  file_systems_processed = false;                                               Line 1556
  exit_status = EXIT_SUCCESS;                                                   Line 1557
  print_grand_total = false;                                                    Line 1558
  grand_fsu.fsu_blocksize = 1;                                                  Line 1559
                                                                                
  /* If true, use the POSIX output format.  */                                  
  bool posix_format = false;                                                    Line 1562
                                                                                
  const char *msg_mut_excl = _("options %s and %s are mutually exclusive");     Line 1564
                                                                                
  while (true)                                                                  Line 1566
    {                                                                           
      int oi = -1;                                                              Line 1568
      int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,      Line 1569
                           &oi);                                                Line 1570
      if (c == -1)                                                              Line 1571
        break;                                                                  Line 1572
                                                                                
      switch (c)                                                                Line 1574
        {                                                                       
        case 'a':                                                               Line 1576
          show_all_fs = true;                                                   Line 1577
          break;                                                                Line 1578
        case 'B':                                                               Line 1579
          {                                                                     
            enum strtol_error e = human_options (optarg, &human_output_opts,    Line 1581
                                                 &output_block_size);           Line 1582
            if (e != LONGINT_OK)                                                Line 1583
              xstrtol_fatal (e, oi, c, long_options, optarg);                   Line 1584
          }                                                                     
          break;                                                                Line 1586
        case 'i':                                                               Line 1587
          if (header_mode == OUTPUT_MODE)                                       Line 1588
            {                                                                   
              error (0, 0, msg_mut_excl, "-i", "--output");                     Line 1590
              usage (EXIT_FAILURE);                                             Line 1591
            }                                                                   
          header_mode = INODES_MODE;                                            Line 1593
          break;                                                                Line 1594
        case 'h':                                                               Line 1595
          human_output_opts = human_autoscale | human_SI | human_base_1024;     Line 1596
          output_block_size = 1;                                                Line 1597
          break;                                                                Line 1598
        case 'H':                                                               Line 1599
          human_output_opts = human_autoscale | human_SI;                       Line 1600
          output_block_size = 1;                                                Line 1601
          break;                                                                Line 1602
        case 'k':                                                               Line 1603
          human_output_opts = 0;                                                Line 1604
          output_block_size = 1024;                                             Line 1605
          break;                                                                Line 1606
        case 'l':                                                               Line 1607
          show_local_fs = true;                                                 Line 1608
          break;                                                                Line 1609
        case 'm': /* obsolescent, exists for BSD compatibility */               Line 1610
          human_output_opts = 0;                                                Line 1611
          output_block_size = 1024 * 1024;                                      Line 1612
          break;                                                                Line 1613
        case 'T':                                                               Line 1614
          if (header_mode == OUTPUT_MODE)                                       Line 1615
            {                                                                   
              error (0, 0, msg_mut_excl, "-T", "--output");                     Line 1617
              usage (EXIT_FAILURE);                                             Line 1618
            }                                                                   
          print_type = true;                                                    Line 1620
          break;                                                                Line 1621
        case 'P':                                                               Line 1622
          if (header_mode == OUTPUT_MODE)                                       Line 1623
            {                                                                   
              error (0, 0, msg_mut_excl, "-P", "--output");                     Line 1625
              usage (EXIT_FAILURE);                                             Line 1626
            }                                                                   
          posix_format = true;                                                  Line 1628
          break;                                                                Line 1629
        case SYNC_OPTION:                                                       Line 1630
          require_sync = true;                                                  Line 1631
          break;                                                                Line 1632
        case NO_SYNC_OPTION:                                                    Line 1633
          require_sync = false;                                                 Line 1634
          break;                                                                Line 1635
                                                                                
        case 'F':                                                               Line 1637
          /* Accept -F as a synonym for -t for compatibility with Solaris.  */  
        case 't':                                                               Line 1639
          add_fs_type (optarg);                                                 Line 1640
          break;                                                                Line 1641
                                                                                
        case 'v':  /* For SysV compatibility.  */                               Line 1643
          /* ignore */                                                          
          break;                                                                Line 1645
        case 'x':                                                               Line 1646
          add_excluded_fs_type (optarg);                                        Line 1647
          break;                                                                Line 1648
                                                                                
        case OUTPUT_OPTION:                                                     Line 1650
          if (header_mode == INODES_MODE)                                       Line 1651
            {                                                                   
              error (0, 0, msg_mut_excl, "-i", "--output");                     Line 1653
              usage (EXIT_FAILURE);                                             Line 1654
            }                                                                   
          if (posix_format && header_mode == DEFAULT_MODE)                      Line 1656
            {                                                                   
              error (0, 0, msg_mut_excl, "-P", "--output");                     Line 1658
              usage (EXIT_FAILURE);                                             Line 1659
            }                                                                   
          if (print_type)                                                       Line 1661
            {                                                                   
              error (0, 0, msg_mut_excl, "-T", "--output");                     Line 1663
              usage (EXIT_FAILURE);                                             Line 1664
            }                                                                   
          header_mode = OUTPUT_MODE;                                            Line 1666
          if (optarg)                                                           Line 1667
            decode_output_arg (optarg);                                         Line 1668
          break;                                                                Line 1669
                                                                                
        case TOTAL_OPTION:                                                      Line 1671
          print_grand_total = true;                                             Line 1672
          break;                                                                Line 1673
                                                                                
        case_GETOPT_HELP_CHAR;                                                  Line 1675
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 1676
                                                                                
        default:                                                                Line 1678
          usage (EXIT_FAILURE);                                                 Line 1679
        }                                                                       
    }                                                                           
                                                                                
  if (human_output_opts == -1)                                                  Line 1683
    {                                                                           
      if (posix_format)                                                         Line 1685
        {                                                                       
          human_output_opts = 0;                                                Line 1687
          output_block_size = (getenv ("POSIXLY_CORRECT") ? 512 : 1024);        Line 1688
        }                                                                       
      else                                                                      Line 1690
        human_options (getenv ("DF_BLOCK_SIZE"),                                Line 1691
                       &human_output_opts, &output_block_size);                 Line 1692
    }                                                                           
                                                                                
  if (header_mode == INODES_MODE || header_mode == OUTPUT_MODE)                 Line 1695
    ;                                                                           
  else if (human_output_opts & human_autoscale)                                 Line 1697
    header_mode = HUMAN_MODE;                                                   Line 1698
  else if (posix_format)                                                        Line 1699
    header_mode = POSIX_MODE;                                                   Line 1700
                                                                                
  /* Fail if the same file system type was both selected and excluded.  */      
  {                                                                             
    bool match = false;                                                         Line 1704
    struct fs_type_list *fs_incl;                                               Line 1705
    for (fs_incl = fs_select_list; fs_incl; fs_incl = fs_incl->fs_next)         Line 1706
      {                                                                         
        struct fs_type_list *fs_excl;                                           Line 1708
        for (fs_excl = fs_exclude_list; fs_excl; fs_excl = fs_excl->fs_next)    Line 1709
          {                                                                     
            if (STREQ (fs_incl->fs_name, fs_excl->fs_name))                     Line 1711
              {                                                                 
                error (0, 0,                                                    Line 1713
                       _("file system type %s both selected and excluded"),     Line 1714
                       quote (fs_incl->fs_name));                               Line 1715
                match = true;                                                   Line 1716
                break;                                                          Line 1717
              }                                                                 
          }                                                                     
      }                                                                         
    if (match)                                                                  Line 1721
      return EXIT_FAILURE;                                                      Line 1722
  }                                                                             
                                                                                
  assume (0 < optind);                                                          Line 1725
                                                                                
  if (optind < argc)                                                            Line 1727
    {                                                                           
      /* stat each of the given entries to make sure any corresponding          
         partition is automounted.  This must be done before reading the        
         file system table.  */                                                 
      stats = xnmalloc (argc - optind, sizeof *stats);                          Line 1732
      for (int i = optind; i < argc; ++i)                                       Line 1733
        {                                                                       
          if (stat (argv[i], &stats[i - optind]))                               Line 1735...!syscalls auto-comment...
            {                                                                   
              error (0, errno, "%s", quotef (argv[i]));                         Line 1737
              exit_status = EXIT_FAILURE;                                       Line 1738
              argv[i] = NULL;                                                   Line 1739
            }                                                                   
          else if (! S_ISFIFO (stats[i - optind].st_mode))                      Line 1741
            {                                                                   
              /* open() is needed to automount in some cases.  */               
              int fd = open (argv[i], O_RDONLY | O_NOCTTY);                     Line 1744...!syscalls auto-comment...
              if (0 <= fd)                                                      Line 1745
                close (fd);                                                     Line 1746...!syscalls auto-comment...
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  mount_list =                                                                  Line 1751
    read_file_system_list ((fs_select_list != NULL                              Line 1752
                            || fs_exclude_list != NULL                          Line 1753
                            || print_type                                       Line 1754
                            || field_data[FSTYPE_FIELD].used                    Line 1755
                            || show_local_fs));                                 Line 1756
                                                                                
  if (mount_list == NULL)                                                       Line 1758
    {                                                                           
      /* Couldn't read the table of mounted file systems.                       
         Fail if df was invoked with no file name arguments,                    
         or when either of -a, -l, -t or -x is used with file name              
         arguments.  Otherwise, merely give a warning and proceed.  */          
      int status = 0;                                                           Line 1764
      if ( ! (optind < argc)                                                    Line 1765
           || (show_all_fs                                                      Line 1766
               || show_local_fs                                                 Line 1767
               || fs_select_list != NULL                                        Line 1768
               || fs_exclude_list != NULL))                                     Line 1769
        {                                                                       
          status = EXIT_FAILURE;                                                Line 1771
        }                                                                       
      const char *warning = (status == 0 ? _("Warning: ") : "");                Line 1773
      error (status, errno, "%s%s", warning,                                    Line 1774
             _("cannot read table of mounted file systems"));                   Line 1775
    }                                                                           
                                                                                
  if (require_sync)                                                             Line 1778
    sync ();                                                                    Line 1779...!syscalls auto-comment...
                                                                                
  get_field_list ();                                                            Line 1781
  get_header ();                                                                Line 1782
                                                                                
  if (optind < argc)                                                            Line 1784
    {                                                                           
      /* Display explicitly requested empty file systems.  */                   
      show_listed_fs = true;                                                    Line 1787
                                                                                
      for (int i = optind; i < argc; ++i)                                       Line 1789
        if (argv[i])                                                            Line 1790
          get_entry (argv[i], &stats[i - optind]);                              Line 1791
                                                                                
      IF_LINT (free (stats));                                                   Line 1793
    }                                                                           
  else                                                                          Line 1795
    get_all_entries ();                                                         Line 1796
                                                                                
  if (file_systems_processed)                                                   Line 1798
    {                                                                           
      if (print_grand_total)                                                    Line 1800
        get_dev ("total",                                                       Line 1801
                 (field_data[SOURCE_FIELD].used ? "-" : "total"),               Line 1802
                 NULL, NULL, NULL, false, false, &grand_fsu, false);            Line 1803
                                                                                
      print_table ();                                                           Line 1805
    }                                                                           
  else                                                                          Line 1807
    {                                                                           
      /* Print the "no FS processed" diagnostic only if there was no preceding  
         diagnostic, e.g., if all have been excluded.  */                       
      if (exit_status == EXIT_SUCCESS)                                          Line 1811
        die (EXIT_FAILURE, 0, _("no file systems processed"));                  Line 1812
    }                                                                           
                                                                                
  IF_LINT (free (columns));                                                     Line 1815
                                                                                
  return exit_status;                                                           Line 1817
}                                                                               Block 41