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. 23207753Smm/// Use an union to make sure that the buffer is properly aligned. 24207753Smmtypedef union { 25207753Smm uint8_t u8[IO_BUFFER_SIZE]; 26207753Smm uint32_t u32[IO_BUFFER_SIZE / sizeof(uint32_t)]; 27207753Smm uint64_t u64[IO_BUFFER_SIZE / sizeof(uint64_t)]; 28207753Smm} io_buf; 29207753Smm 30207753Smm 31207753Smmtypedef struct { 32207753Smm /// Name of the source filename (as given on the command line) or 33207753Smm /// pointer to static "(stdin)" when reading from standard input. 34207753Smm const char *src_name; 35207753Smm 36207753Smm /// Destination filename converted from src_name or pointer to static 37207753Smm /// "(stdout)" when writing to standard output. 38207753Smm char *dest_name; 39207753Smm 40207753Smm /// File descriptor of the source file 41207753Smm int src_fd; 42207753Smm 43207753Smm /// File descriptor of the target file 44207753Smm int dest_fd; 45207753Smm 46207753Smm /// True once end of the source file has been detected. 47207753Smm bool src_eof; 48207753Smm 49207753Smm /// If true, we look for long chunks of zeros and try to create 50207753Smm /// a sparse file. 51207753Smm bool dest_try_sparse; 52207753Smm 53207753Smm /// This is used only if dest_try_sparse is true. This holds the 54207753Smm /// number of zero bytes we haven't written out, because we plan 55207753Smm /// to make that byte range a sparse chunk. 56207753Smm off_t dest_pending_sparse; 57207753Smm 58207753Smm /// Stat of the source file. 59207753Smm struct stat src_st; 60207753Smm 61207753Smm /// Stat of the destination file. 62207753Smm struct stat dest_st; 63207753Smm 64207753Smm} file_pair; 65207753Smm 66207753Smm 67207753Smm/// \brief Initialize the I/O module 68207753Smmextern void io_init(void); 69207753Smm 70207753Smm 71207753Smm/// \brief Disable creation of sparse files when decompressing 72207753Smmextern void io_no_sparse(void); 73207753Smm 74207753Smm 75207753Smm/// \brief Open the source file 76207753Smmextern file_pair *io_open_src(const char *src_name); 77207753Smm 78207753Smm 79207753Smm/// \brief Open the destination file 80207753Smmextern bool io_open_dest(file_pair *pair); 81207753Smm 82207753Smm 83207753Smm/// \brief Closes the file descriptors and frees possible allocated memory 84207753Smm/// 85207753Smm/// The success argument determines if source or destination file gets 86207753Smm/// unlinked: 87207753Smm/// - false: The destination file is unlinked. 88207753Smm/// - true: The source file is unlinked unless writing to stdout or --keep 89207753Smm/// was used. 90207753Smmextern void io_close(file_pair *pair, bool success); 91207753Smm 92207753Smm 93207753Smm/// \brief Reads from the source file to a buffer 94207753Smm/// 95207753Smm/// \param pair File pair having the source file open for reading 96207753Smm/// \param buf Destination buffer to hold the read data 97207753Smm/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX 98207753Smm/// 99207753Smm/// \return On success, number of bytes read is returned. On end of 100207753Smm/// file zero is returned and pair->src_eof set to true. 101207753Smm/// On error, SIZE_MAX is returned and error message printed. 102207753Smmextern size_t io_read(file_pair *pair, io_buf *buf, size_t size); 103207753Smm 104207753Smm 105207753Smm/// \brief Read from source file from given offset to a buffer 106207753Smm/// 107207753Smm/// This is remotely similar to standard pread(). This uses lseek() though, 108207753Smm/// so the read offset is changed on each call. 109207753Smm/// 110207753Smm/// \param pair Seekable source file 111207753Smm/// \param buf Destination buffer 112207753Smm/// \param size Amount of data to read 113207753Smm/// \param pos Offset relative to the beginning of the file, 114207753Smm/// from which the data should be read. 115207753Smm/// 116207753Smm/// \return On success, false is returned. On error, error message 117207753Smm/// is printed and true is returned. 118207753Smmextern bool io_pread(file_pair *pair, io_buf *buf, size_t size, off_t pos); 119207753Smm 120207753Smm 121207753Smm/// \brief Writes a buffer to the destination file 122207753Smm/// 123207753Smm/// \param pair File pair having the destination file open for writing 124207753Smm/// \param buf Buffer containing the data to be written 125207753Smm/// \param size Size of the buffer; assumed be smaller than SSIZE_MAX 126207753Smm/// 127207753Smm/// \return On success, zero is returned. On error, -1 is returned 128207753Smm/// and error message printed. 129207753Smmextern bool io_write(file_pair *pair, const io_buf *buf, size_t size); 130