--- libaitio/src/bufio.c 2012/02/02 15:58:14 1.1 +++ libaitio/src/bufio.c 2012/02/02 21:32:42 1.2 @@ -0,0 +1,385 @@ +#include "global.h" + + +static void +unmap_cf(struct tagBufIO *buf) +{ + if (buf) + munmap(buf->buf_base, buf->buf_size); +} + +static int +cf_(struct tagBufIO *buf) +{ + if (!buf) { + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; + } + + if (buf->buf_mode == BUFIO_MODE_INFINIT) + free(buf->buf_base); + else if (buf->buf_unmap) + buf->buf_unmap(buf); + + free(buf); + return 0; +} + +static fpos_t +sf_lim(struct tagBufIO *buf, fpos_t pos, int w) +{ + if (!buf) + goto err; + + switch (w) { + case SEEK_SET: + if (buf->buf_size < pos || pos < 0) + goto err; + buf->buf_offset = pos; + break; + case SEEK_CUR: + if (buf->buf_size < (buf->buf_offset + pos) || (buf->buf_offset + pos) < 0) + goto err; + buf->buf_offset += pos; + break; + case SEEK_END: + if (buf->buf_size < (buf->buf_size + pos) || (buf->buf_size + pos) < 0) + goto err; + buf->buf_offset = buf->buf_size + pos; + break; + default: + goto err; + } + + return buf->buf_offset; +err: + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; +} + +static int +rf_lim(struct tagBufIO *buf, char *dat, int siz) +{ + if (!buf || !dat) { + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; + } + + if (buf->buf_offset + siz > buf->buf_size) + siz = buf->buf_size - buf->buf_offset; + + memcpy(dat, buf->buf_base + buf->buf_offset, siz); + buf->buf_offset += siz; + return siz; +} + +static int +wf_lim(struct tagBufIO *buf, const char *dat, int siz) +{ + if (!buf || !dat) { + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; + } + + if (buf->buf_offset + siz > buf->buf_size) + siz = buf->buf_size - buf->buf_offset; + + memcpy(buf->buf_base + buf->buf_offset, dat, siz); + buf->buf_offset += siz; + return siz; +} + +static fpos_t +sf_inf(struct tagBufIO *buf, fpos_t pos, int w) +{ + void *b; + + if (!buf) + goto err; + + switch (w) { + case SEEK_SET: + if (pos < 0) + goto err; + if (buf->buf_size < pos) { + b = realloc(buf->buf_base, pos); + if (!b) { + LOGERR; + return -1; + } else { + buf->buf_base = b; + memset(buf->buf_base + buf->buf_size, 0, pos - buf->buf_size); + buf->buf_size = pos; + } + } + buf->buf_offset = pos; + break; + case SEEK_CUR: + if ((buf->buf_offset + pos) < 0) + goto err; + if (buf->buf_size < (buf->buf_offset + pos)) { + b = realloc(buf->buf_base, buf->buf_offset + pos); + if (!b) { + LOGERR; + return -1; + } else { + buf->buf_base = b; + memset(buf->buf_base + buf->buf_size, 0, + buf->buf_offset + pos - buf->buf_size); + buf->buf_size = buf->buf_offset + pos; + } + } + buf->buf_offset += pos; + break; + case SEEK_END: + if ((buf->buf_size + pos) < 0) + goto err; + if (buf->buf_size < (buf->buf_size + pos)) { + b = realloc(buf->buf_base, buf->buf_size + pos); + if (!b) { + LOGERR; + return -1; + } else { + buf->buf_base = b; + memset(buf->buf_base + buf->buf_size, 0, pos); + buf->buf_size += pos; + buf->buf_offset = buf->buf_size; + } + } else + buf->buf_offset = buf->buf_size + pos; + break; + default: + goto err; + } + + return buf->buf_offset; +err: + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; +} + +static int +wf_inf(struct tagBufIO *buf, const char *dat, int siz) +{ + void *b; + + if (!buf || !dat) { + io_SetErr(EINVAL, "Invalid arguments ..."); + return -1; + } + + if (buf->buf_offset + siz > buf->buf_size) { + b = realloc(buf->buf_base, buf->buf_offset + siz); + if (!b) { + LOGERR; + return -1; + } else { + buf->buf_base = b; + memset(buf->buf_base + buf->buf_size, 0, + buf->buf_offset + siz - buf->buf_size); + buf->buf_size = buf->buf_offset + siz; + } + } + + memcpy(buf->buf_base + buf->buf_offset, dat, siz); + buf->buf_offset += siz; + return siz; +} + + +/* + * io_fmemopen() File buffered stream operations over memory block + * + * @base = Base address of memory block, if =NULL Infinit length(auto-grow) + * @basesize = Size of memory block + * return: NULL error or !=NULL Opened file resource + */ +FILE * +io_fmemopen(void ** __restrict base, off_t basesize) +{ + FILE *f = NULL; + struct tagBufIO *buf; + + if (!base) { + io_SetErr(EINVAL, "Invalid base argument ..."); + return NULL; + } + + buf = malloc(sizeof(struct tagBufIO)); + if (!buf) { + LOGERR; + return NULL; + } else + memset(buf, 0, sizeof(struct tagBufIO)); + + if (!*base) { + *base = malloc(basesize); + if (!*base) { + LOGERR; + free(buf); + return NULL; + } else + memset(*base, 0, basesize); + + buf->buf_mode = BUFIO_MODE_INFINIT; + } else + buf->buf_mode = BUFIO_MODE_LIMIT; + + buf->buf_base = *base; + buf->buf_size = basesize; + + if (buf->buf_mode == BUFIO_MODE_INFINIT) + f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, + (int (*)(void *, char const *, int)) wf_inf, + (fpos_t (*)(void *, fpos_t, int)) sf_inf, + (int (*)(void *)) cf_); + else + f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, + (int (*)(void *, char const *, int)) wf_lim, + (fpos_t (*)(void *, fpos_t, int)) sf_lim, + (int (*)(void *)) cf_); + if (!f) { + LOGERR; + if (buf->buf_mode == BUFIO_MODE_INFINIT) { + free(*base); + *base = NULL; + } + free(buf); + return NULL; + } + + return f; +} + +/* + * io_fmapopen() File buffered stream operations over MMAP block + * + * @csFile = Filename for MMAP, if =NULL private MMAP block + * @mode = File open mode + * @perm = If file not exists will be created with this access permissions + * @prot = MMAP protection + * @flags = MMAP mode flags + * @offset = Map from file offset, if csFile==NULL then this is size of MMAP private block + * return: NULL error or !=NULL Opened file resource + */ +FILE * +io_fmapopen(const char *csFile, int mode, int perm, int prot, int flags, off_t offset) +{ + FILE *f; + struct tagBufIO *buf; + void *base; + off_t basesize; + int fd = -1; + + if (csFile) { + fd = open(csFile, mode, perm); + if (fd == -1) { + LOGERR; + return NULL; + } + basesize = lseek(fd, 0, SEEK_END); + if (basesize == -1) { + LOGERR; + close(fd); + return NULL; + } else + lseek(fd, 0, SEEK_SET); + + base = mmap(NULL, basesize, prot, flags | MAP_FILE, fd, offset); + if (base == MAP_FAILED) { + LOGERR; + close(fd); + return NULL; + } else + close(fd); + } else if (offset) { + basesize = offset; + base = mmap(NULL, basesize, prot, MAP_ANON, -1, 0); + if (base == MAP_FAILED) { + LOGERR; + return NULL; + } + } else { + io_SetErr(EINVAL, "Invalid base argument ..."); + return NULL; + } + + + buf = malloc(sizeof(struct tagBufIO)); + if (!buf) { + LOGERR; + munmap(base, basesize); + return NULL; + } else + memset(buf, 0, sizeof(struct tagBufIO)); + + buf->buf_mode = BUFIO_MODE_LIMIT; + buf->buf_base = base; + buf->buf_size = basesize; + buf->buf_unmap = unmap_cf; + + f = funopen(buf, (int (*)(void *, char *, int)) rf_lim, + (int (*)(void *, char const *, int)) wf_lim, + (fpos_t (*)(void *, fpos_t, int)) sf_lim, + (int (*)(void *)) cf_); + if (!f) { + LOGERR; + free(buf); + munmap(base, basesize); + return NULL; + } + + return f; +} + +/* + * io_dumbFile() Create empry or dumb file with fixed size + * + * @csFile = Filename for create + * @mode = File access permissions + * @size = File size + * return: -1 error or open file handle + */ +int +io_dumbFile(const char *csFile, int mode, off_t size) +{ + int fd; + + fd = open(csFile, O_RDWR | O_CREAT, mode); + if (fd == -1) { + LOGERR; + return -1; + } + + if (lseek(fd, size - 1, SEEK_SET) == -1) + goto err; + if (write(fd, "", 1) != 1) + goto err; + else + lseek(fd, 0, SEEK_SET); + + return fd; +err: + LOGERR; + close(fd); + return -1; +} + +/* + * io_fd2buf() Convert open file handle to buffered file I/O + * + * @fd = File handle + * @mode = Permissions for new buffered file I/O + * return: NULL error or open buffered file + */ +inline FILE * +io_fd2buf(int fd, const char *mode) +{ + FILE *f; + + f = fdopen(fd, mode); + if (!f) + LOGERR; + + return f; +}