mirror of
https://github.com/systemd/systemd.git
synced 2025-01-10 05:18:17 +03:00
Merge pull request #9920 from yuwata/udev-cleanup-4
udev: drop unused udev structs and use verbs in udevadm
This commit is contained in:
commit
1327f272d3
2
TODO
2
TODO
@ -15,8 +15,6 @@ Janitorial Clean-ups:
|
||||
* rework mount.c and swap.c to follow proper state enumeration/deserialization
|
||||
semantics, like we do for device.c now
|
||||
|
||||
* udev: drop "collect", it's nonsense
|
||||
|
||||
Features:
|
||||
|
||||
* optionally, if a per-partition GPT flag is set for the root/home/… partitions
|
||||
|
@ -66,6 +66,9 @@ void strbuf_complete(struct strbuf *str) {
|
||||
|
||||
/* clean up everything */
|
||||
void strbuf_cleanup(struct strbuf *str) {
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
strbuf_complete(str);
|
||||
free(str->buf);
|
||||
free(str);
|
||||
|
@ -123,11 +123,9 @@ int util_log_priority(const char *priority);
|
||||
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_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);
|
||||
|
||||
/* libudev-util-private.c */
|
||||
int util_resolve_subsys_kernel(struct udev *udev, const char *string, char *result, size_t maxsize, int read_value);
|
||||
int util_resolve_subsys_kernel(const char *string, char *result, size_t maxsize, int read_value);
|
||||
|
||||
/* Cleanup functions */
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC(struct udev*, udev_unref);
|
||||
|
@ -23,9 +23,8 @@
|
||||
*/
|
||||
|
||||
/* handle "[<SUBSYSTEM>/<KERNEL>]<attribute>" format */
|
||||
int util_resolve_subsys_kernel(struct udev *udev, const char *string,
|
||||
char *result, size_t maxsize, int read_value)
|
||||
{
|
||||
int util_resolve_subsys_kernel(const char *string,
|
||||
char *result, size_t maxsize, int read_value) {
|
||||
char temp[UTIL_PATH_SIZE];
|
||||
char *subsys;
|
||||
char *sysname;
|
||||
@ -58,7 +57,7 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
|
||||
if (read_value && attr == NULL)
|
||||
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)
|
||||
return -1;
|
||||
|
||||
@ -85,8 +84,7 @@ int util_resolve_subsys_kernel(struct udev *udev, const char *string,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int util_log_priority(const char *priority)
|
||||
{
|
||||
int util_log_priority(const char *priority) {
|
||||
char *endptr;
|
||||
int prio;
|
||||
|
||||
@ -101,8 +99,7 @@ int util_log_priority(const char *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;
|
||||
|
||||
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
|
||||
* 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;
|
||||
|
||||
/* 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 */
|
||||
int util_replace_chars(char *str, const char *white)
|
||||
{
|
||||
int util_replace_chars(char *str, const char *white) {
|
||||
size_t i = 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.
|
||||
**/
|
||||
_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);
|
||||
}
|
||||
|
||||
unsigned int util_string_hash32(const char *str)
|
||||
{
|
||||
uint32_t util_string_hash32(const char *str) {
|
||||
return MurmurHash2(str, strlen(str), 0);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
unsigned int hash = util_string_hash32(str);
|
||||
uint32_t hash = util_string_hash32(str);
|
||||
|
||||
bits |= 1LLU << (hash & 63);
|
||||
bits |= 1LLU << ((hash >> 6) & 63);
|
||||
|
@ -52,7 +52,6 @@ static int fake_filesystems(void) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(udev_unrefp) struct udev *udev = NULL;
|
||||
_cleanup_(udev_event_unrefp) struct udev_event *event = NULL;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
|
||||
_cleanup_(udev_rules_unrefp) struct udev_rules *rules = NULL;
|
||||
@ -68,10 +67,6 @@ int main(int argc, char *argv[]) {
|
||||
if (err < 0)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
udev = udev_new();
|
||||
if (udev == NULL)
|
||||
return EXIT_FAILURE;
|
||||
|
||||
log_debug("version %s", PACKAGE_VERSION);
|
||||
mac_selinux_init();
|
||||
|
||||
@ -87,10 +82,10 @@ int main(int argc, char *argv[]) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
rules = udev_rules_new(udev, 1);
|
||||
rules = udev_rules_new(1);
|
||||
|
||||
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) {
|
||||
log_debug("unknown device '%s'", devpath);
|
||||
goto out;
|
||||
|
@ -23,8 +23,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libudev.h"
|
||||
|
||||
#include "fd-util.h"
|
||||
#include "libudev-private.h"
|
||||
#include "log.h"
|
||||
@ -32,14 +30,13 @@
|
||||
|
||||
#define COMMAND_TIMEOUT_MSEC (30 * 1000)
|
||||
|
||||
static int disk_scsi_inquiry_command(int fd,
|
||||
void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
static int disk_scsi_inquiry_command(
|
||||
int fd,
|
||||
void *buf,
|
||||
size_t buf_len) {
|
||||
|
||||
uint8_t cdb[6] = {
|
||||
/*
|
||||
* INQUIRY, see SPC-4 section 6.4
|
||||
*/
|
||||
/* INQUIRY, see SPC-4 section 6.4 */
|
||||
[0] = 0x12, /* OPERATION CODE: INQUIRY */
|
||||
[3] = (buf_len >> 8), /* ALLOCATION LENGTH */
|
||||
[4] = (buf_len & 0xff),
|
||||
@ -101,10 +98,11 @@ static int disk_scsi_inquiry_command(int fd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disk_identify_command(int fd,
|
||||
void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
static int disk_identify_command(
|
||||
int fd,
|
||||
void *buf,
|
||||
size_t buf_len) {
|
||||
|
||||
uint8_t cdb[12] = {
|
||||
/*
|
||||
* ATA Pass-Through 12 byte command, as described in
|
||||
@ -171,10 +169,11 @@ static int disk_identify_command(int fd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int disk_identify_packet_device_command(int fd,
|
||||
void *buf,
|
||||
size_t buf_len)
|
||||
{
|
||||
static int disk_identify_packet_device_command(
|
||||
int fd,
|
||||
void *buf,
|
||||
size_t buf_len) {
|
||||
|
||||
uint8_t cdb[16] = {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static void disk_identify_get_string(uint8_t identify[512],
|
||||
unsigned int offset_words,
|
||||
char *dest,
|
||||
size_t dest_len)
|
||||
{
|
||||
static void disk_identify_get_string(
|
||||
uint8_t identify[512],
|
||||
unsigned int offset_words,
|
||||
char *dest,
|
||||
size_t dest_len) {
|
||||
|
||||
unsigned int c1;
|
||||
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],
|
||||
unsigned int offset_words,
|
||||
size_t len)
|
||||
{
|
||||
static void disk_identify_fixup_string(
|
||||
uint8_t identify[512],
|
||||
unsigned int offset_words,
|
||||
size_t len) {
|
||||
disk_identify_get_string(identify, offset_words,
|
||||
(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;
|
||||
|
||||
p = (uint16_t *) identify;
|
||||
@ -294,7 +293,6 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned int offs
|
||||
|
||||
/**
|
||||
* disk_identify:
|
||||
* @udev: The libudev context.
|
||||
* @fd: File descriptor for the block device.
|
||||
* @out_identify: Return location for IDENTIFY data.
|
||||
* @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
|
||||
* non-zero with errno set.
|
||||
*/
|
||||
static int disk_identify(struct udev *udev,
|
||||
int fd,
|
||||
static int disk_identify(int fd,
|
||||
uint8_t out_identify[512],
|
||||
int *out_is_packet_device)
|
||||
{
|
||||
int *out_is_packet_device) {
|
||||
int ret;
|
||||
uint8_t inquiry_buf[36];
|
||||
int peripheral_device_type;
|
||||
@ -390,7 +386,6 @@ out:
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
_cleanup_(udev_unrefp) struct udev *udev = NULL;
|
||||
struct hd_driveid id;
|
||||
union {
|
||||
uint8_t byte[512];
|
||||
@ -416,10 +411,6 @@ int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
udev = udev_new();
|
||||
if (udev == NULL)
|
||||
return 0;
|
||||
|
||||
for (;;) {
|
||||
int option;
|
||||
|
||||
@ -451,7 +442,7 @@ int main(int argc, char *argv[]) {
|
||||
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
|
||||
* use and copy it into the hd_driveid struct for convenience
|
||||
|
@ -20,11 +20,10 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libudev.h"
|
||||
|
||||
#include "libudev-private.h"
|
||||
#include "log.h"
|
||||
#include "random-util.h"
|
||||
#include "udev-util.h"
|
||||
#include "util.h"
|
||||
|
||||
/* device info */
|
||||
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 ASCQ(errcode) ((errcode) & 0xFF)
|
||||
|
||||
static bool is_mounted(const char *device)
|
||||
{
|
||||
static bool is_mounted(const char *device) {
|
||||
struct stat statbuf;
|
||||
FILE *fp;
|
||||
int maj, min;
|
||||
@ -109,8 +107,7 @@ static bool is_mounted(const char *device)
|
||||
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) {
|
||||
log_debug("%s failed", cmd);
|
||||
return;
|
||||
@ -127,8 +124,7 @@ struct scsi_cmd {
|
||||
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));
|
||||
cmd->cgc.quiet = 1;
|
||||
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;
|
||||
}
|
||||
|
||||
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->cgc.cmd[i] = arg;
|
||||
}
|
||||
|
||||
#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;
|
||||
|
||||
if (bufsize > 0) {
|
||||
@ -173,8 +167,7 @@ static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigne
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int media_lock(struct udev *udev, int fd, bool lock)
|
||||
{
|
||||
static int media_lock(int fd, bool lock) {
|
||||
int err;
|
||||
|
||||
/* disable the kernel's lock logic */
|
||||
@ -189,25 +182,23 @@ static int media_lock(struct udev *udev, int fd, bool lock)
|
||||
return err;
|
||||
}
|
||||
|
||||
static int media_eject(struct udev *udev, int fd)
|
||||
{
|
||||
static int media_eject(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
int err;
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x1b);
|
||||
scsi_cmd_set(udev, &sc, 4, 0x02);
|
||||
scsi_cmd_set(udev, &sc, 5, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, NULL, 0);
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x1b);
|
||||
scsi_cmd_set(&sc, 4, 0x02);
|
||||
scsi_cmd_set(&sc, 5, 0);
|
||||
err = scsi_cmd_run(&sc, fd, NULL, 0);
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "START_STOP_UNIT", err);
|
||||
info_scsi_cmd_err("START_STOP_UNIT", err);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cd_capability_compat(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_capability_compat(int fd) {
|
||||
int capability;
|
||||
|
||||
capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL);
|
||||
@ -233,8 +224,7 @@ static int cd_capability_compat(struct udev *udev, int fd)
|
||||
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) {
|
||||
log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK");
|
||||
return -1;
|
||||
@ -243,19 +233,18 @@ static int cd_media_compat(struct udev *udev, int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cd_inquiry(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_inquiry(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
unsigned char inq[128];
|
||||
int err;
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x12);
|
||||
scsi_cmd_set(udev, &sc, 4, 36);
|
||||
scsi_cmd_set(udev, &sc, 5, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, inq, 36);
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x12);
|
||||
scsi_cmd_set(&sc, 4, 36);
|
||||
scsi_cmd_set(&sc, 5, 0);
|
||||
err = scsi_cmd_run(&sc, fd, inq, 36);
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "INQUIRY", err);
|
||||
info_scsi_cmd_err("INQUIRY", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -268,8 +257,7 @@ static int cd_inquiry(struct udev *udev, int fd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void feature_profile_media(struct udev *udev, int cur_profile)
|
||||
{
|
||||
static void feature_profile_media(int cur_profile) {
|
||||
switch (cur_profile) {
|
||||
case 0x03:
|
||||
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;
|
||||
|
||||
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 */
|
||||
static int cd_profiles_old_mmc(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_profiles_old_mmc(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
int err;
|
||||
|
||||
unsigned char header[32];
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x51);
|
||||
scsi_cmd_set(udev, &sc, 8, sizeof(header));
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x51);
|
||||
scsi_cmd_set(&sc, 8, sizeof(header));
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, header, sizeof(header));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ DISC INFORMATION", err);
|
||||
info_scsi_cmd_err("READ DISC INFORMATION", err);
|
||||
if (cd_media == 1) {
|
||||
log_debug("no current profile, but disc is present; assuming CD-ROM");
|
||||
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 */
|
||||
static int cd_profiles(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_profiles(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
unsigned char features[65530];
|
||||
unsigned int cur_profile = 0;
|
||||
@ -522,18 +507,18 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
ret = -1;
|
||||
|
||||
/* First query the current profile */
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x46);
|
||||
scsi_cmd_set(udev, &sc, 8, 8);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, features, 8);
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x46);
|
||||
scsi_cmd_set(&sc, 8, 8);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, features, 8);
|
||||
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 */
|
||||
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("trying to work around the problem");
|
||||
ret = cd_profiles_old_mmc(udev, fd);
|
||||
ret = cd_profiles_old_mmc(fd);
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
@ -541,7 +526,7 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
cur_profile = features[6] << 8 | features[7];
|
||||
if (cur_profile > 0) {
|
||||
log_debug("current profile 0x%02x", cur_profile);
|
||||
feature_profile_media (udev, cur_profile);
|
||||
feature_profile_media(cur_profile);
|
||||
ret = 0; /* we have media */
|
||||
} else {
|
||||
log_debug("no current profile, assuming no media");
|
||||
@ -557,14 +542,14 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
len = sizeof(features);
|
||||
|
||||
/* Now get the full feature buffer */
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x46);
|
||||
scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 8, len & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, features, len);
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x46);
|
||||
scsi_cmd_set(&sc, 7, ( len >> 8 ) & 0xff);
|
||||
scsi_cmd_set(&sc, 8, len & 0xff);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, features, len);
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "GET CONFIGURATION", err);
|
||||
info_scsi_cmd_err("GET CONFIGURATION", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -586,7 +571,7 @@ static int cd_profiles(struct udev *udev, int fd)
|
||||
switch (feature) {
|
||||
case 0x00:
|
||||
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;
|
||||
default:
|
||||
log_debug("GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes", feature, features[i+3]);
|
||||
@ -597,8 +582,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int cd_media_info(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_media_info(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
unsigned char header[32];
|
||||
static const char *media_status[] = {
|
||||
@ -609,13 +593,13 @@ static int cd_media_info(struct udev *udev, int fd)
|
||||
};
|
||||
int err;
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x51);
|
||||
scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x51);
|
||||
scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, header, sizeof(header));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ DISC INFORMATION", err);
|
||||
info_scsi_cmd_err("READ DISC INFORMATION", err);
|
||||
return -1;
|
||||
};
|
||||
|
||||
@ -647,14 +631,14 @@ static int cd_media_info(struct udev *udev, int fd)
|
||||
unsigned char dvdstruct[8];
|
||||
unsigned char format[12];
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0xAD);
|
||||
scsi_cmd_set(udev, &sc, 7, 0xC0);
|
||||
scsi_cmd_set(udev, &sc, 9, sizeof(dvdstruct));
|
||||
scsi_cmd_set(udev, &sc, 11, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, dvdstruct, sizeof(dvdstruct));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0xAD);
|
||||
scsi_cmd_set(&sc, 7, 0xC0);
|
||||
scsi_cmd_set(&sc, 9, sizeof(dvdstruct));
|
||||
scsi_cmd_set(&sc, 11, 0);
|
||||
err = scsi_cmd_run(&sc, fd, dvdstruct, sizeof(dvdstruct));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ DVD STRUCTURE", err);
|
||||
info_scsi_cmd_err("READ DVD STRUCTURE", err);
|
||||
return -1;
|
||||
}
|
||||
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 */
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x23);
|
||||
scsi_cmd_set(udev, &sc, 8, sizeof(format));
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, format, sizeof(format));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x23);
|
||||
scsi_cmd_set(&sc, 8, sizeof(format));
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, format, sizeof(format));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ DVD FORMAT CAPACITIES", err);
|
||||
info_scsi_cmd_err("READ DVD FORMAT CAPACITIES", err);
|
||||
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
|
||||
* for ISO and UDF PVDs or a fs superblock presence and do it
|
||||
* in one ioctl (we need just sectors 0 and 16) */
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x28);
|
||||
scsi_cmd_set(udev, &sc, 5, 0);
|
||||
scsi_cmd_set(udev, &sc, 8, 32);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, buffer, sizeof(buffer));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x28);
|
||||
scsi_cmd_set(&sc, 5, 0);
|
||||
scsi_cmd_set(&sc, 8, 32);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, buffer, sizeof(buffer));
|
||||
if ((err != 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;
|
||||
}
|
||||
|
||||
@ -750,8 +734,7 @@ determined:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cd_media_toc(struct udev *udev, int fd)
|
||||
{
|
||||
static int cd_media_toc(int fd) {
|
||||
struct scsi_cmd sc;
|
||||
unsigned char header[12];
|
||||
unsigned char toc[65536];
|
||||
@ -759,14 +742,14 @@ static int cd_media_toc(struct udev *udev, int fd)
|
||||
unsigned char *p;
|
||||
int err;
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x43);
|
||||
scsi_cmd_set(udev, &sc, 6, 1);
|
||||
scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x43);
|
||||
scsi_cmd_set(&sc, 6, 1);
|
||||
scsi_cmd_set(&sc, 8, sizeof(header) & 0xff);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, header, sizeof(header));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ TOC", err);
|
||||
info_scsi_cmd_err("READ TOC", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -783,15 +766,15 @@ static int cd_media_toc(struct udev *udev, int fd)
|
||||
if (len < 8)
|
||||
return 0;
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x43);
|
||||
scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */
|
||||
scsi_cmd_set(udev, &sc, 7, (len >> 8) & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 8, len & 0xff);
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, toc, len);
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x43);
|
||||
scsi_cmd_set(&sc, 6, header[2]); /* First Track/Session Number */
|
||||
scsi_cmd_set(&sc, 7, (len >> 8) & 0xff);
|
||||
scsi_cmd_set(&sc, 8, len & 0xff);
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, toc, len);
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ TOC (tracks)", err);
|
||||
info_scsi_cmd_err("READ TOC (tracks)", err);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -814,14 +797,14 @@ static int cd_media_toc(struct udev *udev, int fd)
|
||||
cd_media_track_count_audio++;
|
||||
}
|
||||
|
||||
scsi_cmd_init(udev, &sc);
|
||||
scsi_cmd_set(udev, &sc, 0, 0x43);
|
||||
scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */
|
||||
scsi_cmd_set(udev, &sc, 8, sizeof(header));
|
||||
scsi_cmd_set(udev, &sc, 9, 0);
|
||||
err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header));
|
||||
scsi_cmd_init(&sc);
|
||||
scsi_cmd_set(&sc, 0, 0x43);
|
||||
scsi_cmd_set(&sc, 2, 1); /* Session Info */
|
||||
scsi_cmd_set(&sc, 8, sizeof(header));
|
||||
scsi_cmd_set(&sc, 9, 0);
|
||||
err = scsi_cmd_run(&sc, fd, header, sizeof(header));
|
||||
if ((err != 0)) {
|
||||
info_scsi_cmd_err(udev, "READ TOC (multi session)", err);
|
||||
info_scsi_cmd_err("READ TOC (multi session)", err);
|
||||
return -1;
|
||||
}
|
||||
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[]) {
|
||||
struct udev *udev;
|
||||
static const struct option options[] = {
|
||||
{ "lock-media", no_argument, NULL, 'l' },
|
||||
{ "unlock-media", no_argument, NULL, 'u' },
|
||||
@ -853,10 +835,6 @@ int main(int argc, char *argv[]) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
udev = udev_new();
|
||||
if (udev == NULL)
|
||||
goto exit;
|
||||
|
||||
for (;;) {
|
||||
int option;
|
||||
|
||||
@ -896,7 +874,6 @@ int main(int argc, char *argv[]) {
|
||||
node = argv[optind];
|
||||
if (!node) {
|
||||
log_error("no device");
|
||||
fprintf(stderr, "no device\n");
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
@ -914,55 +891,54 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
if (fd < 0) {
|
||||
log_debug("unable to open '%s'", node);
|
||||
fprintf(stderr, "unable to open '%s'\n", node);
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
log_debug("probing: '%s'", node);
|
||||
|
||||
/* same data as original cdrom_id */
|
||||
if (cd_capability_compat(udev, fd) < 0) {
|
||||
if (cd_capability_compat(fd) < 0) {
|
||||
rc = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* check for media - don't bail if there's no media as we still need to
|
||||
* to read profiles */
|
||||
cd_media_compat(udev, fd);
|
||||
cd_media_compat(fd);
|
||||
|
||||
/* check if drive talks MMC */
|
||||
if (cd_inquiry(udev, fd) < 0)
|
||||
if (cd_inquiry(fd) < 0)
|
||||
goto work;
|
||||
|
||||
/* read drive and possibly current profile */
|
||||
if (cd_profiles(udev, fd) != 0)
|
||||
if (cd_profiles(fd) != 0)
|
||||
goto work;
|
||||
|
||||
/* at this point we are guaranteed to have media in the drive - find out more about it */
|
||||
|
||||
/* get session/track info */
|
||||
cd_media_toc(udev, fd);
|
||||
cd_media_toc(fd);
|
||||
|
||||
/* get writable media state */
|
||||
cd_media_info(udev, fd);
|
||||
cd_media_info(fd);
|
||||
|
||||
work:
|
||||
/* lock the media, so we enable eject button events */
|
||||
if (lock && cd_media) {
|
||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)");
|
||||
media_lock(udev, fd, true);
|
||||
media_lock(fd, true);
|
||||
}
|
||||
|
||||
if (unlock && cd_media) {
|
||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
||||
media_lock(udev, fd, false);
|
||||
media_lock(fd, false);
|
||||
}
|
||||
|
||||
if (eject) {
|
||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
||||
media_lock(udev, fd, false);
|
||||
media_lock(fd, false);
|
||||
log_debug("START_STOP_UNIT (eject)");
|
||||
media_eject(udev, fd);
|
||||
media_eject(fd);
|
||||
}
|
||||
|
||||
printf("ID_CDROM=1\n");
|
||||
@ -1067,7 +1043,6 @@ work:
|
||||
exit:
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
udev_unref(udev);
|
||||
log_close();
|
||||
return rc;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
@ -2,14 +2,15 @@
|
||||
|
||||
udevadm_sources = files('''
|
||||
udevadm.c
|
||||
udevadm-info.c
|
||||
udevadm.h
|
||||
udevadm-control.c
|
||||
udevadm-monitor.c
|
||||
udevadm-hwdb.c
|
||||
udevadm-info.c
|
||||
udevadm-monitor.c
|
||||
udevadm-settle.c
|
||||
udevadm-trigger.c
|
||||
udevadm-test.c
|
||||
udevadm-test-builtin.c
|
||||
udevadm-trigger.c
|
||||
udevadm-util.c
|
||||
udevadm-util.h
|
||||
'''.split())
|
||||
@ -159,7 +160,6 @@ libudev_core = static_library(
|
||||
|
||||
foreach prog : [['ata_id/ata_id.c'],
|
||||
['cdrom_id/cdrom_id.c'],
|
||||
['collect/collect.c'],
|
||||
['scsi_id/scsi_id.c',
|
||||
'scsi_id/scsi_id.h',
|
||||
'scsi_id/scsi_serial.c',
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <netinet/ether.h>
|
||||
|
||||
#include "sd-device.h"
|
||||
#include "sd-netlink.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
@ -9,8 +10,6 @@
|
||||
#include "conf-parser.h"
|
||||
#include "ethtool-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "libudev-device-internal.h"
|
||||
#include "libudev-private.h"
|
||||
#include "link-config.h"
|
||||
#include "log.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);
|
||||
}
|
||||
|
||||
int link_config_get(link_config_ctx *ctx, struct udev_device *device,
|
||||
link_config **ret) {
|
||||
int link_config_get(link_config_ctx *ctx, sd_device *device, link_config **ret) {
|
||||
link_config *link;
|
||||
|
||||
assert(ctx);
|
||||
@ -227,43 +225,50 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device,
|
||||
assert(ret);
|
||||
|
||||
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,
|
||||
link->match_type, link->match_name, link->match_host,
|
||||
link->match_virt, link->match_kernel_cmdline,
|
||||
link->match_kernel_version, link->match_arch,
|
||||
attr_value ? ether_aton(attr_value) : NULL,
|
||||
udev_device_get_property_value(device, "ID_PATH"),
|
||||
udev_device_get_driver(udev_device_get_parent(device)),
|
||||
udev_device_get_property_value(device, "ID_NET_DRIVER"),
|
||||
udev_device_get_devtype(device),
|
||||
udev_device_get_sysname(device))) {
|
||||
address ? ether_aton(address) : NULL,
|
||||
id_path,
|
||||
parent_driver,
|
||||
id_net_driver,
|
||||
devtype,
|
||||
sysname)) {
|
||||
if (link->match_name) {
|
||||
unsigned char name_assign_type = NET_NAME_UNKNOWN;
|
||||
const char *attr_value;
|
||||
|
||||
attr_value = udev_device_get_sysattr_value(device, "name_assign_type");
|
||||
if (attr_value)
|
||||
if (sd_device_get_sysattr_value(device, "name_assign_type", &attr_value) >= 0)
|
||||
(void) safe_atou8(attr_value, &name_assign_type);
|
||||
|
||||
if (name_assign_type == NET_NAME_ENUM) {
|
||||
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;
|
||||
|
||||
return 0;
|
||||
} else if (name_assign_type == NET_NAME_RENAMED) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("Config file %s applies to device %s",
|
||||
link->filename, udev_device_get_sysname(device));
|
||||
link->filename, sysname);
|
||||
|
||||
*ret = link;
|
||||
|
||||
@ -276,14 +281,13 @@ int link_config_get(link_config_ctx *ctx, struct udev_device *device,
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
static bool mac_is_random(struct udev_device *device) {
|
||||
static bool mac_is_random(sd_device *device) {
|
||||
const char *s;
|
||||
unsigned type;
|
||||
int r;
|
||||
|
||||
/* if we can't get the assign type, assume it is not random */
|
||||
s = udev_device_get_sysattr_value(device, "addr_assign_type");
|
||||
if (!s)
|
||||
if (sd_device_get_sysattr_value(device, "addr_assign_type", &s) < 0)
|
||||
return false;
|
||||
|
||||
r = safe_atou(s, &type);
|
||||
@ -293,14 +297,13 @@ static bool mac_is_random(struct udev_device *device) {
|
||||
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;
|
||||
unsigned type;
|
||||
int r;
|
||||
|
||||
/* if we can't get the assgin type, assume we should rename */
|
||||
s = udev_device_get_sysattr_value(device, "name_assign_type");
|
||||
if (!s)
|
||||
if (sd_device_get_sysattr_value(device, "name_assign_type", &s) < 0)
|
||||
return true;
|
||||
|
||||
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) {
|
||||
int r;
|
||||
|
||||
@ -333,7 +336,7 @@ static int get_mac(struct udev_device *device, bool want_random,
|
||||
else {
|
||||
uint64_t result;
|
||||
|
||||
r = net_get_unique_predictable_data(device->device, &result);
|
||||
r = net_get_unique_predictable_data(device, &result);
|
||||
if (r < 0)
|
||||
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,
|
||||
struct udev_device *device, const char **name) {
|
||||
sd_device *device, const char **name) {
|
||||
bool respect_predictable = false;
|
||||
struct ether_addr generated_mac;
|
||||
struct ether_addr *mac = NULL;
|
||||
@ -363,9 +366,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
|
||||
assert(device);
|
||||
assert(name);
|
||||
|
||||
old_name = udev_device_get_sysname(device);
|
||||
if (!old_name)
|
||||
return -EINVAL;
|
||||
r = sd_device_get_sysname(device, &old_name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ethtool_set_glinksettings(&ctx->ethtool_fd, old_name, config);
|
||||
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);
|
||||
}
|
||||
|
||||
ifindex = udev_device_get_ifindex(device);
|
||||
if (ifindex <= 0) {
|
||||
log_warning("Could not find ifindex");
|
||||
return -ENODEV;
|
||||
}
|
||||
r = sd_device_get_ifindex(device, &ifindex);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "Could not find ifindex: %m");
|
||||
if (ifindex <= 0)
|
||||
return log_warning_errno(EINVAL, "Invalid ifindex '%d'", ifindex);
|
||||
|
||||
if (ctx->enable_name_policy && config->name_policy) {
|
||||
NamePolicy *policy;
|
||||
@ -413,19 +416,19 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
|
||||
respect_predictable = true;
|
||||
break;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
@ -477,14 +480,14 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
|
||||
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;
|
||||
char *driver = NULL;
|
||||
int r;
|
||||
|
||||
name = udev_device_get_sysname(device);
|
||||
if (!name)
|
||||
return -EINVAL;
|
||||
r = sd_device_get_sysname(device, &name);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = ethtool_get_driver(&ctx->ethtool_fd, name, &driver);
|
||||
if (r < 0)
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
#pragma once
|
||||
|
||||
#include "libudev.h"
|
||||
#include "sd-device.h"
|
||||
|
||||
#include "condition.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);
|
||||
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_apply(link_config_ctx *ctx, struct link_config *config, struct udev_device *device, const char **name);
|
||||
|
||||
int link_get_driver(link_config_ctx *ctx, struct udev_device *device, char **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, sd_device *device, const char **name);
|
||||
int link_get_driver(link_config_ctx *ctx, sd_device *device, char **ret);
|
||||
|
||||
const char *name_policy_to_string(NamePolicy p) _const_;
|
||||
NamePolicy name_policy_from_string(const char *p) _pure_;
|
||||
|
@ -17,8 +17,6 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libudev.h"
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "libudev-private.h"
|
||||
@ -55,8 +53,7 @@ static char model_enc_str[256];
|
||||
static char revision_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;
|
||||
char *eptr;
|
||||
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
|
||||
* matches.
|
||||
*/
|
||||
static char *get_value(char **buffer)
|
||||
{
|
||||
static char *get_value(char **buffer) {
|
||||
static const char *quote_string = "\"\n";
|
||||
static const char *comma_string = ",\n";
|
||||
char *val;
|
||||
@ -130,8 +126,7 @@ static char *get_value(char **buffer)
|
||||
return val;
|
||||
}
|
||||
|
||||
static int argc_count(char *opts)
|
||||
{
|
||||
static int argc_count(char *opts) {
|
||||
int i = 0;
|
||||
while (*opts != '\0')
|
||||
if (*opts++ == ' ')
|
||||
@ -148,10 +143,8 @@ static int argc_count(char *opts)
|
||||
*
|
||||
* vendor and model can end in '\n'.
|
||||
*/
|
||||
static int get_file_options(struct udev *udev,
|
||||
const char *vendor, const char *model,
|
||||
int *argc, char ***newargv)
|
||||
{
|
||||
static int get_file_options(const char *vendor, const char *model,
|
||||
int *argc, char ***newargv) {
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
_cleanup_fclose_ FILE *f;
|
||||
char *buf;
|
||||
@ -311,10 +304,8 @@ static void help(void) {
|
||||
|
||||
}
|
||||
|
||||
static int set_options(struct udev *udev,
|
||||
int argc, char **argv,
|
||||
char *maj_min_dev)
|
||||
{
|
||||
static int set_options(int argc, char **argv,
|
||||
char *maj_min_dev) {
|
||||
int option;
|
||||
|
||||
/*
|
||||
@ -400,9 +391,7 @@ static int set_options(struct udev *udev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int per_dev_options(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int *good_bad, int *page_code)
|
||||
{
|
||||
static int per_dev_options(struct scsi_id_device *dev_scsi, int *good_bad, int *page_code) {
|
||||
int retval;
|
||||
int newargc;
|
||||
char **newargv = NULL;
|
||||
@ -411,7 +400,7 @@ static int per_dev_options(struct udev *udev,
|
||||
*good_bad = all_good;
|
||||
*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 */
|
||||
while (retval == 0) {
|
||||
@ -455,13 +444,12 @@ static int per_dev_options(struct udev *udev,
|
||||
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;
|
||||
|
||||
dev_scsi->use_sg = sg_version;
|
||||
|
||||
retval = scsi_std_inquiry(udev, dev_scsi, path);
|
||||
retval = scsi_std_inquiry(dev_scsi, path);
|
||||
if (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.
|
||||
* 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 = {};
|
||||
int good_dev;
|
||||
int page_code;
|
||||
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;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
retval = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
char serial_str[MAX_SERIAL_LEN];
|
||||
@ -557,7 +544,6 @@ out:
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
_cleanup_(udev_unrefp) struct udev *udev;
|
||||
int retval = 0;
|
||||
char maj_min_dev[MAX_PATH_LEN];
|
||||
int newargc;
|
||||
@ -568,14 +554,10 @@ int main(int argc, char **argv) {
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
udev = udev_new();
|
||||
if (udev == NULL)
|
||||
goto exit;
|
||||
|
||||
/*
|
||||
* Get config file options.
|
||||
*/
|
||||
retval = get_file_options(udev, NULL, NULL, &newargc, &newargv);
|
||||
retval = get_file_options(NULL, NULL, &newargc, &newargv);
|
||||
if (retval < 0) {
|
||||
retval = 1;
|
||||
goto exit;
|
||||
@ -583,7 +565,7 @@ int main(int argc, char **argv) {
|
||||
if (retval == 0) {
|
||||
assert(newargv);
|
||||
|
||||
if (set_options(udev, newargc, newargv, maj_min_dev) < 0) {
|
||||
if (set_options(newargc, newargv, maj_min_dev) < 0) {
|
||||
retval = 2;
|
||||
goto exit;
|
||||
}
|
||||
@ -592,7 +574,7 @@ int main(int argc, char **argv) {
|
||||
/*
|
||||
* 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);
|
||||
|
||||
if (!dev_specified) {
|
||||
@ -601,7 +583,7 @@ int main(int argc, char **argv) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retval = scsi_id(udev, maj_min_dev);
|
||||
retval = scsi_id(maj_min_dev);
|
||||
|
||||
exit:
|
||||
if (newargv) {
|
||||
|
@ -48,8 +48,8 @@ struct scsi_id_device {
|
||||
char tgpt_group[8];
|
||||
};
|
||||
|
||||
int scsi_std_inquiry(struct udev *udev, 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_std_inquiry(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);
|
||||
|
||||
/*
|
||||
|
@ -21,13 +21,11 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "libudev.h"
|
||||
|
||||
#include "libudev-private.h"
|
||||
#include "random-util.h"
|
||||
#include "scsi.h"
|
||||
#include "scsi_id.h"
|
||||
#include "string-util.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
* 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_OTHER 99 /* Some other error/warning */
|
||||
|
||||
static int do_scsi_page80_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int max_len);
|
||||
|
||||
static int sg_err_category_new(struct udev *udev,
|
||||
int scsi_status, int msg_status, int
|
||||
static int sg_err_category_new(int scsi_status, int msg_status, int
|
||||
host_status, int driver_status, const
|
||||
unsigned char *sense_buffer, int sb_len)
|
||||
{
|
||||
unsigned char *sense_buffer, int sb_len) {
|
||||
scsi_status &= 0x7e;
|
||||
|
||||
/*
|
||||
@ -140,35 +135,26 @@ static int sg_err_category_new(struct udev *udev,
|
||||
return SG_ERR_CAT_OTHER;
|
||||
}
|
||||
|
||||
static int sg_err_category3(struct udev *udev, struct sg_io_hdr *hp)
|
||||
{
|
||||
return sg_err_category_new(udev,
|
||||
hp->status, hp->msg_status,
|
||||
static int sg_err_category3(struct sg_io_hdr *hp) {
|
||||
return sg_err_category_new(hp->status, hp->msg_status,
|
||||
hp->host_status, hp->driver_status,
|
||||
hp->sbp, hp->sb_len_wr);
|
||||
}
|
||||
|
||||
static int sg_err_category4(struct udev *udev, struct sg_io_v4 *hp)
|
||||
{
|
||||
return sg_err_category_new(udev, hp->device_status, 0,
|
||||
static int sg_err_category4(struct sg_io_v4 *hp) {
|
||||
return sg_err_category_new(hp->device_status, 0,
|
||||
hp->transport_status, hp->driver_status,
|
||||
(unsigned char *)(uintptr_t)hp->response,
|
||||
hp->response_len);
|
||||
}
|
||||
|
||||
static int scsi_dump_sense(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi,
|
||||
unsigned char *sense_buffer, int sb_len)
|
||||
{
|
||||
static int scsi_dump_sense(struct scsi_id_device *dev_scsi,
|
||||
unsigned char *sense_buffer, int sb_len) {
|
||||
int s;
|
||||
int code;
|
||||
int sense_class;
|
||||
int sense_key;
|
||||
int asc, ascq;
|
||||
#ifdef DUMP_SENSE
|
||||
char out_buffer[256];
|
||||
int i, j;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
static int scsi_dump(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, struct sg_io_hdr *io)
|
||||
{
|
||||
static int scsi_dump(struct scsi_id_device *dev_scsi, struct sg_io_hdr *io) {
|
||||
if (!io->status && !io->host_status && !io->msg_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",
|
||||
dev_scsi->kernel, io->driver_status, io->host_status, io->msg_status, io->status);
|
||||
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
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int scsi_dump_v4(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, struct sg_io_v4 *io)
|
||||
{
|
||||
static int scsi_dump_v4(struct scsi_id_device *dev_scsi, struct sg_io_v4 *io) {
|
||||
if (!io->device_status && !io->transport_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",
|
||||
dev_scsi->kernel, io->driver_status, io->transport_status, io->device_status);
|
||||
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);
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int scsi_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
static int scsi_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
unsigned char evpd, unsigned char page,
|
||||
unsigned char *buf, unsigned int buflen)
|
||||
{
|
||||
unsigned char *buf, unsigned int buflen) {
|
||||
unsigned char inq_cmd[INQUIRY_CMDLEN] =
|
||||
{ INQUIRY_CMD, evpd, page, 0, buflen, 0 };
|
||||
unsigned char sense[SENSE_BUFF_LEN];
|
||||
@ -352,9 +321,9 @@ resend:
|
||||
}
|
||||
|
||||
if (dev_scsi->use_sg == 4)
|
||||
retval = sg_err_category4(udev, io_buf);
|
||||
retval = sg_err_category4(io_buf);
|
||||
else
|
||||
retval = sg_err_category3(udev, io_buf);
|
||||
retval = sg_err_category3(io_buf);
|
||||
|
||||
switch (retval) {
|
||||
case SG_ERR_CAT_NOTSUPPORTED:
|
||||
@ -367,9 +336,9 @@ resend:
|
||||
|
||||
default:
|
||||
if (dev_scsi->use_sg == 4)
|
||||
retval = scsi_dump_v4(udev, dev_scsi, io_buf);
|
||||
retval = scsi_dump_v4(dev_scsi, io_buf);
|
||||
else
|
||||
retval = scsi_dump(udev, dev_scsi, io_buf);
|
||||
retval = scsi_dump(dev_scsi, io_buf);
|
||||
}
|
||||
|
||||
if (!retval) {
|
||||
@ -389,14 +358,12 @@ error:
|
||||
}
|
||||
|
||||
/* Get list of supported EVPD pages */
|
||||
static int do_scsi_page0_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
unsigned char *buffer, unsigned int len)
|
||||
{
|
||||
static int do_scsi_page0_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
unsigned char *buffer, unsigned int len) {
|
||||
int retval;
|
||||
|
||||
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)
|
||||
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 +
|
||||
* model.
|
||||
*/
|
||||
static int prepend_vendor_model(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, char *serial)
|
||||
{
|
||||
static int prepend_vendor_model(struct scsi_id_device *dev_scsi, char *serial) {
|
||||
int ind;
|
||||
|
||||
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
|
||||
* serial number.
|
||||
*/
|
||||
static int check_fill_0x83_id(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi,
|
||||
static int check_fill_0x83_id(struct scsi_id_device *dev_scsi,
|
||||
unsigned char *page_83,
|
||||
const struct scsi_id_search_values
|
||||
*id_search, char *serial, char *serial_short,
|
||||
int max_len, char *wwn,
|
||||
char *wwn_vendor_extension, char *tgpt_group)
|
||||
{
|
||||
char *wwn_vendor_extension, char *tgpt_group) {
|
||||
int i, j, s, len;
|
||||
|
||||
/*
|
||||
@ -534,7 +497,7 @@ static int check_fill_0x83_id(struct udev *udev,
|
||||
* included in the identifier.
|
||||
*/
|
||||
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;
|
||||
|
||||
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 */
|
||||
static int check_fill_0x83_prespc3(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi,
|
||||
static int check_fill_0x83_prespc3(struct scsi_id_device *dev_scsi,
|
||||
unsigned char *page_83,
|
||||
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;
|
||||
|
||||
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 */
|
||||
static int do_scsi_page83_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
static int do_scsi_page83_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int len,
|
||||
char *unit_serial_number, char *wwn,
|
||||
char *wwn_vendor_extension, char *tgpt_group)
|
||||
{
|
||||
char *wwn_vendor_extension, char *tgpt_group) {
|
||||
int retval;
|
||||
unsigned int id_ind, j;
|
||||
unsigned char page_83[SCSI_INQ_BUFF_LEN];
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
if (retval < 0)
|
||||
return 1;
|
||||
@ -645,8 +604,7 @@ static int do_scsi_page83_inquiry(struct udev *udev,
|
||||
*/
|
||||
|
||||
if (page_83[6] != 0)
|
||||
return check_fill_0x83_prespc3(udev,
|
||||
dev_scsi, page_83, id_search_list,
|
||||
return check_fill_0x83_prespc3(dev_scsi, page_83, id_search_list,
|
||||
serial, serial_short, len);
|
||||
|
||||
/*
|
||||
@ -661,8 +619,7 @@ static int do_scsi_page83_inquiry(struct udev *udev,
|
||||
* one or a small number of descriptors.
|
||||
*/
|
||||
for (j = 4; j <= (unsigned int)page_83[3] + 3; j += page_83[j + 3] + 4) {
|
||||
retval = check_fill_0x83_id(udev,
|
||||
dev_scsi, &page_83[j],
|
||||
retval = check_fill_0x83_id(dev_scsi, &page_83[j],
|
||||
&id_search_list[id_ind],
|
||||
serial, serial_short, len,
|
||||
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
|
||||
* conformant to the SCSI-2 format.
|
||||
*/
|
||||
static int do_scsi_page83_prespc3_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int len)
|
||||
{
|
||||
static int do_scsi_page83_prespc3_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int len) {
|
||||
int retval;
|
||||
int i, j;
|
||||
unsigned char 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)
|
||||
return 1;
|
||||
|
||||
@ -745,10 +700,8 @@ static int do_scsi_page83_prespc3_inquiry(struct udev *udev,
|
||||
}
|
||||
|
||||
/* Get unit serial number VPD page */
|
||||
static int do_scsi_page80_inquiry(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int max_len)
|
||||
{
|
||||
static int do_scsi_page80_inquiry(struct scsi_id_device *dev_scsi, int fd,
|
||||
char *serial, char *serial_short, int max_len) {
|
||||
int retval;
|
||||
int ser_ind;
|
||||
int i;
|
||||
@ -756,7 +709,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
|
||||
unsigned char 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)
|
||||
return retval;
|
||||
|
||||
@ -778,7 +731,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
|
||||
len = buf[3];
|
||||
if (serial != NULL) {
|
||||
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)
|
||||
return 1;
|
||||
ser_ind++; /* for the leading 'S' */
|
||||
@ -792,9 +745,7 @@ static int do_scsi_page80_inquiry(struct udev *udev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 fd;
|
||||
unsigned char buf[SCSI_INQ_BUFF_LEN];
|
||||
struct stat statbuf;
|
||||
@ -815,7 +766,7 @@ int scsi_std_inquiry(struct udev *udev,
|
||||
minor(statbuf.st_rdev));
|
||||
|
||||
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)
|
||||
goto out;
|
||||
|
||||
@ -833,10 +784,8 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
int scsi_get_serial(struct udev *udev,
|
||||
struct scsi_id_device *dev_scsi, const char *devname,
|
||||
int page_code, int len)
|
||||
{
|
||||
int scsi_get_serial(struct scsi_id_device *dev_scsi, const char *devname,
|
||||
int page_code, int len) {
|
||||
unsigned char page0[SCSI_INQ_BUFF_LEN];
|
||||
int fd = -1;
|
||||
int cnt;
|
||||
@ -859,7 +808,7 @@ int scsi_get_serial(struct udev *udev,
|
||||
return 1;
|
||||
|
||||
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;
|
||||
goto completed;
|
||||
} else {
|
||||
@ -867,7 +816,7 @@ int scsi_get_serial(struct udev *udev,
|
||||
goto completed;
|
||||
}
|
||||
} 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;
|
||||
goto completed;
|
||||
} else {
|
||||
@ -875,7 +824,7 @@ int scsi_get_serial(struct udev *udev,
|
||||
goto completed;
|
||||
}
|
||||
} 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) {
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
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;
|
||||
goto completed;
|
||||
} 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
|
||||
* 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
|
||||
* 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++)
|
||||
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)) {
|
||||
/*
|
||||
* Success
|
||||
@ -932,7 +881,7 @@ int scsi_get_serial(struct udev *udev,
|
||||
|
||||
for (ind = 4; ind <= page0[3] + 3; ind++)
|
||||
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)) {
|
||||
/*
|
||||
* Success
|
||||
|
@ -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 */
|
||||
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)
|
||||
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 */
|
||||
static int builtin_hwdb_init(struct udev *udev) {
|
||||
static int builtin_hwdb_init(void) {
|
||||
int r;
|
||||
|
||||
if (hwdb)
|
||||
@ -185,12 +185,12 @@ static int builtin_hwdb_init(struct udev *udev) {
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool te
|
||||
}
|
||||
|
||||
/* called at udev startup and reload */
|
||||
static int builtin_kmod_init(struct udev *udev) {
|
||||
static int builtin_kmod_init(void) {
|
||||
if (ctx)
|
||||
return 0;
|
||||
|
||||
@ -48,19 +48,19 @@ static int builtin_kmod_init(struct udev *udev) {
|
||||
return -ENOMEM;
|
||||
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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");
|
||||
ctx = kmod_unref(ctx);
|
||||
}
|
||||
|
||||
/* 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");
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
@ -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) {
|
||||
struct udev *udev;
|
||||
const char *physfn_link_file;
|
||||
_cleanup_free_ char *physfn_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 = {};
|
||||
int r;
|
||||
|
||||
udev = udev_device_get_udev(names->pcidev);
|
||||
if (!udev)
|
||||
return -ENOENT;
|
||||
/* Check if this is a virtual function. */
|
||||
physfn_link_file = strjoina(udev_device_get_syspath(names->pcidev), "/physfn");
|
||||
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;
|
||||
|
||||
/* 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)
|
||||
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) {
|
||||
struct udev *udev = udev_device_get_udev(names->pcidev);
|
||||
unsigned domain, bus, slot, func, dev_port = 0, hotplug_slot = 0;
|
||||
size_t l;
|
||||
char *s;
|
||||
@ -331,7 +326,7 @@ static int dev_pci_slot(struct udev_device *dev, struct netnames *names) {
|
||||
names->pci_path[0] = '\0';
|
||||
|
||||
/* 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)
|
||||
return -ENOENT;
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1+ */
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "libudev-device-internal.h"
|
||||
#include "link-config.h"
|
||||
#include "log.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;
|
||||
}
|
||||
|
||||
r = link_get_driver(ctx, dev, &driver);
|
||||
r = link_get_driver(ctx, dev->device, &driver);
|
||||
if (r >= 0)
|
||||
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 == -ENOENT) {
|
||||
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)
|
||||
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;
|
||||
}
|
||||
|
||||
static int builtin_net_setup_link_init(struct udev *udev) {
|
||||
static int builtin_net_setup_link_init(void) {
|
||||
int r;
|
||||
|
||||
if (ctx)
|
||||
@ -63,13 +64,13 @@ static int builtin_net_setup_link_init(struct udev *udev) {
|
||||
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);
|
||||
ctx = NULL;
|
||||
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.");
|
||||
if (!ctx)
|
||||
return false;
|
||||
|
@ -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) {
|
||||
struct udev *udev;
|
||||
struct udev_device *targetdev;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *fcdev = NULL;
|
||||
const char *port;
|
||||
@ -95,13 +94,12 @@ static struct udev_device *handle_scsi_fibre_channel(struct udev_device *parent,
|
||||
assert(parent);
|
||||
assert(path);
|
||||
|
||||
udev = udev_device_get_udev(parent);
|
||||
|
||||
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
|
||||
if (!targetdev)
|
||||
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)
|
||||
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) {
|
||||
struct udev *udev;
|
||||
struct udev_device *targetdev, *target_parent;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *sasdev = NULL;
|
||||
const char *sas_address;
|
||||
@ -124,7 +121,6 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
|
||||
assert(parent);
|
||||
assert(path);
|
||||
|
||||
udev = udev_device_get_udev(parent);
|
||||
|
||||
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
|
||||
if (!targetdev)
|
||||
@ -134,7 +130,7 @@ static struct udev_device *handle_scsi_sas_wide_port(struct udev_device *parent,
|
||||
if (!target_parent)
|
||||
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));
|
||||
if (!sasdev)
|
||||
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)
|
||||
{
|
||||
struct udev *udev;
|
||||
struct udev_device *targetdev, *target_parent, *port, *expander;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device
|
||||
*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(path);
|
||||
|
||||
udev = udev_device_get_udev(parent);
|
||||
|
||||
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_target");
|
||||
if (!targetdev)
|
||||
@ -173,8 +167,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
|
||||
return NULL;
|
||||
|
||||
/* Get sas device */
|
||||
target_sasdev = udev_device_new_from_subsystem_sysname(
|
||||
udev, "sas_device", udev_device_get_sysname(target_parent));
|
||||
target_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_device", udev_device_get_sysname(target_parent));
|
||||
if (!target_sasdev)
|
||||
return NULL;
|
||||
|
||||
@ -184,8 +177,7 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
|
||||
return NULL;
|
||||
|
||||
/* Get port device */
|
||||
port_sasdev = udev_device_new_from_subsystem_sysname(
|
||||
udev, "sas_port", udev_device_get_sysname(port));
|
||||
port_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_port", udev_device_get_sysname(port));
|
||||
|
||||
phy_count = udev_device_get_sysattr_value(port_sasdev, "num_phys");
|
||||
if (!phy_count)
|
||||
@ -206,12 +198,10 @@ static struct udev_device *handle_scsi_sas(struct udev_device *parent, char **pa
|
||||
return NULL;
|
||||
|
||||
/* Get expander device */
|
||||
expander_sasdev = udev_device_new_from_subsystem_sysname(
|
||||
udev, "sas_device", udev_device_get_sysname(expander));
|
||||
expander_sasdev = udev_device_new_from_subsystem_sysname(NULL, "sas_device", udev_device_get_sysname(expander));
|
||||
if (expander_sasdev) {
|
||||
/* Get expander's address */
|
||||
sas_address = udev_device_get_sysattr_value(expander_sasdev,
|
||||
"sas_address");
|
||||
sas_address = udev_device_get_sysattr_value(expander_sasdev, "sas_address");
|
||||
if (!sas_address)
|
||||
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) {
|
||||
struct udev *udev;
|
||||
struct udev_device *transportdev;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device
|
||||
*sessiondev = NULL, *conndev = NULL;
|
||||
@ -236,7 +225,6 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
|
||||
assert(parent);
|
||||
assert(path);
|
||||
|
||||
udev = udev_device_get_udev(parent);
|
||||
|
||||
/* find iscsi session */
|
||||
transportdev = parent;
|
||||
@ -249,7 +237,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
|
||||
}
|
||||
|
||||
/* 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)
|
||||
return NULL;
|
||||
|
||||
@ -258,7 +246,7 @@ static struct udev_device *handle_scsi_iscsi(struct udev_device *parent, char **
|
||||
return NULL;
|
||||
|
||||
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)
|
||||
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) {
|
||||
struct udev *udev;
|
||||
struct udev_device *targetdev, *target_parent;
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *atadev = NULL;
|
||||
const char *port_no;
|
||||
@ -281,7 +268,6 @@ static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **pa
|
||||
assert(parent);
|
||||
assert(path);
|
||||
|
||||
udev = udev_device_get_udev(parent);
|
||||
|
||||
targetdev = udev_device_get_parent_with_subsystem_devtype(parent, "scsi", "scsi_host");
|
||||
if (!targetdev)
|
||||
@ -291,7 +277,7 @@ static struct udev_device *handle_scsi_ata(struct udev_device *parent, char **pa
|
||||
if (!target_parent)
|
||||
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)
|
||||
return NULL;
|
||||
|
||||
|
@ -29,7 +29,7 @@ static const struct udev_builtin *builtins[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
void udev_builtin_init(struct udev *udev) {
|
||||
void udev_builtin_init(void) {
|
||||
unsigned int i;
|
||||
|
||||
if (initialized)
|
||||
@ -37,12 +37,12 @@ void udev_builtin_init(struct udev *udev) {
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(builtins); i++)
|
||||
if (builtins[i] && builtins[i]->init)
|
||||
builtins[i]->init(udev);
|
||||
builtins[i]->init();
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
void udev_builtin_exit(struct udev *udev) {
|
||||
void udev_builtin_exit(void) {
|
||||
unsigned int i;
|
||||
|
||||
if (!initialized)
|
||||
@ -50,21 +50,21 @@ void udev_builtin_exit(struct udev *udev) {
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(builtins); i++)
|
||||
if (builtins[i] && builtins[i]->exit)
|
||||
builtins[i]->exit(udev);
|
||||
builtins[i]->exit();
|
||||
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
bool udev_builtin_validate(struct udev *udev) {
|
||||
bool udev_builtin_validate(void) {
|
||||
unsigned int 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 false;
|
||||
}
|
||||
|
||||
void udev_builtin_list(struct udev *udev) {
|
||||
void udev_builtin_list(void) {
|
||||
unsigned int 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 */
|
||||
optind = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -49,14 +49,13 @@ struct udev_ctrl_msg_wire {
|
||||
};
|
||||
|
||||
struct udev_ctrl_msg {
|
||||
int refcount;
|
||||
unsigned n_ref;
|
||||
struct udev_ctrl_connection *conn;
|
||||
struct udev_ctrl_msg_wire ctrl_msg_wire;
|
||||
};
|
||||
|
||||
struct udev_ctrl {
|
||||
int refcount;
|
||||
struct udev *udev;
|
||||
unsigned n_ref;
|
||||
int sock;
|
||||
union sockaddr_union saddr;
|
||||
socklen_t addrlen;
|
||||
@ -66,12 +65,12 @@ struct udev_ctrl {
|
||||
};
|
||||
|
||||
struct udev_ctrl_connection {
|
||||
int refcount;
|
||||
unsigned n_ref;
|
||||
struct udev_ctrl *uctrl;
|
||||
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;
|
||||
const int on = 1;
|
||||
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);
|
||||
if (uctrl == NULL)
|
||||
return NULL;
|
||||
uctrl->refcount = 1;
|
||||
uctrl->udev = udev;
|
||||
uctrl->n_ref = 1;
|
||||
|
||||
if (fd < 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;
|
||||
}
|
||||
|
||||
struct udev_ctrl *udev_ctrl_new(struct udev *udev) {
|
||||
return udev_ctrl_new_from_fd(udev, -1);
|
||||
struct udev_ctrl *udev_ctrl_new(void) {
|
||||
return udev_ctrl_new_from_fd(-1);
|
||||
}
|
||||
|
||||
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) {
|
||||
@ -135,26 +133,15 @@ int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct udev *udev_ctrl_get_udev(struct udev_ctrl *uctrl) {
|
||||
return uctrl->udev;
|
||||
static struct udev_ctrl *udev_ctrl_free(struct udev_ctrl *uctrl) {
|
||||
assert(uctrl);
|
||||
|
||||
safe_close(uctrl->sock);
|
||||
return mfree(uctrl);
|
||||
}
|
||||
|
||||
static struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl) {
|
||||
if (uctrl)
|
||||
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;
|
||||
}
|
||||
DEFINE_PRIVATE_TRIVIAL_REF_FUNC(struct udev_ctrl, udev_ctrl);
|
||||
DEFINE_TRIVIAL_UNREF_FUNC(struct udev_ctrl, udev_ctrl, udev_ctrl_free);
|
||||
|
||||
int udev_ctrl_cleanup(struct udev_ctrl *uctrl) {
|
||||
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);
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
conn->refcount = 1;
|
||||
conn->n_ref = 1;
|
||||
conn->uctrl = uctrl;
|
||||
|
||||
conn->sock = accept4(uctrl->sock, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK);
|
||||
@ -213,25 +200,15 @@ err:
|
||||
return mfree(conn);
|
||||
}
|
||||
|
||||
struct udev_ctrl_connection *udev_ctrl_connection_ref(struct udev_ctrl_connection *conn) {
|
||||
if (conn == NULL)
|
||||
return NULL;
|
||||
conn->refcount++;
|
||||
return conn;
|
||||
static struct udev_ctrl_connection *udev_ctrl_connection_free(struct udev_ctrl_connection *conn) {
|
||||
assert(conn);
|
||||
|
||||
safe_close(conn->sock);
|
||||
udev_ctrl_unref(conn->uctrl);
|
||||
return mfree(conn);
|
||||
}
|
||||
|
||||
struct udev_ctrl_connection *udev_ctrl_connection_unref(struct udev_ctrl_connection *conn) {
|
||||
if (conn && -- conn->refcount == 0) {
|
||||
if (conn->sock >= 0)
|
||||
close(conn->sock);
|
||||
|
||||
udev_ctrl_unref(conn->uctrl);
|
||||
|
||||
free(conn);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
DEFINE_TRIVIAL_REF_UNREF_FUNC(struct udev_ctrl_connection, udev_ctrl_connection, udev_ctrl_connection_free);
|
||||
|
||||
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;
|
||||
@ -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);
|
||||
if (uctrl_msg == NULL)
|
||||
return NULL;
|
||||
uctrl_msg->refcount = 1;
|
||||
uctrl_msg->n_ref = 1;
|
||||
uctrl_msg->conn = conn;
|
||||
udev_ctrl_connection_ref(conn);
|
||||
|
||||
@ -402,15 +379,15 @@ err:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct udev_ctrl_msg *udev_ctrl_msg_unref(struct udev_ctrl_msg *ctrl_msg) {
|
||||
if (ctrl_msg && -- ctrl_msg->refcount == 0) {
|
||||
udev_ctrl_connection_unref(ctrl_msg->conn);
|
||||
free(ctrl_msg);
|
||||
}
|
||||
static struct udev_ctrl_msg *udev_ctrl_msg_free(struct udev_ctrl_msg *ctrl_msg) {
|
||||
assert(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) {
|
||||
if (ctrl_msg->ctrl_msg_wire.type == UDEV_CTRL_SET_LOG_LEVEL)
|
||||
return ctrl_msg->ctrl_msg_wire.intval;
|
||||
|
@ -33,16 +33,14 @@ typedef struct Spawn {
|
||||
} Spawn;
|
||||
|
||||
struct udev_event *udev_event_new(struct udev_device *dev) {
|
||||
struct udev *udev = udev_device_get_udev(dev);
|
||||
struct udev_event *event;
|
||||
|
||||
event = new0(struct udev_event, 1);
|
||||
if (event == NULL)
|
||||
return NULL;
|
||||
event->dev = dev;
|
||||
event->udev = udev;
|
||||
udev_list_init(udev, &event->run_list, false);
|
||||
udev_list_init(udev, &event->seclabel_list, false);
|
||||
udev_list_init(NULL, &event->run_list, false);
|
||||
udev_list_init(NULL, &event->seclabel_list, false);
|
||||
event->birth_usec = now(CLOCK_MONOTONIC);
|
||||
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" */
|
||||
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;
|
||||
|
||||
/* try to read the attribute the device */
|
||||
@ -698,7 +696,7 @@ static int spawn_wait(struct udev_event *event,
|
||||
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;
|
||||
char *pos;
|
||||
|
||||
@ -771,7 +769,7 @@ int udev_event_spawn(struct udev_event *event,
|
||||
errpipe[READ_END] = safe_close(errpipe[READ_END]);
|
||||
|
||||
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 */
|
||||
if (argv[0][0] != '/') {
|
||||
@ -845,7 +843,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
udev_device_delete_db(dev);
|
||||
|
||||
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,
|
||||
timeout_usec, timeout_warn_usec,
|
||||
@ -858,7 +856,7 @@ void udev_event_execute_rules(struct udev_event *event,
|
||||
if (event->dev_db != NULL) {
|
||||
/* disable watch during event processing */
|
||||
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 &&
|
||||
streq(udev_device_get_action(dev), "move"))
|
||||
|
@ -113,7 +113,6 @@ exit:
|
||||
|
||||
/* 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) {
|
||||
struct udev *udev = udev_device_get_udev(dev);
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
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)))
|
||||
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) {
|
||||
const char *devnode;
|
||||
|
||||
|
@ -50,7 +50,6 @@ static const char* const rules_dirs[] = {
|
||||
};
|
||||
|
||||
struct udev_rules {
|
||||
struct udev *udev;
|
||||
usec_t dirs_ts_usec;
|
||||
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 *temp;
|
||||
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} */
|
||||
static const char *get_key_attribute(struct udev *udev, char *str) {
|
||||
static const char *get_key_attribute(char *str) {
|
||||
char *pos;
|
||||
char *attr;
|
||||
|
||||
@ -1019,7 +1018,7 @@ static void add_rule(struct udev_rules *rules, char *line,
|
||||
char *value;
|
||||
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
|
||||
* so save the work for the error case instead of always trying
|
||||
* 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);
|
||||
|
||||
} else if (startswith(key, "ATTR{")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("ATTR"));
|
||||
attr = get_key_attribute(key + STRLEN("ATTR"));
|
||||
if (attr == NULL)
|
||||
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);
|
||||
|
||||
} else if (startswith(key, "SYSCTL{")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("SYSCTL"));
|
||||
attr = get_key_attribute(key + STRLEN("SYSCTL"));
|
||||
if (attr == NULL)
|
||||
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);
|
||||
|
||||
} else if (startswith(key, "SECLABEL{")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("SECLABEL"));
|
||||
attr = get_key_attribute(key + STRLEN("SECLABEL"));
|
||||
if (attr == NULL)
|
||||
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)
|
||||
LOG_AND_RETURN("invalid %s operation", "ATTRS");
|
||||
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("ATTRS"));
|
||||
attr = get_key_attribute(key + STRLEN("ATTRS"));
|
||||
if (attr == NULL)
|
||||
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);
|
||||
|
||||
} else if (startswith(key, "ENV{")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("ENV"));
|
||||
attr = get_key_attribute(key + STRLEN("ENV"));
|
||||
if (attr == NULL)
|
||||
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);
|
||||
|
||||
} else if (startswith(key, "IMPORT")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("IMPORT"));
|
||||
attr = get_key_attribute(key + STRLEN("IMPORT"));
|
||||
if (attr == NULL) {
|
||||
LOG_RULE_WARNING("ignoring IMPORT{} with missing type");
|
||||
continue;
|
||||
@ -1252,8 +1245,7 @@ static void add_rule(struct udev_rules *rules, char *line,
|
||||
if (op > OP_MATCH_MAX)
|
||||
LOG_AND_RETURN("invalid %s operation", "TEST");
|
||||
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("TEST"));
|
||||
attr = get_key_attribute(key + STRLEN("TEST"));
|
||||
if (attr != NULL) {
|
||||
mode = strtol(attr, NULL, 8);
|
||||
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);
|
||||
|
||||
} else if (startswith(key, "RUN")) {
|
||||
attr = get_key_attribute(rules->udev,
|
||||
key + STRLEN("RUN"));
|
||||
attr = get_key_attribute(key + STRLEN("RUN"));
|
||||
if (attr == NULL)
|
||||
attr = "program";
|
||||
if (op == OP_REMOVE)
|
||||
@ -1513,7 +1504,7 @@ static int parse_file(struct udev_rules *rules, const char *filename) {
|
||||
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_list file_list;
|
||||
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);
|
||||
if (rules == NULL)
|
||||
return NULL;
|
||||
rules->udev = udev;
|
||||
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 */
|
||||
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;
|
||||
break;
|
||||
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;
|
||||
value = vbuf;
|
||||
break;
|
||||
@ -1923,7 +1913,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
|
||||
int match;
|
||||
|
||||
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] != '/') {
|
||||
char tmp[UTIL_PATH_SIZE];
|
||||
|
||||
@ -2356,7 +2346,7 @@ void udev_rules_apply_to_event(struct udev_rules *rules,
|
||||
char value[UTIL_NAME_SIZE];
|
||||
_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);
|
||||
attr_subst_subdir(attr, sizeof(attr));
|
||||
|
||||
|
@ -20,7 +20,7 @@ static int inotify_fd = -1;
|
||||
* set to cloexec since we need our children to be able to add
|
||||
* watches for us
|
||||
*/
|
||||
int udev_watch_init(struct udev *udev) {
|
||||
int udev_watch_init(void) {
|
||||
inotify_fd = inotify_init1(IN_CLOEXEC);
|
||||
if (inotify_fd < 0)
|
||||
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
|
||||
* the watches
|
||||
*/
|
||||
void udev_watch_restore(struct udev *udev) {
|
||||
void udev_watch_restore(void) {
|
||||
if (inotify_fd < 0)
|
||||
return;
|
||||
|
||||
@ -57,12 +57,12 @@ void udev_watch_restore(struct udev *udev) {
|
||||
goto unlink;
|
||||
device[len] = '\0';
|
||||
|
||||
dev = udev_device_new_from_device_id(udev, device);
|
||||
dev = udev_device_new_from_device_id(NULL, device);
|
||||
if (dev == NULL)
|
||||
goto unlink;
|
||||
|
||||
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);
|
||||
unlink:
|
||||
(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");
|
||||
}
|
||||
|
||||
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)];
|
||||
int wd;
|
||||
int r;
|
||||
@ -101,7 +101,7 @@ void udev_watch_begin(struct udev *udev, struct udev_device *dev) {
|
||||
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;
|
||||
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);
|
||||
}
|
||||
|
||||
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 device[UTIL_NAME_SIZE];
|
||||
ssize_t len;
|
||||
@ -135,5 +135,5 @@ struct udev_device *udev_watch_lookup(struct udev *udev, int wd) {
|
||||
return NULL;
|
||||
device[len] = '\0';
|
||||
|
||||
return udev_device_new_from_device_id(udev, device);
|
||||
return udev_device_new_from_device_id(NULL, device);
|
||||
}
|
||||
|
@ -19,7 +19,6 @@
|
||||
#include "util.h"
|
||||
|
||||
struct udev_event {
|
||||
struct udev *udev;
|
||||
struct udev_device *dev;
|
||||
struct udev_device *dev_parent;
|
||||
struct udev_device *dev_db;
|
||||
@ -48,15 +47,9 @@ struct udev_event {
|
||||
bool run_final;
|
||||
};
|
||||
|
||||
struct udev_watch {
|
||||
struct udev_list_node node;
|
||||
int handle;
|
||||
char *name;
|
||||
};
|
||||
|
||||
/* udev-rules.c */
|
||||
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);
|
||||
bool udev_rules_check_timestamp(struct udev_rules *rules);
|
||||
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_rules *rules);
|
||||
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 */
|
||||
int udev_watch_init(struct udev *udev);
|
||||
void udev_watch_restore(struct udev *udev);
|
||||
void udev_watch_begin(struct udev *udev, struct udev_device *dev);
|
||||
void udev_watch_end(struct udev *udev, struct udev_device *dev);
|
||||
struct udev_device *udev_watch_lookup(struct udev *udev, int wd);
|
||||
int udev_watch_init(void);
|
||||
void udev_watch_restore(void);
|
||||
void udev_watch_begin(struct udev_device *dev);
|
||||
void udev_watch_end(struct udev_device *dev);
|
||||
struct udev_device *udev_watch_lookup(int wd);
|
||||
|
||||
/* udev-node.c */
|
||||
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 */
|
||||
struct udev_ctrl;
|
||||
struct udev_ctrl *udev_ctrl_new(struct udev *udev);
|
||||
struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd);
|
||||
struct udev_ctrl *udev_ctrl_new(void);
|
||||
struct udev_ctrl *udev_ctrl_new_from_fd(int fd);
|
||||
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
|
||||
struct udev_ctrl *udev_ctrl_unref(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_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);
|
||||
@ -156,9 +148,9 @@ struct udev_builtin {
|
||||
const char *name;
|
||||
int (*cmd)(struct udev_device *dev, int argc, char *argv[], bool test);
|
||||
const char *help;
|
||||
int (*init)(struct udev *udev);
|
||||
void (*exit)(struct udev *udev);
|
||||
bool (*validate)(struct udev *udev);
|
||||
int (*init)(void);
|
||||
void (*exit)(void);
|
||||
bool (*validate)(void);
|
||||
bool run_once;
|
||||
};
|
||||
#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_usb_id;
|
||||
extern const struct udev_builtin udev_builtin_uaccess;
|
||||
void udev_builtin_init(struct udev *udev);
|
||||
void udev_builtin_exit(struct udev *udev);
|
||||
void udev_builtin_init(void);
|
||||
void udev_builtin_exit(void);
|
||||
enum udev_builtin_cmd udev_builtin_lookup(const char *command);
|
||||
const char *udev_builtin_name(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);
|
||||
void udev_builtin_list(struct udev *udev);
|
||||
bool udev_builtin_validate(struct udev *udev);
|
||||
void udev_builtin_list(void);
|
||||
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_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias,
|
||||
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_connection*, udev_ctrl_connection_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;
|
||||
|
@ -19,12 +19,13 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "parse-util.h"
|
||||
#include "process-util.h"
|
||||
#include "time-util.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"
|
||||
"Control the udev daemon.\n\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"
|
||||
" -t --timeout=SECONDS Maximum time to block for a reply\n"
|
||||
, 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;
|
||||
int timeout = 60;
|
||||
int rc = 1, c;
|
||||
int c, r;
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "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)
|
||||
return 1;
|
||||
r = must_be_root();
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
uctrl = udev_ctrl_new(udev);
|
||||
if (uctrl == NULL)
|
||||
return 2;
|
||||
if (argc <= 1)
|
||||
log_error("Option missing");
|
||||
|
||||
uctrl = udev_ctrl_new();
|
||||
if (!uctrl)
|
||||
return -ENOMEM;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "el:sSRp:m:t:Vh", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
case 'e':
|
||||
if (udev_ctrl_send_exit(uctrl, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = udev_ctrl_send_exit(uctrl, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case 'l': {
|
||||
int i;
|
||||
|
||||
i = util_log_priority(optarg);
|
||||
if (i < 0) {
|
||||
log_error("invalid number '%s'", optarg);
|
||||
return rc;
|
||||
}
|
||||
if (udev_ctrl_send_set_log_level(uctrl, util_log_priority(optarg), timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
if (i < 0)
|
||||
return log_error_errno(i, "invalid number '%s'", optarg);
|
||||
|
||||
r = udev_ctrl_send_set_log_level(uctrl, i, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
case 's':
|
||||
if (udev_ctrl_send_stop_exec_queue(uctrl, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = udev_ctrl_send_stop_exec_queue(uctrl, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case 'S':
|
||||
if (udev_ctrl_send_start_exec_queue(uctrl, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = udev_ctrl_send_start_exec_queue(uctrl, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case 'R':
|
||||
if (udev_ctrl_send_reload(uctrl, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = udev_ctrl_send_reload(uctrl, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case 'p':
|
||||
if (strchr(optarg, '=') == NULL) {
|
||||
if (!strchr(optarg, '=')) {
|
||||
log_error("expect <KEY>=<value> instead of '%s'", optarg);
|
||||
return rc;
|
||||
return -EINVAL;
|
||||
}
|
||||
if (udev_ctrl_send_set_env(uctrl, optarg, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = udev_ctrl_send_set_env(uctrl, optarg, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
case 'm': {
|
||||
char *endp;
|
||||
int i;
|
||||
unsigned i;
|
||||
|
||||
i = strtoul(optarg, &endp, 0);
|
||||
if (endp[0] != '\0' || i < 1) {
|
||||
log_error("invalid number '%s'", optarg);
|
||||
return rc;
|
||||
}
|
||||
if (udev_ctrl_send_set_children_max(uctrl, i, timeout) < 0)
|
||||
rc = 2;
|
||||
else
|
||||
rc = 0;
|
||||
r = safe_atou(optarg, &i);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse maximum number of events '%s': %m", optarg);
|
||||
|
||||
r = udev_ctrl_send_set_children_max(uctrl, i, timeout);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
case 't': {
|
||||
int r, seconds;
|
||||
usec_t 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);
|
||||
|
||||
if (DIV_ROUND_UP(s, USEC_PER_SEC) > INT_MAX)
|
||||
log_error("Timeout value is out of range.");
|
||||
else {
|
||||
seconds = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
|
||||
timeout = seconds;
|
||||
rc = 0;
|
||||
}
|
||||
log_error("Timeout value is out of range, ignoring.");
|
||||
else
|
||||
timeout = s != USEC_INFINITY ? (int) DIV_ROUND_UP(s, USEC_PER_SEC) : INT_MAX;
|
||||
break;
|
||||
}
|
||||
case 'V':
|
||||
print_version();
|
||||
rc = 0;
|
||||
break;
|
||||
return version();
|
||||
case 'h':
|
||||
print_help();
|
||||
rc = 0;
|
||||
break;
|
||||
return help();
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown option.");
|
||||
}
|
||||
|
||||
if (optind < argc)
|
||||
if (optind < argc) {
|
||||
log_error("Extraneous argument: %s", argv[optind]);
|
||||
else if (optind == 1)
|
||||
return -EINVAL;
|
||||
} else if (optind == 1) {
|
||||
log_error("Option missing");
|
||||
return rc;
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_control = {
|
||||
.name = "control",
|
||||
.cmd = adm_control,
|
||||
.help = "Control the udev daemon",
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,10 +13,11 @@
|
||||
#include "hwdb-util.h"
|
||||
#include "label.h"
|
||||
#include "mkdir.h"
|
||||
#include "path-util.h"
|
||||
#include "strbuf.h"
|
||||
#include "string-util.h"
|
||||
#include "udev.h"
|
||||
#include "udevadm-util.h"
|
||||
#include "udevadm.h"
|
||||
#include "util.h"
|
||||
|
||||
/*
|
||||
@ -24,6 +25,12 @@
|
||||
* 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[] = {
|
||||
"/etc/udev/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) {
|
||||
size_t i;
|
||||
|
||||
if (!node)
|
||||
return;
|
||||
|
||||
for (i = 0; i < node->children_count; i++)
|
||||
trie_node_cleanup(node->children[i].child);
|
||||
free(node->children);
|
||||
@ -114,6 +124,17 @@ static void trie_node_cleanup(struct trie_node *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) {
|
||||
const struct trie_value_entry *val1 = v1;
|
||||
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;
|
||||
}
|
||||
|
||||
static int import_file(struct udev *udev, struct trie *trie, const char *filename) {
|
||||
static int import_file(struct trie *trie, const char *filename) {
|
||||
enum {
|
||||
HW_MATCH,
|
||||
HW_DATA,
|
||||
@ -447,7 +468,7 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
|
||||
struct udev_list match_list;
|
||||
int r = 0, err;
|
||||
|
||||
udev_list_init(udev, &match_list, false);
|
||||
udev_list_init(NULL, &match_list, false);
|
||||
|
||||
f = fopen(filename, "re");
|
||||
if (f == NULL)
|
||||
@ -538,7 +559,87 @@ static int import_file(struct udev *udev, struct trie *trie, const char *filenam
|
||||
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"
|
||||
" -h --help Print this message\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"
|
||||
"Please use systemd-hwdb instead.\n"
|
||||
, 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 {
|
||||
ARG_USR = 0x100,
|
||||
};
|
||||
@ -568,144 +671,59 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{}
|
||||
};
|
||||
const char *test = NULL;
|
||||
const char *root = "";
|
||||
const char *hwdb_bin_dir = "/etc/udev";
|
||||
bool update = false;
|
||||
struct trie *trie = NULL;
|
||||
int err, c;
|
||||
int rc = EXIT_SUCCESS;
|
||||
bool strict = false;
|
||||
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "ust:r:Vh", options, NULL)) >= 0)
|
||||
switch(c) {
|
||||
case 'u':
|
||||
update = true;
|
||||
arg_update = true;
|
||||
break;
|
||||
case ARG_USR:
|
||||
hwdb_bin_dir = UDEVLIBEXECDIR;
|
||||
arg_hwdb_bin_dir = UDEVLIBEXECDIR;
|
||||
break;
|
||||
case 's':
|
||||
strict = true;
|
||||
arg_strict = true;
|
||||
break;
|
||||
case 't':
|
||||
test = optarg;
|
||||
arg_test = optarg;
|
||||
break;
|
||||
case 'r':
|
||||
root = optarg;
|
||||
arg_root = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
return EXIT_SUCCESS;
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
return EXIT_SUCCESS;
|
||||
return help();
|
||||
case '?':
|
||||
return EXIT_FAILURE;
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown option");
|
||||
}
|
||||
|
||||
if (!update && !test) {
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_hwdb = {
|
||||
.name = "hwdb",
|
||||
.cmd = adm_hwdb,
|
||||
};
|
||||
int hwdb_main(int argc, char *argv[], void *userdata) {
|
||||
int r;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "string-util.h"
|
||||
#include "udev.h"
|
||||
#include "udevadm.h"
|
||||
#include "udevadm-util.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static int export_devices(struct udev *udev) {
|
||||
static int export_devices(void) {
|
||||
_cleanup_(udev_enumerate_unrefp) struct udev_enumerate *udev_enumerate;
|
||||
struct udev_list_entry *list_entry;
|
||||
|
||||
udev_enumerate = udev_enumerate_new(udev);
|
||||
udev_enumerate = udev_enumerate_new(NULL);
|
||||
if (udev_enumerate == NULL)
|
||||
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)) {
|
||||
_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)
|
||||
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;
|
||||
|
||||
(void) unlink("/run/udev/queue.bin");
|
||||
@ -229,7 +230,7 @@ static void cleanup_db(struct udev *udev) {
|
||||
cleanup_dir(dir5, 0, 1);
|
||||
}
|
||||
|
||||
static void help(void) {
|
||||
static int help(void) {
|
||||
|
||||
printf("%s info [OPTIONS] [DEVPATH|FILE]\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"
|
||||
" -c --cleanup-db Clean up the udev database\n"
|
||||
, 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;
|
||||
bool root = 0;
|
||||
bool export = 0;
|
||||
const char *export_prefix = NULL;
|
||||
char name[UTIL_PATH_SIZE];
|
||||
struct udev_list_entry *list_entry;
|
||||
int c;
|
||||
int c, r;
|
||||
|
||||
static const struct option options[] = {
|
||||
{ "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)
|
||||
switch (c) {
|
||||
case 'n': {
|
||||
if (device != NULL) {
|
||||
fprintf(stderr, "device already specified\n");
|
||||
return 2;
|
||||
case 'n':
|
||||
if (device) {
|
||||
log_error("device already specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
device = find_device(udev, optarg, "/dev/");
|
||||
if (device == NULL) {
|
||||
fprintf(stderr, "device node not found\n");
|
||||
return 2;
|
||||
}
|
||||
device = find_device(optarg, "/dev/");
|
||||
if (!device)
|
||||
return log_error_errno(errno, "device node not found: %m");
|
||||
break;
|
||||
}
|
||||
case 'p':
|
||||
if (device != NULL) {
|
||||
fprintf(stderr, "device already specified\n");
|
||||
return 2;
|
||||
if (device) {
|
||||
log_error("device already specified");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
device = find_device(udev, optarg, "/sys");
|
||||
if (device == NULL) {
|
||||
fprintf(stderr, "syspath not found\n");
|
||||
return 2;
|
||||
}
|
||||
device = find_device(optarg, "/sys");
|
||||
if (!device)
|
||||
return log_error_errno(errno, "syspath not found: %m");
|
||||
break;
|
||||
case 'q':
|
||||
action = ACTION_QUERY;
|
||||
@ -333,8 +331,8 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
else if (streq(optarg, "all"))
|
||||
query = QUERY_ALL;
|
||||
else {
|
||||
fprintf(stderr, "unknown query type\n");
|
||||
return 3;
|
||||
log_error("unknown query type");
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 'r':
|
||||
@ -348,11 +346,9 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
action = ACTION_ATTRIBUTE_WALK;
|
||||
break;
|
||||
case 'e':
|
||||
if (export_devices(udev) < 0)
|
||||
return 1;
|
||||
return 0;
|
||||
return export_devices();
|
||||
case 'c':
|
||||
cleanup_db(udev);
|
||||
cleanup_db();
|
||||
return 0;
|
||||
case 'x':
|
||||
export = true;
|
||||
@ -361,13 +357,13 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
export_prefix = optarg;
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
return 0;
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
return help();
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
default:
|
||||
return 1;
|
||||
assert_not_reached("Unknown option");
|
||||
}
|
||||
|
||||
switch (action) {
|
||||
@ -375,12 +371,12 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
if (!device) {
|
||||
if (!argv[optind]) {
|
||||
help();
|
||||
return 2;
|
||||
return -EINVAL;
|
||||
}
|
||||
device = find_device(udev, argv[optind], NULL);
|
||||
device = find_device(argv[optind], NULL);
|
||||
if (!device) {
|
||||
fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n");
|
||||
return 4;
|
||||
log_error("Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -388,10 +384,8 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
case QUERY_NAME: {
|
||||
const char *node = udev_device_get_devnode(device);
|
||||
|
||||
if (node == NULL) {
|
||||
fprintf(stderr, "no device node found\n");
|
||||
return 5;
|
||||
}
|
||||
if (!node)
|
||||
return log_error_errno(errno, "no device node found");
|
||||
|
||||
if (root)
|
||||
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:
|
||||
list_entry = udev_device_get_devlinks_list_entry(device);
|
||||
while (list_entry != NULL) {
|
||||
while (list_entry) {
|
||||
if (root)
|
||||
printf("%s", udev_list_entry_get_name(list_entry));
|
||||
else
|
||||
printf("%s",
|
||||
udev_list_entry_get_name(list_entry) + STRLEN("/dev/"));
|
||||
list_entry = udev_list_entry_get_next(list_entry);
|
||||
if (list_entry != NULL)
|
||||
if (list_entry)
|
||||
printf(" ");
|
||||
}
|
||||
printf("\n");
|
||||
@ -419,7 +413,7 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
return 0;
|
||||
case QUERY_PROPERTY:
|
||||
list_entry = udev_device_get_properties_list_entry(device);
|
||||
while (list_entry != NULL) {
|
||||
while (list_entry) {
|
||||
if (export)
|
||||
printf("%s%s='%s'\n", strempty(export_prefix),
|
||||
udev_list_entry_get_name(list_entry),
|
||||
@ -439,29 +433,24 @@ static int uinfo(struct udev *udev, int argc, char *argv[]) {
|
||||
break;
|
||||
case ACTION_ATTRIBUTE_WALK:
|
||||
if (!device && argv[optind]) {
|
||||
device = find_device(udev, argv[optind], NULL);
|
||||
device = find_device(argv[optind], NULL);
|
||||
if (!device) {
|
||||
fprintf(stderr, "Unknown device, absolute path in /dev/ or /sys expected.\n");
|
||||
return 4;
|
||||
log_error("Unknown device, absolute path in /dev/ or /sys expected.");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
if (!device) {
|
||||
fprintf(stderr, "Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.\n");
|
||||
return 4;
|
||||
log_error("Unknown device, --name=, --path=, or absolute path in /dev/ or /sys expected.");
|
||||
return -EINVAL;
|
||||
}
|
||||
print_device_chain(device);
|
||||
break;
|
||||
case ACTION_DEVICE_ID_FILE:
|
||||
if (stat_device(name, export, export_prefix) != 0)
|
||||
return 1;
|
||||
r = stat_device(name, export, export_prefix);
|
||||
if (r < 0)
|
||||
return r;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_info = {
|
||||
.name = "info",
|
||||
.cmd = uinfo,
|
||||
.help = "Query sysfs or the udev database",
|
||||
};
|
||||
|
@ -10,40 +10,113 @@
|
||||
#include <sys/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 "format-util.h"
|
||||
#include "udev.h"
|
||||
#include "udevadm-util.h"
|
||||
#include "hashmap.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) {
|
||||
if (IN_SET(signum, SIGINT, SIGTERM))
|
||||
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;
|
||||
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);
|
||||
|
||||
printf("%-6s[%"PRI_TIME".%06"PRI_NSEC"] %-8s %s (%s)\n",
|
||||
source,
|
||||
ts.tv_sec, (nsec_t)ts.tv_nsec/1000,
|
||||
udev_device_get_action(device),
|
||||
udev_device_get_devpath(device),
|
||||
udev_device_get_subsystem(device));
|
||||
if (prop) {
|
||||
struct udev_list_entry *list_entry;
|
||||
action, devpath, subsystem);
|
||||
|
||||
if (arg_show_property) {
|
||||
const char *key, *value;
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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"
|
||||
"Listen to kernel and udev events.\n\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"
|
||||
" -t --tag-match=TAG Filter events by tag\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm_monitor(struct udev *udev, 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 int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "property", no_argument, NULL, '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);
|
||||
udev_list_init(udev, &tag_match_list, true);
|
||||
int r, c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "pekus:t:Vh", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
case 'p':
|
||||
case 'e':
|
||||
prop = true;
|
||||
arg_show_property = true;
|
||||
break;
|
||||
case 'k':
|
||||
print_kernel = true;
|
||||
arg_print_kernel = true;
|
||||
break;
|
||||
case 'u':
|
||||
print_udev = true;
|
||||
arg_print_udev = true;
|
||||
break;
|
||||
case 's':
|
||||
{
|
||||
char subsys[UTIL_NAME_SIZE];
|
||||
char *devtype;
|
||||
case 's': {
|
||||
_cleanup_free_ char *subsystem = NULL, *devtype = NULL;
|
||||
const char *slash;
|
||||
|
||||
strscpy(subsys, sizeof(subsys), optarg);
|
||||
devtype = strchr(subsys, '/');
|
||||
if (devtype != NULL) {
|
||||
devtype[0] = '\0';
|
||||
devtype++;
|
||||
}
|
||||
udev_list_entry_add(&subsystem_match_list, subsys, devtype);
|
||||
break;
|
||||
}
|
||||
case 't':
|
||||
udev_list_entry_add(&tag_match_list, optarg, NULL);
|
||||
slash = strchr(optarg, '/');
|
||||
if (slash) {
|
||||
devtype = strdup(devtype + 1);
|
||||
if (!devtype)
|
||||
return -ENOMEM;
|
||||
|
||||
subsystem = strndup(optarg, devtype - optarg);
|
||||
} else
|
||||
subsystem = strdup(optarg);
|
||||
|
||||
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;
|
||||
}
|
||||
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':
|
||||
print_version();
|
||||
return 0;
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
return help();
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
default:
|
||||
return 1;
|
||||
assert_not_reached("Unknown option.");
|
||||
}
|
||||
|
||||
if (!print_kernel && !print_udev) {
|
||||
print_kernel = true;
|
||||
print_udev = true;
|
||||
if (!arg_print_kernel && !arg_print_udev) {
|
||||
arg_print_kernel = 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 */
|
||||
act.sa_handler = sig_handler;
|
||||
act.sa_flags = SA_RESTART;
|
||||
act = (struct sigaction) {
|
||||
.sa_handler = sig_handler,
|
||||
.sa_flags = SA_RESTART,
|
||||
};
|
||||
assert_se(sigaction(SIGINT, &act, NULL) == 0);
|
||||
assert_se(sigaction(SIGTERM, &act, NULL) == 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);
|
||||
if (fd_ep < 0) {
|
||||
log_error_errno(errno, "error creating epoll fd: %m");
|
||||
return 1;
|
||||
r = log_error_errno(errno, "Failed to create epoll fd: %m");
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
printf("monitor will print the received events for:\n");
|
||||
if (print_udev) {
|
||||
struct udev_list_entry *entry;
|
||||
|
||||
udev_monitor = udev_monitor_new_from_netlink(udev, "udev");
|
||||
if (udev_monitor == NULL) {
|
||||
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;
|
||||
if (arg_print_udev) {
|
||||
fd_udev = setup_monitor("udev", fd_ep, &udev_monitor);
|
||||
if (fd_udev < 0) {
|
||||
r = fd_udev;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
printf("UDEV - the event which udev sends out after rule processing\n");
|
||||
}
|
||||
|
||||
if (print_kernel) {
|
||||
struct udev_list_entry *entry;
|
||||
|
||||
kernel_monitor = udev_monitor_new_from_netlink(udev, "kernel");
|
||||
if (kernel_monitor == NULL) {
|
||||
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;
|
||||
if (arg_print_kernel) {
|
||||
fd_kernel = setup_monitor("kernel", fd_ep, &kernel_monitor);
|
||||
if (fd_kernel < 0) {
|
||||
r = fd_kernel;
|
||||
goto finalize;
|
||||
}
|
||||
|
||||
printf("KERNEL - the kernel uevent\n");
|
||||
@ -228,43 +278,28 @@ static int adm_monitor(struct udev *udev, int argc, char *argv[]) {
|
||||
printf("\n");
|
||||
|
||||
while (!udev_exit) {
|
||||
int fdcount;
|
||||
struct epoll_event ev[4];
|
||||
int i;
|
||||
int fdcount, i;
|
||||
|
||||
fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
|
||||
if (fdcount < 0) {
|
||||
if (errno != EINTR)
|
||||
fprintf(stderr, "error receiving uevent message: %m\n");
|
||||
log_debug_errno(errno, "Failed to receive uevent message, ignoring: %m");
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < fdcount; i++) {
|
||||
if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN) {
|
||||
struct udev_device *device;
|
||||
|
||||
device = udev_monitor_receive_device(kernel_monitor);
|
||||
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);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < fdcount; i++)
|
||||
if (ev[i].data.fd == fd_kernel && ev[i].events & EPOLLIN)
|
||||
(void) receive_and_print_device(kernel_monitor, "KERNEL");
|
||||
else if (ev[i].data.fd == fd_udev && ev[i].events & EPOLLIN)
|
||||
(void) receive_and_print_device(udev_monitor, "UDEV");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
r = 0;
|
||||
|
||||
const struct udevadm_cmd udevadm_monitor = {
|
||||
.name = "monitor",
|
||||
.cmd = adm_monitor,
|
||||
.help = "Listen to kernel and udev events",
|
||||
};
|
||||
finalize:
|
||||
hashmap_free_free_free(arg_subsystem_filter);
|
||||
set_free_free(arg_tag_filter);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -13,22 +13,26 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "parse-util.h"
|
||||
#include "time-util.h"
|
||||
#include "udevadm.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"
|
||||
"Wait for pending udev events.\n\n"
|
||||
" -h --help Show this help\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"
|
||||
, 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[] = {
|
||||
{ "timeout", required_argument, NULL, 't' },
|
||||
{ "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 */
|
||||
{}
|
||||
};
|
||||
usec_t deadline;
|
||||
const char *exists = NULL;
|
||||
unsigned int timeout = 120;
|
||||
struct pollfd pfd[1] = { {.fd = -1}, };
|
||||
int c;
|
||||
struct udev_queue *queue;
|
||||
int rc = EXIT_FAILURE;
|
||||
|
||||
int c, r;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "t:E:Vhs:e:q", options, NULL)) >= 0) {
|
||||
switch (c) {
|
||||
|
||||
case 't': {
|
||||
int r;
|
||||
|
||||
r = safe_atou(optarg, &timeout);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Invalid timeout value '%s': %m", optarg);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
case 't':
|
||||
r = parse_sec(optarg, &arg_timeout);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to parse timeout value '%s': %m", optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'E':
|
||||
exists = optarg;
|
||||
arg_exists = optarg;
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
print_version();
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
return help();
|
||||
case 's':
|
||||
case 'e':
|
||||
case 'q':
|
||||
log_info("Option -%c no longer supported.", c);
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return -EINVAL;
|
||||
case '?':
|
||||
return EXIT_FAILURE;
|
||||
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown argument");
|
||||
assert_not_reached("Unknown option.");
|
||||
}
|
||||
}
|
||||
|
||||
if (optind < argc) {
|
||||
fprintf(stderr, "Extraneous argument: '%s'\n", argv[optind]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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 */
|
||||
if (getuid() == 0) {
|
||||
struct udev_ctrl *uctrl;
|
||||
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *uctrl = NULL;
|
||||
|
||||
uctrl = udev_ctrl_new(udev);
|
||||
if (uctrl != NULL) {
|
||||
if (udev_ctrl_send_ping(uctrl, MAX(5U, timeout)) < 0) {
|
||||
log_debug("no connection to daemon");
|
||||
udev_ctrl_unref(uctrl);
|
||||
return EXIT_SUCCESS;
|
||||
uctrl = udev_ctrl_new();
|
||||
if (uctrl) {
|
||||
r = udev_ctrl_send_ping(uctrl, MAX(5U, arg_timeout / USEC_PER_SEC));
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to connect to udev daemon.");
|
||||
return 0;
|
||||
}
|
||||
udev_ctrl_unref(uctrl);
|
||||
}
|
||||
}
|
||||
|
||||
queue = udev_queue_new(udev);
|
||||
if (!queue) {
|
||||
log_error("unable to get udev queue");
|
||||
return EXIT_FAILURE;
|
||||
queue = udev_queue_new(NULL);
|
||||
if (!queue)
|
||||
return log_error_errno(errno, "Failed to get udev queue: %m");
|
||||
|
||||
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[0].fd = udev_queue_get_fd(queue);
|
||||
if (pfd[0].fd < 0) {
|
||||
log_debug("queue is empty, nothing to watch");
|
||||
rc = EXIT_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
pfd = (struct pollfd) {
|
||||
.events = POLLIN,
|
||||
.fd = r,
|
||||
};
|
||||
|
||||
for (;;) {
|
||||
if (exists && access(exists, F_OK) >= 0) {
|
||||
rc = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (arg_exists && access(arg_exists, F_OK) >= 0)
|
||||
return 0;
|
||||
|
||||
/* exit if queue is empty */
|
||||
if (udev_queue_get_queue_is_empty(queue)) {
|
||||
rc = EXIT_SUCCESS;
|
||||
break;
|
||||
}
|
||||
if (udev_queue_get_queue_is_empty(queue))
|
||||
return 0;
|
||||
|
||||
if (now(CLOCK_MONOTONIC) >= deadline)
|
||||
break;
|
||||
return -ETIMEDOUT;
|
||||
|
||||
/* wake up when queue is empty */
|
||||
if (poll(pfd, 1, MSEC_PER_SEC) > 0 && pfd[0].revents & POLLIN)
|
||||
udev_queue_flush(queue);
|
||||
/* wake up when queue becomes empty */
|
||||
if (poll(&pfd, 1, MSEC_PER_SEC) > 0 && pfd.revents & POLLIN) {
|
||||
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",
|
||||
};
|
||||
|
@ -9,9 +9,12 @@
|
||||
#include "path-util.h"
|
||||
#include "string-util.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"
|
||||
"Test a built-in command.\n\n"
|
||||
" -h --help Print this message\n"
|
||||
@ -19,85 +22,85 @@ static void help(struct udev *udev) {
|
||||
"Commands:\n"
|
||||
, 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[] = {
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{}
|
||||
};
|
||||
char *command = NULL;
|
||||
char *syspath = NULL;
|
||||
char filename[UTIL_PATH_SIZE];
|
||||
struct udev_device *dev = NULL;
|
||||
enum udev_builtin_cmd cmd;
|
||||
int rc = EXIT_SUCCESS, c;
|
||||
|
||||
const char *s;
|
||||
int c;
|
||||
|
||||
while ((c = getopt_long(argc, argv, "Vh", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
case 'V':
|
||||
print_version();
|
||||
goto out;
|
||||
return version();
|
||||
case 'h':
|
||||
help(udev);
|
||||
goto out;
|
||||
return help();
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown option");
|
||||
}
|
||||
|
||||
command = argv[optind++];
|
||||
if (command == NULL) {
|
||||
fprintf(stderr, "command missing\n");
|
||||
help(udev);
|
||||
rc = 2;
|
||||
goto out;
|
||||
arg_command = argv[optind++];
|
||||
if (!arg_command) {
|
||||
log_error("Command missing.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
syspath = argv[optind++];
|
||||
if (syspath == NULL) {
|
||||
fprintf(stderr, "syspath missing\n");
|
||||
rc = 3;
|
||||
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;
|
||||
s = argv[optind++];
|
||||
if (!s) {
|
||||
log_error("syspath missing.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* add /sys if needed */
|
||||
if (!path_startswith(syspath, "/sys"))
|
||||
strscpyl(filename, sizeof(filename), "/sys", syspath, NULL);
|
||||
if (!path_startswith(s, "/sys"))
|
||||
strscpyl(arg_syspath, sizeof(arg_syspath), "/sys", s, NULL);
|
||||
else
|
||||
strscpy(filename, sizeof(filename), syspath);
|
||||
delete_trailing_chars(filename, "/");
|
||||
strscpy(arg_syspath, sizeof(arg_syspath), s);
|
||||
|
||||
dev = udev_device_new_from_syspath(udev, filename);
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_test_builtin = {
|
||||
.name = "test-builtin",
|
||||
.cmd = adm_builtin,
|
||||
.help = "Test a built-in command",
|
||||
.debug = true,
|
||||
};
|
||||
int builtin_main(int argc, char *argv[], void *userdata) {
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *dev = NULL;
|
||||
enum udev_builtin_cmd cmd;
|
||||
int r;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -14,9 +14,13 @@
|
||||
|
||||
#include "string-util.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"
|
||||
"Test an event run.\n\n"
|
||||
@ -25,20 +29,11 @@ static void help(void) {
|
||||
" -a --action=ACTION Set action string\n"
|
||||
" -N --resolve-names=early|late|never When to resolve names\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int adm_test(struct udev *udev, 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 int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "action", required_argument, NULL, 'a' },
|
||||
{ "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)
|
||||
switch (c) {
|
||||
case 'a':
|
||||
action = optarg;
|
||||
arg_action = optarg;
|
||||
break;
|
||||
case 'N':
|
||||
if (streq (optarg, "early")) {
|
||||
resolve_names = 1;
|
||||
arg_resolve_names = 1;
|
||||
} else if (streq (optarg, "late")) {
|
||||
resolve_names = 0;
|
||||
arg_resolve_names = 0;
|
||||
} else if (streq (optarg, "never")) {
|
||||
resolve_names = -1;
|
||||
arg_resolve_names = -1;
|
||||
} else {
|
||||
fprintf(stderr, "resolve-names must be early, late or never\n");
|
||||
log_error("resolve-names must be early, late or never");
|
||||
exit(EXIT_FAILURE);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 'V':
|
||||
print_version();
|
||||
exit(EXIT_SUCCESS);
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
exit(EXIT_SUCCESS);
|
||||
return help();
|
||||
case '?':
|
||||
exit(EXIT_FAILURE);
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown option");
|
||||
}
|
||||
|
||||
syspath = argv[optind];
|
||||
if (syspath == NULL) {
|
||||
fprintf(stderr, "syspath parameter missing\n");
|
||||
rc = 2;
|
||||
goto out;
|
||||
if (!argv[optind]) {
|
||||
log_error("syspath parameter missing.");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* 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"
|
||||
"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"
|
||||
@ -93,26 +106,18 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) {
|
||||
|
||||
sigprocmask(SIG_SETMASK, NULL, &sigmask_orig);
|
||||
|
||||
udev_builtin_init(udev);
|
||||
udev_builtin_init();
|
||||
|
||||
rules = udev_rules_new(udev, resolve_names);
|
||||
if (rules == NULL) {
|
||||
fprintf(stderr, "error reading rules\n");
|
||||
rc = 3;
|
||||
rules = udev_rules_new(arg_resolve_names);
|
||||
if (!rules) {
|
||||
log_error("Failed to read udev rules.");
|
||||
r = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* add /sys if needed */
|
||||
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);
|
||||
dev = udev_device_new_from_synthetic_event(NULL, arg_syspath, arg_action);
|
||||
if (dev == NULL) {
|
||||
fprintf(stderr, "unable to open device '%s'\n", filename);
|
||||
rc = 4;
|
||||
r = log_error_errno(errno, "Failed to open device '%s': %m", arg_syspath);
|
||||
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);
|
||||
printf("run: '%s'\n", program);
|
||||
}
|
||||
out:
|
||||
udev_builtin_exit(udev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_test = {
|
||||
.name = "test",
|
||||
.cmd = adm_test,
|
||||
.help = "Test an event run",
|
||||
.debug = true,
|
||||
};
|
||||
r = 0;
|
||||
out:
|
||||
udev_builtin_exit();
|
||||
return r;
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "set.h"
|
||||
#include "string-util.h"
|
||||
#include "udev.h"
|
||||
#include "udevadm.h"
|
||||
#include "udevadm-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;
|
||||
}
|
||||
|
||||
static void help(void) {
|
||||
static int help(void) {
|
||||
printf("%s trigger [OPTIONS] DEVPATH\n\n"
|
||||
"Request events from the kernel.\n\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"
|
||||
" -w --settle Wait for the triggered events to complete\n"
|
||||
, 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 {
|
||||
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;
|
||||
int c, r;
|
||||
|
||||
udev_enumerate = udev_enumerate_new(udev);
|
||||
udev_enumerate = udev_enumerate_new(NULL);
|
||||
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) {
|
||||
const char *key;
|
||||
@ -149,83 +152,66 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
|
||||
device_type = TYPE_SUBSYSTEMS;
|
||||
else {
|
||||
log_error("unknown type --type=%s", optarg);
|
||||
return 2;
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
if (!STR_IN_SET(optarg, "add", "remove", "change")) {
|
||||
log_error("unknown action '%s'", optarg);
|
||||
return 2;
|
||||
} else
|
||||
if (STR_IN_SET(optarg, "add", "remove", "change"))
|
||||
action = optarg;
|
||||
else {
|
||||
log_error("unknown action '%s'", optarg);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
break;
|
||||
case 's':
|
||||
r = udev_enumerate_add_match_subsystem(udev_enumerate, optarg);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add subsystem match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add subsystem match '%s': %m", optarg);
|
||||
break;
|
||||
case 'S':
|
||||
r = udev_enumerate_add_nomatch_subsystem(udev_enumerate, optarg);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add negative subsystem match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add negative subsystem match '%s': %m", optarg);
|
||||
break;
|
||||
case 'a':
|
||||
key = keyval(optarg, &val, buf, sizeof(buf));
|
||||
r = udev_enumerate_add_match_sysattr(udev_enumerate, key, val);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add sysattr match '%s=%s': %m", key, val);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add sysattr match '%s=%s': %m", key, val);
|
||||
break;
|
||||
case 'A':
|
||||
key = keyval(optarg, &val, buf, sizeof(buf));
|
||||
r = udev_enumerate_add_nomatch_sysattr(udev_enumerate, key, val);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add negative sysattr match '%s=%s': %m", key, val);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add negative sysattr match '%s=%s': %m", key, val);
|
||||
break;
|
||||
case 'p':
|
||||
key = keyval(optarg, &val, buf, sizeof(buf));
|
||||
r = udev_enumerate_add_match_property(udev_enumerate, key, val);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add property match '%s=%s': %m", key, val);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add property match '%s=%s': %m", key, val);
|
||||
break;
|
||||
case 'g':
|
||||
r = udev_enumerate_add_match_tag(udev_enumerate, optarg);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add tag match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add tag match '%s': %m", optarg);
|
||||
break;
|
||||
case 'y':
|
||||
r = udev_enumerate_add_match_sysname(udev_enumerate, optarg);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add sysname match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add sysname match '%s': %m", optarg);
|
||||
break;
|
||||
case 'b': {
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *dev;
|
||||
|
||||
dev = find_device(udev, optarg, "/sys");
|
||||
if (!dev) {
|
||||
log_error("unable to open the device '%s'", optarg);
|
||||
return 2;
|
||||
}
|
||||
dev = find_device(optarg, "/sys");
|
||||
if (!dev)
|
||||
return log_error_errno(errno, "unable to open the device '%s'", optarg);
|
||||
|
||||
r = udev_enumerate_add_match_parent(udev_enumerate, dev);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add parent match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add parent match '%s': %m", optarg);
|
||||
break;
|
||||
}
|
||||
case 'w':
|
||||
@ -235,28 +221,22 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
|
||||
case ARG_NAME: {
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *dev;
|
||||
|
||||
dev = find_device(udev, optarg, "/dev/");
|
||||
if (!dev) {
|
||||
log_error("unable to open the device '%s'", optarg);
|
||||
return 2;
|
||||
}
|
||||
dev = find_device(optarg, "/dev/");
|
||||
if (!dev)
|
||||
return log_error_errno(errno, "unable to open the device '%s'", optarg);
|
||||
|
||||
r = udev_enumerate_add_match_parent(udev_enumerate, dev);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add parent match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add parent match '%s': %m", optarg);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'V':
|
||||
print_version();
|
||||
return 0;
|
||||
return version();
|
||||
case 'h':
|
||||
help();
|
||||
return 0;
|
||||
return help();
|
||||
case '?':
|
||||
return 1;
|
||||
return -EINVAL;
|
||||
default:
|
||||
assert_not_reached("Unknown option");
|
||||
}
|
||||
@ -265,49 +245,39 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
|
||||
for (; optind < argc; optind++) {
|
||||
_cleanup_(udev_device_unrefp) struct udev_device *dev;
|
||||
|
||||
dev = find_device(udev, argv[optind], NULL);
|
||||
dev = find_device(argv[optind], NULL);
|
||||
if (!dev) {
|
||||
log_error("unable to open the device '%s'", argv[optind]);
|
||||
return 2;
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = udev_enumerate_add_match_parent(udev_enumerate, dev);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "could not add tag match '%s': %m", optarg);
|
||||
return 2;
|
||||
}
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "could not add tag match '%s': %m", optarg);
|
||||
}
|
||||
|
||||
if (settle) {
|
||||
fd_ep = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (fd_ep < 0) {
|
||||
log_error_errno(errno, "error creating epoll fd: %m");
|
||||
return 1;
|
||||
}
|
||||
if (fd_ep < 0)
|
||||
return log_error_errno(errno, "error creating epoll fd: %m");
|
||||
|
||||
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);
|
||||
|
||||
if (udev_monitor_enable_receiving(udev_monitor) < 0) {
|
||||
log_error("error: unable to subscribe to udev events");
|
||||
return 4;
|
||||
}
|
||||
r = udev_monitor_enable_receiving(udev_monitor);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "error: unable to subscribe to udev events: %m");
|
||||
|
||||
ep_udev = (struct epoll_event) { .events = EPOLLIN, .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 5;
|
||||
}
|
||||
if (epoll_ctl(fd_ep, EPOLL_CTL_ADD, fd_udev, &ep_udev) < 0)
|
||||
return log_error_errno(errno, "fail to add fd to epoll: %m");
|
||||
|
||||
settle_set = set_new(&string_hash_ops);
|
||||
if (!settle_set) {
|
||||
log_oom();
|
||||
return 1;
|
||||
}
|
||||
if (!settle_set)
|
||||
return log_oom();
|
||||
}
|
||||
|
||||
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);
|
||||
if (r < 0)
|
||||
return 1;
|
||||
return r;
|
||||
|
||||
while (!set_isempty(settle_set)) {
|
||||
int fdcount;
|
||||
@ -356,9 +326,3 @@ static int adm_trigger(struct udev *udev, int argc, char *argv[]) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct udevadm_cmd udevadm_trigger = {
|
||||
.name = "trigger",
|
||||
.cmd = adm_trigger,
|
||||
.help = "Request events from the kernel",
|
||||
};
|
||||
|
@ -4,8 +4,7 @@
|
||||
#include "string-util.h"
|
||||
#include "udevadm-util.h"
|
||||
|
||||
struct udev_device *find_device(struct udev *udev,
|
||||
const char *id,
|
||||
struct udev_device *find_device(const char *id,
|
||||
const char *prefix) {
|
||||
|
||||
assert(id);
|
||||
@ -27,9 +26,9 @@ struct udev_device *find_device(struct udev *udev,
|
||||
else
|
||||
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/"))
|
||||
return udev_device_new_from_syspath(udev, id);
|
||||
return udev_device_new_from_syspath(NULL, id);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
@ -3,10 +3,5 @@
|
||||
|
||||
#include "udev.h"
|
||||
|
||||
struct udev_device *find_device(struct udev *udev,
|
||||
const char *id,
|
||||
struct udev_device *find_device(const char *id,
|
||||
const char *prefix);
|
||||
|
||||
static inline void print_version(void) {
|
||||
printf("%s\n", PACKAGE_VERSION);
|
||||
}
|
||||
|
@ -5,43 +5,26 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "selinux-util.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "udevadm.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[]) {
|
||||
printf("%s\n", PACKAGE_VERSION);
|
||||
return 0;
|
||||
}
|
||||
static int help(void) {
|
||||
static const char * short_descriptions[][2] = {
|
||||
{ "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;
|
||||
size_t i;
|
||||
int r;
|
||||
@ -55,42 +38,24 @@ static int adm_help(struct udev *udev, int argc, char *argv[]) {
|
||||
"Commands:\n"
|
||||
, program_invocation_short_name);
|
||||
|
||||
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++)
|
||||
if (udevadm_cmds[i]->help != NULL)
|
||||
printf(" %-12s %s\n", udevadm_cmds[i]->name, udevadm_cmds[i]->help);
|
||||
for (i = 0; i < ELEMENTSOF(short_descriptions); i++)
|
||||
printf(" %-12s %s\n", short_descriptions[i][0], short_descriptions[i][1]);
|
||||
|
||||
printf("\nSee the %s for details.\n", link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int run_command(struct udev *udev, const struct udevadm_cmd *cmd, 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 int parse_argv(int argc, char *argv[]) {
|
||||
static const struct option options[] = {
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "debug", no_argument, NULL, 'd' },
|
||||
{ "help", no_argument, NULL, 'h' },
|
||||
{ "version", no_argument, NULL, 'V' },
|
||||
{}
|
||||
};
|
||||
const char *command;
|
||||
unsigned int i;
|
||||
int rc = 1, c;
|
||||
int c;
|
||||
|
||||
udev_parse_config();
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
mac_selinux_init();
|
||||
|
||||
udev = udev_new();
|
||||
if (udev == NULL)
|
||||
goto out;
|
||||
assert(argc >= 0);
|
||||
assert(argv);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "+dhV", options, NULL)) >= 0)
|
||||
switch (c) {
|
||||
@ -100,35 +65,66 @@ int main(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
rc = adm_help(udev, argc, argv);
|
||||
goto out;
|
||||
return help();
|
||||
|
||||
case 'V':
|
||||
rc = adm_version(udev, argc, argv);
|
||||
goto out;
|
||||
return version();
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
default:
|
||||
goto out;
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
command = argv[optind];
|
||||
|
||||
if (command != NULL)
|
||||
for (i = 0; i < ELEMENTSOF(udevadm_cmds); i++)
|
||||
if (streq(udevadm_cmds[i]->name, command)) {
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
/* we need '0' here to reset the internal state */
|
||||
optind = 0;
|
||||
rc = run_command(udev, udevadm_cmds[i], argc, argv);
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(stderr, "%s: missing or unknown command\n", program_invocation_short_name);
|
||||
rc = 2;
|
||||
out:
|
||||
mac_selinux_finish();
|
||||
udev_unref(udev);
|
||||
log_close();
|
||||
return rc;
|
||||
return 1; /* work to do */
|
||||
}
|
||||
|
||||
static int version_main(int argc, char *argv[], void *userdata) {
|
||||
return version();
|
||||
}
|
||||
|
||||
static int help_main(int argc, char *argv[], void *userdata) {
|
||||
return help();
|
||||
}
|
||||
|
||||
static int udevadm_main(int argc, char *argv[]) {
|
||||
static const Verb verbs[] = {
|
||||
{ "info", VERB_ANY, VERB_ANY, 0, info_main },
|
||||
{ "trigger", VERB_ANY, VERB_ANY, 0, trigger_main },
|
||||
{ "settle", VERB_ANY, VERB_ANY, 0, settle_main },
|
||||
{ "control", VERB_ANY, VERB_ANY, 0, control_main },
|
||||
{ "monitor", VERB_ANY, VERB_ANY, 0, monitor_main },
|
||||
{ "hwdb", VERB_ANY, VERB_ANY, 0, hwdb_main },
|
||||
{ "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
11
src/udev/udevadm.h
Normal 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);
|
@ -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;
|
||||
|
||||
typedef struct Manager {
|
||||
struct udev *udev;
|
||||
sd_event *event;
|
||||
Hashmap *workers;
|
||||
LIST_HEAD(struct event, events);
|
||||
@ -98,7 +97,6 @@ enum event_state {
|
||||
struct event {
|
||||
LIST_FIELDS(struct event, event);
|
||||
Manager *manager;
|
||||
struct udev *udev;
|
||||
struct udev_device *dev;
|
||||
struct udev_device *dev_kernel;
|
||||
struct worker *worker;
|
||||
@ -126,7 +124,6 @@ enum worker_state {
|
||||
|
||||
struct worker {
|
||||
Manager *manager;
|
||||
int refcount;
|
||||
pid_t pid;
|
||||
struct udev_monitor *monitor;
|
||||
enum worker_state state;
|
||||
@ -204,7 +201,6 @@ static int worker_new(struct worker **ret, Manager *manager, struct udev_monitor
|
||||
if (!worker)
|
||||
return -ENOMEM;
|
||||
|
||||
worker->refcount = 1;
|
||||
worker->manager = manager;
|
||||
/* close monitor, but keep address around */
|
||||
udev_monitor_disconnect(worker_monitor);
|
||||
@ -278,13 +274,12 @@ static void manager_free(Manager *manager) {
|
||||
if (!manager)
|
||||
return;
|
||||
|
||||
udev_builtin_exit(manager->udev);
|
||||
udev_builtin_exit();
|
||||
|
||||
sd_event_source_unref(manager->ctrl_event);
|
||||
sd_event_source_unref(manager->uevent_event);
|
||||
sd_event_source_unref(manager->inotify_event);
|
||||
|
||||
udev_unref(manager->udev);
|
||||
sd_event_unref(manager->event);
|
||||
manager_workers_free(manager);
|
||||
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) {
|
||||
struct udev *udev = event->udev;
|
||||
_cleanup_(udev_monitor_unrefp) struct udev_monitor *worker_monitor = NULL;
|
||||
pid_t pid;
|
||||
int r = 0;
|
||||
|
||||
/* 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)
|
||||
return;
|
||||
/* 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 */
|
||||
if (udev_event->inotify_watch) {
|
||||
udev_watch_begin(udev, dev);
|
||||
udev_watch_begin(dev);
|
||||
udev_device_update_db(dev);
|
||||
}
|
||||
|
||||
@ -591,7 +585,6 @@ static int event_queue_insert(Manager *manager, struct udev_device *dev) {
|
||||
if (!event)
|
||||
return -ENOMEM;
|
||||
|
||||
event->udev = udev_device_get_udev(dev);
|
||||
event->manager = manager;
|
||||
event->dev = dev;
|
||||
event->dev_kernel = udev_device_shallow_clone(dev);
|
||||
@ -762,7 +755,7 @@ static void manager_reload(Manager *manager) {
|
||||
|
||||
manager_kill_workers(manager);
|
||||
manager->rules = udev_rules_unref(manager->rules);
|
||||
udev_builtin_exit(manager->udev);
|
||||
udev_builtin_exit();
|
||||
|
||||
sd_notifyf(false,
|
||||
"READY=1\n"
|
||||
@ -784,16 +777,16 @@ static void event_queue_start(Manager *manager) {
|
||||
if (manager->last_usec == 0 ||
|
||||
(usec - manager->last_usec) > 3 * USEC_PER_SEC) {
|
||||
if (udev_rules_check_timestamp(manager->rules) ||
|
||||
udev_builtin_validate(manager->udev))
|
||||
udev_builtin_validate())
|
||||
manager_reload(manager);
|
||||
|
||||
manager->last_usec = usec;
|
||||
}
|
||||
|
||||
udev_builtin_init(manager->udev);
|
||||
udev_builtin_init();
|
||||
|
||||
if (!manager->rules) {
|
||||
manager->rules = udev_rules_new(manager->udev, arg_resolve_names);
|
||||
manager->rules = udev_rules_new(arg_resolve_names);
|
||||
if (!manager->rules)
|
||||
return;
|
||||
}
|
||||
@ -1014,7 +1007,6 @@ static int synthesize_change(struct udev_device *dev) {
|
||||
bool part_table_read = false;
|
||||
bool has_partitions = false;
|
||||
int fd;
|
||||
struct udev *udev = udev_device_get_udev(dev);
|
||||
_cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL;
|
||||
struct udev_list_entry *item;
|
||||
|
||||
@ -1036,7 +1028,7 @@ static int synthesize_change(struct udev_device *dev) {
|
||||
}
|
||||
|
||||
/* search for partitions */
|
||||
e = udev_enumerate_new(udev);
|
||||
e = udev_enumerate_new(NULL);
|
||||
if (!e)
|
||||
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)) {
|
||||
_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)
|
||||
continue;
|
||||
|
||||
@ -1085,7 +1077,7 @@ static int synthesize_change(struct udev_device *dev) {
|
||||
udev_list_entry_foreach(item, udev_enumerate_get_list_entry(e)) {
|
||||
_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)
|
||||
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) {
|
||||
_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)
|
||||
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);
|
||||
} else if (e->mask & IN_IGNORED)
|
||||
udev_watch_end(manager->udev, dev);
|
||||
udev_watch_end(dev);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -1252,7 +1244,6 @@ static int on_post(sd_event_source *s, void *userdata) {
|
||||
}
|
||||
|
||||
static int listen_fds(int *rctrl, int *rnetlink) {
|
||||
_cleanup_(udev_unrefp) struct udev *udev = NULL;
|
||||
int ctrl_fd = -1, netlink_fd = -1;
|
||||
int fd, n, r;
|
||||
|
||||
@ -1284,11 +1275,7 @@ static int listen_fds(int *rctrl, int *rnetlink) {
|
||||
if (ctrl_fd < 0) {
|
||||
_cleanup_(udev_ctrl_unrefp) struct udev_ctrl *ctrl = NULL;
|
||||
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return -ENOMEM;
|
||||
|
||||
ctrl = udev_ctrl_new(udev);
|
||||
ctrl = udev_ctrl_new();
|
||||
if (!ctrl)
|
||||
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) {
|
||||
_cleanup_(udev_monitor_unrefp) struct udev_monitor *monitor = NULL;
|
||||
|
||||
if (!udev) {
|
||||
udev = udev_new();
|
||||
if (!udev)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
monitor = udev_monitor_new_from_netlink(udev, "kernel");
|
||||
monitor = udev_monitor_new_from_netlink(NULL, "kernel");
|
||||
if (!monitor)
|
||||
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[READ_END] = -1;
|
||||
|
||||
manager->udev = udev_new();
|
||||
if (!manager->udev)
|
||||
return log_error_errno(errno, "could not allocate udev context: %m");
|
||||
udev_builtin_init();
|
||||
|
||||
udev_builtin_init(manager->udev);
|
||||
|
||||
manager->rules = udev_rules_new(manager->udev, arg_resolve_names);
|
||||
manager->rules = udev_rules_new(arg_resolve_names);
|
||||
if (!manager->rules)
|
||||
return log_error_errno(ENOMEM, "error reading rules");
|
||||
|
||||
LIST_HEAD_INIT(manager->events);
|
||||
udev_list_init(manager->udev, &manager->properties, true);
|
||||
udev_list_init(NULL, &manager->properties, true);
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return log_error_errno(ENOMEM, "error initializing inotify");
|
||||
|
||||
udev_watch_restore(manager->udev);
|
||||
udev_watch_restore();
|
||||
|
||||
/* block and listen to all signals on signalfd */
|
||||
assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, SIGHUP, SIGCHLD, -1) >= 0);
|
||||
|
Loading…
Reference in New Issue
Block a user