namedev.c revision 0db6d4cc61523ee7f3f627f807c01f86ee2d36ab
/*
*
* Userspace devfs
*
* Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
*
*
* under the terms of the GNU General Public License as published by the
* Free Software Foundation version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/* define this to enable parsing debugging */
/* #define DEBUG_PARSER */
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <unistd.h>
#include <errno.h>
#include "list.h"
#include "udev.h"
#include "udev_version.h"
#include "namedev.h"
#include "libsysfs/libsysfs.h"
#include "klibc_fixups.h"
#define TYPE_LABEL "LABEL"
#define TYPE_NUMBER "NUMBER"
#define TYPE_TOPOLOGY "TOPOLOGY"
#define TYPE_REPLACE "REPLACE"
#define TYPE_CALLOUT "CALLOUT"
#define CALLOUT_MAXARG 8
static LIST_HEAD(config_device_list);
/* s2 may end with '*' to match everything */
{
len--;
else
}
{
case KERNEL_NAME:
dbg_parse("KERNEL name='%s' ,"
"owner='%s', group='%s', mode=%#o",
break;
case LABEL:
dbg_parse("LABEL name='%s', bus='%s', sysfs_file='%s', sysfs_value='%s', "
"owner='%s', group='%s', mode=%#o",
break;
case NUMBER:
dbg_parse("NUMBER name='%s', bus='%s', id='%s', "
"owner='%s', group='%s', mode=%#o",
break;
case TOPOLOGY:
dbg_parse("TOPOLOGY name='%s', bus='%s', place='%s', "
"owner='%s', group='%s', mode=%#o",
break;
case REPLACE:
dbg_parse("REPLACE name=%s, kernel_name=%s, "
"owner='%s', group='%s', mode=%#o",
break;
case CALLOUT:
dbg_parse("CALLOUT name='%s', bus='%s', program='%s', id='%s', "
"owner='%s', group='%s', mode=%#o",
break;
default:
dbg_parse("unknown type of method");
}
}
if (b->var) \
#define copy_string(a, b, var) \
{
struct config_device *tmp_dev;
/* update the values if we already have the device */
continue;
continue;
return 0;
}
/* not found, add new structure to the device list */
if (!tmp_dev)
return -ENOMEM;
//dump_dev(tmp_dev);
return 0;
}
static void dump_dev_list(void)
{
}
}
{
char *temp;
char *string = *orig_string;
if (!string)
return -ENODEV;
/* eat any whitespace */
++string;
/* split based on '=' */
if (!string)
return -ENODEV;
/* take the right side and strip off the '"' */
++string;
if (*string == '"')
++string;
else
return -ENODEV;
return -ENODEV;
*orig_string = string;
return 0;
}
{
int retval;
char *left_string;
if (retval)
return retval;
return -ENODEV;
return 0;
}
static int namedev_init_config(void)
{
char line[255];
int lineno;
char *temp;
char *temp2;
char *temp3;
int retval = 0;
struct config_device dev;
return -ENODEV;
}
/* loop through the whole file */
lineno = 0;
while (1) {
/* get a line */
goto exit;
lineno++;
/* eat the whitespace at the beginning of the line */
++temp;
/* empty line? */
if (*temp == 0x00)
continue;
/* see if this is a comment */
if (*temp == COMMENT_CHARACTER)
continue;
/* parse the line */
/* label type */
/* BUS="bus" */
if (retval)
break;
/* file="value" */
if (retval)
break;
/* NAME="new_name" */
if (retval)
break;
dbg_parse("LABEL name='%s', bus='%s', "
"sysfs_file='%s', sysfs_value='%s'",
}
/* number type */
/* BUS="bus" */
if (retval)
break;
/* ID="id" */
if (retval)
break;
/* NAME="new_name" */
if (retval)
break;
dbg_parse("NUMBER name='%s', bus='%s', id='%s'",
}
/* number type */
/* BUS="bus" */
if (retval)
break;
/* PLACE="place" */
if (retval)
break;
/* NAME="new_name" */
if (retval)
break;
dbg_parse("TOPOLOGY name='%s', bus='%s', place='%s'",
}
/* number type */
/* KERNEL="kernel_name" */
if (retval)
break;
/* NAME="new_name" */
if (retval)
break;
dbg_parse("REPLACE name='%s', kernel_name='%s'",
}
/* number type */
/* BUS="bus" */
if (retval)
break;
/* PROGRAM="executable" */
if (retval)
break;
/* ID="id" */
if (retval)
break;
/* NAME="new_name" */
if (retval)
break;
dbg_parse("CALLOUT name='%s', program='%s'",
}
if (retval) {
goto exit;
}
}
exit:
return retval;
}
static int namedev_init_permissions(void)
{
char line[255];
char *temp;
char *temp2;
int retval = 0;
struct config_device dev;
return -ENODEV;
}
/* loop through the whole file */
while (1) {
break;
/* eat the whitespace at the beginning of the line */
++temp;
/* empty line? */
if (*temp == 0x00)
continue;
/* see if this is a comment */
if (*temp == COMMENT_CHARACTER)
continue;
/* parse the line */
if (!temp2) {
continue;
}
if (!temp2) {
continue;
}
if (!temp2) {
continue;
}
if (!temp) {
continue;
}
dbg_parse("name='%s', owner='%s', group='%s', mode=%#o",
if (retval) {
goto exit;
}
}
exit:
return retval;
}
{
/* just default everyone to rw for the world! */
return 0666;
}
{
char *dig;
/* FIXME, figure out how to handle stuff like sdaj which will not work right now. */
dig--;
}
{
char *pos;
while (1) {
if (pos) {
*pos = 0x00;
switch (pos[1]) {
case 'b':
break;
break;
case 'n':
break;
break;
case 'D':
break;
}
break;
case 'm':
break;
case 'M':
break;
case 'c':
break;
break;
default:
break;
}
} else
break;
}
}
{
int retval;
int res;
int status;
int fds[2];
int value_set = 0;
char buffer[256];
char *arg;
char *args[CALLOUT_MAXARG];
int i;
if (retval != 0) {
dbg("pipe failed");
return -1;
}
if (pid == -1) {
dbg("fork failed");
return -1;
}
if (pid == 0) {
/* child */
/* callout with arguments */
for (i=0; i < CALLOUT_MAXARG-1; i++) {
break;
}
if (args[i]) {
dbg("too many args - %d", i);
}
} else {
}
if (retval != 0) {
dbg("child execve failed");
exit(1);
}
return -1; /* avoid compiler warning */
} else {
/* parent reads from fds[0] */
retval = 0;
while (1) {
if (res <= 0)
break;
retval = -1;
}
if (value_set) {
dbg("callout value already set");
retval = -1;
} else {
value_set = 1;
}
}
if (res < 0) {
retval = -1;
}
#ifndef __KLIBC__
retval = -1;
}
#endif
}
return retval;
}
static int do_callout(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
struct config_device *dev;
continue;
if (sysfs_device) {
continue;
}
/* substitute anything that needs to be in the program name */
continue;
continue;
}
dbg_parse("callout returned matching value '%s', '%s' becomes '%s'"
" - owner='%s', group='%s', mode=%#o",
return 0;
}
return -ENODEV;
}
static int do_label(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
struct config_device *dev;
continue;
if (sysfs_device) {
continue;
}
/* try to find the attribute in the class device directory */
if (tmpattr)
goto label_found;
/* look in the class device directory if present */
if (sysfs_device) {
if (tmpattr)
goto label_found;
}
continue;
dbg_parse("compare attribute '%s' value '%s' with '%s'",
continue;
}
dbg_parse("found matching attribute '%s', '%s' becomes '%s' "
"- owner='%s', group='%s', mode=%#o",
return 0;
}
return -ENODEV;
}
static int do_number(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
struct config_device *dev;
char path[SYSFS_PATH_MAX];
int found;
/* we have to have a sysfs device for NUMBER to work */
if (!sysfs_device)
return -ENODEV;
continue;
continue;
found = 0;
found = 1;
} else {
*temp = 0x00;
found = 1;
}
if (!found)
continue;
}
dbg_parse("found matching id '%s', '%s' becomes '%s'"
" - owner='%s', group ='%s', mode=%#o",
return 0;
}
return -ENODEV;
}
static int do_topology(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
struct config_device *dev;
char path[SYSFS_PATH_MAX];
int found;
/* we have to have a sysfs device for TOPOLOGY to work */
if (!sysfs_device)
return -ENODEV;
continue;
continue;
found = 0;
found = 1;
} else {
*temp = 0x00;
found = 1;
}
if (!found)
continue;
}
dbg_parse("found matching place '%s', '%s' becomes '%s'"
" - owner='%s', group ='%s', mode=%#o",
return 0;
}
return -ENODEV;
}
static int do_replace(struct sysfs_class_device *class_dev, struct udevice *udev, struct sysfs_device *sysfs_device)
{
struct config_device *dev;
continue;
dbg_parse("compare name '%s' with '%s'",
continue;
}
dbg_parse("found name, '%s' becomes '%s' - owner='%s', group='%s', mode = %#o",
return 0;
}
return -ENODEV;
}
{
struct config_device *dev;
int len;
/* look for permissions */
continue;
}
}
}
{
int retval = 0;
/* find the sysfs_device for this class device */
/* Wouldn't it really be nice if libsysfs could do this for us? */
} else {
/* bah, let's go backwards up a level to see if the device is there,
* as block partitions don't point to the physical device. Need to fix that
* up in the kernel...
*/
dbg_parse("looking at block device");
char path[SYSFS_PATH_MAX];
dbg_parse("really is a partition");
*temp = 0x00;
if (class_dev_parent == NULL) {
} else {
if (class_dev_parent->sysdevice)
}
}
}
}
if (sysfs_device) {
} else {
}
/* rules are looked at in priority order */
if (retval == 0)
goto found;
if (retval == 0)
goto found;
if (retval == 0)
goto found;
if (retval == 0)
goto found;
if (retval == 0)
goto found;
goto done;
/* substitute placeholder in NAME */
done:
/* mode was never set above */
}
if (class_dev_parent)
return 0;
}
{
int retval;
if (retval)
dbg("get_attr failed");
return retval;
}
int namedev_init(void)
{
int retval;
if (retval)
return retval;
if (retval)
return retval;
return retval;
}