This repository has been archived by the owner on Jan 12, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sm2mpx10_unpack.c
125 lines (100 loc) · 3.55 KB
/
sm2mpx10_unpack.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
/* sm2mpx10 archive unpacking utility */
/* Copyright (C) 2020 Ørjan Malde */
/* */
/* 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 program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program; if not, write to the Free Software */
/* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <libgen.h>
#if __GNUC__ > 6
#pragma scalar_storage_order little-endian
#endif
#pragma pack(push, 1)
typedef struct
{
uint8_t magic[8]; /* SM2MPX10 */
uint32_t file_num;
uint32_t index_size;
char archive_name[12];
uint32_t header_size; /* == 32 bytes */
} sm2mpx10_header;
typedef struct
{
char name[12];
uint32_t offset;
uint32_t size;
} entry;
#pragma pack(pop)
int main(int argc, char *argv[])
{
sm2mpx10_header *header;
uint32_t i, j;
FILE *archive_file, *out_file;
uint8_t *header_buf, *filelist_buf;
const uint8_t sig[] = {'S','M','2','M','P','X','1','0'};
char *directory_path, *out_path_filename;
if(argc < 2)
exit(1);
header_buf = malloc(sizeof(sm2mpx10_header));
if(!header_buf) {
puts("malloc failure.");
exit(1);
}
archive_file = fopen(argv[1], "rb");
directory_path = dirname(argv[1]);
fread(header_buf, sizeof(sm2mpx10_header), 1, archive_file);
if(memcmp(sig, header_buf, 8)) {
puts("not an ikura archive");
exit(1);
}
header = (sm2mpx10_header *)header_buf;
#if 0
printf("files: %u\nindex_size: %u\narchive name: %s\nheader size: %u\n", header->file_num, \
header->index_size, header->archive_name, header->header_size);
#endif
filelist_buf = malloc(header->file_num * sizeof(entry));
if(!filelist_buf) {
puts("malloc failure");
exit(1);
}
fread(filelist_buf, sizeof(entry), header->file_num, archive_file);
for(i = 0; i < header->file_num; i++) {
entry *e = (entry *)(filelist_buf + (i * sizeof(entry)));
#if 0
printf("name: %.12s, size: %u, offset: %u\n", e->name, e->size, e->offset);
#endif
out_path_filename = malloc(strlen(directory_path) + 13);
if(!out_path_filename) {
puts("malloc failure");
exit(1);
}
strcpy(out_path_filename, directory_path);
strcat(out_path_filename, "/");
strncat(out_path_filename, e->name, 12);
/* write each file */
out_file = fopen(out_path_filename, "wb");
fseek(archive_file, e->offset, SEEK_SET);
for(j = 0; j < e->size; j++) {
(void)fputc(fgetc(archive_file), out_file);
}
free(out_path_filename);
fclose(out_file);
}
fclose(archive_file);
free(filelist_buf);
free(header_buf);
return 0;
}