diff mbox series

[LEDE-DEV] jshn: add functionality to read big JSON

Message ID 20171116185214.13895-1-dontmind@freeshell.org
State Changes Requested
Delegated to: John Crispin
Headers show
Series [LEDE-DEV] jshn: add functionality to read big JSON | expand

Commit Message

Christian Beier Nov. 16, 2017, 6:52 p.m. UTC
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>
---
 jshn.c     | 30 ++++++++++++++++++++++++++++--
 sh/jshn.sh |  4 ++++
 2 files changed, 32 insertions(+), 2 deletions(-)

Comments

Alexandru Ardelean Nov. 17, 2017, 7:17 a.m. UTC | #1
On Thu, Nov 16, 2017 at 8:52 PM, Christian Beier <dontmind@freeshell.org> wrote:
> 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>
> ---
>  jshn.c     | 30 ++++++++++++++++++++++++++++--
>  sh/jshn.sh |  4 ++++
>  2 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/jshn.c b/jshn.c
> index 79136dd..a3866a0 100644
> --- a/jshn.c
> +++ b/jshn.c
> @@ -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"
> @@ -300,7 +302,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;
>  }
>
> @@ -333,6 +335,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++);
> @@ -354,7 +360,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;
> @@ -362,6 +368,26 @@ 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)) || 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;
nitpick/preference: I would move this code into a file, so that the
case statement is not too loaded
it would allow for a simpler/cleaner code-path with some goto
statements [if put into a function]

>                 case 'w':
>                         return jshn_format(no_newline, indent);
>                 case 'n':
> diff --git a/sh/jshn.sh b/sh/jshn.sh
> index bf76edb..0a146e1 100644
> --- a/sh/jshn.sh
> +++ b/sh/jshn.sh
> @@ -174,6 +174,10 @@ json_load() {
>         eval "`jshn -r "$1"`"
>  }
>
> +json_load_file() {
> +       eval "`jshn -R "$1"`"
would it be an idea to try to use $JSON_PREFIX here ?
for cases when you need to change the JSON namespace, the JSON_PREFIX
var is used if available
it would definitely complete this function

> +}
> +
>  json_dump() {
>         jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
>  }
> --
> 2.11.0
>

from my side [as a simple reviewer], this looks pretty neat

thanks :)

Alex

>
> _______________________________________________
> Lede-dev mailing list
> Lede-dev@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/lede-dev
Christian Beier Nov. 18, 2017, 1:55 p.m. UTC | #2
Am Fri, 17 Nov 2017 09:17:39 +0200
schrieb Alexandru Ardelean <ardeleanalex@gmail.com>:

> On Thu, Nov 16, 2017 at 8:52 PM, Christian Beier <dontmind@freeshell.org>
> wrote:
> > 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>
> > ---
> >  jshn.c     | 30 ++++++++++++++++++++++++++++--
> >  sh/jshn.sh |  4 ++++
> >  2 files changed, 32 insertions(+), 2 deletions(-)
> >
> > diff --git a/jshn.c b/jshn.c
> > index 79136dd..a3866a0 100644
> > --- a/jshn.c
> > +++ b/jshn.c
> > @@ -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"
> > @@ -300,7 +302,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;
> >  }
> >
> > @@ -333,6 +335,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++);
> > @@ -354,7 +360,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;
> > @@ -362,6 +368,26 @@ 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)) || 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;  
> nitpick/preference: I would move this code into a file, so that the
> case statement is not too loaded
> it would allow for a simpler/cleaner code-path with some goto
> statements [if put into a function]

Yeah, I tried keeping all those error case printf and return blocks as minimal
as possible, though it still boils down to 3. Might be an idea to factor out the
file-opening-and-reading into a separate function to keep the switch statement
cleaner, but then OTOH it'd be a function with only one caller. 

Also, I was unsure if it'd be overkill to assign different exit codes to the
different error conditions, so I simply used the first unused one (3) for all
of them. 

> 
> >                 case 'w':
> >                         return jshn_format(no_newline, indent);
> >                 case 'n':
> > diff --git a/sh/jshn.sh b/sh/jshn.sh
> > index bf76edb..0a146e1 100644
> > --- a/sh/jshn.sh
> > +++ b/sh/jshn.sh
> > @@ -174,6 +174,10 @@ json_load() {
> >         eval "`jshn -r "$1"`"
> >  }
> >
> > +json_load_file() {
> > +       eval "`jshn -R "$1"`"  
> would it be an idea to try to use $JSON_PREFIX here ?
> for cases when you need to change the JSON namespace, the JSON_PREFIX
> var is used if available
> it would definitely complete this function

TBH, I don't really know what JSON_PREFIX is for. I simply used the existing
json_load() function as a blueprint.

> 
> > +}
> > +
> >  json_dump() {
> >         jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
> >  }
> > --
> > 2.11.0
> >  
> 
> from my side [as a simple reviewer], this looks pretty neat
> 
> thanks :)

