static int builtin_net_setup_link(sd_device *dev, int argc, char **argv, bool test) { _cleanup_free_ char *driver = NULL; const char *name = NULL; link_config *link; int r; if (argc > 1) return log_device_error_errno(dev, EINVAL, "This program takes no arguments."); r = link_get_driver(ctx, dev, &driver); if (r >= 0) udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); r = link_config_get(ctx, dev, &link); if (r < 0) { if (r == -ENOENT) return log_device_debug_errno(dev, r, "No matching link configuration found."); return log_device_error_errno(dev, r, "Failed to get link config: %m"); } r = link_config_apply(ctx, link, dev, &name); if (r < 0) log_device_warning_errno(dev, r, "Could not apply link config, ignoring: %m"); udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename); if (name) udev_builtin_add_property(dev, test, "ID_NET_NAME", name); return 0; }
/* key like devices */ static bool test_key(struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_key, bool test) { unsigned i; unsigned long found; unsigned long mask; bool ret = false; /* do we have any KEY_* capability? */ if (!test_bit(EV_KEY, bitmask_ev)) { log_debug("test_key: no EV_KEY capability"); return false; } /* only consider KEY_* here, not BTN_* */ found = 0; for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) { found |= bitmask_key[i]; log_debug("test_key: checking bit block %lu for any keys; found=%i", (unsigned long)i*BITS_PER_LONG, found > 0); } /* If there are no keys in the lower block, check the higher blocks */ if (!found) { unsigned block; for (block = 0; block < (sizeof(high_key_blocks) / sizeof(struct range)); ++block) { for (i = high_key_blocks[block].start; i < high_key_blocks[block].end; ++i) { if (test_bit(i, bitmask_key)) { log_debug("test_key: Found key %x in high block", i); found = 1; break; } } } } if (found > 0) { udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); ret = true; } /* the first 32 bits are ESC, numbers, and Q to D; if we have all of * those, consider it a full keyboard; do not test KEY_RESERVED, though */ mask = 0xFFFFFFFE; if ((bitmask_key[0] & mask) == mask) { udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1"); ret = true; } return ret; }
static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_device *pdev; unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_rel[NBITS(REL_MAX)]; unsigned long bitmask_props[NBITS(INPUT_PROP_MAX)]; const char *sysname, *devnode; bool is_pointer; bool is_key; assert(dev); /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ pdev = dev; while (pdev != NULL && udev_device_get_sysattr_value(pdev, "capabilities/ev") == NULL) pdev = udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); if (pdev) { /* Use this as a flag that input devices were detected, so that this * program doesn't need to be called more than once per device */ udev_builtin_add_property(dev, test, "ID_INPUT", "1"); get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); get_cap_mask(dev, pdev, "properties", bitmask_props, sizeof(bitmask_props), test); is_pointer = test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, bitmask_props, test); is_key = test_key(dev, bitmask_ev, bitmask_key, test); /* Some evdev nodes have only a scrollwheel */ if (!is_pointer && !is_key && test_bit(EV_REL, bitmask_ev) && (test_bit(REL_WHEEL, bitmask_rel) || test_bit(REL_HWHEEL, bitmask_rel))) udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); if (test_bit(EV_SW, bitmask_ev)) udev_builtin_add_property(dev, test, "ID_INPUT_SWITCH", "1"); } devnode = udev_device_get_devnode(dev); sysname = udev_device_get_sysname(dev); if (devnode && sysname && startswith(sysname, "event")) extract_info(dev, devnode, test); return EXIT_SUCCESS; }
int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, const char *filter, bool test) { _cleanup_free_ const char *lookup = NULL; const char *key, *value; int n = 0; if (!hwdb) return -ENOENT; if (prefix) { lookup = strjoin(prefix, modalias, NULL); if (!lookup) return -ENOMEM; modalias = lookup; } SD_HWDB_FOREACH_PROPERTY(hwdb, modalias, key, value) { if (filter && fnmatch(filter, key, FNM_NOESCAPE) != 0) continue; if (udev_builtin_add_property(dev, test, key, value) < 0) return -ENOMEM; n++; } return n; }
static int builtin_input_id(struct udev_device *dev, int argc, char *argv[], bool test) { struct udev_device *pdev; unsigned long bitmask_ev[NBITS(EV_MAX)]; unsigned long bitmask_abs[NBITS(ABS_MAX)]; unsigned long bitmask_key[NBITS(KEY_MAX)]; unsigned long bitmask_rel[NBITS(REL_MAX)]; /* walk up the parental chain until we find the real input device; the * argument is very likely a subdevice of this, like eventN */ pdev = dev; while (pdev != NULL && udev_device_get_sysattr_value(pdev, "capabilities/ev") == NULL) pdev = udev_device_get_parent_with_subsystem_devtype(pdev, "input", NULL); /* not an "input" class device */ if (pdev == NULL) return EXIT_SUCCESS; /* Use this as a flag that input devices were detected, so that this * program doesn't need to be called more than once per device */ udev_builtin_add_property(dev, test, "ID_INPUT", "1"); get_cap_mask(dev, pdev, "capabilities/ev", bitmask_ev, sizeof(bitmask_ev), test); get_cap_mask(dev, pdev, "capabilities/abs", bitmask_abs, sizeof(bitmask_abs), test); get_cap_mask(dev, pdev, "capabilities/rel", bitmask_rel, sizeof(bitmask_rel), test); get_cap_mask(dev, pdev, "capabilities/key", bitmask_key, sizeof(bitmask_key), test); test_pointers(dev, bitmask_ev, bitmask_abs, bitmask_key, bitmask_rel, test); test_key(dev, bitmask_ev, bitmask_key, test); return EXIT_SUCCESS; }
int udev_builtin_hwdb_lookup(struct udev_device *dev, const char *prefix, const char *modalias, const char *filter, bool test) { struct udev_list_entry *list; struct udev_list_entry *entry; int n = 0; if (!hwdb) return -ENOENT; if (prefix) { _cleanup_free_ const char *lookup; lookup = strjoin(prefix, modalias, NULL); if (!lookup) return -ENOMEM; list = udev_hwdb_get_properties_list_entry(hwdb, lookup, 0); } else list = udev_hwdb_get_properties_list_entry(hwdb, modalias, 0); udev_list_entry_foreach(entry, list) { if (filter && fnmatch(filter, udev_list_entry_get_name(entry), FNM_NOESCAPE) != 0) continue; if (udev_builtin_add_property(dev, test, udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)) < 0) return -ENOMEM; n++; } return n; }
/* key like devices */ static void test_key (struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_key, bool test) { struct udev *udev = udev_device_get_udev(dev); unsigned i; unsigned long found; unsigned long mask; /* do we have any KEY_* capability? */ if (!test_bit (EV_KEY, bitmask_ev)) { info(udev, "test_key: no EV_KEY capability\n"); return; } /* only consider KEY_* here, not BTN_* */ found = 0; for (i = 0; i < BTN_MISC/BITS_PER_LONG; ++i) { found |= bitmask_key[i]; info(udev, "test_key: checking bit block %lu for any keys; found=%i\n", i*BITS_PER_LONG, found > 0); } /* If there are no keys in the lower block, check the higher block */ if (!found) { for (i = KEY_OK; i < BTN_TRIGGER_HAPPY; ++i) { if (test_bit (i, bitmask_key)) { info(udev, "test_key: Found key %x in high block\n", i); found = 1; break; } } } if (found > 0) udev_builtin_add_property(dev, test, "ID_INPUT_KEY", "1"); /* the first 32 bits are ESC, numbers, and Q to D; if we have all of * those, consider it a full keyboard; do not test KEY_RESERVED, though */ mask = 0xFFFFFFFE; if ((bitmask_key[0] & mask) == mask) udev_builtin_add_property(dev, test, "ID_INPUT_KEYBOARD", "1"); }
static void extract_info(struct udev_device *dev, const char *devpath, bool test) { char width[DECIMAL_STR_MAX(int)], height[DECIMAL_STR_MAX(int)]; struct input_absinfo xabsinfo = {}, yabsinfo = {}; _cleanup_close_ int fd = -1; fd = open(devpath, O_RDONLY|O_CLOEXEC); if (fd < 0) return; if (ioctl(fd, EVIOCGABS(ABS_X), &xabsinfo) < 0 || ioctl(fd, EVIOCGABS(ABS_Y), &yabsinfo) < 0) return; if (xabsinfo.resolution <= 0 || yabsinfo.resolution <= 0) return; snprintf(width, sizeof(width), "%d", abs_size_mm(&xabsinfo)); snprintf(height, sizeof(height), "%d", abs_size_mm(&yabsinfo)); udev_builtin_add_property(dev, test, "ID_INPUT_WIDTH_MM", width); udev_builtin_add_property(dev, test, "ID_INPUT_HEIGHT_MM", height); }
static int builtin_net_setup_link(struct udev_device *dev, int argc, char **argv, bool test) { _cleanup_free_ char *driver = NULL; const char *name = NULL; link_config *link; int r; if (argc > 1) { log_error("This program takes no arguments."); return EXIT_FAILURE; } r = link_get_driver(ctx, dev, &driver); if (r >= 0) udev_builtin_add_property(dev, test, "ID_NET_DRIVER", driver); r = link_config_get(ctx, dev, &link); if (r < 0) { if (r == -ENOENT) { log_debug("No matching link configuration found."); return EXIT_SUCCESS; } else { log_error_errno(r, "Could not get link config: %m"); return EXIT_FAILURE; } } r = link_config_apply(ctx, link, dev, &name); if (r < 0) { log_error_errno(r, "Could not apply link config to %s: %m", udev_device_get_sysname(dev)); return EXIT_FAILURE; } udev_builtin_add_property(dev, test, "ID_NET_LINK_FILE", link->filename); if (name) udev_builtin_add_property(dev, test, "ID_NET_NAME", name); return EXIT_SUCCESS; }
/* pointer devices */ static void test_pointers (struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_abs, const unsigned long* bitmask_key, const unsigned long* bitmask_rel, bool test) { int is_mouse = 0; int is_touchpad = 0; if (!test_bit (EV_KEY, bitmask_ev)) { if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs) && test_bit (ABS_Z, bitmask_abs)) udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return; } if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs)) { if (test_bit (BTN_STYLUS, bitmask_key) || test_bit (BTN_TOOL_PEN, bitmask_key)) udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); else if (test_bit (BTN_TOOL_FINGER, bitmask_key) && !test_bit (BTN_TOOL_PEN, bitmask_key)) is_touchpad = 1; else if (test_bit (BTN_MOUSE, bitmask_key)) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ is_mouse = 1; else if (test_bit (BTN_TOUCH, bitmask_key)) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); /* joysticks don't necessarily have to have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have * other fancy axes */ else if (test_bit (BTN_TRIGGER, bitmask_key) || test_bit (BTN_A, bitmask_key) || test_bit (BTN_1, bitmask_key) || test_bit (ABS_RX, bitmask_abs) || test_bit (ABS_RY, bitmask_abs) || test_bit (ABS_RZ, bitmask_abs) || test_bit (ABS_THROTTLE, bitmask_abs) || test_bit (ABS_RUDDER, bitmask_abs) || test_bit (ABS_WHEEL, bitmask_abs) || test_bit (ABS_GAS, bitmask_abs) || test_bit (ABS_BRAKE, bitmask_abs)) udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); } if (test_bit (EV_REL, bitmask_ev) && test_bit (REL_X, bitmask_rel) && test_bit (REL_Y, bitmask_rel) && test_bit (BTN_MOUSE, bitmask_key)) is_mouse = 1; if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); }
static int builtin_btrfs(struct udev_device *dev, int argc, char *argv[], bool test) { struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -1; int err; if (argc != 3 || !streq(argv[1], "ready")) return EXIT_FAILURE; fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC); if (fd < 0) return EXIT_FAILURE; strscpy(args.name, sizeof(args.name), argv[2]); err = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); if (err < 0) return EXIT_FAILURE; udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(err == 0)); return EXIT_SUCCESS; }
static int builtin_btrfs(sd_device *dev, int argc, char *argv[], bool test) { struct btrfs_ioctl_vol_args args = {}; _cleanup_close_ int fd = -1; int r; if (argc != 3 || !streq(argv[1], "ready")) return log_device_error_errno(dev, EINVAL, "Invalid arguments"); fd = open("/dev/btrfs-control", O_RDWR|O_CLOEXEC); if (fd < 0) return log_device_debug_errno(dev, errno, "Failed to open /dev/btrfs-control: %m"); strscpy(args.name, sizeof(args.name), argv[2]); r = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); if (r < 0) return log_device_debug_errno(dev, errno, "Failed to call BTRFS_IOC_DEVICES_READY: %m"); udev_builtin_add_property(dev, test, "ID_BTRFS_READY", one_zero(r == 0)); return 0; }
/* pointer devices */ static void test_pointers (struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_abs, const unsigned long* bitmask_key, const unsigned long* bitmask_rel, bool test) { int is_mouse = 0; int is_touchpad = 0; if (!test_bit (EV_KEY, bitmask_ev)) { if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs) && test_bit (ABS_Z, bitmask_abs)) udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return; } if (test_bit (EV_ABS, bitmask_ev) && test_bit (ABS_X, bitmask_abs) && test_bit (ABS_Y, bitmask_abs)) { if (test_bit (BTN_STYLUS, bitmask_key) || test_bit (BTN_TOOL_PEN, bitmask_key)) udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); else if (test_bit (BTN_TOOL_FINGER, bitmask_key) && !test_bit (BTN_TOOL_PEN, bitmask_key)) is_touchpad = 1; else if (test_bit (BTN_TRIGGER, bitmask_key) || test_bit (BTN_A, bitmask_key) || test_bit (BTN_1, bitmask_key)) udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); else if (test_bit (BTN_MOUSE, bitmask_key)) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ is_mouse = 1; else if (test_bit (BTN_TOUCH, bitmask_key)) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); } if (test_bit (EV_REL, bitmask_ev) && test_bit (REL_X, bitmask_rel) && test_bit (REL_Y, bitmask_rel) && test_bit (BTN_MOUSE, bitmask_key)) is_mouse = 1; if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); }
static int builtin_btrfs(struct udev_device *dev, int argc, char *argv[], bool test) { struct btrfs_ioctl_vol_args args; int fd; int err; if (argc != 3 || !streq(argv[1], "ready")) return EXIT_FAILURE; fd = open("/dev/btrfs-control", O_RDWR); if (fd < 0) return EXIT_FAILURE; util_strscpy(args.name, sizeof(args.name), argv[2]); err = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args); close(fd); if (err < 0) return EXIT_FAILURE; udev_builtin_add_property(dev, test, "ID_BTRFS_READY", err == 0 ? "1" : "0"); return EXIT_SUCCESS; }
static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) { char s[256]; s[0] = '\0'; if (streq(name, "TYPE")) { udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); } else if (streq(name, "USAGE")) { udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); } else if (streq(name, "VERSION")) { udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); } else if (streq(name, "UUID")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); } else if (streq(name, "UUID_SUB")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); } else if (streq(name, "LABEL")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); } else if (streq(name, "PTTYPE")) { udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); } else if (streq(name, "PTUUID")) { udev_builtin_add_property(dev, test, "ID_PART_TABLE_UUID", value); } else if (streq(name, "PART_ENTRY_NAME")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); } else if (streq(name, "PART_ENTRY_TYPE")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); } else if (startswith(name, "PART_ENTRY_")) { strscpyl(s, sizeof(s), "ID_", name, NULL); udev_builtin_add_property(dev, test, s, value); } else if (streq(name, "SYSTEM_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_SYSTEM_ID", s); } else if (streq(name, "PUBLISHER_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_PUBLISHER_ID", s); } else if (streq(name, "APPLICATION_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_APPLICATION_ID", s); } else if (streq(name, "BOOT_SYSTEM_ID")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_BOOT_SYSTEM_ID", s); } }
static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) { const char *root_partition; int64_t offset = 0; bool noraid = false; _cleanup_close_ int fd = -1; blkid_probe pr; const char *data; const char *name; int nvals; int i; int err = 0; bool is_gpt = false; static const struct option options[] = { { "offset", optional_argument, NULL, 'o' }, { "noraid", no_argument, NULL, 'R' }, {} }; for (;;) { int option; option = getopt_long(argc, argv, "oR", options, NULL); if (option == -1) break; switch (option) { case 'o': offset = strtoull(optarg, NULL, 0); break; case 'R': noraid = true; break; } } pr = blkid_new_probe(); if (!pr) return EXIT_FAILURE; blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); if (noraid) blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); if (fd < 0) { fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); goto out; } err = blkid_probe_set_device(pr, fd, offset, 0); if (err < 0) goto out; log_debug("probe %s %sraid offset=%llu", udev_device_get_devnode(dev), noraid ? "no" : "", (unsigned long long) offset); err = probe_superblocks(pr); if (err < 0) goto out; /* If we are a partition then our parent passed on the root * partition UUID to us */ root_partition = udev_device_get_property_value(dev, "ID_PART_GPT_AUTO_ROOT_UUID"); nvals = blkid_probe_numof_values(pr); for (i = 0; i < nvals; i++) { if (blkid_probe_get_value(pr, i, &name, &data, NULL)) continue; print_property(dev, test, name, data); /* Is this a disk with GPT partition table? */ if (streq(name, "PTTYPE") && streq(data, "gpt")) is_gpt = true; /* Is this a partition that matches the root partition * property we inherited from our parent? */ if (root_partition && streq(name, "PART_ENTRY_UUID") && streq(data, root_partition)) udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT", "1"); } if (is_gpt) find_gpt_root(dev, pr, test); blkid_free_probe(pr); out: if (err < 0) return EXIT_FAILURE; return EXIT_SUCCESS; }
static int find_gpt_root(struct udev_device *dev, blkid_probe pr, bool test) { #if defined(GPT_ROOT_NATIVE) && defined(ENABLE_EFI) _cleanup_free_ char *root_id = NULL; bool found_esp = false; blkid_partlist pl; int i, nvals, r; assert(pr); /* Iterate through the partitions on this disk, and see if the * EFI ESP we booted from is on it. If so, find the first root * disk, and add a property indicating its partition UUID. */ errno = 0; pl = blkid_probe_get_partitions(pr); if (!pl) return errno ? -errno : -ENOMEM; nvals = blkid_partlist_numof_partitions(pl); for (i = 0; i < nvals; i++) { blkid_partition pp; const char *stype, *sid; sd_id128_t type; pp = blkid_partlist_get_partition(pl, i); if (!pp) continue; sid = blkid_partition_get_uuid(pp); if (!sid) continue; stype = blkid_partition_get_type_string(pp); if (!stype) continue; if (sd_id128_from_string(stype, &type) < 0) continue; if (sd_id128_equal(type, GPT_ESP)) { sd_id128_t id, esp; /* We found an ESP, let's see if it matches * the ESP we booted from. */ if (sd_id128_from_string(sid, &id) < 0) continue; r = efi_loader_get_device_part_uuid(&esp); if (r < 0) return r; if (sd_id128_equal(id, esp)) found_esp = true; } else if (sd_id128_equal(type, GPT_ROOT_NATIVE)) { /* We found a suitable root partition, let's * remember the first one. */ if (!root_id) { root_id = strdup(sid); if (!root_id) return -ENOMEM; } } } /* We found the ESP on this disk, and also found a root * partition, nice! Let's export its UUID */ if (found_esp && root_id) udev_builtin_add_property(dev, test, "ID_PART_GPT_AUTO_ROOT_UUID", root_id); #endif return 0; }
/* pointer devices */ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_abs, const unsigned long* bitmask_key, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { int button, axis; bool has_abs_coordinates = false; bool has_rel_coordinates = false; bool has_mt_coordinates = false; bool has_joystick_axes_or_buttons = false; bool is_direct = false; bool has_touch = false; bool has_3d_coordinates = false; bool has_keys = false; bool stylus_or_pen = false; bool finger_but_no_pen = false; bool has_mouse_button = false; bool is_mouse = false; bool is_touchpad = false; bool is_touchscreen = false; bool is_tablet = false; bool is_joystick = false; bool is_accelerometer = false; bool is_pointing_stick= false; has_keys = test_bit(EV_KEY, bitmask_ev); has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs); has_3d_coordinates = has_abs_coordinates && test_bit(ABS_Z, bitmask_abs); is_accelerometer = test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props); if (!has_keys && has_3d_coordinates) is_accelerometer = true; if (is_accelerometer) { udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return true; } is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); for (button = BTN_MOUSE; button < BTN_JOYSTICK && !has_mouse_button; button++) has_mouse_button = test_bit(button, bitmask_key); has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); /* unset has_mt_coordinates if devices claims to have all abs axis */ if (has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs)) has_mt_coordinates = false; is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props); has_touch = test_bit(BTN_TOUCH, bitmask_key); /* joysticks don't necessarily have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have * other fancy axes. Others have buttons only but no axes. * * The BTN_JOYSTICK range starts after the mouse range, so a mouse * with more than 16 buttons runs into the joystick range (e.g. Mad * Catz Mad Catz M.M.O.TE). Skip those. */ if (!test_bit(BTN_JOYSTICK - 1, bitmask_key)) { for (button = BTN_JOYSTICK; button < BTN_DIGI && !has_joystick_axes_or_buttons; button++) has_joystick_axes_or_buttons = test_bit(button, bitmask_key); for (button = BTN_TRIGGER_HAPPY1; button <= BTN_TRIGGER_HAPPY40 && !has_joystick_axes_or_buttons; button++) has_joystick_axes_or_buttons = test_bit(button, bitmask_key); for (button = BTN_DPAD_UP; button <= BTN_DPAD_RIGHT && !has_joystick_axes_or_buttons; button++) has_joystick_axes_or_buttons = test_bit(button, bitmask_key); } for (axis = ABS_RX; axis < ABS_PRESSURE && !has_joystick_axes_or_buttons; axis++) has_joystick_axes_or_buttons = test_bit(axis, bitmask_abs); if (has_abs_coordinates) { if (stylus_or_pen) is_tablet = true; else if (finger_but_no_pen && !is_direct) is_touchpad = true; else if (has_mouse_button) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ is_mouse = true; else if (has_touch || is_direct) is_touchscreen = true; else if (has_joystick_axes_or_buttons) is_joystick = true; } else if (has_joystick_axes_or_buttons) { is_joystick = true; } if (has_mt_coordinates) { if (stylus_or_pen) is_tablet = true; else if (finger_but_no_pen && !is_direct) is_touchpad = true; else if (has_touch || is_direct) is_touchscreen = true; } if (!is_tablet && !is_touchpad && !is_joystick && has_mouse_button && (has_rel_coordinates || !has_abs_coordinates)) /* mouse buttons and no axis */ is_mouse = true; if (is_pointing_stick) udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); if (is_touchscreen) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); if (is_joystick) udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); if (is_tablet) udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); return is_tablet || is_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick; }
static int builtin_net_id(struct udev_device *dev, int argc, char *argv[], bool test) { const char *s; const char *p; unsigned int i; const char *devtype; const char *prefix = "en"; struct netnames names = {}; int err; /* handle only ARPHRD_ETHER devices */ s = udev_device_get_sysattr_value(dev, "type"); if (!s) return EXIT_FAILURE; i = strtoul(s, NULL, 0); if (i != 1) return 0; /* skip stacked devices, like VLANs, ... */ s = udev_device_get_sysattr_value(dev, "ifindex"); if (!s) return EXIT_FAILURE; p = udev_device_get_sysattr_value(dev, "iflink"); if (!p) return EXIT_FAILURE; if (strcmp(s, p) != 0) return 0; devtype = udev_device_get_devtype(dev); if (devtype) { if (streq("wlan", devtype)) prefix = "wl"; else if (streq("wwan", devtype)) prefix = "ww"; } err = names_mac(dev, &names); if (err >= 0 && names.mac_valid) { char str[IFNAMSIZ]; snprintf(str, sizeof(str), "%sx%02x%02x%02x%02x%02x%02x", prefix, names.mac[0], names.mac[1], names.mac[2], names.mac[3], names.mac[4], names.mac[5]); udev_builtin_add_property(dev, test, "ID_NET_NAME_MAC", str); ieee_oui(dev, &names, test); } /* get PCI based path names, we compose only PCI based paths */ err = names_pci(dev, &names); if (err < 0) goto out; /* plain PCI device */ if (names.type == NET_PCI) { char str[IFNAMSIZ]; if (names.pci_onboard[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_ONBOARD", str); if (names.pci_onboard_label) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_onboard_label) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_LABEL_ONBOARD", str); if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_path) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s", prefix, names.pci_slot) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* USB device */ err = names_usb(dev, &names); if (err >= 0 && names.type == NET_USB) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.usb_ports) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } /* Broadcom bus */ err = names_bcma(dev, &names); if (err >= 0 && names.type == NET_BCMA) { char str[IFNAMSIZ]; if (names.pci_path[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_path, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_PATH", str); if (names.pci_slot[0]) if (snprintf(str, sizeof(str), "%s%s%s", prefix, names.pci_slot, names.bcma_core) < (int)sizeof(str)) udev_builtin_add_property(dev, test, "ID_NET_NAME_SLOT", str); goto out; } out: return EXIT_SUCCESS; }
/* pointer devices */ static bool test_pointers(struct udev_device *dev, const unsigned long* bitmask_ev, const unsigned long* bitmask_abs, const unsigned long* bitmask_key, const unsigned long* bitmask_rel, const unsigned long* bitmask_props, bool test) { bool has_abs_coordinates = false; bool has_rel_coordinates = false; bool has_mt_coordinates = false; bool has_joystick_axes_or_buttons = false; bool is_direct = false; bool has_touch = false; bool has_3d_coordinates = false; bool has_keys = false; bool stylus_or_pen = false; bool finger_but_no_pen = false; bool has_mouse_button = false; bool is_mouse = false; bool is_touchpad = false; bool is_touchscreen = false; bool is_tablet = false; bool is_joystick = false; bool is_accelerometer = false; bool is_pointing_stick= false; has_keys = test_bit(EV_KEY, bitmask_ev); has_abs_coordinates = test_bit(ABS_X, bitmask_abs) && test_bit(ABS_Y, bitmask_abs); has_3d_coordinates = has_abs_coordinates && test_bit(ABS_Z, bitmask_abs); is_accelerometer = test_bit(INPUT_PROP_ACCELEROMETER, bitmask_props); if (!has_keys && has_3d_coordinates) is_accelerometer = true; if (is_accelerometer) { udev_builtin_add_property(dev, test, "ID_INPUT_ACCELEROMETER", "1"); return true; } is_pointing_stick = test_bit(INPUT_PROP_POINTING_STICK, bitmask_props); stylus_or_pen = test_bit(BTN_STYLUS, bitmask_key) || test_bit(BTN_TOOL_PEN, bitmask_key); finger_but_no_pen = test_bit(BTN_TOOL_FINGER, bitmask_key) && !test_bit(BTN_TOOL_PEN, bitmask_key); has_mouse_button = test_bit(BTN_LEFT, bitmask_key); has_rel_coordinates = test_bit(EV_REL, bitmask_ev) && test_bit(REL_X, bitmask_rel) && test_bit(REL_Y, bitmask_rel); has_mt_coordinates = test_bit(ABS_MT_POSITION_X, bitmask_abs) && test_bit(ABS_MT_POSITION_Y, bitmask_abs); /* unset has_mt_coordinates if devices claims to have all abs axis */ if(has_mt_coordinates && test_bit(ABS_MT_SLOT, bitmask_abs) && test_bit(ABS_MT_SLOT - 1, bitmask_abs)) has_mt_coordinates = false; is_direct = test_bit(INPUT_PROP_DIRECT, bitmask_props); has_touch = test_bit(BTN_TOUCH, bitmask_key); /* joysticks don't necessarily have buttons; e. g. * rudders/pedals are joystick-like, but buttonless; they have * other fancy axes */ has_joystick_axes_or_buttons = test_bit(BTN_TRIGGER, bitmask_key) || test_bit(BTN_A, bitmask_key) || test_bit(BTN_1, bitmask_key) || test_bit(ABS_RX, bitmask_abs) || test_bit(ABS_RY, bitmask_abs) || test_bit(ABS_RZ, bitmask_abs) || test_bit(ABS_THROTTLE, bitmask_abs) || test_bit(ABS_RUDDER, bitmask_abs) || test_bit(ABS_WHEEL, bitmask_abs) || test_bit(ABS_GAS, bitmask_abs) || test_bit(ABS_BRAKE, bitmask_abs); if (has_abs_coordinates) { if (stylus_or_pen) is_tablet = true; else if (finger_but_no_pen && !is_direct) is_touchpad = true; else if (has_mouse_button) /* This path is taken by VMware's USB mouse, which has * absolute axes, but no touch/pressure button. */ is_mouse = true; else if (has_touch) is_touchscreen = true; else if (has_joystick_axes_or_buttons) is_joystick = true; } if (has_mt_coordinates && is_direct) is_touchscreen = true; if (has_rel_coordinates && has_mouse_button) is_mouse = true; if (is_pointing_stick) udev_builtin_add_property(dev, test, "ID_INPUT_POINTINGSTICK", "1"); if (is_mouse) udev_builtin_add_property(dev, test, "ID_INPUT_MOUSE", "1"); if (is_touchpad) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHPAD", "1"); if (is_touchscreen) udev_builtin_add_property(dev, test, "ID_INPUT_TOUCHSCREEN", "1"); if (is_joystick) udev_builtin_add_property(dev, test, "ID_INPUT_JOYSTICK", "1"); if (is_tablet) udev_builtin_add_property(dev, test, "ID_INPUT_TABLET", "1"); return is_tablet || is_mouse || is_touchpad || is_touchscreen || is_joystick || is_pointing_stick; }
/* * A unique USB identification is generated like this: * * 1.) Get the USB device type from InterfaceClass and InterfaceSubClass * 2.) If the device type is 'Mass-Storage/SPC-2' or 'Mass-Storage/RBC', * use the SCSI vendor and model as USB-Vendor and USB-model. * 3.) Otherwise, use the USB manufacturer and product as * USB-Vendor and USB-model. Any non-printable characters * in those strings will be skipped; a slash '/' will be converted * into a full stop '.'. * 4.) If that fails, too, we will use idVendor and idProduct * as USB-Vendor and USB-model. * 5.) The USB identification is the USB-vendor and USB-model * string concatenated with an underscore '_'. * 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]; char vendor_str_enc[256]; const char *vendor_id; 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]; const char *ifnum = NULL; const char *driver = NULL; char serial[256]; struct udev_device *dev_interface = NULL; struct udev_device *dev_usb = NULL; 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'; /* 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")) { 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; } ifnum = udev_device_get_sysattr_value(dev_interface, "bInterfaceNumber"); driver = udev_device_get_sysattr_value(dev_interface, "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; } 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) protocol = set_usb_mass_storage_ifsubtype(type_str, if_subclass, sizeof(type_str)-1); } 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); /* 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; } /* 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; 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)); 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)); 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)); 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)); 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)); 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)); goto fallback; } util_replace_whitespace(scsi_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); /* * some broken devices have the same identifiers * for all luns, export the target:lun number */ sprintf(instance_str, "%d:%d", target, lun); } fallback: vendor_id = udev_device_get_sysattr_value(dev_usb, "idVendor"); product_id = udev_device_get_sysattr_value(dev_usb, "idProduct"); /* fallback to USB vendor & device */ if (vendor_str[0] == '\0') { const char *usb_vendor = NULL; usb_vendor = udev_device_get_sysattr_value(dev_usb, "manufacturer"); if (!usb_vendor) 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; usb_model = udev_device_get_sysattr_value(dev_usb, "product"); if (!usb_model) 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); } if (revision_str[0] == '\0') { const char *usb_rev; usb_rev = udev_device_get_sysattr_value(dev_usb, "bcdDevice"); if (usb_rev) { util_replace_whitespace(usb_rev, revision_str, sizeof(revision_str)-1); util_replace_chars(revision_str, NULL); } } if (serial_str[0] == '\0') { const char *usb_serial; usb_serial = udev_device_get_sysattr_value(dev_usb, "serial"); if (usb_serial) { const unsigned char *p; /* http://msdn.microsoft.com/en-us/library/windows/hardware/gg487321.aspx */ 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); } } s = serial; l = strpcpyl(&s, sizeof(serial), vendor_str, "_", model_str, NULL); if (serial_str[0] != '\0') l = strpcpyl(&s, l, "_", serial_str, NULL); if (instance_str[0] != '\0') strpcpyl(&s, l, "-", instance_str, NULL); udev_builtin_add_property(dev, test, "ID_VENDOR", vendor_str); udev_builtin_add_property(dev, test, "ID_VENDOR_ENC", vendor_str_enc); udev_builtin_add_property(dev, test, "ID_VENDOR_ID", vendor_id); udev_builtin_add_property(dev, test, "ID_MODEL", model_str); udev_builtin_add_property(dev, test, "ID_MODEL_ENC", model_str_enc); 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') udev_builtin_add_property(dev, test, "ID_SERIAL_SHORT", serial_str); if (type_str[0] != '\0') udev_builtin_add_property(dev, test, "ID_TYPE", type_str); if (instance_str[0] != '\0') 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') udev_builtin_add_property(dev, test, "ID_USB_INTERFACES", packed_if_str); if (ifnum != NULL) udev_builtin_add_property(dev, test, "ID_USB_INTERFACE_NUM", ifnum); if (driver != NULL) udev_builtin_add_property(dev, test, "ID_USB_DRIVER", driver); return EXIT_SUCCESS; }
static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) { char s[265]; s[0] = '\0'; if (!strcmp(name, "TYPE")) { udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); } else if (!strcmp(name, "USAGE")) { udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); } else if (!strcmp(name, "VERSION")) { udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); } else if (!strcmp(name, "UUID")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); } else if (!strcmp(name, "UUID_SUB")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); } else if (!strcmp(name, "LABEL")) { blkid_safe_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); } else if (!strcmp(name, "PTTYPE")) { udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); } else if (!strcmp(name, "PART_ENTRY_NAME")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); } else if (!strcmp(name, "PART_ENTRY_TYPE")) { blkid_encode_string(value, s, sizeof(s)); udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); } else if (!strncmp(name, "PART_ENTRY_", 11)) { util_strscpyl(s, sizeof(s), "ID_", name, NULL); udev_builtin_add_property(dev, test, s, value); } }