(rm): Don't assume C99 for-loop syntax.
[platform/upstream/coreutils.git] / src / remove.c
1 /* remove.c -- core functions for removing files and directories
2    Copyright (C) 88, 90, 91, 1994-2005 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 2, or (at your option)
7    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, write to the Free Software Foundation,
16    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
17
18 /* Extracted from rm.c and librarified, then rewritten by Jim Meyering.  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <sys/types.h>
23 #include <setjmp.h>
24 #include <assert.h>
25
26 #include "system.h"
27 #include "cycle-check.h"
28 #include "dirfd.h"
29 #include "dirname.h"
30 #include "error.h"
31 #include "euidaccess.h"
32 #include "euidaccess-stat.h"
33 #include "file-type.h"
34 #include "hash.h"
35 #include "hash-pjw.h"
36 #include "lstat.h"
37 #include "obstack.h"
38 #include "openat.h"
39 #include "quote.h"
40 #include "remove.h"
41 #include "root-dev-ino.h"
42 #include "unlinkdir.h"
43 #include "yesno.h"
44
45 /* Avoid shadowing warnings because these are functions declared
46    in dirname.h as well as locals used below.  */
47 #define dir_name rm_dir_name
48 #define dir_len rm_dir_len
49
50 #define obstack_chunk_alloc malloc
51 #define obstack_chunk_free free
52
53 /* Define to the options that make open (or openat) fail to open
54    a symlink.  Define to 0 if there are no such options.
55    This is useful because it permits us to skip the `fstat'
56    and dev/ino comparison in AD_push.  */
57 #if defined O_NOFOLLOW
58 # define OPEN_NO_FOLLOW_SYMLINK O_NOFOLLOW
59 #else
60 # define OPEN_NO_FOLLOW_SYMLINK 0
61 #endif
62
63 /* This is the maximum number of consecutive readdir/unlink calls that
64    can be made (with no intervening rewinddir or closedir/opendir)
65    before triggering a bug that makes readdir return NULL even though
66    some directory entries have not been processed.  The bug afflicts
67    SunOS's readdir when applied to ufs file systems and Darwin 6.5's
68    (and OSX v.10.3.8's) HFS+.  This maximum is conservative in that
69    demonstrating the problem seems to require a directory containing
70    at least 254 deletable entries (which doesn't count . and ..), so
71    we could conceivably increase the maximum value to 254.  */
72 enum
73   {
74     CONSECUTIVE_READDIR_UNLINK_THRESHOLD = 200
75   };
76
77 enum
78   {
79     OPENAT_CWD_RESTORE__REQUIRE = false,
80     OPENAT_CWD_RESTORE__ALLOW_FAILURE = true
81   };
82
83 enum Ternary
84   {
85     T_UNKNOWN = 2,
86     T_NO,
87     T_YES
88   };
89 typedef enum Ternary Ternary;
90
91 /* The prompt function may be called twice for a given directory.
92    The first time, we ask whether to descend into it, and the
93    second time, we ask whether to remove it.  */
94 enum Prompt_action
95   {
96     PA_DESCEND_INTO_DIR = 2,
97     PA_REMOVE_DIR
98   };
99
100 /* Initial capacity of per-directory hash table of entries that have
101    been processed but not been deleted.  */
102 enum { HT_UNREMOVABLE_INITIAL_CAPACITY = 13 };
103
104 /* An entry in the active directory stack.
105    Each entry corresponds to an `active' directory.  */
106 struct AD_ent
107 {
108   /* For a given active directory, this is the set of names of
109      entries in that directory that could/should not be removed.
110      For example, `.' and `..', as well as files/dirs for which
111      unlink/rmdir failed e.g., due to access restrictions.  */
112   Hash_table *unremovable;
113
114   /* Record the status for a given active directory; we need to know
115      whether an entry was not removed, either because of an error or
116      because the user declined.  */
117   enum RM_status status;
118
119   /* The directory's dev/ino.  Used to ensure that a malicious user does
120      not replace a directory we're about to process with a symlink to
121      some other directory.  */
122   struct dev_ino dev_ino;
123 };
124
125 extern char *program_name;
126
127 struct dirstack_state
128 {
129   /* The name of the directory (starting with and relative to a command
130      line argument) being processed.  When a subdirectory is entered, a new
131      component is appended (pushed).  Remove (pop) the top component
132      upon chdir'ing out of a directory.  This is used to form the full
133      name of the current directory or a file therein, when necessary.  */
134   struct obstack dir_stack;
135
136   /* Stack of lengths of directory names (including trailing slash)
137      appended to dir_stack.  We have to have a separate stack of lengths
138      (rather than just popping back to previous slash) because the first
139      element pushed onto the dir stack may contain slashes.  */
140   struct obstack len_stack;
141
142   /* Stack of active directory entries.
143      The first `active' directory is the initial working directory.
144      Additional active dirs are pushed onto the stack as we `chdir'
145      into each directory to be processed.  When finished with the
146      hierarchy under a directory, pop the active dir stack.  */
147   struct obstack Active_dir;
148
149   /* Used to detect cycles.  */
150   struct cycle_check_state cycle_check_state;
151
152   /* Target of a longjmp in case rm has to stop processing the current
153      command-line argument.  This happens 1) when rm detects a directory
154      cycle or 2) when it has processed one or more directories, but then
155      is unable to return to the initial working directory to process
156      additional `.'-relative command-line arguments.  */
157   jmp_buf current_arg_jumpbuf;
158 };
159 typedef struct dirstack_state Dirstack_state;
160
161 static void
162 hash_freer (void *x)
163 {
164   free (x);
165 }
166
167 static bool
168 hash_compare_strings (void const *x, void const *y)
169 {
170   return STREQ (x, y) ? true : false;
171 }
172
173 static inline void
174 push_dir (Dirstack_state *ds, const char *dir_name)
175 {
176   size_t len = strlen (dir_name);
177
178   /* Append the string onto the stack.  */
179   obstack_grow (&ds->dir_stack, dir_name, len);
180
181   /* Append a trailing slash.  */
182   obstack_1grow (&ds->dir_stack, '/');
183
184   /* Add one for the slash.  */
185   ++len;
186
187   /* Push the length (including slash) onto its stack.  */
188   obstack_grow (&ds->len_stack, &len, sizeof (len));
189 }
190
191 /* Return the entry name of the directory on the top of the stack
192    in malloc'd storage.  */
193 static inline char *
194 top_dir (Dirstack_state const *ds)
195 {
196   size_t n_lengths = obstack_object_size (&ds->len_stack) / sizeof (size_t);
197   size_t *length = obstack_base (&ds->len_stack);
198   size_t top_len = length[n_lengths - 1];
199   char const *p = obstack_next_free (&ds->dir_stack) - top_len;
200   char *q = xmalloc (top_len);
201   memcpy (q, p, top_len - 1);
202   q[top_len - 1] = 0;
203   return q;
204 }
205
206 static inline void
207 pop_dir (Dirstack_state *ds)
208 {
209   size_t n_lengths = obstack_object_size (&ds->len_stack) / sizeof (size_t);
210   size_t *length = obstack_base (&ds->len_stack);
211
212   assert (n_lengths > 0);
213   size_t top_len = length[n_lengths - 1];
214   assert (top_len >= 2);
215
216   /* Pop the specified length of file name.  */
217   assert (obstack_object_size (&ds->dir_stack) >= top_len);
218   obstack_blank (&ds->dir_stack, -top_len);
219
220   /* Pop the length stack, too.  */
221   assert (obstack_object_size (&ds->len_stack) >= sizeof (size_t));
222   obstack_blank (&ds->len_stack, -(int) sizeof (size_t));
223 }
224
225 /* Copy the SRC_LEN bytes of data beginning at SRC into the DST_LEN-byte
226    buffer, DST, so that the last source byte is at the end of the destination
227    buffer.  If SRC_LEN is longer than DST_LEN, then set *TRUNCATED.
228    Set *RESULT to point to the beginning of (the portion of) the source data
229    in DST.  Return the number of bytes remaining in the destination buffer.  */
230
231 static size_t
232 right_justify (char *dst, size_t dst_len, const char *src, size_t src_len,
233                char **result, bool *truncated)
234 {
235   const char *sp;
236   char *dp;
237
238   if (src_len <= dst_len)
239     {
240       sp = src;
241       dp = dst + (dst_len - src_len);
242       *truncated = false;
243     }
244   else
245     {
246       sp = src + (src_len - dst_len);
247       dp = dst;
248       src_len = dst_len;
249       *truncated = true;
250     }
251
252   *result = memcpy (dp, sp, src_len);
253   return dst_len - src_len;
254 }
255
256 /* Using the global directory name obstack, create the full name FILENAME.
257    Return it in sometimes-realloc'd space that should not be freed by the
258    caller.  Realloc as necessary.  If realloc fails, use a static buffer
259    and put as long a suffix in that buffer as possible.  */
260
261 #define full_filename(Filename) full_filename_ (ds, Filename)
262 static char *
263 full_filename_ (Dirstack_state const *ds, const char *filename)
264 {
265   static char *buf = NULL;
266   static size_t n_allocated = 0;
267
268   size_t dir_len = obstack_object_size (&ds->dir_stack);
269   char *dir_name = obstack_base (&ds->dir_stack);
270   size_t n_bytes_needed;
271   size_t filename_len;
272
273   filename_len = strlen (filename);
274   n_bytes_needed = dir_len + filename_len + 1;
275
276   if (n_allocated < n_bytes_needed)
277     {
278       /* This code requires that realloc accept NULL as the first arg.
279          This function must not use xrealloc.  Otherwise, an out-of-memory
280          error involving a file name to be expanded here wouldn't ever
281          be issued.  Use realloc and fall back on using a static buffer
282          if memory allocation fails.  */
283       char *new_buf = realloc (buf, n_bytes_needed);
284       n_allocated = n_bytes_needed;
285
286       if (new_buf == NULL)
287         {
288 #define SBUF_SIZE 512
289 #define ELLIPSES_PREFIX "[...]"
290           static char static_buf[SBUF_SIZE];
291           bool truncated;
292           size_t len;
293           char *p;
294
295           free (buf);
296           len = right_justify (static_buf, SBUF_SIZE, filename,
297                                filename_len + 1, &p, &truncated);
298           right_justify (static_buf, len, dir_name, dir_len, &p, &truncated);
299           if (truncated)
300             {
301               memcpy (static_buf, ELLIPSES_PREFIX,
302                       sizeof (ELLIPSES_PREFIX) - 1);
303             }
304           return p;
305         }
306
307       buf = new_buf;
308     }
309
310   if (filename_len == 1 && *filename == '.' && dir_len)
311     {
312       /* FILENAME is just `.' and dir_len is nonzero.
313          Copy the directory part, omitting the trailing slash,
314          and append a trailing zero byte.  */
315       char *p = mempcpy (buf, dir_name, dir_len - 1);
316       *p = 0;
317     }
318   else
319     {
320       /* Copy the directory part, including trailing slash, and then
321          append the filename part, including a trailing zero byte.  */
322       memcpy (mempcpy (buf, dir_name, dir_len), filename, filename_len + 1);
323       assert (strlen (buf) + 1 == n_bytes_needed);
324     }
325
326   return buf;
327 }
328
329 static size_t
330 AD_stack_height (Dirstack_state const *ds)
331 {
332   return obstack_object_size (&ds->Active_dir) / sizeof (struct AD_ent);
333 }
334
335 static struct AD_ent *
336 AD_stack_top (Dirstack_state const *ds)
337 {
338   return (struct AD_ent *)
339     ((char *) obstack_next_free (&ds->Active_dir) - sizeof (struct AD_ent));
340 }
341
342 static void
343 AD_stack_pop (Dirstack_state *ds)
344 {
345   assert (0 < AD_stack_height (ds));
346
347   /* operate on Active_dir.  pop and free top entry */
348   struct AD_ent *top = AD_stack_top (ds);
349   if (top->unremovable)
350     hash_free (top->unremovable);
351   obstack_blank (&ds->Active_dir, -(int) sizeof (struct AD_ent));
352 }
353
354 static Dirstack_state *
355 ds_init (void)
356 {
357   Dirstack_state *ds = xmalloc (sizeof *ds);
358   obstack_init (&ds->dir_stack);
359   obstack_init (&ds->len_stack);
360   obstack_init (&ds->Active_dir);
361   return ds;
362 }
363
364 static void
365 ds_clear (Dirstack_state *ds)
366 {
367   obstack_free (&ds->dir_stack, obstack_finish (&ds->dir_stack));
368   obstack_free (&ds->len_stack, obstack_finish (&ds->len_stack));
369   while (0 < AD_stack_height (ds))
370     AD_stack_pop (ds);
371   obstack_free (&ds->Active_dir, obstack_finish (&ds->Active_dir));
372 }
373
374 static void
375 ds_free (Dirstack_state *ds)
376 {
377   obstack_free (&ds->dir_stack, NULL);
378   obstack_free (&ds->len_stack, NULL);
379   obstack_free (&ds->Active_dir, NULL);
380   free (ds);
381 }
382
383 /* Pop the active directory (AD) stack and move *DIRP `up' one level,
384    safely.  Moving `up' usually means opening `..', but when we've just
385    finished recursively processing a command-line directory argument,
386    there's nothing left on the stack, so set *DIRP to NULL in that case.
387    The idea is to return with *DIRP opened on the parent directory,
388    assuming there are entries in that directory that we need to remove.
389
390    Whenever using chdir '..' (virtually, now, via openat), verify
391    that the post-chdir dev/ino numbers for `.' match the saved ones.
392    If any system call fails or if dev/ino don't match then give a
393    diagnostic and longjump out.
394    Set *PREV_DIR to the name (in malloc'd storage) of the
395    directory (usually now empty) from which we're coming, and which
396    corresponds to the input value of *DIRP.  */
397 static void
398 AD_pop_and_chdir (DIR **dirp, Dirstack_state *ds, char **prev_dir)
399 {
400   enum RM_status old_status = AD_stack_top(ds)->status;
401   struct AD_ent *top;
402
403   /* Get the name of the current (but soon to be `previous') directory
404      from the top of the stack.  */
405   *prev_dir = top_dir (ds);
406
407   AD_stack_pop (ds);
408   pop_dir (ds);
409   top = AD_stack_top (ds);
410
411   /* Propagate any failure to parent.  */
412   UPDATE_STATUS (top->status, old_status);
413
414   assert (AD_stack_height (ds));
415
416   if (1 < AD_stack_height (ds))
417     {
418       struct stat sb;
419       int fd = openat (dirfd (*dirp), "..", O_RDONLY);
420       if (CLOSEDIR (*dirp) != 0)
421         {
422           error (0, errno, _("FATAL: failed to close directory %s"),
423                  quote (full_filename (*prev_dir)));
424           longjmp (ds->current_arg_jumpbuf, 1);
425         }
426
427       /* The above fails with EACCES when *DIRP is readable but not
428          searchable, when using Solaris' openat.  Without this openat
429          call, tests/rm2 would fail to remove directories a/2 and a/3.  */
430       if (fd < 0)
431         fd = openat (AT_FDCWD, full_filename ("."), O_RDONLY);
432
433       if (fd < 0)
434         {
435           error (0, errno, _("FATAL: cannot open .. from %s"),
436                  quote (full_filename (*prev_dir)));
437           longjmp (ds->current_arg_jumpbuf, 1);
438         }
439
440       if (fstat (fd, &sb))
441         {
442           error (0, errno,
443                  _("FATAL: cannot ensure %s (returned to via ..) is safe"),
444                  quote (full_filename (".")));
445           close (fd);
446           longjmp (ds->current_arg_jumpbuf, 1);
447         }
448
449       /*  Ensure that post-chdir dev/ino match the stored ones.  */
450       if ( ! SAME_INODE (sb, top->dev_ino))
451         {
452           error (0, 0, _("FATAL: directory %s changed dev/ino"),
453                  quote (full_filename (".")));
454           close (fd);
455           longjmp (ds->current_arg_jumpbuf, 1);
456         }
457
458       *dirp = fdopendir (fd);
459       if (*dirp == NULL)
460         {
461           error (0, errno, _("FATAL: cannot return to .. from %s"),
462                  quote (full_filename (".")));
463           close (fd);
464           longjmp (ds->current_arg_jumpbuf, 1);
465         }
466     }
467   else
468     {
469       if (CLOSEDIR (*dirp) != 0)
470         {
471           error (0, errno, _("FATAL: failed to close directory %s"),
472                  quote (full_filename (*prev_dir)));
473           longjmp (ds->current_arg_jumpbuf, 1);
474         }
475       *dirp = NULL;
476     }
477 }
478
479 /* Initialize *HT if it is NULL.
480    Insert FILENAME into HT.  */
481 static void
482 AD_mark_helper (Hash_table **ht, char const *filename)
483 {
484   if (*ht == NULL)
485     {
486       *ht = hash_initialize (HT_UNREMOVABLE_INITIAL_CAPACITY, NULL, hash_pjw,
487                              hash_compare_strings, hash_freer);
488       if (*ht == NULL)
489         xalloc_die ();
490     }
491   if (! hash_insert (*ht, filename))
492     xalloc_die ();
493 }
494
495 /* Mark FILENAME (in current directory) as unremovable.  */
496 static void
497 AD_mark_as_unremovable (Dirstack_state *ds, char const *filename)
498 {
499   AD_mark_helper (&AD_stack_top(ds)->unremovable, xstrdup (filename));
500 }
501
502 /* Mark the current directory as unremovable.  I.e., mark the entry
503    in the parent directory corresponding to `.'.
504    This happens e.g., when an opendir fails and the only name
505    the caller has conveniently at hand is `.'.  */
506 static void
507 AD_mark_current_as_unremovable (Dirstack_state *ds)
508 {
509   struct AD_ent *top = AD_stack_top (ds);
510   char const *curr = top_dir (ds);
511
512   assert (1 < AD_stack_height (ds));
513
514   --top;
515   AD_mark_helper (&top->unremovable, curr);
516 }
517
518 /* Push an initial dummy entry onto the stack.
519    This will always be the bottommost entry on the stack.  */
520 static void
521 AD_push_initial (Dirstack_state *ds)
522 {
523   struct AD_ent *top;
524
525   /* Extend the stack.  */
526   obstack_blank (&ds->Active_dir, sizeof (struct AD_ent));
527
528   /* Fill in the new values.  */
529   top = AD_stack_top (ds);
530   top->unremovable = NULL;
531
532   /* These should never be used.
533      Give them values that might look suspicious
534      in a debugger or in a diagnostic.  */
535   top->dev_ino.st_dev = TYPE_MAXIMUM (dev_t);
536   top->dev_ino.st_ino = TYPE_MAXIMUM (ino_t);
537 }
538
539 /* Push info about the current working directory (".") onto the
540    active directory stack.  DIR is the ./-relative name through
541    which we've just `chdir'd to this directory.  DIR_SB_FROM_PARENT
542    is the result of calling lstat on DIR from the parent of DIR.
543    Longjump out (skipping the entire command line argument we're
544    dealing with) if `fstat (FD_CWD, ...' fails or if someone has
545    replaced DIR with e.g., a symlink to some other directory.  */
546 static void
547 AD_push (int fd_cwd, Dirstack_state *ds, char const *dir,
548          struct stat const *dir_sb_from_parent)
549 {
550   struct AD_ent *top;
551
552   push_dir (ds, dir);
553
554   /* If our uses of openat are guaranteed not to
555      follow a symlink, then we can skip this check.  */
556   if ( ! OPEN_NO_FOLLOW_SYMLINK)
557     {
558       struct stat sb;
559       if (fstat (fd_cwd, &sb) != 0)
560         {
561           error (0, errno, _("FATAL: cannot enter directory %s"),
562                  quote (full_filename (".")));
563           longjmp (ds->current_arg_jumpbuf, 1);
564         }
565
566       if ( ! SAME_INODE (sb, *dir_sb_from_parent))
567         {
568           error (0, 0,
569                  _("FATAL: just-changed-to directory %s changed dev/ino"),
570                  quote (full_filename (".")));
571           longjmp (ds->current_arg_jumpbuf, 1);
572         }
573     }
574
575   /* Extend the stack.  */
576   obstack_blank (&ds->Active_dir, sizeof (struct AD_ent));
577
578   {
579     size_t n_lengths = obstack_object_size (&ds->len_stack) / sizeof (size_t);
580     assert (AD_stack_height (ds) == n_lengths + 1);
581   }
582
583   /* Fill in the new values.  */
584   top = AD_stack_top (ds);
585   top->dev_ino.st_dev = dir_sb_from_parent->st_dev;
586   top->dev_ino.st_ino = dir_sb_from_parent->st_ino;
587   top->unremovable = NULL;
588 }
589
590 static bool
591 AD_is_removable (Dirstack_state const *ds, char const *file)
592 {
593   struct AD_ent *top = AD_stack_top (ds);
594   return ! (top->unremovable && hash_lookup (top->unremovable, file));
595 }
596
597 /* Return true if DIR is determined to be an empty directory
598    or if fdopendir or readdir fails.  */
599 static bool
600 is_empty_dir (int fd_cwd, char const *dir)
601 {
602   DIR *dirp;
603   struct dirent const *dp;
604   int saved_errno;
605   int fd = openat (fd_cwd, dir, O_RDONLY);
606
607   if (fd < 0)
608     return false;
609
610   dirp = fdopendir (fd);
611   if (dirp == NULL)
612     {
613       close (fd);
614       return false;
615     }
616
617   errno = 0;
618   dp = readdir_ignoring_dot_and_dotdot (dirp);
619   saved_errno = errno;
620   closedir (dirp);
621   if (dp != NULL)
622     return false;
623   return saved_errno == 0 ? true : false;
624 }
625
626 /* Return true if FILE is determined to be an unwritable non-symlink.
627    Otherwise, return false (including when lstat'ing it fails).
628    If lstat (aka fstatat) succeeds, set *BUF_P to BUF.
629    This is to avoid calling euidaccess when FILE is a symlink.  */
630 static bool
631 write_protected_non_symlink (int fd_cwd,
632                              char const *file,
633                              Dirstack_state const *ds,
634                              struct stat **buf_p,
635                              struct stat *buf)
636 {
637   if (fstatat (fd_cwd, file, buf, AT_SYMLINK_NOFOLLOW) != 0)
638     return false;
639   *buf_p = buf;
640   if (S_ISLNK (buf->st_mode))
641     return false;
642   /* Here, we know FILE is not a symbolic link.  */
643
644   /* In order to be reentrant -- i.e., to avoid changing the working
645      directory, and at the same time to be able to deal with alternate
646      access control mechanisms (ACLs, xattr-style attributes) and
647      arbitrarily deep trees -- we need a function like eaccessat, i.e.,
648      like Solaris' eaccess, but fd-relative, in the spirit of openat.  */
649
650   /* In the absence of a native eaccessat function, here are some of
651      the implementation choices [#4 and #5 were suggested by Paul Eggert]:
652      1) call openat with O_WRONLY|O_NOCTTY
653         Disadvantage: may create the file and doesn't work for directory,
654         may mistakenly report `unwritable' for EROFS or ACLs even though
655         perm bits say the file is writable.
656
657      2) fake eaccessat (save_cwd, fchdir, call euidaccess, restore_cwd)
658         Disadvantage: changes working directory (not reentrant) and can't
659         work if save_cwd fails.
660
661      3) if (euidaccess (full_filename (file), W_OK) == 0)
662         Disadvantage: doesn't work if full_filename is too long.
663         Inefficient for very deep trees (O(Depth^2)).
664
665      4) If the full pathname is sufficiently short (say, less than
666         PATH_MAX or 8192 bytes, whichever is shorter):
667         use method (3) (i.e., euidaccess (full_filename (file), W_OK));
668         Otherwise: vfork, fchdir in the child, run euidaccess in the
669         child, then the child exits with a status that tells the parent
670         whether euidaccess succeeded.
671
672         This avoids the O(N**2) algorithm of method (3), and it also avoids
673         the failure-due-to-too-long-file-names of method (3), but it's fast
674         in the normal shallow case.  It also avoids the lack-of-reentrancy
675         and the save_cwd problems.
676         Disadvantage; it uses a process slot for very-long file names,
677         and would be very slow for hierarchies with many such files.
678
679      5) If the full file name is sufficiently short (say, less than
680         PATH_MAX or 8192 bytes, whichever is shorter):
681         use method (3) (i.e., euidaccess (full_filename (file), W_OK));
682         Otherwise: look just at the file bits.  Perhaps issue a warning
683         the first time this occurs.
684
685         This is like (4), except for the "Otherwise" case where it isn't as
686         "perfect" as (4) but is considerably faster.  It conforms to current
687         POSIX, and is uniformly better than what Solaris and FreeBSD do (they
688         mess up with long file names). */
689
690   {
691     /* This implements #5: */
692     size_t file_name_len
693       = obstack_object_size (&ds->dir_stack) + strlen (file);
694
695     return (file_name_len < MIN (PATH_MAX, 8192)
696             ? euidaccess (full_filename (file), W_OK) != 0 && errno == EACCES
697             : euidaccess_stat (buf, W_OK) != 0);
698   }
699 }
700
701 /* Prompt whether to remove FILENAME, if required via a combination of
702    the options specified by X and/or file attributes.  If the file may
703    be removed, return RM_OK.  If the user declines to remove the file,
704    return RM_USER_DECLINED.  If not ignoring missing files and we
705    cannot lstat FILENAME, then return RM_ERROR.
706
707    Depending on MODE, ask whether to `descend into' or to `remove' the
708    directory FILENAME.  MODE is ignored when FILENAME is not a directory.
709    Set *IS_EMPTY to T_YES if FILENAME is an empty directory, and it is
710    appropriate to try to remove it with rmdir (e.g. recursive mode).
711    Don't even try to set *IS_EMPTY when MODE == PA_REMOVE_DIR.
712    Set *IS_DIR to T_YES or T_NO if we happen to determine whether
713    FILENAME is a directory.  */
714 static enum RM_status
715 prompt (int fd_cwd, Dirstack_state const *ds, char const *filename,
716         struct rm_options const *x, enum Prompt_action mode,
717         Ternary *is_dir, Ternary *is_empty)
718 {
719   bool write_protected = false;
720   struct stat *sbuf = NULL;
721   struct stat buf;
722
723   *is_empty = T_UNKNOWN;
724   *is_dir = T_UNKNOWN;
725
726   if (((!x->ignore_missing_files & (x->interactive | x->stdin_tty))
727        && (write_protected = write_protected_non_symlink (fd_cwd, filename,
728                                                           ds, &sbuf, &buf)))
729       || x->interactive)
730     {
731       if (sbuf == NULL)
732         {
733           sbuf = &buf;
734           if (fstatat (fd_cwd, filename, sbuf, AT_SYMLINK_NOFOLLOW))
735             {
736               /* lstat failed.  This happens e.g., with `rm '''.  */
737               error (0, errno, _("cannot remove %s"),
738                      quote (full_filename (filename)));
739               return RM_ERROR;
740             }
741         }
742
743       if (S_ISDIR (sbuf->st_mode) && !x->recursive)
744         {
745           error (0, EISDIR, _("cannot remove directory %s"),
746                  quote (full_filename (filename)));
747           return RM_ERROR;
748         }
749
750       /* Using permissions doesn't make sense for symlinks.  */
751       if (S_ISLNK (sbuf->st_mode))
752         {
753           if ( ! x->interactive)
754             return RM_OK;
755           write_protected = false;
756         }
757
758       /* Issue the prompt.  */
759       {
760         char const *quoted_name = quote (full_filename (filename));
761
762         *is_dir = (S_ISDIR (sbuf->st_mode) ? T_YES : T_NO);
763
764         /* FIXME: use a variant of error (instead of fprintf) that doesn't
765            append a newline.  Then we won't have to declare program_name in
766            this file.  */
767         if (S_ISDIR (sbuf->st_mode)
768             && x->recursive
769             && mode == PA_DESCEND_INTO_DIR
770             && ((*is_empty = (is_empty_dir (fd_cwd, filename) ? T_YES : T_NO))
771                 == T_NO))
772           fprintf (stderr,
773                    (write_protected
774                     ? _("%s: descend into write-protected directory %s? ")
775                     : _("%s: descend into directory %s? ")),
776                    program_name, quoted_name);
777         else
778           {
779             /* TRANSLATORS: You may find it more convenient to translate
780                the equivalent of _("%s: remove %s (write-protected) %s? ").
781                It should avoid grammatical problems with the output
782                of file_type.  */
783             fprintf (stderr,
784                      (write_protected
785                       ? _("%s: remove write-protected %s %s? ")
786                       : _("%s: remove %s %s? ")),
787                      program_name, file_type (sbuf), quoted_name);
788           }
789
790         if (!yesno ())
791           return RM_USER_DECLINED;
792       }
793     }
794   return RM_OK;
795 }
796
797 /* Return true if FILENAME is a directory (and not a symlink to a directory).
798    Otherwise, including the case in which lstat fails, return false.
799    Do not modify errno.  */
800 static inline bool
801 is_dir_lstat (char const *filename)
802 {
803   struct stat sbuf;
804   int saved_errno = errno;
805   bool is_dir = lstat (filename, &sbuf) == 0 && S_ISDIR (sbuf.st_mode);
806   errno = saved_errno;
807   return is_dir;
808 }
809
810 #if HAVE_STRUCT_DIRENT_D_TYPE
811
812 /* True if the type of the directory entry D is known.  */
813 # define DT_IS_KNOWN(d) ((d)->d_type != DT_UNKNOWN)
814
815 /* True if the type of the directory entry D must be T.  */
816 # define DT_MUST_BE(d, t) ((d)->d_type == (t))
817
818 #else
819 # define DT_IS_KNOWN(d) false
820 # define DT_MUST_BE(d, t) false
821 #endif
822
823 #define DO_UNLINK(Fd_cwd, Filename, X)                                  \
824   do                                                                    \
825     {                                                                   \
826       if (unlinkat (Fd_cwd, Filename, 0) == 0)                          \
827         {                                                               \
828           if ((X)->verbose)                                             \
829             printf (_("removed %s\n"), quote (full_filename (Filename))); \
830           return RM_OK;                                                 \
831         }                                                               \
832                                                                         \
833       if (errno == ENOENT && (X)->ignore_missing_files)                 \
834         return RM_OK;                                                   \
835     }                                                                   \
836   while (0)
837
838 #define DO_RMDIR(Fd_cwd, Filename, X)                   \
839   do                                                    \
840     {                                                   \
841       if (unlinkat (Fd_cwd, Filename, AT_REMOVEDIR) == 0) /* rmdir */ \
842         {                                               \
843           if ((X)->verbose)                             \
844             printf (_("removed directory: %s\n"),       \
845                     quote (full_filename (Filename)));  \
846           return RM_OK;                                 \
847         }                                               \
848                                                         \
849       if (errno == ENOENT && (X)->ignore_missing_files) \
850         return RM_OK;                                   \
851                                                         \
852       if (errno == ENOTEMPTY || errno == EEXIST)        \
853         return RM_NONEMPTY_DIR;                         \
854     }                                                   \
855   while (0)
856
857 /* Remove the file or directory specified by FILENAME.
858    Return RM_OK if it is removed, and RM_ERROR or RM_USER_DECLINED if not.
859    But if FILENAME specifies a non-empty directory, return RM_NONEMPTY_DIR. */
860
861 static enum RM_status
862 remove_entry (int fd_cwd, Dirstack_state const *ds, char const *filename,
863               struct rm_options const *x, struct dirent const *dp)
864 {
865   Ternary is_dir;
866   Ternary is_empty_directory;
867   enum RM_status s = prompt (fd_cwd, ds, filename, x, PA_DESCEND_INTO_DIR,
868                              &is_dir, &is_empty_directory);
869
870   if (s != RM_OK)
871     return s;
872
873   /* Why bother with the following if/else block?  Because on systems with
874      an unlink function that *can* unlink directories, we must determine the
875      type of each entry before removing it.  Otherwise, we'd risk unlinking
876      an entire directory tree simply by unlinking a single directory;  then
877      all the storage associated with that hierarchy would not be freed until
878      the next fsck.  Not nice.  To avoid that, on such slightly losing
879      systems, we need to call lstat to determine the type of each entry,
880      and that represents extra overhead that -- it turns out -- we can
881      avoid on non-losing systems, since there, unlink will never remove
882      a directory.  Also, on systems where unlink may unlink directories,
883      we're forced to allow a race condition: we lstat a non-directory, then
884      go to unlink it, but in the mean time, a malicious someone could have
885      replaced it with a directory.  */
886
887   if (cannot_unlink_dir ())
888     {
889       if (is_dir == T_YES && ! x->recursive)
890         {
891           error (0, EISDIR, _("cannot remove directory %s"),
892                  quote (full_filename (filename)));
893           return RM_ERROR;
894         }
895
896       /* is_empty_directory is set iff it's ok to use rmdir.
897          Note that it's set only in interactive mode -- in which case it's
898          an optimization that arranges so that the user is asked just
899          once whether to remove the directory.  */
900       if (is_empty_directory == T_YES)
901         DO_RMDIR (fd_cwd, filename, x);
902
903       /* If we happen to know that FILENAME is a directory, return now
904          and let the caller remove it -- this saves the overhead of a failed
905          unlink call.  If FILENAME is a command-line argument, then dp is NULL,
906          so we'll first try to unlink it.  Using unlink here is ok, because it
907          cannot remove a directory.  */
908       if ((dp && DT_MUST_BE (dp, DT_DIR)) || is_dir == T_YES)
909         return RM_NONEMPTY_DIR;
910
911       DO_UNLINK (fd_cwd, filename, x);
912
913       /* Upon a failed attempt to unlink a directory, most non-Linux systems
914          set errno to the POSIX-required value EPERM.  In that case, change
915          errno to EISDIR so that we emit a better diagnostic.  */
916       if (! x->recursive && errno == EPERM && is_dir_lstat (filename))
917         errno = EISDIR;
918
919       if (! x->recursive
920           || errno == ENOENT || errno == ENOTDIR
921           || errno == ELOOP || errno == ENAMETOOLONG)
922         {
923           /* Either --recursive is not in effect, or the file cannot be a
924              directory.  Report the unlink problem and fail.  */
925           error (0, errno, _("cannot remove %s"),
926                  quote (full_filename (filename)));
927           return RM_ERROR;
928         }
929     }
930   else
931     {
932       /* If we don't already know whether FILENAME is a directory, find out now.
933          Then, if it's a non-directory, we can use unlink on it.  */
934       if (is_dir == T_UNKNOWN)
935         {
936           if (dp && DT_IS_KNOWN (dp))
937             is_dir = DT_MUST_BE (dp, DT_DIR) ? T_YES : T_NO;
938           else
939             {
940               struct stat sbuf;
941               if (fstatat (fd_cwd, filename, &sbuf, AT_SYMLINK_NOFOLLOW))
942                 {
943                   if (errno == ENOENT && x->ignore_missing_files)
944                     return RM_OK;
945
946                   error (0, errno, _("cannot remove %s"),
947                          quote (full_filename (filename)));
948                   return RM_ERROR;
949                 }
950
951               is_dir = S_ISDIR (sbuf.st_mode) ? T_YES : T_NO;
952             }
953         }
954
955       if (is_dir == T_NO)
956         {
957           /* At this point, barring race conditions, FILENAME is known
958              to be a non-directory, so it's ok to try to unlink it.  */
959           DO_UNLINK (fd_cwd, filename, x);
960
961           /* unlink failed with some other error code.  report it.  */
962           error (0, errno, _("cannot remove %s"),
963                  quote (full_filename (filename)));
964           return RM_ERROR;
965         }
966
967       if (! x->recursive)
968         {
969           error (0, EISDIR, _("cannot remove directory %s"),
970                  quote (full_filename (filename)));
971           return RM_ERROR;
972         }
973
974       if (is_empty_directory == T_YES)
975         {
976           DO_RMDIR (fd_cwd, filename, x);
977           /* Don't diagnose any failure here.
978              It'll be detected when the caller tries another way.  */
979         }
980     }
981
982   return RM_NONEMPTY_DIR;
983 }
984
985 /* Given FD_CWD, the file descriptor for an open directory,
986    open its subdirectory F (F is already `known' to be a directory,
987    so if it is no longer one, someone is playing games), return a DIR*
988    pointer for F, and put F's `stat' data in *SUBDIR_SB.
989    Upon failure give a diagnostic and return NULL.
990    If PREV_ERRNO is nonzero, it is the errno value from a preceding failed
991    unlink- or rmdir-like system call -- use that value instead of ENOTDIR
992    if an opened file turns out not to be a directory.  This is important
993    when the preceding non-dir-unlink failed due to e.g., EPERM or EACCES.
994    The caller must set OPENAT_CWD_RESTORE_ALLOW_FAILURE to true the first
995    time this function is called for each command-line-specified directory.
996    Set *CWD_RESTORE_FAILED if OPENAT_CWD_RESTORE_ALLOW_FAILURE is true
997    and openat_ro fails to restore the initial working directory.
998    CWD_RESTORE_FAILED may be NULL.  */
999 static DIR *
1000 fd_to_subdirp (int fd_cwd, char const *f,
1001                struct rm_options const *x, int prev_errno,
1002                struct stat *subdir_sb, Dirstack_state *ds,
1003                bool openat_cwd_restore_allow_failure,
1004                bool *cwd_restore_failed)
1005 {
1006   int fd_sub;
1007   bool dummy;
1008
1009   /* Record dev/ino of F.  We may compare them against saved values
1010      to thwart any attempt to subvert the traversal.  They are also used
1011      to detect directory cycles.  */
1012   if ((fd_sub = (openat_cwd_restore_allow_failure
1013                  ? openat_ro (fd_cwd, f, O_RDONLY | OPEN_NO_FOLLOW_SYMLINK,
1014                               (cwd_restore_failed
1015                                ? cwd_restore_failed : &dummy))
1016                  : openat (fd_cwd, f, O_RDONLY | OPEN_NO_FOLLOW_SYMLINK))) < 0
1017       || fstat (fd_sub, subdir_sb) != 0)
1018     {
1019       if (errno != ENOENT || !x->ignore_missing_files)
1020         error (0, errno,
1021                _("cannot remove %s"), quote (full_filename (f)));
1022       if (0 <= fd_sub)
1023         close (fd_sub);
1024       return NULL;
1025     }
1026
1027   if (! S_ISDIR (subdir_sb->st_mode))
1028     {
1029       error (0, prev_errno ? prev_errno : ENOTDIR, _("cannot remove %s"),
1030              quote (full_filename (f)));
1031       close (fd_sub);
1032       return NULL;
1033     }
1034
1035   DIR *subdir_dirp = fdopendir (fd_sub);
1036   if (subdir_dirp == NULL)
1037     {
1038       if (errno != ENOENT || !x->ignore_missing_files)
1039         error (0, errno, _("cannot open directory %s"),
1040                quote (full_filename (f)));
1041       close (fd_sub);
1042       return NULL;
1043     }
1044
1045   return subdir_dirp;
1046 }
1047
1048 /* Remove entries in the directory open on DIRP
1049    Upon finding a directory that is both non-empty and that can be chdir'd
1050    into, return RM_OK and set *SUBDIR and fill in SUBDIR_SB, where
1051    SUBDIR is the malloc'd name of the subdirectory if the chdir succeeded,
1052    NULL otherwise (e.g., if opendir failed or if there was no subdirectory).
1053    Likewise, SUBDIR_SB is the result of calling lstat on SUBDIR.
1054    Return RM_OK if all entries are removed.  Return RM_ERROR if any
1055    entry cannot be removed.  Otherwise, return RM_USER_DECLINED if
1056    the user declines to remove at least one entry.  Remove as much as
1057    possible, continuing even if we fail to remove some entries.  */
1058 static enum RM_status
1059 remove_cwd_entries (DIR **dirp,
1060                     Dirstack_state *ds, char **subdir, struct stat *subdir_sb,
1061                     struct rm_options const *x)
1062 {
1063   struct AD_ent *top = AD_stack_top (ds);
1064   enum RM_status status = top->status;
1065   size_t n_unlinked_since_opendir_or_last_rewind = 0;
1066
1067   assert (VALID_STATUS (status));
1068   *subdir = NULL;
1069
1070   while (1)
1071     {
1072       struct dirent const *dp;
1073       enum RM_status tmp_status;
1074       const char *f;
1075
1076       /* Set errno to zero so we can distinguish between a readdir failure
1077          and when readdir simply finds that there are no more entries.  */
1078       errno = 0;
1079       dp = readdir_ignoring_dot_and_dotdot (*dirp);
1080       if (dp == NULL)
1081         {
1082           if (errno)
1083             {
1084               /* fall through */
1085             }
1086           else if (CONSECUTIVE_READDIR_UNLINK_THRESHOLD
1087                    < n_unlinked_since_opendir_or_last_rewind)
1088             {
1089               /* Call rewinddir if we've called unlink or rmdir so many times
1090                  (since the opendir or the previous rewinddir) that this
1091                  NULL-return may be the symptom of a buggy readdir.  */
1092               rewinddir (*dirp);
1093               n_unlinked_since_opendir_or_last_rewind = 0;
1094               continue;
1095             }
1096           break;
1097         }
1098
1099       f = dp->d_name;
1100
1101       /* Skip files we've already tried/failed to remove.  */
1102       if ( ! AD_is_removable (ds, f))
1103         continue;
1104
1105       /* Pass dp->d_type info to remove_entry so the non-glibc
1106          case can decide whether to use unlink or chdir.
1107          Systems without the d_type member will have to endure
1108          the performance hit of first calling lstat F. */
1109       tmp_status = remove_entry (dirfd (*dirp), ds, f, x, dp);
1110       switch (tmp_status)
1111         {
1112         case RM_OK:
1113           /* Count how many files we've unlinked since the initial
1114              opendir or the last rewinddir.  On buggy systems, if you
1115              remove too many, readdir returns NULL even though there
1116              remain unprocessed directory entries.  */
1117           ++n_unlinked_since_opendir_or_last_rewind;
1118           break;
1119
1120         case RM_ERROR:
1121         case RM_USER_DECLINED:
1122           AD_mark_as_unremovable (ds, f);
1123           UPDATE_STATUS (status, tmp_status);
1124           break;
1125
1126         case RM_NONEMPTY_DIR:
1127           {
1128             DIR *subdir_dirp = fd_to_subdirp (dirfd (*dirp), f,
1129                                               x, errno, subdir_sb, ds,
1130                                               OPENAT_CWD_RESTORE__REQUIRE,
1131                                               NULL);
1132             if (subdir_dirp == NULL)
1133               {
1134                 AD_mark_as_unremovable (ds, f);
1135                 status = RM_ERROR;
1136                 break;
1137               }
1138
1139             if (cycle_check (&ds->cycle_check_state, subdir_sb))
1140               {
1141                 error (0, 0, _("\
1142 WARNING: Circular directory structure.\n\
1143 This almost certainly means that you have a corrupted file system.\n\
1144 NOTIFY YOUR SYSTEM MANAGER.\n\
1145 The following directory is part of the cycle:\n  %s\n"),
1146                        quote (full_filename (".")));
1147                 longjmp (ds->current_arg_jumpbuf, 1);
1148               }
1149
1150             *subdir = xstrdup (f);
1151             if (CLOSEDIR (*dirp) != 0)
1152               {
1153                 error (0, 0, _("failed to close directory %s"),
1154                        quote (full_filename (".")));
1155                 status = RM_ERROR;
1156               }
1157             *dirp = subdir_dirp;
1158
1159             break;
1160           }
1161         }
1162
1163       /* Record status for this directory.  */
1164       UPDATE_STATUS (top->status, status);
1165
1166       if (*subdir)
1167         break;
1168     }
1169
1170   /* Ensure that *dirp is not NULL and that its file descriptor is valid.  */
1171   assert (*dirp != NULL);
1172   assert (0 <= fcntl (dirfd (*dirp), F_GETFD));
1173
1174   return status;
1175 }
1176
1177 /* Do this after each call to AD_push or AD_push_initial.
1178    Because the status = RM_OK bit is too remove-specific to
1179    go into the general-purpose AD_* package.  */
1180 #define AD_INIT_OTHER_MEMBERS()                 \
1181   do                                            \
1182     {                                           \
1183       AD_stack_top(ds)->status = RM_OK;         \
1184     }                                           \
1185   while (0)
1186
1187 /*  Remove the hierarchy rooted at DIR.
1188     Do that by changing into DIR, then removing its contents, then
1189     returning to the original working directory and removing DIR itself.
1190     Don't use recursion.  Be careful when using chdir ".." that we
1191     return to the same directory from which we came, if necessary.
1192     Return an RM_status value to indicate success or failure.  */
1193
1194 static enum RM_status
1195 remove_dir (int fd_cwd, Dirstack_state *ds, char const *dir,
1196             struct rm_options const *x, bool *cwd_restore_failed)
1197 {
1198   enum RM_status status;
1199   struct stat dir_sb;
1200
1201   /* There is a race condition in that an attacker could replace the nonempty
1202      directory, DIR, with a symlink between the preceding call to rmdir
1203      (unlinkat, in our caller) and fd_to_subdirp's openat call.  But on most
1204      systems, even those without openat, this isn't a problem, since we ensure
1205      that opening a symlink will fail, when that is possible.  Otherwise,
1206      fd_to_subdirp's fstat, along with the `fstat' and the dev/ino
1207      comparison in AD_push ensure that we detect it and fail.  */
1208
1209   DIR *dirp = fd_to_subdirp (fd_cwd, dir, x, 0, &dir_sb, ds,
1210                              OPENAT_CWD_RESTORE__ALLOW_FAILURE,
1211                              cwd_restore_failed);
1212
1213   if (dirp == NULL)
1214     return RM_ERROR;
1215
1216   if (ROOT_DEV_INO_CHECK (x->root_dev_ino, &dir_sb))
1217     {
1218       ROOT_DEV_INO_WARN (full_filename (dir));
1219       status = RM_ERROR;
1220       goto closedir_and_return;
1221     }
1222
1223   AD_push (dirfd (dirp), ds, dir, &dir_sb);
1224   AD_INIT_OTHER_MEMBERS ();
1225
1226   status = RM_OK;
1227
1228   while (1)
1229     {
1230       char *subdir = NULL;
1231       struct stat subdir_sb;
1232       enum RM_status tmp_status;
1233
1234       tmp_status = remove_cwd_entries (&dirp, ds, &subdir, &subdir_sb, x);
1235
1236       if (tmp_status != RM_OK)
1237         {
1238           UPDATE_STATUS (status, tmp_status);
1239           AD_mark_current_as_unremovable (ds);
1240         }
1241       if (subdir)
1242         {
1243           AD_push (dirfd (dirp), ds, subdir, &subdir_sb);
1244           AD_INIT_OTHER_MEMBERS ();
1245
1246           free (subdir);
1247           continue;
1248         }
1249
1250       /* Execution reaches this point when we've removed the last
1251          removable entry from the current directory.  */
1252       {
1253         /* The name of the directory that we have just processed,
1254            nominally removing all of its contents.  */
1255         char *empty_dir;
1256
1257         AD_pop_and_chdir (&dirp, ds, &empty_dir);
1258         int fd = (dirp != NULL ? dirfd (dirp) : AT_FDCWD);
1259         assert (dirp != NULL || AD_stack_height (ds) == 1);
1260
1261         /* Try to remove EMPTY_DIR only if remove_cwd_entries succeeded.  */
1262         if (tmp_status == RM_OK)
1263           {
1264             /* This does a little more work than necessary when it actually
1265                prompts the user.  E.g., we already know that D is a directory
1266                and that it's almost certainly empty, yet we lstat it.
1267                But that's no big deal since we're interactive.  */
1268             Ternary is_dir;
1269             Ternary is_empty;
1270             enum RM_status s = prompt (fd, ds, empty_dir, x,
1271                                        PA_REMOVE_DIR, &is_dir, &is_empty);
1272
1273             if (s != RM_OK)
1274               {
1275                 free (empty_dir);
1276                 status = s;
1277                 goto closedir_and_return;
1278               }
1279
1280             if (unlinkat (fd, empty_dir, AT_REMOVEDIR) == 0)
1281               {
1282                 if (x->verbose)
1283                   printf (_("removed directory: %s\n"),
1284                           quote (full_filename (empty_dir)));
1285               }
1286             else
1287               {
1288                 error (0, errno, _("cannot remove directory %s"),
1289                        quote (full_filename (empty_dir)));
1290                 AD_mark_as_unremovable (ds, empty_dir);
1291                 status = RM_ERROR;
1292                 UPDATE_STATUS (AD_stack_top(ds)->status, status);
1293               }
1294           }
1295
1296         free (empty_dir);
1297
1298         if (AD_stack_height (ds) == 1)
1299           break;
1300       }
1301     }
1302
1303   /* If the first/final hash table of unremovable entries was used,
1304      free it here.  */
1305   AD_stack_pop (ds);
1306
1307  closedir_and_return:;
1308   if (dirp != NULL && CLOSEDIR (dirp) != 0)
1309     {
1310       error (0, 0, _("failed to close directory %s"),
1311              quote (full_filename (".")));
1312       status = RM_ERROR;
1313     }
1314
1315   return status;
1316 }
1317
1318 /* Remove the file or directory specified by FILENAME.
1319    Return RM_OK if it is removed, and RM_ERROR or RM_USER_DECLINED if not.  */
1320
1321 static enum RM_status
1322 rm_1 (Dirstack_state *ds, char const *filename,
1323       struct rm_options const *x, bool *cwd_restore_failed)
1324 {
1325   char const *base = base_name (filename);
1326   if (DOT_OR_DOTDOT (base))
1327     {
1328       error (0, 0, _("cannot remove `.' or `..'"));
1329       return RM_ERROR;
1330     }
1331
1332   AD_push_initial (ds);
1333   AD_INIT_OTHER_MEMBERS ();
1334
1335   /* Put `status' in static storage, so it can't be clobbered
1336      by the potential longjmp into this function.  */
1337   static enum RM_status status;
1338   int fd_cwd = AT_FDCWD;
1339   status = remove_entry (fd_cwd, ds, filename, x, NULL);
1340   if (status == RM_NONEMPTY_DIR)
1341     {
1342       /* In the event that remove_dir->remove_cwd_entries detects
1343          a directory cycle, arrange to fail, give up on this FILE, but
1344          continue on with any other arguments.  */
1345       if (setjmp (ds->current_arg_jumpbuf))
1346         status = RM_ERROR;
1347       else
1348         {
1349           bool t_cwd_restore_failed = false;
1350           status = remove_dir (fd_cwd, ds, filename, x, &t_cwd_restore_failed);
1351           *cwd_restore_failed |= t_cwd_restore_failed;
1352         }
1353     }
1354
1355   ds_clear (ds);
1356
1357   return status;
1358 }
1359
1360 /* Remove all files and/or directories specified by N_FILES and FILE.
1361    Apply the options in X.  */
1362 extern enum RM_status
1363 rm (size_t n_files, char const *const *file, struct rm_options const *x)
1364 {
1365   enum RM_status status = RM_OK;
1366   Dirstack_state *ds = ds_init ();
1367   bool cwd_restore_failed = false;
1368   size_t i;
1369
1370   for (i = 0; i < n_files; i++)
1371     {
1372       if (cwd_restore_failed && IS_RELATIVE_FILE_NAME (file[i]))
1373         {
1374           error (0, 0, _("cannot remove relative-named %s"), quote (file[i]));
1375           status = RM_ERROR;
1376           continue;
1377         }
1378
1379       cycle_check_init (&ds->cycle_check_state);
1380       enum RM_status s = rm_1 (ds, file[i], x, &cwd_restore_failed);
1381       assert (VALID_STATUS (s));
1382       UPDATE_STATUS (status, s);
1383     }
1384
1385   if (x->require_restore_cwd && cwd_restore_failed)
1386     {
1387       error (0, 0,
1388              _("cannot restore current working directory"));
1389       status = RM_ERROR;
1390     }
1391
1392   ds_free (ds);
1393
1394   return status;
1395 }