#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;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>