chiark / gitweb /
unify string replacement
authorKay Sievers <kay.sievers@vrfy.org>
Wed, 5 Nov 2008 20:49:52 +0000 (21:49 +0100)
committerKay Sievers <kay.sievers@vrfy.org>
Wed, 5 Nov 2008 20:49:52 +0000 (21:49 +0100)
extras/ata_id/ata_id.c
extras/scsi_id/scsi_id.c
extras/usb_id/usb_id.c
extras/volume_id/vol_id.c
udev/lib/libudev-private.h
udev/lib/libudev-util.c
udev/udev-event.c
udev/udev-rules.c
udev/udev.h

index a4f73b8..d407b0f 100644 (file)
@@ -44,38 +44,6 @@ static void log_fn(struct udev *udev, int priority,
        vsyslog(priority, format, args);
 }
 
-static void set_str(char *to, const char *from, size_t count)
-{
-       size_t i, j, len;
-
-       /* strip trailing whitespace */
-       len = strnlen(from, count);
-       while (len && isspace(from[len-1]))
-               len--;
-
-       /* strip leading whitespace */
-       i = 0;
-       while (isspace(from[i]) && (i < len))
-               i++;
-
-       j = 0;
-       while (i < len) {
-               /* substitute multiple whitespace */
-               if (isspace(from[i])) {
-                       while (isspace(from[i]))
-                               i++;
-                       to[j++] = '_';
-               }
-               /* skip chars */
-               if (from[i] == '/') {
-                       i++;
-                       continue;
-               }
-               to[j++] = from[i++];
-       }
-       to[j] = '\0';
-}
-
 int main(int argc, char *argv[])
 {
        struct udev *udev;
@@ -146,9 +114,9 @@ int main(int argc, char *argv[])
                goto close;
        }
 
