@@ -65,6 +65,8 @@ static int sscanf_is_broken = 0; | |||||
static int sscanf_is_broken_testdone = 0; | static int sscanf_is_broken_testdone = 0; | ||||
static void sscanf_is_broken_test(void); | static void sscanf_is_broken_test(void); | ||||
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename); | |||||
static char _last_err[256] = ""; | static char _last_err[256] = ""; | ||||
const char *json_util_get_last_err() | const char *json_util_get_last_err() | ||||
@@ -126,42 +128,61 @@ struct json_object* json_object_from_file(const char *filename) | |||||
int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) | int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags) | ||||
{ | { | ||||
const char *json_str; | |||||
int fd, ret; | |||||
unsigned int wpos, wsize; | |||||
int fd, ret; | |||||
int saved_errno; | |||||
if(!obj) { | |||||
_set_last_err("json_object_to_file: object is null\n"); | |||||
return -1; | |||||
} | |||||
if (!obj) { | |||||
_set_last_err("json_object_to_file: object is null\n"); | |||||
return -1; | |||||
} | |||||
if((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { | |||||
_set_last_err("json_object_to_file: error opening file %s: %s\n", | |||||
filename, strerror(errno)); | |||||
return -1; | |||||
} | |||||
if ((fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) { | |||||
_set_last_err("json_object_to_file: error opening file %s: %s\n", | |||||
filename, strerror(errno)); | |||||
return -1; | |||||
} | |||||
ret = _json_object_to_fd(fd, obj, flags, filename); | |||||
saved_errno = errno; | |||||
close(fd); | |||||
errno = saved_errno; | |||||
return ret; | |||||
} | |||||
if(!(json_str = json_object_to_json_string_ext(obj,flags))) { | |||||
close(fd); | |||||
return -1; | |||||
} | |||||
int json_object_to_fd(int fd, struct json_object *obj, int flags) | |||||
{ | |||||
if (!obj) { | |||||
_set_last_err("json_object_to_fd: object is null\n"); | |||||
return -1; | |||||
} | |||||
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ | |||||
wpos = 0; | |||||
while(wpos < wsize) { | |||||
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { | |||||
close(fd); | |||||
_set_last_err("json_object_to_file: error writing file %s: %s\n", | |||||
filename, strerror(errno)); | |||||
return -1; | |||||
} | |||||
return _json_object_to_fd(fd, obj, flags, NULL); | |||||
} | |||||
static int _json_object_to_fd(int fd, struct json_object *obj, int flags, const char *filename) | |||||
{ | |||||
int ret; | |||||
const char *json_str; | |||||
unsigned int wpos, wsize; | |||||
/* because of the above check for ret < 0, we can safely cast and add */ | |||||
wpos += (unsigned int)ret; | |||||
} | |||||
filename = filename ? filename : "(fd)"; | |||||
close(fd); | |||||
return 0; | |||||
if (!(json_str = json_object_to_json_string_ext(obj,flags))) { | |||||
return -1; | |||||
} | |||||
wsize = (unsigned int)(strlen(json_str) & UINT_MAX); /* CAW: probably unnecessary, but the most 64bit safe */ | |||||
wpos = 0; | |||||
while(wpos < wsize) { | |||||
if((ret = write(fd, json_str + wpos, wsize-wpos)) < 0) { | |||||
_set_last_err("json_object_to_file: error writing file %s: %s\n", | |||||
filename, strerror(errno)); | |||||
return -1; | |||||
} | |||||
/* because of the above check for ret < 0, we can safely cast and add */ | |||||
wpos += (unsigned int)ret; | |||||
} | |||||
return 0; | |||||
} | } | ||||
// backwards compatible "format and write to file" function | // backwards compatible "format and write to file" function | ||||
@@ -67,7 +67,18 @@ extern int json_object_to_file(const char *filename, struct json_object *obj); | |||||
extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); | extern int json_object_to_file_ext(const char *filename, struct json_object *obj, int flags); | ||||
/** | /** | ||||
* Return the last error from json_object_to_file{,_ext} or | |||||
* Convert the json_object to a string and write it to the file descriptor. | |||||
* Handles partial writes and will keep writing until done, or an error | |||||
* occurs. | |||||
* | |||||
* @param flags flags to pass to json_object_to_json_string_ext() | |||||
* @return -1 if something fails. See json_util_get_last_err() for details. | |||||
*/ | |||||
extern int json_object_to_fd(int fd, struct json_object *obj, int flags); | |||||
/** | |||||
* Return the last error from json_object_to_file{,_ext}, | |||||
* json_object_to_fd() or | |||||
* json_object_from_{file,fd}, or NULL if there is none. | * json_object_from_{file,fd}, or NULL if there is none. | ||||
*/ | */ | ||||
const char *json_util_get_last_err(void); | const char *json_util_get_last_err(void); | ||||
@@ -49,6 +49,25 @@ static void test_write_to_file() | |||||
(rv == 0) ? "OK" : "FAIL", outfile2, rv); | (rv == 0) ? "OK" : "FAIL", outfile2, rv); | ||||
if (rv == 0) | if (rv == 0) | ||||
stat_and_cat(outfile2); | stat_and_cat(outfile2); | ||||
const char *outfile3 = "json3.out"; | |||||
int d = open(outfile3, O_WRONLY|O_CREAT, 0600); | |||||
if (d < 0) | |||||
{ | |||||
printf("FAIL: unable to open %s %s\n", outfile3, strerror(errno)); | |||||
return; | |||||
} | |||||
rv = json_object_to_fd(d, jso, JSON_C_TO_STRING_PRETTY); | |||||
printf("%s: json_object_to_fd(%s, jso, JSON_C_TO_STRING_PRETTY)=%d\n", | |||||
(rv == 0) ? "OK" : "FAIL", outfile3, rv); | |||||
// Write the same object twice | |||||
rv = json_object_to_fd(d, jso, JSON_C_TO_STRING_PLAIN); | |||||
printf("%s: json_object_to_fd(%s, jso, JSON_C_TO_STRING_PLAIN)=%d\n", | |||||
(rv == 0) ? "OK" : "FAIL", outfile3, rv); | |||||
close(d); | |||||
if (rv == 0) | |||||
stat_and_cat(outfile3); | |||||
json_object_put(jso); | json_object_put(jso); | ||||
} | } | ||||
@@ -19,3 +19,17 @@ file[json2.out], size=367, contents={ | |||||
"foo8":"abcdefghijklmnopqrstuvwxyz", | "foo8":"abcdefghijklmnopqrstuvwxyz", | ||||
"foo9":"abcdefghijklmnopqrstuvwxyz" | "foo9":"abcdefghijklmnopqrstuvwxyz" | ||||
} | } | ||||
OK: json_object_to_fd(json3.out, jso, JSON_C_TO_STRING_PRETTY)=0 | |||||
OK: json_object_to_fd(json3.out, jso, JSON_C_TO_STRING_PLAIN)=0 | |||||
file[json3.out], size=703, contents={ | |||||
"foo":1234, | |||||
"foo1":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo2":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo3":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo4":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo5":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo6":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo7":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo8":"abcdefghijklmnopqrstuvwxyz", | |||||
"foo9":"abcdefghijklmnopqrstuvwxyz" | |||||
}{"foo":1234,"foo1":"abcdefghijklmnopqrstuvwxyz","foo2":"abcdefghijklmnopqrstuvwxyz","foo3":"abcdefghijklmnopqrstuvwxyz","foo4":"abcdefghijklmnopqrstuvwxyz","foo5":"abcdefghijklmnopqrstuvwxyz","foo6":"abcdefghijklmnopqrstuvwxyz","foo7":"abcdefghijklmnopqrstuvwxyz","foo8":"abcdefghijklmnopqrstuvwxyz","foo9":"abcdefghijklmnopqrstuvwxyz"} |