oodle-kraken-ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,342 @@
1
+ /*
2
+ === Kraken Decompressor ===
3
+ Copyright (C) 2016, Powzix
4
+ Copyright (C) 2019, rarten
5
+ Copyright (C) 2022, Kerilk
6
+
7
+ This program is free software: you can redistribute it and/or modify
8
+ it under the terms of the GNU General Public License as published by
9
+ the Free Software Foundation, either version 3 of the License, or
10
+ (at your option) any later version.
11
+
12
+ This program is distributed in the hope that it will be useful,
13
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ GNU General Public License for more details.
16
+
17
+ You should have received a copy of the GNU General Public License
18
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+ */
20
+
21
+
22
+ #include "stdafx.h"
23
+ #include "kraken.h"
24
+ #include <sys/stat.h>
25
+
26
+ // The decompressor will write outside of the target buffer.
27
+ #define SAFE_SPACE 64
28
+
29
+ void error(const char *s, const char *curfile = NULL) {
30
+ if (curfile)
31
+ fprintf(stderr, "%s: ", curfile);
32
+ fprintf(stderr, "%s\n", s);
33
+ exit(1);
34
+ }
35
+
36
+
37
+ byte *load_file(const char *filename, size_t *size) {
38
+ FILE *f = fopen(filename, "rb");
39
+ if (!f) error("file open error", filename);
40
+ fseek(f, 0, SEEK_END);
41
+ ssize_t packed_size = ftell(f);
42
+ if (packed_size<0) error("file tell error", filename);
43
+ fseek(f, 0, SEEK_SET);
44
+ byte *input = new byte[packed_size];
45
+ if (!input) error("memory error", filename);
46
+ if (fread(input, 1, packed_size, f) != packed_size) error("error reading", filename);
47
+ fclose(f);
48
+ *size = (size_t)packed_size;
49
+ return input;
50
+ }
51
+
52
+ enum {
53
+ kCompressor_Kraken = 8,
54
+ kCompressor_Mermaid = 9,
55
+ kCompressor_Selkie = 11,
56
+ kCompressor_Hydra = 12,
57
+ kCompressor_Leviathan = 13,
58
+ };
59
+
60
+ bool arg_stdout, arg_force, arg_quiet, arg_dll;
61
+ int arg_compressor = kCompressor_Kraken, arg_level = 4;
62
+ char arg_direction;
63
+ const char *verifyfolder;
64
+
65
+ int ParseCmdLine(int argc, char *argv[]) {
66
+ int i;
67
+ // parse command line
68
+ for (i = 1; i < argc; i++) {
69
+ const char *s = argv[i];
70
+ char c;
71
+ if (*s != '-')
72
+ break;
73
+ if (*++s == '-') {
74
+ if (*++s == 0) {
75
+ i++;
76
+ break; // --
77
+ }
78
+ // long opts
79
+ if (!strcmp(s, "stdout")) s = "c";
80
+ else if (!strcmp(s, "decompress")) s = "d";
81
+ else if (!strcmp(s, "compress")) s = "z";
82
+ else if (!strncmp(s, "verify=",7)) {
83
+ verifyfolder = s + 7;
84
+ continue;
85
+ } else if (!strcmp(s, "verify")) {
86
+ arg_direction = 't';
87
+ continue;
88
+ } else if (!strcmp(s, "dll")) {
89
+ arg_dll = true;
90
+ continue;
91
+ } else if (!strcmp(s, "kraken")) s = "mk";
92
+ else if (!strcmp(s, "mermaid")) s = "mm";
93
+ else if (!strcmp(s, "selkie")) s = "ms";
94
+ else if (!strcmp(s, "leviathan")) s = "ml";
95
+ else if (!strcmp(s, "hydra")) s = "mh";
96
+ else if (!strncmp(s, "level=", 6)) {
97
+ arg_level = atoi(s + 6);
98
+ continue;
99
+ } else {
100
+ return -1;
101
+ }
102
+ }
103
+ // short opt
104
+ do {
105
+ switch (c = *s++) {
106
+ case 'z':
107
+ case 'd':
108
+ case 'b':
109
+ if (arg_direction)
110
+ return -1;
111
+ arg_direction = c;
112
+ break;
113
+ case 'c':
114
+ arg_stdout = true;
115
+ break;
116
+ case 'f':
117
+ arg_force = true;
118
+ break;
119
+ case 'q':
120
+ arg_quiet = true;
121
+ break;
122
+ case '1': case '2': case '3': case '4':
123
+ case '5': case '6': case '7': case '8': case '9':
124
+ arg_level = c - '0';
125
+ break;
126
+ case 'm':
127
+ c = *s++;
128
+ arg_compressor = (c == 'k') ? kCompressor_Kraken :
129
+ (c == 'm') ? kCompressor_Mermaid :
130
+ (c == 's') ? kCompressor_Selkie :
131
+ (c == 'l') ? kCompressor_Leviathan :
132
+ (c == 'h') ? kCompressor_Hydra : -1;
133
+ if (arg_compressor < 0)
134
+ return -1;
135
+ break;
136
+ default:
137
+ return -1;
138
+ }
139
+ } while (*s);
140
+ }
141
+ return i;
142
+ }
143
+
144
+ bool Verify(const char *filename, uint8 *output, size_t outbytes, const char *curfile) {
145
+ size_t test_size;
146
+ byte *test = load_file(filename, &test_size);
147
+ if (!test) {
148
+ fprintf(stderr, "file open error: %s\n", filename);
149
+ return false;
150
+ }
151
+ if (test_size != outbytes) {
152
+ fprintf(stderr, "%s: ERROR: File size difference: %zu vs %zu\n", filename, outbytes, test_size);
153
+ return false;
154
+ }
155
+ for (int i = 0; i != test_size; i++) {
156
+ if (test[i] != output[i]) {
157
+ fprintf(stderr, "%s: ERROR: File difference at 0x%x. Was %d instead of %d\n", curfile, i, output[i], test[i]);
158
+ return false;
159
+ }
160
+ }
161
+ return true;
162
+ }
163
+
164
+ #ifndef _MSC_VER
165
+ typedef uint64_t LARGE_INTEGER;
166
+ void QueryPerformanceCounter(LARGE_INTEGER *a) {
167
+ *a = 0;
168
+ }
169
+ void QueryPerformanceFrequency(LARGE_INTEGER *a) {
170
+ *a = 1;
171
+ }
172
+ #define WINAPI
173
+ typedef void* HINSTANCE;
174
+ HINSTANCE LoadLibraryA(const char *s) { return 0; }
175
+ void *GetProcAddress(HINSTANCE h, const char *s) { return 0; }
176
+ #endif
177
+
178
+ typedef ssize_t WINAPI OodLZ_CompressFunc(
179
+ int codec, uint8 *src_buf, size_t src_len, uint8 *dst_buf, int level,
180
+ void *opts, size_t offs, size_t unused, void *scratch, size_t scratch_size);
181
+ typedef ssize_t WINAPI OodLZ_DecompressFunc(uint8 *src_buf, int src_len, uint8 *dst, size_t dst_size,
182
+ int fuzz, int crc, int verbose,
183
+ uint8 *dst_base, size_t e, void *cb, void *cb_ctx, void *scratch, size_t scratch_size, int threadPhase);
184
+
185
+ OodLZ_CompressFunc *OodLZ_Compress;
186
+ OodLZ_DecompressFunc *OodLZ_Decompress;
187
+
188
+ void LoadLib() {
189
+
190
+ #if defined(_M_X64)
191
+ #define LIBNAME "oo2core_7_win64.dll"
192
+ char COMPFUNCNAME[] = "XXdleLZ_Compress";
193
+ char DECFUNCNAME[] = "XXdleLZ_Decompress";
194
+ COMPFUNCNAME[0] = DECFUNCNAME[0] = 'O';
195
+ COMPFUNCNAME[1] = DECFUNCNAME[1] = 'o';
196
+ #else
197
+ #define LIBNAME "oo2core_7_win32.dll"
198
+ char COMPFUNCNAME[] = "_XXdleLZ_Compress@40";
199
+ char DECFUNCNAME[] = "_XXdleLZ_Decompress@56";
200
+ COMPFUNCNAME[1] = DECFUNCNAME[1] = 'O';
201
+ COMPFUNCNAME[2] = DECFUNCNAME[2] = 'o';
202
+ #endif
203
+ HINSTANCE mod = LoadLibraryA(LIBNAME);
204
+ OodLZ_Compress = (OodLZ_CompressFunc*)GetProcAddress(mod, COMPFUNCNAME);
205
+ OodLZ_Decompress = (OodLZ_DecompressFunc*)GetProcAddress(mod, DECFUNCNAME);
206
+ if (!OodLZ_Compress || !OodLZ_Decompress)
207
+ error("error loading", LIBNAME);
208
+ }
209
+
210
+ int main(int argc, char *argv[]) {
211
+ int64_t start, end, freq;
212
+ int argi;
213
+
214
+ if (argc < 2 ||
215
+ (argi = ParseCmdLine(argc, argv)) < 0 ||
216
+ argi >= argc || // no files
217
+ (arg_direction != 'b' && (argc - argi) > 2) || // too many files
218
+ (arg_direction == 't' && (argc - argi) != 2) // missing argument for verify
219
+ ) {
220
+ fprintf(stderr, "ooz v7.0\n\n"
221
+ "Usage: ooz [options] input [output]\n"
222
+ " -c --stdout write to stdout\n"
223
+ " -d --decompress decompress (default)\n"
224
+ " -z --compress compress (requires oo2core_7_win64.dll)\n"
225
+ " -b just benchmark, don't overwrite anything\n"
226
+ " -f force overwrite existing file\n"
227
+ " --dll decompress with the dll\n"
228
+ " --verify decompress and verify that it matches output\n"
229
+ " --verify=<folder> verify with files in this folder\n"
230
+ " -<1-9> --level=<-4..10> compression level\n"
231
+ " -m<k> [k|m|s|l|h] compressor selection\n"
232
+ " --kraken --mermaid --selkie --leviathan --hydra compressor selection\n\n"
233
+ "(Warning! not fuzz safe, so please trust the input)\n"
234
+ );
235
+ return 1;
236
+ }
237
+ bool write_mode = (argi + 1 < argc) && (arg_direction != 't' && arg_direction != 'b');
238
+
239
+ if (!arg_force && write_mode) {
240
+ struct stat sb;
241
+ if (stat(argv[argi + 1], &sb) >= 0) {
242
+ fprintf(stderr, "file %s already exists, skipping.\n", argv[argi + 1]);
243
+ return 1;
244
+ }
245
+ }
246
+
247
+ int nverify = 0;
248
+
249
+ for (; argi < argc; argi++) {
250
+ const char *curfile = argv[argi];
251
+
252
+ size_t input_size;
253
+ byte *input = load_file(curfile, &input_size);
254
+
255
+ byte *output = NULL;
256
+ ssize_t outbytes = 0;
257
+
258
+ if (arg_direction == 'z') {
259
+ // compress using the dll
260
+ LoadLib();
261
+ output = new byte[input_size + 65536];
262
+ if (!output) error("memory error", curfile);
263
+ *(uint64*)output = input_size;
264
+ QueryPerformanceCounter((LARGE_INTEGER*)&start);
265
+ outbytes = OodLZ_Compress(arg_compressor, input, input_size, output + 8, arg_level, 0, 0, 0, 0, 0);
266
+ if (outbytes < 0) error("compress failed", curfile);
267
+ outbytes += 8;
268
+ QueryPerformanceCounter((LARGE_INTEGER*)&end);
269
+ QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
270
+ double seconds = (double)(end - start) / freq;
271
+ if (!arg_quiet)
272
+ fprintf(stderr, "%-20s: %8zu => %8zu (%.2f seconds, %.2f MB/s)\n", argv[argi], input_size, (size_t)outbytes, seconds, input_size * 1e-6 / seconds);
273
+ } else {
274
+ if (arg_dll)
275
+ LoadLib();
276
+
277
+ // stupidly attempt to autodetect if file uses 4-byte or 8-byte header,
278
+ // the previous version of this tool wrote a 4-byte header.
279
+ int hdrsize = *(uint64*)input >= 0x10000000000 ? 4 : 8;
280
+
281
+ size_t unpacked_size = (hdrsize == 8) ? *(size_t*)input : *(uint32*)input;
282
+ if (unpacked_size > (hdrsize == 4 ? 52*1024*1024 : 1024 * 1024 * 1024))
283
+ error("file too large", curfile);
284
+ output = new byte[unpacked_size + SAFE_SPACE];
285
+ if (!output) error("memory error", curfile);
286
+
287
+ QueryPerformanceCounter((LARGE_INTEGER*)&start);
288
+
289
+ if (arg_dll) {
290
+ outbytes = OodLZ_Decompress(input + hdrsize, input_size - hdrsize, output, unpacked_size, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
291
+ } else {
292
+ outbytes = Kraken_Decompress(input + hdrsize, input_size - hdrsize, output, unpacked_size);
293
+ }
294
+ if (outbytes != unpacked_size)
295
+ error("decompress error", curfile);
296
+ QueryPerformanceCounter((LARGE_INTEGER*)&end);
297
+ QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
298
+ double seconds = (double)(end - start) / freq;
299
+ if (!arg_quiet)
300
+ fprintf(stderr, "%-20s: %8zu => %8zu (%.2f seconds, %.2f MB/s)\n", argv[argi], input_size, unpacked_size, seconds, unpacked_size * 1e-6 / seconds);
301
+ }
302
+
303
+ if (verifyfolder) {
304
+ // Verify against the file in verifyfolder with the same basename excluding extension
305
+ char buf[1024];
306
+ const char *basename = curfile;
307
+ for(const char *s = curfile; *s; s++)
308
+ if (*s == '/' || *s == '\\')
309
+ basename = s + 1;
310
+ const char *ext = strrchr(basename, '.');
311
+ snprintf(buf, sizeof(buf), "%s/%.*s", verifyfolder, (int)(ext ? (ext - basename) : strlen(basename)), basename);
312
+ if (!Verify(buf, output, outbytes, curfile))
313
+ return 1;
314
+ nverify++;
315
+ }
316
+
317
+ if (arg_stdout && arg_direction != 't' && arg_direction != 'b')
318
+ fwrite(output, 1, outbytes, stdout);
319
+
320
+ if (write_mode) {
321
+ if (arg_direction == 't') {
322
+ if (!Verify(argv[argi + 1], output, outbytes, curfile))
323
+ return 1;
324
+ fprintf(stderr, "%s: Verify OK\n", curfile);
325
+ } else {
326
+ FILE *f = fopen(argv[argi + 1], "wb");
327
+ if (!f) error("file open for write error", argv[argi + 1]);
328
+ if (fwrite(output, 1, outbytes, f) != outbytes)
329
+ error("file write error", argv[argi + 1]);
330
+ fclose(f);
331
+ }
332
+ break;
333
+ }
334
+ delete[] input;
335
+ delete[] output;
336
+ }
337
+
338
+ if (nverify)
339
+ fprintf(stderr, "%d files verified OK!\n", nverify);
340
+ return 0;
341
+ }
342
+
@@ -0,0 +1,8 @@
1
+ // stdafx.cpp : source file that includes just the standard includes
2
+ // kraken.pch will be the pre-compiled header
3
+ // stdafx.obj will contain the pre-compiled type information
4
+
5
+ #include "stdafx.h"
6
+
7
+ // TODO: reference any additional headers you need in STDAFX.H
8
+ // and not in this file
@@ -0,0 +1,68 @@
1
+ /*
2
+ Copyright (C) 2016, Powzix
3
+ Copyright (C) 2019, rarten
4
+
5
+ This program is free software: you can redistribute it and/or modify
6
+ it under the terms of the GNU General Public License as published by
7
+ the Free Software Foundation, either version 3 of the License, or
8
+ (at your option) any later version.
9
+
10
+ This program is distributed in the hope that it will be useful,
11
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ GNU General Public License for more details.
14
+
15
+ You should have received a copy of the GNU General Public License
16
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+ // stdafx.h : includefile for standard system include files,
20
+ // or project specific include files that are used frequently, but
21
+ // are changed infrequently
22
+ //
23
+
24
+ #pragma once
25
+
26
+ #define _CRT_SECURE_NO_WARNINGS 1
27
+
28
+ #include <stdio.h>
29
+ #include <stdlib.h>
30
+ #include <string.h>
31
+ #include <assert.h>
32
+ #include <stdint.h>
33
+ #include <limits.h>
34
+ #if defined(_MSC_VER)
35
+ #include <Windows.h>
36
+ #include <intrin.h>
37
+ #undef max
38
+ #undef min
39
+ #else
40
+ #include <stddef.h>
41
+ #define __forceinline inline
42
+ #define _byteswap_ushort(x) __builtin_bswap16((uint16)(x))
43
+ #define _byteswap_ulong(x) __builtin_bswap32((uint32)(x))
44
+ #define _byteswap_uint64(x) __builtin_bswap64((uint64)(x))
45
+ #define _BitScanForward(dst, x) (*(dst) = __builtin_ctz(x))
46
+ #define _BitScanReverse(dst, x) (*(dst) = (__builtin_clz(x) ^ 31))
47
+
48
+ static inline uint32_t _rotl(uint32_t x, int n) {
49
+ return (((x) << (n)) | ((x) >> (32-(n))));
50
+ }
51
+
52
+ #include <xmmintrin.h>
53
+ #endif
54
+
55
+ #pragma warning (disable: 4244)
56
+ #pragma warning (disable: 4530) // c++ exception handler used without unwind semantics
57
+ #pragma warning (disable: 4018) // signed/unsigned mismatch
58
+
59
+ // TODO: reference additional headers your program requires here
60
+ typedef uint8_t byte;
61
+ typedef uint8_t uint8;
62
+ typedef uint32_t uint32;
63
+ typedef uint64_t uint64;
64
+ typedef int64_t int64;
65
+ typedef int32_t int32;
66
+ typedef uint16_t uint16;
67
+ typedef int16_t int16;
68
+ typedef unsigned int uint;
@@ -0,0 +1,8 @@
1
+ #pragma once
2
+
3
+ // Including SDKDDKVer.h defines the highest available Windows platform.
4
+
5
+ // If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
6
+ // set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
7
+
8
+ #include <SDKDDKVer.h>
@@ -0,0 +1,2 @@
1
+ require "oodle_kraken_c"
2
+
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oodle-kraken-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Brice Videau
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-10-29 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Uncompress files compressed with Oodle Kraken / Mermaid / Selkie / Leviathan
14
+ / LZNA / Bitknit.
15
+ email: brice.videau@gmail.com
16
+ executables: []
17
+ extensions:
18
+ - ext/oodle-kraken/extconf.rb
19
+ extra_rdoc_files: []
20
+ files:
21
+ - LICENSE
22
+ - ext/oodle-kraken/extconf.rb
23
+ - ext/oodle-kraken/oodle_kraken_c.c
24
+ - ext/oodle-kraken/ooz/LICENSE
25
+ - ext/oodle-kraken/ooz/README.md
26
+ - ext/oodle-kraken/ooz/bitknit.cpp
27
+ - ext/oodle-kraken/ooz/kraken.cpp
28
+ - ext/oodle-kraken/ooz/kraken.h
29
+ - ext/oodle-kraken/ooz/lzna.cpp
30
+ - ext/oodle-kraken/ooz/ooz.cpp
31
+ - ext/oodle-kraken/ooz/stdafx.cpp
32
+ - ext/oodle-kraken/ooz/stdafx.h
33
+ - ext/oodle-kraken/ooz/targetver.h
34
+ - lib/oodle-kraken-ruby.rb
35
+ homepage: https://github.com/kerilk/oodle-kraken-ruby
36
+ licenses:
37
+ - GPL-3.0-or-later
38
+ metadata: {}
39
+ post_install_message:
40
+ rdoc_options: []
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 2.0.0
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
53
+ requirements: []
54
+ rubygems_version: 3.1.2
55
+ signing_key:
56
+ specification_version: 4
57
+ summary: Library for decrompressing Oodle compressed file
58
+ test_files: []