/* * zdev - Modify and display the persistent configuration of devices * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include "lib/util_path.h" #include "lib/util_udev.h" #include "attrib.h" #include "ccw.h" #include "device.h" #include "misc.h" #include "path.h" #include "setting.h" #include "udev.h" #include "zdev_id.h" int udev_need_settle = 0; int udev_no_settle; /* Check if a udev file does not contain any statements. */ bool udev_file_is_empty(struct util_udev_file *file) { struct util_udev_line_node *l; if (!file) return true; util_list_iterate(&file->lines, l) { if (l->line[0]) return false; } return true; } static bool get_ids_cb(const char *filename, void *data) { char *prefix = data; if (strncmp(filename, prefix, strlen(prefix)) != 0) return false; if (!ends_with(filename, UDEV_SUFFIX)) return false; return true; } /* Add the IDs for all devices of the specified subtype name for which a * udev rule exists to strlist LIST. */ void udev_get_device_ids(const char *type, struct util_list *list, bool autoconf) { char *path, *prefix; struct util_list *files; struct strlist_node *s; size_t plen, len; prefix = misc_asprintf("%s-%s-", UDEV_PREFIX, type); plen = strlen(prefix); path = path_get_udev_rules(autoconf); files = strlist_new(); if (!misc_read_dir(path, files, get_ids_cb, prefix)) goto out; util_list_iterate(files, s) { /* 41-dasd-eckd-0.0.1234.rules */ len = strlen(s->str); s->str[len - sizeof(UDEV_SUFFIX) + 1] = 0; strlist_add(list, &s->str[plen]); } out: strlist_free(files); free(path); free(prefix); } /* Remove UDEV rule for device. */ exit_code_t udev_remove_rule(const char *type, const char *id, bool autoconf) { char *path; exit_code_t rc = EXIT_OK; path = path_get_udev_rule(type, id, autoconf); if (util_path_is_reg_file(path)) rc = remove_file(path); free(path); return rc; } /* Wait for all current udev events to finish. */ void udev_settle(void) { if (udev_no_settle) return; misc_system(err_ignore, "%s settle", PATH_UDEVADM); } /* Extract internal attribute settings from @entry and add to @list. * Associate corresponding attribute if found in @attribs. */ void udev_add_internal_from_entry(struct setting_list *list, struct util_udev_entry_node *entry, struct attrib **attribs) { char *copy, *name, *end, *u; struct attrib *a; /* ENV{zdev_var}="1" */ copy = misc_strdup(entry->key); /* Find attribute name start. */ name = strchr(copy, '{'); end = strrchr(copy, '}'); if (!name || !end) goto out; *end = 0; name++; /* zdev_ => zdev: */ u = strchr(name, '_'); if (u) *u = ':'; a = attrib_find(attribs, name); setting_list_apply_actual(list, a, name, entry->value); out: free(copy); } bool is_legacy_rule(struct util_udev_file *file) { struct util_udev_line_node *line; util_list_iterate(&file->lines, line) if (starts_with(line->line, SITE_BLOCK_START)) return false; return true; }