]> icculus.org git repositories - icculus/xz.git/blob - extra/scanlzma/scanlzma.c
Imported to git.
[icculus/xz.git] / extra / scanlzma / scanlzma.c
1 /*
2     scanlzma, scan for lzma compressed data in stdin and echo it to stdout.
3     Copyright (C) 2006 Timo Lindfors
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 2 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
16 /* Usage example:
17
18    $ wget http://www.wifi-shop.cz/Files/produkty/wa2204/wa2204av1.4.1.zip
19    $ unzip wa2204av1.4.1.zip
20    $ gcc scanlzma.c -o scanlzma -Wall
21    $ ./scanlzma 0 < WA2204-FW1.4.1/linux-1.4.bin | lzma -c -d | strings | grep -i "copyright"
22    UpdateDD version 2.5, Copyright (C) 2005 Philipp Benner.
23    Copyright (C) 2005 Philipp Benner.
24    Copyright (C) 2005 Philipp Benner.
25    mawk 1.3%s%s %s, Copyright (C) Michael D. Brennan
26    # Copyright (C) 1998, 1999, 2001  Henry Spencer.
27    ...
28
29 */
30
31
32 /* LZMA compressed file format */
33 /* --------------------------- */
34 /* Offset Size Description */
35 /*   0     1   Special LZMA properties for compressed data */
36 /*   1     4   Dictionary size (little endian) */
37 /*   5     8   Uncompressed size (little endian). -1 means unknown size */
38 /*  13         Compressed data */
39
40 #define BUFSIZE 4096
41
42 int find_lzma_header(unsigned char *buf) {
43         return (buf[0] < 0xE1
44                 && buf[0] == 0x5d
45                 && buf[4] < 0x20
46                 && (memcmp (buf + 10 , "\x00\x00\x00", 3) == 0
47                     || (memcmp (buf + 5, "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8) == 0)));
48 }
49
50 int main(int argc, char *argv[]) {
51         char buf[BUFSIZE];
52         int ret, i, numlzma, blocks=0;
53
54         if (argc != 2) {
55                 printf("usage: %s numlzma < infile | lzma -c -d > outfile\n"
56                        "where numlzma is index of lzma file to extract, starting from zero.\n",
57                        argv[0]);
58                 exit(1);
59         }
60         numlzma = atoi(argv[1]);
61
62         for (;;) {
63                 /* Read data. */
64                 ret = fread(buf, BUFSIZE, 1, stdin);
65                 if (ret != 1)
66                         break;
67                 
68                 /* Scan for signature. */
69                 for (i = 0; i<BUFSIZE-23; i++) {
70                         if (find_lzma_header(buf+i) && numlzma-- <= 0) {
71                                 fwrite(buf+i, (BUFSIZE-i), 1, stdout); 
72                                 for (;;) {
73                                         int ch;
74                                         ch = getchar();
75                                         if (ch == EOF)
76                                                 exit(0);
77                                         putchar(ch);
78                                 }
79                                         
80                         }
81                 }
82                 blocks++;
83         }
84         return 1;
85 }