Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 56 additions & 7 deletions dentls.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
* that has significantly negative effect on unlink performance
*/

// Globals
unsigned long delete_count = 0; // Running count of deletions
unsigned short show_progress = 0; // By default, don't show progress
unsigned short print_only = 1; // By default, print entries, don't unlink
unsigned long progress_interval_minor = 1000; // Print a ".".
unsigned long progress_interval_major = 50; // Print the number done so far.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually, these should be configurable via the value of DENTLS_PROGRESS.


/* Tests indicate that performing a ascending order traversal
* is about 1/3 faster than a descending order traversal */
int compare_fnames(const void *key1, const void *key2) {
Expand All @@ -30,26 +37,46 @@ void walk_tree(const void *node, VISIT val, int lvl) {
int rc = 0;
switch(val) {
case leaf:
printf("%s\n", *(char **)node);
// rc = unlink(*(char **)node);
if (print_only) {
printf("%s\n", *(char **)node);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As modified, this is the only thing that ever appears on stdout.

} else {
rc = unlink(*(char **)node);
}
delete_count++;
break;
/* End order is deliberate here as it offers the best btree
* rebalancing avoidance.
*/
case endorder:
printf("%s\n", *(char **)node);
// rc = unlink(*(char **)node);
if (print_only) {
printf("%s\n", *(char **)node);
} else {
rc = unlink(*(char **)node);
}
delete_count++;
break;
default:
return;
break;
}

if (rc < 0) {
fprintf(stderr, "Failed to delete %s", *(char **)node);
perror("unlink problem");
exit(1);
}

if (show_progress) {
if (delete_count % (progress_interval_minor * progress_interval_major) == 0) {
sleep(1);
fprintf(stderr, "%s%lu", (delete_count ? "\n" : ""), delete_count);
fflush(stderr);
}
else if (delete_count % progress_interval_minor == 0) {
fprintf(stderr, ".");
fflush(stderr);
}
}
}

void dummy_destroy(void *nil) {
Expand All @@ -62,7 +89,7 @@ struct linux_dirent {
long d_ino;
off_t d_off;
unsigned short d_reclen;
char d_name[256];
char d_name[FILENAME_MAX];
char d_type;
};

Expand Down Expand Up @@ -114,6 +141,28 @@ int main(const int argc, const char** argv) {
exit(1);
}

if (argv[1][0] == '-' || argv[1][0] != '/') {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is duplicative. It's here to emphasize that, even if we add proper option handling, we should still require absolute paths.

fprintf(stderr, "Usage: %s <directory>\n", argv[0]);
fprintf(stderr, " For safety, <directory> must be fully-qualified (i.e., start with /).\n");
fprintf(stderr, " Env: Set DENTLS_DELETE=delete to delete instead of print.\n");
fprintf(stderr, " Env: Set DENTLS_PROGRESS to show progress on stderr.\n");
return -1;
}

if (getenv("DENTLS_DELETE") != NULL) {
if (strcmp(getenv("DENTLS_DELETE"), "delete")) {
fprintf(stderr, "If you'd like to delete files, please set DENTLS_DELETE to 'delete', *EXACTLY*.\n");
fprintf(stderr, "If you did not intend to run deletes, please unset the variable entirely.\n");
return 1;
} else {
print_only = 0;
}
}

if (getenv("DENTLS_PROGRESS")) {
show_progress = 1;
}

const char *path = argv[1];

/* Standard sanity checking stuff */
Expand Down Expand Up @@ -190,10 +239,10 @@ int main(const int argc, const char** argv) {
linked_list_prepend_override(&dirent_buffers_list, buffer);
}
fprintf(stderr, "Total files: %d\n", totalfiles);
printf("Performing delete..\n");
fprintf(stderr, "Performing %s...\n", (print_only ? "print" : "delete"));

twalk(tree, walk_tree);
printf("Done\n");
fprintf(stderr, "Done\n");
close(dirfd);
free_linked_list(dirent_buffers_list);
tdestroy(tree, dummy_destroy);
Expand Down