1/* remove.c -- core functions for removing files and directories
2   Copyright (C) 1988, 1990-1991, 1994-2010 Free Software Foundation, Inc.
3
4   This program is free software: you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation, either version 3 of the License, or
7   (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful,
10   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17/* Extracted from rm.c and librarified, then rewritten twice by Jim Meyering.  */
18
19#include <config.h>
20#include <stdio.h>
21#include <sys/types.h>
22#include <assert.h>
23
24#include "system.h"
25#include "error.h"
26#include "euidaccess-stat.h"
27#include "file-type.h"
28#include "hash.h"
29#include "hash-pjw.h"
30#include "obstack.h"
31#include "quote.h"
32#include "remove.h"
33#include "root-dev-ino.h"
34#include "write-any-file.h"
35#include "xfts.h"
36#include "yesno.h"
37
38enum Ternary
39  {
40    T_UNKNOWN = 2,
41    T_NO,
42    T_YES
43  };
44typedef enum Ternary Ternary;
45
46/* The prompt function may be called twice for a given directory.
47   The first time, we ask whether to descend into it, and the
48   second time, we ask whether to remove it.  */
49enum Prompt_action
50  {
51    PA_DESCEND_INTO_DIR = 2,
52    PA_REMOVE_DIR
53  };
54
55/* D_TYPE(D) is the type of directory entry D if known, DT_UNKNOWN
56   otherwise.  */
57#if ! HAVE_STRUCT_DIRENT_D_TYPE
58/* Any int values will do here, so long as they're distinct.
59   Undef any existing macros out of the way.  */
60# undef DT_UNKNOWN
61# undef DT_DIR
62# undef DT_LNK
63# define DT_UNKNOWN 0
64# define DT_DIR 1
65# define DT_LNK 2
66#endif
67
68/* Like fstatat, but cache the result.  If ST->st_size is -1, the
69   status has not been gotten yet.  If less than -1, fstatat failed
70   with errno == ST->st_ino.  Otherwise, the status has already
71   been gotten, so return 0.  */
72static int
73cache_fstatat (int fd, char const *file, struct stat *st, int flag)
74{
75  if (st->st_size == -1 && fstatat (fd, file, st, flag) != 0)
76    {
77      st->st_size = -2;
78      st->st_ino = errno;
79    }
80  if (0 <= st->st_size)
81    return 0;
82  errno = (int) st->st_ino;
83  return -1;
84}
85
86/* Initialize a fstatat cache *ST.  Return ST for convenience.  */
87static inline struct stat *
88cache_stat_init (struct stat *st)
89{
90  st->st_size = -1;
91  return st;
92}
93
94/* Return true if *ST has been statted.  */
95static inline bool
96cache_statted (struct stat *st)
97{
98  return (st->st_size != -1);
99}
100
101/* Return true if *ST has been statted successfully.  */
102static inline bool
103cache_stat_ok (struct stat *st)
104{
105  return (0 <= st->st_size);
106}
107
108/* Return 1 if FILE is an unwritable non-symlink,
109   0 if it is writable or some other type of file,
110   -1 and set errno if there is some problem in determining the answer.
111   Use FULL_NAME only if necessary.
112   Set *BUF to the file status.
113   This is to avoid calling euidaccess when FILE is a symlink.  */
114static int
115write_protected_non_symlink (int fd_cwd,
116                             char const *file,
117                             char const *full_name,
118                             struct stat *buf)
119{
120  if (can_write_any_file ())
121    return 0;
122  if (cache_fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
123    return -1;
124  if (S_ISLNK (buf->st_mode))
125    return 0;
126  /* Here, we know FILE is not a symbolic link.  */
127
128  /* In order to be reentrant -- i.e., to avoid changing the working
129     directory, and at the same time to be able to deal with alternate
130     access control mechanisms (ACLs, xattr-style attributes) and
131     arbitrarily deep trees -- we need a function like eaccessat, i.e.,
132     like Solaris' eaccess, but fd-relative, in the spirit of openat.  */
133
134  /* In the absence of a native eaccessat function, here are some of
135     the implementation choices [#4 and #5 were suggested by Paul Eggert]:
136     1) call openat with O_WRONLY|O_NOCTTY
137        Disadvantage: may create the file and doesn't work for directory,
138        may mistakenly report `unwritable' for EROFS or ACLs even though
139        perm bits say the file is writable.
140
141     2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
142        Disadvantage: changes working directory (not reentrant) and can't
143        work if save_cwd fails.
144
145     3) if (euidaccess (full_name, W_OK) == 0)
146        Disadvantage: doesn't work if full_name is too long.
147        Inefficient for very deep trees (O(Depth^2)).
148
149     4) If the full pathname is sufficiently short (say, less than
150        PATH_MAX or 8192 bytes, whichever is shorter):
151        use method (3) (i.e., euidaccess (full_name, W_OK));
152        Otherwise: vfork, fchdir in the child, run euidaccess in the
153        child, then the child exits with a status that tells the parent
154        whether euidaccess succeeded.
155
156        This avoids the O(N**2) algorithm of method (3), and it also avoids
157        the failure-due-to-too-long-file-names of method (3), but it's fast
158        in the normal shallow case.  It also avoids the lack-of-reentrancy
159        and the save_cwd problems.
160        Disadvantage; it uses a process slot for very-long file names,
161        and would be very slow for hierarchies with many such files.
162
163     5) If the full file name is sufficiently short (say, less than
164        PATH_MAX or 8192 bytes, whichever is shorter):
165        use method (3) (i.e., euidaccess (full_name, W_OK));
166        Otherwise: look just at the file bits.  Perhaps issue a warning
167        the first time this occurs.
168
169        This is like (4), except for the "Otherwise" case where it isn't as
170        "perfect" as (4) but is considerably faster.  It conforms to current
171        POSIX, and is uniformly better than what Solaris and FreeBSD do (they
172        mess up with long file names). */
173
174  {
175    /* This implements #1: on decent systems, either faccessat is
176       native or /proc/self/fd allows us to skip a chdir.  */
177    if (!openat_needs_fchdir ()
178        && faccessat (fd_cwd, file, W_OK, AT_EACCESS) == 0)
179      return 0;
180
181    {
182    /* This implements #5: */
183    size_t file_name_len = strlen (full_name);
184
185    if (MIN (PATH_MAX, 8192) <= file_name_len)
186      return ! euidaccess_stat (buf, W_OK);
187    if (euidaccess (full_name, W_OK) == 0)
188      return 0;
189    if (errno == EACCES)
190      {
191        errno = 0;
192        return 1;
193      }
194    }
195
196    /* Perhaps some other process has removed the file, or perhaps this
197       is a buggy NFS client.  */
198    return -1;
199  }
200}
201
202/* Prompt whether to remove FILENAME (ent->, if required via a combination of
203   the options specified by X and/or file attributes.  If the file may
204   be removed, return RM_OK.  If the user declines to remove the file,
205   return RM_USER_DECLINED.  If not ignoring missing files and we
206   cannot lstat FILENAME, then return RM_ERROR.
207
208   IS_DIR is true if ENT designates a directory, false otherwise.
209
210   Depending on MODE, ask whether to `descend into' or to `remove' the
211   directory FILENAME.  MODE is ignored when FILENAME is not a directory.
212   Set *IS_EMPTY_P to T_YES if FILENAME is an empty directory, and it is
213   appropriate to try to remove it with rmdir (e.g. recursive mode).
214   Don't even try to set *IS_EMPTY_P when MODE == PA_REMOVE_DIR.  */
215static enum RM_status
216prompt (FTS const *fts, FTSENT const *ent, bool is_dir,
217        struct rm_options const *x, enum Prompt_action mode,
218        Ternary *is_empty_p)
219{
220  int wp_errno;
221  int fd_cwd = fts->fts_cwd_fd;
222  char const *full_name = ent->fts_path;
223  char const *filename = ent->fts_accpath;
224  struct stat st;
225  struct stat *sbuf = &st;
226  int dirent_type = is_dir ? DT_DIR : DT_UNKNOWN;
227  int write_protected = 0;
228  if (is_empty_p)
229    *is_empty_p = T_UNKNOWN;
230
231
232  cache_stat_init (sbuf);
233
234  /* When nonzero, this indicates that we failed to remove a child entry,
235     either because the user declined an interactive prompt, or due to
236     some other failure, like permissions.  */
237  if (ent->fts_number)
238    return RM_USER_DECLINED;
239
240  if (x->interactive == RMI_NEVER)
241    return RM_OK;
242
243  wp_errno = 0;
244  if (!x->ignore_missing_files
245      && ((x->interactive == RMI_ALWAYS) || x->stdin_tty)
246      && dirent_type != DT_LNK)
247    {
248      write_protected = write_protected_non_symlink (fd_cwd, filename,
249                                                     full_name, sbuf);
250      wp_errno = errno;
251    }
252
253  if (write_protected || errno || x->interactive == RMI_ALWAYS)
254    {
255      if (0 <= write_protected && dirent_type == DT_UNKNOWN)
256        {
257          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) == 0)
258            {
259              if (S_ISLNK (sbuf->st_mode))
260                dirent_type = DT_LNK;
261              else if (S_ISDIR (sbuf->st_mode))
262                dirent_type = DT_DIR;
263              /* Otherwise it doesn't matter, so leave it DT_UNKNOWN.  */
264            }
265          else
266            {
267              /* This happens, e.g., with `rm '''.  */
268              write_protected = -1;
269              wp_errno = errno;
270            }
271        }
272
273      if (0 <= write_protected)
274        switch (dirent_type)
275          {
276          case DT_LNK:
277            /* Using permissions doesn't make sense for symlinks.  */
278            if (x->interactive != RMI_ALWAYS)
279              return RM_OK;
280            break;
281
282          case DT_DIR:
283            if (!x->recursive)
284              {
285                write_protected = -1;
286                wp_errno = EISDIR;
287              }
288            break;
289          }
290      {
291      char const *quoted_name = quote (full_name);
292      bool is_empty;
293
294      if (write_protected < 0)
295        {
296          error (0, wp_errno, _("cannot remove %s"), quoted_name);
297          return RM_ERROR;
298        }
299
300
301      if (is_empty_p)
302        {
303          is_empty = is_empty_dir (fd_cwd, filename);
304          *is_empty_p = is_empty ? T_YES : T_NO;
305        }
306      else
307        is_empty = false;
308
309      /* Issue the prompt.  */
310      if (dirent_type == DT_DIR
311          && mode == PA_DESCEND_INTO_DIR
312          && !is_empty)
313        fprintf (stderr,
314                 (write_protected
315                  ? _("%s: descend into write-protected directory %s? ")
316                  : _("%s: descend into directory %s? ")),
317                 program_name, quoted_name);
318      else
319        {
320          if (cache_fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW) != 0)
321            {
322              error (0, errno, _("cannot remove %s"), quoted_name);
323              return RM_ERROR;
324            }
325
326          fprintf (stderr,
327                   (write_protected
328                    /* TRANSLATORS: You may find it more convenient to
329                       translate "%s: remove %s (write-protected) %s? "
330                       instead.  It should avoid grammatical problems
331                       with the output of file_type.  */
332                    ? _("%s: remove write-protected %s %s? ")
333                    : _("%s: remove %s %s? ")),
334                   program_name, file_type (sbuf), quoted_name);
335        }
336      }
337
338      if (!yesno ())
339        return RM_USER_DECLINED;
340    }
341  return RM_OK;
342}
343
344/* Return true if FILENAME is a directory (and not a symlink to a directory).
345   Otherwise, including the case in which lstat fails, return false.
346   *ST is FILENAME's tstatus.
347   Do not modify errno.  */
348static inline bool
349is_dir_lstat (int fd_cwd, char const *filename, struct stat *st)
350{
351  int saved_errno = errno;
352  bool is_dir =
353    (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
354     && S_ISDIR (st->st_mode));
355  errno = saved_errno;
356  return is_dir;
357}
358
359/* Return true if FILENAME is a non-directory.
360   Otherwise, including the case in which lstat fails, return false.
361   *ST is FILENAME's tstatus.
362   Do not modify errno.  */
363static inline bool
364is_nondir_lstat (int fd_cwd, char const *filename, struct stat *st)
365{
366  int saved_errno = errno;
367  bool is_non_dir =
368    (cache_fstatat (fd_cwd, filename, st, AT_SYMLINK_NOFOLLOW) == 0
369     && !S_ISDIR (st->st_mode));
370  errno = saved_errno;
371  return is_non_dir;
372}
373
374/* When a function like unlink, rmdir, or fstatat fails with an errno
375   value of ERRNUM, return true if the specified file system object
376   is guaranteed not to exist;  otherwise, return false.  */
377static inline bool
378nonexistent_file_errno (int errnum)
379{
380  /* Do not include ELOOP here, since the specified file may indeed
381     exist, but be (in)accessible only via too long a symlink chain.
382     Likewise for ENAMETOOLONG, since rm -f ./././.../foo may fail
383     if the "..." part expands to a long enough sequence of "./"s,
384     even though ./foo does indeed exist.  */
385
386  switch (errnum)
387    {
388    case ENOENT:
389    case ENOTDIR:
390      return true;
391    default:
392      return false;
393    }
394}
395
396/* Encapsulate the test for whether the errno value, ERRNUM, is ignorable.  */
397static inline bool
398ignorable_missing (struct rm_options const *x, int errnum)
399{
400  return x->ignore_missing_files && nonexistent_file_errno (errnum);
401}
402
403/* Tell fts not to traverse into the hierarchy at ENT.  */
404static void
405fts_skip_tree (FTS *fts, FTSENT *ent)
406{
407  fts_set (fts, ent, FTS_SKIP);
408  /* Ensure that we do not process ENT a second time.  */
409  ent = fts_read (fts);
410}
411
412/* Upon unlink failure, or when the user declines to remove ENT, mark
413   each of its ancestor directories, so that we know not to prompt for
414   its removal.  */
415static void
416mark_ancestor_dirs (FTSENT *ent)
417{
418  FTSENT *p;
419  for (p = ent->fts_parent; FTS_ROOTLEVEL <= p->fts_level; p = p->fts_parent)
420    {
421      if (p->fts_number)
422        break;
423      p->fts_number = 1;
424    }
425}
426
427/* Remove the file system object specified by ENT.  IS_DIR specifies
428   whether it is expected to be a directory or non-directory.
429   Return RM_OK upon success, else RM_ERROR.  */
430static enum RM_status
431excise (FTS *fts, FTSENT *ent, struct rm_options const *x, bool is_dir)
432{
433  int flag = is_dir ? AT_REMOVEDIR : 0;
434  if (unlinkat (fts->fts_cwd_fd, ent->fts_accpath, flag) == 0)
435    {
436      if (x->verbose)
437        {
438          printf ((is_dir
439                   ? _("removed directory: %s\n")
440                   : _("removed %s\n")), quote (ent->fts_path));
441        }
442      return RM_OK;
443    }
444
445  /* The unlinkat from kernels like linux-2.6.32 reports EROFS even for
446     nonexistent files.  When the file is indeed missing, map that to ENOENT,
447     so that rm -f ignores it, as required.  Even without -f, this is useful
448     because it makes rm print the more precise diagnostic.  */
449  if (errno == EROFS)
450    {
451      struct stat st;
452      if ( ! (lstatat (fts->fts_cwd_fd, ent->fts_accpath, &st)
453                       && errno == ENOENT))
454        errno = EROFS;
455    }
456
457  if (ignorable_missing (x, errno))
458    return RM_OK;
459
460  /* When failing to rmdir an unreadable directory, the typical
461     errno value is EISDIR, but that is not as useful to the user
462     as the errno value from the failed open (probably EPERM).
463     Use the earlier, more descriptive errno value.  */
464  if (ent->fts_info == FTS_DNR)
465    errno = ent->fts_errno;
466  error (0, errno, _("cannot remove %s"), quote (ent->fts_path));
467  mark_ancestor_dirs (ent);
468  return RM_ERROR;
469}
470
471/* This function is called once for every file system object that fts
472   encounters.  fts performs a depth-first traversal.
473   A directory is usually processed twice, first with fts_info == FTS_D,
474   and later, after all of its entries have been processed, with FTS_DP.
475   Return RM_ERROR upon error, RM_USER_DECLINED for a negative response
476   to an interactive prompt, and otherwise, RM_OK.  */
477static enum RM_status
478rm_fts (FTS *fts, FTSENT *ent, struct rm_options const *x)
479{
480  switch (ent->fts_info)
481    {
482    case FTS_D:			/* preorder directory */
483      if (! x->recursive)
484        {
485          /* This is the first (pre-order) encounter with a directory.
486             Not recursive, so arrange to skip contents.  */
487          error (0, EISDIR, _("cannot remove %s"), quote (ent->fts_path));
488          mark_ancestor_dirs (ent);
489          fts_skip_tree (fts, ent);
490          return RM_ERROR;
491        }
492
493      /* Perform checks that can apply only for command-line arguments.  */
494      if (ent->fts_level == FTS_ROOTLEVEL)
495        {
496          if (strip_trailing_slashes (ent->fts_path))
497            ent->fts_pathlen = strlen (ent->fts_path);
498
499          /* If the basename of a command line argument is "." or "..",
500             diagnose it and do nothing more with that argument.  */
501          if (dot_or_dotdot (last_component (ent->fts_accpath)))
502            {
503              error (0, 0, _("cannot remove directory: %s"),
504                     quote (ent->fts_path));
505              fts_skip_tree (fts, ent);
506              return RM_ERROR;
507            }
508
509          /* If a command line argument resolves to "/" (and --preserve-root
510             is in effect -- default) diagnose and skip it.  */
511          if (ROOT_DEV_INO_CHECK (x->root_dev_ino, ent->fts_statp))
512            {
513              ROOT_DEV_INO_WARN (ent->fts_path);
514              fts_skip_tree (fts, ent);
515              return RM_ERROR;
516            }
517        }
518
519      {
520        Ternary is_empty_directory;
521        enum RM_status s = prompt (fts, ent, true /*is_dir*/, x,
522                                   PA_DESCEND_INTO_DIR, &is_empty_directory);
523
524        if (s == RM_OK && is_empty_directory == T_YES)
525          {
526            /* When we know (from prompt when in interactive mode)
527               that this is an empty directory, don't prompt twice.  */
528            s = excise (fts, ent, x, true);
529            fts_skip_tree (fts, ent);
530          }
531
532        if (s != RM_OK)
533          {
534            mark_ancestor_dirs (ent);
535            fts_skip_tree (fts, ent);
536          }
537
538        return s;
539      }
540
541    case FTS_F:			/* regular file */
542    case FTS_NS:		/* stat(2) failed */
543    case FTS_SL:		/* symbolic link */
544    case FTS_SLNONE:		/* symbolic link without target */
545    case FTS_DP:		/* postorder directory */
546    case FTS_DNR:		/* unreadable directory */
547    case FTS_NSOK:		/* e.g., dangling symlink */
548    case FTS_DEFAULT:		/* none of the above */
549      {
550        /* With --one-file-system, do not attempt to remove a mount point.
551           fts' FTS_XDEV ensures that we don't process any entries under
552           the mount point.  */
553        if (ent->fts_info == FTS_DP
554            && x->one_file_system
555            && FTS_ROOTLEVEL < ent->fts_level
556            && ent->fts_statp->st_dev != fts->fts_dev)
557          {
558            mark_ancestor_dirs (ent);
559            error (0, 0, _("skipping %s, since it's on a different device"),
560                   quote (ent->fts_path));
561            return RM_ERROR;
562          }
563
564        {
565        bool is_dir = ent->fts_info == FTS_DP || ent->fts_info == FTS_DNR;
566        enum RM_status s = prompt (fts, ent, is_dir, x, PA_REMOVE_DIR, NULL);
567        if (s != RM_OK)
568          return s;
569        return excise (fts, ent, x, is_dir);
570        }
571      }
572
573    case FTS_DC:		/* directory that causes cycles */
574      emit_cycle_warning (ent->fts_path);
575      fts_skip_tree (fts, ent);
576      return RM_ERROR;
577
578    case FTS_ERR:
579      /* Various failures, from opendir to ENOMEM, to failure to "return"
580         to preceding directory, can provoke this.  */
581      error (0, ent->fts_errno, _("traversal failed: %s"),
582             quote (ent->fts_path));
583      fts_skip_tree (fts, ent);
584      return RM_ERROR;
585
586    default:
587      error (0, 0, _("unexpected failure: fts_info=%d: %s\n"
588                     "please report to %s"),
589             ent->fts_info,
590             quote (ent->fts_path),
591             PACKAGE_BUGREPORT);
592      abort ();
593    }
594}
595
596/* Remove FILEs, honoring options specified via X.
597   Return RM_OK if successful.  */
598enum RM_status
599rm (char *const *file, struct rm_options const *x)
600{
601  enum RM_status rm_status = RM_OK;
602
603  if (*file)
604    {
605      int bit_flags = (FTS_CWDFD
606                       | FTS_NOSTAT
607                       | FTS_PHYSICAL);
608      FTS *fts;
609
610      if (x->one_file_system)
611        bit_flags |= FTS_XDEV;
612
613      fts = xfts_open (file, bit_flags, NULL);
614
615      while (1)
616        {
617          FTSENT *ent;
618          enum RM_status s;
619
620          ent = fts_read (fts);
621          if (ent == NULL)
622            {
623              if (errno != 0)
624                {
625                  error (0, errno, _("fts_read failed"));
626                  rm_status = RM_ERROR;
627                }
628              break;
629            }
630
631          s = rm_fts (fts, ent, x);
632
633          assert (VALID_STATUS (s));
634          UPDATE_STATUS (rm_status, s);
635        }
636
637      if (fts_close (fts) != 0)
638        {
639          error (0, errno, _("fts_close failed"));
640          rm_status = RM_ERROR;
641        }
642    }
643
644  return rm_status;
645}
646