diff --git a/src/libudev/libudev-util.c b/src/libudev/libudev-util.c index bbb2879764..45977339ac 100644 --- a/src/libudev/libudev-util.c +++ b/src/libudev/libudev-util.c @@ -109,51 +109,6 @@ size_t util_path_encode(const char *src, char *dest, size_t size) { return j; } -/* - * Copy from 'str' to 'to', while removing all leading and trailing whitespace, - * and replacing each run of consecutive whitespace with a single underscore. - * The chars from 'str' are copied up to the \0 at the end of the string, or - * at most 'len' chars. This appends \0 to 'to', at the end of the copied - * characters. - * - * If 'len' chars are copied into 'to', the final \0 is placed at len+1 - * (i.e. 'to[len] = \0'), so the 'to' buffer must have at least len+1 - * chars available. - * - * Note this may be called with 'str' == 'to', i.e. to replace whitespace - * in-place in a buffer. This function can handle that situation. - * - * Note that only 'len' characters are read from 'str'. - */ -size_t util_replace_whitespace(const char *str, char *to, size_t len) { - bool is_space = false; - size_t i, j; - - assert(str); - assert(to); - - i = strspn(str, WHITESPACE); - - for (j = 0; j < len && i < len && str[i] != '\0'; i++) { - if (isspace(str[i])) { - is_space = true; - continue; - } - - if (is_space) { - if (j + 1 >= len) - break; - - to[j++] = '_'; - is_space = false; - } - to[j++] = str[i]; - } - - to[j] = '\0'; - return j; -} - /* allow chars in allow list, plain ascii, hex-escaping and valid utf8 */ size_t util_replace_chars(char *str, const char *allow) { size_t i = 0, replaced = 0; diff --git a/src/libudev/libudev-util.h b/src/libudev/libudev-util.h index 15e6214b0d..d2b22f9974 100644 --- a/src/libudev/libudev-util.h +++ b/src/libudev/libudev-util.h @@ -11,7 +11,6 @@ #define UTIL_LINE_SIZE 16384 #define UDEV_ALLOWED_CHARS_INPUT "/ $%?," size_t util_path_encode(const char *src, char *dest, size_t size); -size_t util_replace_whitespace(const char *str, char *to, size_t len); size_t util_replace_chars(char *str, const char *white); int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, bool read_value); diff --git a/src/shared/udev-util.c b/src/shared/udev-util.c index 411b1f704b..17b9ed137b 100644 --- a/src/shared/udev-util.c +++ b/src/shared/udev-util.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: LGPL-2.1-or-later */ +#include #include #include @@ -383,3 +384,45 @@ int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos) { *ret_endpos = i + 1; return 0; } + +size_t udev_replace_whitespace(const char *str, char *to, size_t len) { + bool is_space = false; + size_t i, j; + + assert(str); + assert(to); + + /* Copy from 'str' to 'to', while removing all leading and trailing whitespace, and replacing + * each run of consecutive whitespace with a single underscore. The chars from 'str' are copied + * up to the \0 at the end of the string, or at most 'len' chars. This appends \0 to 'to', at + * the end of the copied characters. + * + * If 'len' chars are copied into 'to', the final \0 is placed at len+1 (i.e. 'to[len] = \0'), + * so the 'to' buffer must have at least len+1 chars available. + * + * Note this may be called with 'str' == 'to', i.e. to replace whitespace in-place in a buffer. + * This function can handle that situation. + * + * Note that only 'len' characters are read from 'str'. */ + + i = strspn(str, WHITESPACE); + + for (j = 0; j < len && i < len && str[i] != '\0'; i++) { + if (isspace(str[i])) { + is_space = true; + continue; + } + + if (is_space) { + if (j + 1 >= len) + break; + + to[j++] = '_'; + is_space = false; + } + to[j++] = str[i]; + } + + to[j] = '\0'; + return j; +} diff --git a/src/shared/udev-util.h b/src/shared/udev-util.h index 4e512cf754..d0ebbede41 100644 --- a/src/shared/udev-util.h +++ b/src/shared/udev-util.h @@ -36,3 +36,4 @@ bool device_for_action(sd_device *dev, DeviceAction action); void log_device_uevent(sd_device *device, const char *str); int udev_rule_parse_value(char *str, char **ret_value, char **ret_endpos); +size_t udev_replace_whitespace(const char *str, char *to, size_t len); diff --git a/src/test/test-libudev.c b/src/test/test-libudev.c index d162abaea0..6f72abc007 100644 --- a/src/test/test-libudev.c +++ b/src/test/test-libudev.c @@ -345,60 +345,6 @@ static void test_hwdb(struct udev *udev, const char *modalias) { assert_se(hwdb == NULL); } -static void test_util_replace_whitespace_one_len(const char *str, size_t len, const char *expected) { - _cleanup_free_ char *result = NULL; - int r; - - result = new(char, len + 1); - assert_se(result); - r = util_replace_whitespace(str, result, len); - assert_se((size_t) r == strlen(expected)); - assert_se(streq(result, expected)); -} - -static void test_util_replace_whitespace_one(const char *str, const char *expected) { - test_util_replace_whitespace_one_len(str, strlen(str), expected); -} - -static void test_util_replace_whitespace(void) { - log_info("/* %s */", __func__); - - test_util_replace_whitespace_one("hogehoge", "hogehoge"); - test_util_replace_whitespace_one("hoge hoge", "hoge_hoge"); - test_util_replace_whitespace_one(" hoge hoge ", "hoge_hoge"); - test_util_replace_whitespace_one(" ", ""); - test_util_replace_whitespace_one("hoge ", "hoge"); - - test_util_replace_whitespace_one_len("hoge hoge ", 9, "hoge_hoge"); - test_util_replace_whitespace_one_len("hoge hoge ", 8, "hoge_hog"); - test_util_replace_whitespace_one_len("hoge hoge ", 7, "hoge_ho"); - test_util_replace_whitespace_one_len("hoge hoge ", 6, "hoge_h"); - test_util_replace_whitespace_one_len("hoge hoge ", 5, "hoge"); - test_util_replace_whitespace_one_len("hoge hoge ", 4, "hoge"); - test_util_replace_whitespace_one_len("hoge hoge ", 3, "hog"); - test_util_replace_whitespace_one_len("hoge hoge ", 2, "ho"); - test_util_replace_whitespace_one_len("hoge hoge ", 1, "h"); - test_util_replace_whitespace_one_len("hoge hoge ", 0, ""); - - test_util_replace_whitespace_one_len(" hoge hoge ", 16, "hoge_hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 15, "hoge_hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 14, "hoge_hog"); - test_util_replace_whitespace_one_len(" hoge hoge ", 13, "hoge_ho"); - test_util_replace_whitespace_one_len(" hoge hoge ", 12, "hoge_h"); - test_util_replace_whitespace_one_len(" hoge hoge ", 11, "hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 10, "hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 9, "hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 8, "hoge"); - test_util_replace_whitespace_one_len(" hoge hoge ", 7, "hog"); - test_util_replace_whitespace_one_len(" hoge hoge ", 6, "ho"); - test_util_replace_whitespace_one_len(" hoge hoge ", 5, "h"); - test_util_replace_whitespace_one_len(" hoge hoge ", 4, ""); - test_util_replace_whitespace_one_len(" hoge hoge ", 3, ""); - test_util_replace_whitespace_one_len(" hoge hoge ", 2, ""); - test_util_replace_whitespace_one_len(" hoge hoge ", 1, ""); - test_util_replace_whitespace_one_len(" hoge hoge ", 0, ""); -} - static void test_util_resolve_subsys_kernel_one(const char *str, bool read_value, int retval, const char *expected) { char result[UTIL_PATH_SIZE] = ""; int r; @@ -573,7 +519,6 @@ static int run(int argc, char *argv[]) { if (arg_monitor) test_monitor(udev); - test_util_replace_whitespace(); test_util_resolve_subsys_kernel(); test_list(); diff --git a/src/test/test-udev-util.c b/src/test/test-udev-util.c index b0213f8c39..50d31f44e0 100644 --- a/src/test/test-udev-util.c +++ b/src/test/test-udev-util.c @@ -181,6 +181,60 @@ static void test_parse_value_unicode(void) { ); } +static void test_udev_replace_whitespace_one_len(const char *str, size_t len, const char *expected) { + _cleanup_free_ char *result = NULL; + int r; + + result = new(char, len + 1); + assert_se(result); + r = udev_replace_whitespace(str, result, len); + assert_se((size_t) r == strlen(expected)); + assert_se(streq(result, expected)); +} + +static void test_udev_replace_whitespace_one(const char *str, const char *expected) { + test_udev_replace_whitespace_one_len(str, strlen(str), expected); +} + +static void test_udev_replace_whitespace(void) { + log_info("/* %s */", __func__); + + test_udev_replace_whitespace_one("hogehoge", "hogehoge"); + test_udev_replace_whitespace_one("hoge hoge", "hoge_hoge"); + test_udev_replace_whitespace_one(" hoge hoge ", "hoge_hoge"); + test_udev_replace_whitespace_one(" ", ""); + test_udev_replace_whitespace_one("hoge ", "hoge"); + + test_udev_replace_whitespace_one_len("hoge hoge ", 9, "hoge_hoge"); + test_udev_replace_whitespace_one_len("hoge hoge ", 8, "hoge_hog"); + test_udev_replace_whitespace_one_len("hoge hoge ", 7, "hoge_ho"); + test_udev_replace_whitespace_one_len("hoge hoge ", 6, "hoge_h"); + test_udev_replace_whitespace_one_len("hoge hoge ", 5, "hoge"); + test_udev_replace_whitespace_one_len("hoge hoge ", 4, "hoge"); + test_udev_replace_whitespace_one_len("hoge hoge ", 3, "hog"); + test_udev_replace_whitespace_one_len("hoge hoge ", 2, "ho"); + test_udev_replace_whitespace_one_len("hoge hoge ", 1, "h"); + test_udev_replace_whitespace_one_len("hoge hoge ", 0, ""); + + test_udev_replace_whitespace_one_len(" hoge hoge ", 16, "hoge_hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 15, "hoge_hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 14, "hoge_hog"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 13, "hoge_ho"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 12, "hoge_h"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 11, "hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 10, "hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 9, "hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 8, "hoge"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 7, "hog"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 6, "ho"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 5, "h"); + test_udev_replace_whitespace_one_len(" hoge hoge ", 4, ""); + test_udev_replace_whitespace_one_len(" hoge hoge ", 3, ""); + test_udev_replace_whitespace_one_len(" hoge hoge ", 2, ""); + test_udev_replace_whitespace_one_len(" hoge hoge ", 1, ""); + test_udev_replace_whitespace_one_len(" hoge hoge ", 0, ""); +} + int main(int argc, char **argv) { test_parse_value(); test_parse_value_with_backslashes(); @@ -198,5 +252,7 @@ int main(int argc, char **argv) { test_parse_value_invalid_termination(); test_parse_value_unicode(); + test_udev_replace_whitespace(); + return EXIT_SUCCESS; } diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c index ce0bf5d24b..434b8765aa 100644 --- a/src/udev/ata_id/ata_id.c +++ b/src/udev/ata_id/ata_id.c @@ -484,11 +484,11 @@ int main(int argc, char *argv[]) { memcpy(model, id.model, 40); model[40] = '\0'; udev_util_encode_string(model, model_enc, sizeof(model_enc)); - util_replace_whitespace((char *) id.model, model, 40); + udev_replace_whitespace((char *) id.model, model, 40); util_replace_chars(model, NULL); - util_replace_whitespace((char *) id.serial_no, serial, 20); + udev_replace_whitespace((char *) id.serial_no, serial, 20); util_replace_chars(serial, NULL); - util_replace_whitespace((char *) id.fw_rev, revision, 8); + udev_replace_whitespace((char *) id.fw_rev, revision, 8); util_replace_chars(revision, NULL); if (export) { diff --git a/src/udev/scsi_id/scsi_id.c b/src/udev/scsi_id/scsi_id.c index 57202564da..162bd4e7df 100644 --- a/src/udev/scsi_id/scsi_id.c +++ b/src/udev/scsi_id/scsi_id.c @@ -456,12 +456,12 @@ static int set_inq_values(struct scsi_id_device *dev_scsi, const char *path) { udev_util_encode_string(dev_scsi->vendor, vendor_enc_str, sizeof(vendor_enc_str)); udev_util_encode_string(dev_scsi->model, model_enc_str, sizeof(model_enc_str)); - util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str)-1); + udev_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); - util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str)-1); + udev_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); set_type(dev_scsi->type, type_str, sizeof(type_str)); - util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str)-1); + udev_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); return 0; } @@ -502,10 +502,10 @@ static int scsi_id(char *maj_min_dev) { printf("ID_REVISION=%s\n", revision_str); printf("ID_TYPE=%s\n", type_str); if (dev_scsi.serial[0] != '\0') { - util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); + udev_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); printf("ID_SERIAL=%s\n", serial_str); - util_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)-1); + udev_replace_whitespace(dev_scsi.serial_short, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); printf("ID_SERIAL_SHORT=%s\n", serial_str); } @@ -532,7 +532,7 @@ static int scsi_id(char *maj_min_dev) { if (reformat_serial) { char serial_str[MAX_SERIAL_LEN]; - util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); + udev_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); printf("%s\n", serial_str); goto out; diff --git a/src/udev/udev-builtin-usb_id.c b/src/udev/udev-builtin-usb_id.c index fa554e740f..aa501a894e 100644 --- a/src/udev/udev-builtin-usb_id.c +++ b/src/udev/udev-builtin-usb_id.c @@ -21,6 +21,7 @@ #include "string-util.h" #include "strxcpyx.h" #include "udev-builtin.h" +#include "udev-util.h" static void set_usb_iftype(char *to, int if_class_num, size_t len) { const char *type = "generic"; @@ -329,7 +330,7 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) { goto fallback; } udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc)); - util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); + udev_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); r = sd_device_get_sysattr_value(dev_scsi, "model", &scsi_model); @@ -338,7 +339,7 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) { goto fallback; } udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc)); - util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); + udev_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); r = sd_device_get_sysattr_value(dev_scsi, "type", &scsi_type); @@ -353,7 +354,7 @@ static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) { log_device_debug_errno(dev_scsi, r, "Failed to get SCSI revision attribute: %m"); goto fallback; } - util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); + udev_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); /* @@ -379,7 +380,7 @@ fallback: if (sd_device_get_sysattr_value(dev_usb, "manufacturer", &usb_vendor) < 0) usb_vendor = vendor_id; udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc)); - util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); + udev_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1); util_replace_chars(vendor_str, NULL); } @@ -389,7 +390,7 @@ fallback: if (sd_device_get_sysattr_value(dev_usb, "product", &usb_model) < 0) usb_model = product_id; udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc)); - util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); + udev_replace_whitespace(usb_model, model_str, sizeof(model_str)-1); util_replace_chars(model_str, NULL); } @@ -397,7 +398,7 @@ fallback: const char *usb_rev; if (sd_device_get_sysattr_value(dev_usb, "bcdDevice", &usb_rev) >= 0) { - util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); + udev_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); } } @@ -416,7 +417,7 @@ fallback: } if (usb_serial) { - util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); + udev_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1); util_replace_chars(serial_str, NULL); } } diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 307f949fde..bc12e4df79 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -478,9 +478,9 @@ size_t udev_event_apply_format(UdevEvent *event, /* FORMAT_SUBST_RESULT handles spaces itself */ if (replace_whitespace && type != FORMAT_SUBST_RESULT) - /* util_replace_whitespace can replace in-place, + /* udev_replace_whitespace can replace in-place, * and does nothing if subst_len == 0 */ - subst_len = util_replace_whitespace(dest, dest, subst_len); + subst_len = udev_replace_whitespace(dest, dest, subst_len); dest += subst_len; size -= subst_len;