cool, thanks!

> 
> Alex
> 
> >
> > _______________________________________________
> > Lede-dev mailing list
> > Lede-dev@lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/lede-dev
Alexandru Ardelean Nov. 19, 2017, 11:57 a.m. UTC | #3
On Sat, Nov 18, 2017 at 3:55 PM, Christian Beier <dontmind@sdf.org> wrote:
> Am Fri, 17 Nov 2017 09:17:39 +0200
> schrieb Alexandru Ardelean <ardeleanalex@gmail.com>:
>
>> On Thu, Nov 16, 2017 at 8:52 PM, Christian Beier <dontmind@freeshell.org>
>> wrote:
>> > 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>
>> > ---
>> >  jshn.c     | 30 ++++++++++++++++++++++++++++--
>> >  sh/jshn.sh |  4 ++++
>> >  2 files changed, 32 insertions(+), 2 deletions(-)
>> >
>> > diff --git a/jshn.c b/jshn.c
>> > index 79136dd..a3866a0 100644
>> > --- a/jshn.c
>> > +++ b/jshn.c
>> > @@ -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"
>> > @@ -300,7 +302,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;
>> >  }
>> >
>> > @@ -333,6 +335,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++);
>> > @@ -354,7 +360,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;
>> > @@ -362,6 +368,26 @@ 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)) || 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;
>> nitpick/preference: I would move this code into a file, so that the
>> case statement is not too loaded
>> it would allow for a simpler/cleaner code-path with some goto
>> statements [if put into a function]
>
> Yeah, I tried keeping all those error case printf and return blocks as minimal
> as possible, though it still boils down to 3. Might be an idea to factor out the
> file-opening-and-reading into a separate function to keep the switch statement
> cleaner, but then OTOH it'd be a function with only one caller.
>
> Also, I was unsure if it'd be overkill to assign different exit codes to the
> different error conditions, so I simply used the first unused one (3) for all
> of them.
>
>>
>> >                 case 'w':
>> >                         return jshn_format(no_newline, indent);
>> >                 case 'n':
>> > diff --git a/sh/jshn.sh b/sh/jshn.sh
>> > index bf76edb..0a146e1 100644
>> > --- a/sh/jshn.sh
>> > +++ b/sh/jshn.sh
>> > @@ -174,6 +174,10 @@ json_load() {
>> >         eval "`jshn -r "$1"`"
>> >  }
>> >
>> > +json_load_file() {
>> > +       eval "`jshn -R "$1"`"
>> would it be an idea to try to use $JSON_PREFIX here ?
>> for cases when you need to change the JSON namespace, the JSON_PREFIX
>> var is used if available
>> it would definitely complete this function
>
> TBH, I don't really know what JSON_PREFIX is for. I simply used the existing
> json_load() function as a blueprint.

oh right ;
disregard what i was saying ;
i was looking at the json_dump() function

JSON_PREFIX is used for changing the namespace;
that allows to load into shell vars multiple JSON instances, and
switch between them with the json_set_namespace() function ;
it's useful when you need to work with more than 1 JSON objects/instances

>
>>
>> > +}
>> > +
>> >  json_dump() {
>> >         jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
>> >  }
>> > --
>> > 2.11.0
>> >
>>
>> from my side [as a simple reviewer], this looks pretty neat
>>
>> thanks :)
>
> cool, thanks!
>
>>
>> Alex
>>
>> >
>> > _______________________________________________
>> > Lede-dev mailing list
>> > Lede-dev@lists.infradead.org
>> > http://lists.infradead.org/mailman/listinfo/lede-dev
>
John Crispin Dec. 12, 2017, 11:03 a.m. UTC | #4
Hi Christian,

small formatting nitpick inline ...


