summaryrefslogtreecommitdiff
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
parentc579f3458775ca45bd86dcb9b8ef09e7d2a03bdc (diff)
Cleaning up and sanityzing the ioctl subsystem.
-rw-r--r--int-bios.h13
-rw-r--r--mpq-bios.c144
-rw-r--r--mpq-bios.h15
-rw-r--r--mpq-errors.c2
-rw-r--r--mpq-errors.h2
-rw-r--r--mpq-file.c11
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
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;
}
diff --git a/mpq-bios.h b/mpq-bios.h
index af58b93..5444469 100644
--- a/mpq-bios.h
+++ b/mpq-bios.h
@@ -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,
diff --git a/mpq-file.c b/mpq-file.c
index 56fe2b5..8356483 100644
--- a/mpq-file.c
+++ b/mpq-file.c
@@ -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;