/* chmod -- change permission modes of files                                    This is the chmod utility
   Copyright (C) 1989-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> */                           
                                                                                
#include <config.h>                                                             Provides system specific information
#include <stdio.h>                                                              Provides standard I/O capability
#include <getopt.h>                                                             ...!includes auto-comment...
#include <sys/types.h>                                                          Provides system data types
                                                                                
#include "system.h"                                                             ...!includes auto-comment...
#include "dev-ino.h"                                                            ...!includes auto-comment...
#include "die.h"                                                                ...!includes auto-comment...
#include "error.h"                                                              ...!includes auto-comment...
#include "filemode.h"                                                           ...!includes auto-comment...
#include "ignore-value.h"                                                       ...!includes auto-comment...
#include "modechange.h"                                                         ...!includes auto-comment...
#include "quote.h"                                                              ...!includes auto-comment...
#include "root-dev-ino.h"                                                       ...!includes auto-comment......!includes auto-comment...
#include "xfts.h"                                                               ...!includes auto-comment...
                                                                                
/* The official name of this program (e.g., no 'g' prefix).  */                 
#define PROGRAM_NAME "chmod"                                                    Line 36
                                                                                
#define AUTHORS \                                                               Line 38
  proper_name ("David MacKenzie"), \                                            Line 39
  proper_name ("Jim Meyering")                                                  Line 40
                                                                                
enum Change_status                                                              Line 42
{                                                                               
  CH_NOT_APPLIED,                                                               Line 44
  CH_SUCCEEDED,                                                                 Line 45
  CH_FAILED,                                                                    Line 46
  CH_NO_CHANGE_REQUESTED                                                        Line 47
};                                                                              Block 1
                                                                                
enum Verbosity                                                                  Line 50
{                                                                               
  /* Print a message for each file that is processed.  */                       
  V_high,                                                                       Line 53
                                                                                
  /* Print a message for each file whose attributes we change.  */              
  V_changes_only,                                                               Line 56
                                                                                
  /* Do not be verbose.  This is the default. */                                
  V_off                                                                         Line 59
};                                                                              
                                                                                
/* The desired change to the mode.  */                                          
static struct mode_change *change;                                              Line 63
                                                                                
/* The initial umask value, if it might be needed.  */                          
static mode_t umask_value;                                                      Line 66
                                                                                
/* If true, change the modes of directories recursively. */                     
static bool recurse;                                                            Line 69
                                                                                
/* If true, force silence (suppress most of error messages). */                 
static bool force_silent;                                                       Line 72
                                                                                
/* If true, diagnose surprises from naive misuses like "chmod -r file".         
   POSIX allows diagnostics here, as portable code is supposed to use           
   "chmod -- -r file".  */                                                      
static bool diagnose_surprises;                                                 Line 77
                                                                                
/* Level of verbosity.  */                                                      
static enum Verbosity verbosity = V_off;                                        Line 80
                                                                                
/* Pointer to the device and inode numbers of '/', when --recursive.            
   Otherwise NULL.  */                                                          
static struct dev_ino *root_dev_ino;                                            Line 84
                                                                                
/* 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 88
{                                                                               
  NO_PRESERVE_ROOT = CHAR_MAX + 1,                                              Line 90
  PRESERVE_ROOT,                                                                Line 91
  REFERENCE_FILE_OPTION                                                         Line 92
};                                                                              Block 3
                                                                                
static struct option const long_options[] =                                     Line 95
{                                                                               
  {"changes", no_argument, NULL, 'c'},                                          Line 97
  {"recursive", no_argument, NULL, 'R'},                                        Line 98
  {"no-preserve-root", no_argument, NULL, NO_PRESERVE_ROOT},                    Line 99
  {"preserve-root", no_argument, NULL, PRESERVE_ROOT},                          Line 100
  {"quiet", no_argument, NULL, 'f'},                                            Line 101
  {"reference", required_argument, NULL, REFERENCE_FILE_OPTION},                Line 102
  {"silent", no_argument, NULL, 'f'},                                           Line 103
  {"verbose", no_argument, NULL, 'v'},                                          Line 104
  {GETOPT_HELP_OPTION_DECL},                                                    Line 105
  {GETOPT_VERSION_OPTION_DECL},                                                 Line 106
  {NULL, 0, NULL, 0}                                                            Line 107
};                                                                              Block 4
                                                                                
/* Return true if the chmodable permission bits of FILE changed.                
   The old mode was OLD_MODE, but it was changed to NEW_MODE.  */               
                                                                                
