Skip to content

Commit ea80487

Browse files
ddissakpm00
authored andcommitted
gen_init_cpio: support file checksum archiving
Documentation/driver-api/early-userspace/buffer-format.rst includes the specification for checksum-enabled cpio archives. Implement support for this format in gen_init_cpio via a new '-c' parameter. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: David Disseldorp <[email protected]> Suggested-by: Matthew Wilcox (Oracle) <[email protected]> Cc: Al Viro <[email protected]> Cc: Christian Brauner <[email protected]> Cc: Martin Wilck <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 3a2699c commit ea80487

File tree

1 file changed

+45
-9
lines changed

1 file changed

+45
-9
lines changed

usr/gen_init_cpio.c

+45-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <stdio.h>
33
#include <stdlib.h>
4+
#include <stdint.h>
5+
#include <stdbool.h>
46
#include <sys/types.h>
57
#include <sys/stat.h>
68
#include <string.h>
@@ -25,6 +27,7 @@
2527
static unsigned int offset;
2628
static unsigned int ino = 721;
2729
static time_t default_mtime;
30+
static bool do_csum = false;
2831

2932
struct file_handler {
3033
const char *type;
@@ -78,7 +81,7 @@ static void cpio_trailer(void)
7881

7982
sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
8083
"%08X%08X%08X%08X%08X%08X%08X",
81-
"070701", /* magic */
84+
do_csum ? "070702" : "070701", /* magic */
8285
0, /* ino */
8386
0, /* mode */
8487
(long) 0, /* uid */
@@ -110,7 +113,7 @@ static int cpio_mkslink(const char *name, const char *target,
110113
name++;
111114
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
112115
"%08X%08X%08X%08X%08X%08X%08X",
113-
"070701", /* magic */
116+
do_csum ? "070702" : "070701", /* magic */
114117
ino++, /* ino */
115118
S_IFLNK | mode, /* mode */
116119
(long) uid, /* uid */
@@ -159,7 +162,7 @@ static int cpio_mkgeneric(const char *name, unsigned int mode,
159162
name++;
160163
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
161164
"%08X%08X%08X%08X%08X%08X%08X",
162-
"070701", /* magic */
165+
do_csum ? "070702" : "070701", /* magic */
163166
ino++, /* ino */
164167
mode, /* mode */
165168
(long) uid, /* uid */
@@ -253,7 +256,7 @@ static int cpio_mknod(const char *name, unsigned int mode,
253256
name++;
254257
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
255258
"%08X%08X%08X%08X%08X%08X%08X",
256-
"070701", /* magic */
259+
do_csum ? "070702" : "070701", /* magic */
257260
ino++, /* ino */
258261
mode, /* mode */
259262
(long) uid, /* uid */
@@ -293,6 +296,29 @@ static int cpio_mknod_line(const char *line)
293296
return rc;
294297
}
295298

299+
static int cpio_mkfile_csum(int fd, unsigned long size, uint32_t *csum)
300+
{
301+
while (size) {
302+
unsigned char filebuf[65536];
303+
ssize_t this_read;
304+
size_t i, this_size = MIN(size, sizeof(filebuf));
305+
306+
this_read = read(fd, filebuf, this_size);
307+
if (this_read <= 0 || this_read > this_size)
308+
return -1;
309+
310+
for (i = 0; i < this_read; i++)
311+
*csum += filebuf[i];
312+
313+
size -= this_read;
314+
}
315+
/* seek back to the start for data segment I/O */
316+
if (lseek(fd, 0, SEEK_SET) < 0)
317+
return -1;
318+
319+
return 0;
320+
}
321+
296322
static int cpio_mkfile(const char *name, const char *location,
297323
unsigned int mode, uid_t uid, gid_t gid,
298324
unsigned int nlinks)
@@ -305,6 +331,7 @@ static int cpio_mkfile(const char *name, const char *location,
305331
int rc = -1;
306332
int namesize;
307333
unsigned int i;
334+
uint32_t csum = 0;
308335

309336
mode |= S_IFREG;
310337

@@ -332,6 +359,11 @@ static int cpio_mkfile(const char *name, const char *location,
332359
goto error;
333360
}
334361

362+
if (do_csum && cpio_mkfile_csum(file, buf.st_size, &csum) < 0) {
363+
fprintf(stderr, "Failed to checksum file %s\n", location);
364+
goto error;
365+
}
366+
335367
size = 0;
336368
for (i = 1; i <= nlinks; i++) {
337369
/* data goes on last link */
@@ -343,7 +375,7 @@ static int cpio_mkfile(const char *name, const char *location,
343375
namesize = strlen(name) + 1;
344376
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
345377
"%08lX%08X%08X%08X%08X%08X%08X",
346-
"070701", /* magic */
378+
do_csum ? "070702" : "070701", /* magic */
347379
ino, /* ino */
348380
mode, /* mode */
349381
(long) uid, /* uid */
@@ -356,7 +388,7 @@ static int cpio_mkfile(const char *name, const char *location,
356388
0, /* rmajor */
357389
0, /* rminor */
358390
namesize, /* namesize */
359-
0); /* chksum */
391+
size ? csum : 0); /* chksum */
360392
push_hdr(s);
361393
push_string(name);
362394
push_pad();
@@ -464,7 +496,7 @@ static int cpio_mkfile_line(const char *line)
464496
static void usage(const char *prog)
465497
{
466498
fprintf(stderr, "Usage:\n"
467-
"\t%s [-t <timestamp>] <cpio_list>\n"
499+
"\t%s [-t <timestamp>] [-c] <cpio_list>\n"
468500
"\n"
469501
"<cpio_list> is a file containing newline separated entries that\n"
470502
"describe the files to be included in the initramfs archive:\n"
@@ -499,7 +531,8 @@ static void usage(const char *prog)
499531
"\n"
500532
"<timestamp> is time in seconds since Epoch that will be used\n"
501533
"as mtime for symlinks, special files and directories. The default\n"
502-
"is to use the current time for these entries.\n",
534+
"is to use the current time for these entries.\n"
535+
"-c: calculate and store 32-bit checksums for file data.\n",
503536
prog);
504537
}
505538

@@ -541,7 +574,7 @@ int main (int argc, char *argv[])
541574

542575
default_mtime = time(NULL);
543576
while (1) {
544-
int opt = getopt(argc, argv, "t:h");
577+
int opt = getopt(argc, argv, "t:ch");
545578
char *invalid;
546579

547580
if (opt == -1)
@@ -556,6 +589,9 @@ int main (int argc, char *argv[])
556589
exit(1);
557590
}
558591
break;
592+
case 'c':
593+
do_csum = true;
594+
break;
559595
case 'h':
560596
case '?':
561597
usage(argv[0]);

0 commit comments

Comments
 (0)