FreeCalypso > hg > freecalypso-reveng
view mpffs/xtr.c @ 180:25b54c5ad6c2
calextract tool written, works
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sat, 12 Jul 2014 00:05:22 +0000 |
parents | 7ceab8bfacb3 |
children |
line wrap: on
line source
/* * 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(ch, opaque) struct objinfo *ch; u_long opaque; { int fd = (int) opaque; u8 *endchunk; endchunk = find_end_of_chunk(ch); write(fd, ch->dataptr, endchunk - ch->dataptr); } extract_file(head) struct objinfo *head; { int fd; fd = open(workpath + 1, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (fd < 0) { perror(workpath + 1); exit(1); } dump_head_chunk(fd, head); iterate_extra_chunks(head->descend, dump_extra_chunk, (u_long) fd); 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); }