Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
gen_init_cpio: support file checksum archiving
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
ddiss authored and akpm00 committed May 10, 2022
1 parent 3a2699c commit ea80487
Showing 1 changed file with 45 additions and 9 deletions.
54 changes: 45 additions & 9 deletions usr/gen_init_cpio.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
Expand All @@ -25,6 +27,7 @@
static unsigned int offset;
static unsigned int ino = 721;
static time_t default_mtime;
static bool do_csum = false;

struct file_handler {
const char *type;
Expand Down Expand Up @@ -78,7 +81,7 @@ static void cpio_trailer(void)

sprintf(s, "%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
do_csum ? "070702" : "070701", /* magic */
0, /* ino */
0, /* mode */
(long) 0, /* uid */
Expand Down Expand Up @@ -110,7 +113,7 @@ static int cpio_mkslink(const char *name, const char *target,
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
do_csum ? "070702" : "070701", /* magic */
ino++, /* ino */
S_IFLNK | mode, /* mode */
(long) uid, /* uid */
Expand Down Expand Up @@ -159,7 +162,7 @@ static int cpio_mkgeneric(const char *name, unsigned int mode,
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
do_csum ? "070702" : "070701", /* magic */
ino++, /* ino */
mode, /* mode */
(long) uid, /* uid */
Expand Down Expand Up @@ -253,7 +256,7 @@ static int cpio_mknod(const char *name, unsigned int mode,
name++;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08X%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
do_csum ? "070702" : "070701", /* magic */
ino++, /* ino */
mode, /* mode */
(long) uid, /* uid */
Expand Down Expand Up @@ -293,6 +296,29 @@ static int cpio_mknod_line(const char *line)
return rc;
}

static int cpio_mkfile_csum(int fd, unsigned long size, uint32_t *csum)
{
while (size) {
unsigned char filebuf[65536];
ssize_t this_read;
size_t i, this_size = MIN(size, sizeof(filebuf));

this_read = read(fd, filebuf, this_size);
if (this_read <= 0 || this_read > this_size)
return -1;

for (i = 0; i < this_read; i++)
*csum += filebuf[i];

size -= this_read;
}
/* seek back to the start for data segment I/O */
if (lseek(fd, 0, SEEK_SET) < 0)
return -1;

return 0;
}

static int cpio_mkfile(const char *name, const char *location,
unsigned int mode, uid_t uid, gid_t gid,
unsigned int nlinks)
Expand All @@ -305,6 +331,7 @@ static int cpio_mkfile(const char *name, const char *location,
int rc = -1;
int namesize;
unsigned int i;
uint32_t csum = 0;

mode |= S_IFREG;

Expand Down Expand Up @@ -332,6 +359,11 @@ static int cpio_mkfile(const char *name, const char *location,
goto error;
}

if (do_csum && cpio_mkfile_csum(file, buf.st_size, &csum) < 0) {
fprintf(stderr, "Failed to checksum file %s\n", location);
goto error;
}

size = 0;
for (i = 1; i <= nlinks; i++) {
/* data goes on last link */
Expand All @@ -343,7 +375,7 @@ static int cpio_mkfile(const char *name, const char *location,
namesize = strlen(name) + 1;
sprintf(s,"%s%08X%08X%08lX%08lX%08X%08lX"
"%08lX%08X%08X%08X%08X%08X%08X",
"070701", /* magic */
do_csum ? "070702" : "070701", /* magic */
ino, /* ino */
mode, /* mode */
(long) uid, /* uid */
Expand All @@ -356,7 +388,7 @@ static int cpio_mkfile(const char *name, const char *location,
0, /* rmajor */
0, /* rminor */
namesize, /* namesize */
0); /* chksum */
size ? csum : 0); /* chksum */
push_hdr(s);
push_string(name);
push_pad();
Expand Down Expand Up @@ -464,7 +496,7 @@ static int cpio_mkfile_line(const char *line)
static void usage(const char *prog)
{
fprintf(stderr, "Usage:\n"
"\t%s [-t <timestamp>] <cpio_list>\n"
"\t%s [-t <timestamp>] [-c] <cpio_list>\n"
"\n"
"<cpio_list> is a file containing newline separated entries that\n"
"describe the files to be included in the initramfs archive:\n"
Expand Down Expand Up @@ -499,7 +531,8 @@ static void usage(const char *prog)
"\n"
"<timestamp> is time in seconds since Epoch that will be used\n"
"as mtime for symlinks, special files and directories. The default\n"
"is to use the current time for these entries.\n",
"is to use the current time for these entries.\n"
"-c: calculate and store 32-bit checksums for file data.\n",
prog);
}

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

default_mtime = time(NULL);
while (1) {
int opt = getopt(argc, argv, "t:h");
int opt = getopt(argc, argv, "t:ch");
char *invalid;

if (opt == -1)
Expand All @@ -556,6 +589,9 @@ int main (int argc, char *argv[])
exit(1);
}
break;
case 'c':
do_csum = true;
break;
case 'h':
case '?':
usage(argv[0]);
Expand Down

0 comments on commit ea80487

Please sign in to comment.