diff options
| author | Pixel <pixel@nobis-crew.org> | 2009-08-05 18:24:59 -0700 | 
|---|---|---|
| committer | Pixel <pixel@nobis-crew.org> | 2009-08-05 18:24:59 -0700 | 
| commit | 6b5b44074fd6bdbbeb59f8d006fb88e0230cf1ef (patch) | |
| tree | c3559f4579a0ca63b41b766dfeb68f62360a97cc | |
| parent | c579f3458775ca45bd86dcb9b8ef09e7d2a03bdc (diff) | |
Cleaning up and sanityzing the ioctl subsystem.
| -rw-r--r-- | int-bios.h | 13 | ||||
| -rw-r--r-- | mpq-bios.c | 144 | ||||
| -rw-r--r-- | mpq-bios.h | 15 | ||||
| -rw-r--r-- | mpq-errors.c | 2 | ||||
| -rw-r--r-- | mpq-errors.h | 2 | ||||
| -rw-r--r-- | mpq-file.c | 11 | 
6 files changed, 130 insertions, 57 deletions
| diff --git a/int-bios.h b/int-bios.h deleted file mode 100644 index 2c1c4ee..0000000 --- a/int-bios.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef __INT_BIOS_H__ -#define __INT_BIOS_H__ - -#include "mpq-bios.h" - -/* - * Internal BIOS functions. - */ - -int __mpqlib_seek(struct mpq_archive_t *, uint64_t); -int __mpqlib_read(struct mpq_archive_t *, void *, uint32_t); - -#endif @@ -21,12 +21,12 @@  #include <fcntl.h>  #include <stdlib.h>  #include <string.h> +#include <stdarg.h>  #include "mpq-crypto.h"  #include "mpq-bios.h"  #include "mpq-errors.h"  #include "mpq-misc.h" -#include "int-bios.h"  #include "errors.h"  #ifndef MAX @@ -213,6 +213,12 @@ static int read_data(struct mpq_archive_t * mpq_a, void * buf, size_t l) {      return 1;  } +static int write_data(struct mpq_archive_t * mpq_a, const void * buf, size_t l) { +    if (write(mpq_a->fd, buf, l) != l) +        return 0; +    return 1; +} +  void mpqlib_init() {      __mpqlib_init_cryptography();  } @@ -437,12 +443,12 @@ static hash_t * mpqlib_locate_hash_entry(struct mpq_archive_t * mpq_a, uint32_t      return NULL;  } -static hash_t * mpqlib_find_free_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uint32_t hA, uint32_t hB, uint32_t language, uint32_t platform) { +int mpqlib_add_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uint32_t hA, uint32_t hB, uint16_t language, uint16_t platform, int entry) {      uint32_t i;      if (!mpq_a->for_write) {          __mpqlib_errno = MPQLIB_ERROR_READONLY; -        return NULL; +        return -1;      }      /* The hash table is a true one, pre-built. We can access it as-it, speeding up the searches drastically. */ @@ -453,20 +459,26 @@ static hash_t * mpqlib_find_free_hash_entry_by_hash(struct mpq_archive_t * mpq_a              (mpq_a->hashs[i].platform == platform)) {              /* Full collision ?! */              __mpqlib_errno = MPQLIB_ERROR_UNKNOWN; -            return NULL; +            return -1; +        } +        if (mpq_a->hashs[i].file_block_index == 0xffffffff) { +            mpq_a->hashs[i].file_path_hasha = hA; +            mpq_a->hashs[i].file_path_hashb = hB; +            mpq_a->hashs[i].language = language; +            mpq_a->hashs[i].platform = platform; +            mpq_a->hashs[i].file_block_index = entry; +            return 0;          } -        if (mpq_a->hashs[i].file_block_index == 0xffffffff) -            return mpq_a->hashs + i;      }      __mpqlib_errno = MPQLIB_ERROR_TOO_MANY_FILES; -    return NULL;     +    return -1;  } -static hash_t * mpqlib_find_free_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * name, uint32_t language, uint32_t platform) { +int mpqlib_add_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * name, uint16_t language, uint16_t platform, int entry) {      if (!mpq_a->for_write) {          __mpqlib_errno = MPQLIB_ERROR_READONLY; -        return NULL; +        return -1;      }      uint32_t h, hA, hB; @@ -475,10 +487,10 @@ static hash_t * mpqlib_find_free_hash_entry_by_name(struct mpq_archive_t * mpq_a      hA = mpqlib_hashA_filename(name);      hB = mpqlib_hashB_filename(name); -    return mpqlib_find_free_hash_entry_by_hash(mpq_a, h, hA, hB, language, platform); +    return mpqlib_add_hash_entry_by_hash(mpq_a, h, hA, hB, language, platform, entry);  } -int mpqlib_find_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * name, uint32_t language, uint32_t platform) { +int mpqlib_find_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * name, uint16_t language, uint16_t platform) {      uint32_t h, hA, hB;      h = mpqlib_hash_filename(name); @@ -487,8 +499,8 @@ int mpqlib_find_hash_entry_by_name(struct mpq_archive_t * mpq_a, const char * na      return mpqlib_find_hash_entry_by_hash(mpq_a, h, hA, hB, language, platform);  } -     -int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uint32_t hA, uint32_t hB, uint32_t language, uint32_t platform) { + +int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uint32_t hA, uint32_t hB, uint16_t language, uint16_t platform) {      hash_t * hash = mpqlib_locate_hash_entry(mpq_a, h, hA, hB, language, platform);      if (hash) { @@ -497,53 +509,115 @@ int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t * mpq_a, uint32_t h, uin      return -1;  } -int __mpqlib_seek(struct mpq_archive_t * mpq_a, uint64_t off) { -    if (lseek64(mpq_a->fd, off, SEEK_SET) != off) -        return 0; -    return 1; -} - -int __mpqlib_read(struct mpq_archive_t * mpq_a, void * buffer, uint32_t size) { -    return read_data(mpq_a, buffer, size); -} - -uint64_t mpqlib_ioctl(struct mpq_archive_t * mpq_a, enum mpqlib_ioctl_t command, int entry) { +uint64_t mpqlib_ioctl(struct mpq_archive_t * mpq_a, enum mpqlib_ioctl_t command, ...) {      __mpqlib_errno = MPQLIB_ERROR_NO_ERROR; +    int r = 0; +    uint32_t u32; +    uint64_t u64; +    int entry; +    void * buffer; +    va_list ap; +    va_start(ap, command);      switch(command) {      case MPQLIB_IOCTL_NO_ACTION: -        return 0; +        break; +    case MPQLIB_IOCTL_SEEK: +        u64 = va_arg(ap, uint64_t); +        if (lseek64(mpq_a->fd, u64, SEEK_SET) != u64) { +            r = -1; +            __mpqlib_errno = MPQLIB_ERROR_SEEK; +        } +        break; +    case MPQLIB_IOCTL_READ: +        buffer = va_arg(ap, void *); +        u32 = va_arg(ap, uint32_t); +        r = read_data(mpq_a, buffer, u32) ? 0 : -1; +        if (r == -1) +            __mpqlib_errno = MPQLIB_ERROR_READ; +        break; +    case MPQLIB_IOCTL_WRITE: +        if (!mpq_a->for_write) { +            __mpqlib_errno = MPQLIB_ERROR_READONLY; +            r = -1; +            break; +        } +        buffer = va_arg(ap, void *); +        u32 = va_arg(ap, uint32_t); +        r = write_data(mpq_a, buffer, u32) ? 0 : -1; +        if (r == -1) +            __mpqlib_errno = MPQLIB_ERROR_WRITE; +        break;      case MPQLIB_IOCTL_GET_FORMAT_VERSION: -        return mpq_a->format_version; +        r = mpq_a->format_version; +        break;      case MPQLIB_IOCTL_GET_SECTOR_SIZE: -        return mpq_a->sector_size; +        r = mpq_a->sector_size; +        break; +    case MPQLIB_IOCTL_SET_BLOCK_OFFSET: +    case MPQLIB_IOCTL_SET_BLOCK_SIZE: +    case MPQLIB_IOCTL_SET_FILE_SIZE: +    case MPQLIB_IOCTL_SET_FLAGS: +        if (!mpq_a->for_write) { +            __mpqlib_errno = MPQLIB_ERROR_READONLY; +            r = -1; +            break; +        }      case MPQLIB_IOCTL_ENTRY_EXISTS:      case MPQLIB_IOCTL_GET_BLOCK_OFFSET:      case MPQLIB_IOCTL_GET_BLOCK_SIZE:      case MPQLIB_IOCTL_GET_FILE_SIZE:      case MPQLIB_IOCTL_GET_FLAGS: +        entry = va_arg(ap, int);          if ((entry >= mpq_a->block_table_entries) || (entry < 0)) {              __mpqlib_errno = MPQLIB_ERROR_IOCTL_INVALID_ENTRY; -            return -1; +            r = -1; +            break;          }          switch (command) {  	case MPQLIB_IOCTL_ENTRY_EXISTS: -	    return 0; +	    break;          case MPQLIB_IOCTL_GET_BLOCK_OFFSET: -            return mpq_a->blocks[entry].block_offset; +            r =  mpq_a->blocks[entry].block_offset; +            break;          case MPQLIB_IOCTL_GET_BLOCK_SIZE: -            return mpq_a->blocks[entry].block_size; +            r = mpq_a->blocks[entry].block_size; +            break;          case MPQLIB_IOCTL_GET_FILE_SIZE: -            return mpq_a->blocks[entry].file_size; +            r = mpq_a->blocks[entry].file_size; +            break;          case MPQLIB_IOCTL_GET_FLAGS: -            return mpq_a->blocks[entry].flags; +            r = mpq_a->blocks[entry].flags; +            break; +        case MPQLIB_IOCTL_SET_BLOCK_OFFSET: +            u64 = va_arg(ap, uint64_t); +            mpq_a->blocks[entry].block_offset = u64; +            break; +        case MPQLIB_IOCTL_SET_BLOCK_SIZE: +            u32 = va_arg(ap, uint32_t); +            mpq_a->blocks[entry].block_size = u32; +            break; +        case MPQLIB_IOCTL_SET_FILE_SIZE: +            u32 = va_arg(ap, uint32_t); +            mpq_a->blocks[entry].file_size = u32; +            break; +        case MPQLIB_IOCTL_SET_FLAGS: +            u32 = va_arg(ap, uint32_t); +            mpq_a->blocks[entry].flags = u32; +            break;          default:              // should never get there.              __mpqlib_errno = MPQLIB_ERROR_UNKNOWN; -            return -1; +            r = -1; +            break;          } +        break;      default:          __mpqlib_errno = MPQLIB_ERROR_INVALID_IOCTL; -        return -1; +        r = -1; +        break;      } +     +    va_end(ap); +    return r;  } @@ -15,6 +15,9 @@ struct mpq_archive_t;  enum mpqlib_ioctl_t {      MPQLIB_IOCTL_NO_ACTION = 0, +    MPQLIB_IOCTL_SEEK, +    MPQLIB_IOCTL_READ, +    MPQLIB_IOCTL_WRITE,      MPQLIB_IOCTL_ENTRY_EXISTS,      MPQLIB_IOCTL_GET_FORMAT_VERSION,      MPQLIB_IOCTL_GET_SECTOR_SIZE, @@ -22,6 +25,10 @@ enum mpqlib_ioctl_t {      MPQLIB_IOCTL_GET_BLOCK_SIZE,      MPQLIB_IOCTL_GET_FILE_SIZE,      MPQLIB_IOCTL_GET_FLAGS, +    MPQLIB_IOCTL_SET_BLOCK_OFFSET, +    MPQLIB_IOCTL_SET_BLOCK_SIZE, +    MPQLIB_IOCTL_SET_FILE_SIZE, +    MPQLIB_IOCTL_SET_FLAGS,  };  #ifdef __cplusplus @@ -34,9 +41,11 @@ struct mpq_archive_t * mpqlib_open_archive_for_writing(const char * fname);  struct mpq_archive_t * mpqlib_reopen_archive(int fd);  void mpqlib_printtables(struct mpq_archive_t *);  void mpqlib_close_archive(struct mpq_archive_t *); -int mpqlib_find_hash_entry_by_name(struct mpq_archive_t *, const char * name, uint32_t language, uint32_t platform); -int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t *, uint32_t h, uint32_t hA, uint32_t hB, uint32_t language, uint32_t platform); -uint64_t mpqlib_ioctl(struct mpq_archive_t *, enum mpqlib_ioctl_t command, int entry); +int mpqlib_find_hash_entry_by_name(struct mpq_archive_t *, const char * name, uint16_t language, uint16_t platform); +int mpqlib_find_hash_entry_by_hash(struct mpq_archive_t *, uint32_t h, uint32_t hA, uint32_t hB, uint16_t language, uint16_t platform); +int mpqlib_add_hash_entry_by_name(struct mpq_archive_t *, const char * name, uint16_t language, uint16_t platform, int entry); +int mpqlib_add_hash_entry_by_hash(struct mpq_archive_t *, uint32_t h, uint32_t hA, uint32_t hB, uint16_t language, uint16_t, int entry); +uint64_t mpqlib_ioctl(struct mpq_archive_t *, enum mpqlib_ioctl_t command, ...);  #ifdef __cplusplus  } diff --git a/mpq-errors.c b/mpq-errors.c index b052e3b..3198e06 100644 --- a/mpq-errors.c +++ b/mpq-errors.c @@ -7,7 +7,9 @@ static const char * error_strings[] = {      "Error opening file.",      "File specified isn't an MPQ archive.",      "Not enough memory.", +    "File seek error."      "File read error.", +    "File write error."      "Invalid ioctl.",      "Invalid ioctl's file entry.",      "File not found.", diff --git a/mpq-errors.h b/mpq-errors.h index ada05f1..e22d370 100644 --- a/mpq-errors.h +++ b/mpq-errors.h @@ -18,7 +18,9 @@ enum {      MPQLIB_ERROR_OPEN,      MPQLIB_ERROR_NOT_MPQ_ARCHIVE,      MPQLIB_ERROR_MEMORY, +    MPQLIB_ERROR_SEEK,      MPQLIB_ERROR_READ, +    MPQLIB_ERROR_WRITE,      MPQLIB_ERROR_INVALID_IOCTL,      MPQLIB_ERROR_IOCTL_INVALID_ENTRY,      MPQLIB_ERROR_FILE_NOT_FOUND, @@ -4,7 +4,6 @@  #include "mpq-bios.h"  #include "mpq-file.h"  #include "mpq-errors.h" -#include "int-bios.h"  #include "extract.h"  #include "errors.h" @@ -64,7 +63,7 @@ struct mpq_file_t * mpqlib_open_file(struct mpq_archive_t * mpq_a, int entry) {  	return NULL;      } -    r->sector_size = mpqlib_ioctl(mpq_a, MPQLIB_IOCTL_GET_SECTOR_SIZE, 0); +    r->sector_size = mpqlib_ioctl(mpq_a, MPQLIB_IOCTL_GET_SECTOR_SIZE);      /* Allocating and filling up the mpq_file_t structure. */      if (!(r->buffer = malloc(r->sector_size))) { @@ -102,9 +101,9 @@ struct mpq_file_t * mpqlib_open_file(struct mpq_archive_t * mpq_a, int entry) {      }      /* Reading the offset table and building the size table */ -    __mpqlib_seek(mpq_a, r->offset); +    mpqlib_ioctl(mpq_a, MPQLIB_IOCTL_SEEK, r->offset);      for (i = 0; i <= r->number_of_sectors; i++) { -	__mpqlib_read(mpq_a, &o, 4); +        mpqlib_ioctl(mpq_a, MPQLIB_IOCTL_READ, &o, 4);  	r->offsets[i] = r->offset + o;      } @@ -138,8 +137,8 @@ static int cache_sector(struct mpq_file_t * mpq_f, int sector) {      /* current_sector should be initialized to -1 */      if (mpq_f->current_sector != sector) {          int il, ol; -        __mpqlib_seek(mpq_f->mpq_a, mpq_f->offsets[sector]); -	__mpqlib_read(mpq_f->mpq_a, in_buf, mpq_f->sizes[sector]); +        mpqlib_ioctl(mpq_f->mpq_a, MPQLIB_IOCTL_SEEK, mpq_f->offsets[sector]); +        mpqlib_ioctl(mpq_f->mpq_a, MPQLIB_IOCTL_READ, mpq_f->sizes[sector]);  	mpq_f->current_sector = sector;          il = ol = sector == (mpq_f->number_of_sectors - 1) ? mpq_f->remaining_bytes : mpq_f->sector_size; | 
