From 6b5b44074fd6bdbbeb59f8d006fb88e0230cf1ef Mon Sep 17 00:00:00 2001 From: Pixel Date: Wed, 5 Aug 2009 18:24:59 -0700 Subject: Cleaning up and sanityzing the ioctl subsystem. --- mpq-bios.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 35 deletions(-) (limited to 'mpq-bios.c') diff --git a/mpq-bios.c b/mpq-bios.c index 35f657c..93c0623 100644 --- a/mpq-bios.c +++ b/mpq-bios.c @@ -21,12 +21,12 @@ #include #include #include +#include #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; } -- cgit v1.2.3