changeset 26:d19b4e20ff9f

MysteryFFS: extract utility seems to work
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sat, 18 May 2013 23:43:46 +0000
parents ae5337f881e3
children 343b6b2f178b
files mysteryffs/extract.c
diffstat 1 files changed, 87 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/mysteryffs/extract.c	Sat May 18 23:08:13 2013 +0000
+++ b/mysteryffs/extract.c	Sat May 18 23:43:46 2013 +0000
@@ -195,12 +195,84 @@
 	return(1);
 }
 
+u8 *
+find_end_of_chunk(ch)
+	struct objinfo *ch;
+{
+	u8 *p;
+	int i;
+
+	p = ch->dataptr + ch->len;
+	for (i = 1; i <= 16; i++) {
+		if (!p[-i])
+			return(p - i);
+		if (p[-1] != 0xFF)
+			break;
+	}
+	fprintf(stderr,
+	"chunk starting at %x (index entry %x): no valid termination found\n",
+		ch->offset, ch->entryno);
+	exit(1);
+}
+
+void
+dump_head_chunk(fd, ch)
+	struct objinfo *ch;
+{
+	u8 *endname, *endchunk;
+
+	endname = (u8 *) index((char *)ch->dataptr, '\0') + 1;
+	endchunk = find_end_of_chunk(ch);
+	if (endchunk <= endname)
+		return;
+	write(fd, endname, endchunk - endname);
+}
+
+void
+dump_extra_chunk(fd, ch)
+	struct objinfo *ch;
+{
+	u8 *endchunk;
+
+	endchunk = find_end_of_chunk(ch);
+	write(fd, ch->dataptr, endchunk - ch->dataptr);
+}
+
+extract_file(head)
+	struct objinfo *head;
+{
+	int fd;
+	int ent;
+	struct objinfo ch;
+
+	fd = open(workpath + 1, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+	if (fd < 0) {
+		perror(workpath + 1);
+		exit(1);
+	}
+	dump_head_chunk(fd, head);
+	for (ent = head->descend; ent != 0xFFFF; ent = ch.descend) {
+		ch.entryno = ent;
+		get_index_entry(&ch);
+		if (ch.type != 0xF4) {
+			fprintf(stderr,
+	"file continuation object at index %x: type %02X != expected F4\n",
+				ent, ch.type);
+			exit(1);
+		}
+		validate_chunk(&ch);
+		dump_extra_chunk(fd, &ch);
+		if (ch.sibling != 0xFFFF)
+			printf("warning: file continuation object (index %x) has a non-nil sibling pointer\n",
+				ent);
+	}
+	close(fd);
+}
+
 dump_dir(firstent, path_prefix)
 {
 	int ent;
 	struct objinfo obj;
-	int typechar;
-	u32 length;
 
 	for (ent = firstent; ent != 0xFFFF; ent = obj.sibling) {
 		obj.entryno = ent;
@@ -220,13 +292,24 @@
 		case 0xF2:
 			/* directory */
 			printf("dir: %s\n", workpath);
-			/* mkdir will go here */
+			if (!name_safe_for_extract(&obj)) {
+				printf("name contains unsafe characters; subtree skipped\n");
+				continue;
+			}
+			if (mkdir(workpath + 1, 0777) < 0) {
+				perror(workpath + 1);
+				exit(1);
+			}
 			dump_dir(obj.descend, strlen(workpath));
 			continue;
 		case 0xF1:
 			/* regular file */
 			printf("file: %s\n", workpath);
-			/* file extraction will go here */
+			if (!name_safe_for_extract(&obj)) {
+				printf("name contains unsafe characters; file skipped\n");
+				continue;
+			}
+			extract_file(&obj);
 			continue;
 		case 0xE1:
 			/* special .journal file */