static const char* const resolve_name_timing_table[_RESOLVE_NAME_TIMING_MAX] = {
[RESOLVE_NAME_NEVER] = "never",
- [RESOLVE_NAME_LATE] = "late",
+ [RESOLVE_NAME_LATE] = "late",
[RESOLVE_NAME_EARLY] = "early",
};
return 0;
}
-/* Note that if -ENOENT is returned, it will be logged at debug level rather than error,
- * because it's an expected, common occurrence that the caller will handle with a fallback */
-static int device_new_from_dev_path(const char *devlink, sd_device **ret_device) {
- struct stat st;
- int r;
-
- assert(devlink);
-
- if (stat(devlink, &st) < 0)
- return log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_ERR, errno,
- "Failed to stat() %s: %m", devlink);
-
- if (!S_ISBLK(st.st_mode))
- return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
- "%s does not point to a block device: %m", devlink);
-
- r = sd_device_new_from_stat_rdev(ret_device, &st);
- if (r < 0)
- return log_error_errno(r, "Failed to initialize device from %s: %m", devlink);
-
- return 0;
-}
-
struct DeviceMonitorData {
const char *sysname;
const char *devlink;
}
static int device_monitor_handler(sd_device_monitor *monitor, sd_device *device, void *userdata) {
- struct DeviceMonitorData *data = userdata;
+ struct DeviceMonitorData *data = ASSERT_PTR(userdata);
const char *sysname;
assert(device);
- assert(data);
assert(data->sysname || data->devlink);
assert(!data->device);
if (data->devlink) {
const char *devlink;
- FOREACH_DEVICE_DEVLINK(device, devlink)
- if (path_equal(devlink, data->devlink))
+ FOREACH_DEVICE_DEVLINK(device, link)
+ if (path_equal(link, data->devlink))
goto found;
if (sd_device_get_devname(device, &devlink) >= 0 && path_equal(devlink, data->devlink))
sd_device *_device,
const char *devlink,
const char *subsystem,
- usec_t deadline,
+ usec_t timeout_usec,
sd_device **ret) {
_cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL;
- _cleanup_(sd_event_source_unrefp) sd_event_source *timeout_source = NULL;
_cleanup_(sd_event_unrefp) sd_event *event = NULL;
/* Ensure that if !_device && devlink, device gets unrefd on errors since it will be new */
_cleanup_(sd_device_unrefp) sd_device *device = sd_device_ref(_device);
/* Devlink might already exist, if it does get the device to use the sysname filtering */
if (!device && devlink) {
- r = device_new_from_dev_path(devlink, &device);
- if (r < 0 && r != -ENOENT)
- return r;
+ r = sd_device_new_from_devname(&device, devlink);
+ if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r))
+ return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink);
}
if (device) {
return log_error_errno(r, "Failed to add %s subsystem match to monitor: %m", subsystem);
}
+ _cleanup_free_ char *desc = NULL;
+ const char *sysname = NULL;
+ if (device)
+ (void) sd_device_get_sysname(device, &sysname);
+
+ desc = strjoin(sysname ?: subsystem, devlink ? ":" : ":initialization", devlink);
+ if (desc)
+ (void) sd_device_monitor_set_description(monitor, desc);
+
r = sd_device_monitor_attach_event(monitor, event);
if (r < 0)
return log_error_errno(r, "Failed to attach event to device monitor: %m");
if (r < 0)
return log_error_errno(r, "Failed to start device monitor: %m");
- if (deadline != USEC_INFINITY) {
- r = sd_event_add_time(
- event, &timeout_source,
- CLOCK_MONOTONIC, deadline, 0,
+ if (timeout_usec != USEC_INFINITY) {
+ r = sd_event_add_time_relative(
+ event, NULL,
+ CLOCK_MONOTONIC, timeout_usec, 0,
NULL, INT_TO_PTR(-ETIMEDOUT));
if (r < 0)
return log_error_errno(r, "Failed to add timeout event source: %m");
}
- /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized
- * yet. */
+ /* Check again, maybe things changed. Udev will re-read the db if the device wasn't initialized yet. */
if (!device && devlink) {
- r = device_new_from_dev_path(devlink, &device);
- if (r < 0 && r != -ENOENT)
- return r;
+ r = sd_device_new_from_devname(&device, devlink);
+ if (r < 0 && !ERRNO_IS_DEVICE_ABSENT(r))
+ return log_error_errno(r, "Failed to create sd-device object from %s: %m", devlink);
}
if (device && sd_device_get_is_initialized(device) > 0) {
if (ret)
return 0;
}
-int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t deadline, sd_device **ret) {
- return device_wait_for_initialization_internal(device, NULL, subsystem, deadline, ret);
+int device_wait_for_initialization(sd_device *device, const char *subsystem, usec_t timeout_usec, sd_device **ret) {
+ return device_wait_for_initialization_internal(device, NULL, subsystem, timeout_usec, ret);
}
-int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t deadline, sd_device **ret) {
- return device_wait_for_initialization_internal(NULL, devlink, subsystem, deadline, ret);
+int device_wait_for_devlink(const char *devlink, const char *subsystem, usec_t timeout_usec, sd_device **ret) {
+ return device_wait_for_initialization_internal(NULL, devlink, subsystem, timeout_usec, ret);
}
int device_is_renaming(sd_device *dev) {
str += is_escaped;
if (str[0] != '"')
return -EINVAL;
- str++;
if (!is_escaped) {
/* unescape double quotation '\"'->'"' */
- for (i = j = str; *i != '"'; i++, j++) {
+ for (j = str, i = str + 1; *i != '"'; i++, j++) {
if (*i == '\0')
return -EINVAL;
if (i[0] == '\\' && i[1] == '"')
*j = *i;
}
j[0] = '\0';
+ /*
+ * The return value must be terminated by two subsequent NULs
+ * so it could be safely interpreted as nulstr.
+ */
+ j[1] = '\0';
} else {
_cleanup_free_ char *unescaped = NULL;
ssize_t l;
/* find the end position of value */
- for (i = str; *i != '"'; i++) {
+ for (i = str + 1; *i != '"'; i++) {
if (i[0] == '\\')
i++;
if (*i == '\0')
}
i[0] = '\0';
- l = cunescape_length(str, i - str, 0, &unescaped);
+ l = cunescape_length(str + 1, i - (str + 1), 0, &unescaped);
if (l < 0)
return l;
- assert(l <= i - str);
+ assert(l <= i - (str + 1));
memcpy(str, unescaped, l + 1);
+ /*
+ * The return value must be terminated by two subsequent NULs
+ * so it could be safely interpreted as nulstr.
+ */
+ str[l + 1] = '\0';
}
*ret_value = str;
}
int udev_queue_init(void) {
- _cleanup_close_ int fd = -1;
+ _cleanup_close_ int fd = -EBADF;
fd = inotify_init1(IN_CLOEXEC);
if (fd < 0)
return TAKE_FD(fd);
}
-static int device_is_power_sink(sd_device *device) {
- _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
- bool found_source = false, found_sink = false;
- sd_device *parent, *d;
- int r;
-
- assert(device);
-
- /* USB-C power supply device has two power roles: source or sink. See,
- * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-typec */
-
- r = sd_device_enumerator_new(&e);
- if (r < 0)
- return r;
-
- r = sd_device_enumerator_allow_uninitialized(e);
- if (r < 0)
- return r;
-
- r = sd_device_enumerator_add_match_subsystem(e, "typec", true);
- if (r < 0)
- return r;
-
- r = sd_device_get_parent(device, &parent);
- if (r < 0)
- return r;
-
- r = sd_device_enumerator_add_match_parent(e, parent);
- if (r < 0)
- return r;
-
- FOREACH_DEVICE(e, d) {
- const char *val;
-
- r = sd_device_get_sysattr_value(d, "power_role", &val);
- if (r < 0) {
- if (r != -ENOENT)
- log_device_debug_errno(d, r, "Failed to read 'power_role' sysfs attribute, ignoring: %m");
- continue;
- }
-
- if (strstr(val, "[source]")) {
- found_source = true;
- log_device_debug(d, "The USB type-C port is in power source mode.");
- } else if (strstr(val, "[sink]")) {
- found_sink = true;
- log_device_debug(d, "The USB type-C port is in power sink mode.");
- }
- }
-
- if (found_sink)
- log_device_debug(device, "The USB type-C device has at least one port in power sink mode.");
- else if (!found_source)
- log_device_debug(device, "The USB type-C device has no port in power source mode, assuming the device is in power sink mode.");
- else
- log_device_debug(device, "All USB type-C ports are in power source mode.");
-
- return found_sink || !found_source;
-}
-
-int on_ac_power(void) {
- _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL;
- bool found_offline = false, found_online = false;
- sd_device *d;
- int r;
-
- r = sd_device_enumerator_new(&e);
- if (r < 0)
- return r;
-
- r = sd_device_enumerator_allow_uninitialized(e);
- if (r < 0)
- return r;
-
- r = sd_device_enumerator_add_match_subsystem(e, "power_supply", true);
- if (r < 0)
- return r;
-
- FOREACH_DEVICE(e, d) {
- const char *val;
- unsigned v;
-
- r = sd_device_get_sysattr_value(d, "type", &val);
- if (r < 0) {
- log_device_debug_errno(d, r, "Failed to read 'type' sysfs attribute, ignoring: %m");
- continue;
- }
-
- /* We assume every power source is AC, except for batteries. See
- * https://github.com/torvalds/linux/blob/4eef766b7d4d88f0b984781bc1bcb574a6eafdc7/include/linux/power_supply.h#L176
- * for defined power source types. Also see:
- * https://docs.kernel.org/admin-guide/abi-testing.html#abi-file-testing-sysfs-class-power */
- if (streq(val, "Battery")) {
- log_device_debug(d, "The power supply is battery, ignoring.");
- continue;
- }
-
- /* Ignore USB-C power supply in source mode. See issue #21988. */
- if (streq(val, "USB")) {
- r = device_is_power_sink(d);
- if (r <= 0) {
- if (r < 0)
- log_device_debug_errno(d, r, "Failed to determine the current power role, ignoring: %m");
- else
- log_device_debug(d, "USB power supply is in source mode, ignoring.");
- continue;
- }
- }
-
- r = sd_device_get_sysattr_value(d, "online", &val);
- if (r < 0) {
- log_device_debug_errno(d, r, "Failed to read 'online' sysfs attribute, ignoring: %m");
- continue;
- }
-
- r = safe_atou(val, &v);
- if (r < 0) {
- log_device_debug_errno(d, r, "Failed to parse 'online' attribute, ignoring: %m");
- continue;
- }
-
- if (v > 0) /* At least 1 and 2 are defined as different types of 'online' */
- found_online = true;
- else
- found_offline = true;
-
- log_device_debug(d, "The power supply is currently %s.", v > 0 ? "online" : "offline");
- }
-
- if (found_online)
- log_debug("Found at least one online non-battery power supply, system is running on AC power.");
- else if (!found_offline)
- log_debug("Found no offline non-battery power supply, assuming system is running on AC power.");
- else
- log_debug("All non-battery power supplies are offline, assuming system is running with battery.");
-
- return found_online || !found_offline;
-}
-
bool udev_available(void) {
static int cache = -1;