From b2f84eb55c4a80d3d14609db0c9bf15a13208b67 Mon Sep 17 00:00:00 2001 From: Jan-Piet Mens Date: Tue, 25 Aug 2015 18:01:50 +0200 Subject: [PATCH] Feature: ocat userlist (incomplete!) --- ocat.c | 22 ++++++++++-- storage.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ storage.h | 1 + 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/ocat.c b/ocat.c index c1c83fc..3d839da 100644 --- a/ocat.c +++ b/ocat.c @@ -121,6 +121,7 @@ void usage(char *prog) printf(" geojson\n"); printf(" raw\n"); printf(" tabular\n"); + printf(" --last -L JSON object with last users\n"); printf(" --killdata requires -u and -d\n"); exit(1); @@ -130,7 +131,7 @@ int main(int argc, char **argv) { char *progname = *argv, *p; int c; - int list = 0, killdata = 0; + int list = 0, killdata = 0, last = 0; char *username = NULL, *device = NULL, *time_from = NULL, *time_to = NULL; JsonNode *json, *obj, *locs; time_t now, s_lo, s_hi; @@ -164,12 +165,13 @@ int main(int argc, char **argv) { "from", required_argument, 0, 'F'}, { "to", required_argument, 0, 'T'}, { "format", required_argument, 0, 'f'}, + { "last", no_argument, 0, 'L'}, { "killdata", no_argument, 0, 'K'}, {0, 0, 0, 0} }; int optindex = 0; - c = getopt_long(argc, argv, "hlu:d:F:T:f:K", long_options, &optindex); + c = getopt_long(argc, argv, "hlu:d:F:T:f:KL", long_options, &optindex); if (c == -1) break; @@ -208,6 +210,9 @@ int main(int argc, char **argv) case 'K': killdata = 1; break; + case 'L': + last = 1; + break; case 'h': case '?': /* getopt_long already printed message */ @@ -247,6 +252,19 @@ int main(int argc, char **argv) return (0); } + if (last) { + JsonNode *obj; + char *js; + + obj = last_users(); + js = json_stringify(obj, " "); + printf("%s\n", js); + + free(js); + json_delete(obj); + return (0); + } + if (!username && device) { fprintf(stderr, "%s: device name without username doesn't make sense\n", progname); return (-2); diff --git a/storage.c b/storage.c index 2882469..2c8122c 100644 --- a/storage.c +++ b/storage.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "utstring.h" #include "config.h" #include "storage.h" @@ -36,6 +37,109 @@ void get_geo(JsonNode *o, char *ghash) } } + +/* + * Populate a JSON object (`node') keyed by directory name; each element points + * to a JSON array with a list of subdirectories on the first level. + * + * { "jpm": [ "5s", "nex4" ], "jjolie": [ "iphone5" ] } + * + * Returns 1 on failure. + */ + +static int user_device_list(char *name, int level, JsonNode *obj) +{ + DIR *dirp; + struct dirent *dp; + char path[BUFSIZ]; + JsonNode *devlist; + int rc = 0; + struct stat sb; + + if ((dirp = opendir(name)) == NULL) { + perror(name); + return (1); + } + while ((dp = readdir(dirp)) != NULL) { + if (*dp->d_name != '.') { + sprintf(path, "%s/%s", name, dp->d_name); + + if (stat(path, &sb) != 0) { + continue; + } + if (!S_ISDIR(sb.st_mode)) + continue; + + + if (level == 0) { + devlist = json_mkarray(); + json_append_member(obj, dp->d_name, devlist); + rc = user_device_list(path, level + 1, devlist); + } else if (level == 1) { + json_append_element(obj, json_mkstring(dp->d_name)); + } + } + } + closedir(dirp); + return (rc); +} + +void append_device_details(JsonNode *userlist, char *user, char *device) +{ + char path[BUFSIZ]; + JsonNode *last, *card; + + snprintf(path, BUFSIZ, "%s/last/%s/%s/%s-%s.json", + STORAGEDIR, user, device, user, device); + + last = json_mkobject(); + if (json_copy_from_file(last, path) == TRUE) { + json_append_element(userlist, last); + } else { + json_delete(last); + } + + snprintf(path, BUFSIZ, "%s/cards/%s/%s.json", + STORAGEDIR, user, user); + + card = json_mkobject(); + if (json_copy_from_file(card, path) == TRUE) { + json_copy_to_object(last, card); + } else { + json_delete(card); + } +} + +JsonNode *last_users() +{ + JsonNode *obj = json_mkobject(); + JsonNode *un, *dn, *userlist = json_mkarray(); + char path[BUFSIZ], user[BUFSIZ], device[BUFSIZ]; + + snprintf(path, BUFSIZ, "%s/last", STORAGEDIR); + + if (user_device_list(path, 0, obj) == 1) + return (obj); + + /* Loop through users, devices */ + json_foreach(un, obj) { + if (un->tag != JSON_ARRAY) + continue; + strcpy(user, un->key); + json_foreach(dn, un) { + if (dn->tag == JSON_STRING) { + strcpy(device, dn->string_); + } else if (dn->tag == JSON_NUMBER) { /* all digits? */ + sprintf(device, "%.lf", dn->number_); + } + append_device_details(userlist, user, device); + } + } + json_delete(obj); + + return (userlist); +} + /* * `s' has a time string in it. Try to convert into time_t * using a variety of formats from higher to lower precision. diff --git a/storage.h b/storage.h index 41c93cd..63aa9a3 100644 --- a/storage.h +++ b/storage.h @@ -10,5 +10,6 @@ void locations(char *filename, JsonNode *obj, JsonNode *arr, time_t s_lo, time_t 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); +JsonNode *last_users(); #endif