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;
#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);
/* SPDX-License-Identifier: LGPL-2.1-or-later */
+#include <ctype.h>
#include <errno.h>
#include <unistd.h>
*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;
+}
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);
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;
if (arg_monitor)
test_monitor(udev);
- test_util_replace_whitespace();
test_util_resolve_subsys_kernel();
test_list();
);
}
+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();
test_parse_value_invalid_termination();
test_parse_value_unicode();
+ test_udev_replace_whitespace();
+
return EXIT_SUCCESS;
}
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) {
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;
}
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);
}
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;
#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";
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);
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);
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);
/*
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);
}
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);
}
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);
}
}
}
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);
}
}
/* 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;