272 lines
5.0 KiB
C
272 lines
5.0 KiB
C
#include "file.h"
|
|
|
|
#include <errno.h>
|
|
#include <mango/log.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#define DEFAULT_BUFFER_SIZE 4096
|
|
|
|
static int ringbuf_init(struct ringbuf *buf)
|
|
{
|
|
if (buf->buf_ptr) {
|
|
return SUCCESS;
|
|
}
|
|
|
|
if (!buf->buf_max) {
|
|
buf->buf_max = DEFAULT_BUFFER_SIZE;
|
|
}
|
|
|
|
buf->buf_ptr = malloc(buf->buf_max);
|
|
if (!buf->buf_ptr) {
|
|
return ENOMEM;
|
|
}
|
|
|
|
memset(buf->buf_ptr, 0x0, buf->buf_max);
|
|
return SUCCESS;
|
|
}
|
|
|
|
int __libc_ringbuf_get_read_buffer(
|
|
struct ringbuf *buf,
|
|
const char **out_bufp,
|
|
size_t *out_len)
|
|
{
|
|
int r = ringbuf_init(buf);
|
|
if (r != SUCCESS) {
|
|
return r;
|
|
}
|
|
|
|
size_t contiguous_capacity = 0;
|
|
if (buf->buf_readp > buf->buf_writep) {
|
|
contiguous_capacity = buf->buf_max - buf->buf_readp;
|
|
} else {
|
|
contiguous_capacity = buf->buf_writep - buf->buf_readp;
|
|
}
|
|
|
|
kern_tracef(
|
|
"OPEN READ: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
|
|
buf->buf_readp,
|
|
buf->buf_writep,
|
|
buf->buf_max,
|
|
buf->buf_ptr + buf->buf_readp,
|
|
contiguous_capacity);
|
|
*out_len = contiguous_capacity;
|
|
|
|
if (contiguous_capacity == 0) {
|
|
*out_bufp = NULL;
|
|
} else {
|
|
*out_bufp = buf->buf_ptr + buf->buf_readp;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
void __libc_ringbuf_put_read_buffer(
|
|
struct ringbuf *buf,
|
|
const char **bufp,
|
|
size_t *len)
|
|
{
|
|
buf->buf_readp += *len;
|
|
|
|
if (buf->buf_readp == buf->buf_writep) {
|
|
buf->buf_readp = buf->buf_writep = 0;
|
|
}
|
|
|
|
kern_tracef("CLOSE READ: %p r=%zu", *bufp, *len);
|
|
|
|
*bufp = NULL;
|
|
*len = 0;
|
|
}
|
|
|
|
int __libc_ringbuf_get_write_buffer(
|
|
struct ringbuf *buf,
|
|
char **out_bufp,
|
|
size_t *out_len)
|
|
{
|
|
int r = ringbuf_init(buf);
|
|
if (r != SUCCESS) {
|
|
return r;
|
|
}
|
|
|
|
size_t contiguous_capacity = 0;
|
|
if (buf->buf_writep >= buf->buf_readp) {
|
|
contiguous_capacity = buf->buf_max - buf->buf_writep - 1;
|
|
|
|
if (buf->buf_readp > 0) {
|
|
contiguous_capacity++;
|
|
}
|
|
} else {
|
|
contiguous_capacity = buf->buf_readp - buf->buf_writep - 1;
|
|
}
|
|
|
|
kern_tracef(
|
|
"OPEN WRITE: readp=%zu, writep=%zu, max=%zu -> %p cap=%zu",
|
|
buf->buf_readp,
|
|
buf->buf_writep,
|
|
buf->buf_max,
|
|
buf->buf_ptr + buf->buf_readp,
|
|
contiguous_capacity);
|
|
|
|
*out_len = contiguous_capacity;
|
|
|
|
if (contiguous_capacity == 0) {
|
|
*out_bufp = NULL;
|
|
} else {
|
|
*out_bufp = buf->buf_ptr + buf->buf_writep;
|
|
}
|
|
|
|
return SUCCESS;
|
|
}
|
|
|
|
void __libc_ringbuf_put_write_buffer(
|
|
struct ringbuf *buf,
|
|
char **bufp,
|
|
size_t *len)
|
|
{
|
|
buf->buf_writep += *len;
|
|
|
|
if (buf->buf_readp == buf->buf_writep) {
|
|
buf->buf_readp = buf->buf_writep = 0;
|
|
}
|
|
|
|
kern_tracef(
|
|
"CLOSE WRITE: %p r=%zu (%c)",
|
|
*bufp,
|
|
*len,
|
|
*(char *)(*bufp));
|
|
|
|
*bufp = NULL;
|
|
*len = 0;
|
|
}
|
|
|
|
long __libc_ringbuf_read(struct ringbuf *buf, void *p, size_t count)
|
|
{
|
|
size_t nr_read = 0;
|
|
long r = 0;
|
|
|
|
while (nr_read < count) {
|
|
const char *src = NULL;
|
|
size_t available = 0;
|
|
r = __libc_ringbuf_get_read_buffer(buf, &src, &available);
|
|
if (r < 0) {
|
|
break;
|
|
}
|
|
|
|
char *dest = p + nr_read;
|
|
size_t to_copy = count - nr_read;
|
|
|
|
if (available == 0) {
|
|
__libc_ringbuf_put_read_buffer(buf, &src, &available);
|
|
break;
|
|
}
|
|
|
|
if (to_copy > available) {
|
|
to_copy = available;
|
|
}
|
|
|
|
memcpy(dest, src, to_copy);
|
|
|
|
nr_read += available;
|
|
__libc_ringbuf_put_read_buffer(buf, &src, &to_copy);
|
|
}
|
|
|
|
if (r < 0) {
|
|
return r;
|
|
}
|
|
|
|
return nr_read;
|
|
}
|
|
|
|
long __libc_ringbuf_write(struct ringbuf *buf, const void *p, size_t count)
|
|
{
|
|
size_t nr_written = 0;
|
|
long r = 0;
|
|
|
|
while (nr_written < count) {
|
|
char *dest = NULL;
|
|
size_t available = 0;
|
|
r = __libc_ringbuf_get_write_buffer(buf, &dest, &available);
|
|
if (r < 0) {
|
|
break;
|
|
}
|
|
|
|
const char *src = p + nr_written;
|
|
size_t to_copy = count - nr_written;
|
|
|
|
if (available == 0) {
|
|
__libc_ringbuf_put_write_buffer(buf, &dest, &available);
|
|
break;
|
|
}
|
|
|
|
if (to_copy > available) {
|
|
to_copy = available;
|
|
}
|
|
|
|
memcpy(dest, src, to_copy);
|
|
|
|
nr_written += available;
|
|
__libc_ringbuf_put_write_buffer(buf, &dest, &to_copy);
|
|
}
|
|
|
|
if (r < 0) {
|
|
return r;
|
|
}
|
|
|
|
return nr_written;
|
|
}
|
|
|
|
int __libc_ringbuf_clear(struct ringbuf *buf)
|
|
{
|
|
buf->buf_readp = buf->buf_writep = 0;
|
|
return 0;
|
|
}
|
|
|
|
int __libc_ringbuf_resize(struct ringbuf *buf, size_t max)
|
|
{
|
|
if (!(buf->buf_flags & RINGBUF_STATIC)) {
|
|
free(buf->buf_ptr);
|
|
buf->buf_ptr = NULL;
|
|
}
|
|
|
|
buf->buf_readp = buf->buf_writep = 0;
|
|
buf->buf_flags &= ~RINGBUF_STATIC;
|
|
buf->buf_max = max;
|
|
return 0;
|
|
}
|
|
|
|
int __libc_ringbuf_resize_static(struct ringbuf *buf, void *p, size_t max)
|
|
{
|
|
if (!(buf->buf_flags & RINGBUF_STATIC)) {
|
|
free(buf->buf_ptr);
|
|
buf->buf_ptr = NULL;
|
|
}
|
|
|
|
buf->buf_readp = buf->buf_writep = 0;
|
|
buf->buf_flags |= RINGBUF_STATIC;
|
|
buf->buf_ptr = p;
|
|
buf->buf_max = max;
|
|
return 0;
|
|
}
|
|
|
|
size_t __libc_ringbuf_available(const struct ringbuf *buf)
|
|
{
|
|
if (buf->buf_readp < buf->buf_writep) {
|
|
return buf->buf_writep - buf->buf_readp;
|
|
} else if (buf->buf_readp > buf->buf_writep) {
|
|
return buf->buf_max - buf->buf_readp + buf->buf_writep;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
size_t __libc_ringbuf_capacity(const struct ringbuf *buf)
|
|
{
|
|
if (buf->buf_readp > buf->buf_writep) {
|
|
return buf->buf_readp - buf->buf_writep - 1;
|
|
} else {
|
|
return buf->buf_max - buf->buf_writep + buf->buf_readp - 1;
|
|
}
|
|
}
|