static bool                                                                     Line 113
mode_changed (int dir_fd, char const *file, char const *file_full_name,         Line 114
              mode_t old_mode, mode_t new_mode)                                 Line 115
{                                                                               
  if (new_mode & (S_ISUID | S_ISGID | S_ISVTX))                                 Line 117
    {                                                                           
      /* The new mode contains unusual bits that the call to chmod may          
         have silently cleared.  Check whether they actually changed.  */       
                                                                                
      struct stat new_stats;                                                    Line 122
                                                                                
      if (fstatat (dir_fd, file, &new_stats, 0) != 0)                           Line 124...!syscalls auto-comment...
        {                                                                       
          if (! force_silent)                                                   Line 126
            error (0, errno, _("getting new attributes of %s"),                 Line 127
                   quoteaf (file_full_name));                                   Line 128
          return false;                                                         Line 129
        }                                                                       
                                                                                
      new_mode = new_stats.st_mode;                                             Line 132
    }                                                                           
                                                                                
  return ((old_mode ^ new_mode) & CHMOD_MODE_BITS) != 0;                        Line 135
}                                                                               Block 5
                                                                                
/* Tell the user how/if the MODE of FILE has been changed.                      
   CHANGED describes what (if anything) has happened. */                        
                                                                                
static void                                                                     Line 141
describe_change (const char *file, mode_t old_mode, mode_t mode,                Line 142
                 enum Change_status changed)                                    Line 143
{                                                                               
  char perms[12];  /* "-rwxrwxrwx" ls-style modes. */                           Line 145
  char old_perms[12];                                                           Line 146
  const char *fmt;                                                              Line 147
                                                                                
  if (changed == CH_NOT_APPLIED)                                                Line 149
    {                                                                           
      printf (_("neither symbolic link %s nor referent has been changed\n"),    Line 151
              quoteaf (file));                                                  Line 152
      return;                                                                   Line 153
    }                                                                           
                                                                                
  strmode (mode, perms);                                                        Line 156
  perms[10] = '\0';  /* Remove trailing space.  */                              Line 157
                                                                                
  strmode (old_mode, old_perms);                                                Line 159
  old_perms[10] = '\0';  /* Remove trailing space.  */                          Line 160
                                                                                
  switch (changed)                                                              Line 162
    {                                                                           
    case CH_SUCCEEDED:                                                          Line 164
      fmt = _("mode of %s changed from %04lo (%s) to %04lo (%s)\n");            Line 165
      break;                                                                    Line 166
    case CH_FAILED:                                                             Line 167
      fmt = _("failed to change mode of %s from %04lo (%s) to %04lo (%s)\n");   Line 168
      break;                                                                    Line 169
    case CH_NO_CHANGE_REQUESTED:                                                Line 170
      fmt = _("mode of %s retained as %04lo (%s)\n");                           Line 171
      printf (fmt, quoteaf (file),                                              Line 172
              (unsigned long int) (mode & CHMOD_MODE_BITS), &perms[1]);         Line 173
      return;                                                                   Line 174
    default:                                                                    Line 175
      abort ();                                                                 ...!common auto-comment...
    }                                                                           
  printf (fmt, quoteaf (file),                                                  Line 178
          (unsigned long int) (old_mode & CHMOD_MODE_BITS), &old_perms[1],      Line 179
          (unsigned long int) (mode & CHMOD_MODE_BITS), &perms[1]);             Line 180
}                                                                               Block 6
                                                                                
/* Change the mode of FILE.                                                     
   Return true if successful.  This function is called                          
   once for every file system object that fts encounters.  */                   
                                                                                
