aboutsummaryrefslogtreecommitdiff
path: root/src/file_posix.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/file_posix.c')
-rw-r--r--src/file_posix.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/src/file_posix.c b/src/file_posix.c
index e69de29..0ffbf5e 100644
--- a/src/file_posix.c
+++ b/src/file_posix.c
@@ -0,0 +1,253 @@
+#include <bh/internal/file.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+static const bh_io_table_t bh_file_table = {
+ (int (*)(struct bh_io_s *, int)) bh_file_open_base,
+ (void (*)(struct bh_io_s *)) bh_file_close_base,
+ (int (*)(struct bh_io_s *)) bh_file_is_open_base,
+ (size_t (*)(struct bh_io_s *, char *, size_t)) bh_file_read_base,
+ (size_t (*)(struct bh_io_s *, const char *, size_t)) bh_file_write_base,
+ (void (*)(struct bh_io_s *)) bh_file_flush_base,
+ (int (*)(struct bh_io_s *, bh_off_t, int)) bh_file_seek_base,
+ (bh_off_t (*)(struct bh_io_s *)) bh_file_size_base,
+ (bh_off_t (*)(struct bh_io_s *)) bh_file_tell_base,
+ (bh_off_t (*)(struct bh_io_s *)) bh_file_available_base,
+ (void (*)(struct bh_io_s *)) bh_file_clear_base,
+ (void (*)(struct bh_io_s *)) bh_file_destroy
+};
+
+bh_file_t *bh_file_new(const char *path)
+{
+ bh_file_t *result;
+
+ /* Allocate and initialize file structure */
+ result = malloc(sizeof(*result));
+ if (result && bh_file_init(result, path))
+ {
+ /* Something went wrong - free allocated memory */
+ free(result);
+ result = NULL;
+ }
+
+ return result;
+}
+
+void bh_file_free(bh_file_t *file)
+{
+ bh_file_destroy(file);
+ free(file);
+}
+
+int bh_file_init(bh_file_t *file,
+ const char *path)
+{
+ /* Ensure that path is not empty */
+ if (!path)
+ return BH_INVALID;
+
+ /* Initialize base io object */
+ bh_io_init(&file->base, &bh_file_table);
+
+ /* Initialize file io object */
+ file->handle = -1;
+ file->mode = 0;
+ file->path = strdup(path);
+
+ return BH_OK;
+}
+
+void bh_file_destroy(bh_file_t *file)
+{
+ /* Close the file */
+ bh_file_close(file);
+ free(file->path);
+}
+
+int bh_file_open_base(bh_file_t *file,
+ int mode)
+{
+ /* Set open mode for 0666 permisions */
+ mode_t open_mode = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+ int open_flags = 0;
+
+ /* Check if file is already opened */
+ if (file->handle != -1)
+ return BH_OK;
+
+ /* Determine read/write flags */
+ if (mode & BH_IO_READ_WRITE)
+ open_flags |= O_RDWR;
+ else if (mode & BH_IO_READ)
+ open_flags |= O_RDONLY;
+ else if (mode & BH_IO_WRITE)
+ open_flags |= O_WRONLY;
+ else
+ return BH_INVALID;
+
+ /* Determine open mode */
+ switch (mode & BH_IO_MASK)
+ {
+ case BH_IO_OPEN: break;
+ case BH_IO_CREATE: open_flags |= O_CREAT | O_EXCL; break;
+ case BH_IO_APPEND: open_flags |= O_CREAT | O_APPEND; break;
+ case BH_IO_TRUNCATE: open_flags |= O_CREAT | O_TRUNC; break;
+
+ default:
+ return BH_NO_IMPL;
+ }
+
+ /* Open file */
+ file->handle = open(file->path, open_flags, open_mode);
+
+ /* Check for errors */
+ if (file->handle == -1)
+ return BH_ERROR;
+
+ return BH_OK;
+}
+
+void bh_file_close_base(bh_file_t *file)
+{
+ /* Close file if it's open */
+ if (file->handle != -1)
+ close(file->handle);
+
+ /* Set handle to invalid value */
+ file->handle = -1;
+}
+
+int bh_file_is_open_base(bh_file_t *file)
+{
+ /* If handle is not -1 - then file is open */
+ return file->handle != -1;
+}
+
+size_t bh_file_read_base(bh_file_t *file,
+ char *data,
+ size_t size)
+{
+ ssize_t readed;
+
+ /* Check if file is open */
+ if (file->handle == -1)
+ {
+ /* Error occured - set error bit */
+ file->base.flags |= BH_IO_ERROR;
+ return 0;
+ }
+
+ /* Read data from file */
+ readed = read(file->handle, data, size);
+ if (readed < 0)
+ {
+ /* Error occured - set error bit */
+ file->base.flags |= BH_IO_ERROR;
+ return 0;
+ }
+
+ /* Check for end of file */
+ if (!readed)
+ file->base.flags |= BH_IO_EOF;
+ else
+ file->base.flags &= ~BH_IO_EOF;
+
+ /* Return number of readed bytes */
+ return readed;
+}
+
+size_t bh_file_write_base(bh_file_t *file,
+ const char *data,
+ size_t size)
+{
+ ssize_t written;
+
+ /* Check if file is open */
+ if (file->handle == -1)
+ {
+ /* Error occured - set error bit */
+ file->base.flags |= BH_IO_ERROR;
+ return 0;
+ }
+
+ /* Write data to file */
+ written = write(file->handle, data, size);
+ if (written < 0)
+ {
+ /* Error occured - set error bit */
+ 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;
+
+ /* Return number of written bytes */
+ return written;
+}
+
+void bh_file_flush_base(bh_file_t *file)
+{
+ /* Check if file is open */
+ if (file->handle == -1)
+ return;
+
+ /* Signal OS to flush data from the internal buffers */
+ fsync(file->handle);
+}
+
+int bh_file_seek_base(bh_file_t *file,
+ bh_off_t pos,
+ int dir)
+{
+ /* Check if file is open */
+ if (file->handle == -1)
+ return BH_ERROR;
+
+ /* Seek to desired location */
+ if (lseek(file->handle, pos, dir) == -1);
+ return BH_ERROR;
+
+ return BH_OK;
+}
+
+bh_off_t bh_file_size_base(bh_file_t *file)
+{
+ struct stat sb;
+
+ /* Check if file is open */
+ if (file->handle == -1)
+ return -1;
+
+ /* Get file size from the OS */
+ if (fstat(file->handle, &sb))
+ return -1;
+
+ return sb.st_size;
+}
+
+bh_off_t bh_file_tell_base(bh_file_t *file)
+{
+ /* Check if file is open */
+ if (file->handle == -1)
+ return -1;
+
+ /* Get current file position */
+ return lseek(file->handle, 0, SEEK_CUR);
+}
+
+bh_off_t bh_file_available_base(bh_file_t *file)
+{
+ /* 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)
+{
+ file->base.flags &= ~BH_IO_ERROR;
+}