コード例 #1
0
ファイル: libudev-monitor.c プロジェクト: sylware/mudev
static struct udev_monitor *udev_monitor_new(struct udev *udev)
{
        struct udev_monitor *udev_monitor;

        udev_monitor = calloc(1, sizeof(struct udev_monitor));
        if (udev_monitor == NULL)
                return NULL;
        udev_monitor->refcount = 1;
        udev_monitor->udev = udev;
        udev_list_init(udev, &udev_monitor->filter_subsystem_list, false);
        udev_list_init(udev, &udev_monitor->filter_tag_list, true);
        return udev_monitor;
}
コード例 #2
0
ファイル: udev-event.c プロジェクト: AlexBaranosky/systemd
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);
        event->fd_signal = -1;
        event->birth_usec = now(CLOCK_MONOTONIC);
        return event;
}
コード例 #3
0
ファイル: udev-event.c プロジェクト: chuanchang/systemd
struct udev_event *udev_event_new(struct udev_device *dev)
{
        struct udev *udev = udev_device_get_udev(dev);
        struct udev_event *event;

        event = calloc(1, sizeof(struct udev_event));
        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);
        event->fd_signal = -1;
        event->birth_usec = now(CLOCK_MONOTONIC);
        event->timeout_usec = 30 * 1000 * 1000;
        return event;
}
コード例 #4
0
ファイル: libudev-device.c プロジェクト: AOSC-Dev/systemd
struct udev_device *udev_device_new(struct udev *udev) {
        struct udev_device *udev_device;

        assert_return_errno(udev, NULL, EINVAL);

        udev_device = new0(struct udev_device, 1);
        if (!udev_device) {
                errno = ENOMEM;
                return NULL;
        }
        udev_device->refcount = 1;
        udev_device->udev = udev;
        udev_list_init(udev, &udev_device->properties, true);
        udev_list_init(udev, &udev_device->tags, true);
        udev_list_init(udev, &udev_device->sysattrs, true);
        udev_list_init(udev, &udev_device->devlinks, true);

        return udev_device;
}
コード例 #5
0
static int64_t trie_store_nodes(struct trie_f *trie, struct trie_node *node) {
        uint64_t i;
        struct trie_node_f n = {
                .prefix_off = htole64(trie->strings_off + node->prefix_off),
                .children_count = node->children_count,
                .values_count = htole64(node->values_count),
        };
        struct trie_child_entry_f *children = NULL;
        int64_t node_off;

        if (node->children_count) {
                children = new0(struct trie_child_entry_f, node->children_count);
                if (!children)
                        return -ENOMEM;
        }

        /* post-order recursion */
        for (i = 0; i < node->children_count; i++) {
                int64_t child_off;

                child_off = trie_store_nodes(trie, node->children[i].child);
                if (child_off < 0) {
                        free(children);
                        return child_off;
                }
                children[i].c = node->children[i].c;
                children[i].child_off = htole64(child_off);
        }

        /* write node */
        node_off = ftello(trie->f);
        if (fwrite(&n, sizeof(struct trie_node_f), 1, trie->f) != 1)
                log_error("Failed to write sizeof struct trie_node_f to n in %s\n", "[udevadm-hwdb.c:trie_store_nodes]");
        trie->nodes_count++;

        /* append children array */
        if (node->children_count) {
                if (fwrite(children, sizeof(struct trie_child_entry_f), node->children_count, trie->f) != node->children_count)
                        log_error("Failed to write children_count in %s\n", "[udevadm-hwdb.c:trie_store_nodes]");
                trie->children_count += node->children_count;
                free(children);
        }

        /* append values array */
        for (i = 0; i < node->values_count; i++) {
                struct trie_value_entry_f v = {
                        .key_off = htole64(trie->strings_off + node->values[i].key_off),
                        .value_off = htole64(trie->strings_off + node->values[i].value_off),
                };

                if (fwrite(&v, sizeof(struct trie_value_entry_f), 1, trie->f) != 1)
                        log_error("Failed to write sizeof trie_value_entry_f to v in %s\n", "[udevadm-hwdb.c:trie_store_nodes]");
                trie->values_count++;
        }

        return node_off;
}