static bool                                                                     Line 187
process_file (FTS *fts, FTSENT *ent)                                            Line 188
{                                                                               
  char const *file_full_name = ent->fts_path;                                   Line 190
  char const *file = ent->fts_accpath;                                          Line 191
  const struct stat *file_stats = ent->fts_statp;                               Line 192
  mode_t old_mode IF_LINT ( = 0);                                               Line 193
  mode_t new_mode IF_LINT ( = 0);                                               Line 194
  bool ok = true;                                                               Line 195
  bool chmod_succeeded = false;                                                 Line 196
                                                                                
  switch (ent->fts_info)                                                        Line 198
    {                                                                           
    case FTS_DP:                                                                Line 200
      return true;                                                              Line 201
                                                                                
    case FTS_NS:                                                                Line 203
      /* For a top-level file or directory, this FTS_NS (stat failed)           
         indicator is determined at the time of the initial fts_open call.      
         With programs like chmod, chown, and chgrp, that modify                
         permissions, it is possible that the file in question is               
         accessible when control reaches this point.  So, if this is            
         the first time we've seen the FTS_NS for this file, tell               
         fts_read to stat it "again".  */                                       
      if (ent->fts_level == 0 && ent->fts_number == 0)                          Line 211
        {                                                                       
          ent->fts_number = 1;                                                  Line 213
          fts_set (fts, ent, FTS_AGAIN);                                        Line 214
          return true;                                                          Line 215
        }                                                                       
      if (! force_silent)                                                       Line 217
        error (0, ent->fts_errno, _("cannot access %s"),                        Line 218
               quoteaf (file_full_name));                                       Line 219
      ok = false;                                                               Line 220
      break;                                                                    Line 221
                                                                                
    case FTS_ERR:                                                               Line 223
      if (! force_silent)                                                       Line 224
        error (0, ent->fts_errno, "%s", quotef (file_full_name));               Line 225
      ok = false;                                                               Line 226
      break;                                                                    Line 227
                                                                                
    case FTS_DNR:                                                               Line 229
      if (! force_silent)                                                       Line 230
        error (0, ent->fts_errno, _("cannot read directory %s"),                Line 231
               quoteaf (file_full_name));                                       Line 232
      ok = false;                                                               Line 233
      break;                                                                    Line 234
                                                                                
    case FTS_SLNONE:                                                            Line 236
      if (! force_silent)                                                       Line 237
        error (0, 0, _("cannot operate on dangling symlink %s"),                Line 238
               quoteaf (file_full_name));                                       Line 239
      ok = false;                                                               Line 240
      break;                                                                    Line 241
                                                                                
    case FTS_DC:  /* directory that causes cycles */                            Line 243
      if (cycle_warning_required (fts, ent))                                    Line 244
        {                                                                       
          emit_cycle_warning (file_full_name);                                  Line 246
          return false;                                                         Line 247
        }                                                                       
      break;                                                                    Line 249
                                                                                
    default:                                                                    Line 251
      break;                                                                    Line 252
    }                                                                           
                                                                                
  if (ok && ROOT_DEV_INO_CHECK (root_dev_ino, file_stats))                      Line 255
    {                                                                           
      ROOT_DEV_INO_WARN (file_full_name);                                       Line 257
      /* Tell fts not to traverse into this hierarchy.  */                      
      fts_set (fts, ent, FTS_SKIP);                                             Line 259
      /* Ensure that we do not process "/" on the second visit.  */             
      ignore_value (fts_read (fts));                                            Line 261...!syscalls auto-comment...
      return false;                                                             Line 262
    }                                                                           
                                                                                
  if (ok)                                                                       Line 265
    {                                                                           
      old_mode = file_stats->st_mode;                                           Line 267
      new_mode = mode_adjust (old_mode, S_ISDIR (old_mode) != 0, umask_value,   Line 268
                              change, NULL);                                    Line 269
                                                                                
      if (! S_ISLNK (old_mode))                                                 Line 271
        {                                                                       
          if (chmodat (fts->fts_cwd_fd, file, new_mode) == 0)                   Line 273
            chmod_succeeded = true;                                             Line 274
          else                                                                  Line 275
            {                                                                   
              if (! force_silent)                                               Line 277
                error (0, errno, _("changing permissions of %s"),               Line 278
                       quoteaf (file_full_name));                               Line 279
              ok = false;                                                       Line 280
            }                                                                   
        }                                                                       
    }                                                                           
                                                                                
  if (verbosity != V_off)                                                       Line 285
    {                                                                           
      bool changed = (chmod_succeeded                                           Line 287
                      && mode_changed (fts->fts_cwd_fd, file, file_full_name,   Line 288
                                       old_mode, new_mode));                    Line 289
                                                                                
      if (changed || verbosity == V_high)                                       Line 291
        {                                                                       
          enum Change_status ch_status =                                        Line 293
            (!ok ? CH_FAILED                                                    Line 294
             : !chmod_succeeded ? CH_NOT_APPLIED                                Line 295
             : !changed ? CH_NO_CHANGE_REQUESTED                                Line 296
             : CH_SUCCEEDED);                                                   Line 297
          describe_change (file_full_name, old_mode, new_mode, ch_status);      Line 298
        }                                                                       
    }                                                                           
                                                                                
  if (chmod_succeeded && diagnose_surprises)                                    Line 302
    {                                                                           
      mode_t naively_expected_mode =                                            Line 304
        mode_adjust (old_mode, S_ISDIR (old_mode) != 0, 0, change, NULL);       Line 305
      if (new_mode & ~naively_expected_mode)                                    Line 306
        {                                                                       
          char new_perms[12];                                                   Line 308
          char naively_expected_perms[12];                                      Line 309
          strmode (new_mode, new_perms);                                        Line 310
          strmode (naively_expected_mode, naively_expected_perms);              Line 311
          new_perms[10] = naively_expected_perms[10] = '\0';                    Line 312
          error (0, 0,                                                          Line 313
                 _("%s: new permissions are %s, not %s"),                       Line 314
                 quotef (file_full_name),                                       Line 315
                 new_perms + 1, naively_expected_perms + 1);                    Line 316
          ok = false;                                                           Line 317
        }                                                                       
    }                                                                           
                                                                                
  if ( ! recurse)                                                               Line 321
    fts_set (fts, ent, FTS_SKIP);                                               Line 322
                                                                                
  return ok;                                                                    Line 324
}                                                                               Block 7
                                                                                
