lazysphere/command/rm.c

141 lines
3 KiB
C
Raw Normal View History

2023-05-06 04:39:44 +00:00
#include "command.h"
#include "lslib.h"
2023-05-03 16:17:56 +00:00
#include <dirent.h>
2023-05-06 04:39:44 +00:00
#include <errno.h>
#include <stdlib.h>
2023-05-03 16:17:56 +00:00
#include <string.h>
static struct {
bool force;
bool prompt;
bool verbose;
bool recurse;
} flags;
static void help(void) {
printf("Usage: rm [-irfv] FILE...\n\n");
printf("Remove (unlink) FILESs\n\n");
printf("\t-i\tAlways prompt before removing\n");
printf("\t-f\tForce, never prompt\n");
printf("\t-v\tVerbose\n");
printf("\t-R,-r\tRecurse\n");
}
static int short_arg(char c, char* next) {
UNUSED(next);
switch (c) {
case 'i':
flags.prompt = true;
break;
case 'f':
flags.force = true;
break;
case 'v':
flags.verbose = true;
break;
case 'R':
case 'r':
flags.recurse = true;
break;
default:
return ARG_INVALID;
}
return ARG_UNUSED;
}
2023-05-04 20:10:37 +00:00
static void rm_file (char* path);
2023-05-03 16:17:56 +00:00
2023-05-04 20:10:37 +00:00
static bool rm_dir (void) {
DIR* d;
struct dirent* file;
d = opendir(get_path_buffer());
2023-05-03 16:17:56 +00:00
if (d == NULL) {
error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno));
return false;
}
while ((file = readdir(d)) != NULL) {
if (is_dot_dir(file->d_name)) continue;
rm_file(file->d_name);
}
closedir(d);
return true;
}
static void rm_file(char* path) {
int save = push_path_buffer(path);
struct stat s;
if (lstat(get_path_buffer(), &s) < 0) {
pop_path_buffer(save);
error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno));
return;
}
if (S_ISDIR(s.st_mode)) {
if (!flags.force) {
error_s("cannot delete '%s': Is a directory\n", get_path_buffer());
pop_path_buffer(save);
return;
}
if (flags.recurse && !rm_dir()) {
pop_path_buffer(save);
return;
}
}
if (flags.prompt) {
2023-05-04 20:10:37 +00:00
char c;
2023-05-03 16:17:56 +00:00
fprintf(stderr, "delete '%s'? ", get_path_buffer());
fflush(stderr);
2023-05-04 20:10:37 +00:00
c = getchar();
2023-05-03 16:17:56 +00:00
if (c != 'y' && c != 'Y') {
fprintf(stderr, "Skipping...\n");
pop_path_buffer(save);
return;
}
}
if (remove(get_path_buffer()) < 0) {
error_s("failed to delete '%s': %s\n", get_path_buffer(), strerror(errno));
} else if (flags.verbose) {
output("deleted '%s'\n", get_path_buffer());
}
pop_path_buffer(save);
}
COMMAND(rm) {
2023-05-04 20:10:37 +00:00
int start, i;
2023-05-03 16:17:56 +00:00
if (argc < 1) {
global_help(help);
return EXIT_SUCCESS;
}
flags.prompt = false;
flags.force = false;
flags.verbose = false;
flags.recurse = false;
2023-05-04 20:10:37 +00:00
start = parse_args(argc, argv, help, short_arg, NULL);
2023-05-03 16:17:56 +00:00
#ifdef FRENCH
2023-05-03 16:27:36 +00:00
if (streql(argv[0], "-fr")) {
2023-05-03 16:29:28 +00:00
printf("\x1b[94mremoving \x1b[97mthe \x1b[91mfrench \x1b[93m(baguette noises)\x1b[0m\n");
2023-05-03 16:17:56 +00:00
}
#endif
2023-05-04 20:10:37 +00:00
for (i = start; i < argc; i++) {
2023-05-03 16:17:56 +00:00
rm_file(argv[i]);
}
return EXIT_SUCCESS;
}