aboutsummaryrefslogtreecommitdiff
path: root/src/file_win.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_win.c')
-rw-r--r--src/file_win.c108
1 files changed, 92 insertions, 16 deletions
diff --git a/src/file_win.c b/src/file_win.c
index e31e0de..15d2a61 100644
--- a/src/file_win.c
+++ b/src/file_win.c
@@ -19,9 +19,11 @@ bh_file_t *bh_file_new(const char *path)
{
bh_file_t *result;
+ /* Allocate and initialize file object */
result = malloc(sizeof(*result));
if (result && bh_file_init(result, path))
{
+ /* Something went wrong - free the file object */
free(result);
result = NULL;
}
@@ -31,6 +33,7 @@ bh_file_t *bh_file_new(const char *path)
void bh_file_free(bh_file_t *file)
{
+ /* Destroy file object and free allocated memory */
bh_file_destroy(file);
free(file);
}
@@ -38,38 +41,50 @@ void bh_file_free(bh_file_t *file)
int bh_file_init(bh_file_t *file,
const char *path)
{
+ /* Check if path is not empty */
if (!path)
return BH_INVALID;
+ /* Fill file structure information */
file->handle = INVALID_HANDLE_VALUE;
- file->mode = 0;
+ file->mode = BH_IO_NONE;
file->path = strdup(path);
file->base.table = &bh_file_table;
return BH_OK;
}
+void bh_file_destroy(bh_file_t *file)
+{
+ /* Close the file and free allocated memory */
+ bh_file_close(file);
+ free(file->path);
+}
+
int bh_file_open_base(bh_file_t *file,
int mode)
{
DWORD access = 0, how = 0;
+ /* Check if file is already openned */
+ if (file->handle != INVALID_HANDLE_VALUE)
+ return BH_OK;
+
+ /* Determine read/write access flags */
if (mode & BH_IO_READ)
access |= GENERIC_READ;
if (mode & BH_IO_WRITE)
access |= GENERIC_WRITE;
- switch (mode & BH_IO_MASK)
+ /* Determine open mode flags */
+ switch (mode & (BH_IO_CREATE | BH_IO_OPEN))
{
+ case 0: how = OPEN_ALWAYS; break;
+ case BH_IO_CREATE: how = CREATE_NEW; break;
case BH_IO_OPEN: how = OPEN_EXISTING; break;
- case BH_IO_CREATE: how = CREATE_ALWAYS; break;
- case BH_IO_APPEND: how = OPEN_ALWAYS; break;
-
- default:
- case BH_IO_TRUNCATE:
- return BH_NO_IMPL;
}
+ /* Save mode that we are in and open file */
file->mode = mode;
file->handle = CreateFileA(file->path, access, FILE_SHARE_READ, NULL, how, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -84,27 +99,30 @@ int bh_file_open_base(bh_file_t *file,
}
}
+ /* Truncate file if needed */
+ if (mode & BH_IO_TRUNCATE)
+ SetEndOfFile(file->handle);
+
return BH_OK;
}
void bh_file_close_base(bh_file_t *file)
{
+ /* If file is opened - close it */
if (file->handle != INVALID_HANDLE_VALUE)
CloseHandle(file->handle);
+ /* Reset handle and mode values */
file->handle = INVALID_HANDLE_VALUE;
+ file->mode = BH_IO_NONE;
}
int bh_file_is_open_base(bh_file_t *file)
{
+ /* If handle is not INVALID_HANDLE_VALUE - file is open */
return file->handle != INVALID_HANDLE_VALUE;
}
-void bh_file_destroy(bh_file_t *file)
-{
- bh_file_close(file);
- free(file->path);
-}
size_t bh_file_read_base(bh_file_t *file,
char *data,
@@ -112,17 +130,27 @@ size_t bh_file_read_base(bh_file_t *file,
{
DWORD readed;
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return 0;
+ }
+
+ /* Read data from the file */
if (!ReadFile(file->handle, data, (DWORD)size, &readed, NULL))
{
file->base.flags |= BH_IO_ERROR;
return 0;
}
+ /* Check if we reached end of file */
if (!readed)
file->base.flags |= BH_IO_EOF;
else
file->base.flags &= ~BH_IO_EOF;
+ /* Return readed bytes */
return readed;
}
@@ -132,25 +160,44 @@ size_t bh_file_write_base(bh_file_t *file,
{
DWORD written;
- if ((file->mode & BH_IO_MASK) == BH_IO_APPEND)
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return 0;
+ }
+
+ /* Adjust current position in the file to the end */
+ if (file->mode & BH_IO_APPEND)
bh_file_seek(file, 0, BH_IO_END);
+ /* Write data to the file */
if (!WriteFile(file->handle, data, (DWORD)size, &written, NULL))
{
file->base.flags |= BH_IO_ERROR;
return 0;
}
+ /* Check for end of file */
if (!written)
file->base.flags |= BH_IO_EOF;
else
file->base.flags &= ~BH_IO_EOF;
+ /* Write amount of bytes written */
return written;
}
void bh_file_flush_base(bh_file_t *file)
{
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return;
+ }
+
+ /* Flush OS buffers */
FlushFileBuffers(file->handle);
}
@@ -160,6 +207,14 @@ int bh_file_seek_base(bh_file_t *file,
{
LARGE_INTEGER position;
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return BH_ERROR;
+ }
+
+ /* Set read/write position in the file */
position.QuadPart = pos;
if (SetFilePointerEx(file->handle, position, NULL, dir))
return BH_OK;
@@ -169,6 +224,19 @@ int bh_file_seek_base(bh_file_t *file,
bh_off_t bh_file_size_base(bh_file_t *file)
{
+ LARGE_INTEGER size;
+
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return -1;
+ }
+
+ /* Get current file size */
+ if (GetFileSizeEx(file->handle, &size))
+ return size.QuadPart;
+
return -1;
}
@@ -176,8 +244,15 @@ bh_off_t bh_file_tell_base(bh_file_t *file)
{
LARGE_INTEGER dummy, position;
- dummy.QuadPart = 0;
+ /* Check if file is opened */
+ if (file->handle == INVALID_HANDLE_VALUE)
+ {
+ file->base.flags |= BH_IO_ERROR;
+ return -1;
+ }
+ /* Readback current position in the file */
+ dummy.QuadPart = 0;
if (SetFilePointerEx(file->handle, dummy, &position, BH_IO_CURRENT))
return position.QuadPart;
@@ -186,7 +261,8 @@ bh_off_t bh_file_tell_base(bh_file_t *file)
bh_off_t bh_file_available_base(bh_file_t *file)
{
- return 0;
+ /* Get available bytes for reading */
+ return bh_file_size_base(file) - bh_file_tell_base(file);
}
void bh_file_clear_base(bh_file_t *file)