/* Recursively change the modes of the specified FILES (the last entry          
   of which is NULL).  BIT_FLAGS controls how fts works.                        
   Return true if successful.  */                                               
                                                                                
static bool                                                                     Line 331
process_files (char **files, int bit_flags)                                     Line 332
{                                                                               
  bool ok = true;                                                               Line 334
                                                                                
  FTS *fts = xfts_open (files, bit_flags, NULL);                                Line 336...!syscalls auto-comment...
                                                                                
  while (1)                                                                     Line 338
    {                                                                           
      FTSENT *ent;                                                              Line 340
                                                                                
      ent = fts_read (fts);                                                     Line 342...!syscalls auto-comment...
      if (ent == NULL)                                                          Line 343
        {                                                                       
          if (errno != 0)                                                       Line 345
            {                                                                   
              /* FIXME: try to give a better message  */                        
              if (! force_silent)                                               Line 348
                error (0, errno, _("fts_read failed"));                         Line 349
              ok = false;                                                       Line 350
            }                                                                   
          break;                                                                Line 352
        }                                                                       
                                                                                
      ok &= process_file (fts, ent);                                            Line 355
    }                                                                           
                                                                                
  if (fts_close (fts) != 0)                                                     Line 358...!syscalls auto-comment...
    {                                                                           
      error (0, errno, _("fts_close failed"));                                  Line 360
      ok = false;                                                               Line 361
    }                                                                           
                                                                                
  return ok;                                                                    Line 364
}                                                                               Block 8
                                                                                
