Skip to content

Commit 79c4e5d

Browse files
committed
rm-rf: optionally rewind right before the rm_rf() operation
The comments in rm-rf.h suggested to do this already manually. Let's add a way to make this less manual.
1 parent b7be9cc commit 79c4e5d

3 files changed

Lines changed: 16 additions & 6 deletions

File tree

src/shared/copy.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -710,10 +710,7 @@ static void hardlink_context_destroy(HardlinkContext *c) {
710710

711711
if (c->dir_fd >= 0) {
712712
/* <dir_fd> might be have already been used for reading, so we need to rewind it. */
713-
if (lseek(c->dir_fd, 0, SEEK_SET) < 0)
714-
log_debug_errno(errno, "Failed to lseek on file descriptor, ignoring: %m");
715-
716-
r = rm_rf_children(TAKE_FD(c->dir_fd), REMOVE_PHYSICAL, NULL); /* consumes dir_fd in all cases, even on failure */
713+
r = rm_rf_children(TAKE_FD(c->dir_fd), REMOVE_PHYSICAL|REMOVE_REWIND, NULL); /* consumes dir_fd in all cases, even on failure */
717714
if (r < 0)
718715
log_debug_errno(r, "Failed to remove hardlink store (%s) contents, ignoring: %m", c->subdir);
719716

src/shared/rm-rf.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,18 @@ static int rm_rf_children_impl(
308308
/* Return the first error we run into, but nevertheless try to go on.
309309
* The passed fd is closed in all cases, including on failure. */
310310

311+
assert(fd >= 0);
312+
313+
if (FLAGS_SET(flags, REMOVE_REWIND)) {
314+
if (lseek(fd, 0, SEEK_SET) < 0) {
315+
r = -errno;
316+
safe_close(fd); /* always close */
317+
return r;
318+
}
319+
320+
flags &= ~REMOVE_REWIND;
321+
}
322+
311323
for (;;) { /* This loop corresponds to the directory nesting level. */
312324
_cleanup_closedir_ DIR *d = NULL;
313325

@@ -375,7 +387,7 @@ static int rm_rf_children_impl(
375387

376388
is_dir = de->d_type == DT_UNKNOWN ? -1 : de->d_type == DT_DIR;
377389

378-
r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, false);
390+
r = rm_rf_inner_child(fd, de->d_name, is_dir, flags, root_dev, /* allow_recursion= */ false);
379391
if (r == -EISDIR) {
380392
/* Push the current working state onto the todo list */
381393

@@ -521,7 +533,7 @@ int rm_rf_child(int fd, const char *name, RemoveFlags flags) {
521533
if (FLAGS_SET(flags, REMOVE_ONLY_DIRECTORIES|REMOVE_SUBVOLUME))
522534
return -EINVAL;
523535

524-
return rm_rf_inner_child(fd, name, -1, flags, NULL, true);
536+
return rm_rf_inner_child(fd, name, /* is_dir= */ -1, flags, /* root_dev= */ NULL, /* allow_recursion= */ true);
525537
}
526538

527539
const char* rm_rf_safe(const char *p) {

src/shared/rm-rf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ typedef enum RemoveFlags {
1212
REMOVE_CHMOD = 1 << 5, /* chmod() for write access if we cannot delete or access something */
1313
REMOVE_CHMOD_RESTORE = 1 << 6, /* Restore the old mode before returning */
1414
REMOVE_SYNCFS = 1 << 7, /* syncfs() the root of the specified directory after removing everything in it */
15+
REMOVE_REWIND = 1 << 8, /* Rewind the directory fd before operation */
1516
} RemoveFlags;
1617

1718
int unlinkat_harder(int dfd, const char *filename, int unlink_flags, RemoveFlags remove_flags);

0 commit comments

Comments
 (0)