systemd-journal-dyncfg.c 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. #include "systemd-internals.h"
  3. #define JOURNAL_DIRECTORIES_JSON_NODE "journalDirectories"
  4. static int systemd_journal_directories_dyncfg_update(BUFFER *result, BUFFER *payload) {
  5. if(!payload || !buffer_strlen(payload))
  6. return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "empty payload received");
  7. CLEAN_JSON_OBJECT *jobj = json_tokener_parse(buffer_tostring(payload));
  8. if(!jobj)
  9. return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "cannot parse json payload");
  10. struct json_object *journalDirectories;
  11. json_object_object_get_ex(jobj, JOURNAL_DIRECTORIES_JSON_NODE, &journalDirectories);
  12. size_t n_directories = json_object_array_length(journalDirectories);
  13. size_t added = 0;
  14. for(size_t i = 0; i < n_directories; i++) {
  15. struct json_object *dir = json_object_array_get_idx(journalDirectories, i);
  16. const char *s = json_object_get_string(dir);
  17. if(s && *s) {
  18. string_freez(journal_directories[added].path);
  19. journal_directories[added++].path = string_strdupz(s);
  20. }
  21. }
  22. if(!added)
  23. return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "no directories in the payload");
  24. else {
  25. for(size_t i = added; i < MAX_JOURNAL_DIRECTORIES; i++) {
  26. string_freez(journal_directories[i].path);
  27. journal_directories[i].path = NULL;
  28. }
  29. }
  30. return dyncfg_default_response(result, HTTP_RESP_OK, "applied");
  31. }
  32. static int systemd_journal_directories_dyncfg_get(BUFFER *wb) {
  33. buffer_flush(wb);
  34. buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
  35. buffer_json_member_add_array(wb, JOURNAL_DIRECTORIES_JSON_NODE);
  36. for(size_t i = 0; i < MAX_JOURNAL_DIRECTORIES ;i++) {
  37. if(!journal_directories[i].path)
  38. break;
  39. buffer_json_add_array_item_string(wb, string2str(journal_directories[i].path));
  40. }
  41. buffer_json_array_close(wb);
  42. buffer_json_finalize(wb);
  43. return HTTP_RESP_OK;
  44. }
  45. static int systemd_journal_directories_dyncfg_cb(const char *transaction,
  46. const char *id,
  47. DYNCFG_CMDS cmd,
  48. BUFFER *payload,
  49. usec_t *stop_monotonic_ut __maybe_unused,
  50. bool *cancelled __maybe_unused,
  51. BUFFER *result,
  52. const char *source __maybe_unused,
  53. void *data __maybe_unused) {
  54. CLEAN_BUFFER *action = buffer_create(100, NULL);
  55. dyncfg_cmds2buffer(cmd, action);
  56. if(cmd == DYNCFG_CMD_GET)
  57. return systemd_journal_directories_dyncfg_get(result);
  58. if(cmd == DYNCFG_CMD_UPDATE)
  59. return systemd_journal_directories_dyncfg_update(result, payload);
  60. nd_log(NDLS_COLLECTORS, NDLP_ERR,
  61. "DYNCFG: unhandled transaction '%s', id '%s' cmd '%s', payload: %s",
  62. transaction, id, buffer_tostring(action), payload ? buffer_tostring(payload) : "");
  63. return dyncfg_default_response(result, HTTP_RESP_BAD_REQUEST, "the command is not handled by this plugin");
  64. }
  65. // ----------------------------------------------------------------------------
  66. void systemd_journal_dyncfg_init(struct functions_evloop_globals *wg) {
  67. functions_evloop_dyncfg_add(
  68. wg,
  69. "systemd-journal:monitored-directories",
  70. "/collectors/logs/systemd-journal",
  71. DYNCFG_STATUS_RUNNING,
  72. DYNCFG_TYPE_SINGLE,
  73. DYNCFG_SOURCE_TYPE_INTERNAL,
  74. "internal",
  75. DYNCFG_CMD_SCHEMA | DYNCFG_CMD_GET | DYNCFG_CMD_UPDATE,
  76. systemd_journal_directories_dyncfg_cb,
  77. NULL);
  78. }