diff mpffs/xtr.c @ 36:390be89892c4

mpffs-xtr ported over
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 30 Jun 2013 17:24:21 +0000
parents
children 7ceab8bfacb3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mpffs/xtr.c	Sun Jun 30 17:24:21 2013 +0000
@@ -0,0 +1,174 @@
+/*
+ * This module contains the main function and other code specific to mpffs-xtr
+ */
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "types.h"
+#include "struct.h"
+
+extern char *imgfile;
+extern struct objinfo root;
+extern int verbose;
+
+extern u8 *find_end_of_chunk();
+
+char workpath[512];
+
+name_safe_for_extract(oi)
+	struct objinfo *oi;
+{
+	char *s;
+
+	s = (char *)oi->dataptr;
+	if (!isalnum(*s) && *s != '_')
+		return(0);
+	for (s++; *s; s++)
+		if (!isalnum(*s) && *s != '_' && *s != '.')
+			return(0);
+	return(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;
+
+	for (ent = firstent; ent != 0xFFFF; ent = obj.sibling) {
+		obj.entryno = ent;
+		get_index_entry(&obj);
+		if (!obj.type) /* skip deleted objects w/o further validation */
+			continue;
+		validate_chunk(&obj);
+		validate_obj_name(&obj);
+		if (path_prefix + strlen(obj.dataptr) + 2 > sizeof workpath) {
+			fprintf(stderr,
+	"handling object at index %x, name \"%s\": path buffer overflow\n",
+				obj.entryno, (char *)obj.dataptr);
+			exit(1);
+		}
+		sprintf(workpath + path_prefix, "/%s", (char *)obj.dataptr);
+		switch (obj.type) {
+		case 0xF2:
+			/* directory */
+			if (verbose)
+				printf("dir: %s\n", workpath);
+			if (!name_safe_for_extract(&obj)) {
+				fprintf(stderr,
+"warning: directory 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 */
+			if (verbose)
+				printf("file: %s\n", workpath);
+			if (!name_safe_for_extract(&obj)) {
+				fprintf(stderr,
+	"warning: file name contains unsafe characters; file skipped\n");
+				continue;
+			}
+			extract_file(&obj);
+			continue;
+		case 0xE1:
+			/* special .journal file */
+			if (verbose)
+				printf("skipping E1 file: %s\n", workpath);
+			continue;
+		default:
+			fprintf(stderr,
+	"warning: %s (index entry #%x): unexpected type %02X; skipping\n",
+				workpath, obj.entryno, obj.type);
+			continue;
+		}
+	}
+}
+
+usage()
+{
+	fprintf(stderr, "usage: mpffs-xtr [options] ffs-image destdir\n");
+	exit(1);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	extern int optind;
+
+	parse_cmdline_options(argc, argv);
+	if (argc - optind != 2)
+		usage();
+	imgfile = argv[optind];
+	preliminaries();
+	if (chdir(argv[optind+1]) < 0) {
+		perror(argv[optind+1]);
+		exit(1);
+	}
+	dump_dir(root.descend, 0);
+	exit(0);
+}