1 #ifndef GZIP_H_ 2 #define GZIP_H_ 3 4 #include "cado_config.h" // for HAVE_GETRUSAGE 5 #include <stdio.h> 6 #ifdef HAVE_GETRUSAGE 7 #include <sys/time.h> // IWYU pragma: keep 8 #include <sys/resource.h> // IWYU pragma: keep 9 #endif 10 11 /* Length of preempt buffer. Must be a power of 2. */ 12 #define PREEMPT_BUF (1<<22) 13 14 /* Length of one write in preempt buffer. Between 64 and 1024 Ko 15 seems best. */ 16 #define PREEMPT_ONE_READ (PREEMPT_BUF>>2) 17 18 #ifdef __cplusplus 19 extern "C" { 20 #endif 21 22 /* Return a unix commands list with antebuffer. Example: 23 * antebuffer X file_relation1 | cat - 24 * antebuffer X file_relation2.gz file_relation3.gz | gzip -dc - 25 * antebuffer X file_relation4.bz2 file_relation5.bz2 | bzip2 -dc - 26 * [empty string] 27 28 * antebuffer_cmd is /path/to/antebuffer <X>, where <X> is an integer 29 * denoting the size of the antebuffer (24 means 2^24 bytes). 30 */ 31 extern char ** prepare_grouped_command_lines (char ** list_of_files); 32 33 /* Search the executable in PATH and, if found, return in real_path the 34 complete path WITH the executable in the end */ 35 char * search_real_exec_in_path(const char *executable, char *real_path); 36 37 /* Search the path of antebuffer and put the complete path + name of the 38 * executable "antebuffer" in a static variable used by the gzip.c layer. 39 * Arguments are the $0 variable (path from cwd to the current executable 40 * file), and path_antebuffer, which is obtained from the command line if 41 * it happens to exist. Either, or both, may be NULL. The rule for 42 * deriving the path to the antebuffer binary is as follows (first match 43 * wins): 44 * 45 * - if path_antebuffer is a complete path to an executable program, use 46 * it. 47 * - if executable_filename is non-NULL, use `dirname 48 * $0`/../utils/antebuffer, if that happens to point to a valid 49 * executable filename. 50 * - otherwise, antebuffer is disabled. 51 * 52 * Configuring to *not* use antebuffer can be done by calling 53 * set_antebuffer_path(NULL, NULL), or not calling it at all. 54 * 55 * The return value is 1 if an executable has been found. 56 * 57 * This is a configuration function which must be called at most once, and in 58 * a monothreaded context. 59 */ 60 int set_antebuffer_path (const char *executable_filename, const char *path_antebuffer); 61 62 /* There are of course scores of existing basename() codes accessible, 63 * starting with POSIX basename. However we fear posible inconsistencies 64 * here, so we stick to a simple-and-stupid version, whose specification 65 * meets our needs. Here, the returned string is always a substring of 66 * the input string, and the latter never undergoes any modification. 67 */ 68 extern const char * path_basename(const char * path); 69 70 extern int is_supported_compression_format(const char * s); 71 extern int filename_matches_one_compression_format(const char * path); 72 73 /* Put in sfx the suffix in s (can be "" or NULL) */ 74 extern void get_suffix_from_filename (char *s, char const **sfx); 75 76 /* Takes a filename, possibly ending with any recognized compression 77 * extension, and returns the associated file stream. The stream may have 78 * been opened by either fopen() of popen(), depending on whether an 79 * external decompression program has to be called. If the caller is 80 * intersted in knowing, the integer *p_pipeflag is filled with 1 (for 81 * popen) or 0 (for fopen). In fact, the caller should care, because this 82 * can be used to decide whether to close the stream with pclose or 83 * fclose (even if fclose works, it's almost guaranteed to create 84 * zombies). 85 * If non-NULL, suf is the location of a pointer which is position to the 86 * recognized suffix, which has been used to decide on which compression 87 * method. 88 */ 89 extern FILE * fopen_maybe_compressed2(const char * name, const char * mode, int* p_pipeflag, char const ** suf); 90 extern FILE * fopen_maybe_compressed(const char * name, const char * mode); 91 92 /* This one just looks at the file name, and guesses again whether popen() or 93 * fopen() was used. The file stream is then closed with pclose() or 94 * fclose() accordingly. */ 95 extern int fclose_maybe_compressed(FILE *, const char * name); 96 97 #ifdef HAVE_GETRUSAGE 98 /* Same, but recovers the time taken by the underlying process */ 99 extern int fclose_maybe_compressed2 (FILE * f, const char * name, struct rusage * r); 100 #endif 101 102 #ifdef __cplusplus 103 } 104 #endif 105 106 #ifdef __cplusplus 107 #include <istream> // std::istream // IWYU pragma: keep 108 #include <ostream> // std::ostream // IWYU pragma: keep 109 #include <memory> 110 class cado_pipe_streambuf; 111 112 class streambase_maybe_compressed : virtual public std::ios { 113 bool pipe; 114 protected: 115 std::unique_ptr<cado_pipe_streambuf> pbuf; 116 std::unique_ptr<std::filebuf> fbuf; 117 std::streambuf * buf; 118 std::string orig_name; 119 std::string tempname; 120 public: 121 /* I don't think that we need a default ctor, do we ? */ 122 streambase_maybe_compressed(const char * name, std::ios_base::openmode mode); 123 /* Note that in output mode, the file will first be created with a 124 * temp name, and eventually only the dtor will move it from that 125 * temp name to the final location. 126 * (this behaviour might be system-dependent). 127 */ 128 ~streambase_maybe_compressed() override; 129 void open(const char * name, std::ios_base::openmode mode); 130 void close(); is_pipe()131 bool is_pipe() const { return pipe; } 132 }; 133 134 template <class charT, class Traits = std::char_traits<charT> > 135 class basic_ifstream_maybe_compressed : public streambase_maybe_compressed, public std::basic_istream<charT, Traits> { 136 public: basic_ifstream_maybe_compressed(const char * name)137 basic_ifstream_maybe_compressed(const char * name) 138 : streambase_maybe_compressed(name, std::ios::in) 139 , std::basic_istream<charT, Traits>(buf) 140 {} open(const char * name)141 void open(const char * name) { 142 streambase_maybe_compressed::open(name, std::ios::in); 143 } 144 }; 145 146 template <class charT, class Traits = std::char_traits<charT> > 147 class basic_ofstream_maybe_compressed : public streambase_maybe_compressed, public std::basic_ostream<charT, Traits> { 148 public: basic_ofstream_maybe_compressed(const char * name)149 basic_ofstream_maybe_compressed(const char * name) 150 : streambase_maybe_compressed(name, std::ios::out) 151 , std::basic_ostream<charT, Traits>(buf) 152 {} open(const char * name)153 void open(const char * name) { 154 streambase_maybe_compressed::open(name, std::ios::out); 155 } 156 }; 157 158 // extern template<> basic_ifstream_maybe_compressed<char>; 159 // extern template<> basic_ofstream_maybe_compressed<char>; 160 161 typedef basic_ifstream_maybe_compressed<char> ifstream_maybe_compressed; 162 typedef basic_ofstream_maybe_compressed<char> ofstream_maybe_compressed; 163 164 #endif 165 166 #endif /* GZIP_H_ */ 167