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