static int trie_store(struct trie *trie, const char *filename) {
        struct trie_f t = {
                .trie = trie,
        };
        char *filename_tmp;
        int64_t pos;
        int64_t root_off;
        int64_t size;
        struct trie_header_f h = {
                .signature = HWDB_SIG,
                .tool_version = htole64(atoi(VERSION)),
                .header_size = htole64(sizeof(struct trie_header_f)),
                .node_size = htole64(sizeof(struct trie_node_f)),
                .child_entry_size = htole64(sizeof(struct trie_child_entry_f)),
                .value_entry_size = htole64(sizeof(struct trie_value_entry_f)),
        };
        int err;

        /* calculate size of header, nodes, children entries, value entries */
        t.strings_off = sizeof(struct trie_header_f);
        trie_store_nodes_size(&t, trie->root);

        err = fopen_temporary(filename , &t.f, &filename_tmp);
        if (err < 0)
                return err;
        fchmod(fileno(t.f), 0444);

        /* write nodes */
        fseeko(t.f, sizeof(struct trie_header_f), SEEK_SET);
        root_off = trie_store_nodes(&t, trie->root);
        h.nodes_root_off = htole64(root_off);
        pos = ftello(t.f);
        h.nodes_len = htole64(pos - sizeof(struct trie_header_f));

        /* write string buffer */
        if (fwrite(trie->strings->buf, trie->strings->len, 1, t.f) != 1)
                log_error("Failed to write into trie->strings->buf in %s\n", "[udevadm-hwdb.c:trie_store]");
        h.strings_len = htole64(trie->strings->len);

        /* write header */
        size = ftello(t.f);
        h.file_size = htole64(size);
        fseeko(t.f, 0, SEEK_SET);
        if (fwrite(&h, sizeof(struct trie_header_f), 1, t.f) != 1)
                log_error("Failed to write into h in %s\n", "[udevadm-hwdb.c:trie_store]");
        err = ferror(t.f);
        if (err)
                err = -errno;
        fclose(t.f);
        if (err < 0 || rename(filename_tmp, filename) < 0) {
                unlink(filename_tmp);
                goto out;
        }

        log_debug("=== trie on-disk ===\n");
        log_debug("size:             %8llu bytes\n", (unsigned long long)size);
        log_debug("header:           %8zu bytes\n", sizeof(struct trie_header_f));
        log_debug("nodes:            %8llu bytes (%8llu)\n",
                  (unsigned long long)t.nodes_count * sizeof(struct trie_node_f), (unsigned long long)t.nodes_count);
        log_debug("child pointers:   %8llu bytes (%8llu)\n",
                  (unsigned long long)t.children_count * sizeof(struct trie_child_entry_f), (unsigned long long)t.children_count);
        log_debug("value pointers:   %8llu bytes (%8llu)\n",
                  (unsigned long long)t.values_count * sizeof(struct trie_value_entry_f), (unsigned long long)t.values_count);
        log_debug("string store:     %8llu bytes\n", (unsigned long long)trie->strings->len);
        log_debug("strings start:    %8llu\n", (unsigned long long) t.strings_off);
out:
        free(filename_tmp);
        return err;
}

static int insert_data(struct trie *trie, struct udev_list *match_list,
                       char *line, const char *filename) {
        char *value;
        struct udev_list_entry *entry;

        value = strchr(line, '=');
        if (!value) {
                log_error("Error, key/value pair expected but got '%s' in '%s':\n", line, filename);
                return -EINVAL;
        }

        value[0] = '\0';
        value++;

        if (line[0] == '\0' || value[0] == '\0') {
                log_error("Error, empty key or value '%s' in '%s':\n", line, filename);
                return -EINVAL;
        }

        udev_list_entry_foreach(entry, udev_list_get_entry(match_list))
                trie_insert(trie, trie->root, udev_list_entry_get_name(entry), line, value);

        return 0;
}