-       set_str(model, (char *) id.model, 40);
-       set_str(serial, (char *) id.serial_no, 20);
-       set_str(revision, (char *) id.fw_rev, 8);
+       udev_util_replace_whitespace((char *) id.model, model, 40);
+       udev_util_replace_whitespace((char *) id.serial_no, serial, 20);
+       udev_util_replace_whitespace((char *) id.fw_rev, revision, 8);
 
        if (export) {
                if ((id.config >> 8) & 0x80) {
index 45e4860..69994dd 100644 (file)
@@ -69,39 +69,7 @@ static void log_fn(struct udev *udev, int priority,
        vsyslog(priority, format, args);
 }
 
-static void set_str(char *to, const char *from, size_t count)
-{
-       size_t i, j, len;
-
-       /* strip trailing whitespace */
-       len = strnlen(from, count);
-       while (len && isspace(from[len-1]))
-               len--;
-
-       /* strip leading whitespace */
-       i = 0;
-       while (isspace(from[i]) && (i < len))
-               i++;
-
-       j = 0;
-       while (i < len) {
-               /* substitute multiple whitespace */
-               if (isspace(from[i])) {
-                       while (isspace(from[i]))
-                               i++;
-                       to[j++] = '_';
-               }
-               /* skip chars */
-               if (from[i] == '/') {
-                       i++;
-                       continue;
-               }
-               to[j++] = from[i++];
-       }
-       to[j] = '\0';
-}
-
-static void set_type(char *to, const char *from, size_t len)
+static void set_type(const char *from, char *to, size_t len)
 {
        int type_num;
        char *eptr;
@@ -533,11 +501,10 @@ static int set_inq_values(struct udev *udev, struct scsi_id_device *dev_scsi, co
        if (retval)
                return retval;
 
-       set_str(vendor_str, dev_scsi->vendor, sizeof(vendor_str));
-       set_str(model_str, dev_scsi->model, sizeof(model_str));
-       set_type(type_str, dev_scsi->type, sizeof(type_str));
-       set_str(revision_str, dev_scsi->revision, sizeof(revision_str));
-
+       udev_util_replace_whitespace(dev_scsi->vendor, vendor_str, sizeof(vendor_str));
+       udev_util_replace_whitespace(dev_scsi->model, model_str, sizeof(model_str));
+       set_type(dev_scsi->type, type_str, sizeof(type_str));
+       udev_util_replace_whitespace(dev_scsi->revision, revision_str, sizeof(revision_str));
        return 0;
 }
 
@@ -604,9 +571,9 @@ static int scsi_id(struct udev *udev, char *maj_min_dev)
                        printf("ID_VENDOR=%s\n", vendor_str);
                        printf("ID_MODEL=%s\n", model_str);
                        printf("ID_REVISION=%s\n", revision_str);
-                       set_str(serial_str, dev_scsi.serial, sizeof(serial_str));
+                       udev_util_replace_whitespace(dev_scsi.serial, serial_str, sizeof(serial_str));
                        printf("ID_SERIAL=%s\n", serial_str);
-                       set_str(serial_str, serial_short, sizeof(serial_str));
+                       udev_util_replace_whitespace(serial_short, serial_str, sizeof(serial_str));
                        printf("ID_SERIAL_SHORT=%s\n", serial_str);
                        printf("ID_TYPE=%s\n", type_str);
                } else {
index 1499695..6dd1d45 100644 (file)
@@ -46,44 +46,6 @@ static char instance_str[64];
 static int use_usb_info;
 static int use_num_info;
 
-static void set_str(char *to, const char *from, size_t count)
-{
-       size_t i, j, len;
-
-       /* strip trailing whitespace */
-       len = strnlen(from, count);
-       while (len && isspace(from[len-1]))
-               len--;
-
-       /* strip leading whitespace */
-       i = 0;
-       while (isspace(from[i]) && (i < len))
-               i++;
-
-       j = 0;
-       while (i < len) {
-               /* substitute multiple whitespace */
-               if (isspace(from[i])) {
-                       while (isspace(from[i]))
-                               i++;
-                       to[j++] = '_';
-               }
-               /* Replace '/' with '.' */
-               if (from[i] == '/') {
-                       to[j++] = '.';
-                       i++;
-                       continue;
-               }
-               /* skip non-printable chars */
-               if (!isalnum(from[i]) && !ispunct(from[i])) {
-                       i++;
-                       continue;
-               }
-               to[j++] = from[i++];
-       }
-       to[j] = '\0';
-}
-
 static void set_usb_iftype(char *to, int if_class_num, size_t len)
 {
        char *type = "generic";
@@ -274,7 +236,7 @@ static int usb_id(struct udev_device *dev)
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
-               set_str(vendor_str, scsi_vendor, sizeof(vendor_str)-1);
+               udev_util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1);
 
                scsi_model = udev_device_get_sysattr_value(dev_scsi, "model");
                if (!scsi_model) {
@@ -282,7 +244,7 @@ static int usb_id(struct udev_device *dev)
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
-               set_str(model_str, scsi_model, sizeof(model_str)-1);
+               udev_util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1);
 
                scsi_type = udev_device_get_sysattr_value(dev_scsi, "type");
                if (!scsi_type) {
@@ -298,7 +260,7 @@ static int usb_id(struct udev_device *dev)
                             udev_device_get_sysname(dev_scsi));
                        goto fallback;
                }
-               set_str(revision_str, scsi_rev, sizeof(revision_str)-1);
+               udev_util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1);
 
                /*
                 * some broken devices have the same identifiers
@@ -322,7 +284,7 @@ fallback:
                        info(udev, "No USB vendor information available\n");
                        return 1;
                }
-               set_str(vendor_str, usb_vendor, sizeof(vendor_str)-1);
+               udev_util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1);
        }
 
        if (model_str[0] == '\0') {
@@ -338,7 +300,7 @@ fallback:
                        dbg(udev, "No USB model information available\n");
                        return 1;
                }
-               set_str(model_str, usb_model, sizeof(model_str)-1);
+               udev_util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1);
        }
 
        if (revision_str[0] == '\0') {
@@ -346,7 +308,7 @@ fallback:
 
                usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice");
                if (usb_rev)
-                       set_str(revision_str, usb_rev, sizeof(revision_str)-1);
+                       udev_util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1);
        }
 
        if (serial_str[0] == '\0') {
@@ -354,7 +316,7 @@ fallback:
 
                usb_serial = udev_device_get_sysattr_value(dev_usb, "serial");
                if (usb_serial)
-                       set_str(serial_str, usb_serial, sizeof(serial_str)-1);
+                       udev_util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1);
        }
        return 0;
 }
index b4db5ad..df47501 100644 (file)
@@ -66,38 +66,6 @@ static void vid_log(int priority, const char *file, int line, const char *format
        return;
 }
 
-static void set_str(char *to, const char *from, size_t count)
-{
-       size_t i, j, len;
-
-       /* strip trailing whitespace */
-       len = strnlen(from, count);
-       while (len && isspace(from[len-1]))
-               len--;
-
-       /* strip leading whitespace */
-       i = 0;
-       while (isspace(from[i]) && (i < len))
-               i++;
-
-       j = 0;
-       while (i < len) {
-               /* substitute multiple whitespace */
-               if (isspace(from[i])) {
-                       while (isspace(from[i]))
-                               i++;
-                       to[j++] = '_';
-               }
-               /* skip chars */
-               if (from[i] == '/') {
-                       i++;
-                       continue;
-               }
-               to[j++] = from[i++];
-       }
-       to[j] = '\0';
-}
-
 static int all_probers(volume_id_probe_fn_t probe_fn,
                       struct volume_id *id, uint64_t off, uint64_t size,
                       void *data)
