mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
libutil: Introduce util_udev
Move code to read udev files from zdev into a utility library for use by other tools. Acked-by: Jan Höppner <hoeppner@linux.ibm.com> Reviewed-by: Peter Oberparleiter <oberpar@linux.ibm.com> Reviewed-by: Tony Krowiak <akrowiak@linux.ibm.com> Signed-off-by: Matthew Rosato <mjrosato@linux.ibm.com> Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
This commit is contained in:
committed by
Jan Höppner
parent
f64b4087dd
commit
6f7982dae5
44
include/lib/util_udev.h
Normal file
44
include/lib/util_udev.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* @defgroup util_udev_h util_udev: UDEV interface
|
||||
* @{
|
||||
* @brief Work with UDEV files
|
||||
*
|
||||
* Copyright IBM Corp. 2022
|
||||
*
|
||||
* s390-tools is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the MIT license. See LICENSE for details.
|
||||
*/
|
||||
|
||||
#ifndef LIB_UTIL_UDEV_H
|
||||
#define LIB_UTIL_UDEV_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "lib/util_exit_code.h"
|
||||
#include "lib/util_list.h"
|
||||
|
||||
/* Single key-operator-value entry in a udev rule line.*/
|
||||
struct util_udev_entry_node {
|
||||
struct util_list_node node;
|
||||
char *key;
|
||||
char *op;
|
||||
char *value;
|
||||
};
|
||||
|
||||
/* Single udev line in a udev rule file. */
|
||||
struct util_udev_line_node {
|
||||
struct util_list_node node;
|
||||
struct util_list entries;
|
||||
char *line;
|
||||
};
|
||||
|
||||
/* Udev rule file. */
|
||||
struct util_udev_file {
|
||||
struct util_list lines;
|
||||
};
|
||||
|
||||
util_exit_code_t util_udev_read_file(const char *path,
|
||||
struct util_udev_file **file_ptr);
|
||||
void util_udev_free_file(struct util_udev_file *file);
|
||||
void util_udev_file_print(struct util_udev_file *file);
|
||||
|
||||
#endif /** LIB_UTIL_UDEV_H @} */
|
||||
362
libutil/util_udev.c
Normal file
362
libutil/util_udev.c
Normal file
@@ -0,0 +1,362 @@
|
||||
/*
|
||||
* util - Utility function library
|
||||
*
|
||||
* UDEV helper functions
|
||||
*
|
||||
* Copyright IBM Corp. 2022
|
||||
*
|
||||
* 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 <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_exit_code.h"
|
||||
#include "lib/util_file.h"
|
||||
#include "lib/util_libc.h"
|
||||
#include "lib/util_list.h"
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
/* Create a newly allocated udev entry. */
|
||||
static struct util_udev_entry_node *util_udev_entry_node_new(const char *key,
|
||||
const char *op,
|
||||
const char *value)
|
||||
{
|
||||
struct util_udev_entry_node *entry;
|
||||
|
||||
entry = util_zalloc(sizeof(struct util_udev_entry_node));
|
||||
entry->key = util_strdup(key);
|
||||
entry->op = util_strdup(op);
|
||||
entry->value = util_strdup(value);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Release resources associated with udev entry. */
|
||||
static void util_udev_entry_node_free(struct util_udev_entry_node *entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
free(entry->key);
|
||||
free(entry->op);
|
||||
free(entry->value);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/* Create a newly allocated udev line. */
|
||||
static struct util_udev_line_node *util_udev_line_node_new(void)
|
||||
{
|
||||
struct util_udev_line_node *line;
|
||||
|
||||
line = util_zalloc(sizeof(struct util_udev_line_node));
|
||||
util_list_init(&line->entries, struct util_udev_entry_node, node);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/* Release resources associated with udev line. */
|
||||
static void util_udev_line_node_free(struct util_udev_line_node *line)
|
||||
{
|
||||
struct util_udev_entry_node *e, *n;
|
||||
|
||||
if (!line)
|
||||
return;
|
||||
util_list_iterate_safe(&line->entries, e, n) {
|
||||
util_list_remove(&line->entries, e);
|
||||
util_udev_entry_node_free(e);
|
||||
}
|
||||
free(line->line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
/* Create a newly allocated udev file. */
|
||||
static struct util_udev_file *util_udev_file_new(void)
|
||||
{
|
||||
struct util_udev_file *file;
|
||||
|
||||
file = util_zalloc(sizeof(struct util_udev_file));
|
||||
util_list_init(&file->lines, struct util_udev_line_node, node);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Release resources associated with udev file.
|
||||
*
|
||||
* @param[in, out] file Udev file structure to be freed
|
||||
*/
|
||||
void util_udev_free_file(struct util_udev_file *file)
|
||||
{
|
||||
struct util_udev_line_node *l, *n;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
util_list_iterate_safe(&file->lines, l, n) {
|
||||
util_list_remove(&file->lines, l);
|
||||
util_udev_line_node_free(l);
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the contents of a udev file to stdout. Used for debugging.
|
||||
*
|
||||
* @param[in] file Udev file structure to print
|
||||
*/
|
||||
void util_udev_file_print(struct util_udev_file *file)
|
||||
{
|
||||
struct util_udev_line_node *l;
|
||||
struct util_udev_entry_node *e;
|
||||
|
||||
printf("util_udev_file at %p\n", (void *) file);
|
||||
if (!file)
|
||||
return;
|
||||
util_list_iterate(&file->lines, l) {
|
||||
printf(" util_udev_line_node at %p\n", (void *) l);
|
||||
printf(" line='%s'\n", l->line);
|
||||
util_list_iterate(&l->entries, e) {
|
||||
printf(" util_udev_entry at %p\n", (void *) e);
|
||||
printf(" '%s' '%s' '%s'\n", e->key, e->op,
|
||||
e->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void skip_whitespace(const char **s_ptr)
|
||||
{
|
||||
const char *s = *s_ptr;
|
||||
|
||||
while (*s && isspace(*s))
|
||||
s++;
|
||||
|
||||
*s_ptr = s;
|
||||
}
|
||||
|
||||
static char *parse_key(const char **s_ptr)
|
||||
{
|
||||
const char *s, *e;
|
||||
char *key;
|
||||
|
||||
s = *s_ptr;
|
||||
/* Parse \w+(\{[^\}]*\})? */
|
||||
e = s;
|
||||
while (*e && (isalnum(*e) || *e == '_'))
|
||||
e++;
|
||||
if (*e == '{') {
|
||||
while (*e && *e != '}')
|
||||
e++;
|
||||
if (*e == '}')
|
||||
e++;
|
||||
}
|
||||
|
||||
if (e == s)
|
||||
return NULL;
|
||||
|
||||
/* s points to key start, e to character after key end. */
|
||||
key = util_zalloc(e - s + 1);
|
||||
memcpy(key, s, e - s);
|
||||
|
||||
*s_ptr = e;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static char *parse_op(const char **s_ptr)
|
||||
{
|
||||
const char *ops[] = { "==", "!=", "=", "+=", ":=", NULL };
|
||||
const char *entry;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
entry = *s_ptr;
|
||||
for (i = 0; ops[i]; i++) {
|
||||
len = strlen(ops[i]);
|
||||
if (strncmp(entry, ops[i], len) == 0) {
|
||||
*s_ptr += len;
|
||||
return util_strdup(ops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *parse_value(const char **s_ptr)
|
||||
{
|
||||
const char *s, *e;
|
||||
char *value;
|
||||
|
||||
/* Parse: ^\s*(.*)\s*$ */
|
||||
s = *s_ptr;
|
||||
skip_whitespace(&s);
|
||||
e = s;
|
||||
while (*e)
|
||||
e++;
|
||||
e--;
|
||||
while (e > s && isspace(*e))
|
||||
e--;
|
||||
e++;
|
||||
|
||||
*s_ptr = e;
|
||||
|
||||
/* Remove quotes. */
|
||||
if ((*s == '"' && *(e - 1) == '"') ||
|
||||
(*s == '\'' && *(e - 1) == '\'')) {
|
||||
s++;
|
||||
e--;
|
||||
}
|
||||
|
||||
/* s points to value start, e to character after value end. */
|
||||
value = util_zalloc(e - s + 1);
|
||||
memcpy(value, s, e - s);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool parse_util_udev_entry(struct util_udev_line_node *line,
|
||||
const char *entry)
|
||||
{
|
||||
char *key = NULL, *op = NULL, *value = NULL;
|
||||
struct util_udev_entry_node *e;
|
||||
bool rc = false;
|
||||
|
||||
/* Parse: ^\s*(\w+)\s*(==|!=|=|\+=|:=)\s*"?([^"]*)"\s*$ */
|
||||
|
||||
/* Parse key. */
|
||||
skip_whitespace(&entry);
|
||||
key = parse_key(&entry);
|
||||
if (!key)
|
||||
goto out;
|
||||
|
||||
/* Parse operator. */
|
||||
skip_whitespace(&entry);
|
||||
op = parse_op(&entry);
|
||||
if (!op)
|
||||
goto out;
|
||||
|
||||
/* Parse value. */
|
||||
skip_whitespace(&entry);
|
||||
value = parse_value(&entry);
|
||||
if (!value)
|
||||
goto out;
|
||||
skip_whitespace(&entry);
|
||||
|
||||
/* Check for unrecognized characters at end of entry. */
|
||||
if (*entry != 0)
|
||||
goto out;
|
||||
|
||||
/* Add entry to list. */
|
||||
e = util_udev_entry_node_new(key, op, value);
|
||||
util_list_add_tail(&line->entries, e);
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
free(key);
|
||||
free(op);
|
||||
free(value);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void replace_unquoted(char *s, char from, char to)
|
||||
{
|
||||
char quoted = 0;
|
||||
|
||||
for (; *s; s++) {
|
||||
if (quoted) {
|
||||
/* Skip until quote end is found. */
|
||||
if (*s == quoted)
|
||||
quoted = 0;
|
||||
continue;
|
||||
}
|
||||
if (*s == '"' || *s == '\'') {
|
||||
quoted = *s;
|
||||
continue;
|
||||
}
|
||||
if (*s == from)
|
||||
*s = to;
|
||||
}
|
||||
}
|
||||
|
||||
static bool parse_util_udev_line(struct util_udev_file *file, const char *line)
|
||||
{
|
||||
char *copy, *curr, *next;
|
||||
struct util_udev_line_node *l;
|
||||
int i;
|
||||
bool result = true;
|
||||
|
||||
l = util_udev_line_node_new();
|
||||
l->line = util_strdup(line);
|
||||
|
||||
/* Check for empty lines and comment lines. */
|
||||
for (i = 0; line[i] && isspace(line[i]); i++);
|
||||
if (line[i] == 0 || line[i] == '#')
|
||||
goto ok;
|
||||
|
||||
/* Parse each comma-separated entry. */
|
||||
copy = util_strdup(line);
|
||||
|
||||
/* A hack to differentiate between quoted and unquoted commas. */
|
||||
replace_unquoted(copy, ',', 1);
|
||||
|
||||
next = copy;
|
||||
while ((curr = strsep(&next, "\1"))) {
|
||||
if (!parse_util_udev_entry(l, curr)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
|
||||
ok:
|
||||
if (result)
|
||||
util_list_add_tail(&file->lines, l);
|
||||
else
|
||||
util_udev_line_node_free(l);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new util_udev_file structure and read the contents of a specified
|
||||
* udev file into that structure.
|
||||
*
|
||||
* @param[in] path Path to the udev file that will be read in
|
||||
* @param[in, out] file_ptr A buffer to store resulting udev file structure
|
||||
*
|
||||
* @retval 0 Udev file read successfully
|
||||
* @retval UTIL_EXIT_RUNTIME_ERROR Error reading the udev file
|
||||
*/
|
||||
util_exit_code_t util_udev_read_file(const char *path,
|
||||
struct util_udev_file **file_ptr)
|
||||
{
|
||||
char *text, *curr, *next;
|
||||
struct util_udev_file *file;
|
||||
int once = 0;
|
||||
|
||||
text = util_file_read_text_file(path, 0);
|
||||
if (!text)
|
||||
return UTIL_EXIT_RUNTIME_ERROR;
|
||||
file = util_udev_file_new();
|
||||
|
||||
/* Iterate over each line. */
|
||||
next = text;
|
||||
while ((curr = strsep(&next, "\n"))) {
|
||||
if (parse_util_udev_line(file, curr))
|
||||
continue;
|
||||
if (!once) {
|
||||
once = 1;
|
||||
fprintf(stderr, "Unrecognized udev rule in %s:\n",
|
||||
path);
|
||||
}
|
||||
fprintf(stderr, "%s\n", curr);
|
||||
}
|
||||
|
||||
free(text);
|
||||
*file_ptr = file;
|
||||
|
||||
return UTIL_EXIT_OK;
|
||||
}
|
||||
@@ -11,7 +11,7 @@
|
||||
#define UDEV_H
|
||||
|
||||
#include "lib/util_list.h"
|
||||
#include "exit_code.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
struct attrib;
|
||||
struct setting_list;
|
||||
@@ -19,30 +19,7 @@ struct setting_list;
|
||||
extern int udev_need_settle;
|
||||
extern int udev_no_settle;
|
||||
|
||||
/* Single key-operator-value entry in a udev rule line.*/
|
||||
struct udev_entry_node {
|
||||
struct util_list_node node;
|
||||
char *key;
|
||||
char *op;
|
||||
char *value;
|
||||
};
|
||||
|
||||
/* Single udev line in a udev rule file. */
|
||||
struct udev_line_node {
|
||||
struct util_list_node node;
|
||||
struct util_list entries;
|
||||
char *line;
|
||||
};
|
||||
|
||||
/* Udev rule file. */
|
||||
struct udev_file {
|
||||
struct util_list lines;
|
||||
};
|
||||
|
||||
exit_code_t udev_read_file(const char *, struct udev_file **);
|
||||
bool udev_file_is_empty(struct udev_file *file);
|
||||
void udev_free_file(struct udev_file *);
|
||||
void udev_file_print(struct udev_file *);
|
||||
bool udev_file_is_empty(struct util_udev_file *file);
|
||||
|
||||
void udev_get_device_ids(const char *type, struct util_list *list,
|
||||
bool autoconf);
|
||||
@@ -51,7 +28,7 @@ exit_code_t udev_remove_rule(const char *type, const char *id, bool autoconf);
|
||||
void udev_settle(void);
|
||||
|
||||
void udev_add_internal_from_entry(struct setting_list *list,
|
||||
struct udev_entry_node *entry,
|
||||
struct util_udev_entry_node *entry,
|
||||
struct attrib **attribs);
|
||||
|
||||
#endif /* UDEV_H */
|
||||
|
||||
327
zdev/src/udev.c
327
zdev/src/udev.c
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
#include "attrib.h"
|
||||
#include "ccw.h"
|
||||
@@ -26,330 +27,10 @@
|
||||
int udev_need_settle = 0;
|
||||
int udev_no_settle;
|
||||
|
||||
/* Create a newly allocated udev entry. */
|
||||
static struct udev_entry_node *udev_entry_node_new(const char *key,
|
||||
const char *op,
|
||||
const char *value)
|
||||
{
|
||||
struct udev_entry_node *entry;
|
||||
|
||||
entry = misc_malloc(sizeof(struct udev_entry_node));
|
||||
entry->key = misc_strdup(key);
|
||||
entry->op = misc_strdup(op);
|
||||
entry->value = misc_strdup(value);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Release resources associated with udev entry. */
|
||||
static void udev_entry_node_free(struct udev_entry_node *entry)
|
||||
{
|
||||
if (!entry)
|
||||
return;
|
||||
free(entry->key);
|
||||
free(entry->op);
|
||||
free(entry->value);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
/* Create a newly allocated udev line. */
|
||||
static struct udev_line_node *udev_line_node_new(void)
|
||||
{
|
||||
struct udev_line_node *line;
|
||||
|
||||
line = misc_malloc(sizeof(struct udev_line_node));
|
||||
util_list_init(&line->entries, struct udev_entry_node, node);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
/* Release resources associated with udev line. */
|
||||
static void udev_line_node_free(struct udev_line_node *line)
|
||||
{
|
||||
struct udev_entry_node *e, *n;
|
||||
|
||||
if (!line)
|
||||
return;
|
||||
util_list_iterate_safe(&line->entries, e, n) {
|
||||
util_list_remove(&line->entries, e);
|
||||
udev_entry_node_free(e);
|
||||
}
|
||||
free(line->line);
|
||||
free(line);
|
||||
}
|
||||
|
||||
/* Create a newly allocated udev file. */
|
||||
static struct udev_file *udev_file_new(void)
|
||||
{
|
||||
struct udev_file *file;
|
||||
|
||||
file = misc_malloc(sizeof(struct udev_file));
|
||||
util_list_init(&file->lines, struct udev_line_node, node);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
/* Release resources associated with udev file. */
|
||||
void udev_free_file(struct udev_file *file)
|
||||
{
|
||||
struct udev_line_node *l, *n;
|
||||
|
||||
if (!file)
|
||||
return;
|
||||
util_list_iterate_safe(&file->lines, l, n) {
|
||||
util_list_remove(&file->lines, l);
|
||||
udev_line_node_free(l);
|
||||
}
|
||||
free(file);
|
||||
}
|
||||
|
||||
/* Used for debugging. */
|
||||
void udev_file_print(struct udev_file *file)
|
||||
{
|
||||
struct udev_line_node *l;
|
||||
struct udev_entry_node *e;
|
||||
|
||||
printf("udev_file at %p\n", (void *) file);
|
||||
if (!file)
|
||||
return;
|
||||
util_list_iterate(&file->lines, l) {
|
||||
printf(" udev_line_node at %p\n", (void *) l);
|
||||
printf(" line='%s'\n", l->line);
|
||||
util_list_iterate(&l->entries, e) {
|
||||
printf(" udev_entry at %p\n", (void *) e);
|
||||
printf(" '%s' '%s' '%s'\n", e->key, e->op,
|
||||
e->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void skip_whitespace(const char **s_ptr)
|
||||
{
|
||||
const char *s = *s_ptr;
|
||||
|
||||
while (*s && isspace(*s))
|
||||
s++;
|
||||
|
||||
*s_ptr = s;
|
||||
}
|
||||
|
||||
static char *parse_key(const char **s_ptr)
|
||||
{
|
||||
const char *s, *e;
|
||||
char *key;
|
||||
|
||||
s = *s_ptr;
|
||||
/* Parse \w+(\{[^\}]*\})? */
|
||||
e = s;
|
||||
while (*e && (isalnum(*e) || *e == '_'))
|
||||
e++;
|
||||
if (*e == '{') {
|
||||
while (*e && *e != '}')
|
||||
e++;
|
||||
if (*e == '}')
|
||||
e++;
|
||||
}
|
||||
|
||||
if (e == s)
|
||||
return NULL;
|
||||
|
||||
/* s points to key start, e to character after key end. */
|
||||
key = misc_malloc(e - s + 1);
|
||||
memcpy(key, s, e - s);
|
||||
|
||||
*s_ptr = e;
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
static char *parse_op(const char **s_ptr)
|
||||
{
|
||||
const char *ops[] = { "==", "!=", "=", "+=", ":=", NULL };
|
||||
const char *entry;
|
||||
size_t len;
|
||||
int i;
|
||||
|
||||
entry = *s_ptr;
|
||||
for (i = 0; ops[i]; i++) {
|
||||
len = strlen(ops[i]);
|
||||
if (strncmp(entry, ops[i], len) == 0) {
|
||||
*s_ptr += len;
|
||||
return misc_strdup(ops[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *parse_value(const char **s_ptr)
|
||||
{
|
||||
const char *s, *e;
|
||||
char *value;
|
||||
|
||||
/* Parse: ^\s*(.*)\s*$ */
|
||||
s = *s_ptr;
|
||||
skip_whitespace(&s);
|
||||
e = s;
|
||||
while (*e)
|
||||
e++;
|
||||
e--;
|
||||
while (e > s && isspace(*e))
|
||||
e--;
|
||||
e++;
|
||||
|
||||
*s_ptr = e;
|
||||
|
||||
/* Remove quotes. */
|
||||
if ((*s == '"' && *(e - 1) == '"') ||
|
||||
(*s == '\'' && *(e - 1) == '\'')) {
|
||||
s++;
|
||||
e--;
|
||||
}
|
||||
|
||||
/* s points to value start, e to character after value end. */
|
||||
value = misc_malloc(e - s + 1);
|
||||
memcpy(value, s, e - s);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool parse_udev_entry(struct udev_line_node *line, const char *entry)
|
||||
{
|
||||
char *key = NULL, *op = NULL, *value = NULL;
|
||||
struct udev_entry_node *e;
|
||||
bool rc = false;
|
||||
|
||||
/* Parse: ^\s*(\w+)\s*(==|!=|=|\+=|:=)\s*"?([^"]*)"\s*$ */
|
||||
|
||||
/* Parse key. */
|
||||
skip_whitespace(&entry);
|
||||
key = parse_key(&entry);
|
||||
if (!key)
|
||||
goto out;
|
||||
|
||||
/* Parse operator. */
|
||||
skip_whitespace(&entry);
|
||||
op = parse_op(&entry);
|
||||
if (!op)
|
||||
goto out;
|
||||
|
||||
/* Parse value. */
|
||||
skip_whitespace(&entry);
|
||||
value = parse_value(&entry);
|
||||
if (!value)
|
||||
goto out;
|
||||
skip_whitespace(&entry);
|
||||
|
||||
/* Check for unrecognized characters at end of entry. */
|
||||
if (*entry != 0)
|
||||
goto out;
|
||||
|
||||
/* Add entry to list. */
|
||||
e = udev_entry_node_new(key, op, value);
|
||||
util_list_add_tail(&line->entries, e);
|
||||
rc = true;
|
||||
|
||||
out:
|
||||
free(key);
|
||||
free(op);
|
||||
free(value);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void replace_unquoted(char *s, char from, char to)
|
||||
{
|
||||
char quoted = 0;
|
||||
|
||||
for (; *s; s++) {
|
||||
if (quoted) {
|
||||
/* Skip until quote end is found. */
|
||||
if (*s == quoted)
|
||||
quoted = 0;
|
||||
continue;
|
||||
}
|
||||
if (*s == '"' || *s == '\'') {
|
||||
quoted = *s;
|
||||
continue;
|
||||
}
|
||||
if (*s == from)
|
||||
*s = to;
|
||||
}
|
||||
}
|
||||
|
||||
static bool parse_udev_line(struct udev_file *file, const char *line)
|
||||
{
|
||||
char *copy, *curr, *next;
|
||||
struct udev_line_node *l;
|
||||
int i;
|
||||
bool result = true;
|
||||
|
||||
l = udev_line_node_new();
|
||||
l->line = misc_strdup(line);
|
||||
|
||||
/* Check for empty lines and comment lines. */
|
||||
for (i = 0; line[i] && isspace(line[i]); i++);
|
||||
if (line[i] == 0 || line[i] == '#')
|
||||
goto ok;
|
||||
|
||||
/* Parse each comma-separated entry. */
|
||||
copy = misc_strdup(line);
|
||||
|
||||
/* A hack to differentiate between quoted and unquoted commas. */
|
||||
replace_unquoted(copy, ',', 1);
|
||||
|
||||
next = copy;
|
||||
while ((curr = strsep(&next, "\1"))) {
|
||||
if (!parse_udev_entry(l, curr)) {
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(copy);
|
||||
|
||||
ok:
|
||||
if (result)
|
||||
util_list_add_tail(&file->lines, l);
|
||||
else
|
||||
udev_line_node_free(l);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Read the contents of a udev rule file. */
|
||||
exit_code_t udev_read_file(const char *path, struct udev_file **file_ptr)
|
||||
{
|
||||
char *text, *curr, *next;
|
||||
struct udev_file *file;
|
||||
int once = 0;
|
||||
|
||||
text = misc_read_text_file(path, 0, err_print);
|
||||
if (!text)
|
||||
return EXIT_RUNTIME_ERROR;
|
||||
file = udev_file_new();
|
||||
|
||||
/* Iterate over each line. */
|
||||
next = text;
|
||||
while ((curr = strsep(&next, "\n"))) {
|
||||
if (parse_udev_line(file, curr))
|
||||
continue;
|
||||
if (!once) {
|
||||
once = 1;
|
||||
verb("Unrecognized udev rule format in %s:\n", path);
|
||||
}
|
||||
verb("%s\n", curr);
|
||||
}
|
||||
|
||||
free(text);
|
||||
*file_ptr = file;
|
||||
|
||||
return EXIT_OK;
|
||||
}
|
||||
|
||||
/* Check if a udev file does not contain any statements. */
|
||||
bool udev_file_is_empty(struct udev_file *file)
|
||||
bool udev_file_is_empty(struct util_udev_file *file)
|
||||
{
|
||||
struct udev_line_node *l;
|
||||
struct util_udev_line_node *l;
|
||||
|
||||
if (!file)
|
||||
return true;
|
||||
@@ -428,7 +109,7 @@ void udev_settle(void)
|
||||
/* 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 udev_entry_node *entry,
|
||||
struct util_udev_entry_node *entry,
|
||||
struct attrib **attribs)
|
||||
{
|
||||
char *copy, *name, *end, *u;
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
#include "attrib.h"
|
||||
#include "ccw.h"
|
||||
@@ -44,7 +45,7 @@ bool udev_ccw_exists(const char *type, const char *id, bool autoconf)
|
||||
}
|
||||
|
||||
static void add_setting_from_entry(struct setting_list *list,
|
||||
struct udev_entry_node *entry,
|
||||
struct util_udev_entry_node *entry,
|
||||
struct attrib **attribs)
|
||||
{
|
||||
char *copy, *name, *end;
|
||||
@@ -79,12 +80,12 @@ out:
|
||||
}
|
||||
|
||||
/* Extract CCW device settings from a CCW device udev rule file. */
|
||||
static void udev_file_get_settings(struct udev_file *file,
|
||||
static void udev_file_get_settings(struct util_udev_file *file,
|
||||
struct attrib **attribs,
|
||||
struct setting_list *list)
|
||||
{
|
||||
struct udev_line_node *line;
|
||||
struct udev_entry_node *entry;
|
||||
struct util_udev_line_node *line;
|
||||
struct util_udev_entry_node *entry;
|
||||
|
||||
util_list_iterate(&file->lines, line) {
|
||||
entry = util_list_start(&line->entries);
|
||||
@@ -100,12 +101,12 @@ exit_code_t udev_ccw_read_device(struct device *dev, bool autoconf)
|
||||
struct subtype *st = dev->subtype;
|
||||
struct device_state *state = autoconf ? &dev->autoconf :
|
||||
&dev->persistent;
|
||||
struct udev_file *file = NULL;
|
||||
struct util_udev_file *file = NULL;
|
||||
exit_code_t rc;
|
||||
char *path;
|
||||
|
||||
path = path_get_udev_rule(st->name, dev->id, autoconf);
|
||||
rc = udev_read_file(path, &file);
|
||||
rc = (exit_code_t) util_udev_read_file(path, &file);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (udev_file_is_empty(file)) {
|
||||
@@ -115,7 +116,7 @@ exit_code_t udev_ccw_read_device(struct device *dev, bool autoconf)
|
||||
udev_file_get_settings(file, st->dev_attribs, state->settings);
|
||||
state->exists = 1;
|
||||
}
|
||||
udev_free_file(file);
|
||||
util_udev_free_file(file);
|
||||
|
||||
out:
|
||||
free(path);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
#include "attrib.h"
|
||||
#include "ccwgroup.h"
|
||||
@@ -63,7 +64,7 @@ bool udev_ccwgroup_exists(const char *type, const char *id, bool autoconf)
|
||||
}
|
||||
|
||||
static void add_setting_from_entry(struct setting_list *list,
|
||||
struct udev_entry_node *entry,
|
||||
struct util_udev_entry_node *entry,
|
||||
struct attrib **attribs)
|
||||
{
|
||||
char *copy, *name, *end;
|
||||
@@ -98,12 +99,12 @@ out:
|
||||
}
|
||||
|
||||
/* Extract CCWGROUP device settings from a CCWGROUP device udev rule file. */
|
||||
static void udev_file_get_settings(struct udev_file *file,
|
||||
static void udev_file_get_settings(struct util_udev_file *file,
|
||||
struct attrib **attribs,
|
||||
struct setting_list *list)
|
||||
{
|
||||
struct udev_line_node *line;
|
||||
struct udev_entry_node *entry;
|
||||
struct util_udev_line_node *line;
|
||||
struct util_udev_entry_node *entry;
|
||||
|
||||
util_list_iterate(&file->lines, line) {
|
||||
entry = util_list_start(&line->entries);
|
||||
@@ -114,12 +115,12 @@ static void udev_file_get_settings(struct udev_file *file,
|
||||
}
|
||||
|
||||
/* Determine full CCWGROUP from data in udev rule file. */
|
||||
static void expand_id(struct device *dev, struct udev_file *file)
|
||||
static void expand_id(struct device *dev, struct util_udev_file *file)
|
||||
{
|
||||
struct ccwgroup_devid devid;
|
||||
struct ccwgroup_devid *devid_ptr = dev->devid;
|
||||
struct udev_line_node *line;
|
||||
struct udev_entry_node *entry;
|
||||
struct util_udev_line_node *line;
|
||||
struct util_udev_entry_node *entry;
|
||||
char *id;
|
||||
int i;
|
||||
|
||||
@@ -155,12 +156,12 @@ exit_code_t udev_ccwgroup_read_device(struct device *dev, bool autoconf)
|
||||
struct subtype *st = dev->subtype;
|
||||
struct device_state *state = autoconf ? &dev->autoconf :
|
||||
&dev->persistent;
|
||||
struct udev_file *file = NULL;
|
||||
struct util_udev_file *file = NULL;
|
||||
exit_code_t rc;
|
||||
char *path;
|
||||
|
||||
path = get_rule_path_by_devid(st->name, dev->devid, autoconf);
|
||||
rc = udev_read_file(path, &file);
|
||||
rc = (exit_code_t) util_udev_read_file(path, &file);
|
||||
if (rc)
|
||||
goto out;
|
||||
if (udev_file_is_empty(file)) {
|
||||
@@ -171,7 +172,7 @@ exit_code_t udev_ccwgroup_read_device(struct device *dev, bool autoconf)
|
||||
expand_id(dev, file);
|
||||
state->exists = 1;
|
||||
}
|
||||
udev_free_file(file);
|
||||
util_udev_free_file(file);
|
||||
|
||||
out:
|
||||
free(path);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "lib/util_path.h"
|
||||
#include "lib/util_udev.h"
|
||||
|
||||
#include "attrib.h"
|
||||
#include "device.h"
|
||||
@@ -126,7 +127,7 @@ void zfcp_lun_node_list_print(struct util_list *list, int indent)
|
||||
}
|
||||
|
||||
static bool zfcp_lun_devid_from_entry(struct zfcp_lun_devid *id_ptr,
|
||||
struct udev_entry_node *entry)
|
||||
struct util_udev_entry_node *entry)
|
||||
{
|
||||
struct zfcp_lun_devid id;
|
||||
char *copy = NULL, *s, *e, *u;
|
||||
@@ -214,7 +215,7 @@ out:
|
||||
}
|
||||
|
||||
static struct zfcp_lun_node *zfcp_lun_node_from_entry(
|
||||
struct udev_entry_node *entry,
|
||||
struct util_udev_entry_node *entry,
|
||||
struct zfcp_lun_node *old,
|
||||
struct util_list *list)
|
||||
{
|
||||
@@ -234,7 +235,7 @@ static struct zfcp_lun_node *zfcp_lun_node_from_entry(
|
||||
return node;
|
||||
}
|
||||
|
||||
static void add_internal_setting_from_entry(struct udev_entry_node *entry,
|
||||
static void add_internal_setting_from_entry(struct util_udev_entry_node *entry,
|
||||
struct zfcp_lun_node *node)
|
||||
{
|
||||
char *copy, *name, *end, *u;
|
||||
@@ -263,7 +264,7 @@ out:
|
||||
free(copy);
|
||||
}
|
||||
|
||||
static void add_fc_setting_from_entry(struct udev_entry_node *entry,
|
||||
static void add_fc_setting_from_entry(struct util_udev_entry_node *entry,
|
||||
struct zfcp_lun_node *node)
|
||||
{
|
||||
char *copy, *s, *e;
|
||||
@@ -294,7 +295,7 @@ out:
|
||||
free(copy);
|
||||
}
|
||||
|
||||
static void add_scsi_setting_from_entry(struct udev_entry_node *entry,
|
||||
static void add_scsi_setting_from_entry(struct util_udev_entry_node *entry,
|
||||
struct zfcp_lun_node *node)
|
||||
{
|
||||
char *copy, *s, *e;
|
||||
@@ -336,9 +337,9 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
||||
struct util_list *list)
|
||||
{
|
||||
exit_code_t rc;
|
||||
struct udev_file *file = NULL;
|
||||
struct udev_line_node *line;
|
||||
struct udev_entry_node *entry;
|
||||
struct util_udev_file *file = NULL;
|
||||
struct util_udev_line_node *line;
|
||||
struct util_udev_entry_node *entry;
|
||||
struct zfcp_lun_node *node = NULL;
|
||||
enum {
|
||||
none,
|
||||
@@ -347,7 +348,7 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
||||
} state = none;
|
||||
bool empty_rule = true;
|
||||
|
||||
rc = udev_read_file(filename, &file);
|
||||
rc = (exit_code_t) util_udev_read_file(filename, &file);
|
||||
if (rc)
|
||||
goto out;
|
||||
|
||||
@@ -398,7 +399,7 @@ static exit_code_t udev_read_zfcp_lun_rule(const char *filename,
|
||||
sort_zfcp_lun_list(list);
|
||||
|
||||
out:
|
||||
udev_free_file(file);
|
||||
util_udev_free_file(file);
|
||||
|
||||
if (empty_rule)
|
||||
warn_once("Warning: Invalid udev rule: %s\n", filename);
|
||||
|
||||
Reference in New Issue
Block a user