diff --git a/src/util-strings.c b/src/util-strings.c index 1f415dd..e0a2c6b 100644 --- a/src/util-strings.c +++ b/src/util-strings.c @@ -224,6 +224,46 @@ strreplace(const char *string, const char *separator, const char *replacement) } +char ** +strv_from_mem(const uint8_t *buffer, size_t sz, size_t stride) +{ + assert(stride > 0); + assert(stride <= 16); + + char **strv = xalloc(((sz / stride) + 2) * sizeof *strv); + + #define hex(buffer_, sz, line_, offset_) \ + (line_ + offset_ < sz) ? buffer_[line_ + offset_] : 0u + for (size_t i = 0; i < sz; i += stride) { + char *str = xaprintf( + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + hex(buffer, sz, i, 0), + hex(buffer, sz, i, 1), + hex(buffer, sz, i, 2), + hex(buffer, sz, i, 3), + hex(buffer, sz, i, 4), + hex(buffer, sz, i, 5), + hex(buffer, sz, i, 6), + hex(buffer, sz, i, 7), + hex(buffer, sz, i, 8), + hex(buffer, sz, i, 9), + hex(buffer, sz, i, 10), + hex(buffer, sz, i, 11), + hex(buffer, sz, i, 12), + hex(buffer, sz, i, 13), + hex(buffer, sz, i, 14), + hex(buffer, sz, i, 15)); + + /* Chop the string off at the last value or our stride, whichever applies */ + if (i + stride >= sz) + str[(sz - i) * 3 - 1] = '\0'; + else if (stride < 16) + str[stride * 3 - 1] = '\0'; + strv[i / stride] = str; + } + return strv; +} + #if _enable_tests_ #include "util-munit.h" @@ -498,4 +538,64 @@ MUNIT_TEST(test_strlen0) return MUNIT_OK; } + +MUNIT_TEST(test_strv_from_mem) +{ + uint8_t buf[36]; + + for (size_t i = 0; i < sizeof(buf); i++) + buf[i] = i; + + { + _cleanup_(strv_freep) char **strv = strv_from_mem(buf, 16, 16); + munit_assert(strv != NULL); + munit_assert(strv[0] != NULL); + munit_assert_null(strv[1]); /* we expect one line */ + munit_assert_string_equal(strv[0], "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f"); + } + + { + _cleanup_(strv_freep) char **strv = strv_from_mem(buf, 8, 16); + munit_assert(strv != NULL); + munit_assert(strv[0] != NULL); + munit_assert_null(strv[1]); /* we expect one line */ + munit_assert_string_equal(strv[0], "00 01 02 03 04 05 06 07"); + } + + { + _cleanup_(strv_freep) char **strv = strv_from_mem(buf, 8, 4); + munit_assert(strv != NULL); + munit_assert(strv[0] != NULL); + munit_assert(strv[1] != NULL); + munit_assert_null(strv[2]); /* we expect two lines */ + munit_assert_string_equal(strv[0], "00 01 02 03"); + munit_assert_string_equal(strv[1], "04 05 06 07"); + } + + { + _cleanup_(strv_freep) char **strv = strv_from_mem(buf, sizeof(buf), 5); + munit_assert(strv != NULL); + munit_assert_string_equal(strv[0], "00 01 02 03 04"); + munit_assert_string_equal(strv[1], "05 06 07 08 09"); + munit_assert_string_equal(strv[2], "0a 0b 0c 0d 0e"); + munit_assert_string_equal(strv[3], "0f 10 11 12 13"); + munit_assert_string_equal(strv[4], "14 15 16 17 18"); + munit_assert_string_equal(strv[5], "19 1a 1b 1c 1d"); + munit_assert_string_equal(strv[6], "1e 1f 20 21 22"); + munit_assert_string_equal(strv[7], "23"); + munit_assert_null(strv[8]); + } + + { + uint8_t buffer[14]; + memset(buffer, -1, sizeof(buffer)); + _cleanup_(strv_freep) char **strv = strv_from_mem(buffer, sizeof(buffer), 8); + munit_assert(strv != NULL); + munit_assert_string_equal(strv[0], "ff ff ff ff ff ff ff ff"); + munit_assert_string_equal(strv[1], "ff ff ff ff ff ff"); + munit_assert_null(strv[2]); + } + + return MUNIT_OK; +} #endif diff --git a/src/util-strings.h b/src/util-strings.h index fb54236..df85235 100644 --- a/src/util-strings.h +++ b/src/util-strings.h @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,13 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char **, strv_free); char * strreplace(const char *string, const char *separator, const char *replacement); +/** + * Creates a list of strings representing the buffer similar to hexdump, i.e. + * a buffer of [0, 1, 2, 3, ...] with a stride of 4 is split into + * the strv of ["00 01 02 03", "04 05 06 07", ...]. + */ +char **strv_from_mem(const uint8_t *buffer, size_t sz, size_t stride); + struct key_value_str{ char *key; char *value;