~ubuntu-branches/ubuntu/saucy/clamav/saucy

« back to all changes in this revision

Viewing changes to libclamunrar_iface/unrar_iface.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2007-12-18 15:18:53 UTC
  • mfrom: (0.25.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20071218151853-ag6bdjbq6budh353
Tags: 0.92~dfsg-0build1
Fake sync to get the new clamav into the NEW queue

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Interface to libclamunrar
 
3
 *  Copyright (C) 2007 Sourcefire, Inc.
 
4
 *  Authors: Trog, Torok Edvin, Tomasz Kojm
 
5
 *
 
6
 *  This library is free software; you can redistribute it and/or
 
7
 *  modify it under the terms of the GNU Lesser General Public
 
8
 *  License version 2.1 as published by the Free Software Foundation.
 
9
 *
 
10
 *  This library 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 GNU
 
13
 *  Lesser General Public License for more details.
 
14
 *
 
15
 *  You should have received a copy of the GNU Lesser General Public
 
16
 *  License along with this library; if not, write to the Free Software
 
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#if HAVE_CONFIG_H
 
21
#include "clamav-config.h"
 
22
#endif
 
23
 
 
24
/* TODO: Add support for dlopen()&Co. */
 
25
 
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
#include <sys/types.h>
 
29
#include <sys/stat.h>
 
30
#include <fcntl.h>
 
31
#ifdef  HAVE_UNISTD_H
 
32
#include <unistd.h>
 
33
#endif
 
34
 
 
35
#include "libclamunrar/unrar.h"
 
36
 
 
37
#include "unrar_iface.h"
 
38
 
 
39
#if WORDS_BIGENDIAN == 0
 
40
#define unrar_endian_convert_16(v)      (v)
 
41
#define unrar_endian_convert_32(v)    (v)
 
42
#else
 
43
static uint16_t unrar_endian_convert_16(uint16_t v)
 
44
{
 
45
    return ((v >> 8) + (v << 8));
 
46
}
 
47
static uint32_t unrar_endian_convert_32(uint32_t v)
 
48
{
 
49
    return ((v >> 24) | ((v & 0x00FF0000) >> 8) | ((v & 0x0000FF00) << 8) | (v << 24));
 
50
}
 
51
#endif
 
52
 
 
53
#ifndef O_BINARY
 
54
#define O_BINARY    0
 
55
#endif
 
56
 
 
57
/* FIXME: allow this to be controlled from unrar_open or so */
 
58
#ifdef RAR_DEBUG_MODE
 
59
#define unrar_dbgmsg printf
 
60
#else
 
61
static void unrar_dbgmsg(const char* fmt,...){}
 
62
#endif
 
63
 
 
64
static void *read_header(int fd, header_type hdr_type)
 
65
{
 
66
        unsigned char encrypt_ver;
 
67
 
 
68
 
 
69
    switch(hdr_type) {
 
70
        case MAIN_HEAD: {
 
71
                unrar_main_header_t *main_hdr;
 
72
 
 
73
            main_hdr = (unrar_main_header_t *) malloc(sizeof(unrar_main_header_t));
 
74
            if(!main_hdr)
 
75
                return NULL;
 
76
 
 
77
            if(read(fd, main_hdr, SIZEOF_NEWMHD) != SIZEOF_NEWMHD) {
 
78
                free(main_hdr);
 
79
                return NULL;
 
80
            }
 
81
            main_hdr->flags = unrar_endian_convert_16(main_hdr->flags);
 
82
            main_hdr->head_size = unrar_endian_convert_16(main_hdr->head_size);
 
83
            main_hdr->head_crc = unrar_endian_convert_16(main_hdr->head_crc);
 
84
            if(main_hdr->flags & MHD_ENCRYPTVER) {
 
85
                if(read(fd, &encrypt_ver, sizeof(unsigned char)) != sizeof(unsigned char)) {
 
86
                    free(main_hdr);
 
87
                    return NULL;
 
88
                }
 
89
                unrar_dbgmsg("UNRAR: RAR Encrypt version: %d\n", encrypt_ver);
 
90
            }
 
91
            return main_hdr;
 
92
        }
 
93
        case FILE_HEAD: {
 
94
                unrar_fileheader_t *file_hdr;
 
95
 
 
96
            file_hdr = (unrar_fileheader_t *) malloc(sizeof(unrar_fileheader_t));
 
97
            if(!file_hdr)
 
98
                return NULL;
 
99
 
 
100
            if(read(fd, file_hdr, SIZEOF_NEWLHD) != SIZEOF_NEWLHD) {
 
101
                free(file_hdr);
 
102
                return NULL;
 
103
            }
 
104
            file_hdr->flags = unrar_endian_convert_16(file_hdr->flags);
 
105
            file_hdr->head_size = unrar_endian_convert_16(file_hdr->head_size);
 
106
            file_hdr->pack_size = unrar_endian_convert_32(file_hdr->pack_size);
 
107
            file_hdr->unpack_size = unrar_endian_convert_32(file_hdr->unpack_size);
 
108
            file_hdr->file_crc = unrar_endian_convert_32(file_hdr->file_crc);
 
109
            file_hdr->name_size = unrar_endian_convert_16(file_hdr->name_size);
 
110
            if(file_hdr->flags & 0x100) {
 
111
                if(read(fd, (char *) file_hdr + SIZEOF_NEWLHD, 8) != 8) {
 
112
                    free(file_hdr);
 
113
                    return NULL;
 
114
                }
 
115
                file_hdr->high_pack_size = unrar_endian_convert_32(file_hdr->high_pack_size);
 
116
                file_hdr->high_unpack_size = unrar_endian_convert_32(file_hdr->high_unpack_size);
 
117
            } else {
 
118
                file_hdr->high_pack_size = 0;
 
119
                file_hdr->high_unpack_size = 0;
 
120
            }
 
121
            return file_hdr;
 
122
        }
 
123
        case COMM_HEAD: {
 
124
                unrar_comment_header_t *comment_hdr;
 
125
 
 
126
            comment_hdr = (unrar_comment_header_t *) malloc(sizeof(unrar_comment_header_t));
 
127
            if(!comment_hdr)
 
128
                return NULL;
 
129
 
 
130
            if(read(fd, comment_hdr, SIZEOF_COMMHEAD) != SIZEOF_COMMHEAD) {
 
131
                free(comment_hdr);
 
132
                return NULL;
 
133
            }
 
134
            comment_hdr->unpack_size = unrar_endian_convert_16(comment_hdr->unpack_size);
 
135
            comment_hdr->comm_crc = unrar_endian_convert_16(comment_hdr->comm_crc);
 
136
            return comment_hdr;
 
137
        }
 
138
        default:
 
139
            unrar_dbgmsg("UNRAR: ERROR: Unknown header type requested\n");
 
140
            return NULL;
 
141
    }
 
142
    return NULL;
 
143
}
 
144
 
 
145
static unrar_fileheader_t *read_block(int fd, header_type hdr_type)
 
146
{
 
147
        unrar_fileheader_t *file_header;
 
148
        off_t offset;
 
149
 
 
150
 
 
151
    for (;;) {
 
152
        offset = lseek(fd, 0, SEEK_CUR);
 
153
        file_header = read_header(fd, FILE_HEAD);
 
154
        if(!file_header)
 
155
            return NULL;
 
156
 
 
157
        file_header->start_offset = offset;
 
158
        file_header->next_offset = offset + file_header->head_size;
 
159
        if(file_header->flags & LONG_BLOCK)
 
160
            file_header->next_offset += file_header->pack_size;
 
161
 
 
162
        if(file_header->next_offset <= offset) {
 
163
            free(file_header);
 
164
            return NULL;
 
165
        }
 
166
 
 
167
        /* Check if the block is of the requested type */
 
168
        if(file_header->head_type == hdr_type) {
 
169
            /* TODO check what to do with SUBBLOCKS */
 
170
            break;
 
171
        }
 
172
 
 
173
        unrar_dbgmsg("UNRAR: Found block type: 0x%x\n", file_header->head_type);
 
174
        unrar_dbgmsg("UNRAR: Head Size: %.4x\n", file_header->head_size);
 
175
        if(lseek(fd, file_header->next_offset, SEEK_SET) != file_header->next_offset) {
 
176
            unrar_dbgmsg("seek: %ld\n", file_header->next_offset);
 
177
            return NULL;
 
178
        }
 
179
 
 
180
        free(file_header);
 
181
    }
 
182
 
 
183
    unrar_dbgmsg("UNRAR: read_block out offset=%ld\n", lseek(fd, 0, SEEK_CUR));
 
184
    unrar_dbgmsg("UNRAR: Found file block.\n");
 
185
    unrar_dbgmsg("UNRAR: Pack Size: %u\n", file_header->pack_size);
 
186
    unrar_dbgmsg("UNRAR: UnPack Version: 0x%.2x\n", file_header->unpack_ver);
 
187
    unrar_dbgmsg("UNRAR: Pack Method: 0x%.2x\n", file_header->method);
 
188
    file_header->filename = (char *) malloc(file_header->name_size+1);
 
189
    if(!file_header->filename) {
 
190
        free(file_header);
 
191
        return NULL;
 
192
    }
 
193
    if(read(fd, file_header->filename, file_header->name_size) != file_header->name_size) {
 
194
        free(file_header->filename);
 
195
        free(file_header);
 
196
        return NULL;
 
197
    }
 
198
    file_header->filename[file_header->name_size] = '\0';
 
199
    unrar_dbgmsg("Filename: %s\n", file_header->filename);
 
200
 
 
201
    return file_header;
 
202
}
 
203
 
 
204
static int is_rar_archive(int fd)
 
205
{
 
206
        mark_header_t mark;
 
207
        const mark_header_t rar_hdr[2] = {{0x52, 0x61, 0x72, 0x21, 0x1a, 0x07, 0x00}, {'U', 'n', 'i', 'q', 'u', 'E', '!'}};
 
208
 
 
209
 
 
210
    if(read(fd, &mark, SIZEOF_MARKHEAD) != SIZEOF_MARKHEAD)
 
211
        return FALSE;
 
212
 
 
213
    if(memcmp(&mark, &rar_hdr[0], SIZEOF_MARKHEAD) == 0)
 
214
        return TRUE;
 
215
 
 
216
    if(memcmp(&mark, &rar_hdr[1], SIZEOF_MARKHEAD) == 0)
 
217
        return TRUE;
 
218
 
 
219
    unrar_dbgmsg("UNRAR: Not a RAR archive\n");
 
220
    return FALSE;
 
221
}
 
222
 
 
223
static void unpack_free_data(unpack_data_t *unpack_data)
 
224
{
 
225
        if (!unpack_data) {
 
226
                return;
 
227
        }
 
228
        /*init_filters(unpack_data);*/
 
229
        rarvm_free(&unpack_data->rarvm_data);
 
230
}
 
231
 
 
232
static unsigned int copy_file_data(int ifd, int ofd, unsigned int len)
 
233
{
 
234
        unsigned char data[8192];
 
235
        unsigned int todo, count, rem;
 
236
 
 
237
    rem = len;
 
238
    while(rem > 0) {
 
239
        todo = MIN(8192, rem);
 
240
        count = read(ifd, data, todo);
 
241
        if(count != todo)
 
242
            return len-rem;
 
243
 
 
244
        if(write(ofd, data, count) != (ssize_t) count)
 
245
            return len-rem-count;
 
246
 
 
247
        rem -= count;
 
248
    }
 
249
    return len;
 
250
}
 
251
 
 
252
int unrar_open(int fd, const char *dirname, unrar_state_t *state)
 
253
{
 
254
        int ofd, retval;
 
255
        char filename[1024];
 
256
        unpack_data_t *unpack_data;
 
257
        unrar_main_header_t *main_hdr;
 
258
        off_t offset;
 
259
 
 
260
 
 
261
    if(!state)
 
262
        return UNRAR_ERR;
 
263
 
 
264
    if(!is_rar_archive(fd))
 
265
        return UNRAR_ERR;
 
266
 
 
267
    unpack_data = (unpack_data_t *) malloc(sizeof(unpack_data_t));
 
268
    if(!unpack_data) {
 
269
        unrar_dbgmsg("UNRAR: malloc failed for unpack_data\n");
 
270
        return UNRAR_EMEM;
 
271
    }
 
272
    unpack_data->rarvm_data.mem = NULL;
 
273
    unpack_data->old_filter_lengths = NULL;
 
274
    unpack_data->PrgStack.array = unpack_data->Filters.array = NULL;
 
275
    unpack_data->PrgStack.num_items = unpack_data->Filters.num_items = 0;
 
276
    unpack_data->unp_crc = 0xffffffff;
 
277
 
 
278
    ppm_constructor(&unpack_data->ppm_data);
 
279
    main_hdr = read_header(fd, MAIN_HEAD);
 
280
    if(!main_hdr) {
 
281
        ppm_destructor(&unpack_data->ppm_data);
 
282
        rar_init_filters(unpack_data);
 
283
        unpack_free_data(unpack_data);
 
284
        free(unpack_data);
 
285
        return UNRAR_ERR;
 
286
    }
 
287
    unrar_dbgmsg("UNRAR: Head CRC: %.4x\n", main_hdr->head_crc);
 
288
    unrar_dbgmsg("UNRAR: Head Type: %.2x\n", main_hdr->head_type);
 
289
    unrar_dbgmsg("UNRAR: Flags: %.4x\n", main_hdr->flags);
 
290
    unrar_dbgmsg("UNRAR: Head Size: %.4x\n", main_hdr->head_size);
 
291
 
 
292
    snprintf(filename,1024,"%s/comments", dirname);
 
293
    if(mkdir(filename,0700)) {
 
294
        unrar_dbgmsg("UNRAR: Unable to create comment temporary directory\n");
 
295
        free(main_hdr);
 
296
        ppm_destructor(&unpack_data->ppm_data);
 
297
        rar_init_filters(unpack_data);
 
298
        unpack_free_data(unpack_data);
 
299
        free(unpack_data);
 
300
        return UNRAR_ERR;
 
301
    }
 
302
    state->comment_dir = strdup(filename);
 
303
    if(!state->comment_dir) {
 
304
        free(main_hdr);
 
305
        ppm_destructor(&unpack_data->ppm_data);
 
306
        rar_init_filters(unpack_data);
 
307
        unpack_free_data(unpack_data);
 
308
        free(unpack_data);
 
309
        return UNRAR_EMEM;
 
310
    }
 
311
 
 
312
    if(main_hdr->head_size < SIZEOF_NEWMHD) {
 
313
        free(main_hdr);
 
314
        ppm_destructor(&unpack_data->ppm_data);
 
315
        rar_init_filters(unpack_data);
 
316
        unpack_free_data(unpack_data);
 
317
        free(unpack_data);
 
318
        free(state->comment_dir);
 
319
        return UNRAR_ERR;
 
320
    }
 
321
 
 
322
    if(main_hdr->flags & MHD_COMMENT) {
 
323
        unrar_comment_header_t *comment_header;
 
324
        unrar_dbgmsg("UNRAR: RAR main comment\n");
 
325
        offset = lseek(fd, 0, SEEK_CUR);
 
326
        unrar_dbgmsg("UNRAR: Offset: %x\n", offset);
 
327
        comment_header = read_header(fd, COMM_HEAD);
 
328
        if(comment_header) {
 
329
            unrar_dbgmsg("UNRAR: Comment type: 0x%.2x\n", comment_header->head_type);
 
330
            unrar_dbgmsg("UNRAR: Head size: 0x%.4x\n", comment_header->head_size);
 
331
            unrar_dbgmsg("UNRAR: UnPack Size: 0x%.4x\n", comment_header->unpack_size);
 
332
            unrar_dbgmsg("UNRAR: UnPack Version: 0x%.2x\n", comment_header->unpack_ver);
 
333
            unrar_dbgmsg("UNRAR: Pack Method: 0x%.2x\n", comment_header->method);
 
334
            snprintf(filename, 1024, "%s/main.cmt", state->comment_dir);
 
335
            ofd = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600);
 
336
            if(ofd < 0) {
 
337
                unrar_dbgmsg("UNRAR: ERROR: Failed to open output file\n");
 
338
                free(comment_header);
 
339
                free(main_hdr);
 
340
                ppm_destructor(&unpack_data->ppm_data);
 
341
                rar_init_filters(unpack_data);
 
342
                unpack_free_data(unpack_data);
 
343
                free(unpack_data);
 
344
                free(state->comment_dir);
 
345
                return UNRAR_ERR;
 
346
            } else {
 
347
                if(comment_header->method == 0x30) {
 
348
                    unrar_dbgmsg("UNRAR: Copying stored comment (not packed)\n");
 
349
                    copy_file_data(fd, ofd, comment_header->unpack_size);
 
350
                } else {
 
351
                    unpack_data->ofd = ofd;
 
352
                    unpack_data->dest_unp_size = comment_header->unpack_size;
 
353
                    unpack_data->pack_size = comment_header->head_size - SIZEOF_COMMHEAD;
 
354
                    retval = rar_unpack(fd, comment_header->unpack_ver, FALSE, unpack_data);
 
355
                    unpack_free_data(unpack_data);
 
356
                }
 
357
                close(ofd);
 
358
            }
 
359
            free(comment_header);
 
360
        }
 
361
        lseek(fd, offset, SEEK_SET);
 
362
    }
 
363
 
 
364
    if(main_hdr->head_size > SIZEOF_NEWMHD) {
 
365
        if(!lseek(fd, main_hdr->head_size - SIZEOF_NEWMHD, SEEK_CUR)) {
 
366
            free(main_hdr);
 
367
            ppm_destructor(&unpack_data->ppm_data);
 
368
            rar_init_filters(unpack_data);
 
369
            unpack_free_data(unpack_data);
 
370
            free(unpack_data);
 
371
            free(state->comment_dir);
 
372
            return UNRAR_ERR;
 
373
        }
 
374
    }
 
375
 
 
376
    state->unpack_data = unpack_data;
 
377
    state->main_hdr = main_hdr;
 
378
    state->metadata_tail = state->metadata = NULL;
 
379
    state->file_count = 1;
 
380
    state->offset = offset;
 
381
    state->fd = fd;
 
382
 
 
383
    return UNRAR_OK;
 
384
}
 
