1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <sys/stat.h>
8 #include <mspack.h>
9 #include <system.h>
10
11 #if HAVE_FSEEKO
12 # define fseek fseeko
13 #endif
14
15 #define BUF_SIZE (1024*4096)
16 char buf[BUF_SIZE];
17
rip(char * fname,off_t offset,unsigned int length)18 void rip(char *fname, off_t offset, unsigned int length) {
19 static unsigned int counter = 1;
20 struct stat st_buf;
21 char outname[13];
22 FILE *in = NULL, *out = NULL;
23
24 /* find an unused output filename */
25 do {
26 snprintf(outname, 13, "%08u.cab", counter++);
27 } while (stat(outname, &st_buf) == 0);
28
29 printf("ripping %s offset %" LD " length %u to %s\n",
30 fname, offset, length, outname);
31
32 if (!(in = fopen(fname, "rb"))) {
33 perror(fname);
34 goto cleanup;
35 }
36 if (!(out = fopen(outname, "wb"))) {
37 perror(outname);
38 goto cleanup;
39 }
40 if (fseek(in, offset, SEEK_SET)) {
41 fprintf(stderr, "%s: can't seek to cab offset %"LD"\n", fname, offset);
42 goto cleanup;
43 }
44 while (length) {
45 size_t run = (length > BUF_SIZE) ? BUF_SIZE : length;
46 size_t actual = fread(&buf[0], 1, run, in);
47 if (actual < run) {
48 fprintf(stderr, "%s: file %u bytes shorter than expected\n",
49 fname, length - (unsigned int)(run - actual));
50 length = run = actual;
51 }
52 if (fwrite(&buf[0], 1, run, out) != run) {
53 perror(outname);
54 break;
55 }
56 length -= run;
57 }
58
59 cleanup:
60 if (in) fclose(in);
61 if (out) fclose(out);
62 }
63
main(int argc,char * argv[])64 int main(int argc, char *argv[]) {
65 struct mscab_decompressor *cabd;
66 struct mscabd_cabinet *cab, *c;
67 int err;
68
69 MSPACK_SYS_SELFTEST(err);
70 if (err) return 0;
71
72 if ((cabd = mspack_create_cab_decompressor(NULL))) {
73 cabd->set_param(cabd, MSCABD_PARAM_SALVAGE, 1);
74 for (argv++; *argv; argv++) {
75 if ((cab = cabd->search(cabd, *argv))) {
76 for (c = cab; c; c = c->next) {
77 rip(*argv, c->base_offset, c->length);
78 }
79 cabd->close(cabd, cab);
80 }
81 }
82 mspack_destroy_cab_decompressor(cabd);
83 }
84 return 0;
85 }
86