File: cabd_memory.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 (179 lines) | stat: -rw-r--r-- 5,865 bytes parent folder | download | duplicates (4)
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* An implementation of the mspack_system interface using only memory */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mspack.h>

/* use a pointer to a mem_buf structure as "filenames" */
struct mem_buf {
  void *data;
  size_t length;
};

struct mem_file {
  char *data;
  size_t length, posn;
};

static void *mem_alloc(struct mspack_system *self, size_t bytes) {
  /* put your memory allocator here */
  return malloc(bytes);
}

static void mem_free(void *buffer) {
  /* put your memory deallocator here */
  free(buffer);
}

static void mem_copy(void *src, void *dest, size_t bytes) {
  /* put your own memory copy routine here */
  memcpy(dest, src, bytes);
}

static void mem_msg(struct mem_file *file, const char *format, ...) {
  /* put your own printf-type routine here, or leave it empty */
}

static struct mem_file *mem_open(struct mspack_system *self,
                                 struct mem_buf *fn, int mode)
{
  struct mem_file *fh;
  if (!fn || !fn->data || !fn->length) return NULL;
  if ((fh = (struct mem_file *) mem_alloc(self, sizeof(struct mem_file)))) {
    fh->data   = (char *) fn->data;
    fh->length = fn->length;
    fh->posn   = (mode == MSPACK_SYS_OPEN_APPEND) ? fn->length : 0;
  }
  return fh;
}

static void mem_close(struct mem_file *fh) {
  if (fh) mem_free(fh);
}

static int mem_read(struct mem_file *fh, void *buffer, int bytes) {
  int todo;
  if (!fh || !buffer || bytes < 0) return -1;
  todo = fh->length - fh->posn;
  if (todo > bytes) todo = bytes;
  if (todo > 0) mem_copy(&fh->data[fh->posn], buffer, (size_t) todo);
  fh->posn += todo; return todo;
}

static int mem_write(struct mem_file *fh, void *buffer, int bytes) {
  int todo;
  if (!fh || !buffer || bytes < 0) return -1;
  todo = fh->length - fh->posn;
  if (todo > bytes) todo = bytes;
  if (todo > 0) mem_copy(buffer, &fh->data[fh->posn], (size_t) todo);
  fh->posn += todo; return todo;
}

static int mem_seek(struct mem_file *fh, off_t offset, int mode) {
  if (!fh) return 1;
  switch (mode) {
  case MSPACK_SYS_SEEK_START: break;
  case MSPACK_SYS_SEEK_CUR:   offset += (off_t) fh->posn; break;
  case MSPACK_SYS_SEEK_END:   offset += (off_t) fh->length; break;
  default: return 1;
  }
  if ((offset < 0) || (offset > (off_t) fh->length)) return 1;
  fh->posn = (size_t) offset;
  return 0;
}

static off_t mem_tell(struct mem_file *fh) {
  return (fh) ? (off_t) fh->posn : -1;
}

static struct mspack_system mem_system = {
  (struct mspack_file * (*)(struct mspack_system *, const char *, int)) &mem_open,
  (void (*)(struct mspack_file *)) &mem_close,
  (int (*)(struct mspack_file *, void *, int)) &mem_read, 
  (int (*)(struct mspack_file *, void *, int)) &mem_write,
  (int (*)(struct mspack_file *, off_t, int)) &mem_seek, 
  (off_t (*)(struct mspack_file *)) &mem_tell,
  (void (*)(struct mspack_file *, const char *, ...)) &mem_msg,
  &mem_alloc,
  &mem_free,
  &mem_copy,
  NULL
};

/* example of usage with mscab_decompressor */

/* a simple cabinet */
static unsigned char embedded_cab[] = {
  0x4D,0x53,0x43,0x46,0x00,0x00,0x00,0x00,0xFD,0x00,0x00,0x00,0x00,0x00,0x00,
  0x00,0x2C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x01,0x01,0x00,0x02,0x00,
  0x00,0x00,0x22,0x06,0x00,0x00,0x5E,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x4D,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x22,0xBA,0x59,0x20,0x00,
  0x68,0x65,0x6C,0x6C,0x6F,0x2E,0x63,0x00,0x4A,0x00,0x00,0x00,0x4D,0x00,0x00,
  0x00,0x00,0x00,0x6C,0x22,0xE7,0x59,0x20,0x00,0x77,0x65,0x6C,0x63,0x6F,0x6D,
  0x65,0x2E,0x63,0x00,0xBD,0x5A,0xA6,0x30,0x97,0x00,0x97,0x00,0x23,0x69,0x6E,
  0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,0x68,0x3E,
  0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,0x28,0x76,
  0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,0x70,0x72,
  0x69,0x6E,0x74,0x66,0x28,0x22,0x48,0x65,0x6C,0x6C,0x6F,0x2C,0x20,0x77,0x6F,
  0x72,0x6C,0x64,0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x23,
  0x69,0x6E,0x63,0x6C,0x75,0x64,0x65,0x20,0x3C,0x73,0x74,0x64,0x69,0x6F,0x2E,
  0x68,0x3E,0x0D,0x0A,0x0D,0x0A,0x76,0x6F,0x69,0x64,0x20,0x6D,0x61,0x69,0x6E,
  0x28,0x76,0x6F,0x69,0x64,0x29,0x0D,0x0A,0x7B,0x0D,0x0A,0x20,0x20,0x20,0x20,
  0x70,0x72,0x69,0x6E,0x74,0x66,0x28,0x22,0x57,0x65,0x6C,0x63,0x6F,0x6D,0x65,
  0x21,0x5C,0x6E,0x22,0x29,0x3B,0x0D,0x0A,0x7D,0x0D,0x0A,0x0D,0x0A
};

int main() {
  struct mscab_decompressor *cabd;
  struct mscabd_cabinet *cab;
  struct mscabd_file *file;
  struct mem_buf source = { &embedded_cab[0], sizeof(embedded_cab) };
  struct mem_buf output;
  int err;

  /* if self-test reveals an error */
  MSPACK_SYS_SELFTEST(err);
  if (err) return 1;

  /* create a cab decompressor using our custom mspack_system interface */
  if ((cabd = mspack_create_cab_decompressor(&mem_system))) {

    /* open a cab file direct from memory */
    if ((cab = cabd->open(cabd, (char *) &source))) {

      /* for all files */
      for (file = cab->files; file; file = file->next) {
        /* fill out our "filename" (memory pointer and length) */
        output.data = (char *) malloc(file->length);
        output.length = file->length;

        /* let cabd extract this file to our memory buffer */
        if (output.data && cabd->extract(cabd, file, (char *) &output)) {
          exit(1);
        }

        /* dump the memory buffer to stdout (for display purposes) */
        printf("Filename: %s\nContents:\n", file->filename);
        fwrite(output.data, 1, output.length, stdout);

        /* free our buffer */
        free(output.data);
      }
      cabd->close(cabd, cab);
    }
    else {
      fprintf(stderr, "can't open cabinet (%d)\n", cabd->last_error(cabd));
    }
    mspack_destroy_cab_decompressor(cabd);
  }
  else {
    fprintf(stderr, "can't make decompressor\n");
  }
  return 0;

}