static int import_file(struct udev *udev, struct trie *trie, const char *filename) {
        enum {
                HW_MATCH,
                HW_DATA,
                HW_NONE,
        } state = HW_NONE;
        FILE *f;
        char line[LINE_MAX];
        struct udev_list match_list;

        udev_list_init(udev, &match_list, false);

        f = fopen(filename, "re");
        if (f == NULL)
                return -errno;

        while (fgets(line, sizeof(line), f)) {
                size_t len;
                char *pos;

                /* comment line */
                if (line[0] == '#')
                        continue;

                /* strip trailing comment */
                pos = strchr(line, '#');
                if (pos)
                        pos[0] = '\0';

                /* strip trailing whitespace */
                len = strlen(line);
                while (len > 0 && isspace(line[len-1]))
                        len--;
                line[len] = '\0';

                switch (state) {
                case HW_NONE:
                        if (len == 0)
                                break;

                        if (line[0] == ' ') {
                                log_error("Error, MATCH expected but got '%s' in '%s':\n", line, filename);
                                break;
                        }

                        /* start of record, first match */
                        state = HW_MATCH;
                        udev_list_entry_add(&match_list, line, NULL);
                        break;

                case HW_MATCH:
                        if (len == 0) {
                                log_error("Error, DATA expected but got empty line in '%s':\n", filename);
                                state = HW_NONE;
                                udev_list_cleanup(&match_list);
                                break;
                        }

                        /* another match */
                        if (line[0] != ' ') {
                                udev_list_entry_add(&match_list, line, NULL);
                                break;
                        }

                        /* first data */
                        state = HW_DATA;
                        insert_data(trie, &match_list, line, filename);
                        break;

                case HW_DATA:
                        /* end of record */
                        if (len == 0) {
                                state = HW_NONE;
                                udev_list_cleanup(&match_list);
                                break;
                        }

                        if (line[0] != ' ') {
                                log_error("Error, DATA expected but got '%s' in '%s':\n", line, filename);
                                state = HW_NONE;
                                udev_list_cleanup(&match_list);
                                break;
                        }

                        insert_data(trie, &match_list, line, filename);
                        break;
                };
        }

        fclose(f);
        udev_list_cleanup(&match_list);
        return 0;
}