385
 
 
386
int unrar_extract_next_prepare(unrar_state_t *state, const char *dirname)
 
387
{
 
388
        char filename[1024];
 
389
        int ofd;
 
390
        unrar_metadata_t *new_metadata;
 
391
        unpack_data_t *unpack_data;
 
392
 
 
393
 
 
394
    state->file_header = read_block(state->fd, FILE_HEAD);
 
395
    if(!state->file_header)
 
396
        return UNRAR_BREAK; /* end of archive */
 
397
 
 
398
    new_metadata = (unrar_metadata_t *) malloc(sizeof(unrar_metadata_t));
 
399
    if(!new_metadata)
 
400
        return UNRAR_EMEM;
 
401
 
 
402
    new_metadata->pack_size = state->file_header->high_pack_size * 0x100000000 + state->file_header->pack_size;
 
403
    new_metadata->unpack_size = state->file_header->high_unpack_size * 0x100000000 + state->file_header->unpack_size;
 
404
    new_metadata->crc = state->file_header->file_crc;
 
405
    new_metadata->method = state->file_header->method;
 
406
    new_metadata->filename = strdup(state->file_header->filename);
 
407
    if(!new_metadata->filename) {
 
408
        free(new_metadata);
 
409
        return UNRAR_EMEM;
 
410
    }
 
411
    new_metadata->next = NULL;
 
412
    new_metadata->encrypted = FALSE;
 
413
    if(state->metadata_tail == NULL) {
 
414
        state->metadata_tail = state->metadata = new_metadata;
 
415
    } else {
 
416
        state->metadata_tail->next = new_metadata;
 
417
        state->metadata_tail = new_metadata;
 
418
    }
 
419
    if(state->file_header->flags & LHD_COMMENT) {
 
420
        unrar_comment_header_t *comment_header;
 
421
 
 
422
        unrar_dbgmsg("UNRAR: File comment present\n");
 
423
        comment_header = read_header(state->fd, COMM_HEAD);
 
424
        if(comment_header) {
 
425
            unrar_dbgmsg("UNRAR: Comment type: 0x%.2x\n", comment_header->head_type);
 
426
            unrar_dbgmsg("UNRAR: Head size: 0x%.4x\n", comment_header->head_size);
 
427
            unrar_dbgmsg("UNRAR: UnPack Size: 0x%.4x\n", comment_header->unpack_size);
 
428
            unrar_dbgmsg("UNRAR: UnPack Version: 0x%.2x\n", comment_header->unpack_ver);
 
429
            unrar_dbgmsg("UNRAR: Pack Method: 0x%.2x\n", comment_header->method);
 
430
 
 
431
            if((comment_header->unpack_ver < 15) || (comment_header->unpack_ver > 29) || (comment_header->method > 0x30)) {
 
432
                unrar_dbgmsg("UNRAR: Can't process file comment - skipping\n");
 
433
            } else {
 
434
                snprintf(filename, 1024, "%s/%lu.cmt", state->comment_dir, state->file_count);
 
435
                ofd = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0600);
 
436
                if(ofd < 0) {
 
437
                    free(comment_header);
 
438
                    unrar_dbgmsg("UNRAR: ERROR: Failed to open output file\n");
 
439
                } else {
 
440
                    unrar_dbgmsg("UNRAR: Copying file comment (not packed)\n");
 
441
                    copy_file_data(state->fd, ofd, comment_header->unpack_size);
 
442
                    close(ofd);
 
443
                }
 
444
            }
 
445
            free(comment_header);
 
446
        }
 
447
    }
 
