1207753Smm/////////////////////////////////////////////////////////////////////////////// 2207753Smm// 3207753Smm/// \file file_io.h 4207753Smm/// \brief I/O types and functions 5207753Smm// 6207753Smm// Author: Lasse Collin 7207753Smm// 8207753Smm// This file has been put into the public domain. 9207753Smm// You can do whatever you want with this file. 10207753Smm// 11207753Smm/////////////////////////////////////////////////////////////////////////////// 12207753Smm 13207753Smm// Some systems have suboptimal BUFSIZ. Use a bit bigger value on them. 14207753Smm// We also need that IO_BUFFER_SIZE is a multiple of 8 (sizeof(uint64_t)) 15207753Smm#if BUFSIZ <= 1024 16207753Smm# define IO_BUFFER_SIZE 8192 17207753Smm#else 18207753Smm# define IO_BUFFER_SIZE (BUFSIZ & ~7U) 19207753Smm#endif 20207753Smm 21207753Smm 22207753Smm/// is_sparse() accesses the buffer as uint64_t for maximum speed. 23360523Sdelphij/// The u32 and u64 members must only be access through this union 24360523Sdelphij/// to avoid strict aliasing violations. Taking a pointer of u8 25360523Sdelphij/// should be fine as long as uint8_t maps to unsigned char which 26360523Sdelphij/// can alias anything. 27207753Smmtypedef union { 28207753Smm uint8_t u8[IO_BUFFER_SIZE]; 29207753Smm uint32_t u32[IO_BUFFER_SIZE / sizeof(uint32_t)]; 30207753Smm uint64_t u64[IO_BUFFER_SIZE / sizeof(uint64_t)]; 31207753Smm} io_buf; 32207753Smm 33207753Smm 34207753Smmtypedef struct { 35207753Smm /// Name of the source filename (as given on the command line) or 36207753Smm /// pointer to static "(stdin)" when reading from standard input. 37207753Smm const char *src_name; 38207753Smm 39207753Smm /// Destination filename converted from src_name or pointer to static 40207753Smm /// "(stdout)" when writing to standard output. 41207753Smm char *dest_name; 42207753Smm 43207753Smm /// File descriptor of the source file 44207753Smm int src_fd; 45207753Smm 46207753Smm /// File descriptor of the target file 47207753Smm int dest_fd; 48207753Smm 49207753Smm /// True once end of the source file has been detected. 50207753Smm bool src_eof; 51207753Smm 52360523Sdelphij /// For --flush-timeout: True if at least one byte has been read 53360523Sdelphij /// since the previous flush or the start of the file. 54360523Sdelphij bool src_has_seen_input; 55360523Sdelphij 56360523Sdelphij /// For --flush-timeout: True when flushing is needed. 57360523Sdelphij bool flush_needed; 58360523Sdelphij 59207753Smm /// If true, we look for long chunks of zeros and try to create 60207753Smm /// a sparse file. 61207753Smm bool dest_try_sparse; 62207753Smm 63207753Smm /// This is used only if dest_try_sparse is true. This holds the 64207753Smm /// number of zero bytes we haven't written out, because we plan 65207753Smm /// to make that byte range a sparse chunk. 66207753Smm off_t dest_pending_sparse; 67207753Smm 68207753Smm /// Stat of the source file. 69207753Smm struct stat src_st; 70207753Smm 71207753Smm /// Stat of the destination file. 72207753Smm struct stat dest_st; 73207753Smm 74207753Smm} file_pair; 75207753Smm 76207753Smm 77207753Smm/// \brief Initialize the I/O module 78207753Smmextern void io_init(void); 79207753Smm 80207753Smm 81278433Srpaulo#ifndef TUKLIB_DOSLIKE 82278433Srpaulo/// \brief Write a byte to user_abort_pipe[1] 83278433Srpaulo/// 84278433Srpaulo/// This is called from a signal handler. 85278433Srpauloextern void io_write_to_user_abort_pipe(void); 86278433Srpaulo#endif 87278433Srpaulo 88278433Srpaulo 89207753Smm/// \brief Disable creation of sparse files when decompressing 90207753Smmextern void io_no_sparse(void); 91207753Smm 92207753Smm 93312517Sdelphij#ifdef ENABLE_SANDBOX 94312517Sdelphij/// \brief main() calls this if conditions for sandboxing have been met. 95312517Sdelphijextern void io_allow_sandbox(void); 96312517Sdelphij#endif 97312517Sdelphij 98312517Sdelphij 99207753Smm/// \brief Open the source file 100207753Smmextern file_pair *io_open_src(const char *src_name); 101207753Smm 102207753Smm 103207753Smm/// \brief Open the destination file 104207753Smmextern bool io_open_dest(file_pair *pair); 105207753Smm 106207753Smm 107207753Smm/// \brief Closes the file descriptors and frees possible allocated memory 108207753Smm/// 109207753Smm/// The success argument determines if source or destination file gets 110207753Smm/// unlinked: 111207753Smm/// - false: The destination file is unlinked. 112207753Smm/// - true: The source file is unlinked unless writing to stdout or --keep 113207753Smm/// was used. 114207753Smmextern void io_close(file_pair *pair, bool success); 115207753Smm 116207753Smm 117207753Smm/// \brief Reads from the source file to a buffer 118207753Smm/// 119207753Smm/// \param pair File pair having the source file open for reading 120207753Smm/// \param buf Destination buffer to hold the read data 121207753Smm/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX 122207753Smm/// 123207753Smm/// \return On success, number of bytes read is returned. On end of 124207753Smm/// file zero is returned and pair->src_eof set to true. 125207753Smm/// On error, SIZE_MAX is returned and error message printed. 126207753Smmextern size_t io_read(file_pair *pair, io_buf *buf, size_t size); 127207753Smm 128207753Smm 129278433Srpaulo/// \brief Fix the position in src_fd 130278433Srpaulo/// 131278433Srpaulo/// This is used when --single-thream has been specified and decompression 132278433Srpaulo/// is successful. If the input file descriptor supports seeking, this 133278433Srpaulo/// function fixes the input position to point to the next byte after the 134278433Srpaulo/// decompressed stream. 135278433Srpaulo/// 136278433Srpaulo/// \param pair File pair having the source file open for reading 137278433Srpaulo/// \param rewind_size How many bytes of extra have been read i.e. 138278433Srpaulo/// how much to seek backwards. 139278433Srpauloextern void io_fix_src_pos(file_pair *pair, size_t rewind_size); 140278433Srpaulo 141278433Srpaulo 142207753Smm/// \brief Read from source file from given offset to a buffer 143207753Smm/// 144207753Smm/// This is remotely similar to standard pread(). This uses lseek() though, 145207753Smm/// so the read offset is changed on each call. 146207753Smm/// 147207753Smm/// \param pair Seekable source file 148207753Smm/// \param buf Destination buffer 149207753Smm/// \param size Amount of data to read 150207753Smm/// \param pos Offset relative to the beginning of the file, 151207753Smm/// from which the data should be read. 152207753Smm/// 153207753Smm/// \return On success, false is returned. On error, error message 154207753Smm/// is printed and true is returned. 155207753Smmextern bool io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos); 156207753Smm 157207753Smm 158207753Smm/// \brief Writes a buffer to the destination file 159207753Smm/// 160207753Smm/// \param pair File pair having the destination file open for writing 161207753Smm/// \param buf Buffer containing the data to be written 162207753Smm/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX 163207753Smm/// 164207753Smm/// \return On success, zero is returned. On error, -1 is returned 165207753Smm/// and error message printed. 166207753Smmextern bool io_write(file_pair *pair, const io_buf *buf, size_t size); 167