static void help(void) {
        printf("Usage: udevadm hwdb OPTIONS\n"
               "  --update            update the hardware database\n"
               "  --test=<modalias>   query database and print result\n"
               "  --root=<path>       alternative root path in the filesystem\n"
               "  --help\n\n");
}
コード例 #6
0
ファイル: udev-node.c プロジェクト: OPSF/uClinux
static int update_link(struct udev_device *dev, const char *slink, int test)
{
	struct udev *udev = udev_device_get_udev(dev);
	struct udev_list_node dev_list;
	struct udev_list_entry *dev_entry;
	char target[UTIL_PATH_SIZE];
	int count;
	int priority = 0;
	int rc = 0;

	dbg(udev, "update symlink '%s' of '%s'\n", slink, udev_device_get_syspath(dev));

	udev_list_init(&dev_list);
	count = name_index_get_devices(udev, slink, &dev_list);
	if (count > 1)
		info(udev, "found %i devices with name '%s'\n", count, slink);

	/* if we don't have a reference, delete it */
	if (count <= 0) {
		info(udev, "no reference left, remove '%s'\n", slink);
		if (!test) {
			unlink(slink);
			util_delete_path(udev, slink);
		}
		goto out;
	}

	/* find the device with the highest priority */
	target[0] = '\0';
	udev_list_entry_foreach(dev_entry, udev_list_get_entry(&dev_list)) {
		const char *syspath;
		struct udev_device *dev_db;
		const char *devnode;

		syspath = udev_list_entry_get_name(dev_entry);
		dbg(udev, "found '%s' for '%s'\n", syspath, slink);

		/* did we find ourself? we win, if we have the same priority */
		if (strcmp(udev_device_get_syspath(dev), syspath) == 0) {
			dbg(udev, "compare (our own) priority of '%s' %i >= %i\n",
			    udev_device_get_devpath(dev), udev_device_get_devlink_priority(dev), priority);
			if (strcmp(udev_device_get_devnode(dev), slink) == 0) {
				info(udev, "'%s' is our device node, database inconsistent, skip link update\n",
				     udev_device_get_devnode(dev));
			} else if (target[0] == '\0' || udev_device_get_devlink_priority(dev) >= priority) {
				priority = udev_device_get_devlink_priority(dev);
				util_strlcpy(target, udev_device_get_devnode(dev), sizeof(target));
			}
			continue;
		}

		/* another device, read priority from database */
		dev_db = udev_device_new_from_syspath(udev, syspath);
		if (dev_db == NULL)
			continue;
		devnode = udev_device_get_devnode(dev_db);
		if (devnode != NULL) {
			if (strcmp(devnode, slink) == 0) {
				info(udev, "'%s' is a device node of '%s', skip link update\n",
				     devnode, syspath);
			} else {
				dbg(udev, "compare priority of '%s' %i > %i\n",
				    udev_device_get_devpath(dev_db),
				    udev_device_get_devlink_priority(dev_db),
				    priority);
				if (target[0] == '\0' || udev_device_get_devlink_priority(dev_db) > priority) {
					priority = udev_device_get_devlink_priority(dev_db);
					util_strlcpy(target, devnode, sizeof(target));
				}
			}
		}
		udev_device_unref(dev_db);
	}
	udev_list_cleanup_entries(udev, &dev_list);

	if (target[0] == '\0') {
		info(udev, "no current target for '%s' found\n", slink);
		rc = 1;
		goto out;
	}

	/* create symlink to the target with the highest priority */
	info(udev, "'%s' with target '%s' has the highest priority %i, create it\n", slink, target, priority);
	if (!test) {
		util_create_path(udev, slink);
		node_symlink(udev, target, slink);
	}
out:
	return rc;
}
コード例 #7
0
ファイル: udevadm-monitor.c プロジェクト: embe/systemd
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_unref_ struct udev_monitor *udev_monitor = NULL;
        _cleanup_udev_monitor_unref_ 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 const struct option options[] = {
                { "property",        no_argument,       NULL, 'p' },
                { "environment",     no_argument,       NULL, 'e' }, /* alias for -p */
                { "kernel",          no_argument,       NULL, 'k' },
                { "udev",            no_argument,       NULL, 'u' },
                { "subsystem-match", required_argument, NULL, 's' },
                { "tag-match",       required_argument, NULL, 't' },
                { "help",            no_argument,       NULL, 'h' },
                {}
        };

        udev_list_init(udev, &subsystem_match_list, true);
        udev_list_init(udev, &tag_match_list, true);

        while ((c = getopt_long(argc, argv, "pekus:t:h", options, NULL)) >= 0)
                switch (c) {
                case 'p':
                case 'e':
                        prop = true;
                        break;
                case 'k':
                        print_kernel = true;
                        break;
                case 'u':
                        print_udev = true;
                        break;
                case 's':
                        {
                                char subsys[UTIL_NAME_SIZE];
                                char *devtype;

                                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);
                        break;
                case 'h':
                        help();
                        return 0;
                default:
                        return 1;
                }

        if (!print_kernel && !print_udev) {
                print_kernel = true;
                print_udev = true;
        }

        /* set signal handlers */
        act.sa_handler = sig_handler;
        act.sa_flags = SA_RESTART;
        sigaction(SIGINT, &act, NULL);
        sigaction(SIGTERM, &act, NULL);
        sigemptyset(&mask);
        sigaddset(&mask, SIGINT);
        sigaddset(&mask, SIGTERM);
        sigprocmask(SIG_UNBLOCK, &mask, NULL);

        /* Callers are expecting to see events as they happen: Line buffering */
        setlinebuf(stdout);

        fd_ep = epoll_create1(EPOLL_CLOEXEC);
        if (fd_ep < 0) {
                log_error_errno(errno, "error creating epoll fd: %m");
                return 1;
        }

        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;
                }

                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;
                }

                printf("KERNEL - the kernel uevent\n");
        }
        printf("\n");

        while (!udev_exit) {
                int fdcount;
                struct epoll_event ev[4];
                int i;

                fdcount = epoll_wait(fd_ep, ev, ELEMENTSOF(ev), -1);
                if (fdcount < 0) {
                        if (errno != EINTR)
                                fprintf(stderr, "error receiving uevent message: %m\n");
                        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);
                        }
                }
        }

        return 0;
}
コード例 #8
0
ファイル: libudev.c プロジェクト: StarchLinux/udev
/**
 * udev_new:
 *
 * Create udev library context.
 *
 * The initial refcount is 1, and needs to be decremented to
 * release the resources of the udev library context.
 *
 * Returns: a new udev library context
 **/
