b80d229ec2
Added all of them - module_loader.c and boot_hack.c won't be needed anymore. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7351 a95241bf-73f2-0310-859d-f6bbb57e9c96
242 lines
5.1 KiB
C
242 lines
5.1 KiB
C
/*
|
|
** Copyright 2002-04, Thomas Kurschel. All rights reserved.
|
|
** Distributed under the terms of the OpenBeOS License.
|
|
*/
|
|
|
|
/*
|
|
Part of PnP Manager
|
|
|
|
Expansion of patterns.
|
|
Used to expand consumer/connector/device names etc.
|
|
*/
|
|
|
|
|
|
#include "device_manager_private.h"
|
|
|
|
#include <KernelExport.h>
|
|
#include <TypeConstants.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
|
|
#define TRACE_PATTERNS
|
|
#ifdef TRACE_PATTERNS
|
|
# define TRACE(x) dprintf x
|
|
#else
|
|
# define TRACE(x) ;
|
|
#endif
|
|
|
|
|
|
/** expand node attribute
|
|
* node - node to get attributes from
|
|
* *pattern - name of attribute, ending with "%" (takes care of "^" sequences)
|
|
* on return, *patterns points to trailing "%"
|
|
* buffer - buffer for name
|
|
* dst - string to write content to
|
|
* node_lock must be hold
|
|
*/
|
|
|
|
static status_t
|
|
expand_attr(pnp_node_info *node, const char **pattern, char *buffer, char *dst)
|
|
{
|
|
pnp_node_attr_info *attr;
|
|
const char *str;
|
|
int buffer_len;
|
|
|
|
// extract attribute name
|
|
buffer_len = 0;
|
|
|
|
for (str = *pattern; *str; ++str) {
|
|
if (*str == '^' && *(str + 1) != 0)
|
|
// copy escaped character directly
|
|
++str;
|
|
else if (*str == '%')
|
|
break;
|
|
|
|
buffer[buffer_len++] = *str;
|
|
}
|
|
|
|
*pattern = str;
|
|
|
|
buffer[buffer_len] = '\0';
|
|
|
|
// get attribute content and add it to path
|
|
attr = pnp_find_attr_nolock(node, buffer, true, B_ANY_TYPE);
|
|
if (attr == NULL) {
|
|
dprintf("Reference to unknown attribute %s\n", buffer);
|
|
return B_NAME_NOT_FOUND;
|
|
}
|
|
|
|
switch (attr->attr.type) {
|
|
case B_UINT8_TYPE:
|
|
sprintf(buffer, "%02x", attr->attr.value.ui8);
|
|
strlcat(dst, buffer, PATH_MAX);
|
|
break;
|
|
case B_UINT16_TYPE:
|
|
sprintf(buffer, "%04x", attr->attr.value.ui16);
|
|
strlcat(dst, buffer, PATH_MAX);
|
|
break;
|
|
case B_UINT32_TYPE:
|
|
sprintf(buffer, "%08lx", attr->attr.value.ui32);
|
|
strlcat(dst, buffer, PATH_MAX);
|
|
break;
|
|
case B_UINT64_TYPE:
|
|
sprintf(buffer, "%16Lx", attr->attr.value.ui64);
|
|
strlcat(dst, buffer, PATH_MAX);
|
|
break;
|
|
case B_STRING_TYPE: {
|
|
const char *str;
|
|
|
|
strlcat(dst, "\"", PATH_MAX);
|
|
|
|
for (str = attr->attr.value.string; *str; ++str) {
|
|
char ch;
|
|
|
|
ch = *str;
|
|
if (ch >= 32 && ch <= 126 && ch != '/' && ch != '%' && ch != '"') {
|
|
buffer[0] = ch;
|
|
buffer[1] = 0;
|
|
} else {
|
|
// convert unprintable/forbidden characters to numbers
|
|
sprintf(buffer, "%%%u%%", (unsigned char)ch);
|
|
}
|
|
|
|
strlcat(dst, buffer, PATH_MAX);
|
|
}
|
|
|
|
strlcat(dst, "\"", PATH_MAX);
|
|
break;
|
|
}
|
|
case B_RAW_TYPE:
|
|
default:
|
|
benaphore_unlock(&gNodeLock);
|
|
return B_BAD_VALUE;
|
|
}
|
|
|
|
benaphore_unlock(&gNodeLock);
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
/** expand pattern.
|
|
* the pattern is both expanded and the position of inidiual parts returned
|
|
* pattern - pattern to expand
|
|
* dest - expanded name is appended to this string
|
|
* buffer - buffer of MAX_PATH+1 size supplied by caller
|
|
* term_array - list of lengths of individual sub-names
|
|
* with index 0 containing the length of the shortest and
|
|
* num_parts-1 - length of the longest sub-name
|
|
* <term_array> and <num_parts> can be NULL
|
|
* node_lock must be hold
|
|
*/
|
|
|
|
status_t
|
|
pnp_expand_pattern(pnp_node_info *node, const char *pattern, char *dest,
|
|
char *buffer, size_t *term_array, int *num_parts)
|
|
{
|
|
const char *str;
|
|
int id;
|
|
status_t res;
|
|
int buffer_len = 0;
|
|
|
|
TRACE(("expand_pattern(pattern: %s)\n", pattern));
|
|
|
|
for (str = pattern, id = 0; *str; ++str) {
|
|
switch (*str) {
|
|
case '^':
|
|
// character following "^" is copied directly
|
|
// exception: if there is a trailing "^" at end of string,
|
|
// we copy it directly
|
|
if (*(str + 1) != 0)
|
|
++str;
|
|
|
|
buffer[buffer_len++] = *str;
|
|
break;
|
|
|
|
case '|':
|
|
// end of one name part
|
|
buffer[buffer_len] = '\0';
|
|
buffer_len = 0;
|
|
strlcat(dest, buffer, PATH_MAX);
|
|
|
|
TRACE(("%d: %s\n", id, dest));
|
|
|
|
if (term_array != NULL)
|
|
term_array[id++] = strlen(dest);
|
|
break;
|
|
|
|
case '%':
|
|
// begin of place-holder
|
|
buffer[buffer_len] = '\0';
|
|
buffer_len = 0;
|
|
strlcat(dest, buffer, PATH_MAX);
|
|
|
|
// skip "%"
|
|
++str;
|
|
|
|
res = expand_attr(node, &str, buffer, dest);
|
|
if (res != B_OK)
|
|
return res;
|
|
break;
|
|
|
|
default:
|
|
// normal character
|
|
buffer[buffer_len++] = *str;
|
|
}
|
|
|
|
// avoid overflow of buffer
|
|
if (buffer_len > PATH_MAX)
|
|
buffer_len = PATH_MAX;
|
|
}
|
|
|
|
// append trailing characters
|
|
buffer[buffer_len] = 0;
|
|
buffer_len = 0;
|
|
strlcat(dest, buffer, PATH_MAX);
|
|
|
|
if (term_array != NULL)
|
|
term_array[id++] = strlen(dest);
|
|
|
|
if (num_parts != NULL)
|
|
*num_parts = id;
|
|
|
|
TRACE(("result: %s\n", dest));
|
|
|
|
return B_OK;
|
|
}
|
|
|
|
|
|
/** expand pattern as specified by attribute <attr_name>
|
|
* node_lock must be hold
|
|
*/
|
|
|
|
status_t
|
|
pnp_expand_pattern_attr(pnp_node_info *node, const char *attr_name,
|
|
char **expanded)
|
|
{
|
|
const char *pattern;
|
|
status_t res;
|
|
|
|
TRACE(("pnp_expand_pattern_attr()\n"));
|
|
|
|
if (pnp_get_attr_string_nolock(node, attr_name, &pattern, false) != B_OK) {
|
|
*expanded = strdup("");
|
|
return B_OK;
|
|
}
|
|
|
|
*expanded = malloc((PATH_MAX + 1) * 2);
|
|
if (*expanded == NULL)
|
|
return B_NO_MEMORY;
|
|
|
|
**expanded = 0;
|
|
res = pnp_expand_pattern(node, pattern,
|
|
*expanded, *expanded + PATH_MAX + 1, NULL, NULL);
|
|
|
|
if (res != B_OK)
|
|
free(*expanded);
|
|
|
|
return res;
|
|
}
|