diff --git a/ocat.c b/ocat.c index 616a0d0..5a63d92 100644 --- a/ocat.c +++ b/ocat.c @@ -89,6 +89,7 @@ void usage(char *prog) printf(" geojson\n"); printf(" raw\n"); printf(" tabular\n"); + printf(" --killdata requires -u and -d\n"); exit(1); } @@ -97,7 +98,7 @@ int main(int argc, char **argv) { char *progname = *argv, *p; int c; - int list = 0; + int list = 0, killdata = 0; char *username = NULL, *device = NULL, *time_from = NULL, *time_to = NULL; JsonNode *json, *obj, *locs; time_t now, s_lo, s_hi; @@ -131,11 +132,12 @@ int main(int argc, char **argv) { "from", required_argument, 0, 'F'}, { "to", required_argument, 0, 'T'}, { "format", required_argument, 0, 'f'}, + { "killdata", no_argument, 0, 'K'}, {0, 0, 0, 0} }; int optindex = 0; - c = getopt_long(argc, argv, "hlu:d:F:T:f:", long_options, &optindex); + c = getopt_long(argc, argv, "hlu:d:F:T:f:K", long_options, &optindex); if (c == -1) break; @@ -171,6 +173,9 @@ int main(int argc, char **argv) exit(2); } break; + case 'K': + killdata = 1; + break; case 'h': case '?': /* getopt_long already printed message */ @@ -185,6 +190,22 @@ int main(int argc, char **argv) argc -= (optind); argv += (optind); + if (killdata) { + JsonNode *killed, *f; + + if (!username || !device) { + fprintf(stderr, "%s: killdata requires username and device\n", progname); + return (-2); + } + + fprintf(stderr, "Storage deleted these files:\n"); + killed = kill_datastore(username, device); + json_foreach(f, killed) { + fprintf(stderr, " %s\n", f->string_); + } + return (0); + } + if (!username && device) { fprintf(stderr, "%s: device name without username doesn't make sense\n", progname); return (-2); @@ -233,8 +254,6 @@ int main(int argc, char **argv) } - - /* * If any files were passed on the command line, we assume these are *.rec * and process those. Otherwise, we expect a `user' and `device' and process diff --git a/storage.c b/storage.c index 5841d04..7847d06 100644 --- a/storage.c +++ b/storage.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "utstring.h" #include "config.h" @@ -481,3 +482,66 @@ JsonNode *geo_json(JsonNode *location_array) return (fcollection); } + +/* + * Remove all data for a user's device. Return a JSON array of deleted files. + */ + +static int kill_datastore_filter(const struct dirent *d) +{ + return (*d->d_name == '.') ? 0 : 1; +} + +JsonNode *kill_datastore(char *user, char *device) +{ + static UT_string *path = NULL, *fname = NULL; + JsonNode *killed = json_mkarray(); + char *bp; + struct dirent **namelist; + int i, n; + + utstring_renew(path); + utstring_renew(fname); + + if (!user || !*user || !device || !*device) + return (killed); + + for (bp = user; bp && *bp; bp++) { + if (isupper(*bp)) + *bp = tolower(*bp); + } + for (bp = device; bp && *bp; bp++) { + if (isupper(*bp)) + *bp = tolower(*bp); + } + + utstring_printf(path, "%s/rec/%s/%s", STORAGEDIR, user, device); + + if ((n = scandir(utstring_body(path), &namelist, kill_datastore_filter, NULL)) < 0) { + perror(utstring_body(path)); + return (killed); + } + + for (i = 0; i < n; i++) { + char *p; + + utstring_clear(fname); + utstring_printf(fname, "%s/%s", utstring_body(path), namelist[i]->d_name); + + p = utstring_body(fname); + if (remove(p) == 0) { + json_append_element(killed, json_mkstring(namelist[i]->d_name)); + } else { + perror(p); + } + + free(namelist[i]); + } + free(namelist); + + if (rmdir(utstring_body(path)) != 0) { + perror(utstring_body(path)); + } + + return (killed); +} diff --git a/storage.h b/storage.h index aba3c1c..41c93cd 100644 --- a/storage.h +++ b/storage.h @@ -9,5 +9,6 @@ JsonNode *lister(char *username, char *device, time_t s_lo, time_t s_hi); void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t s_hi, int rawmode); int make_times(char *time_from, time_t *s_lo, char *time_to, time_t *s_to); JsonNode *geo_json(JsonNode *json); +JsonNode *kill_datastore(char *username, char *device); #endif