@@ -288,12 +256,12 @@ int main(int argc, char *argv[])
                goto exit;
        }
 
-       set_str(label_safe, label, sizeof(label_safe));
-       util_replace_chars(label_safe, ALLOWED_CHARS_INPUT);
+       udev_util_replace_whitespace(label, label_safe, sizeof(label_safe));
+       udev_util_replace_chars(label_safe, UDEV_ALLOWED_CHARS_INPUT);
        volume_id_encode_string(label, label_enc, sizeof(label_enc));
 
-       set_str(uuid_safe, uuid, sizeof(uuid_safe));
-       util_replace_chars(uuid_safe, ALLOWED_CHARS_INPUT);
+       udev_util_replace_whitespace(uuid, uuid_safe, sizeof(uuid_safe));
+       udev_util_replace_chars(uuid_safe, UDEV_ALLOWED_CHARS_INPUT);
        volume_id_encode_string(uuid, uuid_enc, sizeof(uuid_enc));
 
        volume_id_encode_string(type, type_enc, sizeof(type_enc));
index 2f8b825..5e09188 100644 (file)
@@ -159,9 +159,10 @@ extern int udev_queue_export_device_finished(struct udev_queue *udev_queue, stru
 extern int udev_queue_export_device_failed(struct udev_queue *udev_queue, struct udev_device *udev_device);
 
 /* libudev-utils */
-#define UTIL_PATH_SIZE         1024
-#define UTIL_LINE_SIZE         2048
-#define UTIL_NAME_SIZE         512
+#define UTIL_PATH_SIZE                         1024
+#define UTIL_LINE_SIZE                         2048
+#define UTIL_NAME_SIZE                         512
+#define UDEV_ALLOWED_CHARS_INPUT               "/ $%?,"
 extern ssize_t util_get_sys_subsystem(struct udev *udev, const char *syspath, char *subsystem, size_t size);
 extern ssize_t util_get_sys_driver(struct udev *udev, const char *syspath, char *driver, size_t size);
 extern int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size);
@@ -171,5 +172,7 @@ extern size_t util_path_decode(char *s);
 extern void util_remove_trailing_chars(char *path, char c);
 extern size_t util_strlcpy(char *dst, const char *src, size_t size);
 extern size_t util_strlcat(char *dst, const char *src, size_t size);
-extern int util_replace_chars(char *str, const char *white);
+extern int udev_util_replace_whitespace(const char *str, char *to, size_t len);
+extern int udev_util_replace_chars(char *str, const char *white);
+extern int udev_util_encode_string(const char *str, char *str_enc, size_t len);
 #endif
index 9353e8e..f4e7885 100644 (file)
@@ -331,8 +331,47 @@ static int utf8_encoded_valid_unichar(const char *str)
        return len;
 }
 
+int udev_util_replace_whitespace(const char *str, char *to, size_t len)
+{
+       size_t i, j;
+
+       /* strip trailing whitespace */
+       len = strnlen(str, len);
+       while (len && isspace(str[len-1]))
+               len--;
+
+       /* strip leading whitespace */
+       i = 0;
+       while (isspace(str[i]) && (i < len))
+               i++;
+
+       j = 0;
+       while (i < len) {
+               /* substitute multiple whitespace with a single '_' */
+               if (isspace(str[i])) {
+                       while (isspace(str[i]))
+                               i++;
+                       to[j++] = '_';
+               }
+               to[j++] = str[i++];
+       }
+       to[j] = '\0';
+       return 0;
+}
+
+static int is_whitelisted(char c, const char *white)
+{
+       if ((c >= '0' && c <= '9') ||
+           (c >= 'A' && c <= 'Z') ||
+           (c >= 'a' && c <= 'z') ||
+           strchr("#+-.:=@_", c) != NULL ||
+           (white != NULL && strchr(white, c) != NULL))
+               return 1;
+       return 0;
+}
+
 /* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
-int util_replace_chars(char *str, const char *white)
+int udev_util_replace_chars(char *str, const char *white)
 {
        size_t i = 0;
        int replaced = 0;
@@ -340,16 +379,7 @@ int util_replace_chars(char *str, const char *white)
        while (str[i] != '\0') {
                int len;
 
-               /* accept whitelist */
-               if (white != NULL && strchr(white, str[i]) != NULL) {
-                       i++;
-                       continue;
-               }
-
-               /* accept plain ascii char */
-               if ((str[i] >= '0' && str[i] <= '9') ||
-                   (str[i] >= 'A' && str[i] <= 'Z') ||
-                   (str[i] >= 'a' && str[i] <= 'z')) {
+               if (is_whitelisted(str[i], white)) {
                        i++;
                        continue;
                }
@@ -380,6 +410,49 @@ int util_replace_chars(char *str, const char *white)
                i++;
                replaced++;
        }
