From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Surekha.PC" Date: Tue, 25 Nov 2003 12:56:12 +0000 Subject: RE: udev does not create scsi disk entries during bootup MIME-Version: 1 Content-Type: multipart/mixed; boundary="----=_NextPart_000_01BB_01C3B37F.EE750210" Message-Id: List-Id: References: In-Reply-To: To: linux-hotplug@vger.kernel.org This is a multi-part message in MIME format. ------=_NextPart_000_01BB_01C3B37F.EE750210 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Hi Greg, I was able to make hotplug work !!! The latest udev-007 release provides udev startup script, which was not present in earlier udev-005 release. The script however does not get installed in the rc.d path. I had to install it manually to make it work. This needs to be taken care in future releases. I am now able to automatically add and remove my iSCSI devices through udev. I am submitting the patch with 2 changes. 1)To include new field in the NUMBER rule specially for iSCSI devices. The current rule provided by udev is as below. NUMBER, BUS="scsi", ID=2:0:0:0", NAME="disk%n" For iSCSI devices, since hostid is not consistent, we are defining a new iSCSI device attribute in sysfs, which will be checked while naming the device. NUMBER, BUS="scsi", ID="0:0:0", device_type="ISCSI", NAME="ib0t0l0%n" 2) Device partition name needs to be appended with "s" before partition id. If the device name consists of bus,target info like "c0b0t0l0" it will be easier to identify the partition as in "c0b0t0l0s1". Please find the patch alongwith. Thanks, surekha -----Original Message----- From: linux-hotplug-devel-admin@lists.sourceforge.net [mailto:linux-hotplug-devel-admin@lists.sourceforge.net] On Behalf Of Greg KH Sent: Tuesday, November 25, 2003 3:44 AM To: Surekha.PC Cc: 'Martin Hicks'; linux-hotplug-devel@lists.sourceforge.net Subject: Re: udev does not create scsi disk entries during bootup On Mon, Nov 24, 2003 at 06:18:54PM +0530, Surekha.PC wrote: > > > >The 'tree' function is much nicer for seeing things like this :) > > Is this a utility? Appreciate if you can inform me where to get it. Hm, it should be included in your distro. What are you running? > >> Here sda, sdb are my native scsi disks while sdc, sdd are iSCSI > disks. > > >Why is your iscsi host controller haning off of the legacy bus? > >Isn't > it connected to a >ethernet device in reality? You should link it to > that. > > iSCSI is a pseudo SCSI HBA, it is registered with Scsi_Host template > just like any native SCSI HBA. Since there isn't any pci bus > associated with it, it appears on legacy bus. But it's attached to a network connection, correct? If so, why not link it to the network device? > >> I am able to manually create the device nodes for iSCSI disks with > >> udev. > >> > >> Making udev work with hotplug is the only issue now :( > > >Don't know why it isn't working for you. Does any other devices work > >with hotplug? What distro are you using? Can you install the hotplug > >rpms instead of using the tarballs? > > I have native scsi disk devices on my system. These are not tested for > hotplugging since it requires to build udev with initrd, which I am > yet to test with. > > I am using Redhat 9.0 with linux-kernel 2.6.0-test5. > > I was not able to install from rpm, rpm on 2.6 kernel has an issue, it > gives following error and fails... That's another issue. Sounds like you aren't running as root to do that. Anyway, try grabbing the version of hotplug from rawhide/fedora that should be a good base to work off of. Other than that, I really have no idea what's going wrong. It doesn't look to be a kernel or udev error, so I'll be of no help :) Good luck, greg k-h ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel ------=_NextPart_000_01BB_01C3B37F.EE750210 Content-Type: application/octet-stream; name="namedev.c.org" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="namedev.c.org" /*=0A= * namedev.c=0A= *=0A= * Userspace devfs=0A= *=0A= * Copyright (C) 2003 Greg Kroah-Hartman =0A= *=0A= *=0A= * This program is free software; you can redistribute it and/or modify = it=0A= * under the terms of the GNU General Public License as published by the=0A= * Free Software Foundation version 2 of the License.=0A= * =0A= * This program is distributed in the hope that it will be useful, but=0A= * WITHOUT ANY WARRANTY; without even the implied warranty of=0A= * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU=0A= * General Public License for more details.=0A= * =0A= * You should have received a copy of the GNU General Public License = along=0A= * with this program; if not, write to the Free Software Foundation, = Inc.,=0A= * 675 Mass Ave, Cambridge, MA 02139, USA.=0A= *=0A= */=0A= =0A= /* define this to enable parsing debugging */=0A= /* #define DEBUG_PARSER */=0A= =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= =0A= #include "list.h"=0A= #include "udev.h"=0A= #include "udev_version.h"=0A= #include "namedev.h"=0A= #include "libsysfs/libsysfs.h"=0A= #include "klibc_fixups.h"=0A= =0A= #define TYPE_LABEL "LABEL"=0A= #define TYPE_NUMBER "NUMBER"=0A= #define TYPE_TOPOLOGY "TOPOLOGY"=0A= #define TYPE_REPLACE "REPLACE"=0A= #define TYPE_CALLOUT "CALLOUT"=0A= #define CALLOUT_MAXARG 8=0A= =0A= static LIST_HEAD(config_device_list);=0A= =0A= /* s2 may end with '*' to match everything */=0A= static int strncmp_wildcard(char *s1, char *s2, int max)=0A= {=0A= int len =3D strlen(s2);=0A= if (len > max)=0A= len =3D max;=0A= if (s2[len-1] =3D=3D '*')=0A= len--;=0A= else=0A= len =3D max;=0A= return strncmp(s1, s2, len);=0A= }=0A= =0A= static void dump_dev(struct config_device *dev)=0A= {=0A= switch (dev->type) {=0A= case KERNEL_NAME:=0A= dbg_parse("KERNEL name=3D'%s' ,"=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->owner, dev->group, dev->mode);=0A= break;=0A= case LABEL:=0A= dbg_parse("LABEL name=3D'%s', bus=3D'%s', sysfs_file=3D'%s', = sysfs_value=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->sysfs_file, dev->sysfs_value,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case NUMBER:=0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->id,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case TOPOLOGY:=0A= dbg_parse("TOPOLOGY name=3D'%s', bus=3D'%s', place=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->place,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case REPLACE:=0A= dbg_parse("REPLACE name=3D%s, kernel_name=3D%s, "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->kernel_name,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case CALLOUT:=0A= dbg_parse("CALLOUT name=3D'%s', bus=3D'%s', program=3D'%s', id=3D'%s', = "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->exec_program, dev->id,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= default:=0A= dbg_parse("unknown type of method");=0A= }=0A= }=0A= =0A= #define copy_var(a, b, var) \=0A= if (b->var) \=0A= a->var =3D b->var;=0A= =0A= #define copy_string(a, b, var) \=0A= if (strlen(b->var)) \=0A= strcpy(a->var, b->var);=0A= =0A= static int add_dev(struct config_device *new_dev)=0A= {=0A= struct list_head *tmp;=0A= struct config_device *tmp_dev;=0A= =0A= /* update the values if we already have the device */=0A= list_for_each(tmp, &config_device_list) {=0A= struct config_device *dev =3D list_entry(tmp, struct config_device, = node);=0A= if (strncmp_wildcard(dev->name, new_dev->name, sizeof(dev->name)))=0A= continue;=0A= copy_var(dev, new_dev, type);=0A= copy_var(dev, new_dev, mode);=0A= copy_string(dev, new_dev, bus);=0A= copy_string(dev, new_dev, sysfs_file);=0A= copy_string(dev, new_dev, sysfs_value);=0A= copy_string(dev, new_dev, id);=0A= copy_string(dev, new_dev, place);=0A= copy_string(dev, new_dev, kernel_name);=0A= copy_string(dev, new_dev, owner);=0A= copy_string(dev, new_dev, group);=0A= return 0;=0A= }=0A= =0A= /* not found, add new structure to the device list */=0A= tmp_dev =3D malloc(sizeof(*tmp_dev));=0A= if (!tmp_dev)=0A= return -ENOMEM;=0A= memcpy(tmp_dev, new_dev, sizeof(*tmp_dev));=0A= list_add(&tmp_dev->node, &config_device_list);=0A= //dump_dev(tmp_dev);=0A= return 0;=0A= }=0A= =0A= static void dump_dev_list(void)=0A= {=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= struct config_device *dev =3D list_entry(tmp, struct config_device, = node);=0A= dump_dev(dev);=0A= }=0A= }=0A= =0A= static int get_pair(char **orig_string, char **left, char **right)=0A= {=0A= char *temp;=0A= char *string =3D *orig_string;=0A= =0A= if (!string)=0A= return -ENODEV;=0A= =0A= /* eat any whitespace */=0A= while (isspace(*string))=0A= ++string;=0A= =0A= /* split based on '=3D' */=0A= temp =3D strsep(&string, "=3D");=0A= *left =3D temp;=0A= if (!string)=0A= return -ENODEV;=0A= =0A= /* take the right side and strip off the '"' */=0A= while (isspace(*string))=0A= ++string;=0A= if (*string =3D=3D '"')=0A= ++string;=0A= else=0A= return -ENODEV;=0A= =0A= temp =3D strsep(&string, "\"");=0A= if (!string || *temp =3D=3D '\0')=0A= return -ENODEV;=0A= *right =3D temp;=0A= *orig_string =3D string;=0A= =0A= return 0;=0A= }=0A= =0A= static int get_value(const char *left, char **orig_string, char = **ret_string)=0A= {=0A= int retval;=0A= char *left_string;=0A= =0A= retval =3D get_pair(orig_string, &left_string, ret_string);=0A= if (retval)=0A= return retval;=0A= if (strcasecmp(left_string, left) !=3D 0)=0A= return -ENODEV;=0A= return 0;=0A= }=0A= =0A= static int namedev_init_config(void)=0A= {=0A= char line[255];=0A= int lineno;=0A= char *temp;=0A= char *temp2;=0A= char *temp3;=0A= FILE *fd;=0A= int retval =3D 0;=0A= struct config_device dev;=0A= =0A= dbg("opening %s to read as config", udev_config_filename);=0A= fd =3D fopen(udev_config_filename, "r");=0A= if (fd =3D=3D NULL) {=0A= dbg("can't open %s", udev_config_filename);=0A= return -ENODEV;=0A= }=0A= =0A= /* loop through the whole file */=0A= lineno =3D 0;=0A= while (1) {=0A= /* get a line */=0A= temp =3D fgets(line, sizeof(line), fd);=0A= if (temp =3D=3D NULL)=0A= goto exit;=0A= lineno++;=0A= =0A= dbg_parse("read %s", temp);=0A= =0A= /* eat the whitespace at the beginning of the line */=0A= while (isspace(*temp))=0A= ++temp;=0A= =0A= /* empty line? */=0A= if (*temp =3D=3D 0x00)=0A= continue;=0A= =0A= /* see if this is a comment */=0A= if (*temp =3D=3D COMMENT_CHARACTER)=0A= continue;=0A= =0A= memset(&dev, 0x00, sizeof(struct config_device));=0A= =0A= /* parse the line */=0A= temp2 =3D strsep(&temp, ",");=0A= if (strcasecmp(temp2, TYPE_LABEL) =3D=3D 0) {=0A= /* label type */=0A= dev.type =3D LABEL;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* file=3D"value" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_pair(&temp, &temp2, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.sysfs_file, temp2);=0A= strfieldcpy(dev.sysfs_value, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("LABEL name=3D'%s', bus=3D'%s', "=0A= "sysfs_file=3D'%s', sysfs_value=3D'%s'",=0A= dev.name, dev.bus, dev.sysfs_file,=0A= dev.sysfs_value);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_NUMBER) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D NUMBER;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* ID=3D"id" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("ID", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s'",=0A= dev.name, dev.bus, dev.id);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_TOPOLOGY) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D TOPOLOGY;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* PLACE=3D"place" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("PLACE", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.place, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("TOPOLOGY name=3D'%s', bus=3D'%s', place=3D'%s'",=0A= dev.name, dev.bus, dev.place);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_REPLACE) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D REPLACE;=0A= =0A= /* KERNEL=3D"kernel_name" */=0A= retval =3D get_value("KERNEL", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.kernel_name, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= dbg_parse("REPLACE name=3D'%s', kernel_name=3D'%s'",=0A= dev.name, dev.kernel_name);=0A= }=0A= if (strcasecmp(temp2, TYPE_CALLOUT) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D CALLOUT;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* PROGRAM=3D"executable" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("PROGRAM", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.exec_program, temp3);=0A= =0A= /* ID=3D"id" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("ID", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= dbg_parse("CALLOUT name=3D'%s', program=3D'%s'",=0A= dev.name, dev.exec_program);=0A= }=0A= =0A= retval =3D add_dev(&dev);=0A= if (retval) {=0A= dbg("add_dev returned with error %d", retval);=0A= goto exit;=0A= }=0A= }=0A= dbg_parse("%s:%d:%Zd: error parsing '%s'", udev_config_filename,=0A= lineno, temp - line, temp);=0A= exit:=0A= fclose(fd);=0A= return retval;=0A= } =0A= =0A= =0A= static int namedev_init_permissions(void)=0A= {=0A= char line[255];=0A= char *temp;=0A= char *temp2;=0A= FILE *fd;=0A= int retval =3D 0;=0A= struct config_device dev;=0A= =0A= dbg("opening %s to read as permissions config", = udev_config_permission_filename);=0A= fd =3D fopen(udev_config_permission_filename, "r");=0A= if (fd =3D=3D NULL) {=0A= dbg("can't open %s", udev_config_permission_filename);=0A= return -ENODEV;=0A= }=0A= =0A= /* loop through the whole file */=0A= while (1) {=0A= temp =3D fgets(line, sizeof(line), fd);=0A= if (temp =3D=3D NULL)=0A= break;=0A= =0A= dbg_parse("read %s", temp);=0A= =0A= /* eat the whitespace at the beginning of the line */=0A= while (isspace(*temp))=0A= ++temp;=0A= =0A= /* empty line? */=0A= if (*temp =3D=3D 0x00)=0A= continue;=0A= =0A= /* see if this is a comment */=0A= if (*temp =3D=3D COMMENT_CHARACTER)=0A= continue;=0A= =0A= memset(&dev, 0x00, sizeof(dev));=0A= =0A= /* parse the line */=0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.name, temp2, sizeof(dev.name));=0A= =0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.owner, temp2, sizeof(dev.owner));=0A= =0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.group, temp2, sizeof(dev.owner));=0A= =0A= dev.mode =3D strtol(temp, NULL, 8);=0A= =0A= dbg_parse("name=3D'%s', owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev.name, dev.owner, dev.group,=0A= dev.mode);=0A= retval =3D add_dev(&dev);=0A= if (retval) {=0A= dbg("add_dev returned with error %d", retval);=0A= goto exit;=0A= }=0A= }=0A= =0A= exit:=0A= fclose(fd);=0A= return retval;=0A= } =0A= =0A= static mode_t get_default_mode(struct sysfs_class_device *class_dev)=0A= {=0A= /* just default everyone to rw for the world! */=0A= return 0666;=0A= }=0A= =0A= static void build_kernel_number(struct sysfs_class_device *class_dev, = struct udevice *udev)=0A= {=0A= char *dig;=0A= =0A= /* FIXME, figure out how to handle stuff like sdaj which will not work = right now. */=0A= dig =3D class_dev->name + strlen(class_dev->name);=0A= while (isdigit(*(dig-1)))=0A= dig--;=0A= strfieldcpy(udev->kernel_number, dig);=0A= dbg("kernel_number =3D %s", udev->kernel_number);=0A= }=0A= =0A= static void apply_format(struct udevice *udev, unsigned char *string)=0A= {=0A= char name[NAME_SIZE];=0A= char *pos;=0A= =0A= while (1) {=0A= pos =3D strchr(string, '%');=0A= =0A= if (pos) {=0A= strfieldcpy(name, pos+2);=0A= *pos =3D 0x00;=0A= switch (pos[1]) {=0A= case 'b':=0A= if (strlen(udev->bus_id) =3D=3D 0)=0A= break;=0A= strcat(string, udev->bus_id);=0A= dbg("substitute bus_id '%s'", udev->bus_id);=0A= break;=0A= case 'n':=0A= if (strlen(udev->kernel_number) =3D=3D 0)=0A= break;=0A= strcat(pos, udev->kernel_number);=0A= dbg("substitute kernel number '%s'", udev->kernel_number);=0A= break;=0A= case 'm':=0A= sprintf(pos, "%u", udev->minor);=0A= dbg("substitute minor number '%u'", udev->minor);=0A= break;=0A= case 'M':=0A= sprintf(pos, "%u", udev->major);=0A= dbg("substitute major number '%u'", udev->major);=0A= break;=0A= case 'c':=0A= if (strlen(udev->callout_value) =3D=3D 0)=0A= break;=0A= strcat(pos, udev->callout_value);=0A= dbg("substitute callout output '%s'", udev->callout_value);=0A= break;=0A= default:=0A= dbg("unknown substitution type '%%%c'", pos[1]);=0A= break;=0A= }=0A= strcat(string, name);=0A= } else=0A= break;=0A= }=0A= }=0A= =0A= =0A= static int exec_callout(struct config_device *dev, char *value, int len)=0A= {=0A= int retval;=0A= int res;=0A= int status;=0A= int fds[2];=0A= pid_t pid;=0A= int value_set =3D 0;=0A= char buffer[256];=0A= char *arg;=0A= char *args[CALLOUT_MAXARG];=0A= int i;=0A= =0A= dbg("callout to '%s'", dev->exec_program);=0A= retval =3D pipe(fds);=0A= if (retval !=3D 0) {=0A= dbg("pipe failed");=0A= return -1;=0A= }=0A= pid =3D fork();=0A= if (pid =3D=3D -1) {=0A= dbg("fork failed");=0A= return -1;=0A= }=0A= =0A= if (pid =3D=3D 0) {=0A= /* child */=0A= close(STDOUT_FILENO);=0A= dup(fds[1]); /* dup write side of pipe to STDOUT */=0A= if (strchr(dev->exec_program, ' ')) {=0A= /* callout with arguments */=0A= arg =3D dev->exec_program;=0A= for (i=3D0; i < CALLOUT_MAXARG-1; i++) {=0A= args[i] =3D strsep(&arg, " ");=0A= if (args[i] =3D=3D NULL)=0A= break;=0A= }=0A= if (args[i]) {=0A= dbg("too many args - %d", i);=0A= args[i] =3D NULL;=0A= }=0A= retval =3D execve(args[0], args, main_envp);=0A= } else {=0A= retval =3D execve(dev->exec_program, main_argv, main_envp);=0A= }=0A= if (retval !=3D 0) {=0A= dbg("child execve failed");=0A= exit(1);=0A= }=0A= return -1; /* avoid compiler warning */=0A= } else {=0A= /* parent reads from fds[0] */=0A= close(fds[1]);=0A= retval =3D 0;=0A= while (1) {=0A= res =3D read(fds[0], buffer, sizeof(buffer) - 1);=0A= if (res <=3D 0)=0A= break;=0A= buffer[res] =3D '\0';=0A= if (res > len) {=0A= dbg("callout len %d too short\n", len);=0A= retval =3D -1;=0A= }=0A= if (value_set) {=0A= dbg("callout value already set");=0A= retval =3D -1;=0A= } else {=0A= value_set =3D 1;=0A= strncpy(value, buffer, len);=0A= }=0A= }=0A= dbg("callout returned '%s'", value);=0A= close(fds[0]);=0A= res =3D wait(&status);=0A= if (res < 0) {=0A= dbg("wait failed result %d", res);=0A= retval =3D -1;=0A= }=0A= =0A= #ifndef __KLIBC__=0A= if (!WIFEXITED(status) || (WEXITSTATUS(status) !=3D 0)) {=0A= dbg("callout program status 0x%x", status);=0A= retval =3D -1;=0A= }=0A= #endif=0A= }=0A= return retval;=0A= }=0A= =0A= static int do_callout(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D CALLOUT)=0A= continue;=0A= =0A= /* substitute anything that needs to be in the program name */=0A= apply_format(udev, dev->exec_program);=0A= if (exec_callout(dev, udev->callout_value, NAME_SIZE))=0A= continue;=0A= if (strncmp_wildcard(udev->callout_value, dev->id, NAME_SIZE) !=3D 0)=0A= continue;=0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("callout returned matching value '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group=3D'%s', mode =3D%#o",=0A= dev->id, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_label(struct sysfs_class_device *class_dev, struct udevice = *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct sysfs_attribute *tmpattr =3D NULL;=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D LABEL)=0A= continue;=0A= =0A= dbg_parse("look for device attribute '%s'", dev->sysfs_file);=0A= /* try to find the attribute in the class device directory */=0A= tmpattr =3D sysfs_get_classdev_attr(class_dev, dev->sysfs_file);=0A= if (tmpattr)=0A= goto label_found;=0A= =0A= /* look in the class device directory if present */=0A= if (sysfs_device) {=0A= tmpattr =3D sysfs_get_device_attr(sysfs_device, dev->sysfs_file);=0A= if (tmpattr)=0A= goto label_found;=0A= }=0A= =0A= continue;=0A= =0A= label_found:=0A= tmpattr->value[strlen(tmpattr->value)-1] =3D 0x00;=0A= dbg_parse("compare attribute '%s' value '%s' with '%s'",=0A= dev->sysfs_file, tmpattr->value, dev->sysfs_value);=0A= if (strcmp(dev->sysfs_value, tmpattr->value) !=3D 0)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching attribute '%s', '%s' becomes '%s' "=0A= "- owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->sysfs_file, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= =0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_number(struct sysfs_class_device *class_dev, struct = udevice *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= char path[SYSFS_PATH_MAX];=0A= int found;=0A= char *temp =3D NULL;=0A= =0A= /* we have to have a sysfs device for NUMBER to work */=0A= if (!sysfs_device)=0A= return -ENODEV;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D NUMBER)=0A= continue;=0A= =0A= found =3D 0;=0A= strfieldcpy(path, sysfs_device->path);=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->id, temp, path);=0A= if (strstr(temp, dev->id) !=3D NULL) {=0A= found =3D 1;=0A= } else {=0A= *temp =3D 0x00;=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->id, temp, path);=0A= if (strstr(temp, dev->id) !=3D NULL)=0A= found =3D 1;=0A= }=0A= if (!found)=0A= continue;=0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching id '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group =3D'%s', mode=3D%#o",=0A= dev->id, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= =0A= static int do_topology(struct sysfs_class_device *class_dev, struct = udevice *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= char path[SYSFS_PATH_MAX];=0A= int found;=0A= char *temp =3D NULL;=0A= =0A= /* we have to have a sysfs device for TOPOLOGY to work */=0A= if (!sysfs_device)=0A= return -ENODEV;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D TOPOLOGY)=0A= continue;=0A= =0A= found =3D 0;=0A= strfieldcpy(path, sysfs_device->path);=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->place, temp, path);=0A= if (strstr(temp, dev->place) !=3D NULL) {=0A= found =3D 1;=0A= } else {=0A= *temp =3D 0x00;=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->place, temp, path);=0A= if (strstr(temp, dev->place) !=3D NULL)=0A= found =3D 1;=0A= }=0A= if (!found)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching place '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group =3D'%s', mode=3D%#o",=0A= dev->place, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_replace(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D REPLACE)=0A= continue;=0A= =0A= dbg_parse("compare name '%s' with '%s'",=0A= dev->kernel_name, dev->name);=0A= if (strcmp(dev->kernel_name, class_dev->name) !=3D 0)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found name, '%s' becomes '%s' - owner=3D'%s', group=3D'%s', = mode =3D %#o",=0A= dev->kernel_name, udev->name, =0A= dev->owner, dev->group, dev->mode);=0A= =0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static void do_kernelname(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= int len;=0A= =0A= strfieldcpy(udev->name, class_dev->name);=0A= /* look for permissions */=0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= len =3D strlen(dev->name);=0A= if (strncmp_wildcard(class_dev->name, dev->name, sizeof(dev->name)))=0A= continue;=0A= if (dev->mode !=3D 0) {=0A= dbg_parse("found permissions for '%s'", class_dev->name);=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= }=0A= }=0A= =0A= static int get_attr(struct sysfs_class_device *class_dev, struct udevice = *udev)=0A= {=0A= struct sysfs_device *sysfs_device =3D NULL;=0A= struct sysfs_class_device *class_dev_parent =3D NULL;=0A= int retval =3D 0;=0A= char *temp =3D NULL;=0A= =0A= udev->mode =3D 0;=0A= =0A= /* find the sysfs_device for this class device */=0A= /* Wouldn't it really be nice if libsysfs could do this for us? */=0A= if (class_dev->sysdevice) {=0A= sysfs_device =3D class_dev->sysdevice;=0A= } else {=0A= /* bah, let's go backwards up a level to see if the device is there,=0A= * as block partitions don't point to the physical device. Need to = fix that=0A= * up in the kernel...=0A= */=0A= if (strstr(class_dev->path, "block")) {=0A= dbg_parse("looking at block device...");=0A= if (isdigit(class_dev->path[strlen(class_dev->path)-1])) {=0A= char path[SYSFS_PATH_MAX];=0A= =0A= dbg_parse("really is a partition...");=0A= strfieldcpy(path, class_dev->path);=0A= temp =3D strrchr(path, '/');=0A= *temp =3D 0x00;=0A= dbg_parse("looking for a class device at '%s'", path);=0A= class_dev_parent =3D sysfs_open_class_device(path);=0A= if (class_dev_parent =3D=3D NULL) {=0A= dbg("sysfs_open_class_device at '%s' failed", path);=0A= } else {=0A= dbg_parse("class_dev_parent->name=3D%s", class_dev_parent->name);=0A= if (class_dev_parent->sysdevice)=0A= sysfs_device =3D class_dev_parent->sysdevice;=0A= }=0A= }=0A= }=0A= }=0A= =0A= if (sysfs_device) {=0A= dbg_parse("sysfs_device->path=3D'%s'", sysfs_device->path);=0A= dbg_parse("sysfs_device->bus_id=3D'%s'", sysfs_device->bus_id);=0A= strfieldcpy(udev->bus_id, sysfs_device->bus_id);=0A= } else {=0A= dbg_parse("class_dev->name =3D '%s'", class_dev->name);=0A= }=0A= =0A= build_kernel_number(class_dev, udev);=0A= =0A= /* rules are looked at in priority order */=0A= retval =3D do_callout(class_dev, udev);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_label(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_number(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_topology(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_replace(class_dev, udev);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= do_kernelname(class_dev, udev);=0A= goto done;=0A= =0A= found:=0A= /* substitute placeholder in NAME */=0A= apply_format(udev, udev->name);=0A= =0A= done:=0A= /* mode was never set above */=0A= if (!udev->mode) {=0A= udev->mode =3D get_default_mode(class_dev);=0A= udev->owner[0] =3D 0x00;=0A= udev->group[0] =3D 0x00;=0A= }=0A= =0A= if (class_dev_parent)=0A= sysfs_close_class_device(class_dev_parent);=0A= =0A= return 0;=0A= }=0A= =0A= int namedev_name_device(struct sysfs_class_device *class_dev, struct = udevice *dev)=0A= {=0A= int retval;=0A= =0A= retval =3D get_attr(class_dev, dev);=0A= if (retval)=0A= dbg("get_attr failed");=0A= =0A= return retval;=0A= }=0A= =0A= int namedev_init(void)=0A= {=0A= int retval;=0A= =0A= retval =3D namedev_init_config();=0A= if (retval)=0A= return retval;=0A= =0A= retval =3D namedev_init_permissions();=0A= if (retval)=0A= return retval;=0A= =0A= dump_dev_list();=0A= return retval;=0A= }=0A= ------=_NextPart_000_01BB_01C3B37F.EE750210 Content-Type: application/octet-stream; name="namedev.c.diff" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="namedev.c.diff" *** namedev.c.org Tue Nov 25 17:48:47 2003=0A= --- namedev.c Tue Nov 25 17:45:27 2003=0A= ***************=0A= *** 298,310 ****=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= ! /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= ! retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= ! strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s'",=0A= dev.name, dev.bus, dev.id);=0A= }=0A= --- 298,320 ----=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= ! /* file=3D"value" OR NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= ! retval =3D get_pair(&temp, &temp2, &temp3);=0A= if (retval)=0A= break;=0A= ! if(strcmp("NAME", temp2) !=3D 0) {=0A= ! /* file=3D"value" */=0A= ! strfieldcpy(dev.sysfs_file, temp2);=0A= ! strfieldcpy(dev.sysfs_value, temp3);=0A= ! /* NAME=3D"new_name" */=0A= ! temp2 =3D strsep(&temp, ",");=0A= ! retval =3D get_value("NAME", &temp, &temp3);=0A= =0A= + dbg_parse("sysfs_file=3D'%s' sysfs_value=3D'%s'",=0A= + dev.sysfs_file, dev.sysfs_value);=0A= + }=0A= + strfieldcpy(dev.name, temp3);=0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s'",=0A= dev.name, dev.bus, dev.id);=0A= }=0A= ***************=0A= *** 520,525 ****=0A= --- 530,536 ----=0A= case 'n':=0A= if (strlen(udev->kernel_number) =3D=3D 0)=0A= break;=0A= + strcat(pos, "s");=0A= strcat(pos, udev->kernel_number);=0A= dbg("substitute kernel number '%s'", udev->kernel_number);=0A= break;=0A= ***************=0A= *** 724,729 ****=0A= --- 735,741 ----=0A= char path[SYSFS_PATH_MAX];=0A= int found;=0A= char *temp =3D NULL;=0A= + struct sysfs_attribute *tmpattr =3D NULL;=0A= =0A= /* we have to have a sysfs device for NUMBER to work */=0A= if (!sysfs_device)=0A= ***************=0A= *** 749,754 ****=0A= --- 761,797 ----=0A= }=0A= if (!found)=0A= continue;=0A= + =0A= + dbg_parse(" device_type =3D %s\n", dev->sysfs_file);=0A= + if (strcmp(dev->sysfs_file, "device_type") =3D=3D 0) {=0A= + dbg_parse("look for device_type attribute '%s'",=0A= + dev->sysfs_file);=0A= + /* try to find the attribute in the class device directory */=0A= + tmpattr =3D sysfs_get_classdev_attr(class_dev, dev->sysfs_file);=0A= + if (tmpattr)=0A= + goto number_found;=0A= + =0A= + /* look in the class device directory if present */=0A= + if (sysfs_device) {=0A= + tmpattr =3D sysfs_get_device_attr(sysfs_device, dev->sysfs_file);=0A= + if (tmpattr)=0A= + goto number_found;=0A= + }=0A= + =0A= + continue;=0A= + number_found:=0A= + tmpattr->value[strlen(tmpattr->value)-1] =3D '\0';=0A= + dbg_parse("compare attribute '%s' value '%s' with '%s'",=0A= + dev->sysfs_file, tmpattr->value,=0A= + dev->sysfs_value);=0A= + if (strncmp(dev->sysfs_value, tmpattr->value, = strlen(dev->sysfs_value)) !=3D 0)=0A= + continue;=0A= + =0A= + dbg_parse("found matching attribute '%s', '%s' becomes"=0A= + " '%s' - owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= + dev->sysfs_file, class_dev->name, udev->name,=0A= + dev->owner, dev->group, dev->mode);=0A= + }=0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= ------=_NextPart_000_01BB_01C3B37F.EE750210 Content-Type: application/octet-stream; name="namedev.c" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="namedev.c" /*=0A= * namedev.c=0A= *=0A= * Userspace devfs=0A= *=0A= * Copyright (C) 2003 Greg Kroah-Hartman =0A= *=0A= *=0A= * This program is free software; you can redistribute it and/or modify = it=0A= * under the terms of the GNU General Public License as published by the=0A= * Free Software Foundation version 2 of the License.=0A= * =0A= * This program is distributed in the hope that it will be useful, but=0A= * WITHOUT ANY WARRANTY; without even the implied warranty of=0A= * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU=0A= * General Public License for more details.=0A= * =0A= * You should have received a copy of the GNU General Public License = along=0A= * with this program; if not, write to the Free Software Foundation, = Inc.,=0A= * 675 Mass Ave, Cambridge, MA 02139, USA.=0A= *=0A= */=0A= =0A= /* define this to enable parsing debugging */=0A= /* #define DEBUG_PARSER */=0A= =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= #include =0A= =0A= #include "list.h"=0A= #include "udev.h"=0A= #include "udev_version.h"=0A= #include "namedev.h"=0A= #include "libsysfs/libsysfs.h"=0A= #include "klibc_fixups.h"=0A= =0A= #define TYPE_LABEL "LABEL"=0A= #define TYPE_NUMBER "NUMBER"=0A= #define TYPE_TOPOLOGY "TOPOLOGY"=0A= #define TYPE_REPLACE "REPLACE"=0A= #define TYPE_CALLOUT "CALLOUT"=0A= #define CALLOUT_MAXARG 8=0A= =0A= static LIST_HEAD(config_device_list);=0A= =0A= /* s2 may end with '*' to match everything */=0A= static int strncmp_wildcard(char *s1, char *s2, int max)=0A= {=0A= int len =3D strlen(s2);=0A= if (len > max)=0A= len =3D max;=0A= if (s2[len-1] =3D=3D '*')=0A= len--;=0A= else=0A= len =3D max;=0A= return strncmp(s1, s2, len);=0A= }=0A= =0A= static void dump_dev(struct config_device *dev)=0A= {=0A= switch (dev->type) {=0A= case KERNEL_NAME:=0A= dbg_parse("KERNEL name=3D'%s' ,"=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->owner, dev->group, dev->mode);=0A= break;=0A= case LABEL:=0A= dbg_parse("LABEL name=3D'%s', bus=3D'%s', sysfs_file=3D'%s', = sysfs_value=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->sysfs_file, dev->sysfs_value,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case NUMBER:=0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->id,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case TOPOLOGY:=0A= dbg_parse("TOPOLOGY name=3D'%s', bus=3D'%s', place=3D'%s', "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->place,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case REPLACE:=0A= dbg_parse("REPLACE name=3D%s, kernel_name=3D%s, "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->kernel_name,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= case CALLOUT:=0A= dbg_parse("CALLOUT name=3D'%s', bus=3D'%s', program=3D'%s', id=3D'%s', = "=0A= "owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->name, dev->bus, dev->exec_program, dev->id,=0A= dev->owner, dev->group, dev->mode);=0A= break;=0A= default:=0A= dbg_parse("unknown type of method");=0A= }=0A= }=0A= =0A= #define copy_var(a, b, var) \=0A= if (b->var) \=0A= a->var =3D b->var;=0A= =0A= #define copy_string(a, b, var) \=0A= if (strlen(b->var)) \=0A= strcpy(a->var, b->var);=0A= =0A= static int add_dev(struct config_device *new_dev)=0A= {=0A= struct list_head *tmp;=0A= struct config_device *tmp_dev;=0A= =0A= /* update the values if we already have the device */=0A= list_for_each(tmp, &config_device_list) {=0A= struct config_device *dev =3D list_entry(tmp, struct config_device, = node);=0A= if (strncmp_wildcard(dev->name, new_dev->name, sizeof(dev->name)))=0A= continue;=0A= copy_var(dev, new_dev, type);=0A= copy_var(dev, new_dev, mode);=0A= copy_string(dev, new_dev, bus);=0A= copy_string(dev, new_dev, sysfs_file);=0A= copy_string(dev, new_dev, sysfs_value);=0A= copy_string(dev, new_dev, id);=0A= copy_string(dev, new_dev, place);=0A= copy_string(dev, new_dev, kernel_name);=0A= copy_string(dev, new_dev, owner);=0A= copy_string(dev, new_dev, group);=0A= return 0;=0A= }=0A= =0A= /* not found, add new structure to the device list */=0A= tmp_dev =3D malloc(sizeof(*tmp_dev));=0A= if (!tmp_dev)=0A= return -ENOMEM;=0A= memcpy(tmp_dev, new_dev, sizeof(*tmp_dev));=0A= list_add(&tmp_dev->node, &config_device_list);=0A= //dump_dev(tmp_dev);=0A= return 0;=0A= }=0A= =0A= static void dump_dev_list(void)=0A= {=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= struct config_device *dev =3D list_entry(tmp, struct config_device, = node);=0A= dump_dev(dev);=0A= }=0A= }=0A= =0A= static int get_pair(char **orig_string, char **left, char **right)=0A= {=0A= char *temp;=0A= char *string =3D *orig_string;=0A= =0A= if (!string)=0A= return -ENODEV;=0A= =0A= /* eat any whitespace */=0A= while (isspace(*string))=0A= ++string;=0A= =0A= /* split based on '=3D' */=0A= temp =3D strsep(&string, "=3D");=0A= *left =3D temp;=0A= if (!string)=0A= return -ENODEV;=0A= =0A= /* take the right side and strip off the '"' */=0A= while (isspace(*string))=0A= ++string;=0A= if (*string =3D=3D '"')=0A= ++string;=0A= else=0A= return -ENODEV;=0A= =0A= temp =3D strsep(&string, "\"");=0A= if (!string || *temp =3D=3D '\0')=0A= return -ENODEV;=0A= *right =3D temp;=0A= *orig_string =3D string;=0A= =0A= return 0;=0A= }=0A= =0A= static int get_value(const char *left, char **orig_string, char = **ret_string)=0A= {=0A= int retval;=0A= char *left_string;=0A= =0A= retval =3D get_pair(orig_string, &left_string, ret_string);=0A= if (retval)=0A= return retval;=0A= if (strcasecmp(left_string, left) !=3D 0)=0A= return -ENODEV;=0A= return 0;=0A= }=0A= =0A= static int namedev_init_config(void)=0A= {=0A= char line[255];=0A= int lineno;=0A= char *temp;=0A= char *temp2;=0A= char *temp3;=0A= FILE *fd;=0A= int retval =3D 0;=0A= struct config_device dev;=0A= =0A= dbg("opening %s to read as config", udev_config_filename);=0A= fd =3D fopen(udev_config_filename, "r");=0A= if (fd =3D=3D NULL) {=0A= dbg("can't open %s", udev_config_filename);=0A= return -ENODEV;=0A= }=0A= =0A= /* loop through the whole file */=0A= lineno =3D 0;=0A= while (1) {=0A= /* get a line */=0A= temp =3D fgets(line, sizeof(line), fd);=0A= if (temp =3D=3D NULL)=0A= goto exit;=0A= lineno++;=0A= =0A= dbg_parse("read %s", temp);=0A= =0A= /* eat the whitespace at the beginning of the line */=0A= while (isspace(*temp))=0A= ++temp;=0A= =0A= /* empty line? */=0A= if (*temp =3D=3D 0x00)=0A= continue;=0A= =0A= /* see if this is a comment */=0A= if (*temp =3D=3D COMMENT_CHARACTER)=0A= continue;=0A= =0A= memset(&dev, 0x00, sizeof(struct config_device));=0A= =0A= /* parse the line */=0A= temp2 =3D strsep(&temp, ",");=0A= if (strcasecmp(temp2, TYPE_LABEL) =3D=3D 0) {=0A= /* label type */=0A= dev.type =3D LABEL;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* file=3D"value" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_pair(&temp, &temp2, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.sysfs_file, temp2);=0A= strfieldcpy(dev.sysfs_value, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("LABEL name=3D'%s', bus=3D'%s', "=0A= "sysfs_file=3D'%s', sysfs_value=3D'%s'",=0A= dev.name, dev.bus, dev.sysfs_file,=0A= dev.sysfs_value);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_NUMBER) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D NUMBER;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* ID=3D"id" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("ID", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= /* file=3D"value" OR NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_pair(&temp, &temp2, &temp3);=0A= if (retval)=0A= break;=0A= if(strcmp("NAME", temp2) !=3D 0) {=0A= /* file=3D"value" */=0A= strfieldcpy(dev.sysfs_file, temp2);=0A= strfieldcpy(dev.sysfs_value, temp3);=0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= =0A= dbg_parse("sysfs_file=3D'%s' sysfs_value=3D'%s'",=0A= dev.sysfs_file, dev.sysfs_value);=0A= }=0A= strfieldcpy(dev.name, temp3);=0A= dbg_parse("NUMBER name=3D'%s', bus=3D'%s', id=3D'%s'",=0A= dev.name, dev.bus, dev.id);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_TOPOLOGY) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D TOPOLOGY;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* PLACE=3D"place" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("PLACE", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.place, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= =0A= dbg_parse("TOPOLOGY name=3D'%s', bus=3D'%s', place=3D'%s'",=0A= dev.name, dev.bus, dev.place);=0A= }=0A= =0A= if (strcasecmp(temp2, TYPE_REPLACE) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D REPLACE;=0A= =0A= /* KERNEL=3D"kernel_name" */=0A= retval =3D get_value("KERNEL", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.kernel_name, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= dbg_parse("REPLACE name=3D'%s', kernel_name=3D'%s'",=0A= dev.name, dev.kernel_name);=0A= }=0A= if (strcasecmp(temp2, TYPE_CALLOUT) =3D=3D 0) {=0A= /* number type */=0A= dev.type =3D CALLOUT;=0A= =0A= /* BUS=3D"bus" */=0A= retval =3D get_value("BUS", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.bus, temp3);=0A= =0A= /* PROGRAM=3D"executable" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("PROGRAM", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.exec_program, temp3);=0A= =0A= /* ID=3D"id" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("ID", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.id, temp3);=0A= =0A= /* NAME=3D"new_name" */=0A= temp2 =3D strsep(&temp, ",");=0A= retval =3D get_value("NAME", &temp, &temp3);=0A= if (retval)=0A= break;=0A= strfieldcpy(dev.name, temp3);=0A= dbg_parse("CALLOUT name=3D'%s', program=3D'%s'",=0A= dev.name, dev.exec_program);=0A= }=0A= =0A= retval =3D add_dev(&dev);=0A= if (retval) {=0A= dbg("add_dev returned with error %d", retval);=0A= goto exit;=0A= }=0A= }=0A= dbg_parse("%s:%d:%Zd: error parsing '%s'", udev_config_filename,=0A= lineno, temp - line, temp);=0A= exit:=0A= fclose(fd);=0A= return retval;=0A= } =0A= =0A= =0A= static int namedev_init_permissions(void)=0A= {=0A= char line[255];=0A= char *temp;=0A= char *temp2;=0A= FILE *fd;=0A= int retval =3D 0;=0A= struct config_device dev;=0A= =0A= dbg("opening %s to read as permissions config", = udev_config_permission_filename);=0A= fd =3D fopen(udev_config_permission_filename, "r");=0A= if (fd =3D=3D NULL) {=0A= dbg("can't open %s", udev_config_permission_filename);=0A= return -ENODEV;=0A= }=0A= =0A= /* loop through the whole file */=0A= while (1) {=0A= temp =3D fgets(line, sizeof(line), fd);=0A= if (temp =3D=3D NULL)=0A= break;=0A= =0A= dbg_parse("read %s", temp);=0A= =0A= /* eat the whitespace at the beginning of the line */=0A= while (isspace(*temp))=0A= ++temp;=0A= =0A= /* empty line? */=0A= if (*temp =3D=3D 0x00)=0A= continue;=0A= =0A= /* see if this is a comment */=0A= if (*temp =3D=3D COMMENT_CHARACTER)=0A= continue;=0A= =0A= memset(&dev, 0x00, sizeof(dev));=0A= =0A= /* parse the line */=0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.name, temp2, sizeof(dev.name));=0A= =0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.owner, temp2, sizeof(dev.owner));=0A= =0A= temp2 =3D strsep(&temp, ":");=0A= if (!temp2) {=0A= dbg("cannot parse line: %s", line);=0A= continue;=0A= }=0A= strncpy(dev.group, temp2, sizeof(dev.owner));=0A= =0A= dev.mode =3D strtol(temp, NULL, 8);=0A= =0A= dbg_parse("name=3D'%s', owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev.name, dev.owner, dev.group,=0A= dev.mode);=0A= retval =3D add_dev(&dev);=0A= if (retval) {=0A= dbg("add_dev returned with error %d", retval);=0A= goto exit;=0A= }=0A= }=0A= =0A= exit:=0A= fclose(fd);=0A= return retval;=0A= } =0A= =0A= static mode_t get_default_mode(struct sysfs_class_device *class_dev)=0A= {=0A= /* just default everyone to rw for the world! */=0A= return 0666;=0A= }=0A= =0A= static void build_kernel_number(struct sysfs_class_device *class_dev, = struct udevice *udev)=0A= {=0A= char *dig;=0A= =0A= /* FIXME, figure out how to handle stuff like sdaj which will not work = right now. */=0A= dig =3D class_dev->name + strlen(class_dev->name);=0A= while (isdigit(*(dig-1)))=0A= dig--;=0A= strfieldcpy(udev->kernel_number, dig);=0A= dbg("kernel_number =3D %s", udev->kernel_number);=0A= }=0A= =0A= static void apply_format(struct udevice *udev, unsigned char *string)=0A= {=0A= char name[NAME_SIZE];=0A= char *pos;=0A= =0A= while (1) {=0A= pos =3D strchr(string, '%');=0A= =0A= if (pos) {=0A= strfieldcpy(name, pos+2);=0A= *pos =3D 0x00;=0A= switch (pos[1]) {=0A= case 'b':=0A= if (strlen(udev->bus_id) =3D=3D 0)=0A= break;=0A= strcat(string, udev->bus_id);=0A= dbg("substitute bus_id '%s'", udev->bus_id);=0A= break;=0A= case 'n':=0A= if (strlen(udev->kernel_number) =3D=3D 0)=0A= break;=0A= strcat(pos, "s");=0A= strcat(pos, udev->kernel_number);=0A= dbg("substitute kernel number '%s'", udev->kernel_number);=0A= break;=0A= case 'm':=0A= sprintf(pos, "%u", udev->minor);=0A= dbg("substitute minor number '%u'", udev->minor);=0A= break;=0A= case 'M':=0A= sprintf(pos, "%u", udev->major);=0A= dbg("substitute major number '%u'", udev->major);=0A= break;=0A= case 'c':=0A= if (strlen(udev->callout_value) =3D=3D 0)=0A= break;=0A= strcat(pos, udev->callout_value);=0A= dbg("substitute callout output '%s'", udev->callout_value);=0A= break;=0A= default:=0A= dbg("unknown substitution type '%%%c'", pos[1]);=0A= break;=0A= }=0A= strcat(string, name);=0A= } else=0A= break;=0A= }=0A= }=0A= =0A= =0A= static int exec_callout(struct config_device *dev, char *value, int len)=0A= {=0A= int retval;=0A= int res;=0A= int status;=0A= int fds[2];=0A= pid_t pid;=0A= int value_set =3D 0;=0A= char buffer[256];=0A= char *arg;=0A= char *args[CALLOUT_MAXARG];=0A= int i;=0A= =0A= dbg("callout to '%s'", dev->exec_program);=0A= retval =3D pipe(fds);=0A= if (retval !=3D 0) {=0A= dbg("pipe failed");=0A= return -1;=0A= }=0A= pid =3D fork();=0A= if (pid =3D=3D -1) {=0A= dbg("fork failed");=0A= return -1;=0A= }=0A= =0A= if (pid =3D=3D 0) {=0A= /* child */=0A= close(STDOUT_FILENO);=0A= dup(fds[1]); /* dup write side of pipe to STDOUT */=0A= if (strchr(dev->exec_program, ' ')) {=0A= /* callout with arguments */=0A= arg =3D dev->exec_program;=0A= for (i=3D0; i < CALLOUT_MAXARG-1; i++) {=0A= args[i] =3D strsep(&arg, " ");=0A= if (args[i] =3D=3D NULL)=0A= break;=0A= }=0A= if (args[i]) {=0A= dbg("too many args - %d", i);=0A= args[i] =3D NULL;=0A= }=0A= retval =3D execve(args[0], args, main_envp);=0A= } else {=0A= retval =3D execve(dev->exec_program, main_argv, main_envp);=0A= }=0A= if (retval !=3D 0) {=0A= dbg("child execve failed");=0A= exit(1);=0A= }=0A= return -1; /* avoid compiler warning */=0A= } else {=0A= /* parent reads from fds[0] */=0A= close(fds[1]);=0A= retval =3D 0;=0A= while (1) {=0A= res =3D read(fds[0], buffer, sizeof(buffer) - 1);=0A= if (res <=3D 0)=0A= break;=0A= buffer[res] =3D '\0';=0A= if (res > len) {=0A= dbg("callout len %d too short\n", len);=0A= retval =3D -1;=0A= }=0A= if (value_set) {=0A= dbg("callout value already set");=0A= retval =3D -1;=0A= } else {=0A= value_set =3D 1;=0A= strncpy(value, buffer, len);=0A= }=0A= }=0A= dbg("callout returned '%s'", value);=0A= close(fds[0]);=0A= res =3D wait(&status);=0A= if (res < 0) {=0A= dbg("wait failed result %d", res);=0A= retval =3D -1;=0A= }=0A= =0A= #ifndef __KLIBC__=0A= if (!WIFEXITED(status) || (WEXITSTATUS(status) !=3D 0)) {=0A= dbg("callout program status 0x%x", status);=0A= retval =3D -1;=0A= }=0A= #endif=0A= }=0A= return retval;=0A= }=0A= =0A= static int do_callout(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D CALLOUT)=0A= continue;=0A= =0A= /* substitute anything that needs to be in the program name */=0A= apply_format(udev, dev->exec_program);=0A= if (exec_callout(dev, udev->callout_value, NAME_SIZE))=0A= continue;=0A= if (strncmp_wildcard(udev->callout_value, dev->id, NAME_SIZE) !=3D 0)=0A= continue;=0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("callout returned matching value '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group=3D'%s', mode =3D%#o",=0A= dev->id, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_label(struct sysfs_class_device *class_dev, struct udevice = *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct sysfs_attribute *tmpattr =3D NULL;=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D LABEL)=0A= continue;=0A= =0A= dbg_parse("look for device attribute '%s'", dev->sysfs_file);=0A= /* try to find the attribute in the class device directory */=0A= tmpattr =3D sysfs_get_classdev_attr(class_dev, dev->sysfs_file);=0A= if (tmpattr)=0A= goto label_found;=0A= =0A= /* look in the class device directory if present */=0A= if (sysfs_device) {=0A= tmpattr =3D sysfs_get_device_attr(sysfs_device, dev->sysfs_file);=0A= if (tmpattr)=0A= goto label_found;=0A= }=0A= =0A= continue;=0A= =0A= label_found:=0A= tmpattr->value[strlen(tmpattr->value)-1] =3D 0x00;=0A= dbg_parse("compare attribute '%s' value '%s' with '%s'",=0A= dev->sysfs_file, tmpattr->value, dev->sysfs_value);=0A= if (strcmp(dev->sysfs_value, tmpattr->value) !=3D 0)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching attribute '%s', '%s' becomes '%s' "=0A= "- owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->sysfs_file, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= =0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_number(struct sysfs_class_device *class_dev, struct = udevice *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= char path[SYSFS_PATH_MAX];=0A= int found;=0A= char *temp =3D NULL;=0A= struct sysfs_attribute *tmpattr =3D NULL;=0A= =0A= /* we have to have a sysfs device for NUMBER to work */=0A= if (!sysfs_device)=0A= return -ENODEV;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D NUMBER)=0A= continue;=0A= =0A= found =3D 0;=0A= strfieldcpy(path, sysfs_device->path);=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->id, temp, path);=0A= if (strstr(temp, dev->id) !=3D NULL) {=0A= found =3D 1;=0A= } else {=0A= *temp =3D 0x00;=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->id, temp, path);=0A= if (strstr(temp, dev->id) !=3D NULL)=0A= found =3D 1;=0A= }=0A= if (!found)=0A= continue;=0A= =0A= if (strcmp(dev->sysfs_file, "device_type") =3D=3D 0) {=0A= dbg_parse("look for device_type attribute '%s'",=0A= dev->sysfs_file);=0A= /* try to find the attribute in the class device directory */=0A= tmpattr =3D sysfs_get_classdev_attr(class_dev, dev->sysfs_file);=0A= if (tmpattr)=0A= goto number_found;=0A= =0A= /* look in the class device directory if present */=0A= if (sysfs_device) {=0A= tmpattr =3D sysfs_get_device_attr(sysfs_device, dev->sysfs_file);=0A= if (tmpattr)=0A= goto number_found;=0A= }=0A= =0A= continue;=0A= number_found:=0A= tmpattr->value[strlen(tmpattr->value)-1] =3D '\0';=0A= dbg_parse("compare attribute '%s' value '%s' with '%s'",=0A= dev->sysfs_file, tmpattr->value,=0A= dev->sysfs_value);=0A= if (strncmp(dev->sysfs_value, tmpattr->value, = strlen(dev->sysfs_value)) !=3D 0)=0A= continue;=0A= =0A= dbg_parse("found matching attribute '%s', '%s' becomes"=0A= " '%s' - owner=3D'%s', group=3D'%s', mode=3D%#o",=0A= dev->sysfs_file, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= }=0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching id '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group =3D'%s', mode=3D%#o",=0A= dev->id, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= =0A= static int do_topology(struct sysfs_class_device *class_dev, struct = udevice *udev, struct sysfs_device *sysfs_device)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= char path[SYSFS_PATH_MAX];=0A= int found;=0A= char *temp =3D NULL;=0A= =0A= /* we have to have a sysfs device for TOPOLOGY to work */=0A= if (!sysfs_device)=0A= return -ENODEV;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D TOPOLOGY)=0A= continue;=0A= =0A= found =3D 0;=0A= strfieldcpy(path, sysfs_device->path);=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->place, temp, path);=0A= if (strstr(temp, dev->place) !=3D NULL) {=0A= found =3D 1;=0A= } else {=0A= *temp =3D 0x00;=0A= temp =3D strrchr(path, '/');=0A= dbg_parse("search '%s' in '%s', path=3D'%s'", dev->place, temp, path);=0A= if (strstr(temp, dev->place) !=3D NULL)=0A= found =3D 1;=0A= }=0A= if (!found)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found matching place '%s', '%s' becomes '%s'"=0A= " - owner=3D'%s', group =3D'%s', mode=3D%#o",=0A= dev->place, class_dev->name, udev->name,=0A= dev->owner, dev->group, dev->mode);=0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static int do_replace(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= =0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= if (dev->type !=3D REPLACE)=0A= continue;=0A= =0A= dbg_parse("compare name '%s' with '%s'",=0A= dev->kernel_name, dev->name);=0A= if (strcmp(dev->kernel_name, class_dev->name) !=3D 0)=0A= continue;=0A= =0A= strfieldcpy(udev->name, dev->name);=0A= if (dev->mode !=3D 0) {=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= dbg_parse("found name, '%s' becomes '%s' - owner=3D'%s', group=3D'%s', = mode =3D %#o",=0A= dev->kernel_name, udev->name, =0A= dev->owner, dev->group, dev->mode);=0A= =0A= return 0;=0A= }=0A= return -ENODEV;=0A= }=0A= =0A= static void do_kernelname(struct sysfs_class_device *class_dev, struct = udevice *udev)=0A= {=0A= struct config_device *dev;=0A= struct list_head *tmp;=0A= int len;=0A= =0A= strfieldcpy(udev->name, class_dev->name);=0A= /* look for permissions */=0A= list_for_each(tmp, &config_device_list) {=0A= dev =3D list_entry(tmp, struct config_device, node);=0A= len =3D strlen(dev->name);=0A= if (strncmp_wildcard(class_dev->name, dev->name, sizeof(dev->name)))=0A= continue;=0A= if (dev->mode !=3D 0) {=0A= dbg_parse("found permissions for '%s'", class_dev->name);=0A= udev->mode =3D dev->mode;=0A= strfieldcpy(udev->owner, dev->owner);=0A= strfieldcpy(udev->group, dev->group);=0A= }=0A= }=0A= }=0A= =0A= static int get_attr(struct sysfs_class_device *class_dev, struct udevice = *udev)=0A= {=0A= struct sysfs_device *sysfs_device =3D NULL;=0A= struct sysfs_class_device *class_dev_parent =3D NULL;=0A= int retval =3D 0;=0A= char *temp =3D NULL;=0A= =0A= udev->mode =3D 0;=0A= =0A= /* find the sysfs_device for this class device */=0A= /* Wouldn't it really be nice if libsysfs could do this for us? */=0A= if (class_dev->sysdevice) {=0A= sysfs_device =3D class_dev->sysdevice;=0A= } else {=0A= /* bah, let's go backwards up a level to see if the device is there,=0A= * as block partitions don't point to the physical device. Need to = fix that=0A= * up in the kernel...=0A= */=0A= if (strstr(class_dev->path, "block")) {=0A= dbg_parse("looking at block device...");=0A= if (isdigit(class_dev->path[strlen(class_dev->path)-1])) {=0A= char path[SYSFS_PATH_MAX];=0A= =0A= dbg_parse("really is a partition...");=0A= strfieldcpy(path, class_dev->path);=0A= temp =3D strrchr(path, '/');=0A= *temp =3D 0x00;=0A= dbg_parse("looking for a class device at '%s'", path);=0A= class_dev_parent =3D sysfs_open_class_device(path);=0A= if (class_dev_parent =3D=3D NULL) {=0A= dbg("sysfs_open_class_device at '%s' failed", path);=0A= } else {=0A= dbg_parse("class_dev_parent->name=3D%s", class_dev_parent->name);=0A= if (class_dev_parent->sysdevice)=0A= sysfs_device =3D class_dev_parent->sysdevice;=0A= }=0A= }=0A= }=0A= }=0A= =0A= if (sysfs_device) {=0A= dbg_parse("sysfs_device->path=3D'%s'", sysfs_device->path);=0A= dbg_parse("sysfs_device->bus_id=3D'%s'", sysfs_device->bus_id);=0A= strfieldcpy(udev->bus_id, sysfs_device->bus_id);=0A= } else {=0A= dbg_parse("class_dev->name =3D '%s'", class_dev->name);=0A= }=0A= =0A= build_kernel_number(class_dev, udev);=0A= =0A= /* rules are looked at in priority order */=0A= retval =3D do_callout(class_dev, udev);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_label(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_number(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_topology(class_dev, udev, sysfs_device);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= retval =3D do_replace(class_dev, udev);=0A= if (retval =3D=3D 0)=0A= goto found;=0A= =0A= do_kernelname(class_dev, udev);=0A= goto done;=0A= =0A= found:=0A= /* substitute placeholder in NAME */=0A= apply_format(udev, udev->name);=0A= =0A= done:=0A= /* mode was never set above */=0A= if (!udev->mode) {=0A= udev->mode =3D get_default_mode(class_dev);=0A= udev->owner[0] =3D 0x00;=0A= udev->group[0] =3D 0x00;=0A= }=0A= =0A= if (class_dev_parent)=0A= sysfs_close_class_device(class_dev_parent);=0A= =0A= return 0;=0A= }=0A= =0A= int namedev_name_device(struct sysfs_class_device *class_dev, struct = udevice *dev)=0A= {=0A= int retval;=0A= =0A= retval =3D get_attr(class_dev, dev);=0A= if (retval)=0A= dbg("get_attr failed");=0A= =0A= return retval;=0A= }=0A= =0A= int namedev_init(void)=0A= {=0A= int retval;=0A= =0A= retval =3D namedev_init_config();=0A= if (retval)=0A= return retval;=0A= =0A= retval =3D namedev_init_permissions();=0A= if (retval)=0A= return retval;=0A= =0A= dump_dev_list();=0A= return retval;=0A= }=0A= ------=_NextPart_000_01BB_01C3B37F.EE750210-- ------------------------------------------------------- This SF.net email is sponsored by: SF.net Giveback Program. Does SourceForge.net help you be more productive? Does it help you create better code? SHARE THE LOVE, and help us help YOU! Click Here: http://sourceforge.net/donate/ _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel