File src/udev-builtin-blkid.c changed (mode: 100644) (index 2ba103a..baafd8d) |
1 |
1 |
/* |
/* |
2 |
2 |
* probe disks for filesystems and partitions |
* probe disks for filesystems and partitions |
3 |
3 |
* |
* |
4 |
|
* Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> |
|
5 |
|
* Copyright (C) 2011 Karel Zak <kzak@redhat.com> |
|
|
4 |
|
* Copyright (C) 2020 Sylvain BERTRAND <sylvain.bertrand@legeek.net> |
6 |
5 |
* |
* |
7 |
6 |
* This program is free software: you can redistribute it and/or modify |
* This program is free software: you can redistribute it and/or modify |
8 |
7 |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
|
17 |
16 |
* You should have received a copy of the GNU General Public License |
* You should have received a copy of the GNU General Public License |
18 |
17 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 |
18 |
*/ |
*/ |
20 |
|
|
|
21 |
19 |
#include <stdio.h> |
#include <stdio.h> |
22 |
20 |
#include <stdlib.h> |
#include <stdlib.h> |
23 |
21 |
#include <stdarg.h> |
#include <stdarg.h> |
|
26 |
24 |
#include <errno.h> |
#include <errno.h> |
27 |
25 |
#include <fcntl.h> |
#include <fcntl.h> |
28 |
26 |
#include <getopt.h> |
#include <getopt.h> |
29 |
|
#include <sys/stat.h> |
|
30 |
|
#include <blkid.h> |
|
31 |
|
|
|
|
27 |
|
#include <poll.h> |
|
28 |
|
#include <sys/types.h> |
|
29 |
|
#include <sys/socket.h> |
|
30 |
|
#include <sys/wait.h> |
32 |
31 |
#include "udev.h" |
#include "udev.h" |
33 |
|
|
|
34 |
|
static void print_property(struct udev_device *dev, bool test, const char *name, const char *value) |
|
|
32 |
|
#define loop for(;;) |
|
33 |
|
#define u8 char |
|
34 |
|
struct busybox_blkid_t { |
|
35 |
|
char *type; |
|
36 |
|
char *uuid; |
|
37 |
|
char *label; |
|
38 |
|
}; |
|
39 |
|
static void busybox_blkid_exec(struct udev_device *dev, int s) |
35 |
40 |
{ |
{ |
36 |
|
char s[265]; |
|
37 |
|
|
|
38 |
|
s[0] = '\0'; |
|
39 |
|
|
|
40 |
|
if (!strcmp(name, "TYPE")) { |
|
41 |
|
udev_builtin_add_property(dev, test, "ID_FS_TYPE", value); |
|
42 |
|
|
|
43 |
|
} else if (!strcmp(name, "USAGE")) { |
|
44 |
|
udev_builtin_add_property(dev, test, "ID_FS_USAGE", value); |
|
45 |
|
|
|
46 |
|
} else if (!strcmp(name, "VERSION")) { |
|
47 |
|
udev_builtin_add_property(dev, test, "ID_FS_VERSION", value); |
|
48 |
|
|
|
49 |
|
} else if (!strcmp(name, "UUID")) { |
|
50 |
|
blkid_safe_string(value, s, sizeof(s)); |
|
51 |
|
udev_builtin_add_property(dev, test, "ID_FS_UUID", s); |
|
52 |
|
blkid_encode_string(value, s, sizeof(s)); |
|
53 |
|
udev_builtin_add_property(dev, test, "ID_FS_UUID_ENC", s); |
|
54 |
|
|
|
55 |
|
} else if (!strcmp(name, "UUID_SUB")) { |
|
56 |
|
blkid_safe_string(value, s, sizeof(s)); |
|
57 |
|
udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB", s); |
|
58 |
|
blkid_encode_string(value, s, sizeof(s)); |
|
59 |
|
udev_builtin_add_property(dev, test, "ID_FS_UUID_SUB_ENC", s); |
|
60 |
|
|
|
61 |
|
} else if (!strcmp(name, "LABEL")) { |
|
62 |
|
blkid_safe_string(value, s, sizeof(s)); |
|
63 |
|
udev_builtin_add_property(dev, test, "ID_FS_LABEL", s); |
|
64 |
|
blkid_encode_string(value, s, sizeof(s)); |
|
65 |
|
udev_builtin_add_property(dev, test, "ID_FS_LABEL_ENC", s); |
|
66 |
|
|
|
67 |
|
} else if (!strcmp(name, "PTTYPE")) { |
|
68 |
|
udev_builtin_add_property(dev, test, "ID_PART_TABLE_TYPE", value); |
|
69 |
|
|
|
70 |
|
} else if (!strcmp(name, "PART_ENTRY_NAME")) { |
|
71 |
|
blkid_encode_string(value, s, sizeof(s)); |
|
72 |
|
udev_builtin_add_property(dev, test, "ID_PART_ENTRY_NAME", s); |
|
73 |
|
|
|
74 |
|
} else if (!strcmp(name, "PART_ENTRY_TYPE")) { |
|
75 |
|
blkid_encode_string(value, s, sizeof(s)); |
|
76 |
|
udev_builtin_add_property(dev, test, "ID_PART_ENTRY_TYPE", s); |
|
77 |
|
|
|
78 |
|
} else if (!strncmp(name, "PART_ENTRY_", 11)) { |
|
79 |
|
util_strscpyl(s, sizeof(s), "ID_", name, NULL); |
|
80 |
|
udev_builtin_add_property(dev, test, s, value); |
|
81 |
|
} |
|
|
41 |
|
struct udev *udev = udev_device_get_udev(dev); |
|
42 |
|
const char *devnode; |
|
43 |
|
int r; |
|
44 |
|
|
|
45 |
|
devnode = udev_device_get_devnode(dev); |
|
46 |
|
close(0); |
|
47 |
|
r = dup2(s, 1); |
|
48 |
|
if (r == -1) { |
|
49 |
|
err(udev, "blkid:unable to duplicate socket filedescriptor on standart output\n"); |
|
50 |
|
exit(1); |
|
51 |
|
} |
|
52 |
|
loop { |
|
53 |
|
errno = 0; |
|
54 |
|
info(udev, "blkid:exec for %s\n", devnode); |
|
55 |
|
execlp("blkid", "blkid", devnode, 0); |
|
56 |
|
if (errno != EAGAIN) { |
|
57 |
|
err(udev, "blkid:unable to exec\n"); |
|
58 |
|
exit(1); |
|
59 |
|
} |
|
60 |
|
/* EAGAIN */ |
|
61 |
|
} |
|
62 |
|
/* unreachable */ |
82 |
63 |
} |
} |
83 |
|
|
|
84 |
|
static int probe_superblocks(blkid_probe pr) |
|
|
64 |
|
static void busybox_blkid_output_field(char *buf, char *key_name, |
|
65 |
|
char **value_dup) |
85 |
66 |
{ |
{ |
86 |
|
struct stat st; |
|
87 |
|
int rc; |
|
88 |
|
|
|
89 |
|
if (fstat(blkid_probe_get_fd(pr), &st)) |
|
90 |
|
return -1; |
|
91 |
|
|
|
92 |
|
blkid_probe_enable_partitions(pr, 1); |
|
93 |
|
|
|
94 |
|
if (!S_ISCHR(st.st_mode) && blkid_probe_get_size(pr) <= 1024 * 1440 && |
|
95 |
|
blkid_probe_is_wholedisk(pr)) { |
|
96 |
|
/* |
|
97 |
|
* check if the small disk is partitioned, if yes then |
|
98 |
|
* don't probe for filesystems. |
|
99 |
|
*/ |
|
100 |
|
blkid_probe_enable_superblocks(pr, 0); |
|
101 |
|
|
|
102 |
|
rc = blkid_do_fullprobe(pr); |
|
103 |
|
if (rc < 0) |
|
104 |
|
return rc; /* -1 = error, 1 = nothing, 0 = succes */ |
|
105 |
|
|
|
106 |
|
if (blkid_probe_lookup_value(pr, "PTTYPE", NULL, NULL) == 0) |
|
107 |
|
return 0; /* partition table detected */ |
|
108 |
|
} |
|
109 |
|
|
|
110 |
|
blkid_probe_set_partitions_flags(pr, BLKID_PARTS_ENTRY_DETAILS); |
|
111 |
|
blkid_probe_enable_superblocks(pr, 1); |
|
112 |
|
|
|
113 |
|
return blkid_do_safeprobe(pr); |
|
|
67 |
|
char *key; |
|
68 |
|
char *value; |
|
69 |
|
char *value_end; |
|
70 |
|
|
|
71 |
|
key = strstr(buf, key_name); |
|
72 |
|
if (key == 0) |
|
73 |
|
return; |
|
74 |
|
value = strchr(key, '='); |
|
75 |
|
if (value == 0) |
|
76 |
|
return; |
|
77 |
|
if (value[1] == 0 || value[1] != '"') |
|
78 |
|
return; |
|
79 |
|
value += 2; |
|
80 |
|
value_end = strchr(value, '"'); |
|
81 |
|
if (value_end == 0) |
|
82 |
|
return; |
|
83 |
|
*value_end = 0; |
|
84 |
|
*value_dup = strdup(value); |
|
85 |
|
*value_end = '"'; |
114 |
86 |
} |
} |
115 |
|
|
|
116 |
|
static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], bool test) |
|
|
87 |
|
static int busybox_blkid_output_parse(struct udev *udev, int s, |
|
88 |
|
struct busybox_blkid_t *props) |
117 |
89 |
{ |
{ |
118 |
|
struct udev *udev = udev_device_get_udev(dev); |
|
119 |
|
int64_t offset = 0; |
|
120 |
|
bool noraid = false; |
|
121 |
|
int fd = -1; |
|
122 |
|
blkid_probe pr; |
|
123 |
|
const char *data; |
|
124 |
|
const char *name; |
|
125 |
|
int nvals; |
|
126 |
|
int i; |
|
127 |
|
size_t len; |
|
128 |
|
int err = 0; |
|
129 |
|
|
|
130 |
|
static const struct option options[] = { |
|
131 |
|
{ "offset", optional_argument, NULL, 'o' }, |
|
132 |
|
{ "noraid", no_argument, NULL, 'R' }, |
|
133 |
|
{} |
|
134 |
|
}; |
|
135 |
|
|
|
136 |
|
for (;;) { |
|
137 |
|
int option; |
|
138 |
|
|
|
139 |
|
option = getopt_long(argc, argv, "oR", options, NULL); |
|
140 |
|
if (option == -1) |
|
141 |
|
break; |
|
142 |
|
|
|
143 |
|
switch (option) { |
|
144 |
|
case 'o': |
|
145 |
|
offset = strtoull(optarg, NULL, 0); |
|
146 |
|
break; |
|
147 |
|
case 'R': |
|
148 |
|
noraid = true; |
|
149 |
|
break; |
|
150 |
|
} |
|
151 |
|
} |
|
152 |
|
|
|
153 |
|
pr = blkid_new_probe(); |
|
154 |
|
if (!pr) { |
|
155 |
|
err = -ENOMEM; |
|
156 |
|
return EXIT_FAILURE; |
|
157 |
|
} |
|
158 |
|
|
|
159 |
|
blkid_probe_set_superblocks_flags(pr, |
|
160 |
|
BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID | |
|
161 |
|
BLKID_SUBLKS_TYPE | BLKID_SUBLKS_SECTYPE | |
|
162 |
|
BLKID_SUBLKS_USAGE | BLKID_SUBLKS_VERSION); |
|
163 |
|
|
|
164 |
|
if (noraid) |
|
165 |
|
blkid_probe_filter_superblocks_usage(pr, BLKID_FLTR_NOTIN, BLKID_USAGE_RAID); |
|
166 |
|
|
|
167 |
|
fd = open(udev_device_get_devnode(dev), O_RDONLY|O_CLOEXEC); |
|
168 |
|
if (fd < 0) { |
|
169 |
|
fprintf(stderr, "error: %s: %m\n", udev_device_get_devnode(dev)); |
|
170 |
|
goto out; |
|
171 |
|
} |
|
172 |
|
|
|
173 |
|
err = blkid_probe_set_device(pr, fd, offset, 0); |
|
174 |
|
if (err < 0) |
|
175 |
|
goto out; |
|
176 |
|
|
|
177 |
|
info(udev, "probe %s %sraid offset=%llu\n", |
|
178 |
|
udev_device_get_devnode(dev), |
|
179 |
|
noraid ? "no" : "", (unsigned long long) offset); |
|
180 |
|
|
|
181 |
|
err = probe_superblocks(pr); |
|
182 |
|
if (err < 0) |
|
183 |
|
goto out; |
|
184 |
|
|
|
185 |
|
nvals = blkid_probe_numof_values(pr); |
|
186 |
|
for (i = 0; i < nvals; i++) { |
|
187 |
|
if (blkid_probe_get_value(pr, i, &name, &data, &len)) |
|
188 |
|
continue; |
|
189 |
|
len = strnlen((char *) data, len); |
|
190 |
|
print_property(dev, test, name, (char *) data); |
|
191 |
|
} |
|
|
90 |
|
u8 buf[BUFSIZ + 1]; /* zero terminating char in worst case scenario */ |
|
91 |
|
u8 *buf_end; |
|
92 |
|
u8 *p_end; |
|
93 |
|
|
|
94 |
|
buf_end = buf + BUFSIZ; |
|
95 |
|
p_end = buf; |
|
96 |
|
loop { |
|
97 |
|
struct pollfd pfd; |
|
98 |
|
int r; |
|
99 |
|
pfd.fd = s; |
|
100 |
|
pfd.events = POLLIN; |
|
101 |
|
pfd.revents = 0; |
|
102 |
|
errno = 0; |
|
103 |
|
r = poll(&pfd, 1, 2000); /* timeout of 2 secs */ |
|
104 |
|
if (r == -1) { |
|
105 |
|
if (errno == EINTR || errno == EAGAIN) |
|
106 |
|
continue; |
|
107 |
|
err(udev, "blkid:something went wrong while polling the unix socket\n"); |
|
108 |
|
return EXIT_FAILURE; |
|
109 |
|
} else if (r == 0) { |
|
110 |
|
err(udev, "blkid:timeout occured while polling the unix socket\n"); |
|
111 |
|
return EXIT_FAILURE; |
|
112 |
|
} |
|
113 |
|
/* r >= 0 */ |
|
114 |
|
if ((pfd.revents & POLLIN) != 0) { |
|
115 |
|
loop { |
|
116 |
|
errno = 0; |
|
117 |
|
r = recv(s, p_end, buf_end - p_end, 0); |
|
118 |
|
/* |
|
119 |
|
* when dealing with sockets, you can get |
|
120 |
|
* 0-length messages, just use the generalized |
|
121 |
|
* case |
|
122 |
|
*/ |
|
123 |
|
if (r >= 0) { |
|
124 |
|
p_end += r; |
|
125 |
|
break; |
|
126 |
|
} else if (r == -1 && errno == EINTR) |
|
127 |
|
continue; |
|
128 |
|
/* r < -1 || (r == -1 && errno != EINTR) */ |
|
129 |
|
err(udev, "blkid:something went wrong while reading from the unix socket\n"); |
|
130 |
|
return EXIT_FAILURE; |
|
131 |
|
} |
|
132 |
|
if (p_end == buf_end) |
|
133 |
|
break; /* try to process the buf data */ |
|
134 |
|
} |
|
135 |
|
if ((pfd.revents & (POLLERR | POLLHUP)) != 0) |
|
136 |
|
break; /* try to process the buf data */ |
|
137 |
|
} |
|
138 |
|
*p_end = 0; |
|
139 |
|
/*====================================================================*/ |
|
140 |
|
busybox_blkid_output_field(buf, "TYPE", &props->type); |
|
141 |
|
info(udev, "blkid:extracted filesystem \"%s\"\n", props->type ? props->type : "unknown"); |
|
142 |
|
busybox_blkid_output_field(buf, "UUID", &props->uuid); |
|
143 |
|
info(udev, "blkid:extracted uuid \"%s\"\n", props->uuid ? props->uuid : "unknown"); |
|
144 |
|
busybox_blkid_output_field(buf, "LABEL", &props->label); |
|
145 |
|
info(udev, "blkid:extracted label \"%s\"\n", props->label ? props->label : "unknown"); |
|
146 |
|
return EXIT_SUCCESS; |
|
147 |
|
} |
|
148 |
|
static int busybox_blkid_fork(struct udev_device *dev, |
|
149 |
|
struct busybox_blkid_t *props) |
|
150 |
|
{ |
|
151 |
|
struct udev *udev = udev_device_get_udev(dev); |
|
152 |
|
int r; |
|
153 |
|
int parse_r; |
|
154 |
|
int sv[2]; |
|
155 |
|
pid_t blkid_pid; |
|
156 |
|
int blkid_status; |
|
157 |
|
|
|
158 |
|
r = socketpair(AF_UNIX, SOCK_STREAM, 0, sv); |
|
159 |
|
if (r == -1) { |
|
160 |
|
err(udev, "blkid:unable to create a socket pair for invokation\n"); |
|
161 |
|
return EXIT_FAILURE; |
|
162 |
|
} |
|
163 |
|
blkid_pid = fork(); |
|
164 |
|
if (blkid_pid == -1) { |
|
165 |
|
close(sv[0]); |
|
166 |
|
close(sv[1]); |
|
167 |
|
err(udev, "blkid:unable to fork in order to exec\n"); |
|
168 |
|
return EXIT_FAILURE; |
|
169 |
|
} else if (blkid_pid == 0) { |
|
170 |
|
close(sv[0]); |
|
171 |
|
busybox_blkid_exec(dev, sv[1]); |
|
172 |
|
/* unreachable */ |
|
173 |
|
} |
|
174 |
|
close(sv[1]); |
|
175 |
|
parse_r = busybox_blkid_output_parse(udev, sv[0], props); |
|
176 |
|
close(sv[0]); |
|
177 |
|
/*--------------------------------------------------------------------*/ |
|
178 |
|
r = waitpid(blkid_pid, &blkid_status, 0); |
|
179 |
|
if (r == -1) { |
|
180 |
|
err(udev, "blkid:unable to wait for on pid %d\n", blkid_pid); |
|
181 |
|
return parse_r; |
|
182 |
|
} |
|
183 |
|
if (WIFEXITED(blkid_status)) { |
|
184 |
|
if (WEXITSTATUS(blkid_status) != 0) { |
|
185 |
|
err(udev, "blkid:exit status %d\n", WEXITSTATUS(blkid_status)); |
|
186 |
|
return EXIT_FAILURE; |
|
187 |
|
} |
|
188 |
|
/* WEXITSTATUS(blkid_status) == 0 */ |
|
189 |
|
return parse_r; |
|
190 |
|
} |
|
191 |
|
err(udev, "blkid:exited abnormally\n"); |
|
192 |
|
return EXIT_FAILURE; |
|
193 |
|
} |
192 |
194 |
|
|
193 |
|
blkid_free_probe(pr); |
|
194 |
|
out: |
|
195 |
|
if (fd > 0) |
|
196 |
|
close(fd); |
|
197 |
|
if (err < 0) |
|
198 |
|
return EXIT_FAILURE; |
|
199 |
|
return EXIT_SUCCESS; |
|
|
195 |
|
static int builtin_blkid(struct udev_device *dev, int argc, char *argv[], |
|
196 |
|
bool test) |
|
197 |
|
{ |
|
198 |
|
int r; |
|
199 |
|
struct busybox_blkid_t props; |
|
200 |
|
|
|
201 |
|
memset(&props, 0, sizeof(props)); |
|
202 |
|
r = busybox_blkid_fork(dev, &props); |
|
203 |
|
if (r == EXIT_FAILURE) |
|
204 |
|
return EXIT_FAILURE; |
|
205 |
|
if (props.type != 0) { |
|
206 |
|
udev_builtin_add_property(dev, test, "ID_FS_TYPE", props.type); |
|
207 |
|
free(props.type); |
|
208 |
|
} |
|
209 |
|
if (props.uuid != 0) { |
|
210 |
|
udev_builtin_add_property(dev, test, "ID_FS_UUID", props.uuid); |
|
211 |
|
free(props.uuid); |
|
212 |
|
} |
|
213 |
|
if (props.label != 0) { |
|
214 |
|
udev_builtin_add_property(dev, test, "ID_FS_LABEL", |
|
215 |
|
props.label); |
|
216 |
|
free(props.label); |
|
217 |
|
} |
|
218 |
|
return EXIT_SUCCESS; |
200 |
219 |
} |
} |
201 |
220 |
|
|
202 |
221 |
const struct udev_builtin udev_builtin_blkid = { |
const struct udev_builtin udev_builtin_blkid = { |
File src/udev-builtin-kmod.c changed (mode: 100644) (index 57e813f..a844fb3) |
1 |
1 |
/* |
/* |
2 |
2 |
* load kernel modules |
* load kernel modules |
3 |
3 |
* |
* |
4 |
|
* Copyright (C) 2011 Kay Sievers <kay.sievers@vrfy.org> |
|
5 |
|
* Copyright (C) 2011 ProFUSION embedded systems |
|
|
4 |
|
* Copyright (C) 2020 Sylvain BERTRAND <sylvain.bertrand@legeek.net> |
6 |
5 |
* |
* |
7 |
6 |
* This program is free software: you can redistribute it and/or modify |
* This program is free software: you can redistribute it and/or modify |
8 |
7 |
* it under the terms of the GNU General Public License as published by |
* it under the terms of the GNU General Public License as published by |
|
17 |
16 |
* You should have received a copy of the GNU General Public License |
* You should have received a copy of the GNU General Public License |
18 |
17 |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
* along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 |
18 |
*/ |
*/ |
20 |
|
|
|
21 |
19 |
#include <stdio.h> |
#include <stdio.h> |
22 |
20 |
#include <stdlib.h> |
#include <stdlib.h> |
23 |
21 |
#include <stdarg.h> |
#include <stdarg.h> |
|
27 |
25 |
#include <fcntl.h> |
#include <fcntl.h> |
28 |
26 |
#include <sys/stat.h> |
#include <sys/stat.h> |
29 |
27 |
#include <sys/wait.h> |
#include <sys/wait.h> |
30 |
|
#include <libkmod.h> |
|
31 |
|
|
|
32 |
28 |
#include "udev.h" |
#include "udev.h" |
33 |
|
|
|
34 |
|
static struct kmod_ctx *ctx; |
|
35 |
|
|
|
36 |
|
static int load_module(struct udev *udev, const char *alias) |
|
|
29 |
|
#define loop for(;;) |
|
30 |
|
static void busybox_modprobe_exec(struct udev *udev, char *alias) |
37 |
31 |
{ |
{ |
38 |
|
struct kmod_list *list = NULL; |
|
39 |
|
struct kmod_list *l; |
|
40 |
|
int err; |
|
41 |
|
|
|
42 |
|
err = kmod_module_new_from_lookup(ctx, alias, &list); |
|
43 |
|
if (err < 0) |
|
44 |
|
return err; |
|
45 |
|
|
|
46 |
|
if (list == NULL) |
|
47 |
|
info(udev, "no module matches '%s'\n", alias); |
|
48 |
|
|
|
49 |
|
kmod_list_foreach(l, list) { |
|
50 |
|
struct kmod_module *mod = kmod_module_get_module(l); |
|
51 |
|
|
|
52 |
|
err = kmod_module_probe_insert_module(mod, KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL, NULL); |
|
53 |
|
if (err == KMOD_PROBE_APPLY_BLACKLIST) |
|
54 |
|
info(udev, "module '%s' is blacklisted\n", kmod_module_get_name(mod)); |
|
55 |
|
else if (err == 0) |
|
56 |
|
info(udev, "inserted '%s'\n", kmod_module_get_name(mod)); |
|
57 |
|
else |
|
58 |
|
info(udev, "failed to insert '%s'\n", kmod_module_get_name(mod)); |
|
59 |
|
|
|
60 |
|
kmod_module_unref(mod); |
|
61 |
|
} |
|
62 |
|
|
|
63 |
|
kmod_module_unref_list(list); |
|
64 |
|
return err; |
|
|
32 |
|
loop { |
|
33 |
|
errno = 0; |
|
34 |
|
info(udev, "modprobe:exec for %s\n", alias); |
|
35 |
|
execlp("modprobe", "modprobe", alias, 0); |
|
36 |
|
if (errno != EAGAIN) { |
|
37 |
|
err(udev, "modprobe:unable to exec\n"); |
|
38 |
|
exit(1); |
|
39 |
|
} |
|
40 |
|
/* EAGAIN */ |
|
41 |
|
} |
|
42 |
|
/* unreachable */ |
65 |
43 |
} |
} |
66 |
|
|
|
67 |
|
static void udev_kmod_log(void *data, int priority, const char *file, int line, |
|
68 |
|
const char *fn, const char *format, va_list args) |
|
|
44 |
|
/* we fork here */ |
|
45 |
|
static int load_module(struct udev *udev, char *alias) |
69 |
46 |
{ |
{ |
70 |
|
udev_main_log(data, priority, file, line, fn, format, args); |
|
|
47 |
|
pid_t modprobe_pid; |
|
48 |
|
int r; |
|
49 |
|
int modprobe_status; |
|
50 |
|
|
|
51 |
|
modprobe_pid = fork(); |
|
52 |
|
if (modprobe_pid == -1) { |
|
53 |
|
err(udev, "modprobe:unable to fork in order to exec\n"); |
|
54 |
|
return EXIT_FAILURE; |
|
55 |
|
} else if (modprobe_pid == 0) { |
|
56 |
|
busybox_modprobe_exec(udev, alias); |
|
57 |
|
/* unreachable */ |
|
58 |
|
} |
|
59 |
|
r = waitpid(modprobe_pid, &modprobe_status, 0); |
|
60 |
|
if (r == -1) { |
|
61 |
|
err(udev, "modprobe:unable to wait for on pid %d\n", modprobe_pid); |
|
62 |
|
return EXIT_FAILURE; |
|
63 |
|
} |
|
64 |
|
if (WIFEXITED(modprobe_status)) { |
|
65 |
|
if (WEXITSTATUS(modprobe_status) != 0) { |
|
66 |
|
err(udev, "mobprobe:exit status %d\n", WEXITSTATUS(modprobe_status)); |
|
67 |
|
return EXIT_FAILURE; |
|
68 |
|
} |
|
69 |
|
/* WEXITSTATUS(modprobe_status) == 0 */ |
|
70 |
|
return EXIT_SUCCESS; |
|
71 |
|
} |
|
72 |
|
err(udev, "modprobe:exited abnormally\n"); |
|
73 |
|
return EXIT_FAILURE; |
71 |
74 |
} |
} |
72 |
|
|
|
73 |
|
/* needs to re-instantiate the context after a reload */ |
|
74 |
75 |
static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) |
static int builtin_kmod(struct udev_device *dev, int argc, char *argv[], bool test) |
75 |
76 |
{ |
{ |
76 |
77 |
struct udev *udev = udev_device_get_udev(dev); |
struct udev *udev = udev_device_get_udev(dev); |
77 |
78 |
int i; |
int i; |
78 |
79 |
|
|
79 |
|
if (!ctx) { |
|
80 |
|
ctx = kmod_new(NULL, NULL); |
|
81 |
|
if (!ctx) |
|
82 |
|
return -ENOMEM; |
|
83 |
|
|
|
84 |
|
info(udev, "load module index\n"); |
|
85 |
|
kmod_set_log_fn(ctx, udev_kmod_log, udev); |
|
86 |
|
kmod_load_resources(ctx); |
|
87 |
|
} |
|
88 |
|
|
|
89 |
80 |
if (argc < 3 || strcmp(argv[1], "load")) { |
if (argc < 3 || strcmp(argv[1], "load")) { |
90 |
|
err(udev, "expect: %s load <module>\n", argv[0]); |
|
|
81 |
|
err(udev, "modprobe:expect: %s load <module>\n", argv[0]); |
91 |
82 |
return EXIT_FAILURE; |
return EXIT_FAILURE; |
92 |
83 |
} |
} |
93 |
|
|
|
94 |
84 |
for (i = 2; argv[i]; i++) { |
for (i = 2; argv[i]; i++) { |
95 |
|
info(udev, "execute '%s' '%s'\n", argv[1], argv[i]); |
|
|
85 |
|
info(udev, "modprobe:execute '%s' '%s'\n", argv[1], argv[i]); |
96 |
86 |
load_module(udev, argv[i]); |
load_module(udev, argv[i]); |
97 |
87 |
} |
} |
98 |
|
|
|
99 |
88 |
return EXIT_SUCCESS; |
return EXIT_SUCCESS; |
100 |
89 |
} |
} |
101 |
|
|
|
102 |
90 |
/* called at udev startup */ |
/* called at udev startup */ |
103 |
91 |
static int builtin_kmod_init(struct udev *udev) |
static int builtin_kmod_init(struct udev *udev) |
104 |
92 |
{ |
{ |
105 |
|
if (ctx) |
|
106 |
|
return 0; |
|
107 |
|
|
|
108 |
|
ctx = kmod_new(NULL, NULL); |
|
109 |
|
if (!ctx) |
|
110 |
|
return -ENOMEM; |
|
111 |
|
|
|
112 |
|
info(udev, "load module index\n"); |
|
113 |
|
kmod_set_log_fn(ctx, udev_kmod_log, udev); |
|
114 |
|
kmod_load_resources(ctx); |
|
|
93 |
|
info(udev, "initing busybox modprobe:empty\n"); |
115 |
94 |
return 0; |
return 0; |
116 |
95 |
} |
} |
117 |
|
|
|
118 |
96 |
/* called on udev shutdown and reload request */ |
/* called on udev shutdown and reload request */ |
119 |
97 |
static void builtin_kmod_exit(struct udev *udev) |
static void builtin_kmod_exit(struct udev *udev) |
120 |
98 |
{ |
{ |
121 |
|
info(udev, "unload module index\n"); |
|
122 |
|
ctx = kmod_unref(ctx); |
|
|
99 |
|
info(udev, "exiting busybox modprobe:empty\n"); |
123 |
100 |
} |
} |
124 |
|
|
|
125 |
101 |
/* called every couple of seconds during event activity; 'true' if config has changed */ |
/* called every couple of seconds during event activity; 'true' if config has changed */ |
126 |
102 |
static bool builtin_kmod_validate(struct udev *udev) |
static bool builtin_kmod_validate(struct udev *udev) |
127 |
103 |
{ |
{ |
128 |
|
info(udev, "validate module index\n"); |
|
129 |
|
if (kmod_validate_resources(ctx) != KMOD_RESOURCES_OK) |
|
130 |
|
return true; |
|
131 |
|
return false; |
|
|
104 |
|
info(udev, "validation of busybox module databases done at invokation time\n"); |
|
105 |
|
return true; |
132 |
106 |
} |
} |
133 |
|
|
|
134 |
107 |
const struct udev_builtin udev_builtin_kmod = { |
const struct udev_builtin udev_builtin_kmod = { |
135 |
108 |
.name = "kmod", |
.name = "kmod", |
136 |
109 |
.cmd = builtin_kmod, |
.cmd = builtin_kmod, |