FreeCalypso > hg > freecalypso-reveng
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 */