From 065db052211d3bf08d9b0f698a79a8798faf11d2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Wed, 20 May 2009 17:57:52 +0200 Subject: [PATCH] use more efficient string copying --- extras/edd_id/edd_id.c | 2 +- extras/fstab_import/fstab_import.c | 4 +- extras/scsi_id/scsi_id.c | 8 +- extras/usb_id/usb_id.c | 28 +- test/udev-test.pl | 9 - udev/lib/libudev-ctrl.c | 2 +- udev/lib/libudev-device-db-write.c | 41 +-- udev/lib/libudev-device.c | 148 ++++----- udev/lib/libudev-enumerate.c | 40 +-- udev/lib/libudev-monitor.c | 25 +- udev/lib/libudev-private.h | 10 +- udev/lib/libudev-queue.c | 57 ++-- udev/lib/libudev-util.c | 142 ++++---- udev/test-udev.c | 3 +- udev/udev-event.c | 504 +++++++++++++++-------------- udev/udev-node.c | 61 ++-- udev/udev-rules.c | 130 +++----- udev/udev-util.c | 27 +- udev/udev-watch.c | 47 ++- udev/udev.h | 2 +- udev/udevadm-info.c | 27 +- udev/udevadm-monitor.c | 2 +- udev/udevadm-test.c | 13 +- udev/udevadm-trigger.c | 7 +- udev/udevd.c | 48 +-- 25 files changed, 635 insertions(+), 752 deletions(-) diff --git a/extras/edd_id/edd_id.c b/extras/edd_id/edd_id.c index 4154387c..9e9667fc 100644 --- a/extras/edd_id/edd_id.c +++ b/extras/edd_id/edd_id.c @@ -157,7 +157,7 @@ int main(int argc, char *argv[]) if (disk_id == sysfs_id) { if (match[0] == '\0') { /* store id */ - util_strlcpy(match, dent->d_name, sizeof(match)); + util_strscpy(match, sizeof(match), dent->d_name); } else { /* error, same signature for another device */ info(udev, "'%s' does not have a unique signature\n", node); diff --git a/extras/fstab_import/fstab_import.c b/extras/fstab_import/fstab_import.c index e793604f..e46ba7ec 100644 --- a/extras/fstab_import/fstab_import.c +++ b/extras/fstab_import/fstab_import.c @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) if (label[0] == '"' || label[0] == '\'') { char *pos; - util_strlcpy(str, &label[1], sizeof(str)); + util_strscpy(str, sizeof(str), &label[1]); pos = strrchr(str, label[0]); if (pos == NULL) continue; @@ -168,7 +168,7 @@ int main(int argc, char *argv[]) if (uuid[0] == '"' || uuid[0] == '\'') { char *pos; - util_strlcpy(str, &uuid[1], sizeof(str)); + util_strscpy(str, sizeof(str), &uuid[1]); pos = strrchr(str, uuid[0]); if (pos == NULL) continue; diff --git a/extras/scsi_id/scsi_id.c b/extras/scsi_id/scsi_id.c index d630cf90..213a267a 100644 --- a/extras/scsi_id/scsi_id.c +++ b/extras/scsi_id/scsi_id.c @@ -105,7 +105,7 @@ static void set_type(const char *from, char *to, size_t len) break; } } - util_strlcpy(to, type, len); + util_strscpy(to, len, type); } /* @@ -354,7 +354,7 @@ static int set_options(struct udev *udev, case 'd': dev_specified = 1; - util_strlcpy(maj_min_dev, optarg, MAX_PATH_LEN); + util_strscpy(maj_min_dev, MAX_PATH_LEN, optarg); break; case 'e': @@ -362,7 +362,7 @@ static int set_options(struct udev *udev, break; case 'f': - util_strlcpy(config_file, optarg, MAX_PATH_LEN); + util_strscpy(config_file, MAX_PATH_LEN, optarg); break; case 'g': @@ -428,7 +428,7 @@ static int set_options(struct udev *udev, } if (optind < argc && !dev_specified) { dev_specified = 1; - util_strlcpy(maj_min_dev, argv[optind], MAX_PATH_LEN); + util_strscpy(maj_min_dev, MAX_PATH_LEN, argv[optind]); } return 0; } diff --git a/extras/usb_id/usb_id.c b/extras/usb_id/usb_id.c index 36477669..4679f94f 100644 --- a/extras/usb_id/usb_id.c +++ b/extras/usb_id/usb_id.c @@ -134,7 +134,7 @@ static int set_usb_mass_storage_ifsubtype(char *to, const char *from, size_t len break; } } - util_strlcpy(to, type, len); + util_strscpy(to, len, type); return type_num; } @@ -166,7 +166,7 @@ static void set_scsi_type(char *to, const char *from, size_t len) break; } } - util_strlcpy(to, type, len); + util_strscpy(to, len, type); } #define USB_DT_DEVICE 0x01 @@ -509,8 +509,7 @@ int main(int argc, char **argv) goto exit; } - util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); - util_strlcat(syspath, devpath, sizeof(syspath)); + util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), devpath, NULL); dev = udev_device_new_from_syspath(udev, syspath); if (dev == NULL) { err(udev, "unable to access '%s'\n", devpath); @@ -520,18 +519,15 @@ int main(int argc, char **argv) retval = usb_id(dev); if (retval == 0) { char serial[256]; - - util_strlcpy(serial, vendor_str, sizeof(serial)); - util_strlcat(serial, "_", sizeof(serial)); - util_strlcat(serial, model_str, sizeof(serial)); - if (serial_str[0] != '\0') { - util_strlcat(serial, "_", sizeof(serial)); - util_strlcat(serial, serial_str, sizeof(serial)); - } - if (instance_str[0] != '\0') { - util_strlcat(serial, "-", sizeof(serial)); - util_strlcat(serial, instance_str, sizeof(serial)); - } + size_t l; + char *s; + + s = serial; + l = util_strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); + if (serial_str[0] != '\0') + l = util_strpcpyl(&s, l, "_", serial_str, NULL); + if (instance_str[0] != '\0') + util_strpcpyl(&s, l, "-", instance_str, NULL); if (export) { printf("ID_VENDOR=%s\n", vendor_str); diff --git a/test/udev-test.pl b/test/udev-test.pl index b5abe620..30e8d2ac 100755 --- a/test/udev-test.pl +++ b/test/udev-test.pl @@ -342,15 +342,6 @@ EOF exp_name => "test-0:0:0:0" , rules => < "program with escaped format char (callout returns format char!)", - subsys => "block", - devpath => "/devices/pci0000:00/0000:00:1f.2/host0/target0:0:0/0:0:0:0/block/sda/sda5", - exp_name => "escape-5" , - rules => <= sizeof(target)) { + l = util_strpcpyl(&s, l, " ", &udev_list_entry_get_name(list_entry)[devlen], NULL); + if (l == 0) { info(udev, "size of links too large, create file\n"); goto file; } @@ -121,25 +118,21 @@ out: int udev_device_delete_db(struct udev_device *udev_device) { + struct udev *udev = udev_device_get_udev(udev_device); char filename[UTIL_PATH_SIZE]; - devpath_to_db_path(udev_device_get_udev(udev_device), - udev_device_get_devpath(udev_device), - filename, sizeof(filename)); + devpath_to_db_path(udev, udev_device_get_devpath(udev_device), filename, sizeof(filename)); unlink(filename); return 0; } int udev_device_rename_db(struct udev_device *udev_device, const char *devpath_old) { + struct udev *udev = udev_device_get_udev(udev_device); char filename_old[UTIL_PATH_SIZE]; char filename[UTIL_PATH_SIZE]; - devpath_to_db_path(udev_device_get_udev(udev_device), - devpath_old, - filename_old, sizeof(filename_old)); - devpath_to_db_path(udev_device_get_udev(udev_device), - udev_device_get_devpath(udev_device), - filename, sizeof(filename)); + devpath_to_db_path(udev, devpath_old, filename_old, sizeof(filename_old)); + devpath_to_db_path(udev, udev_device_get_devpath(udev_device), filename, sizeof(filename)); return rename(filename_old, filename); } diff --git a/udev/lib/libudev-device.c b/udev/lib/libudev-device.c index ddc4b341..37b3a3b7 100644 --- a/udev/lib/libudev-device.c +++ b/udev/lib/libudev-device.c @@ -1,7 +1,7 @@ /* * libudev - interface to udev device information * - * Copyright (C) 2008 Kay Sievers + * Copyright (C) 2008-2009 Kay Sievers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -63,13 +63,12 @@ struct udev_device { static size_t devpath_to_db_path(struct udev *udev, const char *devpath, char *filename, size_t len) { - size_t start; + char *s; + size_t l; - /* translate to location of db file */ - util_strlcpy(filename, udev_get_dev_path(udev), len); - start = util_strlcat(filename, "/.udev/db/", len); - util_strlcat(filename, devpath, len); - return util_path_encode(&filename[start], len - start); + s = filename; + l = util_strpcpyl(&s, len, udev_get_dev_path(udev), "/.udev/db/", NULL); + return util_path_encode(devpath, filename, l); } int udev_device_read_db(struct udev_device *udev_device) @@ -104,9 +103,7 @@ int udev_device_read_db(struct udev_device *udev_device) next[0] = '\0'; next = &next[1]; } - util_strlcpy(devnode, udev_get_dev_path(udev_device->udev), sizeof(devnode)); - util_strlcat(devnode, "/", sizeof(devnode)); - util_strlcat(devnode, target, sizeof(devnode)); + util_strscpyl(devnode, sizeof(devnode), udev_get_dev_path(udev_device->udev), "/", target, NULL); udev_device_set_devnode(udev_device, devnode); while (next != NULL) { char devlink[UTIL_PATH_SIZE]; @@ -118,9 +115,7 @@ int udev_device_read_db(struct udev_device *udev_device) next[0] = '\0'; next = &next[1]; } - util_strlcpy(devlink, udev_get_dev_path(udev_device->udev), sizeof(devlink)); - util_strlcat(devlink, "/", sizeof(devlink)); - util_strlcat(devlink, lnk, sizeof(devlink)); + util_strscpyl(devlink, sizeof(devlink), udev_get_dev_path(udev_device->udev), "/", lnk, NULL); udev_device_add_devlink(udev_device, devlink); } info(udev_device->udev, "device %p filled with db symlink data '%s'\n", udev_device, udev_device->devnode); @@ -143,15 +138,11 @@ int udev_device_read_db(struct udev_device *udev_device) val = &line[2]; switch(line[0]) { case 'N': - util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, val, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL); udev_device_set_devnode(udev_device, filename); break; case 'S': - util_strlcpy(filename, udev_get_dev_path(udev_device->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, val, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_device->udev), "/", val, NULL); udev_device_add_devlink(udev_device, filename); break; case 'L': @@ -188,8 +179,7 @@ int udev_device_read_uevent_file(struct udev_device *udev_device) int maj = 0; int min = 0; - util_strlcpy(filename, udev_device->syspath, sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_device->syspath, "/uevent", NULL); f = fopen(filename, "r"); if (f == NULL) return -1; @@ -303,7 +293,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * } /* resolve possible symlink to real path */ - util_strlcpy(path, syspath, sizeof(path)); + util_strscpy(path, sizeof(path), syspath); util_resolve_sys_link(udev, path, sizeof(path)); /* try to resolve the silly block layout if needed */ @@ -311,16 +301,14 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * char block[UTIL_PATH_SIZE]; char part[UTIL_PATH_SIZE]; - util_strlcpy(block, path, sizeof(block)); + util_strscpy(block, sizeof(block), path); pos = strrchr(block, '/'); if (pos == NULL) return NULL; - util_strlcpy(part, pos, sizeof(part)); + util_strscpy(part, sizeof(part), pos); pos[0] = '\0'; - if (util_resolve_sys_link(udev, block, sizeof(block)) == 0) { - util_strlcpy(path, block, sizeof(path)); - util_strlcat(path, part, sizeof(path)); - } + if (util_resolve_sys_link(udev, block, sizeof(block)) == 0) + util_strscpyl(path, sizeof(path), block, part, NULL); } /* path exists in sys */ @@ -330,8 +318,7 @@ struct udev_device *udev_device_new_from_syspath(struct udev *udev, const char * char file[UTIL_PATH_SIZE]; /* all "devices" require a "uevent" file */ - util_strlcpy(file, path, sizeof(file)); - util_strlcat(file, "/uevent", sizeof(file)); + util_strscpyl(file, sizeof(file), path, "/uevent", NULL); if (stat(file, &statbuf) != 0) { dbg(udev, "not a device: %s\n", syspath); return NULL; @@ -407,35 +394,31 @@ struct udev_device *udev_device_new_from_devnum(struct udev *udev, char type, de struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsystem, const char *sysname) { - size_t sys_path_len; char path_full[UTIL_PATH_SIZE]; char *path; + size_t l; struct stat statbuf; - sys_path_len = util_strlcpy(path_full, udev_get_sys_path(udev), sizeof(path_full)); - path = &path_full[sys_path_len]; + path = path_full; + l = util_strpcpyl(&path, sizeof(path_full), udev_get_sys_path(udev), NULL); if (strcmp(subsystem, "subsystem") == 0) { - util_strlcpy(path, "/subsystem/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/subsystem/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; - util_strlcpy(path, "/bus/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/bus/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; - util_strlcpy(path, "/class/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/class/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; goto out; } if (strcmp(subsystem, "module") == 0) { - util_strlcpy(path, "/module/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/module/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; goto out; @@ -445,46 +428,32 @@ struct udev_device *udev_device_new_from_subsystem_sysname(struct udev *udev, co char subsys[UTIL_NAME_SIZE]; char *driver; - util_strlcpy(subsys, sysname, sizeof(subsys)); + util_strscpy(subsys, sizeof(subsys), sysname); driver = strchr(subsys, ':'); if (driver != NULL) { driver[0] = '\0'; driver = &driver[1]; - util_strlcpy(path, "/subsystem/", sizeof(path_full) - sys_path_len); - util_strlcat(path, subsys, sizeof(path_full) - sys_path_len); - util_strlcat(path, "/drivers/", sizeof(path_full) - sys_path_len); - util_strlcat(path, driver, sizeof(path_full) - sys_path_len); + + util_strscpyl(path, l, "/subsystem/", subsys, "/drivers/", driver, NULL); if (stat(path_full, &statbuf) == 0) goto found; - util_strlcpy(path, "/bus/", sizeof(path_full) - sys_path_len); - util_strlcat(path, subsys, sizeof(path_full) - sys_path_len); - util_strlcat(path, "/drivers/", sizeof(path_full) - sys_path_len); - util_strlcat(path, driver, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/bus/", subsys, "/drivers/", driver, NULL); if (stat(path_full, &statbuf) == 0) goto found; } goto out; } - util_strlcpy(path, "/subsystem/", sizeof(path_full) - sys_path_len); - util_strlcat(path, subsystem, sizeof(path_full) - sys_path_len); - util_strlcat(path, "/devices/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/subsystem/", subsystem, "/devices/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; - util_strlcpy(path, "/bus/", sizeof(path_full) - sys_path_len); - util_strlcat(path, subsystem, sizeof(path_full) - sys_path_len); - util_strlcat(path, "/devices/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/bus/", subsystem, "/devices/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; - util_strlcpy(path, "/class/", sizeof(path_full) - sys_path_len); - util_strlcat(path, subsystem, sizeof(path_full) - sys_path_len); - util_strlcat(path, "/", sizeof(path_full) - sys_path_len); - util_strlcat(path, sysname, sizeof(path_full) - sys_path_len); + util_strscpyl(path, l, "/class/", subsystem, "/", sysname, NULL); if (stat(path_full, &statbuf) == 0) goto found; out: @@ -502,8 +471,7 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic /* follow "device" link in deprecated sys layout */ if (strncmp(udev_device->devpath, "/class/", 7) == 0 || strncmp(udev_device->devpath, "/block/", 7) == 0) { - util_strlcpy(path, udev_device->syspath, sizeof(path)); - util_strlcat(path, "/device", sizeof(path)); + util_strscpyl(path, sizeof(path), udev_device->syspath, "/device", NULL); if (util_resolve_sys_link(udev_device->udev, path, sizeof(path)) == 0) { udev_device_parent = udev_device_new_from_syspath(udev_device->udev, path); if (udev_device_parent != NULL) @@ -511,7 +479,7 @@ static struct udev_device *device_new_from_parent(struct udev_device *udev_devic } } - util_strlcpy(path, udev_device->syspath, sizeof(path)); + util_strscpy(path, sizeof(path), udev_device->syspath); subdir = &path[strlen(udev_get_sys_path(udev_device->udev))+1]; while (1) { char *pos; @@ -809,11 +777,13 @@ struct udev_list_entry *udev_device_get_properties_list_entry(struct udev_device udev_device->devlinks_uptodate = 1; list_entry = udev_device_get_devlinks_list_entry(udev_device); if (list_entry != NULL) { - util_strlcpy(symlinks, udev_list_entry_get_name(list_entry), sizeof(symlinks)); - udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) { - util_strlcat(symlinks, " ", sizeof(symlinks)); - util_strlcat(symlinks, udev_list_entry_get_name(list_entry), sizeof(symlinks)); - } + char *s; + size_t l; + + s = symlinks; + l = util_strpcpyl(&s, sizeof(symlinks), udev_list_entry_get_name(list_entry), NULL); + udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) + l = util_strpcpyl(&s, l, " ", udev_list_entry_get_name(list_entry), NULL); udev_device_add_property(udev_device, "DEVLINKS", symlinks); } } @@ -881,10 +851,7 @@ const char *udev_device_get_sysattr_value(struct udev_device *udev_device, const } } - util_strlcpy(path, udev_device_get_syspath(udev_device), sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, sysattr, sizeof(path)); - + util_strscpyl(path, sizeof(path), udev_device_get_syspath(udev_device), "/", sysattr, NULL); if (lstat(path, &statbuf) != 0) { dbg(udev_device->udev, "no attribute '%s', keep negative entry\n", path); udev_list_entry_add(udev_device->udev, &udev_device->sysattr_list, sysattr, NULL, 0, 0); @@ -1047,7 +1014,7 @@ struct udev_list_entry *udev_device_add_property_from_string(struct udev_device char name[UTIL_PATH_SIZE]; char *val; - util_strlcpy(name, property, sizeof(name)); + util_strscpy(name, sizeof(name), property); val = strchr(name, '='); if (val == NULL) return NULL; @@ -1077,8 +1044,8 @@ const char *udev_device_get_property_value(struct udev_device *udev_device, cons static int update_envp_monitor_buf(struct udev_device *udev_device) { struct udev_list_entry *list_entry; - size_t bufpos; - size_t len; + char *s; + size_t l; unsigned int i; /* monitor buffer of property strings */ @@ -1095,33 +1062,26 @@ static int update_envp_monitor_buf(struct udev_device *udev_device) return -ENOMEM; i = 0; - bufpos = 0; + s = udev_device->monitor_buf; + l = MONITOR_BUF_SIZE; udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(udev_device)) { /* add string to envp array */ - udev_device->envp[i++] = &udev_device->monitor_buf[bufpos]; + udev_device->envp[i++] = s; if (i+1 >= ENVP_SIZE) return -EINVAL; /* add property string to monitor buffer */ - len = util_strlcpy(&udev_device->monitor_buf[bufpos], - udev_list_entry_get_name(list_entry), MONITOR_BUF_SIZE-bufpos); - if (len >= MONITOR_BUF_SIZE-bufpos) - return -EINVAL; - bufpos += len; - len = util_strlcpy(&udev_device->monitor_buf[bufpos], "=", MONITOR_BUF_SIZE-bufpos); - if (len >= MONITOR_BUF_SIZE-bufpos) - return -EINVAL; - bufpos += len; - len = util_strlcpy(&udev_device->monitor_buf[bufpos], udev_list_entry_get_value(list_entry), - MONITOR_BUF_SIZE-bufpos); - if (len+1 >= MONITOR_BUF_SIZE-bufpos) + l = util_strpcpyl(&s, l, udev_list_entry_get_name(list_entry), "=", + udev_list_entry_get_value(list_entry), NULL); + if (l == 0) return -EINVAL; - bufpos += len+1; + s++; } udev_device->envp[i] = NULL; - udev_device->monitor_buf_len = bufpos; + udev_device->monitor_buf_len = s - udev_device->monitor_buf; udev_device->envp_uptodate = 1; - dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n", i, bufpos); + dbg(udev_device->udev, "filled envp/monitor buffer, %u properties, %zu bytes\n", + i, udev_device->monitor_buf_len); return 0; } diff --git a/udev/lib/libudev-enumerate.c b/udev/lib/libudev-enumerate.c index a92bf0b6..c236a1c1 100644 --- a/udev/lib/libudev-enumerate.c +++ b/udev/lib/libudev-enumerate.c @@ -261,20 +261,17 @@ static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate, { struct udev *udev = udev_enumerate_get_udev(udev_enumerate); char path[UTIL_PATH_SIZE]; + size_t l; + char *s; DIR *dir; struct dirent *dent; - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, basedir, sizeof(path)); - if (subdir1 != NULL) { - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, subdir1, sizeof(path)); - } - if (subdir2 != NULL) { - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, subdir2, sizeof(path)); - } + s = path; + l = util_strpcpyl(&s, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL); + if (subdir1 != NULL) + l = util_strpcpyl(&s, l, "/", subdir1, NULL); + if (subdir2 != NULL) + l = util_strpcpyl(&s, l, "/", subdir2, NULL); dir = opendir(path); if (dir == NULL) return -1; @@ -285,17 +282,15 @@ static int scan_dir_and_add_devices(struct udev_enumerate *udev_enumerate, if (dent->d_name[0] == '.') continue; - util_strlcpy(syspath, path, sizeof(syspath)); - util_strlcat(syspath, "/", sizeof(syspath)); - util_strlcat(syspath, dent->d_name, sizeof(syspath)); + util_strscpyl(syspath, sizeof(syspath), path, "/", dent->d_name, NULL); if (lstat(syspath, &statbuf) != 0) continue; if (S_ISREG(statbuf.st_mode)) continue; if (S_ISLNK(statbuf.st_mode)) util_resolve_sys_link(udev, syspath, sizeof(syspath)); - util_strlcpy(filename, syspath, sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + + util_strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL); if (stat(filename, &statbuf) != 0) continue; if (!match_sysattr(udev_enumerate, syspath)) @@ -334,9 +329,7 @@ static int scan_dir(struct udev_enumerate *udev_enumerate, const char *basedir, DIR *dir; struct dirent *dent; - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, basedir, sizeof(path)); + util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/", basedir, NULL); dir = opendir(path); if (dir == NULL) return -1; @@ -428,8 +421,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) if (udev_enumerate == NULL) return -EINVAL; - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/subsystem", sizeof(base)); + util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL); if (stat(base, &statbuf) == 0) { /* we have /subsystem/, forget all the old stuff */ dbg(udev, "searching '/subsystem/*/devices/*' dir\n"); @@ -440,8 +432,7 @@ int udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) dbg(udev, "searching '/class/*' dir\n"); scan_dir(udev_enumerate, "class", NULL, NULL); /* if block isn't a class, scan /block/ */ - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/class/block", sizeof(base)); + util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/class/block", NULL); if (stat(base, &statbuf) != 0) { if (match_subsystem(udev_enumerate, "block")) { dbg(udev, "searching '/block/*' dir\n"); @@ -471,8 +462,7 @@ int udev_enumerate_scan_subsystems(struct udev_enumerate *udev_enumerate) if (udev_enumerate == NULL) return -EINVAL; - util_strlcpy(base, udev_get_sys_path(udev), sizeof(base)); - util_strlcat(base, "/subsystem", sizeof(base)); + util_strscpyl(base, sizeof(base), udev_get_sys_path(udev), "/subsystem", NULL); if (stat(base, &statbuf) == 0) subsysdir = "subsystem"; else diff --git a/udev/lib/libudev-monitor.c b/udev/lib/libudev-monitor.c index 2540e85c..395a4d27 100644 --- a/udev/lib/libudev-monitor.c +++ b/udev/lib/libudev-monitor.c @@ -1,7 +1,7 @@ /* * libudev - interface to udev device information * - * Copyright (C) 2008 Kay Sievers + * Copyright (C) 2008-2009 Kay Sievers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -113,16 +113,16 @@ struct udev_monitor *udev_monitor_new_from_socket(struct udev *udev, const char udev_monitor->sun.sun_family = AF_LOCAL; if (socket_path[0] == '@') { /* translate leading '@' to abstract namespace */ - util_strlcpy(udev_monitor->sun.sun_path, socket_path, sizeof(udev_monitor->sun.sun_path)); + util_strscpy(udev_monitor->sun.sun_path, sizeof(udev_monitor->sun.sun_path), socket_path); udev_monitor->sun.sun_path[0] = '\0'; udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path); } else if (stat(socket_path, &statbuf) == 0 && S_ISSOCK(statbuf.st_mode)) { /* existing socket file */ - util_strlcpy(udev_monitor->sun.sun_path, socket_path, sizeof(udev_monitor->sun.sun_path)); + util_strscpy(udev_monitor->sun.sun_path, sizeof(udev_monitor->sun.sun_path), socket_path); udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path); } else { /* no socket file, assume abstract namespace socket */ - util_strlcpy(&udev_monitor->sun.sun_path[1], socket_path, sizeof(udev_monitor->sun.sun_path)-1); + util_strscpy(&udev_monitor->sun.sun_path[1], sizeof(udev_monitor->sun.sun_path)-1, socket_path); udev_monitor->addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(socket_path)+1; } udev_monitor->sock = socket(AF_LOCAL, SOCK_DGRAM, 0); @@ -545,8 +545,7 @@ retry: if (strncmp(key, "DEVPATH=", 8) == 0) { char path[UTIL_PATH_SIZE]; - util_strlcpy(path, udev_get_sys_path(udev_monitor->udev), sizeof(path)); - util_strlcat(path, &key[8], sizeof(path)); + util_strscpyl(path, sizeof(path), udev_get_sys_path(udev_monitor->udev), &key[8], NULL); udev_device_set_syspath(udev_device, path); devpath_set = 1; } else if (strncmp(key, "SUBSYSTEM=", 10) == 0) { @@ -564,7 +563,7 @@ retry: char *slink; char *next; - util_strlcpy(devlinks, &key[9], sizeof(devlinks)); + util_strscpy(devlinks, sizeof(devlinks), &key[9]); slink = devlinks; next = strchr(slink, ' '); while (next != NULL) { @@ -637,19 +636,17 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_devi if (udev_monitor->sun.sun_family != 0) { const char *action; char header[2048]; - size_t hlen; + char *s; /* header @ */ action = udev_device_get_action(udev_device); if (action == NULL) return -EINVAL; - util_strlcpy(header, action, sizeof(header)); - util_strlcat(header, "@", sizeof(header)); - hlen = util_strlcat(header, udev_device_get_devpath(udev_device), sizeof(header))+1; - if (hlen >= sizeof(header)) + s = header; + if (util_strpcpyl(&s, sizeof(header), action, "@", udev_device_get_devpath(udev_device), NULL) == 0) return -EINVAL; iov[0].iov_base = header; - iov[0].iov_len = hlen; + iov[0].iov_len = (s - header)+1; /* add properties list */ iov[1].iov_base = (char *)buf; @@ -667,7 +664,7 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor, struct udev_devi /* add versioned header */ memset(&nlh, 0x00, sizeof(struct udev_monitor_netlink_header)); - util_strlcpy(nlh.version, "udev-" VERSION, sizeof(nlh.version)); + util_strscpy(nlh.version, sizeof(nlh.version), "udev-" VERSION); nlh.magic = htonl(UDEV_MONITOR_MAGIC); val = udev_device_get_subsystem(udev_device); nlh.filter_subsystem = htonl(util_string_hash32(val)); diff --git a/udev/lib/libudev-private.h b/udev/lib/libudev-private.h index 7dd8e7df..9ec5e1aa 100644 --- a/udev/lib/libudev-private.h +++ b/udev/lib/libudev-private.h @@ -1,7 +1,7 @@ /* * libudev - interface to udev device information * - * Copyright (C) 2008 Kay Sievers + * Copyright (C) 2008-2009 Kay Sievers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -164,11 +164,13 @@ ssize_t util_get_sys_subsystem(struct udev *udev, const char *syspath, char *sub ssize_t util_get_sys_driver(struct udev *udev, const char *syspath, char *driver, size_t size); int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size); int util_log_priority(const char *priority); -size_t util_path_encode(char *s, size_t len); +size_t util_path_encode(const char *src, char *dest, size_t size); size_t util_path_decode(char *s); void util_remove_trailing_chars(char *path, char c); -size_t util_strlcpy(char *dst, const char *src, size_t size); -size_t util_strlcat(char *dst, const char *src, size_t size); +size_t util_strpcpy(char **dest, size_t size, const char *src); +size_t util_strpcpyl(char **dest, size_t size, const char *src, ...); +size_t util_strscpy(char *dest, size_t size, const char *src); +size_t util_strscpyl(char *dest, size_t size, const char *src, ...); int udev_util_replace_whitespace(const char *str, char *to, size_t len); int udev_util_replace_chars(char *str, const char *white); int udev_util_encode_string(const char *str, char *str_enc, size_t len); diff --git a/udev/lib/libudev-queue.c b/udev/lib/libudev-queue.c index 63229fd8..a2860ec8 100644 --- a/udev/lib/libudev-queue.c +++ b/udev/lib/libudev-queue.c @@ -84,8 +84,7 @@ unsigned long long int udev_queue_get_kernel_seqnum(struct udev_queue *udev_queu if (udev_queue == NULL) return -EINVAL; - util_strlcpy(filename, udev_get_sys_path(udev_queue->udev), sizeof(filename)); - util_strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev_queue->udev), "/kernel/uevent_seqnum", NULL); fd = open(filename, O_RDONLY); if (fd < 0) return 0; @@ -109,8 +108,7 @@ unsigned long long int udev_queue_get_udev_seqnum(struct udev_queue *udev_queue) if (udev_queue == NULL) return -EINVAL; - util_strlcpy(filename, udev_get_dev_path(udev_queue->udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/uevent_seqnum", NULL); fd = open(filename, O_RDONLY); if (fd < 0) return 0; @@ -132,8 +130,7 @@ int udev_queue_get_udev_is_active(struct udev_queue *udev_queue) if (udev_queue == NULL) return 0; - util_strlcpy(filename, udev_get_dev_path(udev_queue->udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev_queue->udev), "/.udev/uevent_seqnum", NULL); if (stat(filename, &statbuf) == 0) return 1; return 0; @@ -147,8 +144,7 @@ int udev_queue_get_queue_is_empty(struct udev_queue *udev_queue) if (udev_queue == NULL) return -EINVAL; - util_strlcpy(queuename, udev_get_dev_path(udev_queue->udev), sizeof(queuename)); - util_strlcat(queuename, "/.udev/queue", sizeof(queuename)); + util_strscpyl(queuename, sizeof(queuename), udev_get_dev_path(udev_queue->udev), "/.udev/queue", NULL); if (stat(queuename, &statbuf) == 0) { dbg(udev_queue->udev, "queue is not empty\n"); return 0; @@ -200,28 +196,26 @@ struct udev_list_entry *udev_queue_get_queued_list_entry(struct udev_queue *udev if (udev_queue == NULL) return NULL; udev_list_cleanup_entries(udev_queue->udev, &udev_queue->queue_list); - util_strlcpy(path, udev_get_dev_path(udev_queue->udev), sizeof(path)); - util_strlcat(path, "/.udev/queue", sizeof(path)); + util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/queue", NULL); dir = opendir(path); if (dir == NULL) return NULL; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char filename[UTIL_PATH_SIZE]; char syspath[UTIL_PATH_SIZE]; - size_t syslen; + char *s; + size_t l; ssize_t len; if (dent->d_name[0] == '.') continue; - util_strlcpy(filename, path, sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, dent->d_name, sizeof(filename)); - - syslen = util_strlcpy(syspath, udev_get_sys_path(udev_queue->udev), sizeof(syspath)); - len = readlink(filename, &syspath[syslen], sizeof(syspath)-syslen); - if (len < 0 || len >= (ssize_t)(sizeof(syspath)-syslen)) + util_strscpyl(filename, sizeof(filename), path, "/", dent->d_name, NULL); + s = syspath; + l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL); + len = readlink(filename, s, l); + if (len < 0 || (size_t)len >= l) continue; - syspath[syslen + len] = '\0'; + s[len] = '\0'; dbg(udev_queue->udev, "found '%s' [%s]\n", syspath, dent->d_name); udev_list_entry_add(udev_queue->udev, &udev_queue->queue_list, syspath, dent->d_name, 0, 0); } @@ -238,32 +232,29 @@ struct udev_list_entry *udev_queue_get_failed_list_entry(struct udev_queue *udev if (udev_queue == NULL) return NULL; udev_list_cleanup_entries(udev_queue->udev, &udev_queue->failed_list); - util_strlcpy(path, udev_get_dev_path(udev_queue->udev), sizeof(path)); - util_strlcat(path, "/.udev/failed", sizeof(path)); + util_strscpyl(path, sizeof(path), udev_get_dev_path(udev_queue->udev), "/.udev/failed", NULL); dir = opendir(path); if (dir == NULL) return NULL; for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { char filename[UTIL_PATH_SIZE]; char syspath[UTIL_PATH_SIZE]; - struct stat statbuf; - size_t syslen; + char *s; + size_t l; ssize_t len; + struct stat statbuf; if (dent->d_name[0] == '.') continue; - util_strlcpy(filename, path, sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, dent->d_name, sizeof(filename)); - - syslen = util_strlcpy(syspath, udev_get_sys_path(udev_queue->udev), sizeof(syspath)); - len = readlink(filename, &syspath[syslen], sizeof(syspath)-syslen); - if (len < 0 || len >= (ssize_t)(sizeof(syspath)-syslen)) + util_strscpyl(filename, sizeof(filename), path, "/", dent->d_name, NULL); + s = syspath; + l = util_strpcpyl(&s, sizeof(syspath), udev_get_sys_path(udev_queue->udev), NULL); + len = readlink(filename, s, l); + if (len < 0 || (size_t)len >= l) continue; - syspath[syslen + len] = '\0'; + s[len] = '\0'; dbg(udev_queue->udev, "found '%s' [%s]\n", syspath, dent->d_name); - util_strlcpy(filename, syspath, sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), syspath, "/uevent", NULL); if (stat(filename, &statbuf) != 0) continue; udev_list_entry_add(udev_queue->udev, &udev_queue->failed_list, syspath, NULL, 0, 0); diff --git a/udev/lib/libudev-util.c b/udev/lib/libudev-util.c index 2b8cda59..24ea0daa 100644 --- a/udev/lib/libudev-util.c +++ b/udev/lib/libudev-util.c @@ -1,7 +1,7 @@ /* * libudev - interface to udev device information * - * Copyright (C) 2008 Kay Sievers + * Copyright (C) 2008-2009 Kay Sievers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,9 +29,7 @@ static ssize_t get_sys_link(struct udev *udev, const char *slink, const char *sy ssize_t len; const char *pos; - util_strlcpy(path, syspath, sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, slink, sizeof(path)); + util_strscpyl(path, sizeof(path), syspath, "/", slink, NULL); len = readlink(path, path, sizeof(path)); if (len < 0 || len >= (ssize_t) sizeof(path)) return -1; @@ -41,7 +39,7 @@ static ssize_t get_sys_link(struct udev *udev, const char *slink, const char *sy return -1; pos = &pos[1]; dbg(udev, "resolved link to: '%s'\n", pos); - return util_strlcpy(value, pos, size); + return util_strscpy(value, size, pos); } ssize_t util_get_sys_subsystem(struct udev *udev, const char *syspath, char *subsystem, size_t size) @@ -61,6 +59,7 @@ int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size) int len; int i; int back; + char *base; len = readlink(syspath, link_target, sizeof(link_target)); if (len <= 0) @@ -72,15 +71,13 @@ int util_resolve_sys_link(struct udev *udev, char *syspath, size_t size) ; dbg(udev, "base '%s', tail '%s', back %i\n", syspath, &link_target[back * 3], back); for (i = 0; i <= back; i++) { - char *pos = strrchr(syspath, '/'); - - if (pos == NULL) + base = strrchr(syspath, '/'); + if (base == NULL) return -1; - pos[0] = '\0'; + base[0] = '\0'; } dbg(udev, "after moving back '%s'\n", syspath); - util_strlcat(syspath, "/", size); - util_strlcat(syspath, &link_target[back * 3], size); + util_strscpyl(base, size - (base - syspath), "/", &link_target[back * 3], NULL); return 0; } @@ -101,29 +98,35 @@ int util_log_priority(const char *priority) return 0; } -size_t util_path_encode(char *s, size_t size) +size_t util_path_encode(const char *src, char *dest, size_t size) { - char t[(size * 4)+1]; size_t i, j; - for (i = 0, j = 0; s[i] != '\0' && i < size; i++) { - if (s[i] == '/') { - memcpy(&t[j], "\\x2f", 4); + for (i = 0, j = 0; src[i] != '\0'; i++) { + if (src[i] == '/') { + if (j+4 >= size) { + j = 0; + break; + } + memcpy(&dest[j], "\\x2f", 4); j += 4; - } else if (s[i] == '\\') { - memcpy(&t[j], "\\x5c", 4); + } else if (src[i] == '\\') { + if (j+4 >= size) { + j = 0; + break; + } + memcpy(&dest[j], "\\x5c", 4); j += 4; } else { - t[j] = s[i]; + if (j+1 >= size) { + j = 0; + break; + } + dest[j] = src[i]; j++; } } - if (i >= size) - return 0; - if (j >= size) - return 0; - memcpy(s, t, j); - s[j] = '\0'; + dest[j] = '\0'; return j; } @@ -158,47 +161,70 @@ void util_remove_trailing_chars(char *path, char c) path[--len] = '\0'; } -size_t util_strlcpy(char *dst, const char *src, size_t size) +/* + * Concatenates strings. In any case, terminates in _all_ cases with '\0' + * and moves the @dest pointer forward to the added '\0'. Returns the + * remaining size, and 0 if the string was truncated. + */ +size_t util_strpcpy(char **dest, size_t size, const char *src) { - size_t bytes = 0; - char *q = dst; - const char *p = src; - char ch; - - while ((ch = *p++)) { - if (bytes+1 < size) - *q++ = ch; - bytes++; + size_t len; + + len = strlen(src); + if (len >= size) { + if (size > 1) + *dest = mempcpy(*dest, src, size-1); + size = 0; + *dest[0] = '\0'; + } else { + if (len > 0) { + *dest = mempcpy(*dest, src, len); + size -= len; + } + *dest[0] = '\0'; } + return size; +} + +/* concatenates list of strings, moves dest forward */ +size_t util_strpcpyl(char **dest, size_t size, const char *src, ...) +{ + va_list va; + + va_start(va, src); + do { + size = util_strpcpy(dest, size, src); + src = va_arg(va, char *); + } while (src != NULL); + va_end(va); - /* If size == 0 there is no space for a final null... */ - if (size) - *q = '\0'; - return bytes; + return size; } -size_t util_strlcat(char *dst, const char *src, size_t size) +/* copies string */ +size_t util_strscpy(char *dest, size_t size, const char *src) { - size_t bytes = 0; - char *q = dst; - const char *p = src; - char ch; - - while (bytes < size && *q) { - q++; - bytes++; - } - if (bytes == size) - return (bytes + strlen(src)); + char *s; - while ((ch = *p++)) { - if (bytes+1 < size) - *q++ = ch; - bytes++; - } + s = dest; + return util_strpcpy(&s, size, src); +} - *q = '\0'; - return bytes; +/* concatenates list of strings */ +size_t util_strscpyl(char *dest, size_t size, const char *src, ...) +{ + va_list va; + char *s; + + va_start(va, src); + s = dest; + do { + size = util_strpcpy(&s, size, src); + src = va_arg(va, char *); + } while (src != NULL); + va_end(va); + + return size; } /* count of characters used to encode one unicode char */ diff --git a/udev/test-udev.c b/udev/test-udev.c index 6ec91c17..c6b8bf57 100644 --- a/udev/test-udev.c +++ b/udev/test-udev.c @@ -83,8 +83,7 @@ int main(int argc, char *argv[]) rules = udev_rules_new(udev, 1); - util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); - util_strlcat(syspath, devpath, sizeof(syspath)); + util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), devpath, NULL); dev = udev_device_new_from_syspath(udev, syspath); if (dev == NULL) { info(udev, "unknown device '%s'\n", devpath); diff --git a/udev/udev-event.c b/udev/udev-event.c index 03ae3524..d5212519 100644 --- a/udev/udev-event.c +++ b/udev/udev-event.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2008 Kay Sievers + * Copyright (C) 2004-2009 Kay Sievers * * 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 @@ -57,178 +57,185 @@ void udev_event_unref(struct udev_event *event) free(event); } -/* extract possible {attr} and move str behind it */ -static char *get_format_attribute(struct udev *udev, char **str) -{ - char *pos; - char *attr = NULL; - - if (*str[0] == '{') { - pos = strchr(*str, '}'); - if (pos == NULL) { - err(udev, "missing closing brace for format\n"); - return NULL; - } - pos[0] = '\0'; - attr = *str+1; - *str = pos+1; - dbg(udev, "attribute='%s', str='%s'\n", attr, *str); - } - return attr; -} - -void udev_event_apply_format(struct udev_event *event, char *string, size_t maxsize) +size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size) { struct udev_device *dev = event->dev; - char temp[UTIL_PATH_SIZE]; - char temp2[UTIL_PATH_SIZE]; - char *head, *tail, *cpos, *attr, *rest; - int i; - int count; enum subst_type { SUBST_UNKNOWN, - SUBST_DEVPATH, + SUBST_TEMP_NODE, + SUBST_ATTR, + SUBST_ENV, SUBST_KERNEL, SUBST_KERNEL_NUMBER, - SUBST_ID, SUBST_DRIVER, + SUBST_DEVPATH, + SUBST_ID, SUBST_MAJOR, SUBST_MINOR, SUBST_RESULT, - SUBST_ATTR, SUBST_PARENT, - SUBST_TEMP_NODE, SUBST_NAME, SUBST_LINKS, SUBST_ROOT, SUBST_SYS, - SUBST_ENV, }; static const struct subst_map { char *name; char fmt; enum subst_type type; } map[] = { - { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, - { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, + { .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE }, + { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, + { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, + { .name = "env", .fmt = 'E', .type = SUBST_ENV }, { .name = "kernel", .fmt = 'k', .type = SUBST_KERNEL }, - { .name = "id", .fmt = 'b', .type = SUBST_ID }, + { .name = "number", .fmt = 'n', .type = SUBST_KERNEL_NUMBER }, { .name = "driver", .fmt = 'd', .type = SUBST_DRIVER }, + { .name = "devpath", .fmt = 'p', .type = SUBST_DEVPATH }, + { .name = "id", .fmt = 'b', .type = SUBST_ID }, { .name = "major", .fmt = 'M', .type = SUBST_MAJOR }, { .name = "minor", .fmt = 'm', .type = SUBST_MINOR }, { .name = "result", .fmt = 'c', .type = SUBST_RESULT }, - { .name = "attr", .fmt = 's', .type = SUBST_ATTR }, - { .name = "sysfs", .fmt = 's', .type = SUBST_ATTR }, { .name = "parent", .fmt = 'P', .type = SUBST_PARENT }, - { .name = "tempnode", .fmt = 'N', .type = SUBST_TEMP_NODE }, { .name = "name", .fmt = 'D', .type = SUBST_NAME }, { .name = "links", .fmt = 'L', .type = SUBST_LINKS }, { .name = "root", .fmt = 'r', .type = SUBST_ROOT }, { .name = "sys", .fmt = 'S', .type = SUBST_SYS }, - { .name = "env", .fmt = 'E', .type = SUBST_ENV }, - { NULL, '\0', 0 } }; - enum subst_type type; - const struct subst_map *subst; + const char *from; + char *s; + size_t l; + + from = src; + s = dest; + l = size; - head = string; while (1) { - while (head[0] != '\0') { - if (head[0] == '$') { + enum subst_type type = SUBST_UNKNOWN; + char attrbuf[UTIL_PATH_SIZE]; + char *attr = NULL; + + while (from[0] != '\0') { + if (from[0] == '$') { /* substitute named variable */ - if (head[1] == '\0') - break; - if (head[1] == '$') { - util_strlcpy(temp, head+2, sizeof(temp)); - util_strlcpy(head+1, temp, maxsize); - head++; - continue; + unsigned int i; + + if (from[1] == '$') { + from++; + goto copy; } - head[0] = '\0'; - for (subst = map; subst->name; subst++) { - if (strncasecmp(&head[1], subst->name, strlen(subst->name)) == 0) { - type = subst->type; - tail = head + strlen(subst->name)+1; - dbg(event->udev, "will substitute format name '%s'\n", subst->name); - goto found; + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (strncasecmp(&from[1], map[i].name, strlen(map[i].name)) == 0) { + type = map[i].type; + from += strlen(map[i].name)+1; + dbg(event->udev, "will substitute format name '%s'\n", map[i].name); + goto subst; } } - head[0] = '$'; - err(event->udev, "unknown format variable '%s'\n", head); - } else if (head[0] == '%') { + } else if (from[0] == '%') { /* substitute format char */ - if (head[1] == '\0') - break; - if (head[1] == '%') { - util_strlcpy(temp, head+2, sizeof(temp)); - util_strlcpy(head+1, temp, maxsize); - head++; - continue; + unsigned int i; + + if (from[1] == '%') { + from++; + goto copy; } - head[0] = '\0'; - tail = head+1; - for (subst = map; subst->name; subst++) { - if (tail[0] == subst->fmt) { - type = subst->type; - tail++; - dbg(event->udev, "will substitute format char '%c'\n", subst->fmt); - goto found; + + for (i = 0; i < ARRAY_SIZE(map); i++) { + if (from[1] == map[i].fmt) { + type = map[i].type; + from += 2; + dbg(event->udev, "will substitute format char '%c'\n", map[i].fmt); + goto subst; } } - head[0] = '%'; - err(event->udev, "unknown format char '%c'\n", tail[0]); } - head++; +copy: + /* copy char */ + if (l == 0) + goto out; + s[0] = from[0]; + from++; + s++; + l--; + } + + goto out; +subst: + /* extract possible $format{attr} */ + if (from[0] == '{') { + unsigned int i; + + from++; + for (i = 0; from[i] != '}'; i++) { + if (from[i] == '\0') { + err(event->udev, "missing closing brace for format '%s'\n", src); + goto out; + } + } + if (i >= sizeof(attrbuf)) + goto out; + memcpy(attrbuf, from, i); + attrbuf[i] = '\0'; + from += i+1; + attr = attrbuf; } - break; -found: - attr = get_format_attribute(event->udev, &tail); - util_strlcpy(temp, tail, sizeof(temp)); - dbg(event->udev, "format=%i, string='%s', tail='%s'\n", type ,string, tail); switch (type) { case SUBST_DEVPATH: - util_strlcat(string, udev_device_get_devpath(dev), maxsize); + l = util_strpcpy(&s, l, udev_device_get_devpath(dev)); dbg(event->udev, "substitute devpath '%s'\n", udev_device_get_devpath(dev)); break; case SUBST_KERNEL: - util_strlcat(string, udev_device_get_sysname(dev), maxsize); + l = util_strpcpy(&s, l, udev_device_get_sysname(dev)); dbg(event->udev, "substitute kernel name '%s'\n", udev_device_get_sysname(dev)); break; case SUBST_KERNEL_NUMBER: if (udev_device_get_sysnum(dev) == NULL) break; - util_strlcat(string, udev_device_get_sysnum(dev), maxsize); + l = util_strpcpy(&s, l, udev_device_get_sysnum(dev)); dbg(event->udev, "substitute kernel number '%s'\n", udev_device_get_sysnum(dev)); break; case SUBST_ID: - if (event->dev_parent != NULL) { - util_strlcat(string, udev_device_get_sysname(event->dev_parent), maxsize); - dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent)); - } + if (event->dev_parent == NULL) + break; + l = util_strpcpy(&s, l, udev_device_get_sysname(event->dev_parent)); + dbg(event->udev, "substitute id '%s'\n", udev_device_get_sysname(event->dev_parent)); break; - case SUBST_DRIVER: - if (event->dev_parent != NULL) { - const char *driver; + case SUBST_DRIVER: { + const char *driver; - driver = udev_device_get_driver(event->dev_parent); - if (driver == NULL) - break; - util_strlcat(string, driver, maxsize); - dbg(event->udev, "substitute driver '%s'\n", driver); - } + if (event->dev_parent == NULL) + break; + + driver = udev_device_get_driver(event->dev_parent); + if (driver == NULL) + break; + l = util_strpcpy(&s, l, driver); + dbg(event->udev, "substitute driver '%s'\n", driver); break; - case SUBST_MAJOR: - sprintf(temp2, "%d", major(udev_device_get_devnum(dev))); - util_strlcat(string, temp2, maxsize); - dbg(event->udev, "substitute major number '%s'\n", temp2); + } + case SUBST_MAJOR: { + char num[UTIL_PATH_SIZE]; + + sprintf(num, "%d", major(udev_device_get_devnum(dev))); + l = util_strpcpy(&s, l, num); + dbg(event->udev, "substitute major number '%s'\n", num); break; - case SUBST_MINOR: - sprintf(temp2, "%d", minor(udev_device_get_devnum(dev))); - util_strlcat(string, temp2, maxsize); - dbg(event->udev, "substitute minor number '%s'\n", temp2); + } + case SUBST_MINOR: { + char num[UTIL_PATH_SIZE]; + + sprintf(num, "%d", minor(udev_device_get_devnum(dev))); + l = util_strpcpy(&s, l, num); + dbg(event->udev, "substitute minor number '%s'\n", num); break; - case SUBST_RESULT: + } + case SUBST_RESULT: { + char *rest; + int i; + if (event->program_result == NULL) break; /* get part part of the result string */ @@ -237,9 +244,11 @@ found: i = strtoul(attr, &rest, 10); if (i > 0) { char result[UTIL_PATH_SIZE]; + char tmp[UTIL_PATH_SIZE]; + char *cpos; dbg(event->udev, "request part #%d of result string\n", i); - util_strlcpy(result, event->program_result, sizeof(result)); + util_strscpy(result, sizeof(result), event->program_result); cpos = result; while (--i) { while (cpos[0] != '\0' && !isspace(cpos[0])) @@ -251,160 +260,158 @@ found: err(event->udev, "requested part of result string not found\n"); break; } - util_strlcpy(temp2, cpos, sizeof(temp2)); + util_strscpy(tmp, sizeof(tmp), cpos); /* %{2+}c copies the whole string from the second part on */ if (rest[0] != '+') { - cpos = strchr(temp2, ' '); + cpos = strchr(tmp, ' '); if (cpos) cpos[0] = '\0'; } - util_strlcat(string, temp2, maxsize); - dbg(event->udev, "substitute part of result string '%s'\n", temp2); + l = util_strpcpy(&s, l, tmp); + dbg(event->udev, "substitute part of result string '%s'\n", tmp); } else { - util_strlcat(string, event->program_result, maxsize); + l = util_strpcpy(&s, l, event->program_result); dbg(event->udev, "substitute result string '%s'\n", event->program_result); } break; - case SUBST_ATTR: - if (attr == NULL) + } + case SUBST_ATTR: { + const char *val; + char value[UTIL_NAME_SIZE]; + size_t len; + int count; + + if (attr == NULL) { err(event->udev, "missing file parameter for attr\n"); - else { - const char *val; - char value[UTIL_NAME_SIZE]; - size_t size; - - value[0] = '\0'; - /* read the value specified by [usb/]*/ - util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); - - /* try to read attribute of the current device */ - if (value[0] == '\0') { - val = udev_device_get_sysattr_value(event->dev, attr); - if (val != NULL) - util_strlcpy(value, val, sizeof(value)); - } + break; + } - /* try to read the attribute of the parent device, other matches have selected */ - if (value[0] == '\0' && event->dev_parent != NULL && event->dev_parent != event->dev) { - val = udev_device_get_sysattr_value(event->dev_parent, attr); - if (val != NULL) - util_strlcpy(value, val, sizeof(value)); - } + value[0] = '\0'; + /* read the value specified by "[dmi/id]product_name" */ + util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); - if (value[0]=='\0') - break; + /* try to read attribute of the current device */ + if (value[0] == '\0') { + val = udev_device_get_sysattr_value(event->dev, attr); + if (val != NULL) + util_strscpy(value, sizeof(value), val); + } - /* strip trailing whitespace, and replace unwanted characters */ - size = strlen(value); - while (size > 0 && isspace(value[--size])) - value[size] = '\0'; - 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); - dbg(event->udev, "substitute sysfs value '%s'\n", value); + /* try to read the attribute of the parent device, other matches have selected */ + if (value[0] == '\0' && event->dev_parent != NULL && event->dev_parent != event->dev) { + val = udev_device_get_sysattr_value(event->dev_parent, attr); + if (val != NULL) + util_strscpy(value, sizeof(value), val); } + + if (value[0]=='\0') + break; + + /* strip trailing whitespace, and replace unwanted characters */ + len = strlen(value); + while (len > 0 && isspace(value[--len])) + value[len] = '\0'; + count = udev_util_replace_chars(value, UDEV_ALLOWED_CHARS_INPUT); + if (count > 0) + info(event->udev, "%i character(s) replaced\n" , count); + l = util_strpcpy(&s, l, value); + dbg(event->udev, "substitute sysfs value '%s'\n", value); break; - case SUBST_PARENT: - { - struct udev_device *dev_parent; - const char *devnode; + } + case SUBST_PARENT: { + struct udev_device *dev_parent; + const char *devnode; - dev_parent = udev_device_get_parent(event->dev); - if (dev_parent == NULL) - break; + dev_parent = udev_device_get_parent(event->dev); + if (dev_parent == NULL) + break; devnode = udev_device_get_devnode(dev_parent); - if (devnode != NULL) { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; + if (devnode != NULL) { + size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - util_strlcat(string, &devnode[devlen], maxsize); - dbg(event->udev, "found parent '%s', got node name '%s'\n", - udev_device_get_syspath(dev_parent), &devnode[devlen]); - } + l = util_strpcpy(&s, l, &devnode[devlen]); + dbg(event->udev, "found parent '%s', got node name '%s'\n", + udev_device_get_syspath(dev_parent), &devnode[devlen]); } break; - case SUBST_TEMP_NODE: - { - dev_t devnum; - struct stat statbuf; - char filename[UTIL_PATH_SIZE]; - const char *devtype; - - if (event->tmp_node != NULL) { - util_strlcat(string, event->tmp_node, maxsize); - dbg(event->udev, "tempnode: return earlier created one\n"); - break; - } - devnum = udev_device_get_devnum(dev); - if (major(devnum) == 0) - break; - /* lookup kernel provided node */ - if (udev_device_get_knodename(dev) != NULL) { - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, udev_device_get_knodename(dev), sizeof(filename)); - if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) { - util_strlcat(string, filename, maxsize); - dbg(event->udev, "tempnode: return kernel node\n"); - break; - } - } - /* lookup /dev/{char,block}/: */ - if (strcmp(udev_device_get_subsystem(dev), "block") == 0) - devtype = "block"; - else - devtype = "char"; - snprintf(filename, sizeof(filename), "%s/%s/%u:%u", - udev_get_dev_path(event->udev), devtype, - major(udev_device_get_devnum(dev)), - minor(udev_device_get_devnum(dev))); + } + case SUBST_TEMP_NODE: { + dev_t devnum; + struct stat statbuf; + char filename[UTIL_PATH_SIZE]; + const char *devtype; + + if (event->tmp_node != NULL) { + l = util_strpcpy(&s, l, event->tmp_node); + dbg(event->udev, "tempnode: return earlier created one\n"); + break; + } + devnum = udev_device_get_devnum(dev); + if (major(devnum) == 0) + break; + /* lookup kernel provided node */ + if (udev_device_get_knodename(dev) != NULL) { + util_strscpyl(filename, sizeof(filename), + udev_get_dev_path(event->udev), "/", udev_device_get_knodename(dev), NULL); if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) { - util_strlcat(string, filename, maxsize); - dbg(event->udev, "tempnode: return maj:min node\n"); + l = util_strpcpy(&s, l, filename); + dbg(event->udev, "tempnode: return kernel node\n"); break; } - /* create temporary node */ - dbg(event->udev, "tempnode: create temp node\n"); - asprintf(&event->tmp_node, "%s/.tmp-%s-%u:%u", - udev_get_dev_path(event->udev), devtype, - major(udev_device_get_devnum(dev)), - minor(udev_device_get_devnum(dev))); - if (event->tmp_node == NULL) - break; - udev_node_mknod(dev, event->tmp_node, makedev(0, 0), 0600, 0, 0); - util_strlcat(string, event->tmp_node, maxsize); } + /* lookup /dev/{char,block}/: */ + if (strcmp(udev_device_get_subsystem(dev), "block") == 0) + devtype = "block"; + else + devtype = "char"; + snprintf(filename, sizeof(filename), "%s/%s/%u:%u", + udev_get_dev_path(event->udev), devtype, + major(udev_device_get_devnum(dev)), + minor(udev_device_get_devnum(dev))); + if (stat(filename, &statbuf) == 0 && statbuf.st_rdev == devnum) { + l = util_strpcpy(&s, l, filename); + dbg(event->udev, "tempnode: return maj:min node\n"); + break; + } + /* create temporary node */ + dbg(event->udev, "tempnode: create temp node\n"); + asprintf(&event->tmp_node, "%s/.tmp-%s-%u:%u", + udev_get_dev_path(event->udev), devtype, + major(udev_device_get_devnum(dev)), + minor(udev_device_get_devnum(dev))); + if (event->tmp_node == NULL) + break; + udev_node_mknod(dev, event->tmp_node, makedev(0, 0), 0600, 0, 0); + l = util_strpcpy(&s, l, event->tmp_node); break; + } case SUBST_NAME: if (event->name != NULL) { - util_strlcat(string, event->name, maxsize); + l = util_strpcpy(&s, l, event->name); dbg(event->udev, "substitute name '%s'\n", event->name); } else { - util_strlcat(string, udev_device_get_sysname(dev), maxsize); + l = util_strpcpy(&s, l, udev_device_get_sysname(dev)); dbg(event->udev, "substitute sysname '%s'\n", udev_device_get_sysname(dev)); } break; - case SUBST_LINKS: - { - size_t devlen = strlen(udev_get_dev_path(event->udev))+1; - struct udev_list_entry *list_entry; + case SUBST_LINKS: { + size_t devlen = strlen(udev_get_dev_path(event->udev))+1; + struct udev_list_entry *list_entry; - list_entry = udev_device_get_devlinks_list_entry(dev); - if (list_entry == NULL) - break; - util_strlcat(string, &udev_list_entry_get_name(list_entry)[devlen], maxsize); - udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) { - util_strlcat(string, " ", maxsize); - util_strlcat(string, &udev_list_entry_get_name(list_entry)[devlen], maxsize); - } - } + list_entry = udev_device_get_devlinks_list_entry(dev); + if (list_entry == NULL) + break; + l = util_strpcpy(&s, l, &udev_list_entry_get_name(list_entry)[devlen]); + udev_list_entry_foreach(list_entry, udev_list_entry_get_next(list_entry)) + l = util_strpcpyl(&s, l, " ", &udev_list_entry_get_name(list_entry)[devlen], NULL); break; + } case SUBST_ROOT: - util_strlcat(string, udev_get_dev_path(event->udev), maxsize); + l = util_strpcpy(&s, l, udev_get_dev_path(event->udev)); dbg(event->udev, "substitute udev_root '%s'\n", udev_get_dev_path(event->udev)); break; case SUBST_SYS: - util_strlcat(string, udev_get_sys_path(event->udev), maxsize); + l = util_strpcpy(&s, l, udev_get_sys_path(event->udev)); dbg(event->udev, "substitute sys_path '%s'\n", udev_get_sys_path(event->udev)); break; case SUBST_ENV: @@ -418,15 +425,19 @@ found: if (value == NULL) break; dbg(event->udev, "substitute env '%s=%s'\n", attr, value); - util_strlcat(string, value, maxsize); + l = util_strpcpy(&s, l, value); break; } default: err(event->udev, "unknown substitution type=%i\n", type); break; } - util_strlcat(string, temp, maxsize); } + +out: + s[0] = '\0'; + dbg(event->udev, "'%s' -> '%s' (%zu)\n", src, dest, l); + return l; } static void rename_netif_kernel_log(struct ifreq ifr) @@ -466,8 +477,8 @@ static int rename_netif(struct udev_event *event) } memset(&ifr, 0x00, sizeof(struct ifreq)); - util_strlcpy(ifr.ifr_name, udev_device_get_sysname(dev), IFNAMSIZ); - util_strlcpy(ifr.ifr_newname, event->name, IFNAMSIZ); + util_strscpy(ifr.ifr_name, IFNAMSIZ, udev_device_get_sysname(dev)); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); err = ioctl(sk, SIOCSIFNAME, &ifr); if (err == 0) rename_netif_kernel_log(ifr); @@ -482,8 +493,8 @@ static int rename_netif(struct udev_event *event) } /* free our own name, another process may wait for us */ - util_strlcpy(ifr.ifr_newname, udev_device_get_sysname(dev), IFNAMSIZ); - util_strlcat(ifr.ifr_newname, "_rename", IFNAMSIZ); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, udev_device_get_sysname(dev)); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, "_rename"); err = ioctl(sk, SIOCSIFNAME, &ifr); if (err != 0) { err(event->udev, "error changing netif name %s to %s: %m\n", @@ -492,8 +503,8 @@ static int rename_netif(struct udev_event *event) } /* wait 90 seconds for our target to become available */ - util_strlcpy(ifr.ifr_name, ifr.ifr_newname, IFNAMSIZ); - util_strlcpy(ifr.ifr_newname, event->name, IFNAMSIZ); + util_strscpy(ifr.ifr_name, IFNAMSIZ, ifr.ifr_newname); + util_strscpy(ifr.ifr_newname, IFNAMSIZ, event->name); loop = 90 * 20; while (loop--) { err = ioctl(sk, SIOCSIFNAME, &ifr); @@ -591,9 +602,7 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules) } /* set device node name */ - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, event->name, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", event->name, NULL); udev_device_set_devnode(dev, filename); /* write current database entry */ @@ -609,9 +618,8 @@ exit_add: if (delete_kdevnode && udev_device_get_knodename(dev) != NULL) { struct stat stats; - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, udev_device_get_knodename(dev), sizeof(filename)); + util_strscpyl(filename, sizeof(filename), + udev_get_dev_path(event->udev), "/", udev_device_get_knodename(dev), NULL); if (stat(filename, &stats) == 0 && stats.st_rdev == udev_device_get_devnum(dev)) { unlink(filename); util_delete_path(event->udev, filename); @@ -649,11 +657,11 @@ exit_add: udev_device_add_property(dev, "INTERFACE_OLD", udev_device_get_sysname(dev)); /* now change the devpath, because the kernel device name has changed */ - util_strlcpy(syspath, udev_device_get_syspath(dev), sizeof(syspath)); + util_strscpy(syspath, sizeof(syspath), udev_device_get_syspath(dev)); pos = strrchr(syspath, '/'); if (pos != NULL) { - pos[1] = '\0'; - util_strlcat(syspath, event->name, sizeof(syspath)); + pos++; + util_strscpy(pos, sizeof(syspath) - (pos - syspath), event->name); udev_device_set_syspath(event->dev, syspath); udev_device_add_property(dev, "INTERFACE", udev_device_get_sysname(dev)); info(event->udev, "changed devpath to '%s'\n", udev_device_get_devpath(dev)); @@ -678,9 +686,8 @@ exit_add: info(event->udev, "'%s' not found in database, using kernel name '%s'\n", udev_device_get_syspath(dev), udev_device_get_sysname(dev)); - util_strlcpy(devnode, udev_get_dev_path(event->udev), sizeof(devnode)); - util_strlcat(devnode, "/", sizeof(devnode)); - util_strlcat(devnode, udev_device_get_sysname(dev), sizeof(devnode)); + util_strscpyl(devnode, sizeof(devnode), + udev_get_dev_path(event->udev), "/", udev_device_get_sysname(dev), NULL); udev_device_set_devnode(dev, devnode); } @@ -733,8 +740,7 @@ int udev_event_execute_run(struct udev_event *event) char program[UTIL_PATH_SIZE]; char **envp; - util_strlcpy(program, cmd, sizeof(program)); - udev_event_apply_format(event, program, sizeof(program)); + udev_event_apply_format(event, cmd, program, sizeof(program)); if (event->trace) fprintf(stderr, "run %s (%llu) '%s'\n", udev_device_get_syspath(event->dev), diff --git a/udev/udev-node.c b/udev/udev-node.c index 2f9cf4d7..89b674e4 100644 --- a/udev/udev-node.c +++ b/udev/udev-node.c @@ -34,22 +34,15 @@ /* reverse mapping from the device file name to the devpath */ static int name_index(struct udev *udev, const char *devpath, const char *name, int add) { - char device[UTIL_PATH_SIZE]; + char devpath_enc[UTIL_PATH_SIZE]; + char name_enc[UTIL_PATH_SIZE]; char filename[UTIL_PATH_SIZE * 2]; - size_t devlen = strlen(udev_get_dev_path(udev))+1; - size_t start; int fd; - /* directory with device name */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - start = util_strlcat(filename, "/.udev/names/", sizeof(filename)); - util_strlcat(filename, &name[devlen], sizeof(filename)); - util_path_encode(&filename[start], sizeof(filename) - start); - /* entry with the devpath */ - util_strlcpy(device, devpath, sizeof(device)); - util_path_encode(device, sizeof(device)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, device, sizeof(filename)); + util_path_encode(&name[strlen(udev_get_dev_path(udev))+1], name_enc, sizeof(name_enc)); + util_path_encode(devpath, devpath_enc, sizeof(devpath_enc)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), + "/.udev/names/", name_enc, "/", devpath_enc, NULL); if (add) { dbg(udev, "creating index: '%s'\n", filename); @@ -92,8 +85,7 @@ int udev_node_mknod(struct udev_device *dev, const char *file, dev_t devnum, mod char file_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)]; info(udev, "atomically replace existing file '%s'\n", file); - util_strlcpy(file_tmp, file, sizeof(file_tmp)); - util_strlcat(file_tmp, TMP_FILE_EXT, sizeof(file_tmp)); + util_strscpyl(file_tmp, sizeof(file_tmp), file, TMP_FILE_EXT, NULL); unlink(file_tmp); udev_selinux_setfscreatecon(udev, file_tmp, mode); err = mknod(file_tmp, mode, devnum); @@ -145,10 +137,11 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink) { struct stat stats; char target[UTIL_PATH_SIZE]; + char *s; + size_t l; char slink_tmp[UTIL_PATH_SIZE + sizeof(TMP_FILE_EXT)]; int i = 0; int tail = 0; - int len; int err = 0; /* use relative link */ @@ -158,12 +151,18 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink) tail = i+1; i++; } + s = target; + l = sizeof(target); while (slink[i] != '\0') { if (slink[i] == '/') - util_strlcat(target, "../", sizeof(target)); + l = util_strpcpy(&s, l, "../"); i++; } - util_strlcat(target, &node[tail], sizeof(target)); + l = util_strscpy(s, l, &node[tail]); + if (l == 0) { + err = -EINVAL; + goto exit; + } /* preserve link with correct target, do not replace node of other device */ if (lstat(slink, &stats) == 0) { @@ -185,6 +184,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink) } } else if (S_ISLNK(stats.st_mode)) { char buf[UTIL_PATH_SIZE]; + int len; dbg(udev, "found existing symlink '%s'\n", slink); len = readlink(slink, buf, sizeof(buf)); @@ -208,8 +208,7 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink) } info(udev, "atomically replace '%s'\n", slink); - util_strlcpy(slink_tmp, slink, sizeof(slink_tmp)); - util_strlcat(slink_tmp, TMP_FILE_EXT, sizeof(slink_tmp)); + util_strscpyl(slink_tmp, sizeof(slink_tmp), slink, TMP_FILE_EXT, NULL); unlink(slink_tmp); udev_selinux_setfscreatecon(udev, slink, S_IFLNK); err = symlink(target, slink_tmp); @@ -222,7 +221,6 @@ static int node_symlink(struct udev *udev, const char *node, const char *slink) if (err != 0) { err(udev, "rename(%s, %s) failed: %m\n", slink_tmp, slink); unlink(slink_tmp); - goto exit; } exit: return err; @@ -230,16 +228,16 @@ exit: static int name_index_get_devices(struct udev *udev, const char *name, struct udev_list_node *dev_list) { - char dirname[PATH_MAX]; - size_t devlen = strlen(udev_get_dev_path(udev))+1; - size_t start; + char dirname[UTIL_PATH_SIZE]; + char *s; + size_t l; DIR *dir; int count = 0; - util_strlcpy(dirname, udev_get_dev_path(udev), sizeof(dirname)); - start = util_strlcat(dirname, "/.udev/names/", sizeof(dirname)); - util_strlcat(dirname, &name[devlen], sizeof(dirname)); - util_path_encode(&dirname[start], sizeof(dirname) - start); + s = dirname; + l = util_strpcpyl(&s, sizeof(dirname), udev_get_dev_path(udev), + "/.udev/names/", NULL); + util_path_encode(&name[strlen(udev_get_dev_path(udev))+1], s, l); dir = opendir(dirname); if (dir == NULL) { dbg(udev, "no index directory '%s': %m\n", dirname); @@ -258,8 +256,7 @@ static int name_index_get_devices(struct udev *udev, const char *name, struct ud if (ent->d_name[0] == '.') continue; - util_strlcpy(device, udev_get_sys_path(udev), sizeof(device)); - util_strlcat(device, ent->d_name, sizeof(device)); + util_strscpyl(device, sizeof(device), udev_get_sys_path(udev), ent->d_name, NULL); util_path_decode(device); udev_list_entry_add(udev, dev_list, device, NULL, 1, 0); count++; @@ -313,7 +310,7 @@ static int update_link(struct udev_device *dev, const char *slink) udev_device_get_devnode(dev)); } else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) { priority = udev_device_get_devlink_priority(dev); - util_strlcpy(target, udev_device_get_devnode(dev), sizeof(target)); + util_strscpy(target, sizeof(target), udev_device_get_devnode(dev)); } continue; } @@ -334,7 +331,7 @@ static int update_link(struct udev_device *dev, const char *slink) priority); if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) { priority = udev_device_get_devlink_priority(dev_db); - util_strlcpy(target, devnode, sizeof(target)); + util_strscpy(target, sizeof(target), devnode); } } } diff --git a/udev/udev-rules.c b/udev/udev-rules.c index 39fe55aa..da1d3220 100644 --- a/udev/udev-rules.c +++ b/udev/udev-rules.c @@ -706,8 +706,7 @@ static int import_property_from_string(struct udev_device *dev, char *line) info(udev, "updating devpath from '%s' to '%s'\n", udev_device_get_devpath(dev), val); - util_strlcpy(syspath, udev_get_sys_path(udev), sizeof(syspath)); - util_strlcat(syspath, val, sizeof(syspath)); + util_strscpyl(syspath, sizeof(syspath), udev_get_sys_path(udev), val, NULL); udev_device_set_syspath(dev, syspath); } else { struct udev_list_entry *entry; @@ -799,12 +798,9 @@ static int wait_for_file(struct udev_device *dev, const char *file, int timeout) /* a relative path is a device attribute */ devicepath[0] = '\0'; if (file[0] != '/') { - util_strlcpy(devicepath, udev_get_sys_path(udev), sizeof(devicepath)); - util_strlcat(devicepath, udev_device_get_devpath(dev), sizeof(devicepath)); - - util_strlcpy(filepath, devicepath, sizeof(filepath)); - util_strlcat(filepath, "/", sizeof(filepath)); - util_strlcat(filepath, file, sizeof(filepath)); + util_strscpyl(devicepath, sizeof(devicepath), + udev_get_sys_path(udev), udev_device_get_devpath(dev), NULL); + util_strscpyl(filepath, sizeof(filepath), devicepath, "/", file, NULL); file = filepath; } @@ -829,17 +825,21 @@ static int wait_for_file(struct udev_device *dev, const char *file, int timeout) static int attr_subst_subdir(char *attr, size_t len) { - char *pos; int found = 0; - pos = strstr(attr, "/*/"); - if (pos != NULL) { - char str[UTIL_PATH_SIZE]; + if (strstr(attr, "/*/")) { + char *pos; + char dirname[UTIL_PATH_SIZE]; + const char *tail; DIR *dir; - pos[1] = '\0'; - util_strlcpy(str, &pos[2], sizeof(str)); - dir = opendir(attr); + util_strscpy(dirname, sizeof(dirname), attr); + pos = strstr(dirname, "/*/"); + if (pos == NULL) + return -1; + pos[0] = '\0'; + tail = &pos[2]; + dir = opendir(dirname); if (dir != NULL) { struct dirent *dent; @@ -848,18 +848,14 @@ static int attr_subst_subdir(char *attr, size_t len) if (dent->d_name[0] == '.') continue; - util_strlcat(attr, dent->d_name, len); - util_strlcat(attr, str, len); + util_strscpyl(attr, len, dirname, "/", dent->d_name, tail, NULL); if (stat(attr, &stats) == 0) { found = 1; break; } - pos[1] = '\0'; } closedir(dir); } - if (!found) - util_strlcat(attr, str, len); } return found; @@ -1319,22 +1315,16 @@ static int add_rule(struct udev_rules *rules, char *line, char *pos; struct stat statbuf; - util_strlcpy(file, value, sizeof(file)); + /* allow programs in /lib/udev called without the path */ + if (value[0] != '/') + util_strscpyl(file, sizeof(file), UDEV_PREFIX "/lib/udev/", value, NULL); + else + util_strscpy(file, sizeof(file), value); pos = strchr(file, ' '); if (pos) pos[0] = '\0'; - - /* allow programs in /lib/udev called without the path */ - if (strchr(file, '/') == NULL) { - util_strlcpy(file, UDEV_PREFIX "/lib/udev/", sizeof(file)); - util_strlcat(file, value, sizeof(file)); - pos = strchr(file, ' '); - if (pos) - pos[0] = '\0'; - } - dbg(rules->udev, "IMPORT auto mode for '%s'\n", file); - if (!lstat(file, &statbuf) && (statbuf.st_mode & S_IXUSR)) { + if (stat(file, &statbuf) == 0 && (statbuf.st_mode & S_IXUSR)) { dbg(rules->udev, "IMPORT will be executed (autotype)\n"); rule_add_key(&rule_tmp, TK_M_IMPORT_PROG, op, value, NULL); } else { @@ -1714,8 +1704,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) add_matching_files(udev, &file_list, SYSCONFDIR "/udev/rules.d", ".rules"); /* read dynamic/temporary rules */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/rules.d", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL); if (stat(filename, &statbuf) != 0) { util_create_path(udev, filename); udev_selinux_setfscreatecon(udev, filename, S_IFDIR|0755); @@ -1895,7 +1884,7 @@ static int match_key(struct udev_rules *rules, struct token *token, const char * { char value[UTIL_PATH_SIZE]; - util_strlcpy(value, &rules->buf[token->key.value_off], sizeof(value)); + util_strscpy(value, sizeof(value), &rules->buf[token->key.value_off]); key_value = value; while (key_value != NULL) { pos = strchr(key_value, '|'); @@ -1942,7 +1931,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct if (key_name[0] == '[') { char attr[UTIL_PATH_SIZE]; - util_strlcpy(attr, key_name, sizeof(attr)); + util_strscpy(attr, sizeof(attr), key_name); util_resolve_subsys_kernel(event->udev, attr, value, sizeof(value), 1); } if (value[0] == '\0') { @@ -1951,7 +1940,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct val = udev_device_get_sysattr_value(dev, key_name); if (val == NULL) return -1; - util_strlcpy(value, val, sizeof(value)); + util_strscpy(value, sizeof(value), val); } /* strip trailing whitespace of value, if not asked to match for it */ @@ -2062,8 +2051,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char filename[UTIL_PATH_SIZE]; int found; - util_strlcpy(filename, &rules->buf[cur->key.value_off], sizeof(filename)); - udev_event_apply_format(event, filename, sizeof(filename)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); found = (wait_for_file(event->dev, filename, 10) == 0); if (!found && (cur->key.op != OP_NOMATCH)) goto nomatch; @@ -2135,18 +2123,16 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event struct stat statbuf; int match; - util_strlcpy(filename, &rules->buf[cur->key.value_off], sizeof(filename)); - udev_event_apply_format(event, filename, sizeof(filename)); - if (util_resolve_subsys_kernel(event->udev, NULL, filename, sizeof(filename), 0) != 0) + udev_event_apply_format(event, &rules->buf[cur->key.value_off], filename, sizeof(filename)); + if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) { if (filename[0] != '/') { char tmp[UTIL_PATH_SIZE]; - util_strlcpy(tmp, udev_device_get_syspath(event->dev), sizeof(tmp)); - util_strlcat(tmp, "/", sizeof(tmp)); - util_strlcat(tmp, filename, sizeof(tmp)); - util_strlcpy(filename, tmp, sizeof(filename)); + util_strscpy(tmp, sizeof(tmp), filename); + util_strscpyl(filename, sizeof(filename), + udev_device_get_syspath(event->dev), "/", tmp, NULL); } - + } attr_subst_subdir(filename, sizeof(filename)); match = (stat(filename, &statbuf) == 0); @@ -2170,8 +2156,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event free(event->program_result); event->program_result = NULL; - util_strlcpy(program, &rules->buf[cur->key.value_off], sizeof(program)); - udev_event_apply_format(event, program, sizeof(program)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], program, sizeof(program)); envp = udev_device_get_properties_envp(event->dev); info(event->udev, "PROGRAM '%s' %s:%u\n", program, @@ -2200,8 +2185,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); if (import_file_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; @@ -2211,8 +2195,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); info(event->udev, "IMPORT '%s' %s:%u\n", import, &rules->buf[rule->rule.filename_off], @@ -2226,8 +2209,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event { char import[UTIL_PATH_SIZE]; - util_strlcpy(import, &rules->buf[cur->key.value_off], sizeof(import)); - udev_event_apply_format(event, import, sizeof(import)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], import, sizeof(import)); if (import_parent_into_properties(event->dev, import) != 0) if (cur->key.op != OP_NOMATCH) goto nomatch; @@ -2269,8 +2251,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->owner_final = 1; - util_strlcpy(owner, &rules->buf[cur->key.value_off], sizeof(owner)); - udev_event_apply_format(event, owner, sizeof(owner)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], owner, sizeof(owner)); event->uid = util_lookup_user(event->udev, owner); info(event->udev, "OWNER %u %s:%u\n", event->uid, @@ -2286,8 +2267,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->group_final = 1; - util_strlcpy(group, &rules->buf[cur->key.value_off], sizeof(group)); - udev_event_apply_format(event, group, sizeof(group)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], group, sizeof(group)); event->gid = util_lookup_group(event->udev, group); info(event->udev, "GROUP %u %s:%u\n", event->gid, @@ -2304,8 +2284,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->mode_final = 1; - util_strlcpy(mode, &rules->buf[cur->key.value_off], sizeof(mode)); - udev_event_apply_format(event, mode, sizeof(mode)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], mode, sizeof(mode)); event->mode = strtol(mode, &endptr, 8); if (endptr[0] != '\0') { err(event->udev, "invalide mode '%s' set default mode 0660\n", mode); @@ -2359,8 +2338,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char temp_value[UTIL_NAME_SIZE]; struct udev_list_entry *entry; - util_strlcpy(temp_value, value, sizeof(temp_value)); - udev_event_apply_format(event, temp_value, sizeof(temp_value)); + udev_event_apply_format(event, value, temp_value, sizeof(temp_value)); entry = udev_device_add_property(event->dev, name, temp_value); /* store in db */ udev_list_entry_set_flag(entry, 1); @@ -2379,8 +2357,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event break; if (cur->key.op == OP_ASSIGN_FINAL) event->name_final = 1; - util_strlcpy(name_str, name, sizeof(name_str)); - udev_event_apply_format(event, name_str, sizeof(name_str)); + udev_event_apply_format(event, name, name_str, sizeof(name_str)); if (esc == ESCAPE_UNSET || esc == ESCAPE_REPLACE) { count = udev_util_replace_chars(name_str, "/"); if (count > 0) @@ -2411,8 +2388,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event udev_device_cleanup_devlinks_list(event->dev); /* allow multiple symlinks separated by spaces */ - util_strlcpy(temp, &rules->buf[cur->key.value_off], sizeof(temp)); - udev_event_apply_format(event, temp, sizeof(temp)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], temp, sizeof(temp)); if (esc == ESCAPE_UNSET) count = udev_util_replace_chars(temp, "/ "); else if (esc == ESCAPE_REPLACE) @@ -2430,9 +2406,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event pos, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, pos, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); udev_device_add_devlink(event->dev, filename); while (isspace(next[1])) next++; @@ -2444,9 +2418,7 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event pos, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, pos, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/", pos, NULL); udev_device_add_devlink(event->dev, filename); } } @@ -2464,17 +2436,11 @@ int udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event char value[UTIL_NAME_SIZE]; FILE *f; - util_strlcpy(attr, key_name, sizeof(attr)); - if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) { - util_strlcpy(attr, udev_device_get_syspath(event->dev), sizeof(attr)); - util_strlcat(attr, "/", sizeof(attr)); - util_strlcat(attr, key_name, sizeof(attr)); - } - + if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) + util_strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL); attr_subst_subdir(attr, sizeof(attr)); - util_strlcpy(value, &rules->buf[cur->key.value_off], sizeof(value)); - udev_event_apply_format(event, value, sizeof(value)); + udev_event_apply_format(event, &rules->buf[cur->key.value_off], value, sizeof(value)); info(event->udev, "ATTR '%s' writing '%s' %s:%u\n", attr, value, &rules->buf[rule->rule.filename_off], rule->rule.filename_line); diff --git a/udev/udev-util.c b/udev/udev-util.c index d5eaef70..645293d3 100644 --- a/udev/udev-util.c +++ b/udev/udev-util.c @@ -36,7 +36,7 @@ int util_create_path(struct udev *udev, const char *path) struct stat stats; int ret; - util_strlcpy(p, path, sizeof(p)); + util_strscpy(p, sizeof(p), path); pos = strrchr(p, '/'); if (pos == p || pos == NULL) return 0; @@ -186,12 +186,10 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string, struct udev_device *dev; char *attr; - if (string == NULL) - string = result; if (string[0] != '[') return -1; - util_strlcpy(temp, string, sizeof(temp)); + util_strscpy(temp, sizeof(temp), string); subsys = &temp[1]; @@ -223,16 +221,18 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string, val = udev_device_get_sysattr_value(dev, attr); if (val != NULL) - util_strlcpy(result, val, maxsize); + util_strscpy(result, maxsize, val); else result[0] = '\0'; info(udev, "value '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); } else { - util_strlcpy(result, udev_device_get_syspath(dev), maxsize); - if (attr != NULL) { - util_strlcat(result, "/", maxsize); - util_strlcat(result, attr, maxsize); - } + size_t l; + char *s; + + s = result; + l = util_strpcpyl(&s, maxsize, udev_device_get_syspath(dev), NULL); + if (attr != NULL) + util_strpcpyl(&s, l, "/", attr, NULL); info(udev, "path '[%s/%s]%s' is '%s'\n", subsys, sysname, attr, result); } udev_device_unref(dev); @@ -254,7 +254,7 @@ int util_run_program(struct udev *udev, const char *command, char **envp, int err = 0; /* build argv from command */ - util_strlcpy(arg, command, sizeof(arg)); + util_strscpy(arg, sizeof(arg), command); i = 0; if (strchr(arg, ' ') != NULL) { char *pos = arg; @@ -294,9 +294,8 @@ int util_run_program(struct udev *udev, const char *command, char **envp, } /* allow programs in /lib/udev/ to be called without the path */ - if (strchr(argv[0], '/') == NULL) { - util_strlcpy(program, UDEV_PREFIX "/lib/udev/", sizeof(program)); - util_strlcat(program, argv[0], sizeof(program)); + if (argv[0][0] != '/') { + util_strscpyl(program, sizeof(program), UDEV_PREFIX "/lib/udev/", argv[0], NULL); argv[0] = program; } diff --git a/udev/udev-watch.c b/udev/udev-watch.c index d3334763..8bc87757 100644 --- a/udev/udev-watch.c +++ b/udev/udev-watch.c @@ -59,12 +59,8 @@ void udev_watch_restore(struct udev *udev) if (inotify_fd < 0) return; - util_strlcpy(oldname, udev_get_dev_path(udev), sizeof(oldname)); - util_strlcat(oldname, "/.udev/watch.old", sizeof(oldname)); - - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/watch", sizeof(filename)); - + util_strscpyl(oldname, sizeof(oldname), udev_get_dev_path(udev), "/.udev/watch.old", NULL); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/watch", NULL); if (rename(filename, oldname) == 0) { DIR *dir; struct dirent *ent; @@ -75,27 +71,26 @@ void udev_watch_restore(struct udev *udev) return; } - while ((ent = readdir(dir)) != NULL) { + for (ent = readdir(dir); ent != NULL; ent = readdir(dir)) { char path[UTIL_PATH_SIZE]; char buf[UTIL_PATH_SIZE]; - ssize_t syslen; + char *s; + size_t l; ssize_t len; struct udev_device *dev; if (ent->d_name[0] < '0' || ent->d_name[0] > '9') continue; - util_strlcpy(path, oldname, sizeof(path)); - util_strlcat(path, "/", sizeof(path)); - util_strlcat(path, ent->d_name, sizeof(path)); - - syslen = util_strlcpy(buf, udev_get_sys_path(udev), sizeof(buf)); - len = readlink(path, &buf[syslen], sizeof(buf)-syslen); - if (len <= 0 || len >= (ssize_t)(sizeof(buf)-syslen)) { + util_strscpyl(path, sizeof(path), oldname, "/", ent->d_name, NULL); + s = buf; + l = util_strpcpy(&s, sizeof(buf), udev_get_sys_path(udev)); + len = readlink(path, s, l); + if (len <= 0 || len >= (ssize_t)l) { unlink(path); continue; } - buf[syslen + len] = '\0'; + s[len] = '\0'; dbg(udev, "old watch to '%s' found\n", buf); dev = udev_device_new_from_syspath(udev, buf); if (dev == NULL) { @@ -165,20 +160,20 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev) struct udev_device *udev_watch_lookup(struct udev *udev, int wd) { char filename[UTIL_PATH_SIZE]; - char buf[UTIL_PATH_SIZE]; - ssize_t syslen; + char syspath[UTIL_PATH_SIZE]; + char *s; + size_t l; ssize_t len; if (inotify_fd < 0 || wd < 0) return NULL; snprintf(filename, sizeof(filename), "%s/.udev/watch/%d", udev_get_dev_path(udev), wd); - syslen = util_strlcpy(buf, udev_get_sys_path(udev), sizeof(buf)); - len = readlink(filename, &buf[syslen], sizeof(buf)-syslen); - if (len > 0 || len < (ssize_t)(sizeof(buf)-syslen)) { - buf[syslen + len] = '\0'; - return udev_device_new_from_syspath(udev, buf); - } - - return NULL; + s = syspath; + l = util_strpcpy(&s, sizeof(syspath), udev_get_sys_path(udev)); + len = readlink(filename, s, l); + if (len < 0 || (size_t)len >= l) + return NULL; + s[len] = '\0'; + return udev_device_new_from_syspath(udev, syspath); } diff --git a/udev/udev.h b/udev/udev.h index abf354a6..8f2c1c63 100644 --- a/udev/udev.h +++ b/udev/udev.h @@ -96,7 +96,7 @@ struct udev_event *udev_event_new(struct udev_device *dev); void udev_event_unref(struct udev_event *event); int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules); int udev_event_execute_run(struct udev_event *event); -void udev_event_apply_format(struct udev_event *event, char *string, size_t maxsize); +size_t udev_event_apply_format(struct udev_event *event, const char *src, char *dest, size_t size); int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, char *result, size_t maxsize, int read_value); diff --git a/udev/udevadm-info.c b/udev/udevadm-info.c index f20eb07e..db11a289 100644 --- a/udev/udevadm-info.c +++ b/udev/udevadm-info.c @@ -52,9 +52,7 @@ static void print_all_attributes(struct udev_device *device, const char *key) if (strcmp(dent->d_name, "dev") == 0) continue; - util_strlcpy(filename, udev_device_get_syspath(device), sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, dent->d_name, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_device_get_syspath(device), "/", dent->d_name, NULL); if (lstat(filename, &statbuf) != 0) continue; if (S_ISLNK(statbuf.st_mode)) @@ -270,13 +268,10 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) goto exit; } /* remove /dev if given */ - if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) != 0) { - util_strlcpy(name, udev_get_dev_path(udev), sizeof(name)); - util_strlcat(name, "/", sizeof(name)); - util_strlcat(name, optarg, sizeof(name)); - } else { - util_strlcpy(name, optarg, sizeof(name)); - } + if (strncmp(optarg, udev_get_dev_path(udev), strlen(udev_get_dev_path(udev))) != 0) + util_strscpyl(name, sizeof(name), udev_get_dev_path(udev), "/", optarg, NULL); + else + util_strscpy(name, sizeof(name), optarg); util_remove_trailing_chars(name, '/'); if (stat(name, &statbuf) < 0) { fprintf(stderr, "device node not found\n"); @@ -309,12 +304,10 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) goto exit; } /* add sys dir if needed */ - if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) { - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, optarg, sizeof(path)); - } else { - util_strlcpy(path, optarg, sizeof(path)); - } + if (strncmp(optarg, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) + util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), optarg, NULL); + else + util_strscpy(path, sizeof(path), optarg); util_remove_trailing_chars(path, '/'); device = udev_device_new_from_syspath(udev, path); if (device == NULL) { @@ -355,7 +348,7 @@ int udevadm_info(struct udev *udev, int argc, char *argv[]) break; case 'd': action = ACTION_DEVICE_ID_FILE; - util_strlcpy(name, optarg, sizeof(name)); + util_strscpy(name, sizeof(name), optarg); break; case 'a': action = ACTION_ATTRIBUTE_WALK; diff --git a/udev/udevadm-monitor.c b/udev/udevadm-monitor.c index 3f4cb577..1f094611 100644 --- a/udev/udevadm-monitor.c +++ b/udev/udevadm-monitor.c @@ -107,7 +107,7 @@ int udevadm_monitor(struct udev *udev, int argc, char *argv[]) char subsys[UTIL_NAME_SIZE]; char *devtype; - util_strlcpy(subsys, optarg, sizeof(subsys)); + util_strscpy(subsys, sizeof(subsys), optarg); devtype = strchr(subsys, ':'); if (devtype != NULL) { devtype[0] = '\0'; diff --git a/udev/udevadm-test.c b/udev/udevadm-test.c index c53c2732..e49d52c5 100644 --- a/udev/udevadm-test.c +++ b/udev/udevadm-test.c @@ -91,12 +91,10 @@ int udevadm_test(struct udev *udev, int argc, char *argv[]) } /* add /sys if needed */ - if (strncmp(syspath, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) { - util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename)); - util_strlcat(filename, syspath, sizeof(filename)); - } else { - util_strlcpy(filename, syspath, sizeof(filename)); - } + if (strncmp(syspath, udev_get_sys_path(udev), strlen(udev_get_sys_path(udev))) != 0) + util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev), syspath, NULL); + else + util_strscpy(filename, sizeof(filename), syspath); util_remove_trailing_chars(filename, '/'); dev = udev_device_new_from_syspath(udev, filename); @@ -123,8 +121,7 @@ int udevadm_test(struct udev *udev, int argc, char *argv[]) udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) { char program[UTIL_PATH_SIZE]; - util_strlcpy(program, udev_list_entry_get_name(entry), sizeof(program)); - udev_event_apply_format(event, program, sizeof(program)); + udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program)); info(udev, "run: '%s'\n", program); } } diff --git a/udev/udevadm-trigger.c b/udev/udevadm-trigger.c index 15e7dc17..c256a9e5 100644 --- a/udev/udevadm-trigger.c +++ b/udev/udevadm-trigger.c @@ -49,8 +49,7 @@ static void exec_list(struct udev_enumerate *udev_enumerate, const char *action) printf("%s\n", udev_list_entry_get_name(entry)); if (dry_run) continue; - util_strlcpy(filename, udev_list_entry_get_name(entry), sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_list_entry_get_name(entry), "/uevent", NULL); fd = open(filename, O_WRONLY); if (fd < 0) { dbg(udev, "error on opening %s: %m\n", filename); @@ -150,7 +149,7 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg); break; case 'a': - util_strlcpy(attr, optarg, sizeof(attr)); + util_strscpy(attr, sizeof(attr), optarg); val = strchr(attr, '='); if (val != NULL) { val[0] = 0; @@ -159,7 +158,7 @@ int udevadm_trigger(struct udev *udev, int argc, char *argv[]) udev_enumerate_add_match_sysattr(udev_enumerate, attr, val); break; case 'A': - util_strlcpy(attr, optarg, sizeof(attr)); + util_strscpy(attr, sizeof(attr), optarg); val = strchr(attr, '='); if (val != NULL) { val[0] = 0; diff --git a/udev/udevd.c b/udev/udevd.c index 419c486d..1fe76f88 100644 --- a/udev/udevd.c +++ b/udev/udevd.c @@ -97,18 +97,17 @@ static void export_event_state(struct udev_event *event, enum event_state state) { char filename[UTIL_PATH_SIZE]; char filename_failed[UTIL_PATH_SIZE]; - size_t start; + char *s; + size_t l; /* location of queue file */ snprintf(filename, sizeof(filename), "%s/.udev/queue/%llu", udev_get_dev_path(event->udev), udev_device_get_seqnum(event->dev)); /* location of failed file */ - util_strlcpy(filename_failed, udev_get_dev_path(event->udev), sizeof(filename_failed)); - util_strlcat(filename_failed, "/", sizeof(filename_failed)); - start = util_strlcat(filename_failed, ".udev/failed/", sizeof(filename_failed)); - util_strlcat(filename_failed, udev_device_get_devpath(event->dev), sizeof(filename_failed)); - util_path_encode(&filename_failed[start], sizeof(filename_failed) - start); + s = filename_failed; + l = util_strpcpyl(&s, sizeof(filename_failed), udev_get_dev_path(event->udev), "/.udev/failed/", NULL); + util_path_encode(udev_device_get_devpath(event->dev), s, l); switch (state) { case EVENT_QUEUED: @@ -124,12 +123,9 @@ static void export_event_state(struct udev_event *event, enum event_state state) /* "move" event - rename failed file to current name, do not delete failed */ char filename_failed_old[UTIL_PATH_SIZE]; - util_strlcpy(filename_failed_old, udev_get_dev_path(event->udev), sizeof(filename_failed_old)); - util_strlcat(filename_failed_old, "/", sizeof(filename_failed_old)); - start = util_strlcat(filename_failed_old, ".udev/failed/", sizeof(filename_failed_old)); - util_strlcat(filename_failed_old, udev_device_get_devpath_old(event->dev), sizeof(filename_failed_old)); - util_path_encode(&filename_failed_old[start], sizeof(filename) - start); - + s = filename_failed_old; + l = util_strpcpyl(&s, sizeof(filename_failed_old), udev_get_dev_path(event->udev), "/.udev/failed/", NULL); + util_path_encode(udev_device_get_devpath_old(event->dev), s, l); if (rename(filename_failed_old, filename_failed) == 0) info(event->udev, "renamed devpath, moved failed state of '%s' to %s'\n", udev_device_get_devpath_old(event->dev), udev_device_get_devpath(event->dev)); @@ -270,8 +266,7 @@ static void event_queue_insert(struct udev_event *event) info(event->udev, "seq %llu queued, '%s' '%s'\n", udev_device_get_seqnum(event->dev), udev_device_get_action(event->dev), udev_device_get_subsystem(event->dev)); - util_strlcpy(filename, udev_get_dev_path(event->udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(event->udev), "/.udev/uevent_seqnum", NULL); fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); if (fd >= 0) { char str[32]; @@ -551,8 +546,7 @@ static int handle_inotify(struct udev *udev) int fd; info(udev, "device %s closed, synthesising 'change'\n", udev_device_get_devnode(dev)); - util_strlcpy(filename, udev_device_get_syspath(dev), sizeof(filename)); - util_strlcat(filename, "/uevent", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_device_get_syspath(dev), "/uevent", NULL); fd = open(filename, O_WRONLY); if (fd < 0 || write(fd, "change", 6) < 0) info(udev, "error writing uevent: %m\n"); @@ -641,12 +635,10 @@ static void cleanup_queue_dir(struct udev *udev) char filename[UTIL_PATH_SIZE]; DIR *dir; - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/uevent_seqnum", NULL); unlink(filename); - util_strlcpy(dirname, udev_get_dev_path(udev), sizeof(dirname)); - util_strlcat(dirname, "/.udev/queue", sizeof(dirname)); + util_strscpyl(dirname, sizeof(dirname), udev_get_dev_path(udev), "/.udev/queue", NULL); dir = opendir(dirname); if (dir != NULL) { while (1) { @@ -657,9 +649,7 @@ static void cleanup_queue_dir(struct udev *udev) break; if (dent->d_name[0] == '.') continue; - util_strlcpy(filename, dirname, sizeof(filename)); - util_strlcat(filename, "/", sizeof(filename)); - util_strlcat(filename, dent->d_name, sizeof(filename)); + util_strscpyl(filename, sizeof(filename), dirname, "/", dent->d_name, NULL); unlink(filename); } closedir(dir); @@ -674,8 +664,7 @@ static void export_initial_seqnum(struct udev *udev) char seqnum[32]; ssize_t len = 0; - util_strlcpy(filename, udev_get_sys_path(udev), sizeof(filename)); - util_strlcat(filename, "/kernel/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_sys_path(udev), "/kernel/uevent_seqnum", NULL); fd = open(filename, O_RDONLY); if (fd >= 0) { len = read(fd, seqnum, sizeof(seqnum)-1); @@ -685,8 +674,7 @@ static void export_initial_seqnum(struct udev *udev) strcpy(seqnum, "0\n"); len = 3; } - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/uevent_seqnum", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/uevent_seqnum", NULL); util_create_path(udev, filename); fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, 0644); if (fd >= 0) { @@ -705,8 +693,7 @@ static void startup_log(struct udev *udev) if (f != NULL) fprintf(f, "<6>udev: starting version " VERSION "\n"); - util_strlcpy(path, udev_get_sys_path(udev), sizeof(path)); - util_strlcat(path, "/class/mem/null", sizeof(path)); + util_strscpyl(path, sizeof(path), udev_get_sys_path(udev), "/class/mem/null", NULL); if (lstat(path, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)) { const char *depr_str = "udev: missing sysfs features; please update the kernel " @@ -917,8 +904,7 @@ int main(int argc, char *argv[]) IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); /* watch dynamic rules directory */ - util_strlcpy(filename, udev_get_dev_path(udev), sizeof(filename)); - util_strlcat(filename, "/.udev/rules.d", sizeof(filename)); + util_strscpyl(filename, sizeof(filename), udev_get_dev_path(udev), "/.udev/rules.d", NULL); inotify_add_watch(inotify_fd, filename, IN_CREATE | IN_DELETE | IN_MOVE | IN_CLOSE_WRITE); } -- 2.39.5