diff options
-rw-r--r-- | runtime/lookup.c | 77 | ||||
-rw-r--r-- | runtime/rsyslog.h | 1 |
2 files changed, 78 insertions, 0 deletions
diff --git a/runtime/lookup.c b/runtime/lookup.c index f1931838..c581da6c 100644 --- a/runtime/lookup.c +++ b/runtime/lookup.c @@ -22,9 +22,16 @@ #include "config.h" #include <stdlib.h> #include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <json/json.h> +#include <json/json.h> #include <assert.h> #include "rsyslog.h" +#include "srUtils.h" #include "errmsg.h" #include "lookup.h" #include "msg.h" @@ -91,6 +98,75 @@ lookupInitCnf(lookup_tables_t *lu_tabs) } +/* note: widely-deployed json_c 0.9 does NOT support incremental + * parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS, + * we read the file into one big memory buffer and parse it at once. + * While this is not very elegant, it will not pose any real issue + * for "reasonable" lookup tables (and "unreasonably" large ones + * will probably have other issues as well...). + */ +rsRetVal +lookupReadFile(lookup_t *pThis) +{ + struct json_tokener *tokener = NULL; + struct json_object *json; + int eno = errno; + char errStr[1024]; + char *iobuf = NULL; + int fd; + ssize_t nread; + struct stat sb; + enum json_tokener_error jerr; + DEFiRet; + + + if(stat((char*)pThis->filename, &sb) == -1) { + eno = errno; + errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, + "lookup table file '%s' stat failed: %s", + pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); + } + + CHKmalloc(iobuf = malloc(sb.st_size)); + + if((fd = open((const char*) pThis->filename, O_RDONLY)) == -1) { + eno = errno; + errmsg.LogError(0, RS_RET_FILE_NOT_FOUND, + "lookup table file '%s' could not be opened: %s", + pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_FILE_NOT_FOUND); + } + + tokener = json_tokener_new(); + nread = read(fd, iobuf, sb.st_size); +dbgprintf("DDDD: read buffer of %lld bytes: '%s'\n", (long long) sb.st_size, iobuf); + if(nread != (ssize_t) sb.st_size) { + eno = errno; + errmsg.LogError(0, RS_RET_READ_ERR, + "lookup table file '%s' read error: %s", + pThis->filename, rs_strerror_r(eno, errStr, sizeof(errStr))); + ABORT_FINALIZE(RS_RET_READ_ERR); + } + + json = json_tokener_parse_ex(tokener, iobuf, sb.st_size); + if(json == NULL) { + errmsg.LogError(0, RS_RET_JSON_PARSE_ERR, + "lookup table file '%s' json parsing error", + pThis->filename); + ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); + } + + /* got json object, now populate our own in-memory structure */ + +finalize_it: + free(iobuf); + if(tokener != NULL) + json_tokener_free(tokener); + RETiRet; +} + + rsRetVal lookupProcessCnf(struct cnfobj *o) { @@ -120,6 +196,7 @@ lookupProcessCnf(struct cnfobj *o) "param '%s'\n", modpblk.descr[i].name); } } + CHKiRet(lookupReadFile(lu)); DBGPRINTF("lookup table '%s' loaded from file '%s'\n", lu->name, lu->filename); finalize_it: diff --git a/runtime/rsyslog.h b/runtime/rsyslog.h index 63112627..99bf2ece 100644 --- a/runtime/rsyslog.h +++ b/runtime/rsyslog.h @@ -417,6 +417,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth RS_RET_QUEUE_CRY_DISK_ONLY = -2351,/**< crypto provider only supported for disk-associated queues */ RS_RET_NO_DATA = -2352,/**< file has no data; more a state than a real error */ RS_RET_RELP_AUTH_FAIL = -2353,/**< RELP peer authentication failed */ + RS_RET_READ_ERR = -2354,/**< read error occured (file i/o) */ /* RainerScript error messages (range 1000.. 1999) */ RS_RET_SYSVAR_NOT_FOUND = 1001, /**< system variable could not be found (maybe misspelled) */ |