Skip to content

Commit cfd6168

Browse files
committed
external/ffspart: Use read() rather than mmap()
The various ffspart test cases use /dev/zero as an input which doesn't behave like a normal file. The stat.st_size field for char devs is generally zero so the subsequent attempt to mmap() the file fails because we requested a zero size mapping. Previously we didn't notice this, but it sort of worked since the partitions in the test script that used /dev/zero as an input were also had those partitions marked as ECC. This resulted in the partition contents being re-generated (using a buffer libflash allocates) and the source data pointer being ignored since we said it was zero length. Fix all this by dropping mmap() entirely and inhale the input file into a buffer we malloc() instead. This works for any file, including /dev/urandom, which can't be mmap()ed. Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
1 parent 3da6027 commit cfd6168

File tree

1 file changed

+34
-8
lines changed

1 file changed

+34
-8
lines changed

external/ffspart/ffspart.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ static int parse_entry(struct blocklevel_device *bl,
241241
ffs_entry_put(new_entry);
242242

243243
if (*line != '\0' && *(line + 1) != '\0') {
244+
size_t data_len;
245+
244246
filename = line + 1;
245247

246248
/*
@@ -263,8 +265,29 @@ static int parse_entry(struct blocklevel_device *bl,
263265
close(data_fd);
264266
return -1;
265267
}
268+
269+
data_ptr = calloc(1, psize);
270+
if (!data_ptr) {
271+
return -1;
272+
}
273+
266274
pactual = data_stat.st_size;
267275

276+
/*
277+
* There's two char device inputs we care about: /dev/zero and
278+
* /dev/urandom. Both have a stat.st_size of zero so read in
279+
* a full partition worth, accounting for ECC overhead.
280+
*/
281+
if (!pactual && S_ISCHR(data_stat.st_mode)) {
282+
pactual = psize;
283+
284+
if (has_ecc(new_entry)) {
285+
pactual = ecc_buffer_size_minus_ecc(pactual);
286+
287+
/* ECC input size needs to be a multiple of 8 */
288+
pactual = pactual & ~0x7;
289+
}
290+
}
268291
/*
269292
* Sanity check that the file isn't too large for
270293
* partition
@@ -279,19 +302,22 @@ static int parse_entry(struct blocklevel_device *bl,
279302
return -1;
280303
}
281304

282-
data_ptr = mmap(NULL, pactual, PROT_READ, MAP_SHARED, data_fd, 0);
283-
if (!data_ptr) {
284-
fprintf(stderr, "Couldn't mmap file '%s' for '%s' partition "
285-
"(%m)\n", filename, name);
286-
close(data_fd);
287-
return -1;
305+
for (data_len = 0; data_len < pactual; data_len += rc) {
306+
rc = read(data_fd, &data_ptr[data_len], pactual - data_len);
307+
if (rc == -1) {
308+
fprintf(stderr, "error reading from '%s'", filename);
309+
exit(1);
310+
}
288311
}
289312

290313
rc = blocklevel_write(bl, pbase, data_ptr, pactual);
291-
if (rc)
314+
if (rc) {
292315
fprintf(stderr, "Couldn't write file '%s' for '%s' partition to PNOR "
293316
"(%m)\n", filename, name);
294-
munmap(data_ptr, pactual);
317+
exit(1);
318+
}
319+
320+
free(data_ptr);
295321
close(data_fd);
296322
} else {
297323
if (!allow_empty) {

0 commit comments

Comments
 (0)