-
        return replaced;
 }
+
+/**
+ * util_encode_string:
+ * @str: input string to be encoded
+ * @str_enc: output string to store the encoded input string
+ * @len: maximum size of the output string, which may be
+ *       four times as long as the input string
+ *
+ * Encode all potentially unsafe characters of a string to the
+ * corresponding hex value prefixed by '\x'.
+ *
+ * Returns: 0 if the entire string was copied, non-zero otherwise.
+ **/
+int udev_util_encode_string(const char *str, char *str_enc, size_t len)
+{
+       size_t i, j;
+
+       if (str == NULL || str_enc == NULL || len == 0)
+               return -1;
+
+       str_enc[0] = '\0';
+       for (i = 0, j = 0; str[i] != '\0'; i++) {
+               int seqlen;
+
+               seqlen = utf8_encoded_valid_unichar(&str[i]);
+               if (seqlen > 1) {
+                       memcpy(&str_enc[j], &str[i], seqlen);
+                       j += seqlen;
+                       i += (seqlen-1);
+               } else if (str[i] == '\\' || !is_whitelisted(str[i], NULL)) {
+                       sprintf(&str_enc[j], "\\x%02x", (unsigned char) str[i]);
+                       j += 4;
+               } else {
+                       str_enc[j] = str[i];
+                       j++;
+               }
+               if (j+3 >= len)
+                       goto err;
+       }
+       str_enc[j] = '\0';
+       return 0;
+err:
+       return -1;
+}
index fe579b4..2d513d7 100644 (file)
@@ -319,7 +319,7 @@ found:
                                size = strlen(value);
                                while (size > 0 && isspace(value[--size]))
                                        value[size] = '\0';
-                               count = util_replace_chars(value, ALLOWED_CHARS_INPUT);
+                               count = udev_util_replace_chars(value, UDEV_ALLOWED_CHARS_INPUT);
                                if (count > 0)
                                        info(event->udev, "%i character(s) replaced\n" , count);
                                util_strlcat(string, value, maxsize);
index e07cd32..876aa76 100644 (file)
@@ -2085,7 +2085,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
 
                                        util_remove_trailing_chars(result, '\n');
                                        if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
-                                               count = util_replace_chars(result, ALLOWED_CHARS_INPUT);
+                                               count = udev_util_replace_chars(result, UDEV_ALLOWED_CHARS_INPUT);
                                                if (count > 0)
                                                        info(event->udev, "%i character(s) replaced\n" , count);
                                        }
@@ -2284,7 +2284,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                util_strlcpy(name_str, name, sizeof(name_str));
                                udev_event_apply_format(event, name_str, sizeof(name_str));
                                if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) {
-                                       count = util_replace_chars(name_str, ALLOWED_CHARS_FILE);
+                                       count = udev_util_replace_chars(name_str, "/");
                                        if (count > 0)
                                                info(event->udev, "%i character(s) replaced\n", count);
                                        free(event->name);
@@ -2316,9 +2316,9 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event
                                util_strlcpy(temp, &rules->buf[cur->key.value_off], sizeof(temp));
                                udev_event_apply_format(event, temp, sizeof(temp));
                                if (esc == ESCAPE_UNSET)
-                                       count = util_replace_chars(temp, ALLOWED_CHARS_FILE " ");
+                                       count = udev_util_replace_chars(temp, "/ ");
                                else if (esc == ESCAPE_REPLACE)
-                                       count = util_replace_chars(temp, ALLOWED_CHARS_FILE);
+                                       count = udev_util_replace_chars(temp, "/");
                                if (count > 0)
                                        info(event->udev, "%i character(s) replaced\n" , count);
                                dbg(event->udev, "rule applied, added symlink(s) '%s'\n", temp);
index 732b131..ea8c8d9 100644 (file)
 #include "lib/libudev.h"
 #include "lib/libudev-private.h"
 
-#define ALLOWED_CHARS                          "#+-.:=@_"
-#define ALLOWED_CHARS_FILE                     ALLOWED_CHARS "/"
-#define ALLOWED_CHARS_INPUT                    ALLOWED_CHARS_FILE " $%?,"
-
 #define DEFAULT_FAKE_PARTITIONS_COUNT          15
 #define UDEV_EVENT_TIMEOUT                     180