]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/udev/udev-084/udevsynthesize.patch
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / udev / udev-084 / udevsynthesize.patch
1 --- udev-081/udevsynthesize.c.orig      2006-01-29 12:22:45.000000000 +0100
2 +++ udev-081/udevsynthesize.c   2006-01-29 12:22:40.000000000 +0100
3 @@ -0,0 +1,763 @@
4 +/*
5 + * udevcoldplug.c
6 + *
7 + * Copyright (C) 2005 SUSE Linux Products GmbH
8 + *
9 + * Author:
10 + *   Kay Sievers <kay.sievers@vrfy.org>
11 + *
12 + * Synthesize kernel events from sysfs information and pass them
13 + * to the udevd daemon.
14 + *
15 + *     This program is free software; you can redistribute it and/or modify it
16 + *     under the terms of the GNU General Public License as published by the
17 + *     Free Software Foundation version 2 of the License.
18 + * 
19 + *     This program is distributed in the hope that it will be useful, but
20 + *     WITHOUT ANY WARRANTY; without even the implied warranty of
21 + *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 + *     General Public License for more details.
23 + * 
24 + *     You should have received a copy of the GNU General Public License along
25 + *     with this program; if not, write to the Free Software Foundation, Inc.,
26 + *     675 Mass Ave, Cambridge, MA 02139, USA.
27 + *
28 + */
29 +
30 +#include <stdlib.h>
31 +#include <stddef.h>
32 +#include <string.h>
33 +#include <stdio.h>
34 +#include <unistd.h>
35 +#include <errno.h>
36 +#include <ctype.h>
37 +#include <fcntl.h>
38 +#include <dirent.h>
39 +#include <signal.h>
40 +#include <syslog.h>
41 +#include <sys/socket.h>
42 +#include <sys/un.h>
43 +#include <sys/wait.h>
44 +#include <sys/stat.h>
45 +#include <sys/types.h>
46 +
47 +#include "udev_libc_wrapper.h"
48 +#include "udev.h"
49 +#include "udevd.h"
50 +#include "udev_version.h"
51 +#include "logging.h"
52 +
53 +#include "list.h"
54 +
55 +#ifndef DT_DIR
56 +#define DT_DIR                 4
57 +#endif
58 +
59 +static const char *udev_log_str;
60 +static int udevd_sock = -1;
61 +
62 +#ifdef USE_LOG
63 +void log_message(int priority, const char *format, ...)
64 +{
65 +       va_list args;
66 +
67 +       if (priority > udev_log_priority)
68 +               return;
69 +
70 +       va_start(args, format);
71 +       vsyslog(priority, format, args);
72 +       va_end(args);
73 +}
74 +#endif
75 +
76 +struct device {
77 +       struct list_head node;
78 +       struct udevd_msg msg;
79 +       size_t bufpos;
80 +       char *path;
81 +};
82 +
83 +static dev_t read_devt(const char *path)
84 +{
85 +       char filename[PATH_SIZE];
86 +       char majorminor[64];
87 +       unsigned int major, minor;
88 +       ssize_t count;
89 +       int fd;
90 +
91 +       snprintf(filename, sizeof(filename), "%s/%s", path, "dev");
92 +       filename[sizeof(filename)-1] = '\0';
93 +
94 +       fd = open(filename, O_RDONLY);
95 +       if (fd < 0)
96 +               return 0;
97 +
98 +       count = read(fd, majorminor, sizeof(majorminor));
99 +       close(fd);
100 +       majorminor[count] = '\0';
101 +       if (sscanf(majorminor, "%u:%u", &major, &minor) != 2)
102 +               return 0;
103 +       dbg("found major=%d, minor=%d", major, minor);
104 +
105 +       return makedev(major, minor);
106 +}
107 +
108 +static ssize_t read_file(const char *directory, const char *file, char *str, size_t len)
109 +{
110 +       char filename[PATH_SIZE];
111 +       ssize_t count;
112 +       int fd;
113 +
114 +       memset(filename, 0, sizeof(filename));
115 +       snprintf(filename, sizeof(filename), "%s/%s", directory, file);
116 +       filename[sizeof(filename)-1] = '\0';
117 +
118 +       fd = open(filename, O_RDONLY);
119 +       if (fd < 0)
120 +               return -1;
121 +
122 +       count = read(fd, str, len-1);
123 +       close(fd);
124 +
125 +       if (count > (ssize_t)len)
126 +               count = len;
127 +       str[count-1] = '\0';
128 +
129 +       return count;
130 +}
131 +
132 +static ssize_t read_link(const char *directory, const char *file, char *str, size_t size)
133 +{
134 +       char filename[PATH_SIZE];
135 +       char target[PATH_SIZE];
136 +       int len;
137 +       char *back;
138 +       char *strip;
139 +       int level = 1;
140 +
141 +       snprintf(filename, sizeof(filename), "%s/%s", directory, file);
142 +       filename[sizeof(filename)-1] = '\0';
143 +
144 +       len = readlink(filename, target, sizeof(target)-1);
145 +       if (len < 0)
146 +               return -1;
147 +       target[len] = '\0';
148 +
149 +       back = target;
150 +       while (strncmp(back, "../", 3) == 0) {
151 +               back += 3;
152 +               level++;
153 +       }
154 +       while(level--) {
155 +               strip = strrchr(filename, '/');
156 +               if (!strip)
157 +                       return -1;
158 +               strip[0] = '\0';
159 +       }
160 +
161 +       snprintf(str, size, "%s/%s", filename, back);
162 +       str[size-1] = '\0';
163 +
164 +       return len;
165 +}
166 +
167 +static char *add_env_key(struct device *device, const char *key, const char *value)
168 +{
169 +       size_t pos = device->bufpos;
170 +       device->bufpos += sprintf(&device->msg.envbuf[device->bufpos], "%s=%s", key, value)+1;
171 +       return &device->msg.envbuf[pos];
172 +}
173 +
174 +static struct device *device_create(const char *path, const char *subsystem, dev_t devt)
175 +{
176 +       struct device *device;
177 +       const char *devpath = &path[strlen(sysfs_path)];
178 +       char target[PATH_SIZE];
179 +
180 +       device = malloc(sizeof(struct device));
181 +       if (device == NULL) {
182 +               dbg("error malloc");
183 +               return NULL;
184 +       }
185 +       memset(device, 0x00, sizeof(struct device));
186 +
187 +       device->path = add_env_key(device, "DEVPATH", devpath);
188 +       device->path += strlen("DEVPATH=");
189 +       add_env_key(device, "SUBSYSTEM", subsystem);
190 +       add_env_key(device, "ACTION", "add");
191 +       add_env_key(device, "UDEV_COLDPLUG", "1");
192 +
193 +       if (major(devt)) {
194 +               char number[32];
195 +               sprintf(number, "%u", major(devt));
196 +               add_env_key(device, "MAJOR", number);
197 +               sprintf(number, "%u", minor(devt));
198 +               add_env_key(device, "MINOR", number);
199 +       }
200 +
201 +       if (strncmp(devpath, "/block/", strlen("/block/")) == 0 ||
202 +           strncmp(devpath, "/class/", strlen("/class/")) == 0) {
203 +               char physpath[PATH_SIZE];
204 +
205 +               if (read_link(path, "device", physpath, sizeof(physpath)) > (ssize_t)strlen(sysfs_path)) {
206 +                       add_env_key(device, "PHYSDEVPATH", &physpath[strlen(sysfs_path)]);
207 +                       if (read_link(physpath, "driver", target, sizeof(target)) > (ssize_t)strlen(sysfs_path)) {
208 +                               char *pos = strrchr(target, '/');
209 +                               if (pos)
210 +                                       add_env_key(device, "PHYSDEVDRIVER", &pos[1]);
211 +                       }
212 +                       if (read_link(physpath, "bus", target, sizeof(target)) > (ssize_t)strlen(sysfs_path)) {
213 +                               char *pos = strrchr(target, '/');
214 +                               if (pos)
215 +                                       add_env_key(device, "PHYSDEVBUS", &pos[1]);
216 +                       }
217 +               }
218 +       } else if (strncmp(devpath, "/devices/", strlen("/devices/")) == 0) {
219 +               if (read_link(path, "driver", target, sizeof(target)) > (ssize_t)strlen(sysfs_path)) {
220 +                       char *pos = strrchr(target, '/');
221 +                       if (pos)
222 +                               add_env_key(device, "PHYSDEVDRIVER", &pos[1]);
223 +               }
224 +               if (read_link(path, "bus", target, sizeof(target)) > (ssize_t)strlen(sysfs_path)) {
225 +                       char *pos = strrchr(target, '/');
226 +                       if (pos)
227 +                               add_env_key(device, "PHYSDEVBUS", &pos[1]);
228 +               }
229 +       }
230 +
231 +       return device;
232 +}
233 +
234 +static int device_list_insert(struct list_head *device_list, struct device *device)
235 +{
236 +       struct device *loop_device;
237 +
238 +       dbg("insert: '%s'", device->path);
239 +
240 +       /* sort files in lexical order */
241 +       list_for_each_entry(loop_device, device_list, node)
242 +               if (strcmp(loop_device->path, device->path) > 0)
243 +                       break;
244 +
245 +       list_add_tail(&device->node, &loop_device->node);
246 +
247 +       return 0;
248 +}
249 +
250 +static int add_device_udevd(struct device *device)
251 +{
252 +       size_t msg_len;
253 +       struct sockaddr_un saddr;
254 +       socklen_t addrlen;
255 +       int retval;
256 +
257 +       memset(&saddr, 0x00, sizeof(struct sockaddr_un));
258 +       saddr.sun_family = AF_LOCAL;
259 +       /* use abstract namespace for socket path */
260 +       strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
261 +       addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
262 +
263 +       strcpy(device->msg.magic, UDEV_MAGIC);
264 +       device->msg.type = UDEVD_UEVENT_UDEVSEND;
265 +
266 +       msg_len = offsetof(struct udevd_msg, envbuf) + device->bufpos;
267 +       dbg("msg_len=%i", msg_len);
268 +
269 +       retval = sendto(udevd_sock, &device->msg, msg_len, 0, (struct sockaddr *)&saddr, addrlen);
270 +       if (retval < 0)
271 +               return -1;
272 +
273 +       return 0;
274 +}
275 +
276 +static void exec_list(struct list_head *device_list, const char *first[], const char *last[])
277 +{
278 +       struct device *loop_device;
279 +       struct device *tmp_device;
280 +       int i;
281 +
282 +       /* handle the "first" type devices first */
283 +       if (first)
284 +               list_for_each_entry_safe(loop_device, tmp_device, device_list, node) {
285 +                       for (i = 0; first[i] != NULL; i++) {
286 +                               if (strncmp(loop_device->path, first[i], strlen(first[i])) == 0) {
287 +                                       add_device_udevd(loop_device);
288 +                                       list_del(&loop_device->node);
289 +                                       free(loop_device);
290 +                                       break;
291 +                               }
292 +                       }
293 +               }
294 +
295 +       /* handle the devices we are allowed to, excluding the "last" type devices */
296 +       if (last)
297 +               list_for_each_entry_safe(loop_device, tmp_device, device_list, node) {
298 +                       int found = 0;
299 +                       for (i = 0; last[i] != NULL; i++) {
300 +                               if (strncmp(loop_device->path, last[i], strlen(last[i])) == 0) {
301 +                                       found = 1;
302 +                                       break;
303 +                               }
304 +                       }
305 +                       if (found)
306 +                               continue;
307 +
308 +               add_device_udevd(loop_device);
309 +               list_del(&loop_device->node);
310 +               free(loop_device);
311 +       }
312 +
313 +       /* handle the rest of the devices */
314 +       list_for_each_entry_safe(loop_device, tmp_device, device_list, node) {
315 +               add_device_udevd(loop_device);
316 +               list_del(&loop_device->node);
317 +               free(loop_device);
318 +       }
319 +}
320 +
321 +static int udev_scan_class(void)
322 +{
323 +       char base[PATH_SIZE];
324 +       DIR *dir;
325 +       struct dirent *dent;
326 +       LIST_HEAD(device_list);
327 +
328 +       /* we want /dev/null and /dev/console first */
329 +       const char *first[] = {
330 +               "/class/mem",
331 +               "/class/tty",
332 +               NULL,
333 +       };
334 +
335 +       snprintf(base, sizeof(base), "%s/class", sysfs_path);
336 +       base[sizeof(base)-1] = '\0';
337 +
338 +       dir = opendir(base);
339 +       if (!dir)
340 +               return -1;
341 +
342 +       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
343 +               char dirname[PATH_SIZE];
344 +               DIR *dir2;
345 +               struct dirent *dent2;
346 +
347 +               if (dent->d_name[0] == '.')
348 +                       continue;
349 +
350 +               snprintf(dirname, sizeof(dirname), "%s/%s", base, dent->d_name);
351 +               dirname[sizeof(dirname)-1] = '\0';
352 +
353 +               dir2 = opendir(dirname);
354 +               if (!dir2)
355 +                       continue;
356 +               for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
357 +                       char dirname2[PATH_SIZE];
358 +                       struct device *device;
359 +                       dev_t devt;
360 +
361 +                       if (dent2->d_name[0] == '.')
362 +                               continue;
363 +                       if (dent2->d_type != DT_DIR)
364 +                               continue;
365 +
366 +                       snprintf(dirname2, sizeof(dirname2), "%s/%s", dirname, dent2->d_name);
367 +                       dirname2[sizeof(dirname2)-1] = '\0';
368 +                       devt = read_devt(dirname2);
369 +                       device = device_create(dirname2, dent->d_name, devt);
370 +
371 +                       if (strcmp(dent->d_name, "net") == 0 ||
372 +                           strcmp(dent->d_name, "bluetooth") == 0) {
373 +                               add_env_key(device, "INTERFACE", dent2->d_name);
374 +                       } else if (strcmp(dent->d_name, "pcmcia_socket") == 0 &&
375 +                                  strlen(dent->d_name) > 14) {
376 +                               add_env_key(device, "SOCKET_NO",
377 +                                       dent2->d_name + 14);
378 +                       }
379 +
380 +                       device_list_insert(&device_list, device);
381 +               }
382 +               closedir(dir2);
383 +       }
384 +       closedir(dir);
385 +       exec_list(&device_list, first, NULL);
386 +
387 +       return 0;
388 +}
389 +
390 +static int udev_scan_block(void)
391 +{
392 +       char base[PATH_SIZE];
393 +       DIR *dir;
394 +       struct dirent *dent;
395 +       LIST_HEAD(device_list);
396 +
397 +       /* dm wants to have the block devices around before it */
398 +       const char *last[] = {
399 +               "/block/dm",
400 +               NULL,
401 +       };
402 +
403 +       snprintf(base, sizeof(base), "%s/block", sysfs_path);
404 +       base[sizeof(base)-1] = '\0';
405 +
406 +       dir = opendir(base);
407 +       if (!dir)
408 +               return -1;
409 +
410 +       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
411 +               char dirname[PATH_SIZE];
412 +               struct device *device;
413 +               struct dirent *dent2;
414 +               DIR *dir2;
415 +               dev_t devt;
416 +
417 +               if (dent->d_name[0] == '.')
418 +                       continue;
419 +               if (dent->d_type != DT_DIR)
420 +                       continue;
421 +
422 +               snprintf(dirname, sizeof(dirname), "%s/%s", base, dent->d_name);
423 +               dirname[sizeof(dirname)-1] = '\0';
424 +               devt = read_devt(dirname);
425 +               if (major(devt)) {
426 +                       device = device_create(dirname, "block", devt);
427 +                       device_list_insert(&device_list, device);
428 +               }
429 +
430 +               /* look for partitions */
431 +               dir2 = opendir(dirname);
432 +               if (!dir2)
433 +                       continue;
434 +               for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
435 +                       char dirname2[PATH_SIZE];
436 +
437 +                       if (dent2->d_name[0] == '.')
438 +                               continue;
439 +                       if (dent2->d_type != DT_DIR)
440 +                               continue;
441 +
442 +                       snprintf(dirname2, sizeof(dirname2), "%s/%s", dirname, dent2->d_name);
443 +                       dirname2[sizeof(dirname2)-1] = '\0';
444 +                       devt = read_devt(dirname2);
445 +                       if (major(devt)) {
446 +                               device = device_create(dirname2, "block", devt);
447 +                               device_list_insert(&device_list, device);
448 +                               continue;
449 +                       }
450 +               }
451 +               closedir(dir2);
452 +       }
453 +       closedir(dir);
454 +       exec_list(&device_list, NULL, last);
455 +
456 +       return 0;
457 +}
458 +
459 +static int pci_handler(struct device *device)
460 +{
461 +       char path[PATH_SIZE];
462 +       char value[PATH_SIZE];
463 +       char vendor[PATH_SIZE];
464 +       char product[PATH_SIZE];
465 +       const char *name;
466 +
467 +       snprintf(path, sizeof(path), "%s%s", sysfs_path, device->path);
468 +       path[sizeof(path)-1] = '\0';
469 +
470 +       if (read_file(path, "modalias", value, sizeof(value)) > 0)
471 +               add_env_key(device, "MODALIAS", value);
472 +
473 +       name = strrchr(device->path, '/');
474 +       if (name)
475 +               add_env_key(device, "PCI_SLOT_NAME", &name[1]);
476 +
477 +       if (read_file(path, "class", value, sizeof(value)) > 0)
478 +               add_env_key(device, "PCI_CLASS", &value[2]);
479 +
480 +       if (read_file(path, "vendor", vendor, sizeof(vendor)) > 0 &&
481 +           read_file(path, "device", product, sizeof(product)) > 0) {
482 +               snprintf(value, sizeof(value), "%s:%s", &vendor[2], &product[2]);
483 +               path[sizeof(value)-1] = '\0';
484 +               add_env_key(device, "PCI_ID", value);
485 +       }
486 +
487 +       if (read_file(path, "subsystem_vendor", vendor, sizeof(vendor)) > 0 &&
488 +           read_file(path, "subsystem_device", product, sizeof(product)) > 0) {
489 +               snprintf(value, sizeof(value), "%s:%s", &vendor[2], &product[2]);
490 +               path[sizeof(value)-1] = '\0';
491 +               add_env_key(device, "PCI_SUBSYS_ID", value);
492 +       }
493 +
494 +       return 0;
495 +}
496 +
497 +static int usb_handler(struct device *device)
498 +{
499 +       char path[PATH_SIZE];
500 +       char value[PATH_SIZE];
501 +       char str1[PATH_SIZE];
502 +       char str2[PATH_SIZE];
503 +       char str3[PATH_SIZE];
504 +       unsigned int int1;
505 +       unsigned int int2;
506 +       unsigned int int3;
507 +       char *pos;
508 +
509 +       snprintf(path, sizeof(path), "%s%s", sysfs_path, device->path);
510 +       path[sizeof(path)-1] = '\0';
511 +
512 +       /* device events have : in their directory name */
513 +       pos = strrchr(path, '/');
514 +       if (!strchr(pos, ':'))
515 +               return 0;       /* and do not have other variables */
516 +
517 +       if (read_file(path, "modalias", value, sizeof(value)) > 0)
518 +               add_env_key(device, "MODALIAS", value);
519 +
520 +       if (read_file(path, "bInterfaceClass", str1, sizeof(str1)) > 0 &&
521 +           read_file(path, "bInterfaceSubClass", str2, sizeof(str2)) > 0 &&
522 +           read_file(path, "bInterfaceProtocol", str3, sizeof(str3)) > 0) {
523 +               int1 = (int) strtol(str1, NULL, 16);
524 +               int2 = (int) strtol(str2, NULL, 16);
525 +               int3 = (int) strtol(str3, NULL, 16);
526 +               snprintf(value, sizeof(value), "%u/%u/%u", int1, int2, int3);
527 +               path[sizeof(value)-1] = '\0';
528 +               add_env_key(device, "INTERFACE", value);
529 +       }
530 +
531 +       /* move to the parent directory */
532 +       pos[0] = '\0';
533 +
534 +       if (read_file(path, "idVendor", str1, sizeof(str1)) > 0 &&
535 +           read_file(path, "idProduct", str2, sizeof(str2)) > 0 &&
536 +           read_file(path, "bcdDevice", str3, sizeof(str3)) > 0) {
537 +               int1 = (int) strtol(str1, NULL, 16);
538 +               int2 = (int) strtol(str2, NULL, 16);
539 +               int3 = (int) strtol(str3, NULL, 16);
540 +               snprintf(value, sizeof(value), "%x/%x/%x", int1, int2, int3);
541 +               path[sizeof(value)-1] = '\0';
542 +               add_env_key(device, "PRODUCT", value);
543 +       }
544 +
545 +       if (read_file(path, "bDeviceClass", str1, sizeof(str1)) > 0 &&
546 +           read_file(path, "bDeviceSubClass", str2, sizeof(str2)) > 0 &&
547 +           read_file(path, "bDeviceProtocol", str3, sizeof(str3)) > 0) {
548 +               int1 = (int) strtol(str1, NULL, 16);
549 +               int2 = (int) strtol(str2, NULL, 16);
550 +               int3 = (int) strtol(str3, NULL, 16);
551 +               snprintf(value, sizeof(value), "%u/%u/%u", int1, int2, int3);
552 +               path[sizeof(value)-1] = '\0';
553 +               add_env_key(device, "TYPE", value);
554 +       }
555 +
556 +       if (read_file(path, "devnum", str2, sizeof(str2)) > 0) {
557 +               pos = strrchr(path, 'b');
558 +               int1 = (int) strtol(pos + 1, NULL, 16);
559 +               int2 = (int) strtol(str2, NULL, 16);
560 +               snprintf(value, sizeof(value),
561 +                       "/proc/bus/usb/%03d/%03d", int1, int2);
562 +               path[sizeof(value)-1] = '\0';
563 +               add_env_key(device, "DEVICE", value);
564 +       }
565 +
566 +       return 0;
567 +}
568 +
569 +static int serio_handler(struct device *device)
570 +{
571 +       char path[PATH_SIZE];
572 +       char value[PATH_SIZE];
573 +
574 +       snprintf(path, sizeof(path), "%s%s", sysfs_path, device->path);
575 +       path[sizeof(path)-1] = '\0';
576 +
577 +       if (read_file(path, "modalias", value, sizeof(value)) > 0)
578 +               add_env_key(device, "MODALIAS", value);
579 +
580 +       if (read_file(path, "id/type", value, sizeof(value)) > 0)
581 +               add_env_key(device, "SERIO_TYPE", value);
582 +
583 +       if (read_file(path, "id/proto", value, sizeof(value)) > 0)
584 +               add_env_key(device, "SERIO_PROTO", value);
585 +
586 +       if (read_file(path, "id/id", value, sizeof(value)) > 0)
587 +               add_env_key(device, "SERIO_ID", value);
588 +
589 +       if (read_file(path, "id/extra", value, sizeof(value)) > 0)
590 +               add_env_key(device, "SERIO_EXTRA", value);
591 +
592 +       return 0;
593 +}
594 +
595 +static int ccw_handler(struct device *device)
596 +{
597 +       char path[PATH_SIZE];
598 +       char value[PATH_SIZE], *tmp;
599 +
600 +       snprintf(path, sizeof(path), "%s%s", sysfs_path, device->path);
601 +       path[sizeof(path)-1] = '\0';
602 +
603 +       if (read_file(path, "modalias", value, sizeof(value)) > 0)
604 +               add_env_key(device, "MODALIAS", value);
605 +
606 +       if (read_file(path, "cutype", value, sizeof(value)) > 0) {
607 +               value[4] = 0;
608 +               tmp = &value[5];
609 +               add_env_key(device, "CU_TYPE", value);
610 +               add_env_key(device, "CU_MODEL", tmp);
611 +       }
612 +
613 +       if (read_file(path, "devtype", value, sizeof(value)) > 0) {
614 +               if (value[0] == 'n') {
615 +                       add_env_key(device, "DEV_TYPE", "0000");
616 +                       add_env_key(device, "DEV_MODEL", "00");
617 +               }
618 +               else {
619 +                       value[4] = 0;
620 +                       tmp = &value[5];
621 +                       add_env_key(device, "DEV_TYPE", value);
622 +                       add_env_key(device, "DEV_MODEL", tmp);
623 +               }
624 +       }
625 +
626 +       return 0;
627 +}
628 +
629 +static int modalias_handler(struct device *device)
630 +{
631 +       char path[PATH_SIZE];
632 +       char value[PATH_SIZE];
633 +
634 +       snprintf(path, sizeof(path), "%s%s", sysfs_path, device->path);
635 +       path[sizeof(path)-1] = '\0';
636 +
637 +       if (read_file(path, "modalias", value, sizeof(value)) > 0)
638 +               add_env_key(device, "MODALIAS", value);
639 +
640 +       return 0;
641 +}
642 +
643 +static int udev_scan_bus(const char *bus, int bus_handler(struct device *device))
644 +{
645 +       char base[PATH_SIZE];
646 +       DIR *dir;
647 +       struct dirent *dent;
648 +       LIST_HEAD(device_list);
649 +
650 +       snprintf(base, sizeof(base), "%s/bus/%s/devices", sysfs_path, bus);
651 +       base[sizeof(base)-1] = '\0';
652 +
653 +       dir = opendir(base);
654 +       if (!dir)
655 +               return -1;
656 +       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
657 +               char devpath[PATH_SIZE];
658 +               struct device *device;
659 +
660 +               if (dent->d_name[0] == '.')
661 +                       continue;
662 +
663 +               if (read_link(base, dent->d_name, devpath, sizeof(devpath)) < 0)
664 +                       continue;
665 +
666 +               device = device_create(devpath, bus, makedev(0, 0));
667 +               if (bus_handler) {
668 +                       if (bus_handler(device) < 0) {
669 +                               dbg("'%s' bus handler skipped event", devpath);
670 +                               free(device);
671 +                               continue;
672 +                       }
673 +               }
674 +
675 +               device_list_insert(&device_list, device);
676 +       }
677 +       closedir(dir);
678 +       exec_list(&device_list, NULL, NULL);
679 +
680 +       return 0;
681 +}
682 +
683 +static int udev_scan_devices(void)
684 +{
685 +       char base[PATH_SIZE];
686 +       DIR *dir;
687 +       struct dirent *dent;
688 +
689 +       snprintf(base, sizeof(base), "%s/bus", sysfs_path);
690 +       base[sizeof(base)-1] = '\0';
691 +
692 +       dir = opendir(base);
693 +       if (!dir)
694 +               return -1;
695 +
696 +       for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
697 +               if (dent->d_name[0] == '.')
698 +                       continue;
699 +               if (dent->d_type != DT_DIR)
700 +                       continue;
701 +
702 +               /* add bus specific env values */
703 +               if (strcmp(dent->d_name, "pci") == 0)
704 +                       udev_scan_bus("pci", pci_handler);
705 +               else if (strcmp(dent->d_name, "usb") == 0)
706 +                       udev_scan_bus("usb", usb_handler);
707 +               else if (strcmp(dent->d_name, "serio") == 0)
708 +                       udev_scan_bus("serio", serio_handler);
709 +               else if (strcmp(dent->d_name, "ccw") == 0)
710 +                       udev_scan_bus("ccw", ccw_handler);
711 +               else
712 +                       udev_scan_bus(dent->d_name, modalias_handler);
713 +       }
714 +       closedir(dir);
715 +
716 +       return 0;
717 +}
718 +
719 +int main(int argc, char *argv[], char *envp[])
720 +{
721 +       LIST_HEAD(device_list);
722 +       int i;
723 +
724 +       logging_init("udevcoldplug");
725 +       udev_config_init(); sysfs_init();
726 +       dbg("version %s", UDEV_VERSION);
727 +
728 +       udev_log_str = getenv("UDEV_LOG");
729 +
730 +       /* disable all logging if not explicitely requested */
731 +       if (udev_log_str == NULL)
732 +               udev_log_priority = 0;
733 +
734 +       for (i = 1 ; i < argc; i++) {
735 +               char *arg = argv[i];
736 +
737 +               if (strcmp(arg, "help") == 0  || strcmp(arg, "--help") == 0  || strcmp(arg, "-h") == 0) {
738 +                       printf("Usage: udevcoldplug \n"
739 +                               "  --help                   print this help text\n\n");
740 +                       exit(0);
741 +               } else {
742 +                       fprintf(stderr, "unknown option\n\n");
743 +                       exit(1);
744 +               }
745 +       }
746 +
747 +       udevd_sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
748 +       if (udevd_sock < 0) {
749 +               err("error getting socket");
750 +               return 1;
751 +       }
752 +
753 +       /* create nodes for already available devices */
754 +       udev_scan_class();
755 +       udev_scan_block();
756 +
757 +       /* synthesize events for bus devices
758 +        * may load modules or configure the device */
759 +       udev_scan_devices();
760 +
761 +       if (udevd_sock >= 0)
762 +               close(udevd_sock);
763 +       logging_close();
764 +
765 +       return 0;
766 +}
767 --- udev-081/Makefile
768 +++ udev-081/Makefile
769 @@ -58,6 +58,7 @@ PROGRAMS = \
770         udevmonitor                     \
771         udevinfo                        \
772         udevtest                        \
773 +       udevsynthesize                  \
774         udevstart
775  
776  HEADERS = \