+/* SPDX-License-Identifier: LGPL-2.1+ */
/***
This file is part of systemd.
#include "device-internal.h"
#include "device-private.h"
#include "device-util.h"
+#include "dirent-util.h"
#include "fd-util.h"
#include "fileio.h"
#include "fs-util.h"
}
if (verify) {
- r = readlink_and_canonicalize(_syspath, &syspath);
+ r = readlink_and_canonicalize(_syspath, NULL, &syspath);
if (r == -ENOENT)
/* the device does not exist (any more?) */
return -ENODEV;
/* this is not a valid device */
return -ENODEV;
- log_debug("sd-device: %s does not have an uevent file: %m", syspath);
- return -errno;
+ return log_debug_errno(errno, "sd-device: %s does not have an uevent file: %m", syspath);
}
} else {
/* everything else just needs to be a directory */
return -ENOMEM;
}
- devpath = syspath + strlen("/sys");
+ devpath = syspath + STRLEN("/sys");
r = device_add_property_internal(device, "DEVPATH", devpath);
if (r < 0)
return r;
- free(device->syspath);
- device->syspath = syspath;
- syspath = NULL;
+ free_and_replace(device->syspath, syspath);
device->devpath = devpath;
char id[DECIMAL_STR_MAX(unsigned) * 2 + 1];
assert_return(ret, -EINVAL);
- assert_return(type == 'b' || type == 'c', -EINVAL);
+ 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));
if (access(syspath, F_OK) >= 0)
return sd_device_new_from_syspath(ret, syspath);
+ syspath = strjoina("/sys/firmware/", subsystem, "/", sysname);
+ if (access(syspath, F_OK) >= 0)
+ return sd_device_new_from_syspath(ret, syspath);
+
return -ENODEV;
}
if (r < 0)
return r;
- free(device->devtype);
- device->devtype = devtype;
- devtype = NULL;
+ free_and_replace(device->devtype, devtype);
return 0;
}
if (r < 0)
return r;
- free(device->devname);
- device->devname = devname;
- devname = NULL;
+ free_and_replace(device->devname, devname);
return 0;
}
value = &uevent[i];
state = VALUE;
- /* fall through to handle empty property */
+ _fallthrough_; /* to handle empty property */
case VALUE:
if (strchr(NEWLINE, uevent[i])) {
uevent[i] = '\0';
path = strdup(syspath);
if (!path)
return -ENOMEM;
- subdir = path + strlen("/sys");
+ subdir = path + STRLEN("/sys");
for (;;) {
char *pos;
if (r < 0)
return r;
- free(device->subsystem);
- device->subsystem = subsystem;
- subsystem = NULL;
+ free_and_replace(device->subsystem, subsystem);
device->subsystem_set = true;
if (r < 0)
return r;
- free(device->driver_subsystem);
- device->driver_subsystem = subsystem;
- subsystem = NULL;
+ free_and_replace(device->driver_subsystem, subsystem);
return 0;
}
if (r < 0)
return r;
- free(device->driver);
- device->driver = driver;
- driver = NULL;
+ free_and_replace(device->driver, driver);
device->driver_set = true;
if (len == 0)
sysnum = NULL;
- free(device->sysname);
- device->sysname = sysname;
- sysname = NULL;
+ free_and_replace(device->sysname, sysname);
device->sysnum = sysnum;
if (r < 0)
return r;
- for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
+ FOREACH_DIRENT_ALL(dent, dir, return -errno) {
char *path;
struct stat statbuf;
/* only handle symlinks and regular files */
- if (dent->d_type != DT_LNK && dent->d_type != DT_REG)
+ if (!IN_SET(dent->d_type, DT_LNK, DT_REG))
continue;
path = strjoina(syspath, "/", dent->d_name);
_cleanup_free_ char *value = NULL;
const char *syspath;
char *path;
- struct stat statbuf;
- size_t value_len = 0;
+ size_t len = 0;
ssize_t size;
int r;
return r;
path = strjoina(syspath, "/", sysattr);
- r = lstat(path, &statbuf);
- if (r < 0) {
+
+ fd = open(path, O_WRONLY | O_CLOEXEC | O_NOFOLLOW);
+ if (fd < 0) {
+ if (errno == ELOOP)
+ return -EINVAL;
+ if (errno == EISDIR)
+ return -EISDIR;
+
value = strdup("");
if (!value)
return -ENOMEM;
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
+ value = NULL;
return -ENXIO;
}
- if (S_ISLNK(statbuf.st_mode))
- return -EINVAL;
-
- /* skip directories */
- if (S_ISDIR(statbuf.st_mode))
- return -EISDIR;
-
- /* skip non-readable files */
- if ((statbuf.st_mode & S_IRUSR) == 0)
- return -EACCES;
-
- value_len = strlen(_value);
+ len = strlen(_value);
/* drop trailing newlines */
- while (value_len > 0 && _value[value_len - 1] == '\n')
- _value[--value_len] = '\0';
+ while (len > 0 && _value[len - 1] == '\n')
+ len --;
/* value length is limited to 4k */
- if (value_len > 4096)
+ if (len > 4096)
return -EINVAL;
- fd = open(path, O_WRONLY | O_CLOEXEC);
- if (fd < 0)
- return -errno;
-
- value = strdup(_value);
+ value = strndup(_value, len);
if (!value)
return -ENOMEM;
- size = write(fd, value, value_len);
+ size = write(fd, value, len);
if (size < 0)
return -errno;
- if ((size_t)size != value_len)
+ if ((size_t)size != len)
return -EIO;
r = device_add_sysattr_value(device, sysattr, value);
if (r < 0)
return r;
-
value = NULL;
return 0;