summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--udev_utils.c84
-rw-r--r--udev_utils.h29
-rw-r--r--udev_utils_string.c243
4 files changed, 262 insertions, 95 deletions
diff --git a/Makefile b/Makefile
index 1c1280a7dc..8f99330967 100644
--- a/Makefile
+++ b/Makefile
@@ -147,6 +147,7 @@ UDEV_OBJS = \
udev_rules.o \
udev_rules_parse.o \
udev_utils.o \
+ udev_utils_string.o \
udev_utils_file.o \
udev_utils_run.o \
udev_libc_wrapper.o
diff --git a/udev_utils.c b/udev_utils.c
index fc1e2e1f7e..c7292d0f04 100644
--- a/udev_utils.c
+++ b/udev_utils.c
@@ -36,69 +36,6 @@
#include "udev_utils.h"
#include "list.h"
-/* compare string with pattern (supports * ? [0-9] [!A-Z]) */
-int strcmp_pattern(const char *p, const char *s)
-{
- if (s[0] == '\0') {
- while (p[0] == '*')
- p++;
- return (p[0] != '\0');
- }
- switch (p[0]) {
- case '[':
- {
- int not = 0;
- p++;
- if (p[0] == '!') {
- not = 1;
- p++;
- }
- while ((p[0] != '\0') && (p[0] != ']')) {
- int match = 0;
- if (p[1] == '-') {
- if ((s[0] >= p[0]) && (s[0] <= p[2]))
- match = 1;
- p += 3;
- } else {
- match = (p[0] == s[0]);
- p++;
- }
- if (match ^ not) {
- while ((p[0] != '\0') && (p[0] != ']'))
- p++;
- if (p[0] == ']')
- return strcmp_pattern(p+1, s+1);
- }
- }
- }
- break;
- case '*':
- if (strcmp_pattern(p, s+1))
- return strcmp_pattern(p+1, s);
- return 0;
- case '\0':
- if (s[0] == '\0') {
- return 0;
- }
- break;
- default:
- if ((p[0] == s[0]) || (p[0] == '?'))
- return strcmp_pattern(p+1, s+1);
- break;
- }
- return 1;
-}
-
-int string_is_true(const char *str)
-{
- if (strcasecmp(str, "true") == 0)
- return 1;
- if (strcasecmp(str, "yes") == 0)
- return 1;
- if (strcasecmp(str, "1") == 0)
- return 1;
- return 0;
-}
int log_priority(const char *priority)
{
@@ -143,27 +80,6 @@ int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, u
return 0;
}
-void replace_untrusted_chars(char *string)
-{
- size_t len;
-
- for (len = 0; string[len] != '\0'; len++) {
- if (strchr(";,~\\()\'", string[len])) {
- info("replace '%c' in '%s'", string[len], string);
- string[len] = '_';
- }
- }
-}
-
-void remove_trailing_char(char *path, char c)
-{
- size_t len;
-
- len = strlen(path);
- while (len > 0 && path[len-1] == c)
- path[--len] = '\0';
-}
-
int name_list_add(struct list_head *name_list, const char *name, int sort)
{
struct name_entry *loop_name;
diff --git a/udev_utils.h b/udev_utils.h
index 0a307526b7..a07d8d2b7c 100644
--- a/udev_utils.h
+++ b/udev_utils.h
@@ -31,22 +31,29 @@ struct name_entry {
char name[PATH_SIZE];
};
-extern int strcmp_pattern(const char *p, const char *s);
-extern int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel);
-extern int create_path(const char *path);
+/* udev_utils.c */
extern int log_priority(const char *priority);
-extern int string_is_true(const char *str);
-extern int parse_get_pair(char **orig_string, char **left, char **right);
-extern int unlink_secure(const char *filename);
-extern int file_map(const char *filename, char **buf, size_t *bufsize);
-extern void file_unmap(void *buf, size_t bufsize);
-extern size_t buf_get_line(const char *buf, size_t buflen, size_t cur);
-extern void remove_trailing_char(char *path, char c);
-extern void replace_untrusted_chars(char *string);
+extern int kernel_release_satisfactory(unsigned int version, unsigned int patchlevel, unsigned int sublevel);
extern int name_list_add(struct list_head *name_list, const char *name, int sort);
extern int name_list_key_add(struct list_head *name_list, const char *key, const char *value);
extern void name_list_cleanup(struct list_head *name_list);
extern int add_matching_files(struct list_head *name_list, const char *dirname, const char *suffix);
+
+/* udev_utils_string.c */
+extern int strcmp_pattern(const char *p, const char *s);
+extern int string_is_true(const char *str);
+extern void replace_untrusted_chars(char *string);
+extern void remove_trailing_char(char *path, char c);
+extern int utf8_encoded_valid_unichar(const char *str);
+
+/* udev_utils_file.c */
+extern int create_path(const char *path);
+extern int file_map(const char *filename, char **buf, size_t *bufsize);
+extern void file_unmap(void *buf, size_t bufsize);
+extern int unlink_secure(const char *filename);
+extern size_t buf_get_line(const char *buf, size_t buflen, size_t cur);
+
+/* udev_utils_run.c */
extern int pass_env_to_socket(const char *name, const char *devpath, const char *action);
extern int run_program(const char *command, const char *subsystem,
char *result, size_t ressize, size_t *reslen, int log);
diff --git a/udev_utils_string.c b/udev_utils_string.c
new file mode 100644
index 0000000000..a30181e760
--- /dev/null
+++ b/udev_utils_string.c
@@ -0,0 +1,243 @@
+/*
+ * udev_utils_string.c - string manipulation
+ *
+ * Copyright (C) 2004-2005 Kay Sievers <kay.sievers@vrfy.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <syslog.h>
+#include <sys/utsname.h>
+
+#include "udev_libc_wrapper.h"
+#include "udev.h"
+#include "logging.h"
+#include "udev_utils.h"
+#include "list.h"
+
+/* compare string with pattern (like fnmatch(), supports * ? [0-9] [!A-Z]) */
+int strcmp_pattern(const char *p, const char *s)
+{
+ if (s[0] == '\0') {
+ while (p[0] == '*')
+ p++;
+ return (p[0] != '\0');
+ }
+ switch (p[0]) {
+ case '[':
+ {
+ int not = 0;
+ p++;
+ if (p[0] == '!') {
+ not = 1;
+ p++;
+ }
+ while ((p[0] != '\0') && (p[0] != ']')) {
+ int match = 0;
+ if (p[1] == '-') {
+ if ((s[0] >= p[0]) && (s[0] <= p[2]))
+ match = 1;
+ p += 3;
+ } else {
+ match = (p[0] == s[0]);
+ p++;
+ }
+ if (match ^ not) {
+ while ((p[0] != '\0') && (p[0] != ']'))
+ p++;
+ if (p[0] == ']')
+ return strcmp_pattern(p+1, s+1);
+ }
+ }
+ }
+ break;
+ case '*':
+ if (strcmp_pattern(p, s+1))
+ return strcmp_pattern(p+1, s);
+ return 0;
+ case '\0':
+ if (s[0] == '\0') {
+ return 0;
+ }
+ break;
+ default:
+ if ((p[0] == s[0]) || (p[0] == '?'))
+ return strcmp_pattern(p+1, s+1);
+ break;
+ }
+ return 1;
+}
+
+int string_is_true(const char *str)
+{
+ if (strcasecmp(str, "true") == 0)
+ return 1;
+ if (strcasecmp(str, "yes") == 0)
+ return 1;
+ if (strcasecmp(str, "1") == 0)
+ return 1;
+ return 0;
+}
+
+void remove_trailing_char(char *path, char c)
+{
+ size_t len;
+
+ len = strlen(path);
+ while (len > 0 && path[len-1] == c)
+ path[--len] = '\0';
+}
+
+/* count of characters used to encode one unicode char */
+static int utf8_encoded_expected_len(const char *str)
+{
+ unsigned char c = (unsigned char)str[0];
+
+ if (c < 0x80)
+ return 1;
+ if ((c & 0xe0) == 0xc0)
+ return 2;
+ if ((c & 0xf0) == 0xe0)
+ return 3;
+ if ((c & 0xf8) == 0xf0)
+ return 4;
+ if ((c & 0xfc) == 0xf8)
+ return 5;
+ if ((c & 0xfe) == 0xfc)
+ return 6;
+ return 0;
+}
+
+/* decode one unicode char */
+static int utf8_encoded_to_unichar(const char *str)
+{
+ int unichar;
+ int len;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ switch (len) {
+ case 1:
+ return (int)str[0];
+ case 2:
+ unichar = str[0] & 0x1f;
+ break;
+ case 3:
+ unichar = (int)str[0] & 0x0f;
+ break;
+ case 4:
+ unichar = (int)str[0] & 0x07;
+ break;
+ case 5:
+ unichar = (int)str[0] & 0x03;
+ break;
+ case 6:
+ unichar = (int)str[0] & 0x01;
+ break;
+ default:
+ return -1;
+ }
+
+ for (i = 1; i < len; i++) {
+ if (((int)str[i] & 0xc0) != 0x80)
+ return -1;
+ unichar <<= 6;
+ unichar |= (int)str[i] & 0x3f;
+ }
+
+ return unichar;
+}
+
+/* expected size used to encode one unicode char */
+static int utf8_unichar_to_encoded_len(int unichar)
+{
+ if (unichar < 0x80)
+ return 1;
+ if (unichar < 0x800)
+ return 2;
+ if (unichar < 0x10000)
+ return 3;
+ if (unichar < 0x200000)
+ return 4;
+ if (unichar < 0x4000000)
+ return 5;
+ return 6;
+}
+
+/* check if unicode char has a valid numeric range */
+static int utf8_unichar_valid_range(int unichar)
+{
+ if (unichar > 0x10ffff)
+ return 0;
+ if ((unichar & 0xfffff800) == 0xd800)
+ return 0;
+ if ((unichar > 0xfdcf) && (unichar < 0xfdf0))
+ return 0;
+ if ((unichar & 0xffff) == 0xffff)
+ return 0;
+ return 1;
+}
+
+/* validate one encoded unicode char and return its length */
+int utf8_encoded_valid_unichar(const char *str)
+{
+ int len;
+ int unichar;
+ int i;
+
+ len = utf8_encoded_expected_len(str);
+ if (len == 0)
+ return -1;
+
+ /* ascii is valid */
+ if (len == 1)
+ return 1;
+
+ /* check if expected encoded chars are available */
+ for (i = 0; i < len; i++)
+ if ((str[i] & 0x80) != 0x80)
+ return -1;
+
+ unichar = utf8_encoded_to_unichar(str);
+
+ /* check if encoded length matches encoded value */
+ if (utf8_unichar_to_encoded_len(unichar) != len)
+ return -1;
+
+ /* check if value has valid range */
+ if (!utf8_unichar_valid_range(unichar))
+ return -1;
+
+ return len;
+}
+
+void replace_untrusted_chars(char *string)
+{
+ size_t len;
+
+ for (len = 0; string[len] != '\0'; len++) {
+ if (strchr(";,~\\()\'", string[len]))
+ string[len] = '_';
+ }
+}