]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/udev/udev-builtin-usb_id.c
Merge pull request #11827 from keszybz/pkgconfig-variables
[thirdparty/systemd.git] / src / udev / udev-builtin-usb_id.c
index 6516d93a3c960e2f24afb4b3df4ec805daf91fd9..3525d250489f628d3b2e7dfde271868699dcf3cb 100644 (file)
@@ -1,35 +1,27 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
 /*
  * USB device properties and persistent device path
  *
  * Copyright (c) 2005 SUSE Linux Products GmbH, Germany
  *   Author: Hannes Reinecke <hare@suse.de>
- *
- * Copyright (C) 2005-2011 Kay Sievers <kay@vrfy.org>
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <stdarg.h>
-#include <unistd.h>
 #include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <errno.h>
+#include <unistd.h>
 
-#include "udev.h"
+#include "alloc-util.h"
+#include "device-util.h"
+#include "fd-util.h"
+#include "libudev-util.h"
+#include "string-util.h"
+#include "strxcpyx.h"
+#include "udev-builtin.h"
 
 static void set_usb_iftype(char *to, int if_class_num, size_t len) {
         const char *type = "generic";
@@ -145,40 +137,45 @@ static void set_scsi_type(char *to, const char *from, size_t len) {
 #define USB_DT_DEVICE                        0x01
 #define USB_DT_INTERFACE                0x04
 
-static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len) {
+static int dev_if_packed_info(sd_device *dev, char *ifs_str, size_t len) {
         _cleanup_free_ char *filename = NULL;
         _cleanup_close_ int fd = -1;
         ssize_t size;
         unsigned char buf[18 + 65535];
-        int pos = 0;
+        size_t pos = 0;
         unsigned strpos = 0;
+        const char *syspath;
+        int r;
         struct usb_interface_descriptor {
-                uint8_t        bLength;
-                uint8_t        bDescriptorType;
-                uint8_t        bInterfaceNumber;
-                uint8_t        bAlternateSetting;
-                uint8_t        bNumEndpoints;
-                uint8_t        bInterfaceClass;
-                uint8_t        bInterfaceSubClass;
-                uint8_t        bInterfaceProtocol;
-                uint8_t        iInterface;
+                uint8_t bLength;
+                uint8_t bDescriptorType;
+                uint8_t bInterfaceNumber;
+                uint8_t bAlternateSetting;
+                uint8_t bNumEndpoints;
+                uint8_t bInterfaceClass;
+                uint8_t bInterfaceSubClass;
+                uint8_t bInterfaceProtocol;
+                uint8_t iInterface;
         } _packed_;
 
-        if (asprintf(&filename, "%s/descriptors", udev_device_get_syspath(dev)) < 0)
+        r = sd_device_get_syspath(dev, &syspath);
+        if (r < 0)
+                return r;
+        if (asprintf(&filename, "%s/descriptors", syspath) < 0)
                 return log_oom();
 
         fd = open(filename, O_RDONLY|O_CLOEXEC);
-        if (fd < 0) {
-                fprintf(stderr, "error opening USB device 'descriptors' file\n");
-                return -errno;
-        }
+        if (fd < 0)
+                return log_device_debug_errno(dev, errno, "Failed to open USB device 'descriptors' file: %m");
 
         size = read(fd, buf, sizeof(buf));
-        if (size < 18 || size == sizeof(buf))
+        if (size < 18 || (size_t) size >= sizeof(buf))
                 return -EIO;
 
         ifs_str[0] = '\0';
-        while (pos < size && strpos+7 < len-2) {
+        while (pos + sizeof(struct usb_interface_descriptor) < (size_t) size &&
+               strpos + 7 < len - 2) {
+
                 struct usb_interface_descriptor *desc;
                 char if_str[8];
 
@@ -228,138 +225,130 @@ static int dev_if_packed_info(struct udev_device *dev, char *ifs_str, size_t len
  * 6.) If the device supplies a serial number, this number
  *     is concatenated with the identification with an underscore '_'.
  */