struct udev *udev_new(void)
{
	struct udev *udev;
	const char *env;
	char *config_file;
	FILE *f;

	udev = calloc(1, sizeof(struct udev));
	if (udev == NULL)
		return NULL;
	udev->refcount = 1;
	udev->log_fn = log_stderr;
	udev->log_priority = LOG_ERR;
	udev_list_init(&udev->properties_list);
	udev->run = 1;
	udev->dev_path = strdup(UDEV_PREFIX "/dev");
	udev->sys_path = strdup("/sys");
	config_file = strdup(SYSCONFDIR "/udev/udev.conf");
	if (udev->dev_path == NULL ||
	    udev->sys_path == NULL ||
	    config_file == NULL)
		goto err;

	/* settings by environment and config file */
	env = getenv("SYSFS_PATH");
	if (env != NULL) {
		free(udev->sys_path);
		udev->sys_path = strdup(env);
		util_remove_trailing_chars(udev->sys_path, '/');
		udev_add_property(udev, "SYSFS_PATH", udev->sys_path);
	}

	env = getenv("UDEV_RUN");
	if (env != NULL && strcmp(env, "0") == 0)
		udev->run = 0;

	env = getenv("UDEV_CONFIG_FILE");
	if (env != NULL) {
		free(config_file);
		config_file = strdup(env);
		util_remove_trailing_chars(config_file, '/');
	}
	if (config_file == NULL)
		goto err;
	f = fopen(config_file, "r");
	if (f != NULL) {
		char line[UTIL_LINE_SIZE];
		int line_nr = 0;

		while (fgets(line, sizeof(line), f)) {
			size_t len;
			char *key;
			char *val;

			line_nr++;

			/* find key */
			key = line;
			while (isspace(key[0]))
				key++;

			/* comment or empty line */
			if (key[0] == '#' || key[0] == '\0')
				continue;

			/* split key/value */
			val = strchr(key, '=');
			if (val == NULL) {
				err(udev, "missing <key>=<value> in '%s'[%i], skip line\n", config_file, line_nr);
				continue;
			}
			val[0] = '\0';
			val++;

			/* find value */
			while (isspace(val[0]))
				val++;

			/* terminate key */
			len = strlen(key);
			if (len == 0)
				continue;
			while (isspace(key[len-1]))
				len--;
			key[len] = '\0';

			/* terminate value */
			len = strlen(val);
			if (len == 0)
				continue;
			while (isspace(val[len-1]))
				len--;
			val[len] = '\0';

			if (len == 0)
				continue;

			/* unquote */
			if (val[0] == '"' || val[0] == '\'') {
				if (val[len-1] != val[0]) {
					err(udev, "inconsistent quoting in '%s'[%i], skip line\n", config_file, line_nr);
					continue;
				}
				val[len-1] = '\0';
				val++;
			}

			if (strcasecmp(key, "udev_log") == 0) {
				udev_set_log_priority(udev, util_log_priority(val));
				continue;
			}
			if (strcasecmp(key, "udev_root") == 0) {
				free(udev->dev_path);
				udev->dev_path = strdup(val);
				util_remove_trailing_chars(udev->dev_path, '/');
				continue;
			}
			if (strcasecmp(key, "udev_rules") == 0) {
				free(udev->rules_path);
				udev->rules_path = strdup(val);
				util_remove_trailing_chars(udev->rules_path, '/');
				continue;
			}
		}
		fclose(f);
	}

