root/trunk/contrib/extractor/libmpq/mpq.cpp @ 149

Revision 149, 17.0 kB (checked in by yumileroy, 17 years ago)

[svn] *Implement new player conditions CONDITION_NO_AURA, CONDITION_ACTIVE_EVENT
* Default behaviour of pets for creatures changed to REACT_DEFENSIVE
* Disallowed sending wrapped items as COD
* Prevent loading and saving single target auras for pet in same way as already implemented for player
* Correctly limit use some flask types to zones.
* Fixed extracting common.MPQ under *nix
* Many small xleanups and fixes.
** mangos merge rev.

TEST REV so be careful of creepy crawly bugs!

Original author: KingPin?
Date: 2008-11-02 16:53:46-06:00

Line 
1/*
2 *  mpq.c -- functions for developers using libmpq.
3 *
4 *  Copyright (C) 2003 Maik Broemme <mbroemme@plusserver.de>
5 *
6 *  This program is free software; you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation; either version 2 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program; if not, write to the Free Software
18 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 *
20 *  $Id: mpq.c,v 1.6 2004/02/12 00:49:00 mbroemme Exp $
21 */
22#define _CRT_SECURE_NO_DEPRECATE
23
24#include <stdlib.h>
25#include <sys/stat.h>
26//#include <unistd.h>
27//#include <io.h>
28#include <fcntl.h>
29#include <stdio.h>
30#include <string.h>
31#include "mpq.h"
32#include "common.h"
33
34/*
35 *  This function returns version information.
36 *  format: MAJOR.MINOR.PATCH
37 */
38char *libmpq_version() {
39        static char version[10];
40        sprintf(version, "%i.%i.%i", LIBMPQ_MAJOR_VERSION, LIBMPQ_MINOR_VERSION, LIBMPQ_PATCH_VERSION);
41        return version;
42}
43
44/*
45 *  This function reads a file and verify if it is a legit MPQ archive
46 *  or not. Then it fills the mpq_header structure and reads the hash
47 *  table.
48 */
49int libmpq_archive_open(mpq_archive *mpq_a, unsigned char *mpq_filename) {
50        int fd = 0;
51        int rb = 0;
52        int ncnt = FALSE;
53        struct stat fileinfo;
54
55        /* allocate memory */
56        mpq_a->mpq_l = (mpq_list *)malloc(sizeof(mpq_list));
57        memset(mpq_a->mpq_l, 0, sizeof(mpq_list));
58        mpq_a->header = (mpq_header *)malloc(sizeof(mpq_header));
59        memset(mpq_a->header, 0, sizeof(mpq_header));
60
61        /* Check if file exists and is readable */
62        fd = _open((char *)mpq_filename, O_RDONLY | O_BINARY | O_LARGEFILE);
63        if (fd == LIBMPQ_EFILE) {
64                return LIBMPQ_EFILE;
65        }
66
67        /* fill the structures with informations */
68        strcpy((char *)mpq_a->filename, (char *)mpq_filename);
69        libmpq_init_buffer(mpq_a);
70        mpq_a->fd               = fd;
71        mpq_a->header->id       = 0;
72        mpq_a->maxblockindex    = 0;
73        mpq_a->mpq_l->mpq_files = NULL;
74
75    mpq_a->mpqpos = 0; //k
76
77        while (!ncnt) {
78                mpq_a->header->id = 0;
79                #ifdef WIN32
80                        _lseeki64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
81                #else
82                        lseek64(mpq_a->fd, mpq_a->mpqpos, SEEK_SET);
83                #endif
84                rb = _read(mpq_a->fd, mpq_a->header, sizeof(mpq_header));
85
86                /* if different number of bytes read, break the loop */
87                if (rb != sizeof(mpq_header)) {
88                        return LIBMPQ_EFILE_FORMAT;
89                }
90
91                /* special offset for protected MPQs */
92                if (mpq_a->header->offset == LIBMPQ_HEADER_W3M) {
93                        mpq_a->flags |= LIBMPQ_FLAG_PROTECTED;
94                        mpq_a->header->offset = sizeof(mpq_header);
95                }
96
97                /* if valid signature has been found, break the loop */
98        if (mpq_a->header->id == LIBMPQ_ID_MPQ) {
99            ncnt = true;
100        }
101        /*if (mpq_a->header->id == LIBMPQ_ID_MPQ &&
102                    mpq_a->header->offset == sizeof(mpq_header) &&
103                    mpq_a->header->hashtablepos < mpq_a->header->archivesize &&
104                    mpq_a->header->blocktablepos < mpq_a->header->archivesize) {
105                        ncnt = TRUE;
106                }*/
107
108                /* move to the next possible offset */
109                if (!ncnt) {
110                        mpq_a->mpqpos += 0x200;
111                }
112        }
113
114        /* get the right positions of the hash table and the block table. */
115        mpq_a->blocksize = (0x200 << mpq_a->header->blocksize);
116        fstat(mpq_a->fd, &fileinfo);
117
118        /* Normal MPQs must have position of */
119        /*if (mpq_a->header->hashtablepos + mpq_a->mpqpos < fileinfo.st_size &&
120            mpq_a->header->blocktablepos + mpq_a->mpqpos < fileinfo.st_size) {
121                mpq_a->header->hashtablepos  += mpq_a->mpqpos;
122                mpq_a->header->blocktablepos += mpq_a->mpqpos;
123        } else {
124                return LIBMPQ_EFILE_FORMAT;
125        }*/
126
127        /* Try to read and decrypt the hashtable */
128        if (libmpq_read_hashtable(mpq_a) != 0) {
129                return LIBMPQ_EHASHTABLE;
130        }
131
132        /* Try to read and decrypt the blocktable */
133        if (libmpq_read_blocktable(mpq_a) != 0) {
134                return LIBMPQ_EBLOCKTABLE;
135        }
136
137        return LIBMPQ_TOOLS_SUCCESS;
138}
139
140/*
141 *  This function closes the file descriptor opened by
142 *  mpq_open_archive(); and frees the decryption buffer.
143 */
144int libmpq_archive_close(mpq_archive *mpq_a) {
145        memset(mpq_a->buf, 0, sizeof(mpq_a->buf));
146
147        /* free the allocated memory. */
148        free(mpq_a->header);
149        free(mpq_a->mpq_l);
150
151        /* Check if file descriptor is valid. */
152        if ((_close(mpq_a->fd)) == LIBMPQ_EFILE) {
153                return LIBMPQ_EFILE;
154        }
155
156        return LIBMPQ_TOOLS_SUCCESS;
157}
158
159/*
160 * This function returns the value for the given infotype.
161 * If an error occurs something < 0 is returned.
162 */
163int libmpq_archive_info(mpq_archive *mpq_a, unsigned int infotype) {
164        unsigned int filecount = 0;
165        unsigned int fsize = 0;
166        unsigned int csize = 0;
167        mpq_block *mpq_b_end = mpq_a->blocktable + mpq_a->header->blocktablesize;
168        mpq_block *mpq_b = NULL;
169
170        switch (infotype) {
171                case LIBMPQ_MPQ_ARCHIVE_SIZE:
172                        return mpq_a->header->archivesize;
173                case LIBMPQ_MPQ_HASHTABLE_SIZE:
174                        return mpq_a->header->hashtablesize;
175                case LIBMPQ_MPQ_BLOCKTABLE_SIZE:
176                        return mpq_a->header->blocktablesize;
177                case LIBMPQ_MPQ_BLOCKSIZE:
178                        return mpq_a->blocksize;
179                case LIBMPQ_MPQ_NUMFILES:
180                        for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
181                                filecount++;
182                        }
183                        return filecount;
184                case LIBMPQ_MPQ_COMPRESSED_SIZE:
185                        for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
186                                csize += mpq_b->csize;
187                        }
188                        return csize;
189                case LIBMPQ_MPQ_UNCOMPRESSED_SIZE:
190                        for (mpq_b = mpq_a->blocktable; mpq_b < mpq_b_end; mpq_b++) {
191                                fsize += mpq_b->fsize;
192                        }
193                        return fsize;
194                default:
195                        return LIBMPQ_TOOLS_SUCCESS;
196        }
197}
198
199/*
200 * This function returns some useful file information.
201 */
202int libmpq_file_info(mpq_archive *mpq_a, unsigned int infotype, const int number) {
203        int blockindex = number; //-1;
204        int i = 0;
205        mpq_block *mpq_b = NULL;
206        mpq_hash *mpq_h = NULL;
207
208        /* check if given number is not out of range */
209        if (number < 1 || number > mpq_a->header->blocktablesize) {
210                return LIBMPQ_EINV_RANGE;
211        }
212
213        /* search for correct hashtable */
214        /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
215                if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
216                        blockindex = (mpq_a->hashtable[i]).blockindex;
217                        mpq_h = &(mpq_a->hashtable[i]);
218                        break;
219                }
220        }*/
221
222        /* check if file was found */
223        /*if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
224                return LIBMPQ_EFILE_NOT_FOUND;
225        }*/
226
227        /* check if sizes are correct */
228        mpq_b = mpq_a->blocktable + blockindex;
229        if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
230                return LIBMPQ_EFILE_CORRUPT;
231        }
232
233        /* check if file exists */
234        if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
235                return LIBMPQ_EFILE_NOT_FOUND;
236        }
237
238        switch (infotype) {
239                case LIBMPQ_FILE_COMPRESSED_SIZE:
240                        return mpq_b->csize;
241                case LIBMPQ_FILE_UNCOMPRESSED_SIZE:
242                        return mpq_b->fsize;
243                case LIBMPQ_FILE_COMPRESSION_TYPE:
244                        if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_PKWARE) {
245                                return LIBMPQ_FILE_COMPRESS_PKWARE;
246                        }
247                        if (mpq_b->flags & LIBMPQ_FILE_COMPRESS_MULTI) {
248                                return LIBMPQ_FILE_COMPRESS_MULTI;
249                        }
250                default:
251                        return LIBMPQ_TOOLS_SUCCESS;
252        }
253}
254
255/*
256 * This function searches the listfile for the filename.
257 * On success it returns the filename, otherwiese a name
258 * like file000001.xxx and if number is out of range it
259 * returns NULL.
260 */
261char *libmpq_file_name(mpq_archive *mpq_a, const int number) {
262        static char tempfile[PATH_MAX];
263
264        /* check if we are in the range of available files. */
265        if (number > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || number < 1) {
266                return NULL;
267        }
268
269        /* this is safe because we built a fallback filelist, if something was wrong. */
270        sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[number - 1], number);
271
272        return tempfile;
273}
274
275/*
276 *  This function returns the number to the given
277 *  filename.
278 */
279int libmpq_file_number(mpq_archive *mpq_a, const char *name) {
280        int i;
281        char tempfile[PATH_MAX];
282
283        for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
284                sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i + 1);
285                if (strncmp(tempfile, name, strlen(name)) == 0) {
286
287                        /* if file found return the number */
288                        return i + 1;
289                }
290        }
291
292        /* if no matching entry found return LIBMPQ_EFILE_NOT_FOUND */
293        return LIBMPQ_EFILE_NOT_FOUND;
294}
295
296/*
297 *  This function verifies if a given file (by number
298 *  or name) is in the opened mpq archive. On success
299 *  it returns 0, otherwise LIBMPQ_EFILE_NOT_FOUND.
300 */
301int libmpq_file_check(mpq_archive *mpq_a, void *file, int type) {
302        int found = 0;
303        int i;
304        char tempfile[PATH_MAX];
305
306        switch (type) {
307                case LIBMPQ_FILE_TYPE_INT:
308
309                        /* check if we are in the range of available files. */
310                        if (*(int *)file > libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES) || *(int *)file < 1) {
311                                return LIBMPQ_EFILE_NOT_FOUND;
312                        } else {
313                                return LIBMPQ_TOOLS_SUCCESS;
314                        }
315                case LIBMPQ_FILE_TYPE_CHAR:
316                        for (i = 0; mpq_a->mpq_l->mpq_files[i]; i++) {
317                                sprintf(tempfile, (char *)mpq_a->mpq_l->mpq_files[i], i);
318                                if (strncmp(tempfile, (char *)file, strlen((char *)file)) == 0) {
319
320                                        /* if file found break */
321                                        found = 1;
322                                        break;
323                                }
324                        }
325
326                        /* if a file was found return 0 */
327                        if (found == 1) {
328                                return LIBMPQ_TOOLS_SUCCESS;
329                        } else {
330                                return LIBMPQ_EFILE_NOT_FOUND;
331                        }
332                default:
333                        return LIBMPQ_TOOLS_SUCCESS;
334        }
335}
336
337/*
338 *  This function extracts a file from a MPQ archive
339 *  by the given number.
340 */
341int libmpq_file_extract(mpq_archive *mpq_a, const int number, const char *filename) {
342        int blockindex = number; //-1;
343        int fd = 0;
344        int i = 0;
345        char buffer[0x1000];
346        //char tempfile[PATH_MAX];
347        unsigned int transferred = 1;
348        mpq_file *mpq_f = NULL;
349        mpq_block *mpq_b = NULL;
350        mpq_hash *mpq_h = NULL;
351
352/*      if (number < 1 || number > mpq_a->header->blocktablesize) {
353                return LIBMPQ_EINV_RANGE;
354        }*/
355/*
356        sprintf(tempfile, libmpq_file_name(mpq_a, number));
357*/
358        /* check if mpq_f->filename could be written here. */
359        fd = _open(filename, O_RDWR|O_CREAT|O_TRUNC, 0644);
360        if (fd == LIBMPQ_EFILE) {
361                return LIBMPQ_EFILE;
362        }
363
364        /* search for correct hashtable */
365        /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
366                if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
367                        blockindex = (mpq_a->hashtable[i]).blockindex;
368                        mpq_h = &(mpq_a->hashtable[i]);
369                        break;
370                }
371        }*/
372
373        /* check if file was found */
374        if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
375                return LIBMPQ_EFILE_NOT_FOUND;
376        }
377
378        /* check if sizes are correct */
379        mpq_b = mpq_a->blocktable + blockindex;
380        if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
381                return LIBMPQ_EFILE_CORRUPT;
382        }
383
384        /* check if file exists */
385        if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
386                return LIBMPQ_EFILE_NOT_FOUND;
387        }
388
389        /* allocate memory for file structure */
390        mpq_f = (mpq_file *)malloc(sizeof(mpq_file));
391        if (!mpq_f) {
392                return LIBMPQ_EALLOCMEM;
393        }
394
395        /* initialize file structure */
396        memset(mpq_f, 0, sizeof(mpq_file));
397        mpq_f->fd             = fd;
398        mpq_f->mpq_b          = mpq_b;
399        mpq_f->nblocks        = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
400        mpq_f->mpq_h          = mpq_h;
401        mpq_f->accessed       = FALSE;
402        mpq_f->blockposloaded = FALSE;
403        sprintf((char *)mpq_f->filename, filename);
404
405        /* allocate buffers for decompression. */
406        if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
407
408                /*
409                 *  Allocate buffer for block positions. At the begin of file are stored
410                 *  unsigned ints holding positions of each block relative from begin of
411                 *  file in the archive.
412                 */
413                if ((mpq_f->blockpos = (unsigned int *)malloc(sizeof(int) * mpq_f->nblocks + 1)) == NULL) {
414                        return LIBMPQ_EALLOCMEM;
415                }
416        }
417
418        while (transferred > 0) {
419                transferred = libmpq_file_read_file(mpq_a, mpq_f, mpq_f->filepos, buffer, sizeof(buffer));
420                if (transferred == 0) {
421                        break;
422                } else {
423                        mpq_f->accessed  = TRUE;
424                        mpq_f->filepos  += transferred;
425                }
426
427                transferred = _write(mpq_f->fd, buffer, transferred);
428                if (transferred == 0) {
429                        break;
430                }
431        }
432
433        _close(fd);
434
435        /* freeing the file structure */
436        free(mpq_f);
437        return LIBMPQ_TOOLS_SUCCESS;
438}
439
440/*
441 *  This function tries to get the filenames for the hashes. It uses
442 *  an internal listfile database and gets the correct listfile from
443 *  some specific archive informations.
444 */
445
446int libmpq_listfile_open(mpq_archive *mpq_a, char file[PATH_MAX]) {
447        FILE *fp;
448        //char **filelist;
449        int i = 0;
450        //int fl_count;
451        //int fl_size;
452        int fl_count_fb;
453        int fl_size_fb;
454        int result = LIBMPQ_TOOLS_SUCCESS;
455        struct stat statbuf;
456
457        /* get file status */
458        if (stat(file, &statbuf) < 0) {
459                result = LIBMPQ_CONF_EFILE_NOT_FOUND;
460        }
461
462        /* check if file is a filename or directory */
463        /*if (S_ISDIR(statbuf.st_mode)) {
464
465                // allocate memory for the file list
466                filelist = (char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
467                fl_count = 0;
468                fl_size = LIBMPQ_CONF_FL_INCREMENT;
469
470                // check if it is a valid listfile
471                if (libmpq_detect_listfile_rec(file, &filelist, &fl_count, &fl_size)) {
472                        filelist == NULL;
473                }
474
475                filelist[fl_count] = NULL;
476
477                // return if no listfile was found
478                if (filelist == NULL) {
479                        result = LIBMPQ_CONF_EFILE_NOT_FOUND;
480                }
481
482                for (i = 0; filelist[i]; i++) {
483                        if ((fp = fopen(filelist[i], "r")) != NULL ) {
484                                result = libmpq_read_listfile(mpq_a, fp);
485                                fclose(fp);
486                        }
487                }
488
489                // freeing the listfile struct
490                libmpq_free_listfile(filelist);
491        }*/
492
493        /* if file is a regular file use it */
494        //if (S_ISREG(statbuf.st_mode)) {
495
496                /* if specific listfile was forced. */
497                if ((fp = fopen(file, "r")) != NULL ) {
498                        result = libmpq_read_listfile(mpq_a, fp);
499                        fclose(fp);
500                } else {
501                        result = LIBMPQ_CONF_EFILE_OPEN;
502                }
503        //}
504
505        /* if error occured we need to create a fallback filelist. */
506        if (mpq_a->mpq_l->mpq_files == NULL) {
507
508                /* allocate memory for the file list */
509                mpq_a->mpq_l->mpq_files = (unsigned char **)malloc(LIBMPQ_CONF_FL_INCREMENT * sizeof(char *));
510                fl_count_fb = 0;
511                fl_size_fb = LIBMPQ_CONF_FL_INCREMENT;
512
513                for (i = 0; i < libmpq_archive_info(mpq_a, LIBMPQ_MPQ_NUMFILES); i++) {
514
515                        /* set the next filelist entry to a copy of the file */
516                        mpq_a->mpq_l->mpq_files[fl_count_fb++] = (unsigned char *)_strdup("file%06lu.xxx");
517
518                        /* increase the array size */
519                        if (fl_count_fb == fl_size_fb) {
520                                mpq_a->mpq_l->mpq_files = (unsigned char **)realloc(mpq_a->mpq_l->mpq_files, (fl_size_fb + LIBMPQ_CONF_FL_INCREMENT) * sizeof(char *));
521                                fl_size_fb += LIBMPQ_CONF_FL_INCREMENT;
522                        }
523                }
524                mpq_a->mpq_l->mpq_files[fl_count_fb] = NULL;
525
526                /* if no error occurs and no listfile was assigned, we think there was no matching listfile. */
527                if (result == 0) {
528                        result = LIBMPQ_CONF_EFILE_NOT_FOUND;
529                }
530        }
531
532        return result;
533}
534
535/*
536 *  This function frees the allocated memory for the listfile.
537 */
538int libmpq_listfile_close(mpq_archive *mpq_a) {
539        int i = 0;
540
541        /* safety check if we really have a filelist. */
542        if (mpq_a->mpq_l->mpq_files != NULL) {
543                /* freeing the filelist */
544                while (mpq_a->mpq_l->mpq_files[i]) {
545                        free(mpq_a->mpq_l->mpq_files[i++]);
546                }
547                free(mpq_a->mpq_l->mpq_files);
548        }
549    return 0;
550}
551
552int libmpq_file_getdata(mpq_archive *mpq_a, mpq_hash mpq_h, const int number, unsigned char *dest) {
553        int blockindex = number; //-1;
554        int i = 0;
555        mpq_file *mpq_f = NULL;
556        mpq_block *mpq_b = NULL;
557        int success = 0;
558
559        /*if (number < 1 || number > mpq_a->header->blocktablesize) {
560                return LIBMPQ_EINV_RANGE;
561        }*/
562
563        /* search for correct hashtable */
564        /*for (i = 0; i < mpq_a->header->hashtablesize; i++) {
565                if ((number - 1) == (mpq_a->hashtable[i]).blockindex) {
566                        blockindex = (mpq_a->hashtable[i]).blockindex;
567                        mpq_h = &(mpq_a->hashtable[i]);
568                        break;
569                }
570        }*/
571
572        /* check if file was found */
573        if (blockindex == -1 || blockindex > mpq_a->header->blocktablesize) {
574                return LIBMPQ_EFILE_NOT_FOUND;
575        }
576
577        /* check if sizes are correct */
578        mpq_b = mpq_a->blocktable + blockindex;
579        if (mpq_b->filepos > (mpq_a->header->archivesize + mpq_a->mpqpos) || mpq_b->csize > mpq_a->header->archivesize) {
580                return LIBMPQ_EFILE_CORRUPT;
581        }
582
583        /* check if file exists */
584        if ((mpq_b->flags & LIBMPQ_FILE_EXISTS) == 0) {
585                return LIBMPQ_EFILE_NOT_FOUND;
586        }
587
588        /* allocate memory for file structure */
589        mpq_f = (mpq_file*)malloc(sizeof(mpq_file));
590        if (!mpq_f) {
591                return LIBMPQ_EALLOCMEM;
592        }
593
594        /* initialize file structure */
595        memset(mpq_f, 0, sizeof(mpq_file));
596        mpq_f->mpq_b          = mpq_b;
597        mpq_f->nblocks        = (mpq_f->mpq_b->fsize + mpq_a->blocksize - 1) / mpq_a->blocksize;
598        mpq_f->mpq_h          = &mpq_h;
599        mpq_f->accessed       = FALSE;
600        mpq_f->blockposloaded = FALSE;
601
602        /* allocate buffers for decompression. */
603        if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
604
605                /*
606                 *  Allocate buffer for block positions. At the begin of file are stored
607                 *  unsigned ints holding positions of each block relative from begin of
608                 *  file in the archive.
609                 */
610                if ((mpq_f->blockpos = (unsigned int*)malloc(sizeof(int) * (mpq_f->nblocks + 1))) == NULL) {
611                        return LIBMPQ_EALLOCMEM;
612                }
613        }
614
615    if(libmpq_file_read_file(mpq_a, mpq_f, 0, (char*)dest, mpq_b->fsize) == mpq_b->fsize)
616        success = 1;
617
618    if (mpq_f->mpq_b->flags & LIBMPQ_FILE_COMPRESSED) {
619        // Free buffer for block positions
620               
621               free(mpq_f->blockpos);
622        }
623        /* freeing the file structure */
624        free(mpq_f);
625        return success?LIBMPQ_TOOLS_SUCCESS:LIBMPQ_EFILE_CORRUPT;
626}
Note: See TracBrowser for help on using the browser.