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 /mpq-bios.c | |
| parent | c579f3458775ca45bd86dcb9b8ef09e7d2a03bdc (diff) | |
Cleaning up and sanityzing the ioctl subsystem.
Diffstat (limited to 'mpq-bios.c')
| -rw-r--r-- | mpq-bios.c | 144 | 
1 files changed, 109 insertions, 35 deletions
@@ -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;  }  | 