	env = getenv("UDEV_ROOT");
	if (env != NULL) {
		free(udev->dev_path);
		udev->dev_path = strdup(env);
		util_remove_trailing_chars(udev->dev_path, '/');
		udev_add_property(udev, "UDEV_ROOT", udev->dev_path);
	}

	env = getenv("UDEV_LOG");
	if (env != NULL)
		udev_set_log_priority(udev, util_log_priority(env));

	if (udev->dev_path == NULL || udev->sys_path == NULL)
		goto err;
	dbg(udev, "context %p created\n", udev);
	dbg(udev, "log_priority=%d\n", udev->log_priority);
	dbg(udev, "config_file='%s'\n", config_file);
	dbg(udev, "dev_path='%s'\n", udev->dev_path);
	dbg(udev, "sys_path='%s'\n", udev->sys_path);
	if (udev->rules_path != NULL)
		dbg(udev, "rules_path='%s'\n", udev->rules_path);
	free(config_file);
	return udev;
err:
	free(config_file);
	err(udev, "context creation failed\n");
	udev_unref(udev);
	return NULL;
}
コード例 #9
0
ファイル: libudev.c プロジェクト: chuanchang/systemd
/**
 * udev_new:
 *
 * Create udev library context. This reads the udev configuration
 * file, and fills in the default values.
 *
 * The initial refcount is 1, and needs to be decremented to
 * release the resources of the udev library context.
 *
 * Returns: a new udev library context
 **/
_public_ struct udev *udev_new(void)
{
        struct udev *udev;
        const char *env;
        FILE *f;

        udev = calloc(1, sizeof(struct udev));
        if (udev == NULL)
                return NULL;
        udev->refcount = 1;
        udev->log_fn = log_stderr;
        udev->log_priority = LOG_INFO;
        udev_list_init(udev, &udev->properties_list, true);

        f = fopen("/etc/udev/udev.conf", "re");
        if (f != NULL) {
                char line[UTIL_LINE_SIZE];
                int line_nr = 0;

                while (fgets(line, sizeof(line), f)) {
                        size_t len;
                        char *key;
                        char *val;

                        line_nr++;

                        /* find key */
                        key = line;
                        while (isspace(key[0]))
                                key++;

                        /* comment or empty line */
                        if (key[0] == '#' || key[0] == '\0')
                                continue;

                        /* split key/value */
                        val = strchr(key, '=');
                        if (val == NULL) {
                                udev_err(udev, "missing <key>=<value> in /etc/udev/udev.conf[%i]; skip line\n", line_nr);
                                continue;
                        }
                        val[0] = '\0';
                        val++;

                        /* find value */
                        while (isspace(val[0]))
                                val++;

                        /* terminate key */
                        len = strlen(key);
                        if (len == 0)
                                continue;
                        while (isspace(key[len-1]))
                                len--;
                        key[len] = '\0';

                        /* terminate value */
                        len = strlen(val);
                        if (len == 0)
                                continue;
                        while (isspace(val[len-1]))
                                len--;
                        val[len] = '\0';

                        if (len == 0)
                                continue;

                        /* unquote */
                        if (val[0] == '"' || val[0] == '\'') {
                                if (val[len-1] != val[0]) {
                                        udev_err(udev, "inconsistent quoting in /etc/udev/udev.conf[%i]; skip line\n", line_nr);
                                        continue;
                                }
                                val[len-1] = '\0';
                                val++;
                        }

                        if (streq(key, "udev_log")) {
                                udev_set_log_priority(udev, util_log_priority(val));
                                continue;
                        }
                }
                fclose(f);
        }

        /* environment overrides config */
        env = secure_getenv("UDEV_LOG");
        if (env != NULL)
                udev_set_log_priority(udev, util_log_priority(env));

        return udev;
}