summaryrefslogtreecommitdiff
path: root/src/export/extract_version_3.c
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2015-04-29 12:44:47 +0200
committerDirk Engling <erdgeist@erdgeist.org>2015-04-29 12:44:47 +0200
commit43a5ac139b552b23de78434a8ee3df8fc6651b38 (patch)
tree759f5b2a10719d1a12d5ebf0279b4e193506141b /src/export/extract_version_3.c
parent18c51711a08db1a13f7829638295e062b90d8601 (diff)
We have a new format between the former version 1 and 2. So shift version numbers. Add README
Diffstat (limited to 'src/export/extract_version_3.c')
-rw-r--r--src/export/extract_version_3.c170
1 files changed, 115 insertions, 55 deletions
diff --git a/src/export/extract_version_3.c b/src/export/extract_version_3.c
index e0e858d..c4914a7 100644
--- a/src/export/extract_version_3.c
+++ b/src/export/extract_version_3.c
@@ -1,70 +1,130 @@
1#include <stdlib.h>
2#include <stdio.h>
3#include <unistd.h>
4#include <fcntl.h> 1#include <fcntl.h>
5#include <string.h>
6#include <zlib.h>
7#include "mystdlib.h" 2#include "mystdlib.h"
3#include <stdlib.h>
4#include <string.h>
5#include <stdint.h>
6#include <unistd.h>
8 7
9#define XORLEN (29) 8/* lha header:
10#define HUGEBLOCK (8*1024*1024)
11
12int main(int argc, char **argv) {
13 unsigned const char xorkey [XORLEN] = "Just for Fun. Linus Torvalds.";
14 unsigned char input [XORLEN];
15 unsigned char output [HUGEBLOCK];
16 char respath[32]; /* file_XXXXX\0 */
17 int zres = 0, filenum = 0, resfile;
18 size_t i, offs = 0, reported = 0;
19 MAP in;
20
21 if( argc != 2 ) exit(111);
22 in = map_file( argv[1], 1 );
23
24 z_stream z; memset( &z, 0, sizeof(z));
25
26 while( offs < in->size ) {
27 size_t inlen = offs + XORLEN < in->size ? XORLEN : in->size - offs;
28 for( i=0; i<inlen; ++i ) input[i] = in->addr[offs+i] ^ xorkey[i];
29 z.next_in = input; z.avail_in = inlen;
30 z.next_out = output; z.avail_out = HUGEBLOCK;
31 inflateInit( &z ); zres = inflate( &z, Z_NO_FLUSH );
32 if( (zres != Z_OK) && (zres != Z_STREAM_END) )
33 goto error_continue;
34
35 z.next_in = in->addr + offs + inlen;
36 z.avail_in = (unsigned int)(in->size - offs - inlen);
37 while( zres == Z_OK ) zres = inflate( &z, Z_NO_FLUSH );
38
39 if( zres != Z_STREAM_END ) {
40error_continue:
41 inflateEnd(&z); memset( &z, 0, sizeof(z));
42 offs++;
43 continue;
44 }
45 9
46 sprintf( respath, "file_%05X", filenum++ ); 1000 Header length
1101 Header checksum [02-length]
1202 0x2d ('-')
1303 0x6c ('l')
1404 0x68 ('h')
1505 0x?? ('0' or '5') unsure
1606 0x2d ('-')
1707 0x?? LSB of compressed size
1808 0x?? ..
1909 0x00 ..
2010 0x00 MSB of compressed size, i.e. 0
21..
2221 Length of path name
47 23
48 resfile = open( respath, O_RDWR | O_CREAT, 0644 ); 24
49 if( resfile < 0 ) { 25*/
50 fprintf( stderr, "Could not open output file %s\n", respath ); 26
51 exit(1); 27static uint8_t mantra_in[] = { 0x68, 0x35, 0x2d, 0x6c };
28
29int main( int args, char **argv )
30{
31 int filenum = 0, run = 1, first_run = 1;
32 size_t offset = 0, old_offset = 0, reported = 0, enc_len = 32;
33 uint8_t mantra[4], id0, id5, *mapped_file;
34 MAP map;
35
36 /* For streets we do have a enc_len of 34 */
37 while( run ) {
38 switch( getopt( args, argv, ":e:" ) ) {
39 case -1 : run = 0; break;
40 case 'e':
41 enc_len = strtoul( optarg, 0, 0 );
42 break;
43 default:
44 fputs( "Syntax: %s [-e encrypted_length (default: 32, for streets 34 or 0)] path-to-teiln.dat", stderr );
45 exit( 1 );
52 } 46 }
53 write( resfile, output, z.total_out ); 47 }
54 close( resfile ); 48 run = 1;
55 offs += z.total_in; 49
50 if( optind == args )
51 { fputs( "Missing filename.", stderr ); exit( 1 ); }
52
53 map = map_file( argv[optind], 1 );
54 mapped_file = map->addr;
56 55
57 if( reported < ( offs * 10 ) / in->size ) { 56 mantra[0] = mantra_in[0] ^ mapped_file[4];
57 mantra[1] = mantra_in[1] ^ mapped_file[5];
58 mantra[2] = mantra_in[2] ^ mapped_file[2];
59 mantra[3] = mantra_in[3] ^ mapped_file[3];
60
61 id0 = mapped_file[0];
62 id5 = mapped_file[5];
63
64 while( run )
65 {
66 while( ( offset < map->size ) && (
67 ( mapped_file[ offset + 0 ] != id0 ) ||
68 ( mapped_file[ offset + 2 ] != ( '-' ^ mantra[2] )) ||
69 ( mapped_file[ offset + 3 ] != ( 'l' ^ mantra[3] )) ||
70 ( mapped_file[ offset + 4 ] != ( 'h' ^ mantra[0] )) ||
71 ( mapped_file[ offset + 5 ] != id5 ) ||
72 ( mapped_file[ offset + 6 ] != ( '-' ^ mantra[2] ))
73 ) ) offset++;
74
75 // printf( "Found an appropriate offset at: %zd\n", offset );
76
77 if( reported < ( offset * 10 ) / map->size )
78 {
58 reported++; 79 reported++;
59 printf( "%zd%% ", 10 * reported ); 80 printf( "%zd%% ", 10 * reported );
60 fflush( stdout ); 81 fflush( stdout );
61 } 82 }
62 83
63 inflateEnd(&z); memset( &z, 0, sizeof(z)); 84 if( offset == map->size )
85 run = 0;
86
87 if( !first_run )
88 {
89 uint8_t *mf = mapped_file + old_offset, df[128];
90 size_t filename_len, header_len, i;
91 int fh;
92 char filename[32];
93
94 /* De-"crypt" obfuscation to our header copy */
95 for( i=0; i<enc_len; ++i)
96 df[i] = mf[i] ^ mantra[i%4];
97
98 /* Get values from LHA header */
99 header_len = df[0] + 2;
100 filename_len = df[21];
101
102 /* Copy rest of header, so we can checksum */
103 for( i=enc_len; i<header_len; ++i)
104 df[i] = mf[i];
105
106 /* Make up new sequental file name */
107 snprintf( filename, sizeof(filename), "%0*d.lha", (int)filename_len, filenum++ );
108 memcpy( ((uint8_t*)df) + 22, filename, filename_len);
109
110 /* Recalculate checksum with new file name */
111 df[1] = 0; for( i=2; i<header_len; ++i) df[1] += df[i];
112
113 /* Open file and dump our de-"crypted" header and then rest of file */
114 fh = open( filename, O_CREAT | O_TRUNC | O_WRONLY, 0644 );
115 if( enc_len > header_len ) {
116 write( fh, df, enc_len );
117 write( fh, mf + enc_len, offset - old_offset - enc_len );
118 } else {
119 write( fh, df, header_len );
120 write( fh, mf + header_len, offset - old_offset - header_len );
121 }
122 close( fh );
123 }
124 first_run = 0;
125 old_offset = offset++;
64 } 126 }
65 unmap_file(&in); 127
66 if( reported < 10 ) 128 unmap_file( &map );
67 printf( "100%% " );
68 fflush( stdout );
69 return 0; 129 return 0;
70} 130}