diff options
-rw-r--r-- | man/udevadm.xml | 1 | ||||
-rw-r--r-- | src/udev/ata_id/ata_id.c | 345 | ||||
-rw-r--r-- | src/udev/cdrom_id/cdrom_id.c | 20 | ||||
-rw-r--r-- | src/udev/dmi_memory_id/dmi_memory_id.c | 11 | ||||
-rw-r--r-- | src/udev/fido_id/fido_id.c | 52 | ||||
-rw-r--r-- | src/udev/meson.build | 1 | ||||
-rw-r--r-- | src/udev/mtd_probe/mtd_probe.c | 65 | ||||
-rw-r--r-- | src/udev/v4l_id/v4l_id.c | 49 |
8 files changed, 310 insertions, 234 deletions
diff --git a/man/udevadm.xml b/man/udevadm.xml index ce40ded8f3..734e38cd05 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -739,6 +739,7 @@ </varlistentry> <xi:include href="standard-options.xml" xpointer="help" /> + <xi:include href="standard-options.xml" xpointer="version" /> </variablelist> </refsect2> diff --git a/src/udev/ata_id/ata_id.c b/src/udev/ata_id/ata_id.c index 6a631e515c..0b1f0b7157 100644 --- a/src/udev/ata_id/ata_id.c +++ b/src/udev/ata_id/ata_id.c @@ -23,14 +23,20 @@ #include <sys/types.h> #include <unistd.h> +#include "build.h" #include "device-nodes.h" #include "fd-util.h" #include "log.h" +#include "main-func.h" #include "memory-util.h" #include "udev-util.h" +#include "unaligned.h" #define COMMAND_TIMEOUT_MSEC (30 * 1000) +static bool arg_export = false; +static const char *arg_device = NULL; + static int disk_scsi_inquiry_command( int fd, void *buf, @@ -55,45 +61,39 @@ static int disk_scsi_inquiry_command( .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; - int ret; - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { + if (ioctl(fd, SG_IO, &io_v4) != 0) { + if (errno != EINVAL) + return log_debug_errno(errno, "ioctl v4 failed: %m"); + /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr = { - .interface_id = 'S', - .cmdp = (unsigned char*) cdb, - .cmd_len = sizeof (cdb), - .dxferp = buf, - .dxfer_len = buf_len, - .sbp = sense, - .mx_sb_len = sizeof(sense), - .dxfer_direction = SG_DXFER_FROM_DEV, - .timeout = COMMAND_TIMEOUT_MSEC, - }; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - return ret; - - /* even if the ioctl succeeds, we need to check the return value */ - if (!(io_hdr.status == 0 && - io_hdr.host_status == 0 && - io_hdr.driver_status == 0)) { - errno = EIO; - return -1; - } - } else - return ret; - } + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof(sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + if (ioctl(fd, SG_IO, &io_hdr) != 0) + return log_debug_errno(errno, "ioctl v3 failed: %m"); + + /* even if the ioctl succeeds, we need to check the return value */ + if (io_hdr.status != 0 || + io_hdr.host_status != 0 || + io_hdr.driver_status != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v3 failed"); - /* even if the ioctl succeeds, we need to check the return value */ - if (!(io_v4.device_status == 0 && - io_v4.transport_status == 0 && - io_v4.driver_status == 0)) { - errno = EIO; - return -1; + } else { + /* even if the ioctl succeeds, we need to check the return value */ + if (io_v4.device_status != 0 || + io_v4.transport_status != 0 || + io_v4.driver_status != 0) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed"); } return 0; @@ -137,35 +137,30 @@ static int disk_identify_command( .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; - int ret; - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { - /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr = { - .interface_id = 'S', - .cmdp = (unsigned char*) cdb, - .cmd_len = sizeof (cdb), - .dxferp = buf, - .dxfer_len = buf_len, - .sbp = sense, - .mx_sb_len = sizeof (sense), - .dxfer_direction = SG_DXFER_FROM_DEV, - .timeout = COMMAND_TIMEOUT_MSEC, - }; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - return ret; - } else - return ret; - } + if (ioctl(fd, SG_IO, &io_v4) != 0) { + if (errno != EINVAL) + return log_debug_errno(errno, "ioctl v4 failed: %m"); - if (!((sense[0] & 0x7f) == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c) && - !((sense[0] & 0x7f) == 0x70 && sense[12] == 0x00 && sense[13] == 0x1d)) { - errno = EIO; - return -1; + /* could be that the driver doesn't do version 4, try version 3 */ + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof (sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + if (ioctl(fd, SG_IO, &io_hdr) != 0) + return log_debug_errno(errno, "ioctl v3 failed: %m"); + } else { + if (!((sense[0] & 0x7f) == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c) && + !((sense[0] & 0x7f) == 0x70 && sense[12] == 0x00 && sense[13] == 0x1d)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed: %m"); } return 0; @@ -215,34 +210,29 @@ static int disk_identify_packet_device_command( .din_xferp = (uintptr_t) buf, .timeout = COMMAND_TIMEOUT_MSEC, }; - int ret; - ret = ioctl(fd, SG_IO, &io_v4); - if (ret != 0) { - /* could be that the driver doesn't do version 4, try version 3 */ - if (errno == EINVAL) { - struct sg_io_hdr io_hdr = { - .interface_id = 'S', - .cmdp = (unsigned char*) cdb, - .cmd_len = sizeof (cdb), - .dxferp = buf, - .dxfer_len = buf_len, - .sbp = sense, - .mx_sb_len = sizeof (sense), - .dxfer_direction = SG_DXFER_FROM_DEV, - .timeout = COMMAND_TIMEOUT_MSEC, - }; - - ret = ioctl(fd, SG_IO, &io_hdr); - if (ret != 0) - return ret; - } else - return ret; - } + if (ioctl(fd, SG_IO, &io_v4) != 0) { + if (errno != EINVAL) + return log_debug_errno(errno, "ioctl v4 failed: %m"); - if (!((sense[0] & 0x7f) == 0x72 && desc[0] == 0x9 && desc[1] == 0x0c)) { - errno = EIO; - return -1; + /* could be that the driver doesn't do version 4, try version 3 */ + struct sg_io_hdr io_hdr = { + .interface_id = 'S', + .cmdp = (unsigned char*) cdb, + .cmd_len = sizeof (cdb), + .dxferp = buf, + .dxfer_len = buf_len, + .sbp = sense, + .mx_sb_len = sizeof (sense), + .dxfer_direction = SG_DXFER_FROM_DEV, + .timeout = COMMAND_TIMEOUT_MSEC, + }; + + if (ioctl(fd, SG_IO, &io_hdr) != 0) + return log_debug_errno(errno, "ioctl v3 failed: %m"); + } else { + if ((sense[0] & 0x7f) != 0x72 || desc[0] != 0x9 || desc[1] != 0x0c) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "ioctl v4 failed: %m"); } return 0; @@ -282,26 +272,25 @@ static void disk_identify_fixup_string( uint8_t identify[512], unsigned offset_words, size_t len) { + assert(offset_words < 512/2); disk_identify_get_string(identify, offset_words, (char *) identify + offset_words * 2, len); } -static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned offset_words) { - uint16_t *p; - - p = (uint16_t *) identify; - p[offset_words] = le16toh (p[offset_words]); +static void disk_identify_fixup_uint16(uint8_t identify[512], unsigned offset_words) { + assert(offset_words < 512/2); + unaligned_write_ne16(identify + offset_words * 2, + unaligned_read_le16(identify + offset_words * 2)); } /** * disk_identify: * @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 an IDENTIFY PACKET DEVICE. * * Sends the IDENTIFY DEVICE or IDENTIFY PACKET DEVICE command to the * device represented by @fd. If successful, then the result will be - * copied into @out_identify and @out_is_packet_device. + * copied into @out_identify. * * This routine is based on code from libatasmart, LGPL v2.1. * @@ -309,14 +298,9 @@ static void disk_identify_fixup_uint16 (uint8_t identify[512], unsigned offset_w * non-zero with errno set. */ static int disk_identify(int fd, - uint8_t out_identify[512], - int *out_is_packet_device) { - int ret; + uint8_t out_identify[512]) { uint8_t inquiry_buf[36]; - int peripheral_device_type; - int all_nul_bytes; - int n; - int is_packet_device = 0; + int peripheral_device_type, r; /* init results */ memzero(out_identify, 512); @@ -342,110 +326,103 @@ static int disk_identify(int fd, * the original bug-fix and see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=556635 * for the original bug-report.) */ - ret = disk_scsi_inquiry_command (fd, inquiry_buf, sizeof (inquiry_buf)); - if (ret != 0) - goto out; + r = disk_scsi_inquiry_command(fd, inquiry_buf, sizeof inquiry_buf); + if (r < 0) + return r; /* SPC-4, section 6.4.2: Standard INQUIRY data */ peripheral_device_type = inquiry_buf[0] & 0x1f; - if (peripheral_device_type == 0x05) - { - is_packet_device = 1; - ret = disk_identify_packet_device_command(fd, out_identify, 512); - goto check_nul_bytes; - } - if (!IN_SET(peripheral_device_type, 0x00, 0x14)) { - ret = -1; - errno = EIO; - goto out; - } + if (peripheral_device_type == 0x05) { + r = disk_identify_packet_device_command(fd, out_identify, 512); + if (r < 0) + return r; - /* OK, now issue the IDENTIFY DEVICE command */ - ret = disk_identify_command(fd, out_identify, 512); - if (ret != 0) - goto out; + } else { + if (!IN_SET(peripheral_device_type, 0x00, 0x14)) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "Unsupported device type."); + + /* OK, now issue the IDENTIFY DEVICE command */ + r = disk_identify_command(fd, out_identify, 512); + if (r < 0) + return r; + } - check_nul_bytes: /* Check if IDENTIFY data is all NUL bytes - if so, bail */ - all_nul_bytes = 1; - for (n = 0; n < 512; n++) { + bool all_nul_bytes = true; + for (size_t n = 0; n < 512; n++) if (out_identify[n] != '\0') { - all_nul_bytes = 0; + all_nul_bytes = false; break; } - } - if (all_nul_bytes) { - ret = -1; - errno = EIO; - goto out; - } + if (all_nul_bytes) + return log_debug_errno(SYNTHETIC_ERRNO(EIO), "IDENTIFY data is all zeroes."); + + return 0; +} + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "export", no_argument, NULL, 'x' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + {} + }; + int c; + + while ((c = getopt_long(argc, argv, "xh", options, NULL)) >= 0) + switch (c) { + case 'x': + arg_export = true; + break; + case 'h': + printf("%s [OPTIONS...] DEVICE\n\n" + " -x --export Print values as environment keys\n" + " -h --help Show this help text\n" + " --version Show package version\n", + program_invocation_short_name); + return 0; + case 'v': + return version(); + case '?': + return -EINVAL; + default: + assert_not_reached(); + } -out: - if (out_is_packet_device) - *out_is_packet_device = is_packet_device; - return ret; + if (!argv[optind]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "DEVICE argument missing."); + + arg_device = argv[optind]; + return 1; } -int main(int argc, char *argv[]) { +static int run(int argc, char *argv[]) { struct hd_driveid id; union { uint8_t byte[512]; uint16_t wyde[256]; } identify; - char model[41]; - char model_enc[256]; - char serial[21]; - char revision[9]; - const char *node = NULL; - int export = 0; + char model[41], model_enc[256], serial[21], revision[9]; _cleanup_close_ int fd = -EBADF; uint16_t word; - int is_packet_device = 0; - static const struct option options[] = { - { "export", no_argument, NULL, 'x' }, - { "help", no_argument, NULL, 'h' }, - {} - }; + int r; log_set_target(LOG_TARGET_AUTO); udev_parse_config(); log_parse_environment(); log_open(); - for (;;) { - int option; - - option = getopt_long(argc, argv, "xh", options, NULL); - if (option == -1) - break; - - switch (option) { - case 'x': - export = 1; - break; - case 'h': - printf("Usage: %s [--export] [--help] <device>\n" - " -x,--export print values as environment keys\n" - " -h,--help print this help text\n\n", - program_invocation_short_name); - return 0; - } - } + r = parse_argv(argc, argv); + if (r <= 0) + return r; - node = argv[optind]; - if (!node) { - log_error("no node specified"); - return 1; - } + fd = open(ASSERT_PTR(arg_device), O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return log_error_errno(errno, "Cannot open %s: %m", arg_device); - fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_NOCTTY); - if (fd < 0) { - log_error("unable to open '%s'", node); - return 1; - } - - if (disk_identify(fd, identify.byte, &is_packet_device) == 0) { + if (disk_identify(fd, identify.byte) >= 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 @@ -475,10 +452,8 @@ int main(int argc, char *argv[]) { memcpy(&id, identify.byte, sizeof id); } else { /* If this fails, then try HDIO_GET_IDENTITY */ - if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) { - log_debug_errno(errno, "HDIO_GET_IDENTITY failed for '%s': %m", node); - return 2; - } + if (ioctl(fd, HDIO_GET_IDENTITY, &id) != 0) + return log_debug_errno(errno, "%s: HDIO_GET_IDENTITY failed: %m", arg_device); } memcpy(model, id.model, 40); @@ -491,7 +466,7 @@ int main(int argc, char *argv[]) { udev_replace_whitespace((char *) id.fw_rev, revision, 8); udev_replace_chars(revision, NULL); - if (export) { + if (arg_export) { /* Set this to convey the disk speaks the ATA protocol */ printf("ID_ATA=1\n"); @@ -649,3 +624,5 @@ int main(int argc, char *argv[]) { return 0; } + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/cdrom_id/cdrom_id.c b/src/udev/cdrom_id/cdrom_id.c index ea420a9617..5b5fbd0109 100644 --- a/src/udev/cdrom_id/cdrom_id.c +++ b/src/udev/cdrom_id/cdrom_id.c @@ -10,6 +10,7 @@ #include <sys/ioctl.h> #include <unistd.h> +#include "build.h" #include "fd-util.h" #include "main-func.h" #include "memory-util.h" @@ -897,13 +898,13 @@ static void print_properties(const Context *c) { } static int help(void) { - printf("Usage: %s [options] <device>\n" - " -l --lock-media lock the media (to enable eject request events)\n" - " -u --unlock-media unlock the media\n" - " -e --eject-media eject the media\n" - " -d --debug print debug messages to stderr\n" - " -h --help print this help text\n" - "\n", + printf("%s [OPTIONS...] DEVICE\n\n" + " -l --lock-media Lock the media (to enable eject request events)\n" + " -u --unlock-media Unlock the media\n" + " -e --eject-media Eject the media\n" + " -d --debug Print debug messages to stderr\n" + " -h --help Show this help text\n" + " --version Show package version\n", program_invocation_short_name); return 0; @@ -916,6 +917,7 @@ static int parse_argv(int argc, char *argv[]) { { "eject-media", no_argument, NULL, 'e' }, { "debug", no_argument, NULL, 'd' }, { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, {} }; int c; @@ -938,6 +940,10 @@ static int parse_argv(int argc, char *argv[]) { break; case 'h': return help(); + case 'v': + return version(); + case '?': + return -EINVAL; default: assert_not_reached(); } diff --git a/src/udev/dmi_memory_id/dmi_memory_id.c b/src/udev/dmi_memory_id/dmi_memory_id.c index 1345289219..dd46113137 100644 --- a/src/udev/dmi_memory_id/dmi_memory_id.c +++ b/src/udev/dmi_memory_id/dmi_memory_id.c @@ -45,6 +45,7 @@ #include <getopt.h> #include "alloc-util.h" +#include "build.h" #include "fileio.h" #include "main-func.h" #include "string-util.h" @@ -638,9 +639,10 @@ static int legacy_decode(const uint8_t *buf, const char *devmem, bool no_file_of } static int help(void) { - printf("Usage: %s [options]\n" - " -F,--from-dump FILE read DMI information from a binary file\n" - " -h,--help print this help text\n\n", + printf("%s [OPTIONS...]\n\n" + " -F --from-dump FILE Read DMI information from a binary file\n" + " -h --help Show this help text\n" + " --version Show package version\n", program_invocation_short_name); return 0; } @@ -650,6 +652,7 @@ static int parse_argv(int argc, char * const *argv) { { "from-dump", required_argument, NULL, 'F' }, { "version", no_argument, NULL, 'V' }, { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, {} }; int c; @@ -666,6 +669,8 @@ static int parse_argv(int argc, char * const *argv) { return help(); case '?': return -EINVAL; + case 'v': + return version(); default: assert_not_reached(); } diff --git a/src/udev/fido_id/fido_id.c b/src/udev/fido_id/fido_id.c index f2fbc38003..e01f37d04c 100644 --- a/src/udev/fido_id/fido_id.c +++ b/src/udev/fido_id/fido_id.c @@ -8,12 +8,14 @@ #include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <linux/hid.h> #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <unistd.h> +#include "build.h" #include "device-private.h" #include "device-util.h" #include "fd-util.h" @@ -25,16 +27,47 @@ #include "string-util.h" #include "udev-util.h" +static const char *arg_device = NULL; + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + {} + }; + int c; + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + case 'h': + printf("%s [OPTIONS...] SYSFS_PATH\n\n" + " -h --help Show this help text\n" + " --version Show package version\n", + program_invocation_short_name); + return 0; + case 'v': + return version(); + case '?': + return -EINVAL; + default: + assert_not_reached(); + } + + if (argc > 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error: unexpected argument."); + + arg_device = argv[optind]; + return 1; +} + static int run(int argc, char **argv) { _cleanup_(sd_device_unrefp) struct sd_device *device = NULL; _cleanup_free_ char *desc_path = NULL; _cleanup_close_ int fd = -EBADF; - struct sd_device *hid_device; const char *sys_path; uint8_t desc[HID_MAX_DESCRIPTOR_SIZE]; ssize_t desc_len; - int r; log_set_target(LOG_TARGET_AUTO); @@ -42,17 +75,18 @@ static int run(int argc, char **argv) { log_parse_environment(); log_open(); - if (argc > 2) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Usage: %s [SYSFS_PATH]", program_invocation_short_name); + r = parse_argv(argc, argv); + if (r <= 0) + return r; - if (argc == 1) { - r = device_new_from_strv(&device, environ); + if (arg_device) { + r = sd_device_new_from_syspath(&device, arg_device); if (r < 0) - return log_error_errno(r, "Failed to get current device from environment: %m"); + return log_error_errno(r, "Failed to get device from syspath %s: %m", arg_device); } else { - r = sd_device_new_from_syspath(&device, argv[1]); + r = device_new_from_strv(&device, environ); if (r < 0) - return log_error_errno(r, "Failed to get device from syspath: %m"); + return log_error_errno(r, "Failed to get current device from environment: %m"); } r = sd_device_get_parent(device, &hid_device); diff --git a/src/udev/meson.build b/src/udev/meson.build index af7dea0dce..5b44dd8d7d 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -143,6 +143,7 @@ foreach prog : udev_progs install_dir : udevlibexecdir) udev_prog_paths += {name : exe} + public_programs += exe endforeach if install_sysconfdir_samples diff --git a/src/udev/mtd_probe/mtd_probe.c b/src/udev/mtd_probe/mtd_probe.c index a7210a05e3..1035320490 100644 --- a/src/udev/mtd_probe/mtd_probe.c +++ b/src/udev/mtd_probe/mtd_probe.c @@ -20,6 +20,7 @@ #include <errno.h> #include <fcntl.h> +#include <getopt.h> #include <mtd/mtd-user.h> #include <stdio.h> #include <stdlib.h> @@ -29,31 +30,61 @@ #include <unistd.h> #include "alloc-util.h" +#include "build.h" #include "fd-util.h" +#include "main-func.h" #include "mtd_probe.h" -int main(int argc, char** argv) { +static const char *arg_device = NULL; + +static int parse_argv(int argc, char *argv[]) { + static const struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + {} + }; + int c; + + while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) + switch (c) { + case 'h': + printf("%s /dev/mtd[n]\n\n" + " -h --help Show this help text\n" + " --version Show package version\n", + program_invocation_short_name); + return 0; + case 'v': + return version(); + case '?': + return -EINVAL; + default: + assert_not_reached(); + } + + if (argc > 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Error: unexpected argument."); + + arg_device = argv[optind]; + return 1; +} + +static int run(int argc, char** argv) { _cleanup_close_ int mtd_fd = -EBADF; mtd_info_t mtd_info; + int r; - if (argc != 2) { - printf("usage: mtd_probe /dev/mtd[n]\n"); - return EXIT_FAILURE; - } + r = parse_argv(argc, argv); + if (r <= 0) + return r; mtd_fd = open(argv[1], O_RDONLY|O_CLOEXEC|O_NOCTTY); - if (mtd_fd < 0) { - log_error_errno(errno, "Failed to open: %m"); - return EXIT_FAILURE; - } + if (mtd_fd < 0) + return log_error_errno(errno, "Failed to open: %m"); - if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) < 0) { - log_error_errno(errno, "Failed to issue MEMGETINFO ioctl: %m"); - return EXIT_FAILURE; - } + if (ioctl(mtd_fd, MEMGETINFO, &mtd_info) < 0) + return log_error_errno(errno, "MEMGETINFO ioctl failed: %m"); - if (probe_smart_media(mtd_fd, &mtd_info) < 0) - return EXIT_FAILURE; - - return EXIT_SUCCESS; + return probe_smart_media(mtd_fd, &mtd_info); } + +DEFINE_MAIN_FUNCTION(run); diff --git a/src/udev/v4l_id/v4l_id.c b/src/udev/v4l_id/v4l_id.c index 4f163c4350..30527e9556 100644 --- a/src/udev/v4l_id/v4l_id.c +++ b/src/udev/v4l_id/v4l_id.c @@ -26,51 +26,70 @@ #include <unistd.h> #include <linux/videodev2.h> +#include "build.h" #include "fd-util.h" +#include "main-func.h" -int main(int argc, char *argv[]) { +static const char *arg_device = NULL; + +static int parse_argv(int argc, char *argv[]) { static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, {} }; - _cleanup_close_ int fd = -EBADF; - char *device; - struct v4l2_capability v2cap; int c; while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) - switch (c) { case 'h': - printf("%s [-h,--help] <device file>\n\n" + printf("%s [OPTIONS...] DEVICE\n\n" "Video4Linux device identification.\n\n" - " -h Print this message\n", + " -h --help Show this help text\n" + " --version Show package version\n", program_invocation_short_name); return 0; + case 'v': + return version(); case '?': return -EINVAL; - default: assert_not_reached(); } - device = argv[optind]; - if (!device) - return 2; + if (!argv[optind]) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "DEVICE argument missing."); + + arg_device = argv[optind]; + return 1; +} - fd = open(device, O_RDONLY); +static int run(int argc, char *argv[]) { + _cleanup_close_ int fd = -EBADF; + struct v4l2_capability v2cap; + int r; + + r = parse_argv(argc, argv); + if (r <= 0) + return r; + + fd = open(arg_device, O_RDONLY|O_CLOEXEC|O_NOCTTY); if (fd < 0) - return 3; + return log_error_errno(errno, "Failed to open %s: %m", arg_device); if (ioctl(fd, VIDIOC_QUERYCAP, &v2cap) == 0) { int capabilities; + printf("ID_V4L_VERSION=2\n"); printf("ID_V4L_PRODUCT=%s\n", v2cap.card); printf("ID_V4L_CAPABILITIES=:"); + if (v2cap.capabilities & V4L2_CAP_DEVICE_CAPS) capabilities = v2cap.device_caps; else capabilities = v2cap.capabilities; + if ((capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0 || (capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) > 0) printf("capture:"); @@ -90,3 +109,5 @@ int main(int argc, char *argv[]) { return 0; } + +DEFINE_MAIN_FUNCTION(run); |