# HG changeset patch # User Michael Spacefalcon # Date 1368920626 0 # Node ID d19b4e20ff9f4916795b73e0e895569b76835cfa # Parent ae5337f881e311e85084d07935e962831507811f MysteryFFS: extract utility seems to work diff -r ae5337f881e3 -r d19b4e20ff9f mysteryffs/extract.c --- 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 */