shithub: riscv

Download patch

ref: bf398d28c3745d2b15ceca96c1502ac2d965f402
parent: 15f66c69d857a4bd6c26be19c6872542e5b2d16e
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 10 18:07:26 EST 2024

cpiofs: add newc support for cpiofs (thanks rminnich)

Linux initrds, uroot file systems, and
others generate newc cpio images; add
support for them.

--- a/sys/src/cmd/tapefs/cpiofs.c
+++ b/sys/src/cmd/tapefs/cpiofs.c
@@ -114,12 +114,37 @@
 
 	for(x = 0; n > 0; n--) {
 		if((y = egetc() - '0') & ~7)
-			sysfatal("not octal");
+			sysfatal("rdasc:%#c not octal", y);
 		x = x<<3 | y;
 	}
 	return x;
 }
 
+static vlong
+rdascx(int n)
+{
+	vlong x;
+	int y;
+
+	for(x = 0; n > 0; n--) {
+		y = egetc();
+		if ((y >= '0') && (y <= '9')){
+			x = x << 4 | (y - '0');
+			continue;
+		}
+		if ((y >= 'a') && (y <= 'f')){
+			x = x << 4 | 10 + (y - 'a');
+			continue;
+		}
+		if ((y >= 'A') && (y <= 'F')){
+			x = x << 4 | 10 + (y - 'A');
+			continue;
+		}
+		sysfatal("rdascx:%#x:not hex", y);
+	}
+	return x;
+}
+
 /* sysvr3 and sysvr4 skip records with names longer than 256. sysiii,
 sysvr1, and sysvr2 overrun their 256 byte buffer */
 static void
@@ -157,10 +182,70 @@
 	f->name = buf;
 }
 
+/*
+struct cpio_newc_header {
+                   char    c_magic[6];
+                   char    c_ino[8];
+                   char    c_mode[8];
+                   char    c_uid[8];
+                   char    c_gid[8];
+                   char    c_nlink[8];
+                   char    c_mtime[8];
+                   char    c_filesize[8];
+                   char    c_devmajor[8];
+                   char    c_devminor[8];
+                   char    c_rdevmajor[8];
+                   char    c_rdevminor[8];
+                   char    c_namesize[8];
+                   char    c_check[8];
+           };
+*/
+static void
+rdnewc(Fileinf *f)
+{
+	int namesz, n;
+	static char buf[256];
+
+	rdascx(8);	/* ino */
+	f->mode = rdascx(8);
+	f->uid = rdascx(8);
+	f->gid = rdascx(8);
+	rdascx(8);	/* nlink */
+	f->mdate = rdascx(8);
+	f->size = rdascx(8);
+	rdascx(8); //devmajor
+	rdascx(8); //devminor
+	rdascx(8); //rdevmajor
+	rdascx(8); //rdevminor
+	namesz = rdascx(8);
+	rdascx(8); // checksum
+
+	/* namesz includes the trailing nul */
+	if(namesz == 0)
+		sysfatal("name too small");
+	if(namesz > sizeof (buf))
+		sysfatal("name too big");
+	if((n = Bread(tape, buf, namesz)) < 0)
+		sysfatal("read error: %r");
+	if(n < namesz)
+		sysfatal("unexpected eof");
+
+	if(buf[n-1] != '\0')
+		sysfatal("no nul after file name");
+	if((n = strlen(buf)) != namesz-1)
+		sysfatal("mismatched name length: saw %d; expected %d", n, namesz-1);
+	f->name = buf;
+	if((Bseek(tape, 0, 1) & 3)) {
+		int skip = 4-(Bseek(tape, 0, 1) & 3);
+		for(int i = 0; i < skip; i++)
+			egetc();
+	}
+}
+
 static HdrReader *
 rdmagic(void)
 {
-	uchar buf[6];
+	uchar buf[8];
 
 	buf[0] = egetc();
 	buf[1] = egetc();
@@ -171,10 +256,17 @@
 	buf[3] = egetc();
 	buf[4] = egetc();
 	buf[5] = egetc();
+	buf[6] = 0;
 	if(memcmp(buf, "070707", 6) == 0)
 		return rdsysiii;
 
-	sysfatal("Out of phase--get MERT help");
+	if(memcmp(buf, "070701", 6) == 0)
+		return rdnewc;
+
+	for(int i = 0; i < 6; i++)
+		print("%#x,", buf[i]);
+
+	sysfatal("Out of phase(%s)--get MERT help", buf);
 }
 
 void
@@ -187,7 +279,6 @@
 	record headers */
 	if((tape = Bopen(name, OREAD)) == nil)
 		sysfatal("Can't open argument file");
-
 	extern void (*_sysfatal)(char *, va_list);
 	_sysfatal = addrfatal;
 
@@ -224,10 +315,16 @@
 		poppath(f, 1);
 
 		Bseek(tape, f.size, 1);
-
 		/* skip padding */
-		if(rdhdr == rdpwb11 && (Bseek(tape, 0, 1) & 1))
+		if(((rdhdr == rdpwb11)||(rdhdr == rdnewc)) && (Bseek(tape, 0, 1) & 1))
 			egetc();
+
+		/* sleazy alignment hack. Who needs a for loop? */
+		if(rdhdr == rdnewc && (Bseek(tape, 0, 1) & 2)) {
+				egetc();
+				egetc();
+		}
+
 	}
 }
 
--