/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/ #include #include #include #include #include #include #include #include #include void usage() { fprintf(stderr, "usage: IHFSsplit \n"); exit(1); } typedef struct { uint32_t signature; uint32_t fslen; uint32_t unknown1; uint32_t unknown2; char timestamp[12]; uint32_t numfiles; char zeros[476]; uint32_t marker; } ihfs_header_t; #define MAX_FILES 2048 #define MAX_IHFS_PATH 56 typedef struct { struct { char fullpath[MAX_IHFS_PATH]; uint32_t sector; uint32_t length; } files[MAX_FILES]; } ihfs_file_table_t; #define SECTOR_SIZE 512 int ihfs_sanity(const int ihfs_img) { struct stat statbuf; ihfs_header_t ihfs_hdr; printf("starting sanity check for IHFS image...\n"); lseek(ihfs_img, 0, SEEK_SET); read(ihfs_img, &ihfs_hdr, sizeof (ihfs_hdr)); printf(" checking for IHFS signature...\n"); if (ihfs_hdr.signature != 0x49484653) return 1; printf(" checking for FS length...\n"); fstat(ihfs_img, &statbuf); if (ihfs_hdr.fslen * SECTOR_SIZE != statbuf.st_size) return 1; printf(" checking for unknown value 1...\n"); if (ihfs_hdr.unknown1 != 0x00000004) return 1; printf(" checking for unknown value 2...\n"); if (ihfs_hdr.unknown2 != 0xfffff000) return 1; printf(" checking for number of files...\n"); if (ihfs_hdr.numfiles > MAX_FILES) return 1; printf(" checking for marker...\n"); if (ihfs_hdr.marker != 0x55aa55aa) return 1; return 0; } void mkdir_p(const char *path) { char *dir; dir = dirname(strdup(path)); if (strchr(dir, '/')) mkdir_p(dir); #ifdef _WIN32 mkdir(dir); #else mkdir(dir, 0755); #endif } #define BUF_SIZE 4096 void outputfile(const char *outpath, const int ihfs_img, const int offset, const int length) { int outfd; int i, rem; char buf[BUF_SIZE]; lseek(ihfs_img, offset, SEEK_SET); outfd = creat(outpath, 0644); for (i = 0; i < length / BUF_SIZE; ++i) { read(ihfs_img, buf, BUF_SIZE); write(outfd, buf, BUF_SIZE); } rem = length - i * BUF_SIZE; if (rem > 0) { read(ihfs_img, buf, rem); write(outfd, buf, rem); } close(outfd); } int main(int argc, char **argv) { struct stat statbuf; int ihfs_img; ihfs_header_t ihfs_hdr; ihfs_file_table_t ihfs_ftbl; int i, j; char *outpath, *base_path, ihfs_path[MAX_IHFS_PATH+1]; /* check the arguments */ if (argc != 3) usage(); stat(argv[1], &statbuf); if (!S_ISREG(statbuf.st_mode)) usage(); stat(argv[2], &statbuf); if (!S_ISDIR(statbuf.st_mode)) usage(); /* check the file, then split */ ihfs_img = open(argv[1], O_RDONLY); if (ihfs_sanity(ihfs_img)) { printf("Non-IHFS format!\n"); return 1; } else printf("sanity check OK\n"); lseek(ihfs_img, 0, SEEK_SET); read(ihfs_img, &ihfs_hdr, sizeof (ihfs_hdr)); lseek(ihfs_img, 4 * SECTOR_SIZE, SEEK_SET); read(ihfs_img, &ihfs_ftbl, sizeof (ihfs_ftbl)); base_path = strdup(argv[2]); outpath = malloc(strlen(base_path) + 1 + MAX_IHFS_PATH + 1); for (i = 0; i < ihfs_hdr.numfiles; ++i) { printf("\n"); printf("pathname: %s\n", ihfs_ftbl.files[i].fullpath); printf("starts at sector %d, length is %d bytes\n", ihfs_ftbl.files[i].sector, ihfs_ftbl.files[i].length); strncpy(ihfs_path, ihfs_ftbl.files[i].fullpath, MAX_IHFS_PATH); ihfs_path[MAX_IHFS_PATH] = '\0'; for (j = 0; j < strlen(ihfs_path); ++j) if (ihfs_path[j] == '\\') ihfs_path[j] = '/'; sprintf(outpath, "%s/%s", base_path, ihfs_path); mkdir_p(outpath); outputfile(outpath, ihfs_img, ihfs_ftbl.files[i].sector * SECTOR_SIZE, ihfs_ftbl.files[i].length); } free(outpath); close(ihfs_img); return 0; }