File: rm.c

package info (click to toggle)
zsv 1.3.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 49,160 kB
  • sloc: ansic: 175,811; cpp: 56,301; sh: 3,623; makefile: 3,048; javascript: 577; cs: 90; awk: 70; python: 41; sql: 15
file content (131 lines) | stat: -rw-r--r-- 3,768 bytes parent folder | download
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;
}