chiark / gitweb /
2d11edeca2d6fd291e5d6985c47bcbf48274f0ca
[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 #include "udev_lib.h"
37
38
39 #ifdef LOG
40 unsigned char logname[LOGNAME_SIZE];
41 void log_message(int level, const char *format, ...)
42 {
43         va_list args;
44
45         va_start(args, format);
46         vsyslog(level, format, args);
47         va_end(args);
48 }
49 #endif
50
51
52 #define MAX_PATHLEN             1024
53 #define SYSBLOCK                "/sys/block"
54 #define SYSCLASS                "/sys/class"
55 #define UDEV_BIN                "/sbin/udev"
56
57 static void udev_exec(const char *path, const char* subsystem)
58 {
59         pid_t pid;
60         char action[] = "ACTION=add";
61         char devpath[MAX_PATHLEN];
62         char nosleep[] = "UDEV_NO_SLEEP=1";
63         char *env[] = { action, devpath, nosleep, NULL };
64
65         strcpy(devpath, "DEVPATH=");
66         strfieldcat(devpath, path);
67
68         pid = fork();
69         switch (pid) {
70         case 0:
71                 /* child */
72                 execle(UDEV_BIN, "udev", subsystem, NULL, env);
73                 dbg("exec of child failed");
74                 exit(1);
75                 break;
76         case -1:
77                 dbg("fork of child failed");
78                 break;
79         default:
80                 wait(NULL);
81         }
82 }
83
84 static void udev_scan(void)
85 {
86         char *devpath;
87         DIR *dir;
88         struct dirent *dent;
89
90         /* 
91          * We want to scan the class tree first as lvm and dm needs to be able
92          * to have access to the char control device when probing the block
93          * devices.
94          */
95         devpath = "class";
96         dir = opendir(SYSCLASS);
97         if (dir != NULL) {
98                 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
99                         char dirname[MAX_PATHLEN];
100                         DIR *dir2;
101                         struct dirent *dent2;
102
103                         if ((strcmp(dent->d_name, ".") == 0) ||
104                             (strcmp(dent->d_name, "..") == 0))
105                                 continue;
106
107                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSCLASS, dent->d_name);
108                         dirname[MAX_PATHLEN] = '\0';
109                         dir2 = opendir(dirname);
110                         if (dir2 != NULL) {
111                                 for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
112                                         char dirname2[MAX_PATHLEN-1];
113                                         DIR *dir3;
114                                         struct dirent *dent3;
115
116                                         if ((strcmp(dent2->d_name, ".") == 0) ||
117                                             (strcmp(dent2->d_name, "..") == 0))
118                                                 continue;
119
120                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
121                                         dirname2[MAX_PATHLEN-1] = '\0';
122
123                                         dir3 = opendir(dirname2);
124                                         if (dir3 != NULL) {
125                                                 for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
126                                                         char filename[MAX_PATHLEN];
127
128                                                         if (strcmp(dent3->d_name, "dev") == 0) {
129                                                                 snprintf(filename, MAX_PATHLEN, "/class/%s/%s",
130                                                                          dent->d_name, dent2->d_name);
131                                                                 filename[MAX_PATHLEN-1] = '\0';
132                                                                 udev_exec(filename, dent->d_name);
133                                                         }
134                                                 }
135                                                 closedir(dir3);
136                                         }
137                                 }
138                                 closedir(dir2);
139                         }
140                 }
141                 closedir(dir);
142         }
143
144         devpath = "block";
145         dir = opendir(SYSBLOCK);
146         if (dir != NULL) {
147                 for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) {
148                         char dirname[MAX_PATHLEN];
149                         DIR *dir2;
150                         struct dirent *dent2;
151
152                         if ((strcmp(dent->d_name, ".") == 0) ||
153                             (strcmp(dent->d_name, "..") == 0))
154                                 continue;
155
156                         snprintf(dirname, MAX_PATHLEN, "/block/%s", dent->d_name);
157                         dirname[MAX_PATHLEN-1] = '\0';
158                         udev_exec(dirname, "block");
159
160                         snprintf(dirname, MAX_PATHLEN, "%s/%s", SYSBLOCK, dent->d_name);
161                         dir2 = opendir(dirname);
162                         if (dir2 != NULL) {
163                                 for (dent2 = readdir(dir2); dent2 != NULL; dent2 = readdir(dir2)) {
164                                         char dirname2[MAX_PATHLEN];
165                                         DIR *dir3;
166                                         struct dirent *dent3;
167
168                                         if ((strcmp(dent2->d_name, ".") == 0) ||
169                                             (strcmp(dent2->d_name, "..") == 0))
170                                                 continue;
171
172                                         snprintf(dirname2, MAX_PATHLEN, "%s/%s", dirname, dent2->d_name);
173                                         dirname2[MAX_PATHLEN-1] = '\0';
174
175                                         dir3 = opendir(dirname2);
176                                         if (dir3 != NULL) {
177                                                 for (dent3 = readdir(dir3); dent3 != NULL; dent3 = readdir(dir3)) {
178                                                         char filename[MAX_PATHLEN];
179
180                                                         if (strcmp(dent3->d_name, "dev") == 0) {
181                                                                 snprintf(filename, MAX_PATHLEN, "/block/%s/%s",
182                                                                          dent->d_name, dent2->d_name);
183                                                                 filename[MAX_PATHLEN-1] = '\0';
184                                                                 udev_exec(filename, "block");
185                                                         }
186                                                 }
187                                                 closedir(dir3);
188                                         }
189                                 }
190                                 closedir(dir2);
191                         }
192                 }
193                 closedir(dir);
194         }
195 }
196
197 int main(int argc, char *argv[], char *envp[])
198 {
199         init_logging("udevstart");
200
201         udev_scan();
202
203         return 0;
204 }