-static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool test) {
-        char vendor_str[64];
+static int builtin_usb_id(sd_device *dev, int argc, char *argv[], bool test) {
+        char vendor_str[64] = "";
         char vendor_str_enc[256];
         const char *vendor_id;
-        char model_str[64];
+        char model_str[64] = "";
         char model_str_enc[256];
         const char *product_id;
-        char serial_str[UTIL_NAME_SIZE];
-        char packed_if_str[UTIL_NAME_SIZE];
-        char revision_str[64];
-        char type_str[64];
-        char instance_str[64];
+        char serial_str[UTIL_NAME_SIZE] = "";
+        char packed_if_str[UTIL_NAME_SIZE] = "";
+        char revision_str[64] = "";
+        char type_str[64] = "";
+        char instance_str[64] = "";
         const char *ifnum = NULL;
         const char *driver = NULL;
         char serial[256];
 
-        struct udev_device *dev_interface = NULL;
-        struct udev_device *dev_usb = NULL;
+        sd_device *dev_interface, *dev_usb;
         const char *if_class, *if_subclass;
         int if_class_num;
         int protocol = 0;
         size_t l;
         char *s;
 
-        vendor_str[0] = '\0';
-        model_str[0] = '\0';
-        serial_str[0] = '\0';
-        packed_if_str[0] = '\0';
-        revision_str[0] = '\0';
-        type_str[0] = '\0';
-        instance_str[0] = '\0';
+        const char *syspath, *sysname, *devtype, *interface_syspath;
+        int r;
+
+        assert(dev);
+
+        r = sd_device_get_syspath(dev, &syspath);
+        if (r < 0)
+                return r;
+
+        r = sd_device_get_sysname(dev, &sysname);
+        if (r < 0)
+                return r;
 
         /* shortcut, if we are called directly for a "usb_device" type */
-        if (udev_device_get_devtype(dev) != NULL && streq(udev_device_get_devtype(dev), "usb_device")) {
+        if (sd_device_get_devtype(dev, &devtype) >= 0 && streq(devtype, "usb_device")) {
                 dev_if_packed_info(dev, packed_if_str, sizeof(packed_if_str));
                 dev_usb = dev;
                 goto fallback;
         }
 
         /* usb interface directory */
-        dev_interface = udev_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface");
-        if (dev_interface == NULL) {
-                log_debug("unable to access usb_interface device of '%s'",
-                     udev_device_get_syspath(dev));
-                return EXIT_FAILURE;
-        }
+        r = sd_device_get_parent_with_subsystem_devtype(dev, "usb", "usb_interface", &dev_interface);
+        if (r < 0)
+                return log_device_debug_errno(dev, r, "Failed to access usb_interface: %m");
 
-        ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber");
-        driver = udev_device_get_sysattr_value(dev_interface, "driver");
+        r = sd_device_get_syspath(dev_interface, &interface_syspath);
+        if (r < 0)
+                return log_device_debug_errno(dev_interface, r, "Failed to get syspath: %m");
+        (void) sd_device_get_sysattr_value(dev_interface, "bInterfaceNumber", &ifnum);
+        (void) sd_device_get_sysattr_value(dev_interface, "driver", &driver);
 
-        if_class = udev_device_get_sysattr_value(dev_interface, "bInterfaceClass");
-        if (!if_class) {
-                log_debug("%s: cannot get bInterfaceClass attribute",
-                     udev_device_get_sysname(dev));
-                return EXIT_FAILURE;
-        }
+        r = sd_device_get_sysattr_value(dev_interface, "bInterfaceClass", &if_class);
+        if (r < 0)
+                return log_device_debug_errno(dev_interface, r, "Failed to get bInterfaceClass attribute: %m");
 
         if_class_num = strtoul(if_class, NULL, 16);
         if (if_class_num == 8) {
                 /* mass storage */
-                if_subclass = udev_device_get_sysattr_value(dev_interface, "bInterfaceSubClass");
-                if (if_subclass != NULL)
+                if (sd_device_get_sysattr_value(dev_interface, "bInterfaceSubClass", &if_subclass) >= 0)
                         protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1);
-        } else {
+        } else
                 set_usb_iftype(type_str, if_class_num, sizeof(type_str)-1);
-        }
 
-        log_debug("%s: if_class %d protocol %d",
-             udev_device_get_syspath(dev_interface), if_class_num, protocol);
+        log_device_debug(dev_interface, "if_class:%d protocol:%d", if_class_num, protocol);
 
         /* usb device directory */
-        dev_usb = udev_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device");
-        if (!dev_usb) {
-                log_debug("unable to find parent 'usb' device of '%s'",
-                     udev_device_get_syspath(dev));
-                return EXIT_FAILURE;
-        }
+        r = sd_device_get_parent_with_subsystem_devtype(dev_interface, "usb", "usb_device", &dev_usb);
+        if (r < 0)
+                return log_device_debug_errno(dev_interface, r, "Failed to find parent 'usb' device");
 
         /* all interfaces of the device in a single string */
         dev_if_packed_info(dev_usb, packed_if_str, sizeof(packed_if_str));
 
         /* mass storage : SCSI or ATAPI */
-        if ((protocol == 6 || protocol == 2)) {
-                struct udev_device *dev_scsi;
-                const char *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev;
+        if (IN_SET(protocol, 6, 2)) {
+                sd_device *dev_scsi;
+                const char *scsi_sysname, *scsi_model, *scsi_vendor, *scsi_type, *scsi_rev;
                 int host, bus, target, lun;
 
                 /* get scsi device */
-                dev_scsi = udev_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device");
-                if (dev_scsi == NULL) {
-                        log_debug("unable to find parent 'scsi' device of '%s'",
-                             udev_device_get_syspath(dev));
+                r = sd_device_get_parent_with_subsystem_devtype(dev, "scsi", "scsi_device", &dev_scsi);
+                if (r < 0) {
+                        log_device_debug_errno(dev, r, "Unable to find parent SCSI device");
                         goto fallback;
                 }
-                if (sscanf(udev_device_get_sysname(dev_scsi), "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) {
-                        log_debug("invalid scsi device '%s'", udev_device_get_sysname(dev_scsi));
+                if (sd_device_get_sysname(dev_scsi, &scsi_sysname) < 0)
+                        goto fallback;
+                if (sscanf(scsi_sysname, "%d:%d:%d:%d", &host, &bus, &target, &lun) != 4) {
+                        log_device_debug(dev_scsi, "Invalid SCSI device");
                         goto fallback;
                 }
 
                 /* Generic SPC-2 device */
-                scsi_vendor = udev_device_get_sysattr_value(dev_scsi, "vendor");
-                if (!scsi_vendor) {
-                        log_debug("%s: cannot get SCSI vendor attribute",
-                             udev_device_get_sysname(dev_scsi));
+                r = sd_device_get_sysattr_value(dev_scsi, "vendor", &scsi_vendor);
+                if (r < 0) {
+                        log_device_debug_errno(dev_scsi, r, "Failed to get SCSI vendor attribute: %m");
                         goto fallback;
                 }
                 udev_util_encode_string(scsi_vendor, vendor_str_enc, sizeof(vendor_str_enc));
                 util_replace_whitespace(scsi_vendor, vendor_str, sizeof(vendor_str)-1);
                 util_replace_chars(vendor_str, NULL);
 
-                scsi_model = udev_device_get_sysattr_value(dev_scsi, "model");
-                if (!scsi_model) {
-                        log_debug("%s: cannot get SCSI model attribute",
-                             udev_device_get_sysname(dev_scsi));
+                r = sd_device_get_sysattr_value(dev_scsi, "model", &scsi_model);
+                if (r < 0) {
+                        log_device_debug_errno(dev_scsi, r, "Failed to get SCSI model attribute: %m");
                         goto fallback;
                 }
                 udev_util_encode_string(scsi_model, model_str_enc, sizeof(model_str_enc));
                 util_replace_whitespace(scsi_model, model_str, sizeof(model_str)-1);
                 util_replace_chars(model_str, NULL);
 
-                scsi_type = udev_device_get_sysattr_value(dev_scsi, "type");
-                if (!scsi_type) {
-                        log_debug("%s: cannot get SCSI type attribute",
-                             udev_device_get_sysname(dev_scsi));
+                r = sd_device_get_sysattr_value(dev_scsi, "type", &scsi_type);
+                if (r < 0) {
+                        log_device_debug_errno(dev_scsi, r, "Failed to get SCSI type attribute: %m");
                         goto fallback;
                 }
                 set_scsi_type(type_str, scsi_type, sizeof(type_str)-1);
 
-                scsi_rev = udev_device_get_sysattr_value(dev_scsi, "rev");
-                if (!scsi_rev) {
-                        log_debug("%s: cannot get SCSI revision attribute",
-                             udev_device_get_sysname(dev_scsi));
+                r = sd_device_get_sysattr_value(dev_scsi, "rev", &scsi_rev);
+                if (r < 0) {
+                        log_device_debug_errno(dev_scsi, r, "Failed to get SCSI revision attribute: %m");
                         goto fallback;
                 }
                 util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1);
@@ -373,33 +362,30 @@ static int builtin_usb_id(struct udev_device *dev, int argc, char *argv[], bool
         }
 
 fallback:
-        vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor");
-        product_id = udev_device_get_sysattr_value(dev_usb, "idProduct");
+        r = sd_device_get_sysattr_value(dev_usb, "idVendor", &vendor_id);
+        if (r < 0)
+                return log_device_debug_errno(dev_usb, r, "Failed to get idVendor attribute: %m");
+
+        r = sd_device_get_sysattr_value(dev_usb, "idProduct", &product_id);
+        if (r < 0)
+                return log_device_debug_errno(dev_usb, r, "Failed to get idProduct attribute: %m");
 
         /* fallback to USB vendor & device */
         if (vendor_str[0] == '\0') {
-                const char *usb_vendor = NULL;
+                const char *usb_vendor;
 
-                usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer");
-                if (!usb_vendor)
+                if (sd_device_get_sysattr_value(dev_usb, "manufacturer", &usb_vendor) < 0)
                         usb_vendor = vendor_id;
-                if (!usb_vendor) {
-                        log_debug("No USB vendor information available");
-                        return EXIT_FAILURE;
-                }
                 udev_util_encode_string(usb_vendor, vendor_str_enc, sizeof(vendor_str_enc));
                 util_replace_whitespace(usb_vendor, vendor_str, sizeof(vendor_str)-1);
                 util_replace_chars(vendor_str, NULL);
         }
 
         if (model_str[0] == '\0') {
-                const char *usb_model = NULL;
+                const char *usb_model;
 
-                usb_model = udev_device_get_sysattr_value(dev_usb, "product");
-                if (!usb_model)
+                if (sd_device_get_sysattr_value(dev_usb, "product", &usb_model) < 0)
                         usb_model = product_id;
-                if (!usb_model)
-                        return EXIT_FAILURE;
                 udev_util_encode_string(usb_model, model_str_enc, sizeof(model_str_enc));
                 util_replace_whitespace(usb_model, model_str, sizeof(model_str)-1);
                 util_replace_chars(model_str, NULL);
@@ -408,8 +394,7 @@ fallback:
         if (revision_str[0] == '\0') {
                 const char *usb_rev;
 
-                usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice");
-                if (usb_rev) {
+                if (sd_device_get_sysattr_value(dev_usb, "bcdDevice", &usb_rev) >= 0) {
                         util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1);
                         util_replace_chars(revision_str, NULL);
                 }
@@ -418,30 +403,29 @@ fallback:
         if (serial_str[0] == '\0') {
                 const char *usb_serial;
 
-                usb_serial = udev_device_get_sysattr_value(dev_usb, "serial");
-                if (usb_serial) {
+                if (sd_device_get_sysattr_value(dev_usb, "serial", &usb_serial) >= 0) {
                         const unsigned char *p;
 
                         /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */
-                        for (p = (unsigned char *)usb_serial; *p != '\0'; p++)
+                        for (p = (unsigned char *) usb_serial; *p != '\0'; p++)
                                 if (*p < 0x20 || *p > 0x7f || *p == ',') {
                                         usb_serial = NULL;
                                         break;
                                 }
-                }
 
-                if (usb_serial) {
-                        util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1);
-                        util_replace_chars(serial_str, NULL);
+                        if (usb_serial) {
+                                util_replace_whitespace(usb_serial, serial_str, sizeof(serial_str)-1);
+                                util_replace_chars(serial_str, NULL);
+                        }
                 }
         }
 
         s = serial;
         l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL);
-        if (serial_str[0] != '\0')
+        if (!isempty(serial_str))
                 l = strpcpyl(&s, l, "_", serial_str, NULL);
 
-        if (instance_str[0] != '\0')
+        if (!isempty(instance_str))
                 strpcpyl(&s, l, "-", instance_str, NULL);
 
         udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str);
@@ -452,20 +436,20 @@ fallback:
         udev_builtin_add_property(dev, test, "ID_MODEL_ID", product_id);
         udev_builtin_add_property(dev, test, "ID_REVISION", revision_str);
         udev_builtin_add_property(dev, test, "ID_SERIAL", serial);
-        if (serial_str[0] != '\0')
+        if (!isempty(serial_str))
                 udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str);
-        if (type_str[0] != '\0')
+        if (!isempty(type_str))
                 udev_builtin_add_property(dev, test, "ID_TYPE", type_str);
-        if (instance_str[0] != '\0')
+        if (!isempty(instance_str))
                 udev_builtin_add_property(dev, test, "ID_INSTANCE", instance_str);
         udev_builtin_add_property(dev, test, "ID_BUS", "usb");
-        if (packed_if_str[0] != '\0')
+        if (!isempty(packed_if_str))
                 udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str);
-        if (ifnum != NULL)
+        if (ifnum)
                 udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum);
-        if (driver != NULL)
+        if (driver)
                 udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver);
-        return EXIT_SUCCESS;
+        return 0;
 }
 
 const struct udev_builtin udev_builtin_usb_id = {