FreeCalypso > hg > freecalypso-reveng
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); +}