summaryrefslogtreecommitdiff
path: root/mpq-bios.c
diff options
context:
space:
mode:
authorPixel <pixel@nobis-crew.org>2009-08-05 18:24:59 -0700
committerPixel <pixel@nobis-crew.org>2009-08-05 18:24:59 -0700
commit6b5b44074fd6bdbbeb59f8d006fb88e0230cf1ef (patch)
treec3559f4579a0ca63b41b766dfeb68f62360a97cc /mpq-bios.c
parentc579f3458775ca45bd86dcb9b8ef09e7d2a03bdc (diff)
Cleaning up and sanityzing the ioctl subsystem.
Diffstat (limited to 'mpq-bios.c')
-rw-r--r--mpq-bios.c144
1 files changed, 109 insertions, 35 deletions
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 <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;
}