diff options
Diffstat (limited to 'src/file_posix.c')
| -rw-r--r-- | src/file_posix.c | 253 |
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; +} |