void                                                                            Line 367
usage (int status)                                                              Line 368
{                                                                               
  if (status != EXIT_SUCCESS)                                                   Line 370
    emit_try_help ();                                                           ...!common auto-comment...
  else                                                                          Line 372
    {                                                                           
      printf (_("\                                                              Line 374
Usage: %s [OPTION]... MODE[,MODE]... FILE...\n\                                 Line 375
  or:  %s [OPTION]... OCTAL-MODE FILE...\n\                                     Line 376
  or:  %s [OPTION]... --reference=RFILE FILE...\n\                              Line 377
"),                                                                             Line 378
              program_name, program_name, program_name);                        Line 379
      fputs (_("\                                                               Line 380
Change the mode of each FILE to MODE.\n\                                        Line 381
With --reference, change the mode of each FILE to that of RFILE.\n\             Line 382
\n\                                                                             
"), stdout);                                                                    Line 384
      fputs (_("\                                                               Line 385
  -c, --changes          like verbose but report only when a change is made\n\  Line 386
  -f, --silent, --quiet  suppress most error messages\n\                        Line 387
  -v, --verbose          output a diagnostic for every file processed\n\        Line 388
"), stdout);                                                                    Line 389
      fputs (_("\                                                               Line 390
      --no-preserve-root  do not treat '/' specially (the default)\n\           Line 391
      --preserve-root    fail to operate recursively on '/'\n\                  Line 392
"), stdout);                                                                    Line 393
      fputs (_("\                                                               Line 394
      --reference=RFILE  use RFILE's mode instead of MODE values\n\             Line 395
"), stdout);                                                                    Line 396
      fputs (_("\                                                               Line 397
  -R, --recursive        change files and directories recursively\n\            Line 398
"), stdout);                                                                    Line 399
      fputs (HELP_OPTION_DESCRIPTION, stdout);                                  Line 400
      fputs (VERSION_OPTION_DESCRIPTION, stdout);                               Line 401
      fputs (_("\                                                               Line 402
\n\                                                                             
Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=][0-7]+'.\n\     Line 404
"), stdout);                                                                    Line 405
      emit_ancillary_info (PROGRAM_NAME);                                       Line 406
    }                                                                           
  exit (status);                                                                Line 408
}                                                                               Block 9
                                                                                
/* Parse the ASCII mode given on the command line into a linked list            
   of 'struct mode_change' and apply that to each file argument. */             
                                                                                
int                                                                             
main (int argc, char **argv)                                                    Line 415
{                                                                               
  char *mode = NULL;                                                            Line 417
  size_t mode_len = 0;                                                          Line 418
  size_t mode_alloc = 0;                                                        Line 419
  bool ok;                                                                      Line 420
  bool preserve_root = false;                                                   Line 421
  char const *reference_file = NULL;                                            Line 422
  int c;                                                                        Line 423
                                                                                
  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)
                                                                                
  recurse = force_silent = diagnose_surprises = false;                          Line 433
                                                                                
  while ((c = getopt_long (argc, argv,                                          Line 435
                           ("Rcfvr::w::x::X::s::t::u::g::o::a::,::+::=::"       Line 436
                            "0::1::2::3::4::5::6::7::"),                        Line 437
                           long_options, NULL))                                 Line 438
         != -1)                                                                 Line 439
    {                                                                           
      switch (c)                                                                Line 441
        {                                                                       
        case 'r':                                                               Line 443
        case 'w':                                                               Line 444
        case 'x':                                                               Line 445
        case 'X':                                                               Line 446
        case 's':                                                               Line 447
        case 't':                                                               Line 448
        case 'u':                                                               Line 449
        case 'g':                                                               Line 450
        case 'o':                                                               Line 451
        case 'a':                                                               Line 452
        case ',':                                                               Line 453
        case '+':                                                               Line 454
        case '=':                                                               Line 455
        case '0': case '1': case '2': case '3':                                 Line 456
        case '4': case '5': case '6': case '7':                                 Line 457
          /* Support nonportable uses like "chmod -w", but diagnose             
             surprises due to umask confusion.  Even though "--", "--r",        
             etc., are valid modes, there is no "case '-'" here since           
             getopt_long reserves leading "--" for long options.  */            
          {                                                                     
            /* Allocate a mode string (e.g., "-rwx") by concatenating           
               the argument containing this option.  If a previous mode         
               string was given, concatenate the previous string, a             
               comma, and the new string (e.g., "-s,-rwx").  */                 
                                                                                
            char const *arg = argv[optind - 1];                                 Line 468
            size_t arg_len = strlen (arg);                                      Line 469
            size_t mode_comma_len = mode_len + !!mode_len;                      Line 470
            size_t new_mode_len = mode_comma_len + arg_len;                     Line 471
            if (mode_alloc <= new_mode_len)                                     Line 472
              {                                                                 
                mode_alloc = new_mode_len + 1;                                  Line 474
                mode = X2REALLOC (mode, &mode_alloc);                           Line 475
              }                                                                 
            mode[mode_len] = ',';                                               Line 477
            memcpy (mode + mode_comma_len, arg, arg_len + 1);                   Line 478
            mode_len = new_mode_len;                                            Line 479
                                                                                
            diagnose_surprises = true;                                          Line 481
          }                                                                     
          break;                                                                Line 483
        case NO_PRESERVE_ROOT:                                                  Line 484
          preserve_root = false;                                                Line 485
          break;                                                                Line 486
        case PRESERVE_ROOT:                                                     Line 487
          preserve_root = true;                                                 Line 488
          break;                                                                Line 489
        case REFERENCE_FILE_OPTION:                                             Line 490
          reference_file = optarg;                                              Line 491
          break;                                                                Line 492
        case 'R':                                                               Line 493
          recurse = true;                                                       Line 494
          break;                                                                Line 495
        case 'c':                                                               Line 496
          verbosity = V_changes_only;                                           Line 497
          break;                                                                Line 498
        case 'f':                                                               Line 499
          force_silent = true;                                                  Line 500
          break;                                                                Line 501
        case 'v':                                                               Line 502
          verbosity = V_high;                                                   Line 503
          break;                                                                Line 504
        case_GETOPT_HELP_CHAR;                                                  Line 505
        case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);                       Line 506
        default:                                                                Line 507
          usage (EXIT_FAILURE);                                                 Line 508
        }                                                                       
    }                                                                           
                                                                                
  if (reference_file)                                                           Line 512
    {                                                                           
      if (mode)                                                                 Line 514
        {                                                                       
          error (0, 0, _("cannot combine mode and --reference options"));       Line 516
          usage (EXIT_FAILURE);                                                 Line 517
        }                                                                       
    }                                                                           
  else                                                                          Line 520
    {                                                                           
      if (!mode)                                                                Line 522
        mode = argv[optind++];                                                  Line 523
    }                                                                           
                                                                                
  if (optind >= argc)                                                           Line 526
    {                                                                           
      if (!mode || mode != argv[optind - 1])                                    Line 528
        error (0, 0, _("missing operand"));                                     Line 529
      else                                                                      Line 530
        error (0, 0, _("missing operand after %s"), quote (argv[argc - 1]));    Line 531
      usage (EXIT_FAILURE);                                                     Line 532
    }                                                                           
                                                                                
  if (reference_file)                                                           Line 535
    {                                                                           
      change = mode_create_from_ref (reference_file);                           Line 537
      if (!change)                                                              Line 538
        die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),          Line 539
             quoteaf (reference_file));                                         Line 540
    }                                                                           
  else                                                                          Line 542
    {                                                                           
      change = mode_compile (mode);                                             Line 544
      if (!change)                                                              Line 545
        {                                                                       
          error (0, 0, _("invalid mode: %s"), quote (mode));                    Line 547
          usage (EXIT_FAILURE);                                                 Line 548
        }                                                                       
      umask_value = umask (0);                                                  Line 550
    }                                                                           
                                                                                
  if (recurse && preserve_root)                                                 Line 553
    {                                                                           
      static struct dev_ino dev_ino_buf;                                        Line 555
      root_dev_ino = get_root_dev_ino (&dev_ino_buf);                           Line 556
      if (root_dev_ino == NULL)                                                 Line 557
        die (EXIT_FAILURE, errno, _("failed to get attributes of %s"),          Line 558
             quoteaf ("/"));                                                    Line 559
    }                                                                           
  else                                                                          Line 561
    {                                                                           
      root_dev_ino = NULL;                                                      Line 563
    }                                                                           
                                                                                
  ok = process_files (argv + optind,                                            Line 566
                      FTS_COMFOLLOW | FTS_PHYSICAL | FTS_DEFER_STAT);           Line 567
                                                                                
  IF_LINT (free (change));                                                      Line 569
                                                                                
  return ok ? EXIT_SUCCESS : EXIT_FAILURE;                                      Line 571
}                                                                               Block 10