#include "util.h"
int device_new_aux(sd_device **ret) {
- sd_device *device = NULL;
+ sd_device *device;
assert(ret);
.devmode = (mode_t) -1,
.devuid = (uid_t) -1,
.devgid = (gid_t) -1,
+ .action = _DEVICE_ACTION_INVALID,
};
*ret = device;
_syspath);
if (verify) {
- r = chase_symlinks(_syspath, NULL, 0, &syspath);
+ r = chase_symlinks(_syspath, NULL, 0, &syspath, NULL);
if (r == -ENOENT)
return -ENODEV; /* the device does not exist (any more?) */
if (r < 0)
char *p;
/* /sys is a symlink to somewhere sysfs is mounted on? In that case, we convert the path to real sysfs to "/sys". */
- r = chase_symlinks("/sys", NULL, 0, &real_sys);
+ r = chase_symlinks("/sys", NULL, 0, &real_sys, NULL);
if (r < 0)
return log_debug_errno(r, "sd-device: Failed to chase symlink /sys: %m");
"sd-device: Canonicalized path '%s' does not starts with sysfs mount point '%s'",
syspath, real_sys);
- new_syspath = strjoin("/sys/", p);
+ new_syspath = path_join("/sys", p);
if (!new_syspath)
return -ENOMEM;
devpath = syspath + STRLEN("/sys");
+ if (devpath[0] == '\0')
+ /* '/sys' alone is not a valid device path */
+ return -ENODEV;
+
r = device_add_property_internal(device, "DEVPATH", devpath);
if (r < 0)
return r;
free_and_replace(device->syspath, syspath);
-
device->devpath = devpath;
-
return 0;
}
return r;
*ret = TAKE_PTR(device);
-
return 0;
}
assert_return(IN_SET(type, 'b', 'c'), -EINVAL);
/* use /sys/dev/{block,char}/<maj>:<min> link */
- snprintf(id, sizeof(id), "%u:%u", major(devnum), minor(devnum));
+ xsprintf(id, "%u:%u", major(devnum), minor(devnum));
syspath = strjoina("/sys/dev/", (type == 'b' ? "block" : "char"), "/", id);
return sd_device_new_from_devnum(ret, id[0], devt);
}
- case 'n':
- {
+
+ case 'n': {
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
_cleanup_close_ int sk = -1;
struct ifreq ifr = {};
return -ENODEV;
*ret = TAKE_PTR(device);
-
return 0;
}
- case '+':
- {
+
+ case '+': {
char subsys[PATH_MAX];
char *sysname;
return sd_device_new_from_subsystem_sysname(ret, subsys, sysname);
}
+
default:
return -EINVAL;
}
return -ENOENT;
*ret = child->parent;
-
return 0;
}
if (r < 0)
return r;
- free_and_replace(device->subsystem, subsystem);
-
device->subsystem_set = true;
-
- return 0;
+ return free_and_replace(device->subsystem, subsystem);
}
static int device_set_drivers_subsystem(sd_device *device, const char *_subsystem) {
if (r < 0)
return r;
- free_and_replace(device->driver_subsystem, subsystem);
-
- return 0;
+ return free_and_replace(device->driver_subsystem, subsystem);
}
_public_ int sd_device_get_subsystem(sd_device *device, const char **ret) {
return -ENOENT;
*ret = device->subsystem;
-
return 0;
}
_public_ int sd_device_get_devtype(sd_device *device, const char **devtype) {
int r;
- assert(devtype);
- assert(device);
+ assert_return(device, -EINVAL);
r = device_read_uevent_file(device);
if (r < 0)
if (!device->devtype)
return -ENOENT;
- *devtype = device->devtype;
+ if (devtype)
+ *devtype = device->devtype;
- return 0;
+ return !!device->devtype;
}
_public_ int sd_device_get_parent_with_subsystem_devtype(sd_device *child, const char *subsystem, const char *devtype, sd_device **ret) {
return r;
*ret = parent;
-
return 0;
}
if (r < 0)
return r;
- free_and_replace(device->driver, driver);
-
device->driver_set = true;
-
- return 0;
+ return free_and_replace(device->driver, driver);
}
_public_ int sd_device_get_driver(sd_device *device, const char **ret) {
return -ENOENT;
*ret = device->driver;
-
return 0;
}
assert(device->devpath[0] == '/');
*devpath = device->devpath;
-
return 0;
}
assert(path_startswith(device->devname, "/dev/"));
*devname = device->devname;
-
return 0;
}
const char *pos;
size_t len = 0;
+ if (!device->devpath)
+ return -EINVAL;
+
pos = strrchr(device->devpath, '/');
if (!pos)
return -EINVAL;
if (len == 0)
sysnum = NULL;
- free_and_replace(device->sysname, sysname);
-
- device->sysnum = sysnum;
-
device->sysname_set = true;
-
- return 0;
+ device->sysnum = sysnum;
+ return free_and_replace(device->sysname, sysname);
}
_public_ int sd_device_get_sysname(sd_device *device, const char **ret) {
assert_return(device->sysname, -ENOENT);
*ret = device->sysname;
-
return 0;
}
return -ENOENT;
*ret = device->sysnum;
-
return 0;
}
static int device_add_property_internal_from_string(sd_device *device, const char *str) {
_cleanup_free_ char *key = NULL;
char *value;
+ int r;
assert(device);
assert(str);
if (isempty(++value))
value = NULL;
- return device_add_property_internal(device, key, value);
+ /* Add the property to both sd_device::properties and sd_device::properties_db,
+ * as this is called by only handle_db_line(). */
+ r = device_add_property_aux(device, key, value, false);
+ if (r < 0)
+ return r;
+
+ return device_add_property_aux(device, key, value, true);
}
int device_set_usec_initialized(sd_device *device, usec_t when) {
}
*ret = device->id_filename;
-
return 0;
}
-int device_read_db_internal(sd_device *device, bool force) {
+int device_read_db_internal_filename(sd_device *device, const char *filename) {
_cleanup_free_ char *db = NULL;
- char *path;
- const char *id, *value;
+ const char *value;
+ size_t db_len, i;
char key;
- size_t db_len;
- unsigned i;
int r;
enum {
} state = PRE_KEY;
assert(device);
+ assert(filename);
- if (device->db_loaded || (!force && device->sealed))
- return 0;
-
- r = device_get_id_filename(device, &id);
- if (r < 0)
- return r;
-
- path = strjoina("/run/udev/data/", id);
-
- r = read_full_file(path, &db, &db_len);
+ r = read_full_file(filename, &db, &db_len);
if (r < 0) {
if (r == -ENOENT)
return 0;
- else
- return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", path);
+
+ return log_device_debug_errno(device, r, "sd-device: Failed to read db '%s': %m", filename);
}
/* devices with a database entry are initialized */
break;
default:
- assert_not_reached("Invalid state when parsing db");
+ return log_device_debug_errno(device, SYNTHETIC_ERRNO(EINVAL), "sd-device: invalid db syntax.");
}
}
return 0;
}
+int device_read_db_internal(sd_device *device, bool force) {
+ const char *id, *path;
+ int r;
+
+ assert(device);
+
+ if (device->db_loaded || (!force && device->sealed))
+ return 0;
+
+ r = device_get_id_filename(device, &id);
+ if (r < 0)
+ return r;
+
+ path = strjoina("/run/udev/data/", id);
+
+ return device_read_db_internal_filename(device, path);
+}
+
_public_ int sd_device_get_is_initialized(sd_device *device) {
int r;
return -EIO;
*usec = now_ts - device->usec_initialized;
-
return 0;
}
return v;
}
-static int device_properties_prepare(sd_device *device) {
+int device_properties_prepare(sd_device *device) {
int r;
assert(device);
_public_ const char *sd_device_get_property_first(sd_device *device, const char **_value) {
const char *key;
- const char *value;
int r;
assert_return(device, NULL);
device->properties_iterator_generation = device->properties_generation;
device->properties_iterator = ITERATOR_FIRST;
- ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
-
- if (_value)
- *_value = value;
-
+ (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
return key;
}
_public_ const char *sd_device_get_property_next(sd_device *device, const char **_value) {
const char *key;
- const char *value;
int r;
assert_return(device, NULL);
if (device->properties_iterator_generation != device->properties_generation)
return NULL;
- ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)&value, (const void**)&key);
-
- if (_value)
- *_value = value;
-
+ (void) ordered_hashmap_iterate(device->properties, &device->properties_iterator, (void**)_value, (const void**)&key);
return key;
}
return r;
FOREACH_DIRENT_ALL(dent, dir, return -errno) {
- char *path;
+ _cleanup_free_ char *path = NULL;
struct stat statbuf;
/* only handle symlinks and regular files */
if (!IN_SET(dent->d_type, DT_LNK, DT_REG))
continue;
- path = strjoina(syspath, "/", dent->d_name);
+ path = path_join(syspath, dent->d_name);
+ if (!path)
+ return -ENOMEM;
if (lstat(path, &statbuf) != 0)
continue;
if (_value)
*_value = value;
-
return 0;
}
r = hashmap_put(device->sysattr_values, key, value);
if (r < 0)
return r;
-
- key = NULL;
+ TAKE_PTR(key);
return 0;
}
if (_value)
*_value = value;
-
return 0;
}
* with a NULL value in the cache, otherwise the returned string is stored */
_public_ int sd_device_get_sysattr_value(sd_device *device, const char *sysattr, const char **_value) {
_cleanup_free_ char *value = NULL;
- const char *syspath, *cached_value = NULL;
- char *path;
+ const char *path, *syspath, *cached_value = NULL;
struct stat statbuf;
int r;
if (r < 0)
return r;
- path = strjoina(syspath, "/", sysattr);
+ path = prefix_roota(syspath, sysattr);
r = lstat(path, &statbuf);
if (r < 0) {
/* remember that we could not access the sysattr */
size_t size;
/* read attribute value */
- r = read_full_file(path, &value, &size);
+ r = read_full_virtual_file(path, &value, &size);
if (r < 0)
return r;
static void device_remove_sysattr_value(sd_device *device, const char *_key) {
_cleanup_free_ char *key = NULL;
- _cleanup_free_ char *value = NULL;
assert(device);
assert(_key);
- value = hashmap_remove2(device->sysattr_values, _key, (void **) &key);
-
- return;
+ free(hashmap_remove2(device->sysattr_values, _key, (void **) &key));
}
/* set the attribute and save it in the cache. If a NULL value is passed the
if (!_value) {
device_remove_sysattr_value(device, sysattr);
-
return 0;
}
if (r < 0)
return r;
- path = strjoina(syspath, "/", sysattr);
+ path = prefix_roota(syspath, sysattr);
len = strlen(_value);
if (r == -EISDIR)
return r;
- free(value);
- value = strdup("");
- if (!value)
- return -ENOMEM;
+ r = free_and_strdup(&value, "");
+ if (r < 0)
+ return r;
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
+ TAKE_PTR(value);
- value = NULL;
return -ENXIO;
}
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
+ TAKE_PTR(value);
- value = NULL;
return 0;
}