448
 
 
449
    return UNRAR_OK;
 
450
}
 
451
 
 
452
int unrar_extract_next(unrar_state_t *state, const char *dirname)
 
453
{
 
454
        int ofd;
 
455
        int retval;
 
456
        unpack_data_t *unpack_data;
 
457
 
 
458
 
 
459
    if(lseek(state->fd, state->file_header->start_offset+state->file_header->head_size, SEEK_SET) != state->file_header->start_offset+state->file_header->head_size) {
 
460
        unrar_dbgmsg("UNRAR: Seek failed: %ld\n", state->offset+state->file_header->head_size);
 
461
        free(state->file_header->filename);
 
462
        free(state->file_header);
 
463
        return UNRAR_ERR;
 
464
    }
 
465
 
 
466
    if(state->file_header->flags & LHD_PASSWORD) {
 
467
        unrar_dbgmsg("UNRAR: PASSWORDed file: %s\n", state->file_header->filename);
 
468
        state->metadata_tail->encrypted = TRUE;
 
469
    } else if(state->file_header->flags & (LHD_SPLIT_BEFORE | LHD_SPLIT_AFTER)) {
 
470
        unrar_dbgmsg("UNRAR: Skipping split file\n");
 
471
 
 
472
    } else if((state->main_hdr->flags & MHD_VOLUME) && (state->main_hdr->flags & MHD_SOLID)) {
 
473
        unrar_dbgmsg("UNRAR: Skipping file inside multi-volume solid archive\n");
 
474
 
 
475
    } else {
 
476
        snprintf(state->filename, 1024, "%s/%lu.ura", dirname, state->file_count);
 
477
        ofd = open(state->filename, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0600);
 
478
        if(ofd < 0) {
 
479
            free(state->file_header->filename);
 
480
            free(state->file_header);
 
481
            unrar_dbgmsg("UNRAR: ERROR: Failed to open output file\n");
 
482
            return UNRAR_ERR;
 
483
        }
 
484
        unpack_data = (unpack_data_t *) state->unpack_data;
 
485
        state->ofd = unpack_data->ofd = ofd;
 
486
        if(state->file_header->method == 0x30) {
 
487
            unrar_dbgmsg("UNRAR: Copying stored file (not packed)\n");
 
488
            copy_file_data(state->fd, ofd, state->file_header->pack_size);
 
489
        } else {
 
490
            unpack_data->dest_unp_size = state->file_header->unpack_size;
 
491
            unpack_data->pack_size = state->file_header->pack_size;
 
492
            if(state->file_header->unpack_ver <= 15) {
 
493
                retval = rar_unpack(state->fd, 15, (state->file_count>1) && ((state->main_hdr->flags&MHD_SOLID)!=0), unpack_data);
 
494
            } else {
 
495
                if((state->file_count == 1) && (state->file_header->flags & LHD_SOLID)) {
 
496
                    unrar_dbgmsg("UNRAR: Bad header. First file can't be SOLID.\n");
 
497
                    unrar_dbgmsg("UNRAR: Clearing flag and continuing.\n");
 
498
                    state->file_header->flags -= LHD_SOLID;
 
499
                }
 
500
                retval = rar_unpack(state->fd, state->file_header->unpack_ver, state->file_header->flags & LHD_SOLID, unpack_data);
 
501
            }
 
502
            unrar_dbgmsg("UNRAR: Expected File CRC: 0x%x\n", state->file_header->file_crc);
 
503
            unrar_dbgmsg("UNRAR: Computed File CRC: 0x%x\n", unpack_data->unp_crc^0xffffffff);
 
504
            if(unpack_data->unp_crc != 0xffffffff) {
 
505
                if(state->file_header->file_crc != (unpack_data->unp_crc^0xffffffff)) {
 
506
                    unrar_dbgmsg("UNRAR: RAR CRC error. If the file is not corrupted, please report at http://bugs.clamav.net/\n");
 
507
                }
 
508
            }
 
509
            if(!retval) {
 
510
                unrar_dbgmsg("UNRAR: Corrupt file detected\n");
 
511
                if(state->file_header->flags & LHD_SOLID) {
 
512
                    unrar_dbgmsg("UNRAR: SOLID archive, can't continue\n");
 
513
                    free(state->file_header->filename);
 
514
                    free(state->file_header);
 
515
                    return UNRAR_ERR;
 
516
                }
 
517
            }
 
518
        }
 
519
    }
 
520
 
 
521
    if(lseek(state->fd, state->file_header->next_offset, SEEK_SET) != state->file_header->next_offset) {
 
522
        unrar_dbgmsg("UNRAR: ERROR: seek failed: %ld\n", state->file_header->next_offset);
 
523
        free(state->file_header->filename);
 
524
        free(state->file_header);
 
525
        return UNRAR_ERR;
 
526
    }
 
527
 
 
528
    free(state->file_header->filename);
 
529
    free(state->file_header);
 
530
    unpack_free_data(state->unpack_data);
 
531
    state->file_count++;
 
532
    return UNRAR_OK;
 
533
}
 
534
 
 
535
void unrar_close(unrar_state_t *state)
 
536
{
 
537
        unpack_data_t *unpack_data = state->unpack_data;
 
538
 
 
539
    ppm_destructor(&unpack_data->ppm_data);
 
540
    free(state->main_hdr);
 
541
    rar_init_filters(state->unpack_data);
 
542
    unpack_free_data(state->unpack_data);
 
543
    free(state->unpack_data);
 
544
    free(state->comment_dir);
 
545
}