summaryrefslogtreecommitdiff
path: root/utils/jz4740_tools/IHFSsplit.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils/jz4740_tools/IHFSsplit.c')
-rw-r--r--utils/jz4740_tools/IHFSsplit.c195
1 files changed, 195 insertions, 0 deletions
diff --git a/utils/jz4740_tools/IHFSsplit.c b/utils/jz4740_tools/IHFSsplit.c
new file mode 100644
index 0000000000..1f90a50007
--- /dev/null
+++ b/utils/jz4740_tools/IHFSsplit.c
@@ -0,0 +1,195 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by William Poetra Yoga Hadisoeseno
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include <stdio.h>
23#include <string.h>
24#include <stdlib.h>
25#include <stdint.h>
26#include <libgen.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <unistd.h>
30#include <fcntl.h>
31
32void usage()
33{
34 fprintf(stderr, "usage: IHFSsplit <ihfs_img> <output_dir>\n");
35 exit(1);
36}
37
38typedef struct {
39 uint32_t signature;
40 uint32_t fslen;
41 uint32_t unknown1;
42 uint32_t unknown2;
43 char timestamp[12];
44 uint32_t numfiles;
45 char zeros[476];
46 uint32_t marker;
47} ihfs_header_t;
48
49#define MAX_FILES 2048
50#define MAX_IHFS_PATH 56
51
52typedef struct {
53 struct {
54 char fullpath[MAX_IHFS_PATH];
55 uint32_t sector;
56 uint32_t length;
57 } files[MAX_FILES];
58} ihfs_file_table_t;
59
60#define SECTOR_SIZE 512
61
62int ihfs_sanity(const int ihfs_img)
63{
64 struct stat statbuf;
65 ihfs_header_t ihfs_hdr;
66
67 printf("starting sanity check for IHFS image...\n");
68
69 lseek(ihfs_img, 0, SEEK_SET);
70 read(ihfs_img, &ihfs_hdr, sizeof (ihfs_hdr));
71
72 printf(" checking for IHFS signature...\n");
73 if (ihfs_hdr.signature != 0x49484653)
74 return 1;
75
76 printf(" checking for FS length...\n");
77 fstat(ihfs_img, &statbuf);
78 if (ihfs_hdr.fslen * SECTOR_SIZE != statbuf.st_size)
79 return 1;
80
81 printf(" checking for unknown value 1...\n");
82 if (ihfs_hdr.unknown1 != 0x00000004)
83 return 1;
84
85 printf(" checking for unknown value 2...\n");
86 if (ihfs_hdr.unknown2 != 0xfffff000)
87 return 1;
88
89 printf(" checking for number of files...\n");
90 if (ihfs_hdr.numfiles > MAX_FILES)
91 return 1;
92
93 printf(" checking for marker...\n");
94 if (ihfs_hdr.marker != 0x55aa55aa)
95 return 1;
96
97 return 0;
98}
99
100void mkdir_p(const char *path)
101{
102 char *dir;
103
104 dir = dirname(strdup(path));
105 if (strchr(dir, '/'))
106 mkdir_p(dir);
107
108 mkdir(dir, 0755);
109}
110
111#define BUF_SIZE 4096
112
113void outputfile(const char *outpath, const int ihfs_img, const int offset, const int length)
114{
115 int outfd;
116 int i, rem;
117 char buf[BUF_SIZE];
118
119 lseek(ihfs_img, offset, SEEK_SET);
120
121 outfd = creat(outpath, 0644);
122
123 for (i = 0; i < length / BUF_SIZE; ++i) {
124 read(ihfs_img, buf, BUF_SIZE);
125 write(outfd, buf, BUF_SIZE);
126 }
127 rem = length - i * BUF_SIZE;
128 if (rem > 0) {
129 read(ihfs_img, buf, rem);
130 write(outfd, buf, rem);
131 }
132
133 close(outfd);
134}
135
136int main(int argc, char **argv)
137{
138 struct stat statbuf;
139 int ihfs_img;
140 ihfs_header_t ihfs_hdr;
141 ihfs_file_table_t ihfs_ftbl;
142 int i, j;
143 char *outpath, *base_path, ihfs_path[MAX_IHFS_PATH+1];
144
145 /* check the arguments */
146
147 if (argc != 3)
148 usage();
149
150 stat(argv[1], &statbuf);
151 if (!S_ISREG(statbuf.st_mode))
152 usage();
153
154 stat(argv[2], &statbuf);
155 if (!S_ISDIR(statbuf.st_mode))
156 usage();
157
158 /* check the file, then split */
159
160 ihfs_img = open(argv[1], O_RDONLY);
161
162 if (ihfs_sanity(ihfs_img)) {
163 printf("Non-IHFS format!\n");
164 return 1;
165 } else
166 printf("sanity check OK\n");
167
168 lseek(ihfs_img, 0, SEEK_SET);
169 read(ihfs_img, &ihfs_hdr, sizeof (ihfs_hdr));
170 lseek(ihfs_img, 4 * SECTOR_SIZE, SEEK_SET);
171 read(ihfs_img, &ihfs_ftbl, sizeof (ihfs_ftbl));
172
173 base_path = strdup(argv[2]);
174 outpath = malloc(strlen(base_path) + 1 + MAX_IHFS_PATH + 1);
175 for (i = 0; i < ihfs_hdr.numfiles; ++i) {
176 printf("\n");
177 printf("pathname: %s\n", ihfs_ftbl.files[i].fullpath);
178 printf("starts at sector %d, length is %d bytes\n", ihfs_ftbl.files[i].sector, ihfs_ftbl.files[i].length);
179
180 strncpy(ihfs_path, ihfs_ftbl.files[i].fullpath, MAX_IHFS_PATH);
181 ihfs_path[MAX_IHFS_PATH] = '\0';
182 for (j = 0; j < strlen(ihfs_path); ++j)
183 if (ihfs_path[j] == '\\')
184 ihfs_path[j] = '/';
185
186 sprintf(outpath, "%s/%s", base_path, ihfs_path);
187 mkdir_p(outpath);
188 outputfile(outpath, ihfs_img, ihfs_ftbl.files[i].sector * SECTOR_SIZE, ihfs_ftbl.files[i].length);
189 }
190 free(outpath);
191
192 close(ihfs_img);
193
194 return 0;
195} \ No newline at end of file