/* * Copyright (C) 2003, 2004, 2005, 2015 Filip Pizlo. All rights reserved. * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY FILIP PIZLO ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL FILIP PIZLO OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "tsf_internal.h" #include #include #include tsf_bool_t tsf_fd_writer(void *arg, const void *data, uint32_t len) { uint8_t *cur = (uint8_t*)data; int fd = *((int*)arg); while (len) { int res = write(fd, cur, len); if (res < 0) { if (errno == EINTR) { continue; } tsf_set_errno("Calling write() in tsf_fd_writer()"); return tsf_false; } cur += res; len -= res; } return tsf_true; } tsf_bool_t tsf_fd_reader(void *arg, void *data, uint32_t len) { uint8_t *cur=data; int fd=*((int*)arg); while (len) { int res=read(fd,cur,len); if (res<0) { if (errno==EINTR) { continue; } tsf_set_errno("Calling read() in tsf_fd_reader()"); return tsf_false; } if (res==0) { tsf_set_error((void*)cur==data? TSF_E_UNEXPECTED_EOF:TSF_E_ERRONEOUS_EOF, "Calling read() in tsf_fd_reader()"); return tsf_false; } cur+=res; len-=res; } return tsf_true; } int32_t tsf_fd_partial_reader(void *arg, void *data, uint32_t len) { int fd=*((int*)arg); for (;;) { int res=read(fd,data,len); if (res<0) { if (errno==EINTR) { continue; } tsf_set_errno("Calling read() in tsf_fd_partial_reader()"); return -1; } if (res==0) { tsf_set_error(TSF_E_UNEXPECTED_EOF, "Calling read() in tsf_fd_partial_reader()"); return -1; } return res; } } tsf_bool_t tsf_comparing_writer(void *arg, const void *buf, uint32_t len) { tsf_comparing_writer_t *self=arg; void *my_buf=malloc(len); if (my_buf==NULL) { tsf_set_errno("Could not allocate temporary buffer"); return tsf_false; } if (self->reader(self->arg,my_buf,len)) { int res=memcmp(buf,my_buf,len); free(my_buf); if (res==0) { return tsf_true; } else { tsf_set_error(TSF_E_COMPARE_FAIL,NULL); return tsf_false; } } else { free(my_buf); return tsf_false; } } tsf_bool_t tsf_hashing_writer(void *arg, const void *_buf, uint32_t len) { uint8_t *buf = (uint8_t*)_buf; uint32_t *hash = arg; uint32_t h = *hash, g; /* this is the ELF hash, at least according to my hashtable library. */ while (len --> 0) { h = (h << 4) + buf[len]; g = h & 0xf0000000; if (g) { h ^= g >> 24; } h &= ~g; } *hash = h; return tsf_true; } tsf_bool_t tsf_size_calc_writer(void *arg, const void *buf, uint32_t len) { uint32_t *total_len=arg; (*total_len)+=len; return tsf_true; } tsf_bool_t tsf_size_aware_reader(void *arg, void *buf, uint32_t len) { tsf_size_aware_rdr_t *self=arg; if (self->limitname); return tsf_false; } if (!self->reader(self->arg,buf,len)) { return tsf_false; } self->limit-=len; return tsf_true; } tsf_bool_t tsf_buffer_only_writer(void *arg, const void *buf, uint32_t len) { uint8_t **cur = arg; memcpy(*cur, buf, len); (*cur) += len; return tsf_true; } tsf_bool_t tsf_resizable_buffer_writer(void *arg, const void *buf, uint32_t len) { tsf_resizable_buffer_t *resizable = arg; if (resizable->end - resizable->cur < len) { size_t old_size; size_t new_size; uint8_t *new_base; old_size = resizable->end - resizable->base; new_size = (old_size + len) << 1; if (resizable->base == NULL) { new_base = malloc(new_size); } else { new_base = realloc(resizable->base, new_size); } if (new_base == NULL) { tsf_set_errno("Could not malloc resizable buffer"); return tsf_false; } resizable->end = new_base + new_size; resizable->cur = new_base + (resizable->cur - resizable->base); resizable->base = new_base; } memcpy(resizable->cur, buf, len); resizable->cur += len; return tsf_true; } tsf_bool_t tsf_buffer_only_reader(void *arg, void *buf, uint32_t len) { tsf_light_buffer_t *state=arg; if (state->cur == state->end) { tsf_set_error(TSF_E_UNEXPECTED_EOF, "Buffer is empty"); return tsf_false; } if (state->cur+len > state->end) { tsf_set_error(TSF_E_ERRONEOUS_EOF, "Buffer does not have requested data"); return tsf_false; } memcpy(buf,state->cur,len); state->cur+=len; return tsf_true; }