summaryrefslogtreecommitdiffstats
path: root/gen_init_cpio.c
diff options
context:
space:
mode:
authorturret <turret@duck.com>2026-01-05 02:51:25 -0600
committerturret <turret@duck.com>2026-01-05 02:51:25 -0600
commitec80dadf67e9f26fcdd68ebc67472c6c42977ccd (patch)
tree64ae3266b8e07c194b06ef5182fa60f5b3c7cdc3 /gen_init_cpio.c
parent397f95a3c09d2aa66a51aad1952975c924e6be0b (diff)
downloadgengine-sdk-ec80dadf67e9f26fcdd68ebc67472c6c42977ccd.tar.gz
gengine-sdk-ec80dadf67e9f26fcdd68ebc67472c6c42977ccd.tar.bz2
gengine-sdk-ec80dadf67e9f26fcdd68ebc67472c6c42977ccd.zip
gen_init_cpio: generate PWB-type cpio imagesHEADmaster
NOTE: I have been unable to make it generate cpio images that are inline with the actual cpio utility. Your mileage may vary when not using this with your own tools.
Diffstat (limited to 'gen_init_cpio.c')
-rw-r--r--gen_init_cpio.c270
1 files changed, 106 insertions, 164 deletions
diff --git a/gen_init_cpio.c b/gen_init_cpio.c
index 694b88c..ea8eb0a 100644
--- a/gen_init_cpio.c
+++ b/gen_init_cpio.c
@@ -18,6 +18,7 @@
#include <errno.h>
#include <ctype.h>
#include <limits.h>
+#include <endian.h>
/*
* Original work by Jeff Garzik
@@ -29,9 +30,7 @@
#define xstr(s) #s
#define str(s) xstr(s)
#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define CPIO_HDR_LEN 110
#define CPIO_TRAILER "TRAILER!!!"
-#define padlen(_off, _align) (((_align) - ((_off) & ((_align) - 1))) % (_align))
/* zero-padding the filename field for data alignment is limited by PATH_MAX */
static char padding[PATH_MAX];
@@ -39,36 +38,39 @@ static unsigned int offset;
static unsigned int ino = 721;
static time_t default_mtime;
static bool do_file_mtime;
-static bool do_csum = false;
static int outfd = STDOUT_FILENO;
static unsigned int dalign;
+#pragma pack(1)
+struct header_pwb_cpio {
+ uint16_t h_magic;
+ uint16_t h_dev;
+ uint16_t h_ino;
+ uint16_t h_mode;
+ uint16_t h_uid;
+ uint16_t h_gid;
+ uint16_t h_nlink;
+ uint16_t h_majmin;
+ uint32_t h_mtime;
+ uint16_t h_namesize;
+ uint32_t h_filesize;
+};
+#define CPIO_HDR_LEN sizeof(struct header_pwb_cpio)
+
struct file_handler {
const char *type;
int (*handler)(const char *line);
};
-static int push_buf(const char *name, size_t name_len)
-{
- ssize_t len;
-
- len = write(outfd, name, name_len);
- if (len != name_len)
- return -1;
-
- offset += name_len;
- return 0;
-}
-
-static int push_pad(size_t padlen)
+static int push_pad()
{
ssize_t len = 0;
+ size_t padlen = offset % 2;
if (!padlen)
return 0;
- if (padlen < sizeof(padding))
- len = write(outfd, padding, padlen);
+ len = write(outfd, padding, padlen);
if (len != padlen)
return -1;
@@ -76,7 +78,7 @@ static int push_pad(size_t padlen)
return 0;
}
-static int push_rest(const char *name, size_t name_len)
+static int push_buf(const char *name, size_t name_len)
{
ssize_t len;
@@ -85,36 +87,32 @@ static int push_rest(const char *name, size_t name_len)
return -1;
offset += name_len;
-
- return push_pad(padlen(name_len + CPIO_HDR_LEN, 4));
+ return push_pad();
}
static int cpio_trailer(void)
{
- int len;
+ int len;
unsigned int namesize = sizeof(CPIO_TRAILER);
- len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
- "%08X%08X%08X%08X%08X%08X%08X",
- do_csum ? "070702" : "070701", /* magic */
- 0, /* ino */
- 0, /* mode */
- (long) 0, /* uid */
- (long) 0, /* gid */
- 1, /* nlink */
- (long) 0, /* mtime */
- 0, /* filesize */
- 0, /* major */
- 0, /* minor */
- 0, /* rmajor */
- 0, /* rminor */
- namesize, /* namesize */
- 0); /* chksum */
+ struct header_pwb_cpio header = {
+ .h_magic = 070707,
+ .h_dev = 0,
+ .h_ino = 0,
+ .h_mode = 0,
+ .h_uid = 0,
+ .h_gid = 0,
+ .h_nlink = 1,
+ .h_majmin = 0,
+ .h_mtime = 0,
+ .h_namesize = namesize,
+ .h_filesize = 0
+ };
+ len = write(outfd, &header, CPIO_HDR_LEN);
offset += len;
if (len != CPIO_HDR_LEN ||
- push_rest(CPIO_TRAILER, namesize) < 0 ||
- push_pad(padlen(offset, 512)) < 0)
+ push_buf(CPIO_TRAILER, namesize) < 0)
return -1;
if (fsync(outfd) < 0 && errno != EINVAL)
@@ -127,35 +125,31 @@ static int cpio_mkslink(const char *name, const char *target,
unsigned int mode, uid_t uid, gid_t gid)
{
int len;
- unsigned int namesize, targetsize = strlen(target) + 1;
+ unsigned int namesize, targetsize = strlen(target);
if (name[0] == '/')
name++;
- namesize = strlen(name) + 1;
-
- len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
- "%08X%08X%08X%08X%08X%08X%08X",
- do_csum ? "070702" : "070701", /* magic */
- ino++, /* ino */
- S_IFLNK | mode, /* mode */
- (long) uid, /* uid */
- (long) gid, /* gid */
- 1, /* nlink */
- (long) default_mtime, /* mtime */
- targetsize, /* filesize */
- 3, /* major */
- 1, /* minor */
- 0, /* rmajor */
- 0, /* rminor */
- namesize, /* namesize */
- 0); /* chksum */
+ namesize = strlen(name);
+
+ struct header_pwb_cpio header = {
+ .h_magic = 070707,
+ .h_dev = 0,
+ .h_ino = ino++,
+ .h_mode = S_IFLNK | mode,
+ .h_uid = uid,
+ .h_gid = gid,
+ .h_nlink = 1,
+ .h_majmin = 0,
+ .h_mtime = default_mtime,
+ .h_namesize = namesize,
+ .h_filesize = htobe32(targetsize)
+ };
+ len = write(outfd, &header, CPIO_HDR_LEN);
offset += len;
if (len != CPIO_HDR_LEN ||
push_buf(name, namesize) < 0 ||
- push_pad(padlen(offset, 4)) < 0 ||
- push_buf(target, targetsize) < 0 ||
- push_pad(padlen(offset, 4)) < 0)
+ push_buf(target, targetsize) < 0)
return -1;
return 0;
@@ -190,26 +184,24 @@ static int cpio_mkgeneric(const char *name, unsigned int mode,
name++;
namesize = strlen(name) + 1;
- len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
- "%08X%08X%08X%08X%08X%08X%08X",
- do_csum ? "070702" : "070701", /* magic */
- ino++, /* ino */
- mode, /* mode */
- (long) uid, /* uid */
- (long) gid, /* gid */
- 2, /* nlink */
- (long) default_mtime, /* mtime */
- 0, /* filesize */
- 3, /* major */
- 1, /* minor */
- 0, /* rmajor */
- 0, /* rminor */
- namesize, /* namesize */
- 0); /* chksum */
+ struct header_pwb_cpio header = {
+ .h_magic = 070707,
+ .h_dev = 0,
+ .h_ino = ino++,
+ .h_mode = mode,
+ .h_uid = uid,
+ .h_gid = gid,
+ .h_nlink = 2,
+ .h_majmin = 0,
+ .h_mtime = default_mtime,
+ .h_namesize = namesize,
+ .h_filesize = 0
+ };
+ len = write(outfd, &header, CPIO_HDR_LEN);
offset += len;
if (len != CPIO_HDR_LEN ||
- push_rest(name, namesize) < 0)
+ push_buf(name, namesize) < 0)
return -1;
return 0;
@@ -291,26 +283,24 @@ static int cpio_mknod(const char *name, unsigned int mode,
name++;
namesize = strlen(name) + 1;
- len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
- "%08X%08X%08X%08X%08X%08X%08X",
- do_csum ? "070702" : "070701", /* magic */
- ino++, /* ino */
- mode, /* mode */
- (long) uid, /* uid */
- (long) gid, /* gid */
- 1, /* nlink */
- (long) default_mtime, /* mtime */
- 0, /* filesize */
- 3, /* major */
- 1, /* minor */
- maj, /* rmajor */
- min, /* rminor */
- namesize, /* namesize */
- 0); /* chksum */
+ struct header_pwb_cpio header = {
+ .h_magic = 070707,
+ .h_dev = 0,
+ .h_ino = ino++,
+ .h_mode = mode,
+ .h_uid = uid,
+ .h_gid = gid,
+ .h_nlink = 1,
+ .h_majmin = (maj << 8) | min,
+ .h_mtime = default_mtime,
+ .h_namesize = namesize,
+ .h_filesize = 0
+ };
+ len = write(outfd, &header, CPIO_HDR_LEN);
offset += len;
if (len != CPIO_HDR_LEN ||
- push_rest(name, namesize) < 0)
+ push_buf(name, namesize) < 0)
return -1;
return 0;
@@ -337,29 +327,6 @@ 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)
@@ -369,9 +336,8 @@ static int cpio_mkfile(const char *name, const char *location,
int file, retval, len;
int rc = -1;
time_t mtime;
- int namesize, namepadlen;
+ int namesize;
unsigned int i;
- uint32_t csum = 0;
ssize_t this_read;
mode |= S_IFREG;
@@ -411,13 +377,7 @@ 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;
- namepadlen = 0;
for (i = 1; i <= nlinks; i++) {
if (name[0] == '/')
name++;
@@ -427,38 +387,24 @@ static int cpio_mkfile(const char *name, const char *location,
if (i == nlinks)
size = buf.st_size;
- if (dalign && size > dalign) {
- namepadlen = padlen(offset + CPIO_HDR_LEN + namesize,
- dalign);
- if (namesize + namepadlen > PATH_MAX) {
- fprintf(stderr,
- "%s: best-effort alignment %u missed\n",
- name, dalign);
- namepadlen = 0;
- }
- }
-
- len = dprintf(outfd, "%s%08X%08X%08lX%08lX%08X%08lX"
- "%08lX%08X%08X%08X%08X%08X%08X",
- do_csum ? "070702" : "070701", /* magic */
- ino, /* ino */
- mode, /* mode */
- (long) uid, /* uid */
- (long) gid, /* gid */
- nlinks, /* nlink */
- (long) mtime, /* mtime */
- size, /* filesize */
- 3, /* major */
- 1, /* minor */
- 0, /* rmajor */
- 0, /* rminor */
- namesize + namepadlen, /* namesize */
- size ? csum : 0); /* chksum */
+ struct header_pwb_cpio header = {
+ .h_magic = 070707,
+ .h_dev = buf.st_dev,
+ .h_ino = buf.st_ino,
+ .h_mode = mode,
+ .h_uid = uid,
+ .h_gid = gid,
+ .h_nlink = 1,
+ .h_majmin = 0,
+ .h_mtime = htobe32(mtime),
+ .h_namesize = namesize,
+ .h_filesize = htobe32(size)
+ };
+ len = write(outfd, &header, CPIO_HDR_LEN);
offset += len;
if (len != CPIO_HDR_LEN ||
- push_buf(name, namesize) < 0 ||
- push_pad(namepadlen ? namepadlen : padlen(offset, 4)) < 0)
+ push_buf(name, namesize) < 0)
goto error;
if (size) {
@@ -489,7 +435,7 @@ static int cpio_mkfile(const char *name, const char *location,
offset += this_read;
size -= this_read;
}
- if (push_pad(padlen(offset, 4)) < 0)
+ if (push_pad() < 0)
goto error;
name += namesize;
@@ -575,7 +521,7 @@ static int cpio_mkfile_line(const char *line)
static void usage(const char *prog)
{
fprintf(stderr, "Usage:\n"
- "\t%s [-t <timestamp>] [-c] [-o <output_file>] [-a <data_align>] <cpio_list>\n"
+ "\t%s [-t <timestamp>] [-o <output_file>] [-a <data_align>] <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"
@@ -612,7 +558,6 @@ static void usage(const char *prog)
"as mtime for symlinks, directories, regular and special files.\n"
"The default is to use the current time for all files, but\n"
"preserve modification time for regular files.\n"
- "-c: calculate and store 32-bit checksums for file data.\n"
"<output_file>: write cpio to this file instead of stdout\n"
"<data_align>: attempt to align file data by zero-padding the\n"
"filename field up to data_align. Must be a multiple of 4.\n"
@@ -656,7 +601,7 @@ int main (int argc, char *argv[])
int line_nr = 0;
const char *filename;
- default_mtime = time(NULL);
+ default_mtime = htobe32(time(NULL));
while (1) {
int opt = getopt(argc, argv, "t:cho:a:");
char *invalid;
@@ -665,7 +610,7 @@ int main (int argc, char *argv[])
break;
switch (opt) {
case 't':
- default_mtime = strtol(optarg, &invalid, 10);
+ default_mtime = htobe32(strtol(optarg, &invalid, 10));
if (!*optarg || *invalid) {
fprintf(stderr, "Invalid timestamp: %s\n",
optarg);
@@ -674,9 +619,6 @@ int main (int argc, char *argv[])
}
do_file_mtime = true;
break;
- case 'c':
- do_csum = true;
- break;
case 'o':
outfd = open(optarg,
O_WRONLY | O_CREAT | O_LARGEFILE | O_TRUNC,