/* * 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 "tsf_format.h" #include "tsf_serial_protocol.h" #include #include #include #include /* the get mode functions are here for historical reasons. right now all of * the actual detection work happens in the adaptive reader. */ tsf_zip_mode_t tsf_stream_file_get_mode_from_fd(int fd) { uint8_t magic[TSF_SP_MAGIC_LEN]; uint8_t *cur=magic; while (curfd=fd; ret->keep_fd=keep; if (tsf_zip_rdr_attr_is_nozip(&attr)) { ret->use_adpt=tsf_false; ret->reader.buf=tsf_buf_reader_create(ret->fd, buf_size, tsf_false); reader=tsf_buf_reader_read; } else { ret->use_adpt=tsf_true; ret->reader.adpt=tsf_adaptive_reader_create(tsf_fd_partial_reader, &(ret->fd), buf_size, &attr); reader=tsf_adaptive_reader_read; } if (ret->reader.ptr==NULL) { free(ret); return NULL; } ret->in_man=tsf_serial_in_man_create(reader, ret->reader.ptr, limits); if (ret->in_man==NULL) { if (ret->use_adpt) { tsf_adaptive_reader_destroy(ret->reader.adpt); } else { tsf_buf_reader_destroy(ret->reader.buf); } free(ret); return NULL; } /* if we ever have a * tsf_serial_in_man_pretend_that_youve_read_reset_types() * function, we should call it here. */ return ret; } void tsf_stream_file_input_close(tsf_stream_file_input_t *file) { tsf_serial_in_man_destroy(file->in_man); if (file->keep_fd) { close(file->fd); } else { /* try to seek the file descriptor back to where it should have been, if we hadn't been reading with buffering. */ uint32_t num_remaining; if (file->use_adpt) { num_remaining=tsf_adaptive_reader_get_remaining(file->reader.adpt); } else { num_remaining=tsf_buf_reader_get_remaining(file->reader.buf); } lseek(file->fd,-((off_t)num_remaining),SEEK_CUR); /* ignore error, since this is best effort anyway. */ } if (file->use_adpt) { tsf_adaptive_reader_destroy(file->reader.adpt); } else { tsf_buf_reader_destroy(file->reader.buf); } free(file); } tsf_bool_t tsf_stream_file_input_allows_compression(tsf_stream_file_input_t *file) { return file->use_adpt; } tsf_bool_t tsf_stream_file_input_register_type_cback(tsf_stream_file_input_t *file, tsf_type_cback_t cback, void *arg) { return tsf_serial_in_man_register_type_cback(file->in_man, cback, arg); } tsf_bool_t tsf_stream_file_input_unregister_type_cback(tsf_stream_file_input_t *file, tsf_type_cback_t cback, void *arg) { return tsf_serial_in_man_unregister_type_cback(file->in_man, cback, arg); } tsf_buffer_t *tsf_stream_file_input_read(tsf_stream_file_input_t *file) { if (file->use_adpt) { tsf_adaptive_reader_hint_switch(file->reader.adpt); } return tsf_serial_in_man_read(file->in_man); } tsf_bool_t tsf_stream_file_input_read_existing_buffer(tsf_stream_file_input_t *file, tsf_buffer_t *buf) { if (file->use_adpt) { tsf_adaptive_reader_hint_switch(file->reader.adpt); } return tsf_serial_in_man_read_existing_buffer(file->in_man, buf); } tsf_bool_t tsf_stream_file_input_get_mark(tsf_stream_file_input_t *file, tsf_stream_file_mark_t *mark) { if (file->use_adpt) { tsf_set_error(TSF_E_NOT_SUPPORTED, "tsf_stream_file_input_get_mark() is not supported if " "compression is allowed"); return tsf_false; } mark->offset = lseek(file->fd, (off_t) 0, SEEK_CUR); if (mark->offset<0) { tsf_set_errno("Could not lseek() in " "tsf_stream_file_input_get_mark_of_next()"); return tsf_false; } mark->offset -= tsf_buf_reader_get_remaining(file->reader.buf); mark->state = tsf_serial_in_man_get_state(file->in_man); return tsf_true; } tsf_bool_t tsf_stream_file_input_seek(tsf_stream_file_input_t *file, const tsf_stream_file_mark_t *mark) { /* if the file is compressed then the user should not have been able * to get a mark. */ tsf_assert(!file->use_adpt); if (lseek(file->fd, mark->offset, SEEK_SET) < 0) { tsf_set_errno("Could not lseek() in " "tsf_stream_file_input_seek_to_mark()"); return tsf_false; } tsf_buf_reader_reset(file->reader.buf); tsf_serial_in_man_set_state(file->in_man, mark->state); return tsf_true; }