aboutsummaryrefslogtreecommitdiff
path: root/src/Platform/Posix/File.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/Platform/Posix/File.c')
-rw-r--r--src/Platform/Posix/File.c354
1 files changed, 128 insertions, 226 deletions
diff --git a/src/Platform/Posix/File.c b/src/Platform/Posix/File.c
index f8ee089..c91a46f 100644
--- a/src/Platform/Posix/File.c
+++ b/src/Platform/Posix/File.c
@@ -10,166 +10,67 @@
typedef struct BH_File
{
- char *path;
- int mode;
+ BH_IO parent;
int flags;
int handle;
} BH_File;
-static int BH_FileInfo(BH_File *file,
- size_t *size,
- const char **name);
-
-
-static int BH_FileInit(BH_File *file,
- const char *path);
-
-
-static int BH_FileDestroy(BH_File *file);
-
-
-static int BH_FileOpen(BH_File *file,
- int *mode);
-
-
-static int BH_FileClose(BH_File *file);
-
-
-static int BH_FileRead(BH_File *file,
- char *data,
- size_t *size);
-
-
-static int BH_FileWrite(BH_File *file,
- const char *data,
- size_t *size);
-
-
-static int BH_FilePeek(BH_File* file,
- char *data,
- size_t *size);
-
-
-static int BH_FileFlush(BH_File *file);
-
-
-static int BH_FileSeek(BH_File *file,
- int64_t *pos,
- int *dir);
-
-
-static int BH_FileTell(BH_File *file,
- int64_t *pos);
-
-
-static int BH_FileSize(BH_File *file,
- int64_t *size);
-
-
-static int BH_FileFlags(BH_File *file);
-
-
-static int BH_FileClear(BH_File *file);
-
-
-static int BH_FileInfo(BH_File *file,
- size_t *size,
- const char **name)
-{
- static const char classname[] = BH_FILE_CLASSNAME;
-
- if (size)
- *size = sizeof(*file);
- if (name)
- *name = classname;
- return BH_OK;
-}
-
-
-static int BH_FileInit(BH_File *file,
- const char *path)
-{
- /* Check if path is valid */
- if (!path)
- return BH_ERROR;
-
- /* Duplicate path string and initialize the file struct */
- file->path = strdup(path);
- file->mode = 0;
- file->handle = -1;
- file->flags = 0;
-
- return BH_OK;
-}
-
-
-static int BH_FileDestroy(BH_File *file)
-{
- /* Close the file handle on destruction */
- if (file->handle != -1)
- BH_FileClose(file);
-
- /* Free path string */
- free(file->path);
-
- return BH_OK;
-}
-
-
-static int BH_FileOpenFlags(int mode)
+static int fileOpenFlags(int mode)
{
int flags = 0;
/* Determine read/write flags */
- if ((mode & BH_IO_READWRITE) == BH_IO_READWRITE)
+ if ((mode & BH_FILE_READWRITE) == BH_FILE_READWRITE)
flags |= O_RDWR;
- else if (mode & BH_IO_WRITE)
+ else if (mode & BH_FILE_WRITE)
flags |= O_WRONLY;
- else if (mode & BH_IO_READ)
+ else if (mode & BH_FILE_READ)
flags |= O_RDONLY;
else
return -1;
/* Check if existing file should be opened */
- if (!(mode & BH_IO_EXIST))
+ if (!(mode & BH_FILE_EXIST))
{
flags |= O_CREAT;
/* Check if file should be created */
- if (mode & BH_IO_CREATE)
+ if (mode & BH_FILE_CREATE)
flags |= O_EXCL;
}
/* Check if file should be opened in append mode */
- if (mode & BH_IO_APPEND)
+ if (mode & BH_FILE_APPEND)
flags |= O_APPEND;
/* Check if file should be truncated */
- if (mode & BH_IO_TRUNCATE)
+ if (mode & BH_FILE_TRUNCATE)
flags |= O_TRUNC;
return flags;
}
-static int BH_FileOpen(BH_File *file,
- int *mode)
+static int fileInit(BH_File *file,
+ const char *path,
+ int mode)
{
static const mode_t open_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
int flags;
- /* If file is already opened - report error */
- if (file->handle != -1)
+ /* Check if path is valid */
+ if (!path)
return BH_ERROR;
/* Determine file open flags */
- flags = BH_FileOpenFlags(*mode);
+ flags = fileOpenFlags(mode);
if (flags == -1)
return BH_ERROR;
/* Open the file */
- file->handle = open(file->path, flags, open_mode);
+ file->flags = 0;
+ file->handle = open(path, flags, open_mode);
if (file->handle == -1)
return BH_ERROR;
@@ -177,32 +78,22 @@ static int BH_FileOpen(BH_File *file,
}
-static int BH_FileClose(BH_File *file)
+static int fileDestroy(BH_File *file)
{
- /* If file is closed - report error */
- if (file->handle == -1)
- return BH_ERROR;
-
- /* Close and reset the file handle */
close(file->handle);
- file->handle = -1;
+ free(file);
return BH_OK;
}
-static int BH_FileRead(BH_File *file,
- char *data,
- size_t *size)
+static int fileRead(BH_File *file,
+ BH_IOReadInfo *info)
{
ssize_t readed;
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
/* Read data from the file */
- readed = read(file->handle, data, *size);
+ readed = read(file->handle, info->data, info->size);
if (readed < 0)
goto error;
@@ -212,7 +103,8 @@ static int BH_FileRead(BH_File *file,
else
file->flags |= BH_IO_FLAG_EOF;
- *size = readed;
+ if (info->actual)
+ *info->actual = readed;
return BH_OK;
error:
@@ -221,18 +113,13 @@ error:
}
-static int BH_FileWrite(BH_File *file,
- const char *data,
- size_t *size)
+static int fileWrite(BH_File *file,
+ BH_IOWriteInfo *info)
{
ssize_t written;
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
/* Write data to the file */
- written = write(file->handle, data, *size);
+ written = write(file->handle, info->data, info->size);
if (written < 0)
goto error;
@@ -242,7 +129,8 @@ static int BH_FileWrite(BH_File *file,
else
file->flags &= ~BH_IO_FLAG_EOF;
- *size = written;
+ if (info->actual)
+ *info->actual = written;
return BH_OK;
error:
@@ -251,60 +139,19 @@ error:
}
-static int BH_FilePeek(BH_File *file,
- char *data,
- size_t *size)
+static int fileFlush(BH_File *file)
{
- int64_t position;
- int direction;
-
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
- /* Read data from the file */
- if (BH_FileRead(file, data, size))
- goto error;
-
- /* Backtrack by the read amount */
- position = -((int64_t)*size);
- direction = BH_IO_SEEK_CUR;
- if (BH_FileSeek(file, &position, &direction))
- goto error;
-
- return BH_OK;
-
-error:
- file->flags |= BH_IO_FLAG_ERROR;
- return BH_ERROR;
-}
-
-
-static int BH_FileFlush(BH_File *file)
-{
- /* Check if file is open */
- if (file->handle == -1)
- {
- file->flags |= BH_IO_FLAG_ERROR;
- return BH_ERROR;
- }
-
/* Flush the buffers */
fsync(file->handle);
return BH_OK;
}
-static int BH_FileSeek(BH_File *file,
- int64_t *pos,
- int *dir)
+static int fileSeek(BH_File *file,
+ BH_IOSeekInfo *info)
{
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
/* Seek to the specified position */
- if (lseek(file->handle, *pos, *dir) == -1)
+ if (lseek(file->handle, info->offset, info->whence) == -1)
goto error;
return BH_OK;
@@ -315,13 +162,9 @@ error:
}
-static int BH_FileTell(BH_File *file,
- int64_t *pos)
+static int fileTell(BH_File *file,
+ int64_t *pos)
{
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
/* Get current offset in the file */
if ((*pos = lseek(file->handle, 0, SEEK_CUR)) == -1)
goto error;
@@ -334,15 +177,11 @@ error:
}
-static int BH_FileSize(BH_File *file,
- int64_t *size)
+static int fileSize(BH_File *file,
+ int64_t *size)
{
struct stat sb;
- /* Check if file is open */
- if (file->handle == -1)
- goto error;
-
/* Get file size from the OS */
if (fstat(file->handle, &sb))
goto error;
@@ -356,51 +195,114 @@ error:
}
-static int BH_FileFlags(BH_File *file)
+static int fileFlags(BH_File *file,
+ int *flags)
{
- /* If file handle is valid - append IO_OPEN flag */
- if (file->handle != -1)
- return file->flags | BH_IO_FLAG_OPEN;
-
- return file->flags;
+ *flags = file->flags;
+ return BH_OK;
}
-static int BH_FileClear(BH_File *file)
+static int fileClear(BH_File *file)
{
- /* Clear IO_ERROR flag */
+ /* Clear BH_IO_FLAG_ERROR flag */
file->flags &= ~BH_IO_FLAG_ERROR;
return BH_OK;
}
-static int BH_FileCallback(BH_File *file,
- int type,
- void *arg1,
- void *arg2)
+static int fileCap(BH_File *file,
+ int *op)
+{
+ BH_UNUSED(file);
+
+ /* Return operations supported by the file input/output device */
+ switch (*op)
+ {
+ case BH_IO_CTL_FLAGS:
+ case BH_IO_CTL_CLEAR:
+ case BH_IO_CTL_FLUSH:
+ case BH_IO_CTL_SIZE:
+ case BH_IO_CTL_TELL:
+ case BH_IO_CTL_SEEK:
+ return BH_OK;
+
+ default:
+ return BH_NOIMPL;
+ }
+}
+
+
+static int fileCtl(BH_File *file,
+ BH_IOCtlInfo *info)
+{
+ /* Handle supported operations */
+ switch (info->op)
+ {
+ case BH_IO_CTL_FLAGS:
+ return fileFlags(file, (int *)info->arg);
+
+ case BH_IO_CTL_CLEAR:
+ return fileClear(file);
+
+ case BH_IO_CTL_FLUSH:
+ return fileFlush(file);
+
+ case BH_IO_CTL_SIZE:
+ return fileSize(file, (int64_t *)(info->arg));
+
+ case BH_IO_CTL_TELL:
+ return fileTell(file, (int64_t *)(info->arg));
+
+ case BH_IO_CTL_SEEK:
+ return fileSeek(file, (BH_IOSeekInfo *)(info->arg));
+
+ default:
+ return BH_NOIMPL;
+ }
+}
+
+
+static int fileCallback(BH_File *file,
+ int type,
+ void *arg)
{
+ /* Handle basic input/output operations */
switch (type)
{
- case BH_IO_INFO_CB: return BH_FileInfo(file, (size_t *)arg1, (const char **)arg2);
- case BH_IO_INIT_CB: return BH_FileInit(file, (const char *)arg1);
- case BH_IO_DESTROY_CB: return BH_FileDestroy(file);
- case BH_IO_OPEN_CB: return BH_FileOpen(file, (int *)arg1);
- case BH_IO_CLOSE_CB: return BH_FileClose(file);
- case BH_IO_READ_CB: return BH_FileRead(file, (char *)arg1, (size_t *)arg2);
- case BH_IO_WRITE_CB: return BH_FileWrite(file, (const char *)arg1, (size_t *)arg2);
- case BH_IO_PEEK_CB: return BH_FilePeek(file, (char *)arg1, (size_t *)arg2);
- case BH_IO_FLUSH_CB: return BH_FileFlush(file);
- case BH_IO_SEEK_CB: return BH_FileSeek(file, (int64_t *)arg1, (int *)arg2);
- case BH_IO_TELL_CB: return BH_FileTell(file, (int64_t *)arg1);
- case BH_IO_SIZE_CB: return BH_FileSize(file, (int64_t *)arg1);
- case BH_IO_FLAGS_CB: return BH_FileFlags(file);
- case BH_IO_CLEAR_CB: return BH_FileClear(file);
+ case BH_IO_OP_DESTROY: return fileDestroy(file);
+ case BH_IO_OP_READ: return fileRead(file, (BH_IOReadInfo *)arg);
+ case BH_IO_OP_WRITE: return fileWrite(file, (BH_IOWriteInfo *)arg);
+ case BH_IO_OP_CTL: return fileCtl(file, (BH_IOCtlInfo *)arg);
+ case BH_IO_OP_CAP: return fileCap(file, (int*)arg);
default: return BH_NOIMPL;
}
}
-BH_IO *BH_FileNew(const char *path)
+BH_IO *BH_FileNew(const char *path,
+ int mode,
+ int *result)
{
- return BH_IONew((BH_IOCallback)BH_FileCallback, (void *)path);
+ BH_File *file;
+ int code;
+
+ code = BH_OOM;
+
+ /* Allocate new file object and initialize it */
+ if ((file = malloc(sizeof(*file))))
+ {
+ file->parent.callback = (BH_IOCallback)fileCallback;
+ if ((code = fileInit(file, path, mode)))
+ {
+ free(file);
+ file = NULL;
+ }
+ }
+
+ /* Report error code */
+ if (result)
+ *result = code;
+
+ return (BH_IO*)file;
}