1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
/* Copyright (C) 2022 Guarnerix Inc dba Liquidaty - All Rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
* Proprietary and confidential
* Written by Matt Wong <matt@guarnerix.com>
*/
/*
* remove a given file and its cache
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h> // unlink()
#include <errno.h>
#define ZSV_COMMAND_NO_OPTIONS
#define ZSV_COMMAND rm
#include "zsv_command.h"
#include <zsv/utils/dirs.h>
#include <zsv/utils/cache.h>
/**
* TO DO: add --orphaned option to remove all orphaned caches
*/
const char *zsv_rm_usage_msg[] = {
APPNAME ": remove a file and its related cache",
"",
"Usage: " APPNAME " [options] <filepath>",
"",
"Options:",
" -v,--verbose : verbose output",
#ifndef NO_STDIN
" -f,--force : do not prompt for confirmation",
#endif
" -k,--keep : do not remove related cache",
" -C,--cache : only remove related cache (not the file)",
NULL,
};
static int zsv_rm_usage(FILE *target) {
for (size_t j = 0; zsv_rm_usage_msg[j]; j++)
fprintf(target, "%s\n", zsv_rm_usage_msg[j]);
return target == stdout ? 0 : 1;
}
int ZSV_MAIN_NO_OPTIONS_FUNC(ZSV_COMMAND)(int argc, const char *argv[]) {
int err = 0;
if (argc > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))
err = zsv_rm_usage(stdout);
else if (argc < 2)
err = zsv_rm_usage(stderr);
else {
const char *filepath = NULL;
char force = 0;
#ifdef NO_STDIN
force = 1;
#endif
char remove_cache = 1;
char remove_file = 1;
char verbose = 0;
for (int i = 1; !err && i < argc; i++) {
const char *arg = argv[i];
if (*arg == '-') {
if (!strcmp(arg, "-v") || !strcmp(arg, "--verbose"))
verbose = 1;
else if (!strcmp(arg, "-f") || !strcmp(arg, "--force"))
force = 1;
else if (!strcmp(arg, "-k") || !strcmp(arg, "--keep"))
remove_cache = 0;
else if (!strcmp(arg, "-C") || !strcmp(arg, "--cache"))
remove_file = 0;
else
err = zsv_printerr(1, "Unrecognized option: %s", arg);
} else if (!filepath)
filepath = arg;
else
err = zsv_printerr(1, "Unrecognized option: %s", arg);
}
if (!err && !filepath)
err = zsv_rm_usage(stderr);
else if (remove_file == 0 && remove_cache == 0)
err = fprintf(stderr, "Nothing to remove\n");
if (!err) {
char ok = 1;
#ifndef NO_STDIN
if (!force) {
ok = 0;
if (!remove_file)
printf("Are you sure you want to remove the entire cache for the file %s?\n", filepath);
else
printf("Are you sure you want to remove the file %s%s?\n", filepath,
remove_cache ? " and all of its cache contents" : "");
char buff[64];
if (fscanf(stdin, "%60s", buff) == 1 && strchr("Yy", buff[0]))
ok = 1;
}
#endif
if (ok) {
if (remove_file) {
if (verbose)
fprintf(stderr, "Removing %s", filepath);
err = unlink(filepath);
if (err) {
if (err == ENOENT && force)
err = 0;
else
perror(filepath);
}
}
if (!err) {
unsigned char *cache_dir = zsv_cache_path((const unsigned char *)filepath, NULL, 0);
if (!cache_dir)
err = zsv_printerr(ENOMEM, "Out of memory!");
else if (zsv_dir_exists((const char *)cache_dir)) {
err = zsv_remove_dir_recursive(cache_dir);
if (verbose) {
if (!err)
fprintf(stderr, "Removed cache %s", cache_dir);
}
}
free(cache_dir);
}
}
}
}
return err;
}
|