Archive-Tar-Builder

 view release on metacpan or  search on metacpan

src/b_buffer.c  view on Meta::CPAN

#include <unistd.h>
#include <errno.h>
#ifdef __linux__
#include <sys/stat.h>
#include <sys/utsname.h>
#include <stdio.h>
#endif
#include "b_buffer.h"

b_buffer *b_buffer_new(size_t factor) {
    b_buffer *buf;

    if ((buf = malloc(sizeof(*buf))) == NULL) {
        goto error_malloc;
    }

    buf->fd         = 0;
    buf->can_splice = 0;
    buf->size       = factor? factor * B_BUFFER_BLOCK_SIZE: B_BUFFER_DEFAULT_FACTOR * B_BUFFER_BLOCK_SIZE;
    buf->unused     = buf->size;

    if ((buf->data = malloc(buf->size)) == NULL) {
        goto error_malloc_buf;
    }

    memset(buf->data, 0x00, buf->size);

    return buf;

error_malloc_buf:
    buf->data       = NULL;
    buf->can_splice = 0;
    buf->fd         = 0;
    buf->size       = 0;

    free(buf);

error_malloc:
    return NULL;
}

int b_buffer_get_fd(b_buffer *buf) {
    if (buf == NULL) return 0;

    return buf->fd;
}

void b_buffer_set_fd(b_buffer *buf, int fd) {
#ifdef __linux__
    struct stat st;
    char *release, *kernel, *major, *minor;
    int kernel_v, major_v, minor_v;
    struct utsname unameData;
    int uname_ok;
#endif
    if (buf == NULL) return;

    buf->fd         = fd;
    buf->can_splice = 0;
#ifdef __linux__
    if (fstat(fd, &st) == 0) {
        if (S_ISFIFO(st.st_mode)) {
            uname_ok = uname(&unameData);
            if (uname_ok != -1) {
                release = unameData.release;
                kernel = strtok(release, ".");
                major = strtok(NULL, ".");
                minor = strtok(NULL, ".");
                if (release && major && minor) {
                    kernel_v = strtol(kernel,NULL,10);
                    major_v = strtol(major,NULL,10);
                    minor_v = strtol(minor,NULL,10);
                    if (kernel_v >= 3 || (kernel_v == 2 && major_v == 6 && minor_v >= 31) ) {
                        buf->can_splice = 1;
                    }
                }
            }
        }
    }
#endif
    return;
}

size_t b_buffer_size(b_buffer *buf) {
    if (buf == NULL) return 0;

    return buf->size;
}

size_t b_buffer_unused(b_buffer *buf) {
    if (buf == NULL) return 0;

    return buf->unused;
}

int b_buffer_full(b_buffer *buf) {
    if (buf == NULL) return 0;

    return buf->unused == 0;
}

static inline size_t padded_size(size_t size) {
    if (size % B_BUFFER_BLOCK_SIZE == 0) {
        return size;
    }

    return size + (B_BUFFER_BLOCK_SIZE - (size % B_BUFFER_BLOCK_SIZE));
}

off_t b_buffer_reclaim(b_buffer *buf, size_t used, size_t given) {
    size_t padded_len = padded_size(used);
    off_t amount;

    if (buf == NULL || given == 0 || given % B_BUFFER_BLOCK_SIZE) {
        errno = EINVAL;
        return -1;
    }

    amount = given - padded_len;

    buf->unused += amount;



( run in 1.110 second using v1.01-cache-2.11-cpan-f56aa216473 )