File: cabrip.c

package info (click to toggle)
libmspack 0.11-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,880 kB
  • sloc: ansic: 8,128; sh: 4,660; perl: 320; makefile: 100
file content (85 lines) | stat: -rw-r--r-- 2,199 bytes parent folder | download | duplicates (2)
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
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <mspack.h>
#include "mspack/macros.h"

#if HAVE_FSEEKO
# define fseek fseeko
#endif

#define BUF_SIZE (1024*4096)
char buf[BUF_SIZE];

void rip(char *fname, off_t offset, unsigned int length) {
    static unsigned int counter = 1;
    struct stat st_buf;
    char outname[13];
    FILE *in = NULL, *out = NULL;

    /* find an unused output filename */
    do {
        snprintf(outname, 13, "%08u.cab", counter++);
    } while (stat(outname, &st_buf) == 0);

    printf("ripping %s offset %" LD " length %u to %s\n",
           fname, offset, length, outname);

    if (!(in = fopen(fname, "rb"))) {
        perror(fname);
        goto cleanup;
    }
    if (!(out = fopen(outname, "wb"))) {
        perror(outname);
        goto cleanup;
    }
    if (fseek(in, offset, SEEK_SET)) {
        fprintf(stderr, "%s: can't seek to cab offset %"LD"\n", fname, offset);
        goto cleanup;
    }
    while (length) {
        size_t run = (length > BUF_SIZE) ? BUF_SIZE : length;
        size_t actual = fread(&buf[0], 1, run, in);
        if (actual < run) {
            fprintf(stderr, "%s: file %u bytes shorter than expected\n",
                    fname, length - (unsigned int)(run - actual));
            length = run = actual;
        }
        if (fwrite(&buf[0], 1, run, out) != run) {
            perror(outname);
            break;
        }
        length -= run;
    }

cleanup:
    if (in) fclose(in);
    if (out) fclose(out);
}

int main(int argc, char *argv[]) {
    struct mscab_decompressor *cabd;
    struct mscabd_cabinet *cab, *c;
    int err;

    MSPACK_SYS_SELFTEST(err);
    if (err) return 0;

    if ((cabd = mspack_create_cab_decompressor(NULL))) {
        cabd->set_param(cabd, MSCABD_PARAM_SALVAGE, 1);
        for (argv++; *argv; argv++) {
            if ((cab = cabd->search(cabd, *argv))) {
                for (c = cab; c; c = c->next) {
                    rip(*argv, c->base_offset, c->length);
                }
                cabd->close(cabd, cab);
            }
        }
        mspack_destroy_cab_decompressor(cabd);
    }
    return 0;
}