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