1*cc4ad7daSAndroid Build Coastguard Worker /*
2*cc4ad7daSAndroid Build Coastguard Worker * libkmod - interface to kernel built-in modules
3*cc4ad7daSAndroid Build Coastguard Worker *
4*cc4ad7daSAndroid Build Coastguard Worker * Copyright (C) 2019 Alexey Gladkov <[email protected]>
5*cc4ad7daSAndroid Build Coastguard Worker *
6*cc4ad7daSAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or
7*cc4ad7daSAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
8*cc4ad7daSAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
9*cc4ad7daSAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
10*cc4ad7daSAndroid Build Coastguard Worker *
11*cc4ad7daSAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful,
12*cc4ad7daSAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
13*cc4ad7daSAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14*cc4ad7daSAndroid Build Coastguard Worker * Lesser General Public License for more details.
15*cc4ad7daSAndroid Build Coastguard Worker *
16*cc4ad7daSAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
17*cc4ad7daSAndroid Build Coastguard Worker * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18*cc4ad7daSAndroid Build Coastguard Worker */
19*cc4ad7daSAndroid Build Coastguard Worker
20*cc4ad7daSAndroid Build Coastguard Worker #include <sys/types.h>
21*cc4ad7daSAndroid Build Coastguard Worker #include <sys/stat.h>
22*cc4ad7daSAndroid Build Coastguard Worker
23*cc4ad7daSAndroid Build Coastguard Worker #include <unistd.h>
24*cc4ad7daSAndroid Build Coastguard Worker #include <stdio.h>
25*cc4ad7daSAndroid Build Coastguard Worker #include <stdlib.h>
26*cc4ad7daSAndroid Build Coastguard Worker #include <string.h>
27*cc4ad7daSAndroid Build Coastguard Worker #include <errno.h>
28*cc4ad7daSAndroid Build Coastguard Worker
29*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod.h"
30*cc4ad7daSAndroid Build Coastguard Worker #include "libkmod-internal.h"
31*cc4ad7daSAndroid Build Coastguard Worker
32*cc4ad7daSAndroid Build Coastguard Worker #define MODULES_BUILTIN_MODINFO "modules.builtin.modinfo"
33*cc4ad7daSAndroid Build Coastguard Worker
34*cc4ad7daSAndroid Build Coastguard Worker struct kmod_builtin_iter {
35*cc4ad7daSAndroid Build Coastguard Worker struct kmod_ctx *ctx;
36*cc4ad7daSAndroid Build Coastguard Worker
37*cc4ad7daSAndroid Build Coastguard Worker // The file descriptor.
38*cc4ad7daSAndroid Build Coastguard Worker int file;
39*cc4ad7daSAndroid Build Coastguard Worker
40*cc4ad7daSAndroid Build Coastguard Worker // The total size in bytes.
41*cc4ad7daSAndroid Build Coastguard Worker ssize_t size;
42*cc4ad7daSAndroid Build Coastguard Worker
43*cc4ad7daSAndroid Build Coastguard Worker // The offset of current module.
44*cc4ad7daSAndroid Build Coastguard Worker off_t pos;
45*cc4ad7daSAndroid Build Coastguard Worker
46*cc4ad7daSAndroid Build Coastguard Worker // The offset at which the next module is located.
47*cc4ad7daSAndroid Build Coastguard Worker off_t next;
48*cc4ad7daSAndroid Build Coastguard Worker
49*cc4ad7daSAndroid Build Coastguard Worker // Number of strings in the current block.
50*cc4ad7daSAndroid Build Coastguard Worker ssize_t nstrings;
51*cc4ad7daSAndroid Build Coastguard Worker
52*cc4ad7daSAndroid Build Coastguard Worker // Internal buffer and its size.
53*cc4ad7daSAndroid Build Coastguard Worker size_t bufsz;
54*cc4ad7daSAndroid Build Coastguard Worker char *buf;
55*cc4ad7daSAndroid Build Coastguard Worker };
56*cc4ad7daSAndroid Build Coastguard Worker
kmod_builtin_iter_new(struct kmod_ctx * ctx)57*cc4ad7daSAndroid Build Coastguard Worker static struct kmod_builtin_iter *kmod_builtin_iter_new(struct kmod_ctx *ctx)
58*cc4ad7daSAndroid Build Coastguard Worker {
59*cc4ad7daSAndroid Build Coastguard Worker char path[PATH_MAX];
60*cc4ad7daSAndroid Build Coastguard Worker int file, sv_errno;
61*cc4ad7daSAndroid Build Coastguard Worker struct stat sb;
62*cc4ad7daSAndroid Build Coastguard Worker struct kmod_builtin_iter *iter = NULL;
63*cc4ad7daSAndroid Build Coastguard Worker const char *dirname = kmod_get_dirname(ctx);
64*cc4ad7daSAndroid Build Coastguard Worker size_t len = strlen(dirname);
65*cc4ad7daSAndroid Build Coastguard Worker
66*cc4ad7daSAndroid Build Coastguard Worker file = -1;
67*cc4ad7daSAndroid Build Coastguard Worker
68*cc4ad7daSAndroid Build Coastguard Worker if ((len + 1 + strlen(MODULES_BUILTIN_MODINFO) + 1) >= PATH_MAX) {
69*cc4ad7daSAndroid Build Coastguard Worker sv_errno = ENAMETOOLONG;
70*cc4ad7daSAndroid Build Coastguard Worker goto fail;
71*cc4ad7daSAndroid Build Coastguard Worker }
72*cc4ad7daSAndroid Build Coastguard Worker
73*cc4ad7daSAndroid Build Coastguard Worker snprintf(path, PATH_MAX, "%s/%s", dirname, MODULES_BUILTIN_MODINFO);
74*cc4ad7daSAndroid Build Coastguard Worker
75*cc4ad7daSAndroid Build Coastguard Worker file = open(path, O_RDONLY|O_CLOEXEC);
76*cc4ad7daSAndroid Build Coastguard Worker if (file < 0) {
77*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
78*cc4ad7daSAndroid Build Coastguard Worker goto fail;
79*cc4ad7daSAndroid Build Coastguard Worker }
80*cc4ad7daSAndroid Build Coastguard Worker
81*cc4ad7daSAndroid Build Coastguard Worker if (fstat(file, &sb) < 0) {
82*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
83*cc4ad7daSAndroid Build Coastguard Worker goto fail;
84*cc4ad7daSAndroid Build Coastguard Worker }
85*cc4ad7daSAndroid Build Coastguard Worker
86*cc4ad7daSAndroid Build Coastguard Worker iter = malloc(sizeof(*iter));
87*cc4ad7daSAndroid Build Coastguard Worker if (!iter) {
88*cc4ad7daSAndroid Build Coastguard Worker sv_errno = ENOMEM;
89*cc4ad7daSAndroid Build Coastguard Worker goto fail;
90*cc4ad7daSAndroid Build Coastguard Worker }
91*cc4ad7daSAndroid Build Coastguard Worker
92*cc4ad7daSAndroid Build Coastguard Worker iter->ctx = ctx;
93*cc4ad7daSAndroid Build Coastguard Worker iter->file = file;
94*cc4ad7daSAndroid Build Coastguard Worker iter->size = sb.st_size;
95*cc4ad7daSAndroid Build Coastguard Worker iter->nstrings = 0;
96*cc4ad7daSAndroid Build Coastguard Worker iter->pos = 0;
97*cc4ad7daSAndroid Build Coastguard Worker iter->next = 0;
98*cc4ad7daSAndroid Build Coastguard Worker iter->bufsz = 0;
99*cc4ad7daSAndroid Build Coastguard Worker iter->buf = NULL;
100*cc4ad7daSAndroid Build Coastguard Worker
101*cc4ad7daSAndroid Build Coastguard Worker return iter;
102*cc4ad7daSAndroid Build Coastguard Worker fail:
103*cc4ad7daSAndroid Build Coastguard Worker if (file >= 0)
104*cc4ad7daSAndroid Build Coastguard Worker close(file);
105*cc4ad7daSAndroid Build Coastguard Worker
106*cc4ad7daSAndroid Build Coastguard Worker errno = sv_errno;
107*cc4ad7daSAndroid Build Coastguard Worker
108*cc4ad7daSAndroid Build Coastguard Worker return iter;
109*cc4ad7daSAndroid Build Coastguard Worker }
110*cc4ad7daSAndroid Build Coastguard Worker
kmod_builtin_iter_free(struct kmod_builtin_iter * iter)111*cc4ad7daSAndroid Build Coastguard Worker static void kmod_builtin_iter_free(struct kmod_builtin_iter *iter)
112*cc4ad7daSAndroid Build Coastguard Worker {
113*cc4ad7daSAndroid Build Coastguard Worker close(iter->file);
114*cc4ad7daSAndroid Build Coastguard Worker free(iter->buf);
115*cc4ad7daSAndroid Build Coastguard Worker free(iter);
116*cc4ad7daSAndroid Build Coastguard Worker }
117*cc4ad7daSAndroid Build Coastguard Worker
get_string(struct kmod_builtin_iter * iter,off_t offset,char ** line,size_t * size)118*cc4ad7daSAndroid Build Coastguard Worker static off_t get_string(struct kmod_builtin_iter *iter, off_t offset,
119*cc4ad7daSAndroid Build Coastguard Worker char **line, size_t *size)
120*cc4ad7daSAndroid Build Coastguard Worker {
121*cc4ad7daSAndroid Build Coastguard Worker int sv_errno;
122*cc4ad7daSAndroid Build Coastguard Worker char *nullp = NULL;
123*cc4ad7daSAndroid Build Coastguard Worker size_t linesz = 0;
124*cc4ad7daSAndroid Build Coastguard Worker
125*cc4ad7daSAndroid Build Coastguard Worker while (!nullp) {
126*cc4ad7daSAndroid Build Coastguard Worker char buf[BUFSIZ];
127*cc4ad7daSAndroid Build Coastguard Worker ssize_t sz;
128*cc4ad7daSAndroid Build Coastguard Worker size_t partsz;
129*cc4ad7daSAndroid Build Coastguard Worker
130*cc4ad7daSAndroid Build Coastguard Worker sz = pread(iter->file, buf, BUFSIZ, offset);
131*cc4ad7daSAndroid Build Coastguard Worker if (sz < 0) {
132*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
133*cc4ad7daSAndroid Build Coastguard Worker goto fail;
134*cc4ad7daSAndroid Build Coastguard Worker } else if (sz == 0) {
135*cc4ad7daSAndroid Build Coastguard Worker offset = 0;
136*cc4ad7daSAndroid Build Coastguard Worker break;
137*cc4ad7daSAndroid Build Coastguard Worker }
138*cc4ad7daSAndroid Build Coastguard Worker
139*cc4ad7daSAndroid Build Coastguard Worker nullp = memchr(buf, '\0', (size_t) sz);
140*cc4ad7daSAndroid Build Coastguard Worker partsz = (size_t)((nullp) ? (nullp - buf) + 1 : sz);
141*cc4ad7daSAndroid Build Coastguard Worker offset += (off_t) partsz;
142*cc4ad7daSAndroid Build Coastguard Worker
143*cc4ad7daSAndroid Build Coastguard Worker if (iter->bufsz < linesz + partsz) {
144*cc4ad7daSAndroid Build Coastguard Worker iter->bufsz = linesz + partsz;
145*cc4ad7daSAndroid Build Coastguard Worker iter->buf = realloc(iter->buf, iter->bufsz);
146*cc4ad7daSAndroid Build Coastguard Worker
147*cc4ad7daSAndroid Build Coastguard Worker if (!iter->buf) {
148*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
149*cc4ad7daSAndroid Build Coastguard Worker goto fail;
150*cc4ad7daSAndroid Build Coastguard Worker }
151*cc4ad7daSAndroid Build Coastguard Worker }
152*cc4ad7daSAndroid Build Coastguard Worker
153*cc4ad7daSAndroid Build Coastguard Worker strncpy(iter->buf + linesz, buf, partsz);
154*cc4ad7daSAndroid Build Coastguard Worker linesz += partsz;
155*cc4ad7daSAndroid Build Coastguard Worker }
156*cc4ad7daSAndroid Build Coastguard Worker
157*cc4ad7daSAndroid Build Coastguard Worker if (linesz) {
158*cc4ad7daSAndroid Build Coastguard Worker *line = iter->buf;
159*cc4ad7daSAndroid Build Coastguard Worker *size = linesz;
160*cc4ad7daSAndroid Build Coastguard Worker }
161*cc4ad7daSAndroid Build Coastguard Worker
162*cc4ad7daSAndroid Build Coastguard Worker return offset;
163*cc4ad7daSAndroid Build Coastguard Worker fail:
164*cc4ad7daSAndroid Build Coastguard Worker errno = sv_errno;
165*cc4ad7daSAndroid Build Coastguard Worker return -1;
166*cc4ad7daSAndroid Build Coastguard Worker }
167*cc4ad7daSAndroid Build Coastguard Worker
kmod_builtin_iter_next(struct kmod_builtin_iter * iter)168*cc4ad7daSAndroid Build Coastguard Worker static bool kmod_builtin_iter_next(struct kmod_builtin_iter *iter)
169*cc4ad7daSAndroid Build Coastguard Worker {
170*cc4ad7daSAndroid Build Coastguard Worker char *line, *modname;
171*cc4ad7daSAndroid Build Coastguard Worker size_t linesz;
172*cc4ad7daSAndroid Build Coastguard Worker off_t pos, offset, modlen;
173*cc4ad7daSAndroid Build Coastguard Worker
174*cc4ad7daSAndroid Build Coastguard Worker modname = NULL;
175*cc4ad7daSAndroid Build Coastguard Worker
176*cc4ad7daSAndroid Build Coastguard Worker iter->nstrings = 0;
177*cc4ad7daSAndroid Build Coastguard Worker offset = pos = iter->next;
178*cc4ad7daSAndroid Build Coastguard Worker
179*cc4ad7daSAndroid Build Coastguard Worker while (offset < iter->size) {
180*cc4ad7daSAndroid Build Coastguard Worker char *dot;
181*cc4ad7daSAndroid Build Coastguard Worker off_t len;
182*cc4ad7daSAndroid Build Coastguard Worker
183*cc4ad7daSAndroid Build Coastguard Worker offset = get_string(iter, pos, &line, &linesz);
184*cc4ad7daSAndroid Build Coastguard Worker if (offset <= 0) {
185*cc4ad7daSAndroid Build Coastguard Worker if (offset)
186*cc4ad7daSAndroid Build Coastguard Worker ERR(iter->ctx, "get_string: %s\n", strerror(errno));
187*cc4ad7daSAndroid Build Coastguard Worker pos = iter->size;
188*cc4ad7daSAndroid Build Coastguard Worker break;
189*cc4ad7daSAndroid Build Coastguard Worker }
190*cc4ad7daSAndroid Build Coastguard Worker
191*cc4ad7daSAndroid Build Coastguard Worker dot = strchr(line, '.');
192*cc4ad7daSAndroid Build Coastguard Worker if (!dot) {
193*cc4ad7daSAndroid Build Coastguard Worker ERR(iter->ctx, "kmod_builtin_iter_next: unexpected string without modname prefix\n");
194*cc4ad7daSAndroid Build Coastguard Worker pos = iter->size;
195*cc4ad7daSAndroid Build Coastguard Worker break;
196*cc4ad7daSAndroid Build Coastguard Worker }
197*cc4ad7daSAndroid Build Coastguard Worker
198*cc4ad7daSAndroid Build Coastguard Worker len = dot - line;
199*cc4ad7daSAndroid Build Coastguard Worker
200*cc4ad7daSAndroid Build Coastguard Worker if (!modname) {
201*cc4ad7daSAndroid Build Coastguard Worker modname = strdup(line);
202*cc4ad7daSAndroid Build Coastguard Worker modlen = len;
203*cc4ad7daSAndroid Build Coastguard Worker } else if (modlen != len || strncmp(modname, line, len)) {
204*cc4ad7daSAndroid Build Coastguard Worker break;
205*cc4ad7daSAndroid Build Coastguard Worker }
206*cc4ad7daSAndroid Build Coastguard Worker
207*cc4ad7daSAndroid Build Coastguard Worker iter->nstrings++;
208*cc4ad7daSAndroid Build Coastguard Worker pos = offset;
209*cc4ad7daSAndroid Build Coastguard Worker }
210*cc4ad7daSAndroid Build Coastguard Worker
211*cc4ad7daSAndroid Build Coastguard Worker iter->pos = iter->next;
212*cc4ad7daSAndroid Build Coastguard Worker iter->next = pos;
213*cc4ad7daSAndroid Build Coastguard Worker
214*cc4ad7daSAndroid Build Coastguard Worker free(modname);
215*cc4ad7daSAndroid Build Coastguard Worker
216*cc4ad7daSAndroid Build Coastguard Worker return (iter->pos < iter->size);
217*cc4ad7daSAndroid Build Coastguard Worker }
218*cc4ad7daSAndroid Build Coastguard Worker
kmod_builtin_iter_get_modname(struct kmod_builtin_iter * iter,char modname[static PATH_MAX])219*cc4ad7daSAndroid Build Coastguard Worker static bool kmod_builtin_iter_get_modname(struct kmod_builtin_iter *iter,
220*cc4ad7daSAndroid Build Coastguard Worker char modname[static PATH_MAX])
221*cc4ad7daSAndroid Build Coastguard Worker {
222*cc4ad7daSAndroid Build Coastguard Worker int sv_errno;
223*cc4ad7daSAndroid Build Coastguard Worker char *line, *dot;
224*cc4ad7daSAndroid Build Coastguard Worker size_t linesz, len;
225*cc4ad7daSAndroid Build Coastguard Worker off_t offset;
226*cc4ad7daSAndroid Build Coastguard Worker
227*cc4ad7daSAndroid Build Coastguard Worker if (iter->pos == iter->size)
228*cc4ad7daSAndroid Build Coastguard Worker return false;
229*cc4ad7daSAndroid Build Coastguard Worker
230*cc4ad7daSAndroid Build Coastguard Worker line = NULL;
231*cc4ad7daSAndroid Build Coastguard Worker
232*cc4ad7daSAndroid Build Coastguard Worker offset = get_string(iter, iter->pos, &line, &linesz);
233*cc4ad7daSAndroid Build Coastguard Worker if (offset <= 0) {
234*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
235*cc4ad7daSAndroid Build Coastguard Worker if (offset)
236*cc4ad7daSAndroid Build Coastguard Worker ERR(iter->ctx, "get_string: %s\n", strerror(errno));
237*cc4ad7daSAndroid Build Coastguard Worker goto fail;
238*cc4ad7daSAndroid Build Coastguard Worker }
239*cc4ad7daSAndroid Build Coastguard Worker
240*cc4ad7daSAndroid Build Coastguard Worker dot = strchr(line, '.');
241*cc4ad7daSAndroid Build Coastguard Worker if (!dot) {
242*cc4ad7daSAndroid Build Coastguard Worker sv_errno = errno;
243*cc4ad7daSAndroid Build Coastguard Worker ERR(iter->ctx, "kmod_builtin_iter_get_modname: unexpected string without modname prefix\n");
244*cc4ad7daSAndroid Build Coastguard Worker goto fail;
245*cc4ad7daSAndroid Build Coastguard Worker }
246*cc4ad7daSAndroid Build Coastguard Worker
247*cc4ad7daSAndroid Build Coastguard Worker len = dot - line;
248*cc4ad7daSAndroid Build Coastguard Worker
249*cc4ad7daSAndroid Build Coastguard Worker if (len >= PATH_MAX) {
250*cc4ad7daSAndroid Build Coastguard Worker sv_errno = ENAMETOOLONG;
251*cc4ad7daSAndroid Build Coastguard Worker goto fail;
252*cc4ad7daSAndroid Build Coastguard Worker }
253*cc4ad7daSAndroid Build Coastguard Worker
254*cc4ad7daSAndroid Build Coastguard Worker strncpy(modname, line, len);
255*cc4ad7daSAndroid Build Coastguard Worker modname[len] = '\0';
256*cc4ad7daSAndroid Build Coastguard Worker
257*cc4ad7daSAndroid Build Coastguard Worker return true;
258*cc4ad7daSAndroid Build Coastguard Worker fail:
259*cc4ad7daSAndroid Build Coastguard Worker errno = sv_errno;
260*cc4ad7daSAndroid Build Coastguard Worker return false;
261*cc4ad7daSAndroid Build Coastguard Worker }
262*cc4ad7daSAndroid Build Coastguard Worker
263*cc4ad7daSAndroid Build Coastguard Worker /* array will be allocated with strings in a single malloc, just free *array */
kmod_builtin_get_modinfo(struct kmod_ctx * ctx,const char * modname,char *** modinfo)264*cc4ad7daSAndroid Build Coastguard Worker ssize_t kmod_builtin_get_modinfo(struct kmod_ctx *ctx, const char *modname,
265*cc4ad7daSAndroid Build Coastguard Worker char ***modinfo)
266*cc4ad7daSAndroid Build Coastguard Worker {
267*cc4ad7daSAndroid Build Coastguard Worker ssize_t count = 0;
268*cc4ad7daSAndroid Build Coastguard Worker char *s, *line = NULL;
269*cc4ad7daSAndroid Build Coastguard Worker size_t i, n, linesz, modlen, size;
270*cc4ad7daSAndroid Build Coastguard Worker off_t pos, offset;
271*cc4ad7daSAndroid Build Coastguard Worker
272*cc4ad7daSAndroid Build Coastguard Worker char *name = NULL;
273*cc4ad7daSAndroid Build Coastguard Worker char buf[PATH_MAX];
274*cc4ad7daSAndroid Build Coastguard Worker
275*cc4ad7daSAndroid Build Coastguard Worker struct kmod_builtin_iter *iter = kmod_builtin_iter_new(ctx);
276*cc4ad7daSAndroid Build Coastguard Worker
277*cc4ad7daSAndroid Build Coastguard Worker if (!iter)
278*cc4ad7daSAndroid Build Coastguard Worker return -errno;
279*cc4ad7daSAndroid Build Coastguard Worker
280*cc4ad7daSAndroid Build Coastguard Worker while (!name && kmod_builtin_iter_next(iter)) {
281*cc4ad7daSAndroid Build Coastguard Worker if (!kmod_builtin_iter_get_modname(iter, buf)) {
282*cc4ad7daSAndroid Build Coastguard Worker count = -errno;
283*cc4ad7daSAndroid Build Coastguard Worker goto fail;
284*cc4ad7daSAndroid Build Coastguard Worker }
285*cc4ad7daSAndroid Build Coastguard Worker
286*cc4ad7daSAndroid Build Coastguard Worker if (strcmp(modname, buf))
287*cc4ad7daSAndroid Build Coastguard Worker continue;
288*cc4ad7daSAndroid Build Coastguard Worker
289*cc4ad7daSAndroid Build Coastguard Worker name = buf;
290*cc4ad7daSAndroid Build Coastguard Worker }
291*cc4ad7daSAndroid Build Coastguard Worker
292*cc4ad7daSAndroid Build Coastguard Worker if (!name) {
293*cc4ad7daSAndroid Build Coastguard Worker count = -ENOSYS;
294*cc4ad7daSAndroid Build Coastguard Worker goto fail;
295*cc4ad7daSAndroid Build Coastguard Worker }
296*cc4ad7daSAndroid Build Coastguard Worker
297*cc4ad7daSAndroid Build Coastguard Worker modlen = strlen(modname) + 1;
298*cc4ad7daSAndroid Build Coastguard Worker count = iter->nstrings;
299*cc4ad7daSAndroid Build Coastguard Worker size = iter->next - iter->pos - (modlen * count);
300*cc4ad7daSAndroid Build Coastguard Worker
301*cc4ad7daSAndroid Build Coastguard Worker *modinfo = malloc(size + sizeof(char *) * (count + 1));
302*cc4ad7daSAndroid Build Coastguard Worker if (!*modinfo) {
303*cc4ad7daSAndroid Build Coastguard Worker count = -errno;
304*cc4ad7daSAndroid Build Coastguard Worker goto fail;
305*cc4ad7daSAndroid Build Coastguard Worker }
306*cc4ad7daSAndroid Build Coastguard Worker
307*cc4ad7daSAndroid Build Coastguard Worker s = (char *)(*modinfo + count + 1);
308*cc4ad7daSAndroid Build Coastguard Worker i = 0;
309*cc4ad7daSAndroid Build Coastguard Worker
310*cc4ad7daSAndroid Build Coastguard Worker n = 0;
311*cc4ad7daSAndroid Build Coastguard Worker offset = pos = iter->pos;
312*cc4ad7daSAndroid Build Coastguard Worker
313*cc4ad7daSAndroid Build Coastguard Worker while (offset < iter->next) {
314*cc4ad7daSAndroid Build Coastguard Worker offset = get_string(iter, pos, &line, &linesz);
315*cc4ad7daSAndroid Build Coastguard Worker if (offset <= 0) {
316*cc4ad7daSAndroid Build Coastguard Worker count = (offset) ? -errno : -EINVAL;
317*cc4ad7daSAndroid Build Coastguard Worker free(*modinfo);
318*cc4ad7daSAndroid Build Coastguard Worker goto fail;
319*cc4ad7daSAndroid Build Coastguard Worker }
320*cc4ad7daSAndroid Build Coastguard Worker
321*cc4ad7daSAndroid Build Coastguard Worker strcpy(s + i, line + modlen);
322*cc4ad7daSAndroid Build Coastguard Worker (*modinfo)[n++] = s + i;
323*cc4ad7daSAndroid Build Coastguard Worker i += linesz - modlen;
324*cc4ad7daSAndroid Build Coastguard Worker
325*cc4ad7daSAndroid Build Coastguard Worker pos = offset;
326*cc4ad7daSAndroid Build Coastguard Worker }
327*cc4ad7daSAndroid Build Coastguard Worker fail:
328*cc4ad7daSAndroid Build Coastguard Worker kmod_builtin_iter_free(iter);
329*cc4ad7daSAndroid Build Coastguard Worker return count;
330*cc4ad7daSAndroid Build Coastguard Worker }
331