]> git.ipfire.org Git - collecty.git/commitdiff
string: Add formatting functions
authorMichael Tremer <michael.tremer@ipfire.org>
Sun, 5 Oct 2025 14:23:09 +0000 (14:23 +0000)
committerMichael Tremer <michael.tremer@ipfire.org>
Sun, 5 Oct 2025 14:23:09 +0000 (14:23 +0000)
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
src/daemon/proc.c
src/daemon/proto.c
src/daemon/source.c
src/daemon/string.h
src/daemon/util.c

index 972709f6b5c391700e9289cb552aac666cceb6bc..a4e952980594b923fc19b9e724cbfc2baadbe92e 100644 (file)
@@ -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;
index 71b43c7232fd925ff326fdf63db4f3c0e02635d0..8f789b14906da2f8f0210b75f8896f9a5529e10c 100644 (file)
@@ -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;
index 9046d2c7ea7a23f4d4a126b238c1b20a2b5db694..9256cf28b83a687b3ab57af7f8840bebb34ea689 100644 (file)
@@ -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
index ea52538857f7f3fbd3be7d1cebf2e0c24b07d7ad..3f5d982f36f75cd2aef121b2286cdc71201375b6 100644 (file)
 #define COLLECTY_STRING_H
 
 #include <ctype.h>
+#include <errno.h>
 #include <string.h>
 
+#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;
index 093ed1d920541d17b91cd743b6c8de6aae8e68e4..45ae46fd74a837bba19213fcfba7002864cb54c4 100644 (file)
 #include <stdint.h>
 #include <stdio.h>
 
+#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) {