6 * Copyright (C) 2003,2004 Greg Kroah-Hartman <greg@kroah.com>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation version 2 of the License.
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* define this to enable parsing debugging also */
26 /* #define DEBUG_PARSER */
42 static int add_config_dev(struct config_device
*new_dev
)
44 struct config_device
*tmp_dev
;
46 tmp_dev
= malloc(sizeof(*tmp_dev
));
49 memcpy(tmp_dev
, new_dev
, sizeof(*tmp_dev
));
50 list_add_tail(&tmp_dev
->node
, &config_device_list
);
51 //dump_config_dev(tmp_dev);
55 void dump_config_dev(struct config_device
*dev
)
57 /*FIXME dump all sysfs's */
58 dbg_parse("name='%s', symlink='%s', bus='%s', place='%s', id='%s', "
59 "sysfs_file[0]='%s', sysfs_value[0]='%s', "
60 "kernel='%s', program='%s', result='%s'",
61 dev
->name
, dev
->symlink
, dev
->bus
, dev
->place
, dev
->id
,
62 dev
->sysfs_pair
[0].file
, dev
->sysfs_pair
[0].value
,
63 dev
->kernel
, dev
->program
, dev
->result
);
66 void dump_config_dev_list(void)
68 struct config_device
*dev
;
70 list_for_each_entry(dev
, &config_device_list
, node
)
74 void dump_perm_dev(struct perm_device
*dev
)
76 dbg_parse("name='%s', owner='%s', group='%s', mode=%#o",
77 dev
->name
, dev
->owner
, dev
->group
, dev
->mode
);
80 void dump_perm_dev_list(void)
82 struct perm_device
*dev
;
84 list_for_each_entry(dev
, &perm_device_list
, node
)
88 int namedev_init_rules(void)
96 int program_given
= 0;
98 struct config_device dev
;
100 fd
= fopen(udev_rules_filename
, "r");
102 dbg("reading '%s' as rules file", udev_rules_filename
);
104 dbg("can't open '%s' as a rules file", udev_rules_filename
);
108 /* loop through the whole file */
112 temp
= fgets(line
, sizeof(line
), fd
);
116 dbg_parse("read '%s'", temp
);
118 /* eat the whitespace */
119 while (isspace(*temp
))
123 if ((*temp
== '\0') || (*temp
== '\n'))
126 /* see if this is a comment */
127 if (*temp
== COMMENT_CHARACTER
)
130 memset(&dev
, 0x00, sizeof(struct config_device
));
132 /* get all known keys */
134 retval
= parse_get_pair(&temp
, &temp2
, &temp3
);
138 if (strcasecmp(temp2
, FIELD_BUS
) == 0) {
139 strfieldcpy(dev
.bus
, temp3
);
143 if (strcasecmp(temp2
, FIELD_ID
) == 0) {
144 strfieldcpy(dev
.id
, temp3
);
148 if (strcasecmp(temp2
, FIELD_PLACE
) == 0) {
149 strfieldcpy(dev
.place
, temp3
);
153 if (strncasecmp(temp2
, FIELD_SYSFS
, sizeof(FIELD_SYSFS
)-1) == 0) {
154 struct sysfs_pair
*pair
= &dev
.sysfs_pair
[0];
155 int sysfs_pair_num
= 0;
157 /* find first unused pair */
158 while (pair
->file
[0] != '\0') {
160 if (sysfs_pair_num
>= MAX_SYSFS_PAIRS
) {
167 /* remove prepended 'SYSFS_' */
168 strfieldcpy(pair
->file
, temp2
+ sizeof(FIELD_SYSFS
)-1);
169 strfieldcpy(pair
->value
, temp3
);
174 if (strcasecmp(temp2
, FIELD_KERNEL
) == 0) {
175 strfieldcpy(dev
.kernel
, temp3
);
179 if (strcasecmp(temp2
, FIELD_PROGRAM
) == 0) {
181 strfieldcpy(dev
.program
, temp3
);
185 if (strcasecmp(temp2
, FIELD_RESULT
) == 0) {
186 strfieldcpy(dev
.result
, temp3
);
190 if (strcasecmp(temp2
, FIELD_NAME
) == 0) {
191 strfieldcpy(dev
.name
, temp3
);
195 if (strcasecmp(temp2
, FIELD_SYMLINK
) == 0) {
196 strfieldcpy(dev
.symlink
, temp3
);
200 dbg("unknown type of field '%s'", temp2
);
201 dbg("You might be using a rules file in the old format, please fix.");
205 /* simple plausibility check for given keys */
206 if ((dev
.sysfs_pair
[0].file
[0] == '\0') ^
207 (dev
.sysfs_pair
[0].value
[0] == '\0')) {
208 dbg("inconsistency in SYSFS_ key");
212 if ((dev
.result
[0] != '\0') && (program_given
== 0)) {
213 dbg("RESULT is only useful when PROGRAM called in any rule before");
217 dev
.config_line
= lineno
;
218 retval
= add_config_dev(&dev
);
220 dbg("add_config_dev returned with error %d", retval
);
223 dbg("%s:%d:%d: parse error, rule skipped",
224 udev_rules_filename
, lineno
, temp
- line
);
232 int namedev_init_permissions(void)
239 struct perm_device dev
;
241 fd
= fopen(udev_permissions_filename
, "r");
243 dbg("reading '%s' as permissions file", udev_permissions_filename
);
245 dbg("can't open '%s' as permissions file", udev_permissions_filename
);
249 /* loop through the whole file */
251 temp
= fgets(line
, sizeof(line
), fd
);
255 dbg_parse("read '%s'", temp
);
257 /* eat the whitespace at the beginning of the line */
258 while (isspace(*temp
))
262 if ((*temp
== '\0') || (*temp
== '\n'))
265 /* see if this is a comment */
266 if (*temp
== COMMENT_CHARACTER
)
269 memset(&dev
, 0x00, sizeof(dev
));
272 temp2
= strsep(&temp
, ":");
274 dbg("cannot parse line '%s'", line
);
277 strncpy(dev
.name
, temp2
, sizeof(dev
.name
));
279 temp2
= strsep(&temp
, ":");
281 dbg("cannot parse line '%s'", line
);
284 strncpy(dev
.owner
, temp2
, sizeof(dev
.owner
));
286 temp2
= strsep(&temp
, ":");
288 dbg("cannot parse line '%s'", line
);
291 strncpy(dev
.group
, temp2
, sizeof(dev
.group
));
294 dbg("cannot parse line: %s", line
);
297 dev
.mode
= strtol(temp
, NULL
, 8);
299 dbg_parse("name='%s', owner='%s', group='%s', mode=%#o",
300 dev
.name
, dev
.owner
, dev
.group
,
302 retval
= add_perm_dev(&dev
);
304 dbg("add_perm_dev returned with error %d", retval
);