Merge pull request #9920 from yuwata/udev-cleanup-4

udev: drop unused udev structs and use verbs in udevadm
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2018-09-14 10:05:59 +02:00 committed by GitHub
commit 1327f272d3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
39 changed files with 1199 additions and 1910 deletions

2
TODO
View File

@ -15,8 +15,6 @@ Janitorial Clean-ups:
* rework mount.c and swap.c to follow proper state enumeration/deserialization * rework mount.c and swap.c to follow proper state enumeration/deserialization
semantics, like we do for device.c now semantics, like we do for device.c now
* udev: drop "collect", it's nonsense
Features: Features:
* optionally, if a per-partition GPT flag is set for the root/home/… partitions * optionally, if a per-partition GPT flag is set for the root/home/… partitions

View File

@ -66,6 +66,9 @@ void strbuf_complete(struct strbuf *str) {
/* clean up everything */ /* clean up everything */
void strbuf_cleanup(struct strbuf *str) { void strbuf_cleanup(struct strbuf *str) {
if (!str)
return;
strbuf_complete(str); strbuf_complete(str);
free(str->buf); free(str->buf);
free(str); free(str);

View File

@ -123,11 +123,9 @@ int util_log_priority(const char *priority);
size_t util_path_encode(const char *src, char *dest, size_t size); size_t util_path_encode(const char *src, char *dest, size_t size);
int util_replace_whitespace(const char *str, char *to, size_t len); int util_replace_whitespace(const char *str, char *to, size_t len);
int util_replace_chars(char *str, const char *white); int util_replace_chars(char *str, const char *white);
unsigned int util_string_hash32(const char *key); uint32_t util_string_hash32(const char *key);
uint64_t util_string_bloom64(const char *str); uint64_t util_string_bloom64(const char *str);
int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, int read_value);
/* libudev-util-private.c */
int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value);
/* Cleanup functions */ /* Cleanup functions */
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);

View File

@ -23,9 +23,8 @@
*/ */
/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */ /* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
int util_resolve_subsys_kernel(struct udev *udev, const char *string, int util_resolve_subsys_kernel(const char *string,
char *result, size_t maxsize, int read_value) char *result, size_t maxsize, int read_value) {
{
char temp[UTIL_PATH_SIZE]; char temp[UTIL_PATH_SIZE];
char *subsys; char *subsys;
char *sysname; char *sysname;
@ -58,7 +57,7 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
if (read_value && attr == NULL) if (read_value && attr == NULL)
return -1; return -1;
dev = udev_device_new_from_subsystem_sysname(udev, subsys, sysname); dev = udev_device_new_from_subsystem_sysname(NULL, subsys, sysname);
if (dev == NULL) if (dev == NULL)
return -1; return -1;
@ -85,8 +84,7 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
return 0; return 0;
} }
int util_log_priority(const char *priority) int util_log_priority(const char *priority) {
{
char *endptr; char *endptr;
int prio; int prio;
@ -101,8 +99,7 @@ int util_log_priority(const char *priority)
return log_level_from_string(priority); return log_level_from_string(priority);
} }
size_t util_path_encode(const char *src, char *dest, size_t size) size_t util_path_encode(const char *src, char *dest, size_t size) {
{
size_t i, j; size_t i, j;
for (i = 0, j = 0; src[i] != '\0'; i++) { for (i = 0, j = 0; src[i] != '\0'; i++) {
@ -147,8 +144,7 @@ size_t util_path_encode(const char *src, char *dest, size_t size)
* Note this may be called with 'str' == 'to', i.e. to replace whitespace * Note this may be called with 'str' == 'to', i.e. to replace whitespace
* in-place in a buffer. This function can handle that situation. * in-place in a buffer. This function can handle that situation.
*/ */
int util_replace_whitespace(const char *str, char *to, size_t len) int util_replace_whitespace(const char *str, char *to, size_t len) {
{
size_t i, j; size_t i, j;
/* strip trailing whitespace */ /* strip trailing whitespace */
@ -176,8 +172,7 @@ int util_replace_whitespace(const char *str, char *to, size_t len)
} }
/* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */ /* allow chars in whitelist, plain ascii, hex-escaping and valid utf8 */
int util_replace_chars(char *str, const char *white) int util_replace_chars(char *str, const char *white) {
{
size_t i = 0; size_t i = 0;
int replaced = 0; int replaced = 0;
@ -230,21 +225,18 @@ int util_replace_chars(char *str, const char *white)
* *
* Returns: 0 if the entire string was copied, non-zero otherwise. * Returns: 0 if the entire string was copied, non-zero otherwise.
**/ **/
_public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) _public_ int udev_util_encode_string(const char *str, char *str_enc, size_t len) {
{
return encode_devnode_name(str, str_enc, len); return encode_devnode_name(str, str_enc, len);
} }
unsigned int util_string_hash32(const char *str) uint32_t util_string_hash32(const char *str) {
{
return MurmurHash2(str, strlen(str), 0); return MurmurHash2(str, strlen(str), 0);
} }
/* get a bunch of bit numbers out of the hash, and set the bits in our bit field */ /* get a bunch of bit numbers out of the hash, and set the bits in our bit field */
uint64_t util_string_bloom64(const char *str) uint64_t util_string_bloom64(const char *str) {
{
uint64_t bits = 0; uint64_t bits = 0;
unsigned int hash = util_string_hash32(str); uint32_t hash = util_string_hash32(str);
bits |= 1LLU << (hash & 63); bits |= 1LLU << (hash & 63);
bits |= 1LLU << ((hash >> 6) & 63); bits |= 1LLU << ((hash >> 6) & 63);

View File

@ -52,7 +52,6 @@ static int fake_filesystems(void) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
_cleanup_(udev_unrefp) struct udev *udev = NULL;
_cleanup_(udev_event_unrefp) struct udev_event *event = NULL; _cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL; _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL; _cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
@ -68,10 +67,6 @@ int main(int argc, char *argv[]) {
if (err < 0) if (err < 0)
return EXIT_FAILURE; return EXIT_FAILURE;
udev = udev_new();
if (udev == NULL)
return EXIT_FAILURE;
log_debug("version %s", PACKAGE_VERSION); log_debug("version %s", PACKAGE_VERSION);
mac_selinux_init(); mac_selinux_init();
@ -87,10 +82,10 @@ int main(int argc, char *argv[]) {
goto out; goto out;
} }
rules = udev_rules_new(udev, 1); rules = udev_rules_new(1);
strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL); strscpyl(syspath, sizeof(syspath), "/sys", devpath, NULL);
dev = udev_device_new_from_synthetic_event(udev, syspath, action); dev = udev_device_new_from_synthetic_event(NULL, syspath, action);
if (dev == NULL) { if (dev == NULL) {
log_debug("unknown device '%s'", devpath); log_debug("unknown device '%s'", devpath);
goto out; goto out;

View File

@ -23,8 +23,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "libudev.h"
#include "fd-util.h" #include "fd-util.h"
#include "libudev-private.h" #include "libudev-private.h"
#include "log.h" #include "log.h"
@ -32,14 +30,13 @@
#define COMMAND_TIMEOUT_MSEC (30 * 1000) #define COMMAND_TIMEOUT_MSEC (30 * 1000)
static int disk_scsi_inquiry_command(int fd, static int disk_scsi_inquiry_command(
void *buf, int fd,
size_t buf_len) void *buf,
{ size_t buf_len) {
uint8_t cdb[6] = { uint8_t cdb[6] = {
/* /* INQUIRY, see SPC-4 section 6.4 */
* INQUIRY, see SPC-4 section 6.4
*/
[0] = 0x12, /* OPERATION CODE: INQUIRY */ [0] = 0x12, /* OPERATION CODE: INQUIRY */
[3] = (buf_len >> 8), /* ALLOCATION LENGTH */ [3] = (buf_len >> 8), /* ALLOCATION LENGTH */
[4] = (buf_len & 0xff), [4] = (buf_len & 0xff),
@ -101,10 +98,11 @@ static int disk_scsi_inquiry_command(int fd,
return 0; return 0;
} }
static int disk_identify_command(int fd, static int disk_identify_command(
void *buf, int fd,
size_t buf_len) void *buf,
{ size_t buf_len) {
uint8_t cdb[12] = { uint8_t cdb[12] = {
/* /*
* ATA Pass-Through 12 byte command, as described in * ATA Pass-Through 12 byte command, as described in
@ -171,10 +169,11 @@ static int disk_identify_command(int fd,
return 0; return 0;
} }
static int disk_identify_packet_device_command(int fd, static int disk_identify_packet_device_command(
void *buf, int fd,
size_t buf_len) void *buf,
{ size_t buf_len) {
uint8_t cdb[16] = { uint8_t cdb[16] = {
/* /*
* ATA Pass-Through 16 byte command, as described in * ATA Pass-Through 16 byte command, as described in
@ -256,11 +255,12 @@ static int disk_identify_packet_device_command(int fd,
* *
* Copies the ATA string from @identify located at @offset_words into @dest. * Copies the ATA string from @identify located at @offset_words into @dest.
*/ */
static void disk_identify_get_string(uint8_t identify[512], static void disk_identify_get_string(
unsigned int offset_words, uint8_t identify[512],
char *dest, unsigned int offset_words,
size_t dest_len) char *dest,
{ size_t dest_len) {
unsigned int c1; unsigned int c1;
unsigned int c2; unsigned int c2;
@ -276,16 +276,15 @@ static void disk_identify_get_string(uint8_t identify[512],
} }
} }
static void disk_identify_fixup_string(uint8_t identify[512], static void disk_identify_fixup_string(
unsigned int offset_words, uint8_t identify[512],
size_t len) unsigned int offset_words,
{ size_t len) {
disk_identify_get_string(identify, offset_words, disk_identify_get_string(identify, offset_words,
(char *) identify + offset_words * 2, len); (char *) identify + offset_words * 2, len);
} }
static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words) static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offset_words) {
{
uint16_t *p; uint16_t *p;
p = (uint16_t *) identify; p = (uint16_t *) identify;
@ -294,7 +293,6 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
/** /**
* disk_identify: * disk_identify:
* @udev: The libudev context.
* @fd: File descriptor for the block device. * @fd: File descriptor for the block device.
* @out_identify: Return location for IDENTIFY data. * @out_identify: Return location for IDENTIFY data.
* @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE. * @out_is_packet_device: Return location for whether returned data is from a IDENTIFY PACKET DEVICE.
@ -308,11 +306,9 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
* Returns: 0 if the data was successfully obtained, otherwise * Returns: 0 if the data was successfully obtained, otherwise
* non-zero with errno set. * non-zero with errno set.
*/ */
static int disk_identify(struct udev *udev, static int disk_identify(int fd,
int fd,
uint8_t out_identify[512], uint8_t out_identify[512],
int *out_is_packet_device) int *out_is_packet_device) {
{
int ret; int ret;
uint8_t inquiry_buf[36]; uint8_t inquiry_buf[36];
int peripheral_device_type; int peripheral_device_type;
@ -390,7 +386,6 @@ out:
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
_cleanup_(udev_unrefp) struct udev *udev = NULL;
struct hd_driveid id; struct hd_driveid id;
union { union {
uint8_t byte[512]; uint8_t byte[512];
@ -416,10 +411,6 @@ int main(int argc, char *argv[]) {
log_parse_environment(); log_parse_environment();
log_open(); log_open();
udev = udev_new();
if (udev == NULL)
return 0;
for (;;) { for (;;) {
int option; int option;
@ -451,7 +442,7 @@ int main(int argc, char *argv[]) {
return 1; return 1;
} }
if (disk_identify(udev, fd, identify.byte, &is_packet_device) == 0) { if (disk_identify(fd, identify.byte, &is_packet_device) == 0) {
/* /*
* fix up only the fields from the IDENTIFY data that we are going to * fix up only the fields from the IDENTIFY data that we are going to
* use and copy it into the hd_driveid struct for convenience * use and copy it into the hd_driveid struct for convenience

View File

@ -20,11 +20,10 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "libudev.h" #include "log.h"
#include "libudev-private.h"
#include "random-util.h" #include "random-util.h"
#include "udev-util.h" #include "udev-util.h"
#include "util.h"
/* device info */ /* device info */
static unsigned int cd_cd_rom; static unsigned int cd_cd_rom;
@ -86,8 +85,7 @@ static unsigned long long int cd_media_session_last_offset;
#define ASC(errcode) (((errcode) >> 8) & 0xFF) #define ASC(errcode) (((errcode) >> 8) & 0xFF)
#define ASCQ(errcode) ((errcode) & 0xFF) #define ASCQ(errcode) ((errcode) & 0xFF)
static bool is_mounted(const char *device) static bool is_mounted(const char *device) {
{
struct stat statbuf; struct stat statbuf;
FILE *fp; FILE *fp;
int maj, min; int maj, min;
@ -109,8 +107,7 @@ static bool is_mounted(const char *device)
return mounted; return mounted;
} }
static void info_scsi_cmd_err(struct udev *udev, const char *cmd, int err) static void info_scsi_cmd_err(const char *cmd, int err) {
{
if (err == -1) { if (err == -1) {
log_debug("%s failed", cmd); log_debug("%s failed", cmd);
return; return;
@ -127,8 +124,7 @@ struct scsi_cmd {
struct sg_io_hdr sg_io; struct sg_io_hdr sg_io;
}; };
static void scsi_cmd_init(struct udev *udev, struct scsi_cmd *cmd) static void scsi_cmd_init(struct scsi_cmd *cmd) {
{
memzero(cmd, sizeof(struct scsi_cmd)); memzero(cmd, sizeof(struct scsi_cmd));
cmd->cgc.quiet = 1; cmd->cgc.quiet = 1;
cmd->cgc.sense = &cmd->_sense.s; cmd->cgc.sense = &cmd->_sense.s;
@ -139,16 +135,14 @@ static void scsi_cmd_init(struct udev *udev, struct scsi_cmd *cmd)
cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO; cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO;
} }
static void scsi_cmd_set(struct udev *udev, struct scsi_cmd *cmd, size_t i, unsigned char arg) static void scsi_cmd_set(struct scsi_cmd *cmd, size_t i, unsigned char arg) {
{
cmd->sg_io.cmd_len = i + 1; cmd->sg_io.cmd_len = i + 1;
cmd->cgc.cmd[i] = arg; cmd->cgc.cmd[i] = arg;
} }
#define CHECK_CONDITION 0x01 #define CHECK_CONDITION 0x01
static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) static int scsi_cmd_run(struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) {
{
int ret = 0; int ret = 0;
if (bufsize > 0) { if (bufsize > 0) {
@ -173,8 +167,7 @@ static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigne
return ret; return ret;
} }
static int media_lock(struct udev *udev, int fd, bool lock) static int media_lock(int fd, bool lock) {
{
int err; int err;
/* disable the kernel's lock logic */ /* disable the kernel's lock logic */
@ -189,25 +182,23 @@ static int media_lock(struct udev *udev, int fd, bool lock)
return err; return err;
} }
static int media_eject(struct udev *udev, int fd) static int media_eject(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
int err; int err;
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x1b); scsi_cmd_set(&sc, 0, 0x1b);
scsi_cmd_set(udev, &sc, 4, 0x02); scsi_cmd_set(&sc, 4, 0x02);
scsi_cmd_set(udev, &sc, 5, 0); scsi_cmd_set(&sc, 5, 0);
err = scsi_cmd_run(udev, &sc, fd, NULL, 0); err = scsi_cmd_run(&sc, fd, NULL, 0);
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "START_STOP_UNIT", err); info_scsi_cmd_err("START_STOP_UNIT", err);
return -1; return -1;
} }
return 0; return 0;
} }
static int cd_capability_compat(struct udev *udev, int fd) static int cd_capability_compat(int fd) {
{
int capability; int capability;
capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL); capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL);
@ -233,8 +224,7 @@ static int cd_capability_compat(struct udev *udev, int fd)
return 0; return 0;
} }
static int cd_media_compat(struct udev *udev, int fd) static int cd_media_compat(int fd) {
{
if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) { if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) {
log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK"); log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK");
return -1; return -1;
@ -243,19 +233,18 @@ static int cd_media_compat(struct udev *udev, int fd)
return 0; return 0;
} }
static int cd_inquiry(struct udev *udev, int fd) static int cd_inquiry(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
unsigned char inq[128]; unsigned char inq[128];
int err; int err;
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x12); scsi_cmd_set(&sc, 0, 0x12);
scsi_cmd_set(udev, &sc, 4, 36); scsi_cmd_set(&sc, 4, 36);
scsi_cmd_set(udev, &sc, 5, 0); scsi_cmd_set(&sc, 5, 0);
err = scsi_cmd_run(udev, &sc, fd, inq, 36); err = scsi_cmd_run(&sc, fd, inq, 36);
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "INQUIRY", err); info_scsi_cmd_err("INQUIRY", err);
return -1; return -1;
} }
@ -268,8 +257,7 @@ static int cd_inquiry(struct udev *udev, int fd)
return 0; return 0;
} }
static void feature_profile_media(struct udev *udev, int cur_profile) static void feature_profile_media(int cur_profile) {
{
switch (cur_profile) { switch (cur_profile) {
case 0x03: case 0x03:
case 0x04: case 0x04:
@ -377,8 +365,7 @@ static void feature_profile_media(struct udev *udev, int cur_profile)
} }
} }
static int feature_profiles(struct udev *udev, const unsigned char *profiles, size_t size) static int feature_profiles(const unsigned char *profiles, size_t size) {
{
unsigned int i; unsigned int i;
for (i = 0; i+4 <= size; i += 4) { for (i = 0; i+4 <= size; i += 4) {
@ -467,20 +454,19 @@ static int feature_profiles(struct udev *udev, const unsigned char *profiles, si
} }
/* returns 0 if media was detected */ /* returns 0 if media was detected */
static int cd_profiles_old_mmc(struct udev *udev, int fd) static int cd_profiles_old_mmc(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
int err; int err;
unsigned char header[32]; unsigned char header[32];
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x51); scsi_cmd_set(&sc, 0, 0x51);
scsi_cmd_set(udev, &sc, 8, sizeof(header)); scsi_cmd_set(&sc, 8, sizeof(header));
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); err = scsi_cmd_run(&sc, fd, header, sizeof(header));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); info_scsi_cmd_err("READ DISC INFORMATION", err);
if (cd_media == 1) { if (cd_media == 1) {
log_debug("no current profile, but disc is present; assuming CD-ROM"); log_debug("no current profile, but disc is present; assuming CD-ROM");
cd_media_cd_rom = 1; cd_media_cd_rom = 1;
@ -509,8 +495,7 @@ static int cd_profiles_old_mmc(struct udev *udev, int fd)
} }
/* returns 0 if media was detected */ /* returns 0 if media was detected */
static int cd_profiles(struct udev *udev, int fd) static int cd_profiles(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
unsigned char features[65530]; unsigned char features[65530];
unsigned int cur_profile = 0; unsigned int cur_profile = 0;
@ -522,18 +507,18 @@ static int cd_profiles(struct udev *udev, int fd)
ret = -1; ret = -1;
/* First query the current profile */ /* First query the current profile */
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(&sc, 0, 0x46);
scsi_cmd_set(udev, &sc, 8, 8); scsi_cmd_set(&sc, 8, 8);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, features, 8); err = scsi_cmd_run(&sc, fd, features, 8);
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "GET CONFIGURATION", err); info_scsi_cmd_err("GET CONFIGURATION", err);
/* handle pre-MMC2 drives which do not support GET CONFIGURATION */ /* handle pre-MMC2 drives which do not support GET CONFIGURATION */
if (SK(err) == 0x5 && IN_SET(ASC(err), 0x20, 0x24)) { if (SK(err) == 0x5 && IN_SET(ASC(err), 0x20, 0x24)) {
log_debug("drive is pre-MMC2 and does not support 46h get configuration command"); log_debug("drive is pre-MMC2 and does not support 46h get configuration command");
log_debug("trying to work around the problem"); log_debug("trying to work around the problem");
ret = cd_profiles_old_mmc(udev, fd); ret = cd_profiles_old_mmc(fd);
} }
goto out; goto out;
} }
@ -541,7 +526,7 @@ static int cd_profiles(struct udev *udev, int fd)
cur_profile = features[6] << 8 | features[7]; cur_profile = features[6] << 8 | features[7];
if (cur_profile > 0) { if (cur_profile > 0) {
log_debug("current profile 0x%02x", cur_profile); log_debug("current profile 0x%02x", cur_profile);
feature_profile_media (udev, cur_profile); feature_profile_media(cur_profile);
ret = 0; /* we have media */ ret = 0; /* we have media */
} else { } else {
log_debug("no current profile, assuming no media"); log_debug("no current profile, assuming no media");
@ -557,14 +542,14 @@ static int cd_profiles(struct udev *udev, int fd)
len = sizeof(features); len = sizeof(features);
/* Now get the full feature buffer */ /* Now get the full feature buffer */
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(&sc, 0, 0x46);
scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff); scsi_cmd_set(&sc, 7, ( len >> 8 ) & 0xff);
scsi_cmd_set(udev, &sc, 8, len & 0xff); scsi_cmd_set(&sc, 8, len & 0xff);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, features, len); err = scsi_cmd_run(&sc, fd, features, len);
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "GET CONFIGURATION", err); info_scsi_cmd_err("GET CONFIGURATION", err);
return -1; return -1;
} }
@ -586,7 +571,7 @@ static int cd_profiles(struct udev *udev, int fd)
switch (feature) { switch (feature) {
case 0x00: case 0x00:
log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features[i+3] / 4); log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features[i+3] / 4);
feature_profiles(udev, &features[i]+4, MIN(features[i+3], len - i - 4)); feature_profiles(&features[i]+4, MIN(features[i+3], len - i - 4));
break; break;
default: default:
log_debug("GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes", feature, features[i+3]); log_debug("GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes", feature, features[i+3]);
@ -597,8 +582,7 @@ out:
return ret; return ret;
} }
static int cd_media_info(struct udev *udev, int fd) static int cd_media_info(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
unsigned char header[32]; unsigned char header[32];
static const char *media_status[] = { static const char *media_status[] = {
@ -609,13 +593,13 @@ static int cd_media_info(struct udev *udev, int fd)
}; };
int err; int err;
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x51); scsi_cmd_set(&sc, 0, 0x51);
scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); err = scsi_cmd_run(&sc, fd, header, sizeof(header));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); info_scsi_cmd_err("READ DISC INFORMATION", err);
return -1; return -1;
}; };
@ -647,14 +631,14 @@ static int cd_media_info(struct udev *udev, int fd)
unsigned char dvdstruct[8]; unsigned char dvdstruct[8];
unsigned char format[12]; unsigned char format[12];
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0xAD); scsi_cmd_set(&sc, 0, 0xAD);
scsi_cmd_set(udev, &sc, 7, 0xC0); scsi_cmd_set(&sc, 7, 0xC0);
scsi_cmd_set(udev, &sc, 9, sizeof(dvdstruct)); scsi_cmd_set(&sc, 9, sizeof(dvdstruct));
scsi_cmd_set(udev, &sc, 11, 0); scsi_cmd_set(&sc, 11, 0);
err = scsi_cmd_run(udev, &sc, fd, dvdstruct, sizeof(dvdstruct)); err = scsi_cmd_run(&sc, fd, dvdstruct, sizeof(dvdstruct));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ DVD STRUCTURE", err); info_scsi_cmd_err("READ DVD STRUCTURE", err);
return -1; return -1;
} }
if (dvdstruct[4] & 0x02) { if (dvdstruct[4] & 0x02) {
@ -664,13 +648,13 @@ static int cd_media_info(struct udev *udev, int fd)
} }
/* let's make sure we don't try to read unformatted media */ /* let's make sure we don't try to read unformatted media */
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x23); scsi_cmd_set(&sc, 0, 0x23);
scsi_cmd_set(udev, &sc, 8, sizeof(format)); scsi_cmd_set(&sc, 8, sizeof(format));
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, format, sizeof(format)); err = scsi_cmd_run(&sc, fd, format, sizeof(format));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ DVD FORMAT CAPACITIES", err); info_scsi_cmd_err("READ DVD FORMAT CAPACITIES", err);
return -1; return -1;
} }
@ -705,15 +689,15 @@ static int cd_media_info(struct udev *udev, int fd)
* has "blank" status", DVD-RAM was examined earlier) and check * has "blank" status", DVD-RAM was examined earlier) and check
* for ISO and UDF PVDs or a fs superblock presence and do it * for ISO and UDF PVDs or a fs superblock presence and do it
* in one ioctl (we need just sectors 0 and 16) */ * in one ioctl (we need just sectors 0 and 16) */
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x28); scsi_cmd_set(&sc, 0, 0x28);
scsi_cmd_set(udev, &sc, 5, 0); scsi_cmd_set(&sc, 5, 0);
scsi_cmd_set(udev, &sc, 8, 32); scsi_cmd_set(&sc, 8, 32);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, buffer, sizeof(buffer)); err = scsi_cmd_run(&sc, fd, buffer, sizeof(buffer));
if ((err != 0)) { if ((err != 0)) {
cd_media = 0; cd_media = 0;
info_scsi_cmd_err(udev, "READ FIRST 32 BLOCKS", err); info_scsi_cmd_err("READ FIRST 32 BLOCKS", err);
return -1; return -1;
} }
@ -750,8 +734,7 @@ determined:
return 0; return 0;
} }
static int cd_media_toc(struct udev *udev, int fd) static int cd_media_toc(int fd) {
{
struct scsi_cmd sc; struct scsi_cmd sc;
unsigned char header[12]; unsigned char header[12];
unsigned char toc[65536]; unsigned char toc[65536];
@ -759,14 +742,14 @@ static int cd_media_toc(struct udev *udev, int fd)
unsigned char *p; unsigned char *p;
int err; int err;
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(&sc, 0, 0x43);
scsi_cmd_set(udev, &sc, 6, 1); scsi_cmd_set(&sc, 6, 1);
scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); err = scsi_cmd_run(&sc, fd, header, sizeof(header));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ TOC", err); info_scsi_cmd_err("READ TOC", err);
return -1; return -1;
} }
@ -783,15 +766,15 @@ static int cd_media_toc(struct udev *udev, int fd)
if (len < 8) if (len < 8)
return 0; return 0;
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(&sc, 0, 0x43);
scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */ scsi_cmd_set(&sc, 6, header[2]); /* First Track/Session Number */
scsi_cmd_set(udev, &sc, 7, (len >> 8) & 0xff); scsi_cmd_set(&sc, 7, (len >> 8) & 0xff);
scsi_cmd_set(udev, &sc, 8, len & 0xff); scsi_cmd_set(&sc, 8, len & 0xff);
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, toc, len); err = scsi_cmd_run(&sc, fd, toc, len);
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ TOC (tracks)", err); info_scsi_cmd_err("READ TOC (tracks)", err);
return -1; return -1;
} }
@ -814,14 +797,14 @@ static int cd_media_toc(struct udev *udev, int fd)
cd_media_track_count_audio++; cd_media_track_count_audio++;
} }
scsi_cmd_init(udev, &sc); scsi_cmd_init(&sc);
scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(&sc, 0, 0x43);
scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */ scsi_cmd_set(&sc, 2, 1); /* Session Info */
scsi_cmd_set(udev, &sc, 8, sizeof(header)); scsi_cmd_set(&sc, 8, sizeof(header));
scsi_cmd_set(udev, &sc, 9, 0); scsi_cmd_set(&sc, 9, 0);
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); err = scsi_cmd_run(&sc, fd, header, sizeof(header));
if ((err != 0)) { if ((err != 0)) {
info_scsi_cmd_err(udev, "READ TOC (multi session)", err); info_scsi_cmd_err("READ TOC (multi session)", err);
return -1; return -1;
} }
len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7]; len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7];
@ -831,7 +814,6 @@ static int cd_media_toc(struct udev *udev, int fd)
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
struct udev *udev;
static const struct option options[] = { static const struct option options[] = {
{ "lock-media", no_argument, NULL, 'l' }, { "lock-media", no_argument, NULL, 'l' },
{ "unlock-media", no_argument, NULL, 'u' }, { "unlock-media", no_argument, NULL, 'u' },
@ -853,10 +835,6 @@ int main(int argc, char *argv[]) {
log_parse_environment(); log_parse_environment();
log_open(); log_open();
udev = udev_new();
if (udev == NULL)
goto exit;
for (;;) { for (;;) {
int option; int option;
@ -896,7 +874,6 @@ int main(int argc, char *argv[]) {
node = argv[optind]; node = argv[optind];
if (!node) { if (!node) {
log_error("no device"); log_error("no device");
fprintf(stderr, "no device\n");
rc = 1; rc = 1;
goto exit; goto exit;
} }
@ -914,55 +891,54 @@ int main(int argc, char *argv[]) {
} }
if (fd < 0) { if (fd < 0) {
log_debug("unable to open '%s'", node); log_debug("unable to open '%s'", node);
fprintf(stderr, "unable to open '%s'\n", node);
rc = 1; rc = 1;
goto exit; goto exit;
} }
log_debug("probing: '%s'", node); log_debug("probing: '%s'", node);
/* same data as original cdrom_id */ /* same data as original cdrom_id */
if (cd_capability_compat(udev, fd) < 0) { if (cd_capability_compat(fd) < 0) {
rc = 1; rc = 1;
goto exit; goto exit;
} }
/* check for media - don't bail if there's no media as we still need to /* check for media - don't bail if there's no media as we still need to
* to read profiles */ * to read profiles */
cd_media_compat(udev, fd); cd_media_compat(fd);
/* check if drive talks MMC */ /* check if drive talks MMC */
if (cd_inquiry(udev, fd) < 0) if (cd_inquiry(fd) < 0)
goto work; goto work;
/* read drive and possibly current profile */ /* read drive and possibly current profile */
if (cd_profiles(udev, fd) != 0) if (cd_profiles(fd) != 0)
goto work; goto work;
/* at this point we are guaranteed to have media in the drive - find out more about it */ /* at this point we are guaranteed to have media in the drive - find out more about it */
/* get session/track info */ /* get session/track info */
cd_media_toc(udev, fd); cd_media_toc(fd);
/* get writable media state */ /* get writable media state */
cd_media_info(udev, fd); cd_media_info(fd);
work: work:
/* lock the media, so we enable eject button events */ /* lock the media, so we enable eject button events */
if (lock && cd_media) { if (lock && cd_media) {
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)"); log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)");
media_lock(udev, fd, true); media_lock(fd, true);
} }
if (unlock && cd_media) { if (unlock && cd_media) {
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
media_lock(udev, fd, false); media_lock(fd, false);
} }
if (eject) { if (eject) {
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)"); log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
media_lock(udev, fd, false); media_lock(fd, false);
log_debug("START_STOP_UNIT (eject)"); log_debug("START_STOP_UNIT (eject)");
media_eject(udev, fd); media_eject(fd);
} }
printf("ID_CDROM=1\n"); printf("ID_CDROM=1\n");
@ -1067,7 +1043,6 @@ work:
exit: exit:
if (fd >= 0) if (fd >= 0)
close(fd); close(fd);
udev_unref(udev);
log_close(); log_close();
return rc; return rc;
} }

View File

@ -1,478 +0,0 @@
/* SPDX-License-Identifier: GPL-2.0+ */
/*
* Collect variables across events.
*
* usage: collect [--add|--remove] <checkpoint> <id> <idlist>
*
* Adds ID <id> to the list governed by <checkpoint>.
* <id> must be part of the ID list <idlist>.
* If all IDs given by <idlist> are listed (ie collect has been
* invoked for each ID in <idlist>) collect returns 0, the
* number of missing IDs otherwise.
* A negative number is returned on error.
*
* Copyright © 2007, Hannes Reinecke <hare@suse.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*/
#include <errno.h>
#include <getopt.h>
#include <stddef.h>
#include <stdio.h>
#include "alloc-util.h"
#include "libudev-private.h"
#include "macro.h"
#include "stdio-util.h"
#include "string-util.h"
#include "udev-util.h"
#define BUFSIZE 16
#define UDEV_ALARM_TIMEOUT 180
enum collect_state {
STATE_NONE,
STATE_OLD,
STATE_CONFIRMED,
};
struct _mate {
struct udev_list_node node;
char *name;
enum collect_state state;
};
static struct udev_list_node bunch;
static int debug;
/* This can increase dynamically */
static size_t bufsize = BUFSIZE;
static inline struct _mate *node_to_mate(struct udev_list_node *node)
{
return container_of(node, struct _mate, node);
}
_noreturn_ static void sig_alrm(int signo)
{
_exit(4);
}
static void usage(void)
{
printf("%s [options] <checkpoint> <id> <idlist>\n\n"
"Collect variables across events.\n\n"
" -h --help Print this message\n"
" -a --add Add ID <id> to the list <idlist>\n"
" -r --remove Remove ID <id> from the list <idlist>\n"
" -d --debug Debug to stderr\n\n"
" Adds ID <id> to the list governed by <checkpoint>.\n"
" <id> must be part of the list <idlist>.\n"
" If all IDs given by <idlist> are listed (ie collect has been\n"
" invoked for each ID in <idlist>) collect returns 0, the\n"
" number of missing IDs otherwise.\n"
" On error a negative number is returned.\n\n"
, program_invocation_short_name);
}
/*
* prepare
*
* Prepares the database file
*/
static int prepare(char *dir, char *filename)
{
char buf[PATH_MAX];
int r, fd;
r = mkdir(dir, 0700);
if (r < 0 && errno != EEXIST)
return -errno;
snprintf(buf, sizeof buf, "%s/%s", dir, filename);
fd = open(buf, O_RDWR|O_CREAT|O_CLOEXEC, S_IRUSR|S_IWUSR);
if (fd < 0)
fprintf(stderr, "Cannot open %s: %m\n", buf);
if (lockf(fd,F_TLOCK,0) < 0) {
if (debug)
fprintf(stderr, "Lock taken, wait for %d seconds\n", UDEV_ALARM_TIMEOUT);
if (IN_SET(errno, EAGAIN, EACCES)) {
alarm(UDEV_ALARM_TIMEOUT);
lockf(fd, F_LOCK, 0);
if (debug)
fprintf(stderr, "Acquired lock on %s\n", buf);
} else {
if (debug)
fprintf(stderr, "Could not get lock on %s: %m\n", buf);
}
}
return fd;
}
/*
* Read checkpoint file
*
* Tricky reading this. We allocate a buffer twice as large
* as we're going to read. Then we read into the upper half
* of that buffer and start parsing.
* Once we do _not_ find end-of-work terminator (whitespace
* character) we move the upper half to the lower half,
* adjust the read pointer and read the next bit.
* Quite clever methinks :-)
* I should become a programmer ...
*
* Yes, one could have used fgets() for this. But then we'd
* have to use freopen etc which I found quite tedious.
*/
static int checkout(int fd)
{
int len;
_cleanup_free_ char *buf = NULL;
char *ptr, *word = NULL;
struct _mate *him;
restart:
len = bufsize >> 1;
buf = malloc(bufsize + 1);
if (!buf)
return log_oom();
memset(buf, ' ', bufsize);
buf[bufsize] = '\0';
ptr = buf + len;
while ((read(fd, buf + len, len)) > 0) {
while (ptr && *ptr) {
word = ptr;
ptr = strpbrk(word," \n\t\r");
if (!ptr && word < (buf + len)) {
bufsize = bufsize << 1;
if (debug)
fprintf(stderr, "ID overflow, restarting with size %zu\n", bufsize);
lseek(fd, 0, SEEK_SET);
goto restart;
}
if (ptr) {
*ptr = '\0';
ptr++;
if (isempty(word))
continue;
if (debug)
fprintf(stderr, "Found word %s\n", word);
him = malloc(sizeof (struct _mate));
if (!him)
return log_oom();
him->name = strdup(word);
if (!him->name) {
free(him);
return log_oom();
}
him->state = STATE_OLD;
udev_list_node_append(&him->node, &bunch);
word = NULL;
}
}
memcpy(buf, buf + len, len);
memset(buf + len, ' ', len);
if (!ptr)
ptr = word;
ptr -= len;
}
return 0;
}
/*
* invite
*
* Adds a new ID 'us' to the internal list,
* marks it as confirmed.
*/
static void invite(char *us)
{
struct udev_list_node *him_node;
struct _mate *who = NULL;
if (debug)
fprintf(stderr, "Adding ID '%s'\n", us);
udev_list_node_foreach(him_node, &bunch) {
struct _mate *him = node_to_mate(him_node);
if (streq(him->name, us)) {
him->state = STATE_CONFIRMED;
who = him;
}
}
if (debug && !who)
fprintf(stderr, "ID '%s' not in database\n", us);
}
/*
* reject
*
* Marks the ID 'us' as invalid,
* causing it to be removed when the
* list is written out.
*/
static void reject(char *us)
{
struct udev_list_node *him_node;
struct _mate *who = NULL;
if (debug)
fprintf(stderr, "Removing ID '%s'\n", us);
udev_list_node_foreach(him_node, &bunch) {
struct _mate *him = node_to_mate(him_node);
if (streq(him->name, us)) {
him->state = STATE_NONE;
who = him;
}
}
if (debug && !who)
fprintf(stderr, "ID '%s' not in database\n", us);
}
/*
* kickout
*
* Remove all IDs in the internal list which are not part
* of the list passed via the command line.
*/
static void kickout(void)
{
struct udev_list_node *him_node;
struct udev_list_node *tmp;
udev_list_node_foreach_safe(him_node, tmp, &bunch) {
struct _mate *him = node_to_mate(him_node);
if (him->state == STATE_OLD) {
udev_list_node_remove(&him->node);
free(him->name);
free(him);
}
}
}
/*
* missing
*
* Counts all missing IDs in the internal list.
*/
static int missing(int fd)
{
char *buf;
int ret = 0;
struct udev_list_node *him_node;
buf = malloc(bufsize);
if (!buf)
return log_oom();
udev_list_node_foreach(him_node, &bunch) {
struct _mate *him = node_to_mate(him_node);
if (him->state == STATE_NONE) {
ret++;
} else {
while (strlen(him->name)+1 >= bufsize) {
char *tmpbuf;
bufsize = bufsize << 1;
tmpbuf = realloc(buf, bufsize);
if (!tmpbuf) {
free(buf);
return log_oom();
}
buf = tmpbuf;
}
snprintf(buf, strlen(him->name)+2, "%s ", him->name);
if (write(fd, buf, strlen(buf)) < 0) {
free(buf);
return -1;
}
}
}
free(buf);
return ret;
}
/*
* everybody
*
* Prints out the status of the internal list.
*/
static void everybody(void)
{
struct udev_list_node *him_node;
const char *state = "";
udev_list_node_foreach(him_node, &bunch) {
struct _mate *him = node_to_mate(him_node);
switch (him->state) {
case STATE_NONE:
state = "none";
break;
case STATE_OLD:
state = "old";
break;
case STATE_CONFIRMED:
state = "confirmed";
break;
}
fprintf(stderr, "ID: %s=%s\n", him->name, state);
}
}
int main(int argc, char **argv) {
static const struct option options[] = {
{ "add", no_argument, NULL, 'a' },
{ "remove", no_argument, NULL, 'r' },
{ "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' },
{}
};
int argi;
char *checkpoint, *us;
int fd;
int i;
int ret = EXIT_SUCCESS;
int prune = 0;
char tmpdir[UTIL_PATH_SIZE];
log_set_target(LOG_TARGET_AUTO);
udev_parse_config();
log_parse_environment();
log_open();
for (;;) {
int option;
option = getopt_long(argc, argv, "ardh", options, NULL);
if (option == -1)
break;
switch (option) {
case 'a':
prune = 0;
break;
case 'r':
prune = 1;
break;
case 'd':
debug = 1;
break;
case 'h':
usage();
return 0;
default:
return 1;
}
}
argi = optind;
if (argi + 2 > argc) {
printf("Missing parameter(s)\n");
return 1;
}
checkpoint = argv[argi++];
us = argv[argi++];
if (signal(SIGALRM, sig_alrm) == SIG_ERR) {
fprintf(stderr, "Cannot set SIGALRM: %m\n");
return 2;
}
udev_list_node_init(&bunch);
if (debug)
fprintf(stderr, "Using checkpoint '%s'\n", checkpoint);
strscpyl(tmpdir, sizeof(tmpdir), "/run/udev/collect", NULL);
fd = prepare(tmpdir, checkpoint);
if (fd < 0) {
ret = 3;
goto out;
}
if (checkout(fd) < 0) {
ret = 2;
goto out;
}
for (i = argi; i < argc; i++) {
struct udev_list_node *him_node;
struct _mate *who;
who = NULL;
udev_list_node_foreach(him_node, &bunch) {
struct _mate *him = node_to_mate(him_node);
if (streq(him->name, argv[i]))
who = him;
}
if (!who) {
struct _mate *him;
if (debug)
fprintf(stderr, "ID %s: not in database\n", argv[i]);
him = new(struct _mate, 1);
if (!him) {
ret = ENOMEM;
goto out;
}
him->name = strdup(argv[i]);
if (!him->name) {
free(him);
ret = ENOMEM;
goto out;
}
him->state = STATE_NONE;
udev_list_node_append(&him->node, &bunch);
} else {
if (debug)
fprintf(stderr, "ID %s: found in database\n", argv[i]);
who->state = STATE_CONFIRMED;
}
}
if (prune)
reject(us);
else
invite(us);
if (debug) {
everybody();
fprintf(stderr, "Prune lists\n");
}
kickout();
lseek(fd, 0, SEEK_SET);
ftruncate(fd, 0);
ret = missing(fd);
lockf(fd, F_ULOCK, 0);
close(fd);
out:
if (debug)
everybody();
if (ret >= 0)
printf("COLLECT_%s=%d\n", checkpoint, ret);
return ret;
}

View File

@ -2,14 +2,15 @@
udevadm_sources = files(''' udevadm_sources = files('''
udevadm.c udevadm.c
udevadm-info.c udevadm.h
udevadm-control.c udevadm-control.c
udevadm-monitor.c
udevadm-hwdb.c udevadm-hwdb.c
udevadm-info.c
udevadm-monitor.c
udevadm-settle.c udevadm-settle.c
udevadm-trigger.c
udevadm-test.c udevadm-test.c
udevadm-test-builtin.c udevadm-test-builtin.c
udevadm-trigger.c
udevadm-util.c udevadm-util.c
udevadm-util.h udevadm-util.h
'''.split()) '''.split())
@ -159,7 +160,6 @@ libudev_core = static_library(
foreach prog : [['ata_id/ata_id.c'], foreach prog : [['ata_id/ata_id.c'],
['cdrom_id/cdrom_id.c'], ['cdrom_id/cdrom_id.c'],
['collect/collect.c'],
['scsi_id/scsi_id.c', ['scsi_id/scsi_id.c',
'scsi_id/scsi_id.h', 'scsi_id/scsi_id.h',
'scsi_id/scsi_serial.c', 'scsi_id/scsi_serial.c',

View File

@ -2,6 +2,7 @@
#include <netinet/ether.h> #include <netinet/ether.h>
#include "sd-device.h"
#include "sd-netlink.h" #include "sd-netlink.h"
#include "alloc-util.h" #include "alloc-util.h"
@ -9,8 +10,6 @@
#include "conf-parser.h" #include "conf-parser.h"
#include "ethtool-util.h" #include "ethtool-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "libudev-device-internal.h"
#include "libudev-private.h"
#include "link-config.h" #include "link-config.h"
#include "log.h" #include "log.h"
#include "missing.h" #include "missing.h"
@ -218,8 +217,7 @@ bool link_config_should_reload(link_config_ctx *ctx) {
return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false); return paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, false);
} }
int link_config_get(link_config_ctx *ctx, struct udev_device *device, int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
link_config **ret) {
link_config *link; link_config *link;
assert(ctx); assert(ctx);
@ -227,43 +225,50 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device,
assert(ret); assert(ret);
LIST_FOREACH(links, link, ctx->links) { LIST_FOREACH(links, link, ctx->links) {
const char* attr_value; const char *address = NULL, *id_path = NULL, *parent_driver = NULL, *id_net_driver = NULL, *devtype = NULL, *sysname = NULL;
sd_device *parent;
attr_value = udev_device_get_sysattr_value(device, "address"); (void) sd_device_get_sysattr_value(device, "address", &address);
(void) sd_device_get_property_value(device, "ID_PATH", &id_path);
if (sd_device_get_parent(device, &parent) >= 0)
(void) sd_device_get_driver(parent, &parent_driver);
(void) sd_device_get_property_value(device, "ID_NET_DRIVER", &id_net_driver);
(void) sd_device_get_devtype(device, &devtype);
(void) sd_device_get_sysname(device, &sysname);
if (net_match_config(link->match_mac, link->match_path, link->match_driver, if (net_match_config(link->match_mac, link->match_path, link->match_driver,
link->match_type, link->match_name, link->match_host, link->match_type, link->match_name, link->match_host,
link->match_virt, link->match_kernel_cmdline, link->match_virt, link->match_kernel_cmdline,
link->match_kernel_version, link->match_arch, link->match_kernel_version, link->match_arch,
attr_value ? ether_aton(attr_value) : NULL, address ? ether_aton(address) : NULL,
udev_device_get_property_value(device, "ID_PATH"), id_path,
udev_device_get_driver(udev_device_get_parent(device)), parent_driver,
udev_device_get_property_value(device, "ID_NET_DRIVER"), id_net_driver,
udev_device_get_devtype(device), devtype,
udev_device_get_sysname(device))) { sysname)) {
if (link->match_name) { if (link->match_name) {
unsigned char name_assign_type = NET_NAME_UNKNOWN; unsigned char name_assign_type = NET_NAME_UNKNOWN;
const char *attr_value;
attr_value = udev_device_get_sysattr_value(device, "name_assign_type"); if (sd_device_get_sysattr_value(device, "name_assign_type", &attr_value) >= 0)
if (attr_value)
(void) safe_atou8(attr_value, &name_assign_type); (void) safe_atou8(attr_value, &name_assign_type);
if (name_assign_type == NET_NAME_ENUM) { if (name_assign_type == NET_NAME_ENUM) {
log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'", log_warning("Config file %s applies to device based on potentially unpredictable interface name '%s'",
link->filename, udev_device_get_sysname(device)); link->filename, sysname);
*ret = link; *ret = link;
return 0; return 0;
} else if (name_assign_type == NET_NAME_RENAMED) { } else if (name_assign_type == NET_NAME_RENAMED) {
log_warning("Config file %s matches device based on renamed interface name '%s', ignoring", log_warning("Config file %s matches device based on renamed interface name '%s', ignoring",
link->filename, udev_device_get_sysname(device)); link->filename, sysname);
continue; continue;
} }
} }
log_debug("Config file %s applies to device %s", log_debug("Config file %s applies to device %s",
link->filename, udev_device_get_sysname(device)); link->filename, sysname);
*ret = link; *ret = link;
@ -276,14 +281,13 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device,
return -ENOENT; return -ENOENT;
} }
static bool mac_is_random(struct udev_device *device) { static bool mac_is_random(sd_device *device) {
const char *s; const char *s;
unsigned type; unsigned type;
int r; int r;
/* if we can't get the assign type, assume it is not random */ /* if we can't get the assign type, assume it is not random */
s = udev_device_get_sysattr_value(device, "addr_assign_type"); if (sd_device_get_sysattr_value(device, "addr_assign_type", &s) < 0)
if (!s)
return false; return false;
r = safe_atou(s, &type); r = safe_atou(s, &type);
@ -293,14 +297,13 @@ static bool mac_is_random(struct udev_device *device) {
return type == NET_ADDR_RANDOM; return type == NET_ADDR_RANDOM;
} }
static bool should_rename(struct udev_device *device, bool respect_predictable) { static bool should_rename(sd_device *device, bool respect_predictable) {
const char *s; const char *s;
unsigned type; unsigned type;
int r; int r;
/* if we can't get the assgin type, assume we should rename */ /* if we can't get the assgin type, assume we should rename */
s = udev_device_get_sysattr_value(device, "name_assign_type"); if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
if (!s)
return true; return true;
r = safe_atou(s, &type); r = safe_atou(s, &type);
@ -324,7 +327,7 @@ static bool should_rename(struct udev_device *device, bool respect_predictable)
} }
} }
static int get_mac(struct udev_device *device, bool want_random, static int get_mac(sd_device *device, bool want_random,
struct ether_addr *mac) { struct ether_addr *mac) {
int r; int r;
@ -333,7 +336,7 @@ static int get_mac(struct udev_device *device, bool want_random,
else { else {
uint64_t result; uint64_t result;
r = net_get_unique_predictable_data(device->device, &result); r = net_get_unique_predictable_data(device, &result);
if (r < 0) if (r < 0)
return r; return r;
@ -349,7 +352,7 @@ static int get_mac(struct udev_device *device, bool want_random,
} }
int link_config_apply(link_config_ctx *ctx, link_config *config, int link_config_apply(link_config_ctx *ctx, link_config *config,
struct udev_device *device, const char **name) { sd_device *device, const char **name) {
bool respect_predictable = false; bool respect_predictable = false;
struct ether_addr generated_mac; struct ether_addr generated_mac;
struct ether_addr *mac = NULL; struct ether_addr *mac = NULL;
@ -363,9 +366,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
assert(device); assert(device);
assert(name); assert(name);
old_name = udev_device_get_sysname(device); r = sd_device_get_sysname(device, &old_name);
if (!old_name) if (r < 0)
return -EINVAL; return r;
r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config); r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config);
if (r < 0) { if (r < 0) {
@ -397,11 +400,11 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
log_warning_errno(r, "Could not set channels of %s: %m", old_name); log_warning_errno(r, "Could not set channels of %s: %m", old_name);
} }
ifindex = udev_device_get_ifindex(device); r = sd_device_get_ifindex(device, &ifindex);
if (ifindex <= 0) { if (r < 0)
log_warning("Could not find ifindex"); return log_warning_errno(r, "Could not find ifindex: %m");
return -ENODEV; if (ifindex <= 0)
} return log_warning_errno(EINVAL, "Invalid ifindex '%d'", ifindex);
if (ctx->enable_name_policy && config->name_policy) { if (ctx->enable_name_policy && config->name_policy) {
NamePolicy *policy; NamePolicy *policy;
@ -413,19 +416,19 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
respect_predictable = true; respect_predictable = true;
break; break;
case NAMEPOLICY_DATABASE: case NAMEPOLICY_DATABASE:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE"); (void) sd_device_get_property_value(device, "ID_NET_NAME_FROM_DATABASE", &new_name);
break; break;
case NAMEPOLICY_ONBOARD: case NAMEPOLICY_ONBOARD:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_ONBOARD"); (void) sd_device_get_property_value(device, "ID_NET_NAME_ONBOARD", &new_name);
break; break;
case NAMEPOLICY_SLOT: case NAMEPOLICY_SLOT:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_SLOT"); (void) sd_device_get_property_value(device, "ID_NET_NAME_SLOT", &new_name);
break; break;
case NAMEPOLICY_PATH: case NAMEPOLICY_PATH:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_PATH"); (void) sd_device_get_property_value(device, "ID_NET_NAME_PATH", &new_name);
break; break;
case NAMEPOLICY_MAC: case NAMEPOLICY_MAC:
new_name = udev_device_get_property_value(device, "ID_NET_NAME_MAC"); (void) sd_device_get_property_value(device, "ID_NET_NAME_MAC", &new_name);
break; break;
default: default:
break; break;
@ -477,14 +480,14 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
return 0; return 0;
} }
int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret) { int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret) {
const char *name; const char *name;
char *driver = NULL; char *driver = NULL;
int r; int r;
name = udev_device_get_sysname(device); r = sd_device_get_sysname(device, &name);
if (!name) if (r < 0)
return -EINVAL; return r;
r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver); r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
if (r < 0) if (r < 0)

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#pragma once #pragma once
#include "libudev.h" #include "sd-device.h"
#include "condition.h" #include "condition.h"
#include "ethtool-util.h" #include "ethtool-util.h"
@ -68,10 +68,9 @@ void link_config_ctx_free(link_config_ctx *ctx);
int link_config_load(link_config_ctx *ctx); int link_config_load(link_config_ctx *ctx);
bool link_config_should_reload(link_config_ctx *ctx); bool link_config_should_reload(link_config_ctx *ctx);
int link_config_get(link_config_ctx *ctx, struct udev_device *device, struct link_config **ret); int link_config_get(link_config_ctx *ctx, sd_device *device, struct link_config **ret);
int link_config_apply(link_config_ctx *ctx, struct link_config *config, struct udev_device *device, const char **name); int link_config_apply(link_config_ctx *ctx, struct link_config *config, sd_device *device, const char **name);
int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret);
int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **ret);
const char *name_policy_to_string(NamePolicy p) _const_; const char *name_policy_to_string(NamePolicy p) _const_;
NamePolicy name_policy_from_string(const char *p) _pure_; NamePolicy name_policy_from_string(const char *p) _pure_;

View File

@ -17,8 +17,6 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "libudev.h"
#include "alloc-util.h" #include "alloc-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "libudev-private.h" #include "libudev-private.h"
@ -55,8 +53,7 @@ static char model_enc_str[256];
static char revision_str[16]; static char revision_str[16];
static char type_str[16]; static char type_str[16];
static void set_type(const char *from, char *to, size_t len) static void set_type(const char *from, char *to, size_t len) {
{
int type_num; int type_num;
char *eptr; char *eptr;
const char *type = "generic"; const char *type = "generic";
@ -101,8 +98,7 @@ static void set_type(const char *from, char *to, size_t len)
* Return a pointer to the NUL terminated string, returns NULL if no * Return a pointer to the NUL terminated string, returns NULL if no
* matches. * matches.
*/ */
static char *get_value(char **buffer) static char *get_value(char **buffer) {
{
static const char *quote_string = "\"\n"; static const char *quote_string = "\"\n";
static const char *comma_string = ",\n"; static const char *comma_string = ",\n";
char *val; char *val;
@ -130,8 +126,7 @@ static char *get_value(char **buffer)
return val; return val;
} }
static int argc_count(char *opts) static int argc_count(char *opts) {
{
int i = 0; int i = 0;
while (*opts != '\0') while (*opts != '\0')
if (*opts++ == ' ') if (*opts++ == ' ')
@ -148,10 +143,8 @@ static int argc_count(char *opts)
* *
* vendor and model can end in '\n'. * vendor and model can end in '\n'.
*/ */
static int get_file_options(struct udev *udev, static int get_file_options(const char *vendor, const char *model,
const char *vendor, const char *model, int *argc, char ***newargv) {
int *argc, char ***newargv)
{
_cleanup_free_ char *buffer = NULL; _cleanup_free_ char *buffer = NULL;
_cleanup_fclose_ FILE *f; _cleanup_fclose_ FILE *f;
char *buf; char *buf;
@ -311,10 +304,8 @@ static void help(void) {
} }
static int set_options(struct udev *udev, static int set_options(int argc, char **argv,
int argc, char **argv, char *maj_min_dev) {
char *maj_min_dev)
{
int option; int option;
/* /*
@ -400,9 +391,7 @@ static int set_options(struct udev *udev,
return 0; return 0;
} }
static int per_dev_options(struct udev *udev, static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) {
struct scsi_id_device *dev_scsi, int *good_bad, int *page_code)
{
int retval; int retval;
int newargc; int newargc;
char **newargv = NULL; char **newargv = NULL;
@ -411,7 +400,7 @@ static int per_dev_options(struct udev *udev,
*good_bad = all_good; *good_bad = all_good;
*page_code = default_page_code; *page_code = default_page_code;
retval = get_file_options(udev, vendor_str, model_str, &newargc, &newargv); retval = get_file_options(vendor_str, model_str, &newargc, &newargv);
optind = 1; /* reset this global extern */ optind = 1; /* reset this global extern */
while (retval == 0) { while (retval == 0) {
@ -455,13 +444,12 @@ static int per_dev_options(struct udev *udev,
return retval; return retval;
} }
static int set_inq_values(struct udev *udev, struct scsi_id_device *dev_scsi, const char *path) static int set_inq_values(struct scsi_id_device *dev_scsi, const char *path) {
{
int retval; int retval;
dev_scsi->use_sg = sg_version; dev_scsi->use_sg = sg_version;
retval = scsi_std_inquiry(udev, dev_scsi, path); retval = scsi_std_inquiry(dev_scsi, path);
if (retval) if (retval)
return retval; return retval;
@ -482,27 +470,26 @@ static int set_inq_values(struct udev *udev, struct scsi_id_device *dev_scsi, co
* scsi_id: try to get an id, if one is found, printf it to stdout. * scsi_id: try to get an id, if one is found, printf it to stdout.
* returns a value passed to exit() - 0 if printed an id, else 1. * returns a value passed to exit() - 0 if printed an id, else 1.
*/ */
static int scsi_id(struct udev *udev, char *maj_min_dev) static int scsi_id(char *maj_min_dev) {
{
struct scsi_id_device dev_scsi = {}; struct scsi_id_device dev_scsi = {};
int good_dev; int good_dev;
int page_code; int page_code;
int retval = 0; int retval = 0;
if (set_inq_values(udev, &dev_scsi, maj_min_dev) < 0) { if (set_inq_values(&dev_scsi, maj_min_dev) < 0) {
retval = 1; retval = 1;
goto out; goto out;
} }
/* get per device (vendor + model) options from the config file */ /* get per device (vendor + model) options from the config file */
per_dev_options(udev, &dev_scsi, &good_dev, &page_code); per_dev_options(&dev_scsi, &good_dev, &page_code);
if (!good_dev) { if (!good_dev) {
retval = 1; retval = 1;
goto out; goto out;
} }
/* read serial number from mode pages (no values for optical drives) */ /* read serial number from mode pages (no values for optical drives) */
scsi_get_serial(udev, &dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN); scsi_get_serial(&dev_scsi, maj_min_dev, page_code, MAX_SERIAL_LEN);
if (export) { if (export) {
char serial_str[MAX_SERIAL_LEN]; char serial_str[MAX_SERIAL_LEN];
@ -557,7 +544,6 @@ out:
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
_cleanup_(udev_unrefp) struct udev *udev;
int retval = 0; int retval = 0;
char maj_min_dev[MAX_PATH_LEN]; char maj_min_dev[MAX_PATH_LEN];
int newargc; int newargc;
@ -568,14 +554,10 @@ int main(int argc, char **argv) {
log_parse_environment(); log_parse_environment();
log_open(); log_open();
udev = udev_new();
if (udev == NULL)
goto exit;
/* /*
* Get config file options. * Get config file options.
*/ */
retval = get_file_options(udev, NULL, NULL, &newargc, &newargv); retval = get_file_options(NULL, NULL, &newargc, &newargv);
if (retval < 0) { if (retval < 0) {
retval = 1; retval = 1;
goto exit; goto exit;
@ -583,7 +565,7 @@ int main(int argc, char **argv) {
if (retval == 0) { if (retval == 0) {
assert(newargv); assert(newargv);
if (set_options(udev, newargc, newargv, maj_min_dev) < 0) { if (set_options(newargc, newargv, maj_min_dev) < 0) {
retval = 2; retval = 2;
goto exit; goto exit;
} }
@ -592,7 +574,7 @@ int main(int argc, char **argv) {
/* /*
* Get command line options (overriding any config file settings). * Get command line options (overriding any config file settings).
*/ */
if (set_options(udev, argc, argv, maj_min_dev) < 0) if (set_options(argc, argv, maj_min_dev) < 0)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
if (!dev_specified) { if (!dev_specified) {
@ -601,7 +583,7 @@ int main(int argc, char **argv) {
goto exit; goto exit;
} }
retval = scsi_id(udev, maj_min_dev); retval = scsi_id(maj_min_dev);
exit: exit:
if (newargv) { if (newargv) {

View File

@ -48,8 +48,8 @@ struct scsi_id_device {
char tgpt_group[8]; char tgpt_group[8];
}; };
int scsi_std_inquiry(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname); int scsi_std_inquiry(struct scsi_id_device *dev_scsi, const char *devname);
int scsi_get_serial(struct udev *udev, struct scsi_id_device *dev_scsi, const char *devname, int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname,
int page_code, int len); int page_code, int len);
/* /*

View File

@ -21,13 +21,11 @@
#include <time.h> #include <time.h>
#include <unistd.h> #include <unistd.h>
#include "libudev.h"
#include "libudev-private.h"
#include "random-util.h" #include "random-util.h"
#include "scsi.h" #include "scsi.h"
#include "scsi_id.h" #include "scsi_id.h"
#include "string-util.h" #include "string-util.h"
#include "util.h"
/* /*
* A priority based list of id, naa, and binary/ascii for the identifier * A priority based list of id, naa, and binary/ascii for the identifier
@ -85,15 +83,12 @@ static const char hex_str[]="0123456789abcdef";
#define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */ #define SG_ERR_CAT_SENSE 98 /* Something else in the sense buffer */
#define SG_ERR_CAT_OTHER 99 /* Some other error/warning */ #define SG_ERR_CAT_OTHER 99 /* Some other error/warning */
static int do_scsi_page80_inquiry(struct udev *udev, static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd,
char *serial, char *serial_short, int max_len); char *serial, char *serial_short, int max_len);
static int sg_err_category_new(struct udev *udev, static int sg_err_category_new(int scsi_status, int msg_status, int
int scsi_status, int msg_status, int
host_status, int driver_status, const host_status, int driver_status, const
unsigned char *sense_buffer, int sb_len) unsigned char *sense_buffer, int sb_len) {
{
scsi_status &= 0x7e; scsi_status &= 0x7e;
/* /*
@ -140,35 +135,26 @@ static int sg_err_category_new(struct udev *udev,
return SG_ERR_CAT_OTHER; return SG_ERR_CAT_OTHER;
} }
static int sg_err_category3(struct udev *udev, struct sg_io_hdr *hp) static int sg_err_category3(struct sg_io_hdr *hp) {
{ return sg_err_category_new(hp->status, hp->msg_status,
return sg_err_category_new(udev,
hp->status, hp->msg_status,
hp->host_status, hp->driver_status, hp->host_status, hp->driver_status,
hp->sbp, hp->sb_len_wr); hp->sbp, hp->sb_len_wr);
} }
static int sg_err_category4(struct udev *udev, struct sg_io_v4 *hp) static int sg_err_category4(struct sg_io_v4 *hp) {
{ return sg_err_category_new(hp->device_status, 0,
return sg_err_category_new(udev, hp->device_status, 0,
hp->transport_status, hp->driver_status, hp->transport_status, hp->driver_status,
(unsigned char *)(uintptr_t)hp->response, (unsigned char *)(uintptr_t)hp->response,
hp->response_len); hp->response_len);
} }
static int scsi_dump_sense(struct udev *udev, static int scsi_dump_sense(struct scsi_id_device *dev_scsi,
struct scsi_id_device *dev_scsi, unsigned char *sense_buffer, int sb_len) {
unsigned char *sense_buffer, int sb_len)
{
int s; int s;
int code; int code;
int sense_class; int sense_class;
int sense_key; int sense_key;
int asc, ascq; int asc, ascq;
#ifdef DUMP_SENSE
char out_buffer[256];
int i, j;
#endif
/* /*
* Figure out and print the sense key, asc and ascq. * Figure out and print the sense key, asc and ascq.
@ -240,23 +226,10 @@ static int scsi_dump_sense(struct udev *udev,
} }
#ifdef DUMP_SENSE
for (i = 0, j = 0; (i < s) && (j < 254); i++) {
out_buffer[j++] = hex_str[(sense_buffer[i] & 0xf0) >> 4];
out_buffer[j++] = hex_str[sense_buffer[i] & 0x0f];
out_buffer[j++] = ' ';
}
out_buffer[j] = '\0';
log_debug("%s: sense dump:", dev_scsi->kernel);
log_debug("%s: %s", dev_scsi->kernel, out_buffer);
#endif
return -1; return -1;
} }
static int scsi_dump(struct udev *udev, static int scsi_dump(struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) {
struct scsi_id_device *dev_scsi, struct sg_io_hdr *io)
{
if (!io->status && !io->host_status && !io->msg_status && if (!io->status && !io->host_status && !io->msg_status &&
!io->driver_status) { !io->driver_status) {
/* /*
@ -269,14 +242,12 @@ static int scsi_dump(struct udev *udev,
log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x", log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x 0x%x",
dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status); dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
if (io->status == SCSI_CHECK_CONDITION) if (io->status == SCSI_CHECK_CONDITION)
return scsi_dump_sense(udev, dev_scsi, io->sbp, io->sb_len_wr); return scsi_dump_sense(dev_scsi, io->sbp, io->sb_len_wr);
else else
return -1; return -1;
} }
static int scsi_dump_v4(struct udev *udev, static int scsi_dump_v4(struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) {
struct scsi_id_device *dev_scsi, struct sg_io_v4 *io)
{
if (!io->device_status && !io->transport_status && if (!io->device_status && !io->transport_status &&
!io->driver_status) { !io->driver_status) {
/* /*
@ -289,17 +260,15 @@ static int scsi_dump_v4(struct udev *udev,
log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x", log_debug("%s: sg_io failed status 0x%x 0x%x 0x%x",
dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status); dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status);
if (io->device_status == SCSI_CHECK_CONDITION) if (io->device_status == SCSI_CHECK_CONDITION)
return scsi_dump_sense(udev, dev_scsi, (unsigned char *)(uintptr_t)io->response, return scsi_dump_sense(dev_scsi, (unsigned char *)(uintptr_t)io->response,
io->response_len); io->response_len);
else else
return -1; return -1;
} }
static int scsi_inquiry(struct udev *udev, static int scsi_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd,
unsigned char evpd, unsigned char page, unsigned char evpd, unsigned char page,
unsigned char *buf, unsigned int buflen) unsigned char *buf, unsigned int buflen) {
{
unsigned char inq_cmd[INQUIRY_CMDLEN] = unsigned char inq_cmd[INQUIRY_CMDLEN] =
{ INQUIRY_CMD, evpd, page, 0, buflen, 0 }; { INQUIRY_CMD, evpd, page, 0, buflen, 0 };
unsigned char sense[SENSE_BUFF_LEN]; unsigned char sense[SENSE_BUFF_LEN];
@ -352,9 +321,9 @@ resend:
} }
if (dev_scsi->use_sg == 4) if (dev_scsi->use_sg == 4)
retval = sg_err_category4(udev, io_buf); retval = sg_err_category4(io_buf);
else else
retval = sg_err_category3(udev, io_buf); retval = sg_err_category3(io_buf);
switch (retval) { switch (retval) {
case SG_ERR_CAT_NOTSUPPORTED: case SG_ERR_CAT_NOTSUPPORTED:
@ -367,9 +336,9 @@ resend:
default: default:
if (dev_scsi->use_sg == 4) if (dev_scsi->use_sg == 4)
retval = scsi_dump_v4(udev, dev_scsi, io_buf); retval = scsi_dump_v4(dev_scsi, io_buf);
else else
retval = scsi_dump(udev, dev_scsi, io_buf); retval = scsi_dump(dev_scsi, io_buf);
} }
if (!retval) { if (!retval) {
@ -389,14 +358,12 @@ error:
} }
/* Get list of supported EVPD pages */ /* Get list of supported EVPD pages */
static int do_scsi_page0_inquiry(struct udev *udev, static int do_scsi_page0_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd, unsigned char *buffer, unsigned int len) {
unsigned char *buffer, unsigned int len)
{
int retval; int retval;
memzero(buffer, len); memzero(buffer, len);
retval = scsi_inquiry(udev, dev_scsi, fd, 1, 0x0, buffer, len); retval = scsi_inquiry(dev_scsi, fd, 1, 0x0, buffer, len);
if (retval < 0) if (retval < 0)
return 1; return 1;
@ -433,9 +400,7 @@ static int do_scsi_page0_inquiry(struct udev *udev,
* The caller checks that serial is long enough to include the vendor + * The caller checks that serial is long enough to include the vendor +
* model. * model.
*/ */
static int prepend_vendor_model(struct udev *udev, static int prepend_vendor_model(struct scsi_id_device *dev_scsi, char *serial) {
struct scsi_id_device *dev_scsi, char *serial)
{
int ind; int ind;
strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH); strncpy(serial, dev_scsi->vendor, VENDOR_LENGTH);
@ -458,14 +423,12 @@ static int prepend_vendor_model(struct udev *udev,
* check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill * check_fill_0x83_id - check the page 0x83 id, if OK allocate and fill
* serial number. * serial number.
*/ */
static int check_fill_0x83_id(struct udev *udev, static int check_fill_0x83_id(struct scsi_id_device *dev_scsi,
struct scsi_id_device *dev_scsi,
unsigned char *page_83, unsigned char *page_83,
const struct scsi_id_search_values const struct scsi_id_search_values
*id_search, char *serial, char *serial_short, *id_search, char *serial, char *serial_short,
int max_len, char *wwn, int max_len, char *wwn,
char *wwn_vendor_extension, char *tgpt_group) char *wwn_vendor_extension, char *tgpt_group) {
{
int i, j, s, len; int i, j, s, len;
/* /*
@ -534,7 +497,7 @@ static int check_fill_0x83_id(struct udev *udev,
* included in the identifier. * included in the identifier.
*/ */
if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC) if (id_search->id_type == SCSI_ID_VENDOR_SPECIFIC)
if (prepend_vendor_model(udev, dev_scsi, &serial[1]) < 0) if (prepend_vendor_model(dev_scsi, &serial[1]) < 0)
return 1; return 1;
i = 4; /* offset to the start of the identifier */ i = 4; /* offset to the start of the identifier */
@ -569,12 +532,10 @@ static int check_fill_0x83_id(struct udev *udev,
} }
/* Extract the raw binary from VPD 0x83 pre-SPC devices */ /* Extract the raw binary from VPD 0x83 pre-SPC devices */
static int check_fill_0x83_prespc3(struct udev *udev, static int check_fill_0x83_prespc3(struct scsi_id_device *dev_scsi,
struct scsi_id_device *dev_scsi,
unsigned char *page_83, unsigned char *page_83,
const struct scsi_id_search_values const struct scsi_id_search_values
*id_search, char *serial, char *serial_short, int max_len) *id_search, char *serial, char *serial_short, int max_len) {
{
int i, j; int i, j;
serial[0] = hex_str[SCSI_ID_NAA]; serial[0] = hex_str[SCSI_ID_NAA];
@ -591,21 +552,19 @@ static int check_fill_0x83_prespc3(struct udev *udev,
} }
/* Get device identification VPD page */ /* Get device identification VPD page */
static int do_scsi_page83_inquiry(struct udev *udev, static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd,
char *serial, char *serial_short, int len, char *serial, char *serial_short, int len,
char *unit_serial_number, char *wwn, char *unit_serial_number, char *wwn,
char *wwn_vendor_extension, char *tgpt_group) char *wwn_vendor_extension, char *tgpt_group) {
{
int retval; int retval;
unsigned int id_ind, j; unsigned int id_ind, j;
unsigned char page_83[SCSI_INQ_BUFF_LEN]; unsigned char page_83[SCSI_INQ_BUFF_LEN];
/* also pick up the page 80 serial number */ /* also pick up the page 80 serial number */
do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN); do_scsi_page80_inquiry(dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN);
memzero(page_83, SCSI_INQ_BUFF_LEN); memzero(page_83, SCSI_INQ_BUFF_LEN);
retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83,
SCSI_INQ_BUFF_LEN); SCSI_INQ_BUFF_LEN);
if (retval < 0) if (retval < 0)
return 1; return 1;
@ -645,8 +604,7 @@ static int do_scsi_page83_inquiry(struct udev *udev,
*/ */
if (page_83[6] != 0) if (page_83[6] != 0)
return check_fill_0x83_prespc3(udev, return check_fill_0x83_prespc3(dev_scsi, page_83, id_search_list,
dev_scsi, page_83, id_search_list,
serial, serial_short, len); serial, serial_short, len);
/* /*
@ -661,8 +619,7 @@ static int do_scsi_page83_inquiry(struct udev *udev,
* one or a small number of descriptors. * one or a small number of descriptors.
*/ */
for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) { for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) {
retval = check_fill_0x83_id(udev, retval = check_fill_0x83_id(dev_scsi, &page_83[j],
dev_scsi, &page_83[j],
&id_search_list[id_ind], &id_search_list[id_ind],
serial, serial_short, len, serial, serial_short, len,
wwn, wwn_vendor_extension, wwn, wwn_vendor_extension,
@ -683,16 +640,14 @@ static int do_scsi_page83_inquiry(struct udev *udev,
* Return the hard coded error code value 2 if the page 83 reply is not * Return the hard coded error code value 2 if the page 83 reply is not
* conformant to the SCSI-2 format. * conformant to the SCSI-2 format.
*/ */
static int do_scsi_page83_prespc3_inquiry(struct udev *udev, static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int len) {
char *serial, char *serial_short, int len)
{
int retval; int retval;
int i, j; int i, j;
unsigned char page_83[SCSI_INQ_BUFF_LEN]; unsigned char page_83[SCSI_INQ_BUFF_LEN];
memzero(page_83, SCSI_INQ_BUFF_LEN); memzero(page_83, SCSI_INQ_BUFF_LEN);
retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_83, page_83, SCSI_INQ_BUFF_LEN);
if (retval < 0) if (retval < 0)
return 1; return 1;
@ -745,10 +700,8 @@ static int do_scsi_page83_prespc3_inquiry(struct udev *udev,
} }
/* Get unit serial number VPD page */ /* Get unit serial number VPD page */
static int do_scsi_page80_inquiry(struct udev *udev, static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
struct scsi_id_device *dev_scsi, int fd, char *serial, char *serial_short, int max_len) {
char *serial, char *serial_short, int max_len)
{
int retval; int retval;
int ser_ind; int ser_ind;
int i; int i;
@ -756,7 +709,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
unsigned char buf[SCSI_INQ_BUFF_LEN]; unsigned char buf[SCSI_INQ_BUFF_LEN];
memzero(buf, SCSI_INQ_BUFF_LEN); memzero(buf, SCSI_INQ_BUFF_LEN);
retval = scsi_inquiry(udev, dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN); retval = scsi_inquiry(dev_scsi, fd, 1, PAGE_80, buf, SCSI_INQ_BUFF_LEN);
if (retval < 0) if (retval < 0)
return retval; return retval;
@ -778,7 +731,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
len = buf[3]; len = buf[3];
if (serial != NULL) { if (serial != NULL) {
serial[0] = 'S'; serial[0] = 'S';
ser_ind = prepend_vendor_model(udev, dev_scsi, &serial[1]); ser_ind = prepend_vendor_model(dev_scsi, &serial[1]);
if (ser_ind < 0) if (ser_ind < 0)
return 1; return 1;
ser_ind++; /* for the leading 'S' */ ser_ind++; /* for the leading 'S' */
@ -792,9 +745,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
return 0; return 0;
} }
int scsi_std_inquiry(struct udev *udev, int scsi_std_inquiry(struct scsi_id_device *dev_scsi, const char *devname) {
struct scsi_id_device *dev_scsi, const char *devname)
{
int fd; int fd;
unsigned char buf[SCSI_INQ_BUFF_LEN]; unsigned char buf[SCSI_INQ_BUFF_LEN];
struct stat statbuf; struct stat statbuf;
@ -815,7 +766,7 @@ int scsi_std_inquiry(struct udev *udev,
minor(statbuf.st_rdev)); minor(statbuf.st_rdev));
memzero(buf, SCSI_INQ_BUFF_LEN); memzero(buf, SCSI_INQ_BUFF_LEN);
err = scsi_inquiry(udev, dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN); err = scsi_inquiry(dev_scsi, fd, 0, 0, buf, SCSI_INQ_BUFF_LEN);
if (err < 0) if (err < 0)
goto out; goto out;
@ -833,10 +784,8 @@ out:
return err; return err;
} }
int scsi_get_serial(struct udev *udev, int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname,
struct scsi_id_device *dev_scsi, const char *devname, int page_code, int len) {
int page_code, int len)
{
unsigned char page0[SCSI_INQ_BUFF_LEN]; unsigned char page0[SCSI_INQ_BUFF_LEN];
int fd = -1; int fd = -1;
int cnt; int cnt;
@ -859,7 +808,7 @@ int scsi_get_serial(struct udev *udev,
return 1; return 1;
if (page_code == PAGE_80) { if (page_code == PAGE_80) {
if (do_scsi_page80_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) { if (do_scsi_page80_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len)) {
retval = 1; retval = 1;
goto completed; goto completed;
} else { } else {
@ -867,7 +816,7 @@ int scsi_get_serial(struct udev *udev,
goto completed; goto completed;
} }
} else if (page_code == PAGE_83) { } else if (page_code == PAGE_83) {
if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { if (do_scsi_page83_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
retval = 1; retval = 1;
goto completed; goto completed;
} else { } else {
@ -875,7 +824,7 @@ int scsi_get_serial(struct udev *udev,
goto completed; goto completed;
} }
} else if (page_code == PAGE_83_PRE_SPC3) { } else if (page_code == PAGE_83_PRE_SPC3) {
retval = do_scsi_page83_prespc3_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len); retval = do_scsi_page83_prespc3_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len);
if (retval) { if (retval) {
/* /*
* Fallback to servicing a SPC-2/3 compliant page 83 * Fallback to servicing a SPC-2/3 compliant page 83
@ -883,7 +832,7 @@ int scsi_get_serial(struct udev *udev,
* conform to pre-SPC3 expectations. * conform to pre-SPC3 expectations.
*/ */
if (retval == 2) { if (retval == 2) {
if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { if (do_scsi_page83_inquiry(dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
retval = 1; retval = 1;
goto completed; goto completed;
} else { } else {
@ -909,7 +858,7 @@ int scsi_get_serial(struct udev *udev,
* Get page 0, the page of the pages. By default, try from best to * Get page 0, the page of the pages. By default, try from best to
* worst of supported pages: 0x83 then 0x80. * worst of supported pages: 0x83 then 0x80.
*/ */
if (do_scsi_page0_inquiry(udev, dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) { if (do_scsi_page0_inquiry(dev_scsi, fd, page0, SCSI_INQ_BUFF_LEN)) {
/* /*
* Don't try anything else. Black list if a specific page * Don't try anything else. Black list if a specific page
* should be used for this vendor+model, or maybe have an * should be used for this vendor+model, or maybe have an
@ -921,7 +870,7 @@ int scsi_get_serial(struct udev *udev,
for (ind = 4; ind <= page0[3] + 3; ind++) for (ind = 4; ind <= page0[3] + 3; ind++)
if (page0[ind] == PAGE_83) if (page0[ind] == PAGE_83)
if (!do_scsi_page83_inquiry(udev, dev_scsi, fd, if (!do_scsi_page83_inquiry(dev_scsi, fd,
dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) { dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
/* /*
* Success * Success
@ -932,7 +881,7 @@ int scsi_get_serial(struct udev *udev,
for (ind = 4; ind <= page0[3] + 3; ind++) for (ind = 4; ind <= page0[3] + 3; ind++)
if (page0[ind] == PAGE_80) if (page0[ind] == PAGE_80)
if (!do_scsi_page80_inquiry(udev, dev_scsi, fd, if (!do_scsi_page80_inquiry(dev_scsi, fd,
dev_scsi->serial, dev_scsi->serial_short, len)) { dev_scsi->serial, dev_scsi->serial_short, len)) {
/* /*
* Success * Success

View File

@ -160,7 +160,7 @@ static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool te
/* read data from another device than the device we will store the data */ /* read data from another device than the device we will store the data */
if (device) { if (device) {
srcdev = udev_device_new_from_device_id(udev_device_get_udev(dev), device); srcdev = udev_device_new_from_device_id(NULL, device);
if (!srcdev) if (!srcdev)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -171,7 +171,7 @@ static int builtin_hwdb(struct udev_device *dev, int argc, char *argv[], bool te
} }
/* called at udev startup and reload */ /* called at udev startup and reload */
static int builtin_hwdb_init(struct udev *udev) { static int builtin_hwdb_init(void) {
int r; int r;
if (hwdb) if (hwdb)
@ -185,12 +185,12 @@ static int builtin_hwdb_init(struct udev *udev) {
} }
/* called on udev shutdown and reload request */ /* called on udev shutdown and reload request */
static void builtin_hwdb_exit(struct udev *udev) { static void builtin_hwdb_exit(void) {
hwdb = sd_hwdb_unref(hwdb); hwdb = sd_hwdb_unref(hwdb);
} }
/* called every couple of seconds during event activity; 'true' if config has changed */ /* called every couple of seconds during event activity; 'true' if config has changed */
static bool builtin_hwdb_validate(struct udev *udev) { static bool builtin_hwdb_validate(void) {
return hwdb_validate(hwdb); return hwdb_validate(hwdb);
} }

View File

@ -39,7 +39,7 @@ static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool te
} }
/* called at udev startup and reload */ /* called at udev startup and reload */
static int builtin_kmod_init(struct udev *udev) { static int builtin_kmod_init(void) {
if (ctx) if (ctx)
return 0; return 0;
@ -48,19 +48,19 @@ static int builtin_kmod_init(struct udev *udev) {
return -ENOMEM; return -ENOMEM;
log_debug("Load module index"); log_debug("Load module index");
kmod_set_log_fn(ctx, udev_kmod_log, udev); kmod_set_log_fn(ctx, udev_kmod_log, NULL);
kmod_load_resources(ctx); kmod_load_resources(ctx);
return 0; return 0;
} }
/* called on udev shutdown and reload request */ /* called on udev shutdown and reload request */
static void builtin_kmod_exit(struct udev *udev) { static void builtin_kmod_exit(void) {
log_debug("Unload module index"); log_debug("Unload module index");
ctx = kmod_unref(ctx); ctx = kmod_unref(ctx);
} }
/* called every couple of seconds during event activity; 'true' if config has changed */ /* called every couple of seconds during event activity; 'true' if config has changed */
static bool builtin_kmod_validate(struct udev *udev) { static bool builtin_kmod_validate(void) {
log_debug("Validate module index"); log_debug("Validate module index");
if (!ctx) if (!ctx)
return false; return false;

View File

@ -153,7 +153,6 @@ static struct udev_device *skip_virtio(struct udev_device *dev) {
} }
static int get_virtfn_info(struct udev_device *dev, struct netnames *names, struct virtfn_info *vf_info) { static int get_virtfn_info(struct udev_device *dev, struct netnames *names, struct virtfn_info *vf_info) {
struct udev *udev;
const char *physfn_link_file; const char *physfn_link_file;
_cleanup_free_ char *physfn_pci_syspath = NULL; _cleanup_free_ char *physfn_pci_syspath = NULL;
_cleanup_free_ char *virtfn_pci_syspath = NULL; _cleanup_free_ char *virtfn_pci_syspath = NULL;
@ -162,9 +161,6 @@ static int get_virtfn_info(struct udev_device *dev, struct netnames *names, stru
struct virtfn_info vf_info_local = {}; struct virtfn_info vf_info_local = {};
int r; int r;
udev = udev_device_get_udev(names->pcidev);
if (!udev)
return -ENOENT;
/* Check if this is a virtual function. */ /* Check if this is a virtual function. */
physfn_link_file = strjoina(udev_device_get_syspath(names->pcidev), "/physfn"); physfn_link_file = strjoina(udev_device_get_syspath(names->pcidev), "/physfn");
r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath); r = chase_symlinks(physfn_link_file, NULL, 0, &physfn_pci_syspath);
@ -172,7 +168,7 @@ static int get_virtfn_info(struct udev_device *dev, struct netnames *names, stru
return r; return r;
/* Get physical function's pci device. */ /* Get physical function's pci device. */
vf_info_local.physfn_pcidev = udev_device_new_from_syspath(udev, physfn_pci_syspath); vf_info_local.physfn_pcidev = udev_device_new_from_syspath(NULL, physfn_pci_syspath);
if (!vf_info_local.physfn_pcidev) if (!vf_info_local.physfn_pcidev)
return -ENOENT; return -ENOENT;
@ -288,7 +284,6 @@ static bool is_pci_ari_enabled(struct udev_device *dev) {
} }
static int dev_pci_slot(struct udev_device *dev, struct netnames *names) { static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
struct udev *udev = udev_device_get_udev(names->pcidev);
unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0; unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0;
size_t l; size_t l;
char *s; char *s;
@ -331,7 +326,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
names->pci_path[0] = '\0'; names->pci_path[0] = '\0';
/* ACPI _SUN — slot user number */ /* ACPI _SUN — slot user number */
pci = udev_device_new_from_subsystem_sysname(udev, "subsystem", "pci"); pci = udev_device_new_from_subsystem_sysname(NULL, "subsystem", "pci");
if (!pci) if (!pci)
return -ENOENT; return -ENOENT;

View File

@ -1,6 +1,7 @@
/* SPDX-License-Identifier: LGPL-2.1+ */ /* SPDX-License-Identifier: LGPL-2.1+ */
#include "alloc-util.h" #include "alloc-util.h"
#include "libudev-device-internal.h"
#include "link-config.h" #include "link-config.h"
#include "log.h" #include "log.h"
#include "udev.h" #include "udev.h"
@ -18,11 +19,11 @@ static int builtin_net_setup_link(struct udev_device *dev, int argc, char **argv
return EXIT_FAILURE; return EXIT_FAILURE;
} }
r = link_get_driver(ctx, dev, &driver); r = link_get_driver(ctx, dev->device, &driver);
if (r >= 0) if (r >= 0)
udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver);
r = link_config_get(ctx, dev, &link); r = link_config_get(ctx, dev->device, &link);
if (r < 0) { if (r < 0) {
if (r == -ENOENT) { if (r == -ENOENT) {
log_debug("No matching link configuration found."); log_debug("No matching link configuration found.");
@ -33,7 +34,7 @@ static int builtin_net_setup_link(struct udev_device *dev, int argc, char **argv
} }
} }
r = link_config_apply(ctx, link, dev, &name); r = link_config_apply(ctx, link, dev->device, &name);
if (r < 0) if (r < 0)
log_warning_errno(r, "Could not apply link config to %s, ignoring: %m", udev_device_get_sysname(dev)); log_warning_errno(r, "Could not apply link config to %s, ignoring: %m", udev_device_get_sysname(dev));
@ -45,7 +46,7 @@ static int builtin_net_setup_link(struct udev_device *dev, int argc, char **argv
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
static int builtin_net_setup_link_init(struct udev *udev) { static int builtin_net_setup_link_init(void) {
int r; int r;
if (ctx) if (ctx)
@ -63,13 +64,13 @@ static int builtin_net_setup_link_init(struct udev *udev) {
return 0; return 0;
} }
static void builtin_net_setup_link_exit(struct udev *udev) { static void builtin_net_setup_link_exit(void) {
link_config_ctx_free(ctx); link_config_ctx_free(ctx);
ctx = NULL; ctx = NULL;
log_debug("Unloaded link configuration context."); log_debug("Unloaded link configuration context.");
} }
static bool builtin_net_setup_link_validate(struct udev *udev) { static bool builtin_net_setup_link_validate(void) {
log_debug("Check if link configuration needs reloading."); log_debug("Check if link configuration needs reloading.");
if (!ctx) if (!ctx)
return false; return false;

View File

@ -86,7 +86,6 @@ static struct udev_device *skip_subsystem(struct udev_device *dev, const char *s
} }
static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) { static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev; struct udev_device *targetdev;
_cleanup_(udev_device_unrefp) struct udev_device *fcdev = NULL; _cleanup_(udev_device_unrefp) struct udev_device *fcdev = NULL;
const char *port; const char *port;
@ -95,13 +94,12 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
assert(parent); assert(parent);
assert(path); assert(path);
udev = udev_device_get_udev(parent);
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
if (!targetdev) if (!targetdev)
return NULL; return NULL;
fcdev = udev_device_new_from_subsystem_sysname(udev, "fc_transport", udev_device_get_sysname(targetdev)); fcdev = udev_device_new_from_subsystem_sysname(NULL, "fc_transport", udev_device_get_sysname(targetdev));
if (!fcdev) if (!fcdev)
return NULL; return NULL;
@ -115,7 +113,6 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
} }
static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) { static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev, *target_parent; struct udev_device *targetdev, *target_parent;
_cleanup_(udev_device_unrefp) struct udev_device *sasdev = NULL; _cleanup_(udev_device_unrefp) struct udev_device *sasdev = NULL;
const char *sas_address; const char *sas_address;
@ -124,7 +121,6 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
assert(parent); assert(parent);
assert(path); assert(path);
udev = udev_device_get_udev(parent);
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
if (!targetdev) if (!targetdev)
@ -134,7 +130,7 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
if (!target_parent) if (!target_parent)
return NULL; return NULL;
sasdev = udev_device_new_from_subsystem_sysname(udev, "sas_device", sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_device",
udev_device_get_sysname(target_parent)); udev_device_get_sysname(target_parent));
if (!sasdev) if (!sasdev)
return NULL; return NULL;
@ -150,7 +146,6 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path) static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **path)
{ {
struct udev *udev;
struct udev_device *targetdev, *target_parent, *port, *expander; struct udev_device *targetdev, *target_parent, *port, *expander;
_cleanup_(udev_device_unrefp) struct udev_device _cleanup_(udev_device_unrefp) struct udev_device
*target_sasdev = NULL, *expander_sasdev = NULL, *port_sasdev = NULL; *target_sasdev = NULL, *expander_sasdev = NULL, *port_sasdev = NULL;
@ -162,7 +157,6 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
assert(parent); assert(parent);
assert(path); assert(path);
udev = udev_device_get_udev(parent);
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target"); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
if (!targetdev) if (!targetdev)
@ -173,8 +167,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
return NULL; return NULL;
/* Get sas device */ /* Get sas device */
target_sasdev = udev_device_new_from_subsystem_sysname( target_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_device", udev_device_get_sysname(target_parent));
udev, "sas_device", udev_device_get_sysname(target_parent));
if (!target_sasdev) if (!target_sasdev)
return NULL; return NULL;
@ -184,8 +177,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
return NULL; return NULL;
/* Get port device */ /* Get port device */
port_sasdev = udev_device_new_from_subsystem_sysname( port_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_port", udev_device_get_sysname(port));
udev, "sas_port", udev_device_get_sysname(port));
phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys"); phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys");
if (!phy_count) if (!phy_count)
@ -206,12 +198,10 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
return NULL; return NULL;
/* Get expander device */ /* Get expander device */
expander_sasdev = udev_device_new_from_subsystem_sysname( expander_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_device", udev_device_get_sysname(expander));
udev, "sas_device", udev_device_get_sysname(expander));
if (expander_sasdev) { if (expander_sasdev) {
/* Get expander's address */ /* Get expander's address */
sas_address = udev_device_get_sysattr_value(expander_sasdev, sas_address = udev_device_get_sysattr_value(expander_sasdev, "sas_address");
"sas_address");
if (!sas_address) if (!sas_address)
return NULL; return NULL;
} }
@ -226,7 +216,6 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
} }
static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) { static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *transportdev; struct udev_device *transportdev;
_cleanup_(udev_device_unrefp) struct udev_device _cleanup_(udev_device_unrefp) struct udev_device
*sessiondev = NULL, *conndev = NULL; *sessiondev = NULL, *conndev = NULL;
@ -236,7 +225,6 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
assert(parent); assert(parent);
assert(path); assert(path);
udev = udev_device_get_udev(parent);
/* find iscsi session */ /* find iscsi session */
transportdev = parent; transportdev = parent;
@ -249,7 +237,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
} }
/* find iscsi session device */ /* find iscsi session device */
sessiondev = udev_device_new_from_subsystem_sysname(udev, "iscsi_session", udev_device_get_sysname(transportdev)); sessiondev = udev_device_new_from_subsystem_sysname(NULL, "iscsi_session", udev_device_get_sysname(transportdev));
if (!sessiondev) if (!sessiondev)
return NULL; return NULL;
@ -258,7 +246,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
return NULL; return NULL;
connname = strjoina("connection", udev_device_get_sysnum(transportdev), ":0"); connname = strjoina("connection", udev_device_get_sysnum(transportdev), ":0");
conndev = udev_device_new_from_subsystem_sysname(udev, "iscsi_connection", connname); conndev = udev_device_new_from_subsystem_sysname(NULL, "iscsi_connection", connname);
if (!conndev) if (!conndev)
return NULL; return NULL;
@ -273,7 +261,6 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
} }
static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path) { static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **path) {
struct udev *udev;
struct udev_device *targetdev, *target_parent; struct udev_device *targetdev, *target_parent;
_cleanup_(udev_device_unrefp) struct udev_device *atadev = NULL; _cleanup_(udev_device_unrefp) struct udev_device *atadev = NULL;
const char *port_no; const char *port_no;
@ -281,7 +268,6 @@ static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **pa
assert(parent); assert(parent);
assert(path); assert(path);
udev = udev_device_get_udev(parent);
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host"); targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
if (!targetdev) if (!targetdev)
@ -291,7 +277,7 @@ static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **pa
if (!target_parent) if (!target_parent)
return NULL; return NULL;
atadev = udev_device_new_from_subsystem_sysname(udev, "ata_port", udev_device_get_sysname(target_parent)); atadev = udev_device_new_from_subsystem_sysname(NULL, "ata_port", udev_device_get_sysname(target_parent));
if (!atadev) if (!atadev)
return NULL; return NULL;

View File

@ -29,7 +29,7 @@ static const struct udev_builtin *builtins[] = {
#endif #endif
}; };
void udev_builtin_init(struct udev *udev) { void udev_builtin_init(void) {
unsigned int i; unsigned int i;
if (initialized) if (initialized)
@ -37,12 +37,12 @@ void udev_builtin_init(struct udev *udev) {
for (i = 0; i < ELEMENTSOF(builtins); i++) for (i = 0; i < ELEMENTSOF(builtins); i++)
if (builtins[i] && builtins[i]->init) if (builtins[i] && builtins[i]->init)
builtins[i]->init(udev); builtins[i]->init();
initialized = true; initialized = true;
} }
void udev_builtin_exit(struct udev *udev) { void udev_builtin_exit(void) {
unsigned int i; unsigned int i;
if (!initialized) if (!initialized)
@ -50,21 +50,21 @@ void udev_builtin_exit(struct udev *udev) {
for (i = 0; i < ELEMENTSOF(builtins); i++) for (i = 0; i < ELEMENTSOF(builtins); i++)
if (builtins[i] && builtins[i]->exit) if (builtins[i] && builtins[i]->exit)
builtins[i]->exit(udev); builtins[i]->exit();
initialized = false; initialized = false;
} }
bool udev_builtin_validate(struct udev *udev) { bool udev_builtin_validate(void) {
unsigned int i; unsigned int i;
for (i = 0; i < ELEMENTSOF(builtins); i++) for (i = 0; i < ELEMENTSOF(builtins); i++)
if (builtins[i] && builtins[i]->validate && builtins[i]->validate(udev)) if (builtins[i] && builtins[i]->validate && builtins[i]->validate())
return true; return true;
return false; return false;
} }
void udev_builtin_list(struct udev *udev) { void udev_builtin_list(void) {
unsigned int i; unsigned int i;
for (i = 0; i < ELEMENTSOF(builtins); i++) for (i = 0; i < ELEMENTSOF(builtins); i++)
@ -112,7 +112,7 @@ int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const c
/* we need '0' here to reset the internal state */ /* we need '0' here to reset the internal state */
optind = 0; optind = 0;
strscpy(arg, sizeof(arg), command); strscpy(arg, sizeof(arg), command);
udev_build_argv(udev_device_get_udev(dev), arg, &argc, argv); udev_build_argv(arg, &argc, argv);
return builtins[cmd]->cmd(dev, argc, argv, test); return builtins[cmd]->cmd(dev, argc, argv, test);
} }

View File

@ -49,14 +49,13 @@ struct udev_ctrl_msg_wire {
}; };
struct udev_ctrl_msg { struct udev_ctrl_msg {
int refcount; unsigned n_ref;
struct udev_ctrl_connection *conn; struct udev_ctrl_connection *conn;
struct udev_ctrl_msg_wire ctrl_msg_wire; struct udev_ctrl_msg_wire ctrl_msg_wire;
}; };
struct udev_ctrl { struct udev_ctrl {
int refcount; unsigned n_ref;
struct udev *udev;
int sock; int sock;
union sockaddr_union saddr; union sockaddr_union saddr;
socklen_t addrlen; socklen_t addrlen;
@ -66,12 +65,12 @@ struct udev_ctrl {
}; };
struct udev_ctrl_connection { struct udev_ctrl_connection {
int refcount; unsigned n_ref;
struct udev_ctrl *uctrl; struct udev_ctrl *uctrl;
int sock; int sock;
}; };
struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) { struct udev_ctrl *udev_ctrl_new_from_fd(int fd) {
struct udev_ctrl *uctrl; struct udev_ctrl *uctrl;
const int on = 1; const int on = 1;
int r; int r;
@ -79,8 +78,7 @@ struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) {
uctrl = new0(struct udev_ctrl, 1); uctrl = new0(struct udev_ctrl, 1);
if (uctrl == NULL) if (uctrl == NULL)
return NULL; return NULL;
uctrl->refcount = 1; uctrl->n_ref = 1;
uctrl->udev = udev;
if (fd < 0) { if (fd < 0) {
uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); uctrl->sock = socket(AF_LOCAL, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0);
@ -108,8 +106,8 @@ struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd) {
return uctrl; return uctrl;
} }
struct udev_ctrl *udev_ctrl_new(struct udev *udev) { struct udev_ctrl *udev_ctrl_new(void) {
return udev_ctrl_new_from_fd(udev, -1); return udev_ctrl_new_from_fd(-1);
} }
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) { int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) {
@ -135,26 +133,15 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) {
return 0; return 0;
} }
struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl) { static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) {
return uctrl->udev; assert(uctrl);
safe_close(uctrl->sock);
return mfree(uctrl);
} }
static struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl) { DEFINE_PRIVATE_TRIVIAL_REF_FUNC(struct udev_ctrl, udev_ctrl);
if (uctrl) DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
uctrl->refcount++;
return uctrl;
}
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl) {
if (uctrl && -- uctrl->refcount == 0) {
if (uctrl->sock >= 0)
close(uctrl->sock);
free(uctrl);
}
return NULL;
}
int udev_ctrl_cleanup(struct udev_ctrl *uctrl) { int udev_ctrl_cleanup(struct udev_ctrl *uctrl) {
if (uctrl == NULL) if (uctrl == NULL)
@ -179,7 +166,7 @@ struct udev_ctrl_connection *udev_ctrl_get_connection(struct udev_ctrl *uctrl) {
conn = new(struct udev_ctrl_connection, 1); conn = new(struct udev_ctrl_connection, 1);
if (conn == NULL) if (conn == NULL)
return NULL; return NULL;
conn->refcount = 1; conn->n_ref = 1;
conn->uctrl = uctrl; conn->uctrl = uctrl;
conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
@ -213,25 +200,15 @@ err:
return mfree(conn); return mfree(conn);
} }
struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) { static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_connection *conn) {
if (conn == NULL) assert(conn);
return NULL;
conn->refcount++; safe_close(conn->sock);
return conn; udev_ctrl_unref(conn->uctrl);
return mfree(conn);
} }
struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn) { DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
if (conn && -- conn->refcount == 0) {
if (conn->sock >= 0)
close(conn->sock);
udev_ctrl_unref(conn->uctrl);
free(conn);
}
return NULL;
}
static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) { static int ctrl_send(struct udev_ctrl *uctrl, enum udev_ctrl_msg_type type, int intval, const char *buf, int timeout) {
struct udev_ctrl_msg_wire ctrl_msg_wire; struct udev_ctrl_msg_wire ctrl_msg_wire;
@ -336,7 +313,7 @@ struct udev_ctrl_msg *udev_ctrl_receive_msg(struct udev_ctrl_connection *conn) {
uctrl_msg = new0(struct udev_ctrl_msg, 1); uctrl_msg = new0(struct udev_ctrl_msg, 1);
if (uctrl_msg == NULL) if (uctrl_msg == NULL)
return NULL; return NULL;
uctrl_msg->refcount = 1; uctrl_msg->n_ref = 1;
uctrl_msg->conn = conn; uctrl_msg->conn = conn;
udev_ctrl_connection_ref(conn); udev_ctrl_connection_ref(conn);
@ -402,15 +379,15 @@ err:
return NULL; return NULL;
} }
struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg) { static struct udev_ctrl_msg *udev_ctrl_msg_free(struct udev_ctrl_msg *ctrl_msg) {
if (ctrl_msg && -- ctrl_msg->refcount == 0) { assert(ctrl_msg);
udev_ctrl_connection_unref(ctrl_msg->conn);
free(ctrl_msg);
}
return NULL; udev_ctrl_connection_unref(ctrl_msg->conn);
return mfree(ctrl_msg);
} }
DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl_msg, udev_ctrl_msg, udev_ctrl_msg_free);
int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) { int udev_ctrl_get_set_log_level(struct udev_ctrl_msg *ctrl_msg) {
if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL) if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL)
return ctrl_msg->ctrl_msg_wire.intval; return ctrl_msg->ctrl_msg_wire.intval;

View File

@ -33,16 +33,14 @@ typedef struct Spawn {
} Spawn; } Spawn;
struct udev_event *udev_event_new(struct udev_device *dev) { struct udev_event *udev_event_new(struct udev_device *dev) {
struct udev *udev = udev_device_get_udev(dev);
struct udev_event *event; struct udev_event *event;
event = new0(struct udev_event, 1); event = new0(struct udev_event, 1);
if (event == NULL) if (event == NULL)
return NULL; return NULL;
event->dev = dev; event->dev = dev;
event->udev = udev; udev_list_init(NULL, &event->run_list, false);
udev_list_init(udev, &event->run_list, false); udev_list_init(NULL, &event->seclabel_list, false);
udev_list_init(udev, &event->seclabel_list, false);
event->birth_usec = now(CLOCK_MONOTONIC); event->birth_usec = now(CLOCK_MONOTONIC);
return event; return event;
} }
@ -180,7 +178,7 @@ static size_t subst_format_var(struct udev_event *event, struct udev_device *dev
} }
/* try to read the value specified by "[dmi/id]product_name" */ /* try to read the value specified by "[dmi/id]product_name" */
if (util_resolve_subsys_kernel(event->udev, attr, vbuf, sizeof(vbuf), 1) == 0) if (util_resolve_subsys_kernel(attr, vbuf, sizeof(vbuf), 1) == 0)
value = vbuf; value = vbuf;
/* try to read the attribute the device */ /* try to read the attribute the device */
@ -698,7 +696,7 @@ static int spawn_wait(struct udev_event *event,
return ret; return ret;
} }
int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]) { int udev_build_argv(char *cmd, int *argc, char *argv[]) {
int i = 0; int i = 0;
char *pos; char *pos;
@ -771,7 +769,7 @@ int udev_event_spawn(struct udev_event *event,
errpipe[READ_END] = safe_close(errpipe[READ_END]); errpipe[READ_END] = safe_close(errpipe[READ_END]);
strscpy(arg, sizeof(arg), cmd); strscpy(arg, sizeof(arg), cmd);
udev_build_argv(event->udev, arg, NULL, argv); udev_build_argv(arg, NULL, argv);
/* allow programs in /usr/lib/udev/ to be called without the path */ /* allow programs in /usr/lib/udev/ to be called without the path */
if (argv[0][0] != '/') { if (argv[0][0] != '/') {
@ -845,7 +843,7 @@ void udev_event_execute_rules(struct udev_event *event,
udev_device_delete_db(dev); udev_device_delete_db(dev);
if (major(udev_device_get_devnum(dev)) != 0) if (major(udev_device_get_devnum(dev)) != 0)
udev_watch_end(event->udev, dev); udev_watch_end(dev);
udev_rules_apply_to_event(rules, event, udev_rules_apply_to_event(rules, event,
timeout_usec, timeout_warn_usec, timeout_usec, timeout_warn_usec,
@ -858,7 +856,7 @@ void udev_event_execute_rules(struct udev_event *event,
if (event->dev_db != NULL) { if (event->dev_db != NULL) {
/* disable watch during event processing */ /* disable watch during event processing */
if (major(udev_device_get_devnum(dev)) != 0) if (major(udev_device_get_devnum(dev)) != 0)
udev_watch_end(event->udev, event->dev_db); udev_watch_end(event->dev_db);
if (major(udev_device_get_devnum(dev)) == 0 && if (major(udev_device_get_devnum(dev)) == 0 &&
streq(udev_device_get_action(dev), "move")) streq(udev_device_get_action(dev), "move"))

View File

@ -113,7 +113,6 @@ exit:
/* find device node of device with highest priority */ /* find device node of device with highest priority */
static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) { static const char *link_find_prioritized(struct udev_device *dev, bool add, const char *stackdir, char *buf, size_t bufsize) {
struct udev *udev = udev_device_get_udev(dev);
DIR *dir; DIR *dir;
struct dirent *dent; struct dirent *dent;
int priority = 0; int priority = 0;
@ -142,7 +141,7 @@ static const char *link_find_prioritized(struct udev_device *dev, bool add, cons
if (streq(dent->d_name, udev_device_get_id_filename(dev))) if (streq(dent->d_name, udev_device_get_id_filename(dev)))
continue; continue;
dev_db = udev_device_new_from_device_id(udev, dent->d_name); dev_db = udev_device_new_from_device_id(NULL, dent->d_name);
if (dev_db != NULL) { if (dev_db != NULL) {
const char *devnode; const char *devnode;

View File

@ -50,7 +50,6 @@ static const char* const rules_dirs[] = {
}; };
struct udev_rules { struct udev_rules {
struct udev *udev;
usec_t dirs_ts_usec; usec_t dirs_ts_usec;
int resolve_names; int resolve_names;
@ -700,7 +699,7 @@ static void attr_subst_subdir(char *attr, size_t len) {
} }
} }
static int get_key(struct udev *udev, char **line, char **key, enum operation_type *op, char **value) { static int get_key(char **line, char **key, enum operation_type *op, char **value) {
char *linepos; char *linepos;
char *temp; char *temp;
unsigned i, j; unsigned i, j;
@ -802,7 +801,7 @@ static int get_key(struct udev *udev, char **line, char **key, enum operation_ty
} }
/* extract possible KEY{attr} */ /* extract possible KEY{attr} */
static const char *get_key_attribute(struct udev *udev, char *str) { static const char *get_key_attribute(char *str) {
char *pos; char *pos;
char *attr; char *attr;
@ -1019,7 +1018,7 @@ static void add_rule(struct udev_rules *rules, char *line,
char *value; char *value;
enum operation_type op; enum operation_type op;
if (get_key(rules->udev, &linepos, &key, &op, &value) != 0) { if (get_key(&linepos, &key, &op, &value) != 0) {
/* Avoid erroring on trailing whitespace. This is probably rare /* Avoid erroring on trailing whitespace. This is probably rare
* so save the work for the error case instead of always trying * so save the work for the error case instead of always trying
* to strip the trailing whitespace with strstrip(). */ * to strip the trailing whitespace with strstrip(). */
@ -1082,8 +1081,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL); rule_add_key(&rule_tmp, TK_M_DRIVER, op, value, NULL);
} else if (startswith(key, "ATTR{")) { } else if (startswith(key, "ATTR{")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("ATTR"));
key + STRLEN("ATTR"));
if (attr == NULL) if (attr == NULL)
LOG_AND_RETURN("error parsing %s attribute", "ATTR"); LOG_AND_RETURN("error parsing %s attribute", "ATTR");
@ -1096,8 +1094,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr); rule_add_key(&rule_tmp, TK_A_ATTR, op, value, attr);
} else if (startswith(key, "SYSCTL{")) { } else if (startswith(key, "SYSCTL{")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("SYSCTL"));
key + STRLEN("SYSCTL"));
if (attr == NULL) if (attr == NULL)
LOG_AND_RETURN("error parsing %s attribute", "ATTR"); LOG_AND_RETURN("error parsing %s attribute", "ATTR");
@ -1110,8 +1107,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr); rule_add_key(&rule_tmp, TK_A_SYSCTL, op, value, attr);
} else if (startswith(key, "SECLABEL{")) { } else if (startswith(key, "SECLABEL{")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("SECLABEL"));
key + STRLEN("SECLABEL"));
if (attr == NULL) if (attr == NULL)
LOG_AND_RETURN("error parsing %s attribute", "SECLABEL"); LOG_AND_RETURN("error parsing %s attribute", "SECLABEL");
@ -1142,8 +1138,7 @@ static void add_rule(struct udev_rules *rules, char *line,
if (op > OP_MATCH_MAX) if (op > OP_MATCH_MAX)
LOG_AND_RETURN("invalid %s operation", "ATTRS"); LOG_AND_RETURN("invalid %s operation", "ATTRS");
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("ATTRS"));
key + STRLEN("ATTRS"));
if (attr == NULL) if (attr == NULL)
LOG_AND_RETURN("error parsing %s attribute", "ATTRS"); LOG_AND_RETURN("error parsing %s attribute", "ATTRS");
@ -1160,8 +1155,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL); rule_add_key(&rule_tmp, TK_M_TAGS, op, value, NULL);
} else if (startswith(key, "ENV{")) { } else if (startswith(key, "ENV{")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("ENV"));
key + STRLEN("ENV"));
if (attr == NULL) if (attr == NULL)
LOG_AND_RETURN("error parsing %s attribute", "ENV"); LOG_AND_RETURN("error parsing %s attribute", "ENV");
@ -1207,8 +1201,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL); rule_add_key(&rule_tmp, TK_M_RESULT, op, value, NULL);
} else if (startswith(key, "IMPORT")) { } else if (startswith(key, "IMPORT")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("IMPORT"));
key + STRLEN("IMPORT"));
if (attr == NULL) { if (attr == NULL) {
LOG_RULE_WARNING("ignoring IMPORT{} with missing type"); LOG_RULE_WARNING("ignoring IMPORT{} with missing type");
continue; continue;
@ -1252,8 +1245,7 @@ static void add_rule(struct udev_rules *rules, char *line,
if (op > OP_MATCH_MAX) if (op > OP_MATCH_MAX)
LOG_AND_RETURN("invalid %s operation", "TEST"); LOG_AND_RETURN("invalid %s operation", "TEST");
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("TEST"));
key + STRLEN("TEST"));
if (attr != NULL) { if (attr != NULL) {
mode = strtol(attr, NULL, 8); mode = strtol(attr, NULL, 8);
rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode); rule_add_key(&rule_tmp, TK_M_TEST, op, value, &mode);
@ -1261,8 +1253,7 @@ static void add_rule(struct udev_rules *rules, char *line,
rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL); rule_add_key(&rule_tmp, TK_M_TEST, op, value, NULL);
} else if (startswith(key, "RUN")) { } else if (startswith(key, "RUN")) {
attr = get_key_attribute(rules->udev, attr = get_key_attribute(key + STRLEN("RUN"));
key + STRLEN("RUN"));
if (attr == NULL) if (attr == NULL)
attr = "program"; attr = "program";
if (op == OP_REMOVE) if (op == OP_REMOVE)
@ -1513,7 +1504,7 @@ static int parse_file(struct udev_rules *rules, const char *filename) {
return 0; return 0;
} }
struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) { struct udev_rules *udev_rules_new(int resolve_names) {
struct udev_rules *rules; struct udev_rules *rules;
struct udev_list file_list; struct udev_list file_list;
struct token end_token; struct token end_token;
@ -1523,9 +1514,8 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) {
rules = new0(struct udev_rules, 1); rules = new0(struct udev_rules, 1);
if (rules == NULL) if (rules == NULL)
return NULL; return NULL;
rules->udev = udev;
rules->resolve_names = resolve_names; rules->resolve_names = resolve_names;
udev_list_init(udev, &file_list, true); udev_list_init(NULL, &file_list, true);
/* init token array and string buffer */ /* init token array and string buffer */
rules->tokens = malloc_multiply(PREALLOC_TOKEN, sizeof(struct token)); rules->tokens = malloc_multiply(PREALLOC_TOKEN, sizeof(struct token));
@ -1690,7 +1680,7 @@ static int match_attr(struct udev_rules *rules, struct udev_device *dev, struct
return -1; return -1;
break; break;
case SB_SUBSYS: case SB_SUBSYS:
if (util_resolve_subsys_kernel(event->udev, name, vbuf, sizeof(vbuf), 1) != 0) if (util_resolve_subsys_kernel(name, vbuf, sizeof(vbuf), 1) != 0)
return -1; return -1;
value = vbuf; value = vbuf;
break; break;
@ -1923,7 +1913,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
int match; int match;
udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename), false); udev_event_apply_format(event, rules_str(rules, cur->key.value_off), filename, sizeof(filename), false);
if (util_resolve_subsys_kernel(event->udev, filename, filename, sizeof(filename), 0) != 0) { if (util_resolve_subsys_kernel(filename, filename, sizeof(filename), 0) != 0) {
if (filename[0] != '/') { if (filename[0] != '/') {
char tmp[UTIL_PATH_SIZE]; char tmp[UTIL_PATH_SIZE];
@ -2356,7 +2346,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
char value[UTIL_NAME_SIZE]; char value[UTIL_NAME_SIZE];
_cleanup_fclose_ FILE *f = NULL; _cleanup_fclose_ FILE *f = NULL;
if (util_resolve_subsys_kernel(event->udev, key_name, attr, sizeof(attr), 0) != 0) if (util_resolve_subsys_kernel(key_name, attr, sizeof(attr), 0) != 0)
strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL); strscpyl(attr, sizeof(attr), udev_device_get_syspath(event->dev), "/", key_name, NULL);
attr_subst_subdir(attr, sizeof(attr)); attr_subst_subdir(attr, sizeof(attr));

View File

@ -20,7 +20,7 @@ static int inotify_fd = -1;
* set to cloexec since we need our children to be able to add * set to cloexec since we need our children to be able to add
* watches for us * watches for us
*/ */
int udev_watch_init(struct udev *udev) { int udev_watch_init(void) {
inotify_fd = inotify_init1(IN_CLOEXEC); inotify_fd = inotify_init1(IN_CLOEXEC);
if (inotify_fd < 0) if (inotify_fd < 0)
log_error_errno(errno, "inotify_init failed: %m"); log_error_errno(errno, "inotify_init failed: %m");
@ -30,7 +30,7 @@ int udev_watch_init(struct udev *udev) {
/* move any old watches directory out of the way, and then restore /* move any old watches directory out of the way, and then restore
* the watches * the watches
*/ */
void udev_watch_restore(struct udev *udev) { void udev_watch_restore(void) {
if (inotify_fd < 0) if (inotify_fd < 0)
return; return;
@ -57,12 +57,12 @@ void udev_watch_restore(struct udev *udev) {
goto unlink; goto unlink;
device[len] = '\0'; device[len] = '\0';
dev = udev_device_new_from_device_id(udev, device); dev = udev_device_new_from_device_id(NULL, device);
if (dev == NULL) if (dev == NULL)
goto unlink; goto unlink;
log_debug("restoring old watch on '%s'", udev_device_get_devnode(dev)); log_debug("restoring old watch on '%s'", udev_device_get_devnode(dev));
udev_watch_begin(udev, dev); udev_watch_begin(dev);
udev_device_unref(dev); udev_device_unref(dev);
unlink: unlink:
(void) unlinkat(dirfd(dir), ent->d_name, 0); (void) unlinkat(dirfd(dir), ent->d_name, 0);
@ -75,7 +75,7 @@ unlink:
log_error_errno(errno, "unable to move watches dir /run/udev/watch; old watches will not be restored: %m"); log_error_errno(errno, "unable to move watches dir /run/udev/watch; old watches will not be restored: %m");
} }
void udev_watch_begin(struct udev *udev, struct udev_device *dev) { void udev_watch_begin(struct udev_device *dev) {
char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
int wd; int wd;
int r; int r;
@ -101,7 +101,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) {
udev_device_set_watch_handle(dev, wd); udev_device_set_watch_handle(dev, wd);
} }
void udev_watch_end(struct udev *udev, struct udev_device *dev) { void udev_watch_end(struct udev_device *dev) {
int wd; int wd;
char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
@ -121,7 +121,7 @@ void udev_watch_end(struct udev *udev, struct udev_device *dev) {
udev_device_set_watch_handle(dev, -1); udev_device_set_watch_handle(dev, -1);
} }
struct udev_device *udev_watch_lookup(struct udev *udev, int wd) { struct udev_device *udev_watch_lookup(int wd) {
char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)]; char filename[sizeof("/run/udev/watch/") + DECIMAL_STR_MAX(int)];
char device[UTIL_NAME_SIZE]; char device[UTIL_NAME_SIZE];
ssize_t len; ssize_t len;
@ -135,5 +135,5 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd) {
return NULL; return NULL;
device[len] = '\0'; device[len] = '\0';
return udev_device_new_from_device_id(udev, device); return udev_device_new_from_device_id(NULL, device);
} }

View File

@ -19,7 +19,6 @@
#include "util.h" #include "util.h"
struct udev_event { struct udev_event {
struct udev *udev;
struct udev_device *dev; struct udev_device *dev;
struct udev_device *dev_parent; struct udev_device *dev_parent;
struct udev_device *dev_db; struct udev_device *dev_db;
@ -48,15 +47,9 @@ struct udev_event {
bool run_final; bool run_final;
}; };
struct udev_watch {
struct udev_list_node node;
int handle;
char *name;
};
/* udev-rules.c */ /* udev-rules.c */
struct udev_rules; struct udev_rules;
struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names); struct udev_rules *udev_rules_new(int resolve_names);
struct udev_rules *udev_rules_unref(struct udev_rules *rules); struct udev_rules *udev_rules_unref(struct udev_rules *rules);
bool udev_rules_check_timestamp(struct udev_rules *rules); bool udev_rules_check_timestamp(struct udev_rules *rules);
void udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event, void udev_rules_apply_to_event(struct udev_rules *rules, struct udev_event *event,
@ -82,14 +75,14 @@ void udev_event_execute_rules(struct udev_event *event,
struct udev_list *properties_list, struct udev_list *properties_list,
struct udev_rules *rules); struct udev_rules *rules);
void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec); void udev_event_execute_run(struct udev_event *event, usec_t timeout_usec, usec_t timeout_warn_usec);
int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); int udev_build_argv(char *cmd, int *argc, char *argv[]);
/* udev-watch.c */ /* udev-watch.c */
int udev_watch_init(struct udev *udev); int udev_watch_init(void);
void udev_watch_restore(struct udev *udev); void udev_watch_restore(void);
void udev_watch_begin(struct udev *udev, struct udev_device *dev); void udev_watch_begin(struct udev_device *dev);
void udev_watch_end(struct udev *udev, struct udev_device *dev); void udev_watch_end(struct udev_device *dev);
struct udev_device *udev_watch_lookup(struct udev *udev, int wd); struct udev_device *udev_watch_lookup(int wd);
/* udev-node.c */ /* udev-node.c */
void udev_node_add(struct udev_device *dev, bool apply, void udev_node_add(struct udev_device *dev, bool apply,
@ -100,12 +93,11 @@ void udev_node_update_old_links(struct udev_device *dev, struct udev_device *dev
/* udev-ctrl.c */ /* udev-ctrl.c */
struct udev_ctrl; struct udev_ctrl;
struct udev_ctrl *udev_ctrl_new(struct udev *udev); struct udev_ctrl *udev_ctrl_new(void);
struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd); struct udev_ctrl *udev_ctrl_new_from_fd(int fd);
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl); int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl); struct udev_ctrl *udev_ctrl_unref(struct udev_ctrl *uctrl);
int udev_ctrl_cleanup(struct udev_ctrl *uctrl); int udev_ctrl_cleanup(struct udev_ctrl *uctrl);
struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl);
int udev_ctrl_get_fd(struct udev_ctrl *uctrl); int udev_ctrl_get_fd(struct udev_ctrl *uctrl);
int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout); int udev_ctrl_send_set_log_level(struct udev_ctrl *uctrl, int priority, int timeout);
int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout); int udev_ctrl_send_stop_exec_queue(struct udev_ctrl *uctrl, int timeout);
@ -156,9 +148,9 @@ struct udev_builtin {
const char *name; const char *name;
int (*cmd)(struct udev_device *dev, int argc, char *argv[], bool test); int (*cmd)(struct udev_device *dev, int argc, char *argv[], bool test);
const char *help; const char *help;
int (*init)(struct udev *udev); int (*init)(void);
void (*exit)(struct udev *udev); void (*exit)(void);
bool (*validate)(struct udev *udev); bool (*validate)(void);
bool run_once; bool run_once;
}; };
#if HAVE_BLKID #if HAVE_BLKID
@ -176,14 +168,14 @@ extern const struct udev_builtin udev_builtin_net_setup_link;
extern const struct udev_builtin udev_builtin_path_id; extern const struct udev_builtin udev_builtin_path_id;
extern const struct udev_builtin udev_builtin_usb_id; extern const struct udev_builtin udev_builtin_usb_id;
extern const struct udev_builtin udev_builtin_uaccess; extern const struct udev_builtin udev_builtin_uaccess;
void udev_builtin_init(struct udev *udev); void udev_builtin_init(void);
void udev_builtin_exit(struct udev *udev); void udev_builtin_exit(void);
enum udev_builtin_cmd udev_builtin_lookup(const char *command); enum udev_builtin_cmd udev_builtin_lookup(const char *command);
const char *udev_builtin_name(enum udev_builtin_cmd cmd); const char *udev_builtin_name(enum udev_builtin_cmd cmd);
bool udev_builtin_run_once(enum udev_builtin_cmd cmd); bool udev_builtin_run_once(enum udev_builtin_cmd cmd);
int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test); int udev_builtin_run(struct udev_device *dev, enum udev_builtin_cmd cmd, const char *command, bool test);
void udev_builtin_list(struct udev *udev); void udev_builtin_list(void);
bool udev_builtin_validate(struct udev *udev); bool udev_builtin_validate(void);
int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val); int udev_builtin_add_property(struct udev_device *dev, bool test, const char *key, const char *val);
int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias,
const char *filter, bool test); const char *filter, bool test);
@ -194,19 +186,3 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_rules*, udev_rules_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl*, udev_ctrl_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_connection*, udev_ctrl_connection_unref);
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref); DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev_ctrl_msg*, udev_ctrl_msg_unref);
/* udevadm commands */
struct udevadm_cmd {
const char *name;
int (*cmd)(struct udev *udev, int argc, char *argv[]);
const char *help;
int debug;
};
extern const struct udevadm_cmd udevadm_info;
extern const struct udevadm_cmd udevadm_trigger;
extern const struct udevadm_cmd udevadm_settle;
extern const struct udevadm_cmd udevadm_control;
extern const struct udevadm_cmd udevadm_monitor;
extern const struct udevadm_cmd udevadm_hwdb;
extern const struct udevadm_cmd udevadm_test;
extern const struct udevadm_cmd udevadm_test_builtin;

View File

@ -19,12 +19,13 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "parse-util.h"
#include "process-util.h" #include "process-util.h"
#include "time-util.h" #include "time-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm-util.h" #include "udevadm.h"
static void print_help(void) { static int help(void) {
printf("%s control OPTION\n\n" printf("%s control OPTION\n\n"
"Control the udev daemon.\n\n" "Control the udev daemon.\n\n"
" -h --help Show this help\n" " -h --help Show this help\n"
@ -38,12 +39,14 @@ static void print_help(void) {
" -m --children-max=N Maximum number of children\n" " -m --children-max=N Maximum number of children\n"
" -t --timeout=SECONDS Maximum time to block for a reply\n" " -t --timeout=SECONDS Maximum time to block for a reply\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_control(struct udev *udev, int argc, char *argv[]) { int control_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL; _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
int timeout = 60; int timeout = 60;
int rc = 1, c; int c, r;
static const struct option options[] = { static const struct option options[] = {
{ "exit", no_argument, NULL, 'e' }, { "exit", no_argument, NULL, 'e' },
@ -61,80 +64,73 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) {
{} {}
}; };
if (must_be_root() < 0) r = must_be_root();
return 1; if (r < 0)
return r;
uctrl = udev_ctrl_new(udev); if (argc <= 1)
if (uctrl == NULL) log_error("Option missing");
return 2;
uctrl = udev_ctrl_new();
if (!uctrl)
return -ENOMEM;
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'e': case 'e':
if (udev_ctrl_send_exit(uctrl, timeout) < 0) r = udev_ctrl_send_exit(uctrl, timeout);
rc = 2; if (r < 0)
else return r;
rc = 0;
break; break;
case 'l': { case 'l': {
int i; int i;
i = util_log_priority(optarg); i = util_log_priority(optarg);
if (i < 0) { if (i < 0)
log_error("invalid number '%s'", optarg); return log_error_errno(i, "invalid number '%s'", optarg);
return rc;
} r = udev_ctrl_send_set_log_level(uctrl, i, timeout);
if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0) if (r < 0)
rc = 2; return r;
else
rc = 0;
break; break;
} }
case 's': case 's':
if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0) r = udev_ctrl_send_stop_exec_queue(uctrl, timeout);
rc = 2; if (r < 0)
else return r;
rc = 0;
break; break;
case 'S': case 'S':
if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0) r = udev_ctrl_send_start_exec_queue(uctrl, timeout);
rc = 2; if (r < 0)
else return r;
rc = 0;
break; break;
case 'R': case 'R':
if (udev_ctrl_send_reload(uctrl, timeout) < 0) r = udev_ctrl_send_reload(uctrl, timeout);
rc = 2; if (r < 0)
else return r;
rc = 0;
break; break;
case 'p': case 'p':
if (strchr(optarg, '=') == NULL) { if (!strchr(optarg, '=')) {
log_error("expect <KEY>=<value> instead of '%s'", optarg); log_error("expect <KEY>=<value> instead of '%s'", optarg);
return rc; return -EINVAL;
} }
if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0) r = udev_ctrl_send_set_env(uctrl, optarg, timeout);
rc = 2; if (r < 0)
else return r;
rc = 0;
break; break;
case 'm': { case 'm': {
char *endp; unsigned i;
int i;
i = strtoul(optarg, &endp, 0); r = safe_atou(optarg, &i);
if (endp[0] != '\0' || i < 1) { if (r < 0)
log_error("invalid number '%s'", optarg); return log_error_errno(r, "Failed to parse maximum number of events '%s': %m", optarg);
return rc;
} r = udev_ctrl_send_set_children_max(uctrl, i, timeout);
if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0) if (r < 0)
rc = 2; return r;
else
rc = 0;
break; break;
} }
case 't': { case 't': {
int r, seconds;
usec_t s; usec_t s;
r = parse_sec(optarg, &s); r = parse_sec(optarg, &s);
@ -142,33 +138,28 @@ static int adm_control(struct udev *udev, int argc, char *argv[]) {
return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg); return log_error_errno(r, "Failed to parse timeout value '%s'.", optarg);
if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX) if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
log_error("Timeout value is out of range."); log_error("Timeout value is out of range, ignoring.");
else { else
seconds = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX; timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
timeout = seconds;
rc = 0;
}
break; break;
} }
case 'V': case 'V':
print_version(); return version();
rc = 0;
break;
case 'h': case 'h':
print_help(); return help();
rc = 0; case '?':
break; return -EINVAL;
default:
assert_not_reached("Unknown option.");
} }
if (optind < argc) if (optind < argc) {
log_error("Extraneous argument: %s", argv[optind]); log_error("Extraneous argument: %s", argv[optind]);
else if (optind == 1) return -EINVAL;
} else if (optind == 1) {
log_error("Option missing"); log_error("Option missing");
return rc; return -EINVAL;
} }
const struct udevadm_cmd udevadm_control = { return 0;
.name = "control", }
.cmd = adm_control,
.help = "Control the udev daemon",
};

View File

@ -13,10 +13,11 @@
#include "hwdb-util.h" #include "hwdb-util.h"
#include "label.h" #include "label.h"
#include "mkdir.h" #include "mkdir.h"
#include "path-util.h"
#include "strbuf.h" #include "strbuf.h"
#include "string-util.h" #include "string-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm-util.h" #include "udevadm.h"
#include "util.h" #include "util.h"
/* /*
@ -24,6 +25,12 @@
* Uses a Patricia/radix trie to index all matches for efficient lookup. * Uses a Patricia/radix trie to index all matches for efficient lookup.
*/ */
static const char *arg_test = NULL;
static const char *arg_root = NULL;
static const char *arg_hwdb_bin_dir = "/etc/udev";
static bool arg_update = false;
static bool arg_strict = false;
static const char * const conf_file_dirs[] = { static const char * const conf_file_dirs[] = {
"/etc/udev/hwdb.d", "/etc/udev/hwdb.d",
UDEVLIBEXECDIR "/hwdb.d", UDEVLIBEXECDIR "/hwdb.d",
@ -107,6 +114,9 @@ static struct trie_node *node_lookup(const struct trie_node *node, uint8_t c) {
static void trie_node_cleanup(struct trie_node *node) { static void trie_node_cleanup(struct trie_node *node) {
size_t i; size_t i;
if (!node)
return;
for (i = 0; i < node->children_count; i++) for (i = 0; i < node->children_count; i++)
trie_node_cleanup(node->children[i].child); trie_node_cleanup(node->children[i].child);
free(node->children); free(node->children);
@ -114,6 +124,17 @@ static void trie_node_cleanup(struct trie_node *node) {
free(node); free(node);
} }
static void trie_free(struct trie *trie) {
if (!trie)
return;
trie_node_cleanup(trie->root);
strbuf_cleanup(trie->strings);
free(trie);
}
DEFINE_TRIVIAL_CLEANUP_FUNC(struct trie*, trie_free);
static int trie_values_cmp(const void *v1, const void *v2, void *arg) { static int trie_values_cmp(const void *v1, const void *v2, void *arg) {
const struct trie_value_entry *val1 = v1; const struct trie_value_entry *val1 = v1;
const struct trie_value_entry *val2 = v2; const struct trie_value_entry *val2 = v2;
@ -436,7 +457,7 @@ static int insert_data(struct trie *trie, struct udev_list *match_list,
return 0; return 0;
} }
static int import_file(struct udev *udev, struct trie *trie, const char *filename) { static int import_file(struct trie *trie, const char *filename) {
enum { enum {
HW_MATCH, HW_MATCH,
HW_DATA, HW_DATA,
@ -447,7 +468,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
struct udev_list match_list; struct udev_list match_list;
int r = 0, err; int r = 0, err;
udev_list_init(udev, &match_list, false); udev_list_init(NULL, &match_list, false);
f = fopen(filename, "re"); f = fopen(filename, "re");
if (f == NULL) if (f == NULL)
@ -538,7 +559,87 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
return r; return r;
} }
static void help(void) { static int hwdb_update(void) {
_cleanup_(trie_freep) struct trie *trie = NULL;
_cleanup_strv_free_ char **files = NULL;
_cleanup_free_ char *hwdb_bin = NULL;
char **f;
int r;
trie = new0(struct trie, 1);
if (!trie)
return -ENOMEM;
/* string store */
trie->strings = strbuf_new();
if (!trie->strings)
return -ENOMEM;
/* index */
trie->root = new0(struct trie_node, 1);
if (!trie->root)
return -ENOMEM;
trie->nodes_count++;
r = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs);
if (r < 0)
return log_error_errno(r, "failed to enumerate hwdb files: %m");
STRV_FOREACH(f, files) {
log_debug("Reading file '%s'", *f);
r = import_file(trie, *f);
if (r < 0 && arg_strict)
return r;
}
strbuf_complete(trie->strings);
log_debug("=== trie in-memory ===");
log_debug("nodes: %8zu bytes (%8zu)",
trie->nodes_count * sizeof(struct trie_node), trie->nodes_count);
log_debug("children arrays: %8zu bytes (%8zu)",
trie->children_count * sizeof(struct trie_child_entry), trie->children_count);
log_debug("values arrays: %8zu bytes (%8zu)",
trie->values_count * sizeof(struct trie_value_entry), trie->values_count);
log_debug("strings: %8zu bytes",
trie->strings->len);
log_debug("strings incoming: %8zu bytes (%8zu)",
trie->strings->in_len, trie->strings->in_count);
log_debug("strings dedup'ed: %8zu bytes (%8zu)",
trie->strings->dedup_len, trie->strings->dedup_count);
hwdb_bin = path_join(arg_root, arg_hwdb_bin_dir, "/hwdb.bin");
if (!hwdb_bin)
return -ENOMEM;
mkdir_parents_label(hwdb_bin, 0755);
r = trie_store(trie, hwdb_bin);
if (r < 0)
log_error_errno(r, "Failed to write database %s: %m", hwdb_bin);
(void) label_fix(hwdb_bin, 0);
return r;
}
static int hwdb_test(void) {
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
const char *key, *value;
int r;
r = sd_hwdb_new(&hwdb);
if (r < 0)
return r;
SD_HWDB_FOREACH_PROPERTY(hwdb, arg_test, key, value)
printf("%s=%s\n", key, value);
return 0;
}
static int help(void) {
printf("%s hwdb [OPTIONS]\n\n" printf("%s hwdb [OPTIONS]\n\n"
" -h --help Print this message\n" " -h --help Print this message\n"
" -V --version Print version of the program\n" " -V --version Print version of the program\n"
@ -551,9 +652,11 @@ static void help(void) {
"The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n" "The sub-command 'hwdb' is deprecated, and is left for backwards compatibility.\n"
"Please use systemd-hwdb instead.\n" "Please use systemd-hwdb instead.\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_hwdb(struct udev *udev, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
enum { enum {
ARG_USR = 0x100, ARG_USR = 0x100,
}; };
@ -568,144 +671,59 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{} {}
}; };
const char *test = NULL;
const char *root = ""; int c;
const char *hwdb_bin_dir = "/etc/udev";
bool update = false;
struct trie *trie = NULL;
int err, c;
int rc = EXIT_SUCCESS;
bool strict = false;
while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0)
switch(c) { switch(c) {
case 'u': case 'u':
update = true; arg_update = true;
break; break;
case ARG_USR: case ARG_USR:
hwdb_bin_dir = UDEVLIBEXECDIR; arg_hwdb_bin_dir = UDEVLIBEXECDIR;
break; break;
case 's': case 's':
strict = true; arg_strict = true;
break; break;
case 't': case 't':
test = optarg; arg_test = optarg;
break; break;
case 'r': case 'r':
root = optarg; arg_root = optarg;
break; break;
case 'V': case 'V':
print_version(); return version();
return EXIT_SUCCESS;
case 'h': case 'h':
help(); return help();
return EXIT_SUCCESS;
case '?': case '?':
return EXIT_FAILURE; return -EINVAL;
default: default:
assert_not_reached("Unknown option"); assert_not_reached("Unknown option");
} }
if (!update && !test) { return 1;
log_error("Either --update or --test must be used");
return EXIT_FAILURE;
}
if (update) {
char **files, **f;
_cleanup_free_ char *hwdb_bin = NULL;
trie = new0(struct trie, 1);
if (!trie) {
rc = EXIT_FAILURE;
goto out;
}
/* string store */
trie->strings = strbuf_new();
if (!trie->strings) {
rc = EXIT_FAILURE;
goto out;
}
/* index */
trie->root = new0(struct trie_node, 1);
if (!trie->root) {
rc = EXIT_FAILURE;
goto out;
}
trie->nodes_count++;
err = conf_files_list_strv(&files, ".hwdb", root, 0, conf_file_dirs);
if (err < 0) {
log_error_errno(err, "failed to enumerate hwdb files: %m");
rc = EXIT_FAILURE;
goto out;
}
STRV_FOREACH(f, files) {
log_debug("reading file '%s'", *f);
if (import_file(udev, trie, *f) < 0 && strict)
rc = EXIT_FAILURE;
}
strv_free(files);
strbuf_complete(trie->strings);
log_debug("=== trie in-memory ===");
log_debug("nodes: %8zu bytes (%8zu)",
trie->nodes_count * sizeof(struct trie_node), trie->nodes_count);
log_debug("children arrays: %8zu bytes (%8zu)",
trie->children_count * sizeof(struct trie_child_entry), trie->children_count);
log_debug("values arrays: %8zu bytes (%8zu)",
trie->values_count * sizeof(struct trie_value_entry), trie->values_count);
log_debug("strings: %8zu bytes",
trie->strings->len);
log_debug("strings incoming: %8zu bytes (%8zu)",
trie->strings->in_len, trie->strings->in_count);
log_debug("strings dedup'ed: %8zu bytes (%8zu)",
trie->strings->dedup_len, trie->strings->dedup_count);
hwdb_bin = strjoin(root, "/", hwdb_bin_dir, "/hwdb.bin");
if (!hwdb_bin) {
rc = EXIT_FAILURE;
goto out;
}
mkdir_parents_label(hwdb_bin, 0755);
err = trie_store(trie, hwdb_bin);
if (err < 0) {
log_error_errno(err, "Failure writing database %s: %m", hwdb_bin);
rc = EXIT_FAILURE;
}
(void) label_fix(hwdb_bin, 0);
}
if (test) {
_cleanup_(sd_hwdb_unrefp) sd_hwdb *hwdb = NULL;
int r;
r = sd_hwdb_new(&hwdb);
if (r >= 0) {
const char *key, *value;
SD_HWDB_FOREACH_PROPERTY(hwdb, test, key, value)
printf("%s=%s\n", key, value);
}
}
out:
if (trie) {
if (trie->root)
trie_node_cleanup(trie->root);
if (trie->strings)
strbuf_cleanup(trie->strings);
free(trie);
}
return rc;
} }
const struct udevadm_cmd udevadm_hwdb = { int hwdb_main(int argc, char *argv[], void *userdata) {
.name = "hwdb", int r;
.cmd = adm_hwdb,
}; r = parse_argv(argc, argv);
if (r < 0)
return r;
if (!arg_update && !arg_test) {
log_error("Either --update or --test must be used.");
return -EINVAL;
}
if (arg_update) {
r = hwdb_update();
if (r < 0)
return r;
}
if (arg_test)
return hwdb_test();
return 0;
}

View File

@ -14,6 +14,7 @@
#include "fd-util.h" #include "fd-util.h"
#include "string-util.h" #include "string-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm.h"
#include "udevadm-util.h" #include "udevadm-util.h"
static bool skip_attribute(const char *name) { static bool skip_attribute(const char *name) {
@ -155,11 +156,11 @@ static int stat_device(const char *name, bool export, const char *prefix) {
return 0; return 0;
} }
static int export_devices(struct udev *udev) { static int export_devices(void) {
_cleanup_(udev_enumerate_unrefp) struct udev_enumerate *udev_enumerate; _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *udev_enumerate;
struct udev_list_entry *list_entry; struct udev_list_entry *list_entry;
udev_enumerate = udev_enumerate_new(udev); udev_enumerate = udev_enumerate_new(NULL);
if (udev_enumerate == NULL) if (udev_enumerate == NULL)
return -ENOMEM; return -ENOMEM;
@ -167,7 +168,7 @@ static int export_devices(struct udev *udev) {
udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) { udev_list_entry_foreach(list_entry, udev_enumerate_get_list_entry(udev_enumerate)) {
_cleanup_(udev_device_unrefp) struct udev_device *device; _cleanup_(udev_device_unrefp) struct udev_device *device;
device = udev_device_new_from_syspath(udev, udev_list_entry_get_name(list_entry)); device = udev_device_new_from_syspath(NULL, udev_list_entry_get_name(list_entry));
if (device != NULL) if (device != NULL)
print_record(device); print_record(device);
} }
@ -203,7 +204,7 @@ static void cleanup_dir(DIR *dir, mode_t mask, int depth) {
} }
} }
static void cleanup_db(struct udev *udev) { static void cleanup_db(void) {
_cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL, *dir5 = NULL; _cleanup_closedir_ DIR *dir1 = NULL, *dir2 = NULL, *dir3 = NULL, *dir4 = NULL, *dir5 = NULL;
(void) unlink("/run/udev/queue.bin"); (void) unlink("/run/udev/queue.bin");
@ -229,7 +230,7 @@ static void cleanup_db(struct udev *udev) {
cleanup_dir(dir5, 0, 1); cleanup_dir(dir5, 0, 1);
} }
static void help(void) { static int help(void) {
printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n" printf("%s info [OPTIONS] [DEVPATH|FILE]\n\n"
"Query sysfs or the udev database.\n\n" "Query sysfs or the udev database.\n\n"
@ -252,16 +253,18 @@ static void help(void) {
" -e --export-db Export the content of the udev database\n" " -e --export-db Export the content of the udev database\n"
" -c --cleanup-db Clean up the udev database\n" " -c --cleanup-db Clean up the udev database\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int uinfo(struct udev *udev, int argc, char *argv[]) { int info_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_device_unrefp) struct udev_device *device = NULL; _cleanup_(udev_device_unrefp) struct udev_device *device = NULL;
bool root = 0; bool root = 0;
bool export = 0; bool export = 0;
const char *export_prefix = NULL; const char *export_prefix = NULL;
char name[UTIL_PATH_SIZE]; char name[UTIL_PATH_SIZE];
struct udev_list_entry *list_entry; struct udev_list_entry *list_entry;
int c; int c, r;
static const struct option options[] = { static const struct option options[] = {
{ "name", required_argument, NULL, 'n' }, { "name", required_argument, NULL, 'n' },
@ -295,30 +298,25 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
while ((c = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "aced:n:p:q:rxP:RVh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'n': { case 'n':
if (device != NULL) { if (device) {
fprintf(stderr, "device already specified\n"); log_error("device already specified");
return 2; return -EINVAL;
} }
device = find_device(udev, optarg, "/dev/"); device = find_device(optarg, "/dev/");
if (device == NULL) { if (!device)
fprintf(stderr, "device node not found\n"); return log_error_errno(errno, "device node not found: %m");
return 2;
}
break; break;
}
case 'p': case 'p':
if (device != NULL) { if (device) {
fprintf(stderr, "device already specified\n"); log_error("device already specified");
return 2; return -EINVAL;
} }
device = find_device(udev, optarg, "/sys"); device = find_device(optarg, "/sys");
if (device == NULL) { if (!device)
fprintf(stderr, "syspath not found\n"); return log_error_errno(errno, "syspath not found: %m");
return 2;
}
break; break;
case 'q': case 'q':
action = ACTION_QUERY; action = ACTION_QUERY;
@ -333,8 +331,8 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
else if (streq(optarg, "all")) else if (streq(optarg, "all"))
query = QUERY_ALL; query = QUERY_ALL;
else { else {
fprintf(stderr, "unknown query type\n"); log_error("unknown query type");
return 3; return -EINVAL;
} }
break; break;
case 'r': case 'r':
@ -348,11 +346,9 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
action = ACTION_ATTRIBUTE_WALK; action = ACTION_ATTRIBUTE_WALK;
break; break;
case 'e': case 'e':
if (export_devices(udev) < 0) return export_devices();
return 1;
return 0;
case 'c': case 'c':
cleanup_db(udev); cleanup_db();
return 0; return 0;
case 'x': case 'x':
export = true; export = true;
@ -361,13 +357,13 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
export_prefix = optarg; export_prefix = optarg;
break; break;
case 'V': case 'V':
print_version(); return version();
return 0;
case 'h': case 'h':
help(); return help();
return 0; case '?':
return -EINVAL;
default: default:
return 1; assert_not_reached("Unknown option");
} }
switch (action) { switch (action) {
@ -375,12 +371,12 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
if (!device) { if (!device) {
if (!argv[optind]) { if (!argv[optind]) {
help(); help();
return 2; return -EINVAL;
} }
device = find_device(udev, argv[optind], NULL); device = find_device(argv[optind], NULL);
if (!device) { if (!device) {
fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n"); log_error("Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.");
return 4; return -EINVAL;
} }
} }
@ -388,10 +384,8 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
case QUERY_NAME: { case QUERY_NAME: {
const char *node = udev_device_get_devnode(device); const char *node = udev_device_get_devnode(device);
if (node == NULL) { if (!node)
fprintf(stderr, "no device node found\n"); return log_error_errno(errno, "no device node found");
return 5;
}
if (root) if (root)
printf("%s\n", udev_device_get_devnode(device)); printf("%s\n", udev_device_get_devnode(device));
@ -402,14 +396,14 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
} }
case QUERY_SYMLINK: case QUERY_SYMLINK:
list_entry = udev_device_get_devlinks_list_entry(device); list_entry = udev_device_get_devlinks_list_entry(device);
while (list_entry != NULL) { while (list_entry) {
if (root) if (root)
printf("%s", udev_list_entry_get_name(list_entry)); printf("%s", udev_list_entry_get_name(list_entry));
else else
printf("%s", printf("%s",
udev_list_entry_get_name(list_entry) + STRLEN("/dev/")); udev_list_entry_get_name(list_entry) + STRLEN("/dev/"));
list_entry = udev_list_entry_get_next(list_entry); list_entry = udev_list_entry_get_next(list_entry);
if (list_entry != NULL) if (list_entry)
printf(" "); printf(" ");
} }
printf("\n"); printf("\n");
@ -419,7 +413,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
return 0; return 0;
case QUERY_PROPERTY: case QUERY_PROPERTY:
list_entry = udev_device_get_properties_list_entry(device); list_entry = udev_device_get_properties_list_entry(device);
while (list_entry != NULL) { while (list_entry) {
if (export) if (export)
printf("%s%s='%s'\n", strempty(export_prefix), printf("%s%s='%s'\n", strempty(export_prefix),
udev_list_entry_get_name(list_entry), udev_list_entry_get_name(list_entry),
@ -439,29 +433,24 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
break; break;
case ACTION_ATTRIBUTE_WALK: case ACTION_ATTRIBUTE_WALK:
if (!device && argv[optind]) { if (!device && argv[optind]) {
device = find_device(udev, argv[optind], NULL); device = find_device(argv[optind], NULL);
if (!device) { if (!device) {
fprintf(stderr, "Unknown device, absolute path in /dev/ or /sys expected.\n"); log_error("Unknown device, absolute path in /dev/ or /sys expected.");
return 4; return -EINVAL;
} }
} }
if (!device) { if (!device) {
fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n"); log_error("Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.");
return 4; return -EINVAL;
} }
print_device_chain(device); print_device_chain(device);
break; break;
case ACTION_DEVICE_ID_FILE: case ACTION_DEVICE_ID_FILE:
if (stat_device(name, export, export_prefix) != 0) r = stat_device(name, export, export_prefix);
return 1; if (r < 0)
return r;
break; break;
} }
return 0; return 0;
} }
const struct udevadm_cmd udevadm_info = {
.name = "info",
.cmd = uinfo,
.help = "Query sysfs or the udev database",
};

View File

@ -10,40 +10,113 @@
#include <sys/time.h> #include <sys/time.h>
#include <time.h> #include <time.h>
#include "libudev.h"
#include "sd-device.h"
#include "alloc-util.h"
#include "device-util.h"
#include "fd-util.h" #include "fd-util.h"
#include "format-util.h" #include "format-util.h"
#include "udev.h" #include "hashmap.h"
#include "udevadm-util.h" #include "libudev-private.h"
#include "set.h"
#include "string-util.h"
#include "udevadm.h"
static bool udev_exit; static bool udev_exit = false;
static bool arg_show_property = false;
static bool arg_print_kernel = false;
static bool arg_print_udev = false;
static Set *arg_tag_filter = NULL;
static Hashmap *arg_subsystem_filter = NULL;
static void sig_handler(int signum) { static void sig_handler(int signum) {
if (IN_SET(signum, SIGINT, SIGTERM)) if (IN_SET(signum, SIGINT, SIGTERM))
udev_exit = true; udev_exit = true;
} }
static void print_device(struct udev_device *device, const char *source, int prop) { static int receive_and_print_device(struct udev_monitor *monitor, const char *source) {
const char *action = NULL, *devpath = NULL, *subsystem = NULL;
_cleanup_(sd_device_unrefp) sd_device *device = NULL;
struct timespec ts; struct timespec ts;
int r;
r = udev_monitor_receive_sd_device(monitor, &device);
if (r < 0)
return log_debug_errno(r, "Failed to receive device from %s, ignoring: %m", source);
(void) sd_device_get_property_value(device, "ACTION", &action);
(void) sd_device_get_devpath(device, &devpath);
(void) sd_device_get_subsystem(device, &subsystem);
assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0); assert_se(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n", printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n",
source, source,
ts.tv_sec, (nsec_t)ts.tv_nsec/1000, ts.tv_sec, (nsec_t)ts.tv_nsec/1000,
udev_device_get_action(device), action, devpath, subsystem);
udev_device_get_devpath(device),
udev_device_get_subsystem(device)); if (arg_show_property) {
if (prop) { const char *key, *value;
struct udev_list_entry *list_entry;
FOREACH_DEVICE_PROPERTY(device, key, value)
printf("%s=%s\n", key, value);
udev_list_entry_foreach(list_entry, udev_device_get_properties_list_entry(device))
printf("%s=%s\n",
udev_list_entry_get_name(list_entry),
udev_list_entry_get_value(list_entry));
printf("\n"); printf("\n");
} }
return 0;
} }
static void help(void) { static int setup_monitor(const char *sender, int fd_epoll, struct udev_monitor **ret) {
_cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL;
const char *subsystem, *devtype, *tag;
struct epoll_event ep = {};
Iterator i;
int fd, r;
monitor = udev_monitor_new_from_netlink(NULL, sender);
if (!monitor)
return log_error_errno(errno, "Failed to create netlink socket: %m");
r = udev_monitor_set_receive_buffer_size(monitor, 128*1024*1024);
if (r < 0)
return log_error_errno(r, "Failed to set receive buffer size: %m");
fd = udev_monitor_get_fd(monitor);
if (fd < 0)
return log_error_errno(r, "Failed to get socket fd for monitoring: %m");
HASHMAP_FOREACH_KEY(devtype, subsystem, arg_subsystem_filter, i) {
r = udev_monitor_filter_add_match_subsystem_devtype(monitor, subsystem, devtype);
if (r < 0)
return log_error_errno(r, "Failed to apply subsystem filter '%s%s%s': %m",
subsystem, devtype ? "/" : "", strempty(devtype));
}
SET_FOREACH(tag, arg_tag_filter, i) {
r = udev_monitor_filter_add_match_tag(monitor, tag);
if (r < 0)
return log_error_errno(r, "Failed to apply tag filter '%s': %m", tag);
}
r = udev_monitor_enable_receiving(monitor);
if (r < 0)
return log_error_errno(r, "Failed to subscribe %s events: %m", sender);
ep = (struct epoll_event) {
.events = EPOLLIN,
.data.fd = fd,
};
if (epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd, &ep) < 0)
return log_error_errno(errno, "Failed to add fd to epoll: %m");
*ret = TAKE_PTR(monitor);
return fd;
}
static int help(void) {
printf("%s monitor [OPTIONS]\n\n" printf("%s monitor [OPTIONS]\n\n"
"Listen to kernel and udev events.\n\n" "Listen to kernel and udev events.\n\n"
" -h --help Show this help\n" " -h --help Show this help\n"
@ -54,23 +127,11 @@ static void help(void) {
" -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n" " -s --subsystem-match=SUBSYSTEM[/DEVTYPE] Filter events by subsystem\n"
" -t --tag-match=TAG Filter events by tag\n" " -t --tag-match=TAG Filter events by tag\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_monitor(struct udev *udev, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
struct sigaction act = {};
sigset_t mask;
bool prop = false;
bool print_kernel = false;
bool print_udev = false;
_cleanup_(udev_list_cleanup) struct udev_list subsystem_match_list;
_cleanup_(udev_list_cleanup) struct udev_list tag_match_list;
_cleanup_(udev_monitor_unrefp) struct udev_monitor *udev_monitor = NULL;
_cleanup_(udev_monitor_unrefp) struct udev_monitor *kernel_monitor = NULL;
_cleanup_close_ int fd_ep = -1;
int fd_kernel = -1, fd_udev = -1;
struct epoll_event ep_kernel, ep_udev;
int c;
static const struct option options[] = { static const struct option options[] = {
{ "property", no_argument, NULL, 'p' }, { "property", no_argument, NULL, 'p' },
{ "environment", no_argument, NULL, 'e' }, /* alias for -p */ { "environment", no_argument, NULL, 'e' }, /* alias for -p */
@ -83,56 +144,101 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
{} {}
}; };
udev_list_init(udev, &subsystem_match_list, true); int r, c;
udev_list_init(udev, &tag_match_list, true);
while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'p': case 'p':
case 'e': case 'e':
prop = true; arg_show_property = true;
break; break;
case 'k': case 'k':
print_kernel = true; arg_print_kernel = true;
break; break;
case 'u': case 'u':
print_udev = true; arg_print_udev = true;
break; break;
case 's': case 's': {
{ _cleanup_free_ char *subsystem = NULL, *devtype = NULL;
char subsys[UTIL_NAME_SIZE]; const char *slash;
char *devtype;
strscpy(subsys, sizeof(subsys), optarg); slash = strchr(optarg, '/');
devtype = strchr(subsys, '/'); if (slash) {
if (devtype != NULL) { devtype = strdup(devtype + 1);
devtype[0] = '\0'; if (!devtype)
devtype++; return -ENOMEM;
}
udev_list_entry_add(&subsystem_match_list, subsys, devtype); subsystem = strndup(optarg, devtype - optarg);
break; } else
} subsystem = strdup(optarg);
case 't':
udev_list_entry_add(&tag_match_list, optarg, NULL); if (!subsystem)
return -ENOMEM;
r = hashmap_ensure_allocated(&arg_subsystem_filter, NULL);
if (r < 0)
return r;
r = hashmap_put(arg_subsystem_filter, subsystem, devtype);
if (r < 0)
return r;
subsystem = devtype = NULL;
break; break;
}
case 't': {
_cleanup_free_ char *tag = NULL;
r = set_ensure_allocated(&arg_tag_filter, &string_hash_ops);
if (r < 0)
return r;
tag = strdup(optarg);
if (!tag)
return -ENOMEM;
r = set_put(arg_tag_filter, tag);
if (r < 0)
return r;
tag = NULL;
break;
}
case 'V': case 'V':
print_version(); return version();
return 0;
case 'h': case 'h':
help(); return help();
return 0; case '?':
return -EINVAL;
default: default:
return 1; assert_not_reached("Unknown option.");
} }
if (!print_kernel && !print_udev) { if (!arg_print_kernel && !arg_print_udev) {
print_kernel = true; arg_print_kernel = true;
print_udev = true; arg_print_udev = true;
} }
return 1;
}
int monitor_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_monitor_unrefp) struct udev_monitor *kernel_monitor = NULL, *udev_monitor = NULL;
int fd_kernel = -1, fd_udev = -1;
_cleanup_close_ int fd_ep = -1;
struct sigaction act;
sigset_t mask;
int r;
r = parse_argv(argc, argv);
if (r <= 0)
goto finalize;
/* set signal handlers */ /* set signal handlers */
act.sa_handler = sig_handler; act = (struct sigaction) {
act.sa_flags = SA_RESTART; .sa_handler = sig_handler,
.sa_flags = SA_RESTART,
};
assert_se(sigaction(SIGINT, &act, NULL) == 0); assert_se(sigaction(SIGINT, &act, NULL) == 0);
assert_se(sigaction(SIGTERM, &act, NULL) == 0); assert_se(sigaction(SIGTERM, &act, NULL) == 0);
assert_se(sigemptyset(&mask) == 0); assert_se(sigemptyset(&mask) == 0);
@ -145,82 +251,26 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
fd_ep = epoll_create1(EPOLL_CLOEXEC); fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) { if (fd_ep < 0) {
log_error_errno(errno, "error creating epoll fd: %m"); r = log_error_errno(errno, "Failed to create epoll fd: %m");
return 1; goto finalize;
} }
printf("monitor will print the received events for:\n"); printf("monitor will print the received events for:\n");
if (print_udev) { if (arg_print_udev) {
struct udev_list_entry *entry; fd_udev = setup_monitor("udev", fd_ep, &udev_monitor);
if (fd_udev < 0) {
udev_monitor = udev_monitor_new_from_netlink(udev, "udev"); r = fd_udev;
if (udev_monitor == NULL) { goto finalize;
fprintf(stderr, "error: unable to create netlink socket\n");
return 1;
}
udev_monitor_set_receive_buffer_size(udev_monitor, 128*1024*1024);
fd_udev = udev_monitor_get_fd(udev_monitor);
udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) {
const char *subsys = udev_list_entry_get_name(entry);
const char *devtype = udev_list_entry_get_value(entry);
if (udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, subsys, devtype) < 0)
fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys);
}
udev_list_entry_foreach(entry, udev_list_get_entry(&tag_match_list)) {
const char *tag = udev_list_entry_get_name(entry);
if (udev_monitor_filter_add_match_tag(udev_monitor, tag) < 0)
fprintf(stderr, "error: unable to apply tag filter '%s'\n", tag);
}
if (udev_monitor_enable_receiving(udev_monitor) < 0) {
fprintf(stderr, "error: unable to subscribe to udev events\n");
return 2;
}
memzero(&ep_udev, sizeof(struct epoll_event));
ep_udev.events = EPOLLIN;
ep_udev.data.fd = fd_udev;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) {
log_error_errno(errno, "fail to add fd to epoll: %m");
return 2;
} }
printf("UDEV - the event which udev sends out after rule processing\n"); printf("UDEV - the event which udev sends out after rule processing\n");
} }
if (print_kernel) { if (arg_print_kernel) {
struct udev_list_entry *entry; fd_kernel = setup_monitor("kernel", fd_ep, &kernel_monitor);
if (fd_kernel < 0) {
kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel"); r = fd_kernel;
if (kernel_monitor == NULL) { goto finalize;
fprintf(stderr, "error: unable to create netlink socket\n");
return 3;
}
udev_monitor_set_receive_buffer_size(kernel_monitor, 128*1024*1024);
fd_kernel = udev_monitor_get_fd(kernel_monitor);
udev_list_entry_foreach(entry, udev_list_get_entry(&subsystem_match_list)) {
const char *subsys = udev_list_entry_get_name(entry);
if (udev_monitor_filter_add_match_subsystem_devtype(kernel_monitor, subsys, NULL) < 0)
fprintf(stderr, "error: unable to apply subsystem filter '%s'\n", subsys);
}
if (udev_monitor_enable_receiving(kernel_monitor) < 0) {
fprintf(stderr, "error: unable to subscribe to kernel events\n");
return 4;
}
memzero(&ep_kernel, sizeof(struct epoll_event));
ep_kernel.events = EPOLLIN;
ep_kernel.data.fd = fd_kernel;
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_kernel, &ep_kernel) < 0) {
log_error_errno(errno, "fail to add fd to epoll: %m");
return 5;
} }
printf("KERNEL - the kernel uevent\n"); printf("KERNEL - the kernel uevent\n");
@ -228,43 +278,28 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
printf("\n"); printf("\n");
while (!udev_exit) { while (!udev_exit) {
int fdcount;
struct epoll_event ev[4]; struct epoll_event ev[4];
int i; int fdcount, i;
fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1); fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
if (fdcount < 0) { if (fdcount < 0) {
if (errno != EINTR) if (errno != EINTR)
fprintf(stderr, "error receiving uevent message: %m\n"); log_debug_errno(errno, "Failed to receive uevent message, ignoring: %m");
continue; continue;
} }
for (i = 0; i < fdcount; i++) { for (i = 0; i < fdcount; i++)
if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN) { if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN)
struct udev_device *device; (void) receive_and_print_device(kernel_monitor, "KERNEL");
else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN)
device = udev_monitor_receive_device(kernel_monitor); (void) receive_and_print_device(udev_monitor, "UDEV");
if (device == NULL)
continue;
print_device(device, "KERNEL", prop);
udev_device_unref(device);
} else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN) {
struct udev_device *device;
device = udev_monitor_receive_device(udev_monitor);
if (device == NULL)
continue;
print_device(device, "UDEV", prop);
udev_device_unref(device);
}
}
} }
return 0; r = 0;
}
const struct udevadm_cmd udevadm_monitor = { finalize:
.name = "monitor", hashmap_free_free_free(arg_subsystem_filter);
.cmd = adm_monitor, set_free_free(arg_tag_filter);
.help = "Listen to kernel and udev events",
}; return r;
}

View File

@ -13,22 +13,26 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include "parse-util.h" #include "time-util.h"
#include "udevadm.h"
#include "udev.h" #include "udev.h"
#include "udevadm-util.h"
#include "util.h"
static void help(void) { static usec_t arg_timeout = 120 * USEC_PER_SEC;
static const char *arg_exists = NULL;
static int help(void) {
printf("%s settle [OPTIONS]\n\n" printf("%s settle [OPTIONS]\n\n"
"Wait for pending udev events.\n\n" "Wait for pending udev events.\n\n"
" -h --help Show this help\n" " -h --help Show this help\n"
" -V --version Show package version\n" " -V --version Show package version\n"
" -t --timeout=SECONDS Maximum time to wait for events\n" " -t --timeout=SEC Maximum time to wait for events\n"
" -E --exit-if-exists=FILE Stop waiting if file exists\n" " -E --exit-if-exists=FILE Stop waiting if file exists\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_settle(struct udev *udev, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = { static const struct option options[] = {
{ "timeout", required_argument, NULL, 't' }, { "timeout", required_argument, NULL, 't' },
{ "exit-if-exists", required_argument, NULL, 'E' }, { "exit-if-exists", required_argument, NULL, 'E' },
@ -39,117 +43,95 @@ static int adm_settle(struct udev *udev, int argc, char *argv[]) {
{ "quiet", no_argument, NULL, 'q' }, /* removed */ { "quiet", no_argument, NULL, 'q' }, /* removed */
{} {}
}; };
usec_t deadline;
const char *exists = NULL; int c, r;
unsigned int timeout = 120;
struct pollfd pfd[1] = { {.fd = -1}, };
int c;
struct udev_queue *queue;
int rc = EXIT_FAILURE;
while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) { while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) {
switch (c) { switch (c) {
case 't':
case 't': { r = parse_sec(optarg, &arg_timeout);
int r; if (r < 0)
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
r = safe_atou(optarg, &timeout);
if (r < 0) {
log_error_errno(r, "Invalid timeout value '%s': %m", optarg);
return EXIT_FAILURE;
}
break; break;
}
case 'E': case 'E':
exists = optarg; arg_exists = optarg;
break; break;
case 'V': case 'V':
print_version(); return version();
return EXIT_SUCCESS;
case 'h': case 'h':
help(); return help();
return EXIT_SUCCESS;
case 's': case 's':
case 'e': case 'e':
case 'q': case 'q':
log_info("Option -%c no longer supported.", c); log_info("Option -%c no longer supported.", c);
return EXIT_FAILURE; return -EINVAL;
case '?': case '?':
return EXIT_FAILURE; return -EINVAL;
default: default:
assert_not_reached("Unknown argument"); assert_not_reached("Unknown option.");
} }
} }
if (optind < argc) { return 1;
fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]); }
return EXIT_FAILURE;
}
deadline = now(CLOCK_MONOTONIC) + timeout * USEC_PER_SEC; int settle_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_queue_unrefp) struct udev_queue *queue = NULL;
struct pollfd pfd;
usec_t deadline;
int r;
r = parse_argv(argc, argv);
if (r <= 0)
return r;
deadline = now(CLOCK_MONOTONIC) + arg_timeout;
/* guarantee that the udev daemon isn't pre-processing */ /* guarantee that the udev daemon isn't pre-processing */
if (getuid() == 0) { if (getuid() == 0) {
struct udev_ctrl *uctrl; _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
uctrl = udev_ctrl_new(udev); uctrl = udev_ctrl_new();
if (uctrl != NULL) { if (uctrl) {
if (udev_ctrl_send_ping(uctrl, MAX(5U, timeout)) < 0) { r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
log_debug("no connection to daemon"); if (r < 0) {
udev_ctrl_unref(uctrl); log_debug_errno(r, "Failed to connect to udev daemon.");
return EXIT_SUCCESS; return 0;
} }
udev_ctrl_unref(uctrl);
} }
} }
queue = udev_queue_new(udev); queue = udev_queue_new(NULL);
if (!queue) { if (!queue)
log_error("unable to get udev queue"); return log_error_errno(errno, "Failed to get udev queue: %m");
return EXIT_FAILURE;
r = udev_queue_get_fd(queue);
if (r < 0) {
log_debug_errno(r, "Queue is empty, nothing to watch.");
return 0;
} }
pfd[0].events = POLLIN; pfd = (struct pollfd) {
pfd[0].fd = udev_queue_get_fd(queue); .events = POLLIN,
if (pfd[0].fd < 0) { .fd = r,
log_debug("queue is empty, nothing to watch"); };
rc = EXIT_SUCCESS;
goto out;
}
for (;;) { for (;;) {
if (exists && access(exists, F_OK) >= 0) { if (arg_exists && access(arg_exists, F_OK) >= 0)
rc = EXIT_SUCCESS; return 0;
break;
}
/* exit if queue is empty */ /* exit if queue is empty */
if (udev_queue_get_queue_is_empty(queue)) { if (udev_queue_get_queue_is_empty(queue))
rc = EXIT_SUCCESS; return 0;
break;
}
if (now(CLOCK_MONOTONIC) >= deadline) if (now(CLOCK_MONOTONIC) >= deadline)
break; return -ETIMEDOUT;
/* wake up when queue is empty */ /* wake up when queue becomes empty */
if (poll(pfd, 1, MSEC_PER_SEC) > 0 && pfd[0].revents & POLLIN) if (poll(&pfd, 1, MSEC_PER_SEC) > 0 && pfd.revents & POLLIN) {
udev_queue_flush(queue); r = udev_queue_flush(queue);
if (r < 0)
return log_error_errno(r, "Failed to flush queue: %m");
}
} }
out:
udev_queue_unref(queue);
return rc;
} }
const struct udevadm_cmd udevadm_settle = {
.name = "settle",
.cmd = adm_settle,
.help = "Wait for pending udev events",
};

View File

@ -9,9 +9,12 @@
#include "path-util.h" #include "path-util.h"
#include "string-util.h" #include "string-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm-util.h" #include "udevadm.h"
static void help(struct udev *udev) { static const char *arg_command = NULL;
static char arg_syspath[UTIL_PATH_SIZE] = {};
static int help(void) {
printf("%s test-builtin [OPTIONS] COMMAND DEVPATH\n\n" printf("%s test-builtin [OPTIONS] COMMAND DEVPATH\n\n"
"Test a built-in command.\n\n" "Test a built-in command.\n\n"
" -h --help Print this message\n" " -h --help Print this message\n"
@ -19,85 +22,85 @@ static void help(struct udev *udev) {
"Commands:\n" "Commands:\n"
, program_invocation_short_name); , program_invocation_short_name);
udev_builtin_list(udev); udev_builtin_list();
return 0;
} }
static int adm_builtin(struct udev *udev, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
static const struct option options[] = { static const struct option options[] = {
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{} {}
}; };
char *command = NULL;
char *syspath = NULL; const char *s;
char filename[UTIL_PATH_SIZE]; int c;
struct udev_device *dev = NULL;
enum udev_builtin_cmd cmd;
int rc = EXIT_SUCCESS, c;
while ((c = getopt_long(argc, argv, "Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "Vh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'V': case 'V':
print_version(); return version();
goto out;
case 'h': case 'h':
help(udev); return help();
goto out; case '?':
return -EINVAL;
default:
assert_not_reached("Unknown option");
} }
command = argv[optind++]; arg_command = argv[optind++];
if (command == NULL) { if (!arg_command) {
fprintf(stderr, "command missing\n"); log_error("Command missing.");
help(udev); return -EINVAL;
rc = 2;
goto out;
} }
syspath = argv[optind++]; s = argv[optind++];
if (syspath == NULL) { if (!s) {
fprintf(stderr, "syspath missing\n"); log_error("syspath missing.");
rc = 3; return -EINVAL;
goto out;
}
udev_builtin_init(udev);
cmd = udev_builtin_lookup(command);
if (cmd >= UDEV_BUILTIN_MAX) {
fprintf(stderr, "unknown command '%s'\n", command);
help(udev);
rc = 5;
goto out;
} }
/* add /sys if needed */ /* add /sys if needed */
if (!path_startswith(syspath, "/sys")) if (!path_startswith(s, "/sys"))
strscpyl(filename, sizeof(filename), "/sys", syspath, NULL); strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", s, NULL);
else else
strscpy(filename, sizeof(filename), syspath); strscpy(arg_syspath, sizeof(arg_syspath), s);
delete_trailing_chars(filename, "/");
dev = udev_device_new_from_syspath(udev, filename); return 1;
if (dev == NULL) {
fprintf(stderr, "unable to open device '%s'\n\n", filename);
rc = 4;
goto out;
}
rc = udev_builtin_run(dev, cmd, command, true);
if (rc < 0) {
fprintf(stderr, "error executing '%s', exit code %i\n\n", command, rc);
rc = 6;
}
out:
udev_device_unref(dev);
udev_builtin_exit(udev);
return rc;
} }
const struct udevadm_cmd udevadm_test_builtin = { int builtin_main(int argc, char *argv[], void *userdata) {
.name = "test-builtin", _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
.cmd = adm_builtin, enum udev_builtin_cmd cmd;
.help = "Test a built-in command", int r;
.debug = true,
}; log_set_max_level(LOG_DEBUG);
r = parse_argv(argc, argv);
if (r <= 0)
return r;
udev_builtin_init();
cmd = udev_builtin_lookup(arg_command);
if (cmd >= UDEV_BUILTIN_MAX) {
log_error("Unknown command '%s'", arg_command);
r = -EINVAL;
goto finish;
}
dev = udev_device_new_from_syspath(NULL, arg_syspath);
if (!dev) {
r = log_error_errno(errno, "Failed to open device '%s'", arg_syspath);
goto finish;
}
r = udev_builtin_run(dev, cmd, arg_command, true);
if (r < 0)
log_debug("error executing '%s', exit code %i", arg_command, r);
finish:
udev_builtin_exit();
return r;
}

View File

@ -14,9 +14,13 @@
#include "string-util.h" #include "string-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm-util.h" #include "udevadm.h"
static void help(void) { static const char *arg_action = "add";
static int arg_resolve_names = 1;
static char arg_syspath[UTIL_PATH_SIZE] = {};
static int help(void) {
printf("%s test [OPTIONS] DEVPATH\n\n" printf("%s test [OPTIONS] DEVPATH\n\n"
"Test an event run.\n\n" "Test an event run.\n\n"
@ -25,20 +29,11 @@ static void help(void) {
" -a --action=ACTION Set action string\n" " -a --action=ACTION Set action string\n"
" -N --resolve-names=early|late|never When to resolve names\n" " -N --resolve-names=early|late|never When to resolve names\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_test(struct udev *udev, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
int resolve_names = 1;
char filename[UTIL_PATH_SIZE];
const char *action = "add";
const char *syspath = NULL;
struct udev_list_entry *entry;
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
sigset_t mask, sigmask_orig;
int rc = 0, c;
static const struct option options[] = { static const struct option options[] = {
{ "action", required_argument, NULL, 'a' }, { "action", required_argument, NULL, 'a' },
{ "resolve-names", required_argument, NULL, 'N' }, { "resolve-names", required_argument, NULL, 'N' },
@ -47,45 +42,63 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
{} {}
}; };
log_debug("version %s", PACKAGE_VERSION); int c;
while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "a:N:Vh", options, NULL)) >= 0)
switch (c) { switch (c) {
case 'a': case 'a':
action = optarg; arg_action = optarg;
break; break;
case 'N': case 'N':
if (streq (optarg, "early")) { if (streq (optarg, "early")) {
resolve_names = 1; arg_resolve_names = 1;
} else if (streq (optarg, "late")) { } else if (streq (optarg, "late")) {
resolve_names = 0; arg_resolve_names = 0;
} else if (streq (optarg, "never")) { } else if (streq (optarg, "never")) {
resolve_names = -1; arg_resolve_names = -1;
} else { } else {
fprintf(stderr, "resolve-names must be early, late or never\n");
log_error("resolve-names must be early, late or never"); log_error("resolve-names must be early, late or never");
exit(EXIT_FAILURE); return -EINVAL;
} }
break; break;
case 'V': case 'V':
print_version(); return version();
exit(EXIT_SUCCESS);
case 'h': case 'h':
help(); return help();
exit(EXIT_SUCCESS);
case '?': case '?':
exit(EXIT_FAILURE); return -EINVAL;
default: default:
assert_not_reached("Unknown option"); assert_not_reached("Unknown option");
} }
syspath = argv[optind]; if (!argv[optind]) {
if (syspath == NULL) { log_error("syspath parameter missing.");
fprintf(stderr, "syspath parameter missing\n"); return -EINVAL;
rc = 2;
goto out;
} }
/* add /sys if needed */
if (!startswith(argv[optind], "/sys"))
strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", argv[optind], NULL);
else
strscpy(arg_syspath, sizeof(arg_syspath), argv[optind]);
return 1;
}
int test_main(int argc, char *argv[], void *userdata) {
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
_cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
struct udev_list_entry *entry;
sigset_t mask, sigmask_orig;
int r;
log_set_max_level(LOG_DEBUG);
r = parse_argv(argc, argv);
if (r <= 0)
return r;
printf("This program is for debugging only, it does not run any program\n" printf("This program is for debugging only, it does not run any program\n"
"specified by a RUN key. It may show incorrect results, because\n" "specified by a RUN key. It may show incorrect results, because\n"
"some values may be different, or not available at a simulation run.\n" "some values may be different, or not available at a simulation run.\n"
@ -93,26 +106,18 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
sigprocmask(SIG_SETMASK, NULL, &sigmask_orig); sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
udev_builtin_init(udev); udev_builtin_init();
rules = udev_rules_new(udev, resolve_names); rules = udev_rules_new(arg_resolve_names);
if (rules == NULL) { if (!rules) {
fprintf(stderr, "error reading rules\n"); log_error("Failed to read udev rules.");
rc = 3; r = -ENOMEM;
goto out; goto out;
} }
/* add /sys if needed */ dev = udev_device_new_from_synthetic_event(NULL, arg_syspath, arg_action);
if (!startswith(syspath, "/sys"))
strscpyl(filename, sizeof(filename), "/sys", syspath, NULL);
else
strscpy(filename, sizeof(filename), syspath);
delete_trailing_chars(filename, "/");
dev = udev_device_new_from_synthetic_event(udev, filename, action);
if (dev == NULL) { if (dev == NULL) {
fprintf(stderr, "unable to open device '%s'\n", filename); r = log_error_errno(errno, "Failed to open device '%s': %m", arg_syspath);
rc = 4;
goto out; goto out;
} }
@ -138,14 +143,9 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false); udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program), false);
printf("run: '%s'\n", program); printf("run: '%s'\n", program);
} }
out:
udev_builtin_exit(udev);
return rc;
}
const struct udevadm_cmd udevadm_test = { r = 0;
.name = "test", out:
.cmd = adm_test, udev_builtin_exit();
.help = "Test an event run", return r;
.debug = true, }
};

View File

@ -12,6 +12,7 @@
#include "set.h" #include "set.h"
#include "string-util.h" #include "string-util.h"
#include "udev.h" #include "udev.h"
#include "udevadm.h"
#include "udevadm-util.h" #include "udevadm-util.h"
#include "util.h" #include "util.h"
@ -64,7 +65,7 @@ static const char *keyval(const char *str, const char **val, char *buf, size_t s
return buf; return buf;
} }
static void help(void) { static int help(void) {
printf("%s trigger [OPTIONS] DEVPATH\n\n" printf("%s trigger [OPTIONS] DEVPATH\n\n"
"Request events from the kernel.\n\n" "Request events from the kernel.\n\n"
" -h --help Show this help\n" " -h --help Show this help\n"
@ -86,9 +87,11 @@ static void help(void) {
" -b --parent-match=NAME Trigger devices with that parent device\n" " -b --parent-match=NAME Trigger devices with that parent device\n"
" -w --settle Wait for the triggered events to complete\n" " -w --settle Wait for the triggered events to complete\n"
, program_invocation_short_name); , program_invocation_short_name);
return 0;
} }
static int adm_trigger(struct udev *udev, int argc, char *argv[]) { int trigger_main(int argc, char *argv[], void *userdata) {
enum { enum {
ARG_NAME = 0x100, ARG_NAME = 0x100,
}; };
@ -126,9 +129,9 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
_cleanup_set_free_free_ Set *settle_set = NULL; _cleanup_set_free_free_ Set *settle_set = NULL;
int c, r; int c, r;
udev_enumerate = udev_enumerate_new(udev); udev_enumerate = udev_enumerate_new(NULL);
if (!udev_enumerate) if (!udev_enumerate)
return 1; return -errno;
while ((c = getopt_long(argc, argv, "vnt:c:s:S:a:A:p:g:y:b:wVh", options, NULL)) >= 0) { while ((c = getopt_long(argc, argv, "vnt:c:s:S:a:A:p:g:y:b:wVh", options, NULL)) >= 0) {
const char *key; const char *key;
@ -149,83 +152,66 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
device_type = TYPE_SUBSYSTEMS; device_type = TYPE_SUBSYSTEMS;
else { else {
log_error("unknown type --type=%s", optarg); log_error("unknown type --type=%s", optarg);
return 2; return -EINVAL;
} }
break; break;
case 'c': case 'c':
if (!STR_IN_SET(optarg, "add", "remove", "change")) { if (STR_IN_SET(optarg, "add", "remove", "change"))
log_error("unknown action '%s'", optarg);
return 2;
} else
action = optarg; action = optarg;
else {
log_error("unknown action '%s'", optarg);
return -EINVAL;
}
break; break;
case 's': case 's':
r = udev_enumerate_add_match_subsystem(udev_enumerate, optarg); r = udev_enumerate_add_match_subsystem(udev_enumerate, optarg);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add subsystem match '%s': %m", optarg); return log_error_errno(r, "could not add subsystem match '%s': %m", optarg);
return 2;
}
break; break;
case 'S': case 'S':
r = udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg); r = udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add negative subsystem match '%s': %m", optarg); return log_error_errno(r, "could not add negative subsystem match '%s': %m", optarg);
return 2;
}
break; break;
case 'a': case 'a':
key = keyval(optarg, &val, buf, sizeof(buf)); key = keyval(optarg, &val, buf, sizeof(buf));
r = udev_enumerate_add_match_sysattr(udev_enumerate, key, val); r = udev_enumerate_add_match_sysattr(udev_enumerate, key, val);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add sysattr match '%s=%s': %m", key, val); return log_error_errno(r, "could not add sysattr match '%s=%s': %m", key, val);
return 2;
}
break; break;
case 'A': case 'A':
key = keyval(optarg, &val, buf, sizeof(buf)); key = keyval(optarg, &val, buf, sizeof(buf));
r = udev_enumerate_add_nomatch_sysattr(udev_enumerate, key, val); r = udev_enumerate_add_nomatch_sysattr(udev_enumerate, key, val);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add negative sysattr match '%s=%s': %m", key, val); return log_error_errno(r, "could not add negative sysattr match '%s=%s': %m", key, val);
return 2;
}
break; break;
case 'p': case 'p':
key = keyval(optarg, &val, buf, sizeof(buf)); key = keyval(optarg, &val, buf, sizeof(buf));
r = udev_enumerate_add_match_property(udev_enumerate, key, val); r = udev_enumerate_add_match_property(udev_enumerate, key, val);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add property match '%s=%s': %m", key, val); return log_error_errno(r, "could not add property match '%s=%s': %m", key, val);
return 2;
}
break; break;
case 'g': case 'g':
r = udev_enumerate_add_match_tag(udev_enumerate, optarg); r = udev_enumerate_add_match_tag(udev_enumerate, optarg);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add tag match '%s': %m", optarg); return log_error_errno(r, "could not add tag match '%s': %m", optarg);
return 2;
}
break; break;
case 'y': case 'y':
r = udev_enumerate_add_match_sysname(udev_enumerate, optarg); r = udev_enumerate_add_match_sysname(udev_enumerate, optarg);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add sysname match '%s': %m", optarg); return log_error_errno(r, "could not add sysname match '%s': %m", optarg);
return 2;
}
break; break;
case 'b': { case 'b': {
_cleanup_(udev_device_unrefp) struct udev_device *dev; _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, optarg, "/sys"); dev = find_device(optarg, "/sys");
if (!dev) { if (!dev)
log_error("unable to open the device '%s'", optarg); return log_error_errno(errno, "unable to open the device '%s'", optarg);
return 2;
}
r = udev_enumerate_add_match_parent(udev_enumerate, dev); r = udev_enumerate_add_match_parent(udev_enumerate, dev);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add parent match '%s': %m", optarg); return log_error_errno(r, "could not add parent match '%s': %m", optarg);
return 2;
}
break; break;
} }
case 'w': case 'w':
@ -235,28 +221,22 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
case ARG_NAME: { case ARG_NAME: {
_cleanup_(udev_device_unrefp) struct udev_device *dev; _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, optarg, "/dev/"); dev = find_device(optarg, "/dev/");
if (!dev) { if (!dev)
log_error("unable to open the device '%s'", optarg); return log_error_errno(errno, "unable to open the device '%s'", optarg);
return 2;
}
r = udev_enumerate_add_match_parent(udev_enumerate, dev); r = udev_enumerate_add_match_parent(udev_enumerate, dev);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add parent match '%s': %m", optarg); return log_error_errno(r, "could not add parent match '%s': %m", optarg);
return 2;
}
break; break;
} }
case 'V': case 'V':
print_version(); return version();
return 0;
case 'h': case 'h':
help(); return help();
return 0;
case '?': case '?':
return 1; return -EINVAL;
default: default:
assert_not_reached("Unknown option"); assert_not_reached("Unknown option");
} }
@ -265,49 +245,39 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
for (; optind < argc; optind++) { for (; optind < argc; optind++) {
_cleanup_(udev_device_unrefp) struct udev_device *dev; _cleanup_(udev_device_unrefp) struct udev_device *dev;
dev = find_device(udev, argv[optind], NULL); dev = find_device(argv[optind], NULL);
if (!dev) { if (!dev) {
log_error("unable to open the device '%s'", argv[optind]); log_error("unable to open the device '%s'", argv[optind]);
return 2; return -EINVAL;
} }
r = udev_enumerate_add_match_parent(udev_enumerate, dev); r = udev_enumerate_add_match_parent(udev_enumerate, dev);
if (r < 0) { if (r < 0)
log_error_errno(r, "could not add tag match '%s': %m", optarg); return log_error_errno(r, "could not add tag match '%s': %m", optarg);
return 2;
}
} }
if (settle) { if (settle) {
fd_ep = epoll_create1(EPOLL_CLOEXEC); fd_ep = epoll_create1(EPOLL_CLOEXEC);
if (fd_ep < 0) { if (fd_ep < 0)
log_error_errno(errno, "error creating epoll fd: %m"); return log_error_errno(errno, "error creating epoll fd: %m");
return 1;
} udev_monitor = udev_monitor_new_from_netlink(NULL, "udev");
if (!udev_monitor)
return log_error_errno(errno, "error: unable to create netlink socket: %m");
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
if (!udev_monitor) {
log_error("error: unable to create netlink socket");
return 3;
}
fd_udev = udev_monitor_get_fd(udev_monitor); fd_udev = udev_monitor_get_fd(udev_monitor);
if (udev_monitor_enable_receiving(udev_monitor) < 0) { r = udev_monitor_enable_receiving(udev_monitor);
log_error("error: unable to subscribe to udev events"); if (r < 0)
return 4; return log_error_errno(r, "error: unable to subscribe to udev events: %m");
}
ep_udev = (struct epoll_event) { .events = EPOLLIN, .data.fd = fd_udev }; ep_udev = (struct epoll_event) { .events = EPOLLIN, .data.fd = fd_udev };
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0) { if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0)
log_error_errno(errno, "fail to add fd to epoll: %m"); return log_error_errno(errno, "fail to add fd to epoll: %m");
return 5;
}
settle_set = set_new(&string_hash_ops); settle_set = set_new(&string_hash_ops);
if (!settle_set) { if (!settle_set)
log_oom(); return log_oom();
return 1;
}
} }
switch (device_type) { switch (device_type) {
@ -322,7 +292,7 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
} }
r = exec_list(udev_enumerate, action, settle_set); r = exec_list(udev_enumerate, action, settle_set);
if (r < 0) if (r < 0)
return 1; return r;
while (!set_isempty(settle_set)) { while (!set_isempty(settle_set)) {
int fdcount; int fdcount;
@ -356,9 +326,3 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
return 0; return 0;
} }
const struct udevadm_cmd udevadm_trigger = {
.name = "trigger",
.cmd = adm_trigger,
.help = "Request events from the kernel",
};

View File

@ -4,8 +4,7 @@
#include "string-util.h" #include "string-util.h"
#include "udevadm-util.h" #include "udevadm-util.h"
struct udev_device *find_device(struct udev *udev, struct udev_device *find_device(const char *id,
const char *id,
const char *prefix) { const char *prefix) {
assert(id); assert(id);
@ -27,9 +26,9 @@ struct udev_device *find_device(struct udev *udev,
else else
return NULL; return NULL;
return udev_device_new_from_devnum(udev, type, statbuf.st_rdev); return udev_device_new_from_devnum(NULL, type, statbuf.st_rdev);
} else if (path_startswith(id, "/sys/")) } else if (path_startswith(id, "/sys/"))
return udev_device_new_from_syspath(udev, id); return udev_device_new_from_syspath(NULL, id);
else else
return NULL; return NULL;
} }

View File

@ -3,10 +3,5 @@
#include "udev.h" #include "udev.h"
struct udev_device *find_device(struct udev *udev, struct udev_device *find_device(const char *id,
const char *id,
const char *prefix); const char *prefix);
static inline void print_version(void) {
printf("%s\n", PACKAGE_VERSION);
}

View File

@ -5,43 +5,26 @@
#include <stddef.h> #include <stddef.h>
#include <stdio.h> #include <stdio.h>
#include "alloc-util.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "string-util.h" #include "string-util.h"
#include "terminal-util.h" #include "terminal-util.h"
#include "udevadm.h"
#include "udev-util.h" #include "udev-util.h"
#include "udev.h" #include "verbs.h"
#include "util.h"
static int adm_version(struct udev *udev, int argc, char *argv[]) { static int help(void) {
printf("%s\n", PACKAGE_VERSION); static const char * short_descriptions[][2] = {
return 0; { "info", "Query sysfs or the udev database" },
} { "trigger", "Request events from the kernel" },
{ "settle", "Wait for pending udev events" },
{ "control", "Control the udev daemon" },
{ "monitor", "Listen to kernel and udev events" },
{ "test", "Test an event run" },
{ "test-builtin", "Test a built-in command" },
};
static const struct udevadm_cmd udevadm_version = {
.name = "version",
.cmd = adm_version,
};
static int adm_help(struct udev *udev, int argc, char *argv[]);
static const struct udevadm_cmd udevadm_help = {
.name = "help",
.cmd = adm_help,
};
static const struct udevadm_cmd *udevadm_cmds[] = {
&udevadm_info,
&udevadm_trigger,
&udevadm_settle,
&udevadm_control,
&udevadm_monitor,
&udevadm_hwdb,
&udevadm_test,
&udevadm_test_builtin,
&udevadm_version,
&udevadm_help,
};
static int adm_help(struct udev *udev, int argc, char *argv[]) {
_cleanup_free_ char *link = NULL; _cleanup_free_ char *link = NULL;
size_t i; size_t i;
int r; int r;
@ -55,42 +38,24 @@ static int adm_help(struct udev *udev, int argc, char *argv[]) {
"Commands:\n" "Commands:\n"
, program_invocation_short_name); , program_invocation_short_name);
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++) for (i = 0; i < ELEMENTSOF(short_descriptions); i++)
if (udevadm_cmds[i]->help != NULL) printf(" %-12s %s\n", short_descriptions[i][0], short_descriptions[i][1]);
printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help);
printf("\nSee the %s for details.\n", link); printf("\nSee the %s for details.\n", link);
return 0; return 0;
} }
static int run_command(struct udev *udev, const struct udevadm_cmd *cmd, int argc, char *argv[]) { static int parse_argv(int argc, char *argv[]) {
if (cmd->debug)
log_set_max_level(LOG_DEBUG);
log_debug("calling: %s", cmd->name);
return cmd->cmd(udev, argc, argv);
}
int main(int argc, char *argv[]) {
struct udev *udev;
static const struct option options[] = { static const struct option options[] = {
{ "debug", no_argument, NULL, 'd' }, { "debug", no_argument, NULL, 'd' },
{ "help", no_argument, NULL, 'h' }, { "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, 'V' }, { "version", no_argument, NULL, 'V' },
{} {}
}; };
const char *command; int c;
unsigned int i;
int rc = 1, c;
udev_parse_config(); assert(argc >= 0);
log_parse_environment(); assert(argv);
log_open();
mac_selinux_init();
udev = udev_new();
if (udev == NULL)
goto out;
while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0) while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
switch (c) { switch (c) {
@ -100,35 +65,66 @@ int main(int argc, char *argv[]) {
break; break;
case 'h': case 'h':
rc = adm_help(udev, argc, argv); return help();
goto out;
case 'V': case 'V':
rc = adm_version(udev, argc, argv); return version();
goto out;
case '?':
return -EINVAL;
default: default:
goto out; assert_not_reached("Unhandled option");
} }
command = argv[optind]; return 1; /* work to do */
}
if (command != NULL)
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++) static int version_main(int argc, char *argv[], void *userdata) {
if (streq(udevadm_cmds[i]->name, command)) { return version();
argc -= optind; }
argv += optind;
/* we need '0' here to reset the internal state */ static int help_main(int argc, char *argv[], void *userdata) {
optind = 0; return help();
rc = run_command(udev, udevadm_cmds[i], argc, argv); }
goto out;
} static int udevadm_main(int argc, char *argv[]) {
static const Verb verbs[] = {
fprintf(stderr, "%s: missing or unknown command\n", program_invocation_short_name); { "info", VERB_ANY, VERB_ANY, 0, info_main },
rc = 2; { "trigger", VERB_ANY, VERB_ANY, 0, trigger_main },
out: { "settle", VERB_ANY, VERB_ANY, 0, settle_main },
mac_selinux_finish(); { "control", VERB_ANY, VERB_ANY, 0, control_main },
udev_unref(udev); { "monitor", VERB_ANY, VERB_ANY, 0, monitor_main },
log_close(); { "hwdb", VERB_ANY, VERB_ANY, 0, hwdb_main },
return rc; { "test", VERB_ANY, VERB_ANY, 0, test_main },
{ "test-builtin", VERB_ANY, VERB_ANY, 0, builtin_main },
{ "version", VERB_ANY, VERB_ANY, 0, version_main },
{ "help", VERB_ANY, VERB_ANY, 0, help_main },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
int main(int argc, char *argv[]) {
int r;
udev_parse_config();
log_parse_environment();
log_open();
mac_selinux_init();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
r = udevadm_main(argc, argv);
finish:
mac_selinux_finish();
log_close();
/* TODO: fix this later.
* Currently, verbs return positive values on failure. */
return r < 0 ? EXIT_FAILURE : r;
} }

11
src/udev/udevadm.h Normal file
View File

@ -0,0 +1,11 @@
/* SPDX-License-Identifier: GPL-2.0+ */
#pragma once
int info_main(int argc, char *argv[], void *userdata);
int trigger_main(int argc, char *argv[], void *userdata);
int settle_main(int argc, char *argv[], void *userdata);
int control_main(int argc, char *argv[], void *userdata);
int monitor_main(int argc, char *argv[], void *userdata);
int hwdb_main(int argc, char *argv[], void *userdata);
int test_main(int argc, char *argv[], void *userdata);
int builtin_main(int argc, char *argv[], void *userdata);

View File

@ -63,7 +63,6 @@ static usec_t arg_event_timeout_usec = 180 * USEC_PER_SEC;
static usec_t arg_event_timeout_warn_usec = 180 * USEC_PER_SEC / 3; static usec_t arg_event_timeout_warn_usec = 180 * USEC_PER_SEC / 3;
typedef struct Manager { typedef struct Manager {
struct udev *udev;
sd_event *event; sd_event *event;
Hashmap *workers; Hashmap *workers;
LIST_HEAD(struct event, events); LIST_HEAD(struct event, events);
@ -98,7 +97,6 @@ enum event_state {
struct event { struct event {
LIST_FIELDS(struct event, event); LIST_FIELDS(struct event, event);
Manager *manager; Manager *manager;
struct udev *udev;
struct udev_device *dev; struct udev_device *dev;
struct udev_device *dev_kernel; struct udev_device *dev_kernel;
struct worker *worker; struct worker *worker;
@ -126,7 +124,6 @@ enum worker_state {
struct worker { struct worker {
Manager *manager; Manager *manager;
int refcount;
pid_t pid; pid_t pid;
struct udev_monitor *monitor; struct udev_monitor *monitor;
enum worker_state state; enum worker_state state;
@ -204,7 +201,6 @@ static int worker_new(struct worker **ret, Manager *manager, struct udev_monitor
if (!worker) if (!worker)
return -ENOMEM; return -ENOMEM;
worker->refcount = 1;
worker->manager = manager; worker->manager = manager;
/* close monitor, but keep address around */ /* close monitor, but keep address around */
udev_monitor_disconnect(worker_monitor); udev_monitor_disconnect(worker_monitor);
@ -278,13 +274,12 @@ static void manager_free(Manager *manager) {
if (!manager) if (!manager)
return; return;
udev_builtin_exit(manager->udev); udev_builtin_exit();
sd_event_source_unref(manager->ctrl_event); sd_event_source_unref(manager->ctrl_event);
sd_event_source_unref(manager->uevent_event); sd_event_source_unref(manager->uevent_event);
sd_event_source_unref(manager->inotify_event); sd_event_source_unref(manager->inotify_event);
udev_unref(manager->udev);
sd_event_unref(manager->event); sd_event_unref(manager->event);
manager_workers_free(manager); manager_workers_free(manager);
event_queue_cleanup(manager, EVENT_UNDEF); event_queue_cleanup(manager, EVENT_UNDEF);
@ -323,13 +318,12 @@ static bool shall_lock_device(struct udev_device *dev) {
} }
static void worker_spawn(Manager *manager, struct event *event) { static void worker_spawn(Manager *manager, struct event *event) {
struct udev *udev = event->udev;
_cleanup_(udev_monitor_unrefp) struct udev_monitor *worker_monitor = NULL; _cleanup_(udev_monitor_unrefp) struct udev_monitor *worker_monitor = NULL;
pid_t pid; pid_t pid;
int r = 0; int r = 0;
/* listen for new events */ /* listen for new events */
worker_monitor = udev_monitor_new_from_netlink(udev, NULL); worker_monitor = udev_monitor_new_from_netlink(NULL, NULL);
if (worker_monitor == NULL) if (worker_monitor == NULL)
return; return;
/* allow the main daemon netlink address to send devices to the worker */ /* allow the main daemon netlink address to send devices to the worker */
@ -457,7 +451,7 @@ static void worker_spawn(Manager *manager, struct event *event) {
/* apply/restore inotify watch */ /* apply/restore inotify watch */
if (udev_event->inotify_watch) { if (udev_event->inotify_watch) {
udev_watch_begin(udev, dev); udev_watch_begin(dev);
udev_device_update_db(dev); udev_device_update_db(dev);
} }
@ -591,7 +585,6 @@ static int event_queue_insert(Manager *manager, struct udev_device *dev) {
if (!event) if (!event)
return -ENOMEM; return -ENOMEM;
event->udev = udev_device_get_udev(dev);
event->manager = manager; event->manager = manager;
event->dev = dev; event->dev = dev;
event->dev_kernel = udev_device_shallow_clone(dev); event->dev_kernel = udev_device_shallow_clone(dev);
@ -762,7 +755,7 @@ static void manager_reload(Manager *manager) {
manager_kill_workers(manager); manager_kill_workers(manager);
manager->rules = udev_rules_unref(manager->rules); manager->rules = udev_rules_unref(manager->rules);
udev_builtin_exit(manager->udev); udev_builtin_exit();
sd_notifyf(false, sd_notifyf(false,
"READY=1\n" "READY=1\n"
@ -784,16 +777,16 @@ static void event_queue_start(Manager *manager) {
if (manager->last_usec == 0 || if (manager->last_usec == 0 ||
(usec - manager->last_usec) > 3 * USEC_PER_SEC) { (usec - manager->last_usec) > 3 * USEC_PER_SEC) {
if (udev_rules_check_timestamp(manager->rules) || if (udev_rules_check_timestamp(manager->rules) ||
udev_builtin_validate(manager->udev)) udev_builtin_validate())
manager_reload(manager); manager_reload(manager);
manager->last_usec = usec; manager->last_usec = usec;
} }
udev_builtin_init(manager->udev); udev_builtin_init();
if (!manager->rules) { if (!manager->rules) {
manager->rules = udev_rules_new(manager->udev, arg_resolve_names); manager->rules = udev_rules_new(arg_resolve_names);
if (!manager->rules) if (!manager->rules)
return; return;
} }
@ -1014,7 +1007,6 @@ static int synthesize_change(struct udev_device *dev) {
bool part_table_read = false; bool part_table_read = false;
bool has_partitions = false; bool has_partitions = false;
int fd; int fd;
struct udev *udev = udev_device_get_udev(dev);
_cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
struct udev_list_entry *item; struct udev_list_entry *item;
@ -1036,7 +1028,7 @@ static int synthesize_change(struct udev_device *dev) {
} }
/* search for partitions */ /* search for partitions */
e = udev_enumerate_new(udev); e = udev_enumerate_new(NULL);
if (!e) if (!e)
return -ENOMEM; return -ENOMEM;
@ -1055,7 +1047,7 @@ static int synthesize_change(struct udev_device *dev) {
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) { udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
_cleanup_(udev_device_unrefp) struct udev_device *d = NULL; _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); d = udev_device_new_from_syspath(NULL, udev_list_entry_get_name(item));
if (!d) if (!d)
continue; continue;
@ -1085,7 +1077,7 @@ static int synthesize_change(struct udev_device *dev) {
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) { udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
_cleanup_(udev_device_unrefp) struct udev_device *d = NULL; _cleanup_(udev_device_unrefp) struct udev_device *d = NULL;
d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); d = udev_device_new_from_syspath(NULL, udev_list_entry_get_name(item));
if (!d) if (!d)
continue; continue;
@ -1127,7 +1119,7 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
FOREACH_INOTIFY_EVENT(e, buffer, l) { FOREACH_INOTIFY_EVENT(e, buffer, l) {
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL; _cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
dev = udev_watch_lookup(manager->udev, e->wd); dev = udev_watch_lookup(e->wd);
if (!dev) if (!dev)
continue; continue;
@ -1142,7 +1134,7 @@ static int on_inotify(sd_event_source *s, int fd, uint32_t revents, void *userda
*/ */
on_uevent(NULL, -1, 0, manager); on_uevent(NULL, -1, 0, manager);
} else if (e->mask & IN_IGNORED) } else if (e->mask & IN_IGNORED)
udev_watch_end(manager->udev, dev); udev_watch_end(dev);
} }
return 1; return 1;
@ -1252,7 +1244,6 @@ static int on_post(sd_event_source *s, void *userdata) {
} }
static int listen_fds(int *rctrl, int *rnetlink) { static int listen_fds(int *rctrl, int *rnetlink) {
_cleanup_(udev_unrefp) struct udev *udev = NULL;
int ctrl_fd = -1, netlink_fd = -1; int ctrl_fd = -1, netlink_fd = -1;
int fd, n, r; int fd, n, r;
@ -1284,11 +1275,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
if (ctrl_fd < 0) { if (ctrl_fd < 0) {
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *ctrl = NULL; _cleanup_(udev_ctrl_unrefp) struct udev_ctrl *ctrl = NULL;
udev = udev_new(); ctrl = udev_ctrl_new();
if (!udev)
return -ENOMEM;
ctrl = udev_ctrl_new(udev);
if (!ctrl) if (!ctrl)
return log_error_errno(EINVAL, "error initializing udev control socket"); return log_error_errno(EINVAL, "error initializing udev control socket");
@ -1308,13 +1295,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
if (netlink_fd < 0) { if (netlink_fd < 0) {
_cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL; _cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL;
if (!udev) { monitor = udev_monitor_new_from_netlink(NULL, "kernel");
udev = udev_new();
if (!udev)
return -ENOMEM;
}
monitor = udev_monitor_new_from_netlink(udev, "kernel");
if (!monitor) if (!monitor)
return log_error_errno(EINVAL, "error initializing netlink socket"); return log_error_errno(EINVAL, "error initializing netlink socket");
@ -1516,26 +1497,22 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
manager->worker_watch[WRITE_END] = -1; manager->worker_watch[WRITE_END] = -1;
manager->worker_watch[READ_END] = -1; manager->worker_watch[READ_END] = -1;
manager->udev = udev_new(); udev_builtin_init();
if (!manager->udev)
return log_error_errno(errno, "could not allocate udev context: %m");
udev_builtin_init(manager->udev); manager->rules = udev_rules_new(arg_resolve_names);
manager->rules = udev_rules_new(manager->udev, arg_resolve_names);
if (!manager->rules) if (!manager->rules)
return log_error_errno(ENOMEM, "error reading rules"); return log_error_errno(ENOMEM, "error reading rules");
LIST_HEAD_INIT(manager->events); LIST_HEAD_INIT(manager->events);
udev_list_init(manager->udev, &manager->properties, true); udev_list_init(NULL, &manager->properties, true);
manager->cgroup = cgroup; manager->cgroup = cgroup;
manager->ctrl = udev_ctrl_new_from_fd(manager->udev, fd_ctrl); manager->ctrl = udev_ctrl_new_from_fd(fd_ctrl);
if (!manager->ctrl) if (!manager->ctrl)
return log_error_errno(EINVAL, "error taking over udev control socket"); return log_error_errno(EINVAL, "error taking over udev control socket");
manager->monitor = udev_monitor_new_from_netlink_fd(manager->udev, "kernel", fd_uevent); manager->monitor = udev_monitor_new_from_netlink_fd(NULL, "kernel", fd_uevent);
if (!manager->monitor) if (!manager->monitor)
return log_error_errno(EINVAL, "error taking over netlink socket"); return log_error_errno(EINVAL, "error taking over netlink socket");
@ -1550,11 +1527,11 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg
if (r < 0) if (r < 0)
return log_error_errno(errno, "could not enable SO_PASSCRED: %m"); return log_error_errno(errno, "could not enable SO_PASSCRED: %m");
manager->fd_inotify = udev_watch_init(manager->udev); manager->fd_inotify = udev_watch_init();
if (manager->fd_inotify < 0) if (manager->fd_inotify < 0)
return log_error_errno(ENOMEM, "error initializing inotify"); return log_error_errno(ENOMEM, "error initializing inotify");
udev_watch_restore(manager->udev); udev_watch_restore();
/* block and listen to all signals on signalfd */ /* block and listen to all signals on signalfd */
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0); assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);