summaryrefslogtreecommitdiff
path: root/src/commands/rm.c
diff options
context:
space:
mode:
authorTyler Murphy <tylerm@tylerm.dev>2023-05-03 12:17:56 -0400
committerTyler Murphy <tylerm@tylerm.dev>2023-05-03 12:17:56 -0400
commitf2606d0875dbaadb3f414d98d8f37fdbdf6036ea (patch)
tree5319a70aaba6cb57d554e7e7b0651908db4ec20a /src/commands/rm.c
parentfix ls segfault (diff)
downloadlazysphere-f2606d0875dbaadb3f414d98d8f37fdbdf6036ea.tar.gz
lazysphere-f2606d0875dbaadb3f414d98d8f37fdbdf6036ea.tar.bz2
lazysphere-f2606d0875dbaadb3f414d98d8f37fdbdf6036ea.zip
add rm, cp, mkdir, mv
Diffstat (limited to 'src/commands/rm.c')
-rw-r--r--src/commands/rm.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/commands/rm.c b/src/commands/rm.c
new file mode 100644
index 0000000..b85f91a
--- /dev/null
+++ b/src/commands/rm.c
@@ -0,0 +1,132 @@
+#include "../command.h"
+#include <dirent.h>
+#include <string.h>
+
+static struct {
+ bool force;
+ bool prompt;
+ bool verbose;
+ bool recurse;
+} flags;
+
+#ifdef FRENCH
+ static bool get_frenched;
+#endif
+
+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;
+}
+
+static void rm_file(char* path);
+
+static bool rm_dir() {
+ DIR* d = opendir(get_path_buffer());
+ if (d == NULL) {
+ error_s("failed to stat '%s': %s\n", get_path_buffer(), strerror(errno));
+ return false;
+ }
+
+ struct dirent* file;
+ 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) {
+ fprintf(stderr, "delete '%s'? ", get_path_buffer());
+ fflush(stderr);
+ char c = getchar();
+ 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) {
+ if (argc < 1) {
+ global_help(help);
+ return EXIT_SUCCESS;
+ }
+
+ flags.prompt = false;
+ flags.force = false;
+ flags.verbose = false;
+ flags.recurse = false;
+
+ int start = parse_args(argc, argv, help, short_arg, NULL);
+
+#ifdef FRENCH
+ if (streql(argv[0], "-rf")) {
+ printf("\x1b[94mremoving \x1b[97mthe \x1b[91mfrench \x1b[93m(beguette noises)\x1b[0m\n");
+ }
+#endif
+
+ for (int i = start; i < argc; i++) {
+ rm_file(argv[i]);
+ }
+
+ return EXIT_SUCCESS;
+}