fort_SOURCES += $(ASN_MODULE_SRCS) $(ASN_MODULE_HDRS)
fort_CFLAGS = -Wall -Wpedantic
-# Feel free to temporarily remove this one if you're not using gcc 7.3.0.
#fort_CFLAGS += $(GCC_WARNS)
-fort_CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=700
+fort_CFLAGS += -std=c99 -D_DEFAULT_SOURCE=1 -D_XOPEN_SOURCE=700 -D_BSD_SOURCE=1
fort_CFLAGS += -O2 -g $(FORT_FLAGS) ${XML2_CFLAGS}
if BACKTRACE_ENABLED
fort_CFLAGS += -DBACKTRACE_ENABLED
# I'm tired of scrolling up, but feel free to comment this out.
GCC_WARNS = -fmax-errors=1
-# Please ready some arguments if you want to permanently remove some of these
-# flags. I gave a quick read to the documentation of all of these warnings, and
-# generally liked each of them.
GCC_WARNS += -pedantic-errors -Waddress -Walloc-zero -Walloca
GCC_WARNS += -Wno-aggressive-loop-optimizations -Warray-bounds=2 -Wbool-compare
GCC_WARNS += -Wbool-operation -Wno-builtin-declaration-mismatch -Wcast-align
if (uri_is_notif(node->url))
if (json_add_bool(json, TAGNAME_IS_NOTIF, true))
goto cancel;
- if (json_add_date(json, TAGNAME_ATTEMPT_TS, node->attempt.ts))
+ if (json_add_ts(json, TAGNAME_ATTEMPT_TS, node->attempt.ts))
goto cancel;
if (json_add_int(json, TAGNAME_ATTEMPT_ERR, node->attempt.result))
goto cancel;
if (node->success.happened)
- if (json_add_date(json, TAGNAME_SUCCESS_TS, node->success.ts))
+ if (json_add_ts(json, TAGNAME_SUCCESS_TS, node->success.ts))
goto cancel;
return json;
* documented in the Linux man page are not actually portable.
*/
#define JSON_TS_FORMAT "%Y-%m-%dT%H:%M:%SZ"
+#define JSON_TS_LEN 21 /* strlen("YYYY-mm-ddTHH:MM:SSZ") + 1 */
int
json_get_str(json_t *parent, char const *name, char const **result)
return 0;
}
-int
-json_get_ts(json_t *parent, char const *name, time_t *result)
+static int
+str2tt(char const *str, time_t *tt)
{
- char const *str, *consumed;
+ char const *consumed;
struct tm tm;
time_t time;
int error;
- *result = 0;
-
- error = json_get_str(parent, name, &str);
- if (error)
- return error;
-
memset(&tm, 0, sizeof(tm));
consumed = strptime(str, JSON_TS_FORMAT, &tm);
if (consumed == NULL || (*consumed) != 0)
return pr_op_err("String '%s' does not appear to be a timestamp.",
str);
- time = mktime(&tm);
+ time = timegm(&tm);
if (time == ((time_t) -1)) {
error = errno;
return pr_op_err("String '%s' does not appear to be a timestamp: %s",
str, strerror(error));
}
- *result = time;
+ *tt = time;
return 0;
}
+int
+json_get_ts(json_t *parent, char const *name, time_t *result)
+{
+ char const *str;
+ int error;
+
+ error = json_get_str(parent, name, &str);
+ if (error)
+ return error;
+
+ return str2tt(str, result);
+}
+
int
json_get_array(json_t *parent, char const *name, json_t **array)
{
}
static int
-tt2json(time_t tt, json_t **result)
+tt2str(time_t tt, char *str)
{
- char str[32];
struct tm tmbuffer, *tm;
memset(&tmbuffer, 0, sizeof(tmbuffer));
tm = gmtime_r(&tt, &tmbuffer);
if (tm == NULL)
return errno;
- if (strftime(str, sizeof(str) - 1, JSON_TS_FORMAT, tm) == 0)
+ if (strftime(str, JSON_TS_LEN, JSON_TS_FORMAT, tm) == 0)
return ENOSPC;
- *result = json_string(str);
return 0;
}
int
-json_add_date(json_t *parent, char const *name, time_t value)
+json_add_ts(json_t *parent, char const *name, time_t value)
{
- json_t *date = NULL;
+ char str[JSON_TS_LEN];
int error;
- error = tt2json(value, &date);
+ error = tt2str(value, str);
if (error) {
pr_op_err("Cannot convert timestamp '%s' to json: %s",
name, strerror(error));
return error;
}
- if (json_object_set_new(parent, name, date))
+ if (json_object_set_new(parent, name, json_string(str)))
return pr_op_err(
"Cannot convert timestamp '%s' to json; unknown cause.",
name
int json_add_bool(json_t *, char const *, bool);
int json_add_int(json_t *, char const *, int);
int json_add_str(json_t *, char const *, char const *);
-int json_add_date(json_t *, char const *, time_t);
+int json_add_ts(json_t *, char const *, time_t);
#endif /* SRC_JSON_UTIL_H_ */
# mumble_mumble_CFLAGS = ${AM_CFLAGS} flag1 flag2 flag3 ...
AM_CFLAGS = -pedantic -Wall
#AM_CFLAGS += -Wno-unused
-AM_CFLAGS += -std=c99 -D_POSIX_C_SOURCE=200809 -D_XOPEN_SOURCE=700
-AM_CFLAGS += -I../src -DUNIT_TESTING ${CHECK_CFLAGS} ${XML2_CFLAGS}
+AM_CFLAGS += -std=c99 -D_DEFAULT_SOURCE=1 -D_XOPEN_SOURCE=700 -D_BSD_SOURCE=1
+AM_CFLAGS += -I../src -DUNIT_TESTING ${CHECK_CFLAGS} ${XML2_CFLAGS} ${JANSSON_CFLAGS}
# Reminder: As opposed to AM_CFLAGS, "AM_LDADD" is not idiomatic automake, and
# autotools will even reprehend us if we declare it. Therefore, I came up with
# "my" own "ldadd". Unlike AM_CFLAGS, it needs to be manually added to every
# target.
-MY_LDADD = ${CHECK_LIBS}
+MY_LDADD = ${CHECK_LIBS} ${JANSSON_LIBS}
check_PROGRAMS = address.test
check_PROGRAMS += cache.test
check_PROGRAMS += db_table.test
check_PROGRAMS += deltas_array.test
+check_PROGRAMS += json.test
check_PROGRAMS += line_file.test
check_PROGRAMS += pb.test
check_PROGRAMS += pdu_handler.test
deltas_array_test_SOURCES = rtr/db/deltas_array_test.c
deltas_array_test_LDADD = ${MY_LDADD}
+json_test_SOURCES = json_util_test.c
+json_test_LDADD = ${MY_LDADD}
+
line_file_test_SOURCES = line_file_test.c
line_file_test_LDADD = ${MY_LDADD}
--- /dev/null
+#include "json_util.c"
+
+#include <check.h>
+
+#include "mock.c"
+
+START_TEST(test_tt)
+{
+ char str[JSON_TS_LEN + 1];
+ time_t tt;
+
+ ck_assert_int_eq(0, str2tt("2024-03-14T17:51:16Z", &tt));
+
+ memset(str, 'f', sizeof(str));
+ ck_assert_int_eq(0, tt2str(tt, str));
+ ck_assert_str_eq("2024-03-14T17:51:16Z", str);
+ ck_assert_int_eq('f', str[JSON_TS_LEN]); /* Tests JSON_TS_LEN. */
+}
+END_TEST
+
+static Suite *json_load_suite(void)
+{
+ Suite *suite;
+ TCase *core;
+
+ core = tcase_create("utils");
+ tcase_add_test(core, test_tt);
+
+ suite = suite_create("JSON util");
+ suite_add_tcase(suite, core);
+ return suite;
+}
+
+int main(void)
+{
+ Suite *suite;
+ SRunner *runner;
+ int tests_failed;
+
+ suite = json_load_suite();
+
+ runner = srunner_create(suite);
+ srunner_run_all(runner, CK_NORMAL);
+ tests_failed = srunner_ntests_failed(runner);
+ srunner_free(runner);
+
+ return (tests_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}