From: Michael Tremer Date: Sun, 5 Oct 2025 14:23:09 +0000 (+0000) Subject: string: Add formatting functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d52904c4d8fc6635f7a941a733e7998ba387bb6d;p=telemetry.git string: Add formatting functions Signed-off-by: Michael Tremer --- diff --git a/src/daemon/proc.c b/src/daemon/proc.c index 972709f..a4e9529 100644 --- a/src/daemon/proc.c +++ b/src/daemon/proc.c @@ -218,7 +218,7 @@ int collecty_proc_read_pressure(collecty_ctx* ctx, int r; // Make the path - r = snprintf(path, sizeof(path), "/proc/pressure/%s", what); + r = collecty_string_format(path, "/proc/pressure/%s", what); if (r < 0) return -errno; @@ -295,7 +295,7 @@ int collecty_proc_read_softirq(collecty_ctx* ctx, } // Store the key - r = snprintf(key, sizeof(key), "%s", t); + r = collecty_string_set(key, t); if (r < 0) { r = -errno; goto ERROR; diff --git a/src/daemon/proto.c b/src/daemon/proto.c index 71b43c7..8f789b1 100644 --- a/src/daemon/proto.c +++ b/src/daemon/proto.c @@ -116,12 +116,12 @@ static int collecty_proto_set(collecty_proto* self, return -errno; // Store proto - r = snprintf(o->proto, sizeof(o->proto), "%s", proto); + r = collecty_string_set(o->proto, proto); if (r < 0) goto ERROR; // Store key - r = snprintf(o->key, sizeof(o->key), "%s", key); + r = collecty_string_set(o->key, key); if (r < 0) goto ERROR; @@ -175,7 +175,7 @@ static int collecty_proto_read_one(collecty_proto* self, char* keys, char* value return -errno; // Store the protocol - r = snprintf(proto, sizeof(proto), "%s", k); + r = collecty_string_set(proto, k); if (r < 0) return -errno; @@ -243,7 +243,7 @@ int collecty_proto_read(collecty_proto* self, const char* path) { // Even line case 0: // Just store the keys - r = snprintf(keys, sizeof(keys), "%s", line); + r = collecty_string_set(keys, line); if (r < 0) goto ERROR; break; diff --git a/src/daemon/source.c b/src/daemon/source.c index 9046d2c..9256cf2 100644 --- a/src/daemon/source.c +++ b/src/daemon/source.c @@ -33,6 +33,7 @@ #include "ctx.h" #include "daemon.h" #include "source.h" +#include "string.h" #include "time.h" #include "util.h" @@ -440,21 +441,13 @@ const char* collecty_source_name(collecty_source* self) { static int __collecty_source_path(collecty_source* self, const char* object, char* path, size_t length) { - int r; - // Fetch the source name const char* name = collecty_source_name(self); if (object) - r = snprintf(path, length, "%s/%s-%s.rrd", DATABASE_PATH, name, object); - else - r = snprintf(path, length, "%s/%s.rrd", DATABASE_PATH, name); - - // Handle errors - if (r < 0) - return -errno; + return __collecty_string_format(path, length, "%s/%s-%s.rrd", DATABASE_PATH, name, object); - return 0; + return __collecty_string_format(path, length, "%s/%s.rrd", DATABASE_PATH, name); } /* @@ -468,12 +461,12 @@ int collecty_source_submit(collecty_source* self, // Format the arguments va_start(args, format); - r = vsnprintf(value, sizeof(value), format, args); + r = collecty_string_vformat(value, format, args); va_end(args); // Handle errors if (r < 0) - return -errno; + return r; // Submit the data to the daemon return collecty_daemon_submit(self->daemon, self, object, value); @@ -592,13 +585,13 @@ static int collecty_source_render_add_DEF(collecty_source* self, // Append the object to the field name so that we can load multiple RRD of the same source if (object) { - r = snprintf(field, sizeof(field), "%s_%s", ds->field, object); + r = collecty_string_format(field, "%s_%s", ds->field, object); if (r < 0) - return -errno; + return r; } else { - r = snprintf(field, sizeof(field), "%s", ds->field); + r = collecty_string_set(field, ds->field); if (r < 0) - return -errno; + return r; } // Add the classic DEF line diff --git a/src/daemon/string.h b/src/daemon/string.h index ea52538..3f5d982 100644 --- a/src/daemon/string.h +++ b/src/daemon/string.h @@ -22,12 +22,75 @@ #define COLLECTY_STRING_H #include +#include #include +#include "util.h" + inline int collecty_string_equals(const char* s1, const char* s2) { return strcmp(s1, s2) == 0; } +#define collecty_string_vformat(s, format, args) \ + __collecty_string_vformat(s, sizeof(s), format, args) + +static inline int __collecty_string_vformat(char* s, + const size_t length, const char* format, va_list args) { + // Write string to buffer + const ssize_t required = vsnprintf(s, length, format, args); + + // Catch any errors + if (unlikely(required < 0)) + return -errno; + + // Check if the entire string could be written + if (unlikely((size_t)required >= length)) + return -ENOBUFS; + + // Success + return 0; +} + +#define collecty_string_format(s, format, ...) \ + __collecty_string_format(s, sizeof(s), format, __VA_ARGS__) + +static inline int __collecty_string_format(char* s, const size_t length, const char* format, ...) { + va_list args; + int r; + + // Call __collecty_string_vformat + va_start(args, format); + r = __collecty_string_vformat(s, length, format, args); + va_end(args); + + return r; +} + +#define collecty_string_set(s, value) \ + __collecty_string_set(s, sizeof(s), value) + +static inline int __collecty_string_set(char* s, const size_t length, const char* value) { + // If value is NULL or an empty, we will overwrite the buffer with just zeros + if (unlikely(!value)) { + *s = '\0'; + return 0; + } + + // Copy everything until we hit the end of the input string + for (unsigned int i = 0; i < length; i++) { + s[i] = value[i]; + + // Done + if (value[i] == '\0') + return 0; + } + + // It seems that the buffer was not large enough. Terminate and return an error. + s[length - 1] = '\0'; + + return -ENOBUFS; +} + inline void collecty_string_lstrip(char* s) { if (!s) return; diff --git a/src/daemon/util.c b/src/daemon/util.c index 093ed1d..45ae46f 100644 --- a/src/daemon/util.c +++ b/src/daemon/util.c @@ -23,24 +23,16 @@ #include #include +#include "string.h" #include "util.h" int __collecty_format_number(char* buffer, size_t length, int number) { - int r; - // Format the number if positive or zero if (number >= 0) - r = snprintf(buffer, length, "%d", number); + return __collecty_string_format(buffer, length, "%d", number); // Otherwise we set it to UNKNOWN - else - r = snprintf(buffer, length, "U"); - - // Abort on error - if (r < 0) - return -errno; - - return 0; + return __collecty_string_set(buffer, length, "U"); } int collecty_file_read_uint64(const char* path, uint64_t* number) {