chiark / gitweb /
[PATCH] udevd race conditions and performance, assorted cleanups - take 2
[elogind.git] / udevstart.c
1 /*
2  * udevstart.c
3  *
4  * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
5  * 
6  * Quick and dirty way to populate a /dev with udev if your system
7  * does not have access to a shell.  Based originally on a patch to udev 
8  * from Harald Hoyer <harald@redhat.com>
9  *
10  *      This program is free software; you can redistribute it and/or modify it
11  *      under the terms of the GNU General Public License as published by the
12  *      Free Software Foundation version 2 of the License.
13  * 
14  *      This program is distributed in the hope that it will be useful, but
15  *      WITHOUT ANY WARRANTY; without even the implied warranty of
16  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  *      General Public License for more details.
18  * 
19  *      You should have received a copy of the GNU General Public License along
20  *      with this program; if not, write to the Free Software Foundation, Inc.,
21  *      675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <errno.h>
29 #include <ctype.h>
30 #include <dirent.h>
31 #include <sys/wait.h>
32 #include <sys/types.h>
33 #include <unistd.h>
34
35 #include "logging.h"
36
37
38 #ifdef LOG
39 unsigned char logname[LOGNAME_SIZE];
40 void log_message(int level, const char *format, ...)
41 {
42         va_list args;
43
44         va_start(args, format);
45         vsyslog(level, format, args);
46         va_end(args);
47 }
48 #endif
49
50
51 #define MAX_PATHLEN             1024
52 #define SYSBLOCK                "/sys/block"
53 #define SYSCLASS                "/sys/class"
54 #define UDEV_BIN                "/sbin/udev"
55
56 static void udev_exec(const char *path, const char* subsystem)
57 {
58         pid_t pid;
59         char action[] = "ACTION=add";
60         char devpath[MAX_PATHLEN];
61         char nosleep[] = "UDEV_NO_SLEEP=1";
62         char *env[] = { action, devpath, nosleep, NULL };
63
64         snprintf(devpath, MAX_PATHLEN, "DEVPATH=%s", path);
65         devpath[MAX_PATHLEN-1] = '\0';
66
67         pid = fork();
68         switch (pid) {
69         case 0:
70                 /* child */
71                 execle(UDEV_BIN, "udev", subsystem, NULL, env);
72                 dbg("exec of child failed");
73                 exit(1);
74                 break;
75         case -1:
76                 dbg("fork of child failed");
77                 break;
78         default:
79                 wait(NULL);
80         }
81 }
82
83 static void udev_scan(void)
84 {
85         char *devpath;
86         DIR *dir;
87         struct dirent *dent;
88
89         devpath = "block";
90         dir = opendir(SYSBLOCK);
91         if (dir != NULL) {
92                 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
93                         char dirname[MAX_PATHLEN];
94                         DIR *dir2;
95                         struct dirent *dent2;
96
97                         if ((strcmp(dent->d_name, ".") == 0) ||
98                             (strcmp(dent->d_name, "..") == 0))
99                                 continue;
100
101                         snprintf(dirname, MAX_PATHLEN, "/block/%s", dent->d_name);
102                         dirname[MAX_PATHLEN-1] = '\0';
103                         udev_exec(dirname, "block");
104
105                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSBLOCK, dent->d_name);
106                         dir2 = opendir(dirname);
107                         if (dir2 != NULL) {
108                                 for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
109                                         char dirname2[MAX_PATHLEN];
110                                         DIR *dir3;
111                                         struct dirent *dent3;
112
113                                         if ((strcmp(dent2->d_name, ".") == 0) ||
114                                             (strcmp(dent2->d_name, "..") == 0))
115                                                 continue;
116
117                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
118                                         dirname2[MAX_PATHLEN-1] = '\0';
119
120                                         dir3 = opendir(dirname2);
121                                         if (dir3 != NULL) {
122                                                 for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
123                                                         char filename[MAX_PATHLEN];
124
125                                                         if (strcmp(dent3->d_name, "dev") == 0) {
126                                                                 snprintf(filename, MAX_PATHLEN, "/block/%s/%s",
127                                                                          dent->d_name, dent2->d_name);
128                                                                 filename[MAX_PATHLEN-1] = '\0';
129                                                                 udev_exec(filename, "block");
130                                                         }
131                                                 }
132                                         }
133                                 }
134                         }
135                 }
136         }
137
138         devpath = "class";
139         dir = opendir(SYSCLASS);
140         if (dir != NULL) {
141                 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
142                         char dirname[MAX_PATHLEN];
143                         DIR *dir2;
144                         struct dirent *dent2;
145
146                         if ((strcmp(dent->d_name, ".") == 0) ||
147                             (strcmp(dent->d_name, "..") == 0))
148                                 continue;
149
150                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSCLASS, dent->d_name);
151                         dirname[MAX_PATHLEN] = '\0';
152                         dir2 = opendir(dirname);
153                         if (dir2 != NULL) {
154                                 for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
155                                         char dirname2[MAX_PATHLEN-1];
156                                         DIR *dir3;
157                                         struct dirent *dent3;
158
159                                         if ((strcmp(dent2->d_name, ".") == 0) ||
160                                             (strcmp(dent2->d_name, "..") == 0))
161                                                 continue;
162
163                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
164                                         dirname2[MAX_PATHLEN-1] = '\0';
165
166                                         dir3 = opendir(dirname2);
167                                         if (dir3 != NULL) {
168                                                 for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
169                                                         char filename[MAX_PATHLEN];
170
171                                                         if (strcmp(dent3->d_name, "dev") == 0) {
172                                                                 snprintf(filename, MAX_PATHLEN, "/class/%s/%s",
173                                                                          dent->d_name, dent2->d_name);
174                                                                 filename[MAX_PATHLEN-1] = '\0';
175                                                                 udev_exec(filename, dent->d_name);
176                                                         }
177                                                 }
178                                         }
179                                 }
180                         }
181                 }
182         }
183 }
184
185
186 int main(int argc, char *argv[], char *envp[])
187 {
188         init_logging("udevstart");
189
190         udev_scan();
191
192         return 0;
193 }