On 16/11/17 19:52, Christian Beier wrote:
> 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>
> ---
>   jshn.c     | 30 ++++++++++++++++++++++++++++--
>   sh/jshn.sh |  4 ++++
>   2 files changed, 32 insertions(+), 2 deletions(-)
>
> diff --git a/jshn.c b/jshn.c
> index 79136dd..a3866a0 100644
> --- a/jshn.c
> +++ b/jshn.c
> @@ -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"
> @@ -300,7 +302,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;
>   }
>   
> @@ -333,6 +335,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++);
> @@ -354,7 +360,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;
> @@ -362,6 +368,26 @@ int main(int argc, char **argv)
>   			break;
>   		case 'r':
>   			return jshn_parse(optarg);
> +		case 'R':
> +		        if((fd = open(optarg, O_RDONLY)) == -1) {
  you have spaces leading up to the if() and then needs to be a space 
between if and (

> +			    fprintf(stderr, "Error opening %s\n", optarg);
> +			    return 3;
spaces vs tabs
> +			}
> +			if (fstat(fd, &sb) == -1) {
> +			    fprintf(stderr, "Error getting size of %s\n", optarg);
> +			    close(fd);
> +			    return 3;
spaces vs tabs
> +			}
> +			if(!(fbuf = malloc(sb.st_size)) || read(fd, fbuf, sb.st_size) != sb.st_size) {
> +			    fprintf(stderr, "Error reading %s\n", optarg);
> +			    free(fbuf);
> +			    close(fd);
> +			    return 3;
spaces vs tabs

     John

> +			}
> +			ret = jshn_parse(fbuf);
> +			free(fbuf);
> +			close(fd);
> +			return ret;
>   		case 'w':
>   			return jshn_format(no_newline, indent);
>   		case 'n':
> diff --git a/sh/jshn.sh b/sh/jshn.sh
> index bf76edb..0a146e1 100644
> --- a/sh/jshn.sh
> +++ b/sh/jshn.sh
> @@ -174,6 +174,10 @@ json_load() {
>   	eval "`jshn -r "$1"`"
>   }
>   
> +json_load_file() {
> +	eval "`jshn -R "$1"`"
> +}
> +
>   json_dump() {
>   	jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w
>   }
Michael Yartys via Lede-dev Dec. 12, 2017, 6:40 p.m. UTC | #5
The sender domain has a DMARC Reject/Quarantine policy which disallows
sending mailing list messages using the original "From" header.

To mitigate this problem, the original message has been wrapped
automatically by the mailing list software.
Am Tue, 12 Dec 2017 12:03:50 +0100
schrieb John Crispin <john@phrozen.org>:

> Hi Christian,
> 
> small formatting nitpick inline ...

Hi John,

Re-sending with tab adjustments and a space between if and the opening paren.

Cheers, 

   Christian
From fcb002d7c8db41b27713f69422a4e2baecad08b0 Mon Sep 17 00:00:00 2001
From: Christian Beier <dontmind@freeshell.org>
Date: Tue, 12 Dec 2017 19:33:12 +0100
Subject: [PATCH] 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>
---
 jshn.c     | 30 ++++++++++++++++++++++++++++--
 sh/jshn.sh |  4 ++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/jshn.c b/jshn.c
index 79136dd..4a69994 100644
--- a/jshn.c
+++ b/jshn.c
@@ -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"
@@ -300,7 +302,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;
 }
 
@@ -333,6 +335,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++);
@@ -354,7 +360,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;
@@ -362,6 +368,26 @@ 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)) || 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':
diff --git a/sh/jshn.sh b/sh/jshn.sh
index bf76edb..0a146e1 100644
--- a/sh/jshn.sh
+++ b/sh/jshn.sh
@@ -174,6 +174,10 @@ json_load() {
 	eval "`jshn -r "$1"`"
 }
 
+json_load_file() {
+	eval "`jshn -R "$1"`"
+}
+
 json_dump() {
 	jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w 
 }
Christian Beier Dec. 22, 2017, 1:01 p.m. UTC | #6
Am Tue, 12 Dec 2017 19:39:48 +0100
schrieb Christian Beier <christian.cb.beier@gmail.com>:

> Am Tue, 12 Dec 2017 12:03:50 +0100
> schrieb John Crispin <john@phrozen.org>:
> 
> > Hi Christian,
> > 
> > small formatting nitpick inline ...  
> 
> Hi John,
> 
> Re-sending with tab adjustments and a space between if and the opening paren.
> 
> Cheers, 
> 
>    Christian

Hi John,

Is there anything I forgot to take care of? I did not see this appear in
https://git.lede-project.org/?p=project/libubox.git yet. Or has the repo
location changed?

Cheers,

   Christian
Christian Beier Jan. 7, 2018, 5:08 p.m. UTC | #7
This is an updated version of the patch I sent earlier, now with
the reformatting changes requested by John. Apparently my previous
resend somehow got lost (as I did not use git send-email?).
diff mbox series

Patch

diff --git a/jshn.c b/jshn.c
index 79136dd..a3866a0 100644
--- a/jshn.c
+++ b/jshn.c
@@ -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"
@@ -300,7 +302,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;
 }
 
@@ -333,6 +335,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++);
@@ -354,7 +360,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;
@@ -362,6 +368,26 @@  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)) || 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':
diff --git a/sh/jshn.sh b/sh/jshn.sh
index bf76edb..0a146e1 100644
--- a/sh/jshn.sh
+++ b/sh/jshn.sh
@@ -174,6 +174,10 @@  json_load() {
 	eval "`jshn -r "$1"`"
 }
 
+json_load_file() {
+	eval "`jshn -R "$1"`"
+}
+
 json_dump() {
 	jshn "$@" ${JSON_PREFIX:+-p "$JSON_PREFIX"} -w 
 }