rm: add option to remove recursively

This commit is contained in:
Bananymous 2023-10-26 02:32:49 +03:00
parent 38c267b4c8
commit ea0d7156a4
2 changed files with 116 additions and 7 deletions

View File

@ -8,7 +8,7 @@ set(SOURCES
add_executable(rm ${SOURCES})
target_compile_options(rm PUBLIC -O2 -g)
target_link_libraries(rm PUBLIC libc)
target_link_libraries(rm PUBLIC libc ban)
add_custom_target(rm-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/rm ${BANAN_BIN}/

View File

@ -1,21 +1,130 @@
#include <BAN/String.h>
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
bool delete_recursive(const char* path)
{
struct stat st;
if (stat(path, &st) == -1)
{
perror(path);
return false;
}
bool ret = true;
if (S_ISDIR(st.st_mode))
{
DIR* dir = opendir(path);
while (struct dirent* dirent = readdir(dir))
{
if (strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0)
continue;
BAN::String dirent_path;
MUST(dirent_path.append(path));
MUST(dirent_path.push_back('/'));
MUST(dirent_path.append(dirent->d_name));
if (dirent->d_type == DT_DIR)
{
if (!delete_recursive(dirent_path.data()))
ret = false;
}
else
{
if (unlink(dirent_path.data()) == -1)
{
perror(dirent_path.data());
ret = false;
}
}
}
closedir(dir);
}
if (unlink(path) == -1)
{
perror(path);
return false;
}
return true;
}
void usage(const char* argv0, int ret)
{
FILE* out = (ret == 0) ? stdout : stderr;
fprintf(out, "usage: %s [OPTIONS]... FILE...\n");
fprintf(out, " remove each FILE\n");
fprintf(out, "OPTIONS:\n");
fprintf(out, " -r remove directories and their contents recursively\n");
fprintf(out, " -h, --help show this message and exit\n");
exit(ret);
}
int main(int argc, char** argv)
{
if (argc <= 1)
bool recursive = false;
int i = 1;
for (; i < argc; i++)
{
fprintf(stderr, "Missing operand\n");
if (argv[i][0] != '-')
break;
if (strcmp(argv[i], "-r") == 0)
recursive = true;
else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0)
usage(argv[0], 0);
else
{
fprintf(stderr, "unrecognized argument %s. use --help for more information\n", argv[i]);
return 1;
}
}
if (i >= argc)
{
fprintf(stderr, "missing operand. use --help for more information\n");
return 1;
}
int ret = 0;
for (int i = 1; i < argc; i++)
for (; i < argc; i++)
{
if (unlink(argv[i]) == -1)
if (recursive)
{
perror(argv[i]);
ret = 1;
if (!delete_recursive(argv[i]))
ret = 1;
}
else
{
struct stat st;
if (stat(argv[i], &st) == -1)
{
perror(argv[i]);
ret = 1;
continue;
}
if (S_ISDIR(st.st_mode))
{
fprintf(stderr, "%s: %s\n", argv[i], strerror(EISDIR));
ret = 1;
continue;
}
if (unlink(argv[i]) == -1)
{
perror(argv[i]);
ret = 1;
}
}
}
return ret;