diff options
author | Christian Beier <dontmind@freeshell.org> | 2018-01-18 23:21:09 +0300 |
---|---|---|
committer | John Crispin <john@phrozen.org> | 2018-01-22 11:21:03 +0300 |
commit | 9c4aeda96220b3f0d097d153bedd328f71f382bf (patch) | |
tree | bf6f5a1a5030a132e092e8f020d41dfe10067bf6 /jshn.c | |
parent | 1c08e80313fd487112c48346889cc57badeef751 (diff) |
jshn: add functionality to read big JSON
The existing read functionality feeds the complete JSON to jshn as a
cmdline argument, leading to `-ash: jshn: Argument list too long`
errors for JSONs bigger than ca. 100KB.
This commit adds the ability to read the JSON directly from a file if
wanted, removing this shell-imposed size limit.
Tested on x86-64 and ar71xx. An mmap()-based solution was also evaluated,
but found to make no performance difference on either platform.
Signed-off-by: Christian Beier <dontmind@freeshell.org>
Diffstat (limited to 'jshn.c')
-rw-r--r-- | jshn.c | 35 |
1 files changed, 33 insertions, 2 deletions
@@ -25,6 +25,8 @@ #include <stdbool.h> #include <ctype.h> #include <getopt.h> +#include <sys/stat.h> +#include <fcntl.h> #include "list.h" #include "avl.h" @@ -305,7 +307,7 @@ out: static int usage(const char *progname) { - fprintf(stderr, "Usage: %s [-n] [-i] -r <message>|-w\n", progname); + fprintf(stderr, "Usage: %s [-n] [-i] -r <message>|-R <file>|-w\n", progname); return 2; } @@ -338,6 +340,10 @@ int main(int argc, char **argv) struct env_var *vars; int i; int ch; + int fd; + struct stat sb; + char *fbuf; + int ret; avl_init(&env_vars, avl_strcmp_var, false, NULL); for (i = 0; environ[i]; i++); @@ -359,7 +365,7 @@ int main(int argc, char **argv) avl_insert(&env_vars, &vars[i].avl); } - while ((ch = getopt(argc, argv, "p:nir:w")) != -1) { + while ((ch = getopt(argc, argv, "p:nir:R:w")) != -1) { switch(ch) { case 'p': var_prefix = optarg; @@ -367,6 +373,31 @@ int main(int argc, char **argv) break; case 'r': return jshn_parse(optarg); + case 'R': + if ((fd = open(optarg, O_RDONLY)) == -1) { + fprintf(stderr, "Error opening %s\n", optarg); + return 3; + } + if (fstat(fd, &sb) == -1) { + fprintf(stderr, "Error getting size of %s\n", optarg); + close(fd); + return 3; + } + if (!(fbuf = malloc(sb.st_size))) { + fprintf(stderr, "Error allocating memory for %s\n", optarg); + close(fd); + return 3; + } + if (read(fd, fbuf, sb.st_size) != sb.st_size) { + fprintf(stderr, "Error reading %s\n", optarg); + free(fbuf); + close(fd); + return 3; + } + ret = jshn_parse(fbuf); + free(fbuf); + close(fd); + return ret; case 'w': return jshn_format(no_newline, indent); case 'n': |