2023-10-26 02:32:49 +03:00
|
|
|
#include <BAN/String.h>
|
|
|
|
#include <dirent.h>
|
2023-10-25 21:45:27 +03:00
|
|
|
#include <stdio.h>
|
2023-10-26 02:32:49 +03:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <sys/stat.h>
|
2023-10-25 21:45:27 +03:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2023-10-26 02:32:49 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-12-14 11:03:58 +02:00
|
|
|
if (remove(path) == -1)
|
2023-10-26 02:32:49 +03:00
|
|
|
{
|
|
|
|
perror(path);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2023-12-10 19:20:14 +02:00
|
|
|
return ret;
|
2023-10-26 02:32:49 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void usage(const char* argv0, int ret)
|
|
|
|
{
|
|
|
|
FILE* out = (ret == 0) ? stdout : stderr;
|
2023-12-10 19:20:14 +02:00
|
|
|
fprintf(out, "usage: %s [OPTIONS]... FILE...\n", argv0);
|
2023-10-26 02:32:49 +03:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2023-10-25 21:45:27 +03:00
|
|
|
int main(int argc, char** argv)
|
|
|
|
{
|
2023-10-26 02:32:49 +03:00
|
|
|
bool recursive = false;
|
|
|
|
|
|
|
|
int i = 1;
|
|
|
|
for (; i < argc; i++)
|
2023-10-25 21:45:27 +03:00
|
|
|
{
|
2023-10-26 02:32:49 +03:00
|
|
|
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");
|
2023-10-25 21:45:27 +03:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int ret = 0;
|
2023-10-26 02:32:49 +03:00
|
|
|
for (; i < argc; i++)
|
2023-10-25 21:45:27 +03:00
|
|
|
{
|
2023-10-26 02:32:49 +03:00
|
|
|
if (recursive)
|
2023-10-25 21:45:27 +03:00
|
|
|
{
|
2023-10-26 02:32:49 +03:00
|
|
|
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;
|
|
|
|
}
|
2023-10-25 21:45:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|