#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; }