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;
|
|
|
|
}
|