fopen_compressed.cpp
Go to the documentation of this file.
1 /*
2 ===============================================================================
3 
4  FILE: fopen_compressed.cpp
5 
6  CONTENTS:
7 
8  PROGRAMMERS:
9 
10  martin.isenburg@gmail.com
11 
12  COPYRIGHT:
13 
14  (c) 2003-2011, Martin Isenburg, LASSO - tools to catch reality
15 
16  This is free software; you can redistribute and/or modify it under the
17  terms of the GNU Lesser General Licence as published by the Free Software
18  Foundation. See the COPYING file for more information.
19 
20  This software is distributed WITHOUT ANY WARRANTY and without even the
21  implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
22 
23  CHANGE HISTORY:
24 
25  20 March 2011 -- added capability for *.zip, *.rar, and *.7z on Windows
26  12 December 2003 -- adapted from Stefan Gumhold's SIGGRAPH submission hack
27 
28 ===============================================================================
29 */
30 
31 #include <stdio.h>
32 #include <string.h>
33 
34 #ifdef _WIN32
35 #include <io.h>
36 #include <fcntl.h>
37 #include <process.h>
38 #include <windows.h>
39 #endif
40 
41 enum PIPES { READ_HANDLE, WRITE_HANDLE }; /* Constants 0 and 1 for READ and WRITE */
42 
43 // open a 7zipped/ZIPped/gzipped/rarzipped file as if they were regular a file
44 
45 #ifdef _WIN32
46 static FILE* fopen7zipped(const char* filename, const char* mode)
47 {
48  // check mode
49  if (mode[0] == 'r')
50  {
51  // create the pipe
52  int hPipe[2];
53  if (_pipe(hPipe, 2048, ((mode[1] =='b') ? _O_BINARY : _O_TEXT) | _O_NOINHERIT) == -1)
54  {
55  fprintf(stderr, "could not create pipe\n");
56  return NULL;
57  }
58 
59  // duplicate stdin/stdout handle so we can restore them later
60  int hStdOut = _dup(_fileno(stdout));
61 
62  // make the write end of pipe go to stdout
63  if (_dup2(hPipe[WRITE_HANDLE], _fileno(stdout)) != 0)
64  {
65  fprintf(stderr, "could not set pipe output\n");
66  return NULL;
67  }
68 
69  // redirect read end of pipe to input file
70  if (_dup2(hPipe[READ_HANDLE], _fileno(stdin)) != 0)
71  {
72  fprintf(stderr, "could not redirect input file\n");
73  return NULL;
74  }
75 
76  // close original write end of pipe
77  close(hPipe[WRITE_HANDLE]);
78 
79  // Spawn process
80  HANDLE hProcess = (HANDLE) spawnlp(P_NOWAIT, "7z", "7z", "e", "-so", filename, NULL);
81 
82  // redirect stdout back into stdout
83  if (_dup2(hStdOut, _fileno(stdout)) != 0)
84  {
85  fprintf(stderr, "could not reconstruct stdout\n");
86  return NULL;
87  }
88 
89  // return redirected stdin
90  return stdin;
91  }
92  else
93  {
94  return NULL;
95  }
96 }
97 
98 static FILE* fopenZIPped(const char* filename, const char* mode)
99 {
100  // check mode
101  if (mode[0] == 'r')
102  {
103  // create the pipe
104  int hPipe[2];
105  if (_pipe(hPipe, 2048, ((mode[1] =='b') ? _O_BINARY : _O_TEXT) | _O_NOINHERIT) == -1)
106  {
107  fprintf(stderr, "could not create pipe\n");
108  return NULL;
109  }
110 
111  // duplicate stdin/stdout handle so we can restore them later
112  int hStdOut = _dup(_fileno(stdout));
113 
114  // make the write end of pipe go to stdout
115  if (_dup2(hPipe[WRITE_HANDLE], _fileno(stdout)) != 0)
116  {
117  fprintf(stderr, "could not set pipe output\n");
118  return NULL;
119  }
120 
121  // redirect read end of pipe to input file
122  if (_dup2(hPipe[READ_HANDLE], _fileno(stdin)) != 0)
123  {
124  fprintf(stderr, "could not redirect input file\n");
125  return NULL;
126  }
127 
128  // close original write end of pipe
129  close(hPipe[WRITE_HANDLE]);
130 
131  // Spawn process
132  HANDLE hProcess = (HANDLE) spawnlp(P_NOWAIT, "unzip", "unzip", "-p", filename, NULL);
133 
134  // redirect stdout back into stdout
135  if (_dup2(hStdOut, _fileno(stdout)) != 0)
136  {
137  fprintf(stderr, "could not reconstruct stdout\n");
138  return NULL;
139  }
140 
141  // return redirected stdin
142  return stdin;
143  }
144  else
145  {
146  return NULL;
147  }
148 }
149 
150 static FILE* fopenGzipped(const char* filename, const char* mode)
151 {
152  // check mode
153  if (mode[0] == 'r')
154  {
155  // open input file
156  FILE* gzipInput = fopen(filename, mode);
157  if (!gzipInput) return NULL;
158 
159  // create the pipe
160  int hPipe[2];
161  if (_pipe(hPipe, 2048, ((mode[1] =='b') ? _O_BINARY : _O_TEXT) | _O_NOINHERIT) == -1)
162  {
163  fprintf(stderr, "could not create pipe\n");
164  return NULL;
165  }
166 
167  // duplicate stdin handle
168  int hStdIn = _dup(_fileno(stdin));
169  // redirect stdin to input file
170  if (_dup2(_fileno(gzipInput), _fileno(stdin)) != 0)
171  {
172  fprintf(stderr, "could not redirect stdin\n");
173  return NULL;
174  }
175 
176  // duplicate stdout handle
177  int hStdOut = _dup(_fileno(stdout));
178  // redirect stdout to write end of pipe
179  if (_dup2(hPipe[WRITE_HANDLE], _fileno(stdout)) != 0)
180  {
181  fprintf(stderr, "could not set pipe output\n");
182  return NULL;
183  }
184 
185  // close original write end of pipe
186  close(hPipe[WRITE_HANDLE]);
187 
188  // redirect read end of pipe to input file
189  if (_dup2(hPipe[READ_HANDLE], _fileno(gzipInput)) != 0)
190  {
191  fprintf(stderr, "could not redirect input file\n");
192  return NULL;
193  }
194 
195  // close original read end of pipe
196  close(hPipe[READ_HANDLE]);
197 
198  // Spawn process
199  HANDLE hProcess = (HANDLE) spawnlp(P_NOWAIT, "gzip", "gzip", "-d", NULL);
200 
201  // redirect stdin back into stdin
202  if (_dup2(hStdIn, _fileno(stdin)) != 0)
203  {
204  fprintf(stderr, "could not reconstruct stdin\n");
205  return NULL;
206  }
207 
208  // redirect stdout back into stdout
209  if (_dup2(hStdOut, _fileno(stdout)) != 0)
210  {
211  fprintf(stderr, "could not reconstruct stdout\n");
212  return NULL;
213  }
214 
215  // return input file
216  return gzipInput;
217  }
218  else
219  {
220  return NULL;
221  }
222 }
223 
224 static FILE* fopenGzippedNew(const char* filename, const char* mode)
225 {
226  // check mode
227  if (mode[0] == 'r')
228  {
229  // create the pipe
230  int hPipe[2];
231  if (_pipe(hPipe, 2048, ((mode[1] =='b') ? _O_BINARY : _O_TEXT) | _O_NOINHERIT) == -1)
232  {
233  fprintf(stderr, "could not create pipe\n");
234  return NULL;
235  }
236 
237  // duplicate stdin/stdout handle so we can restore them later
238  int hStdOut = _dup(_fileno(stdout));
239 
240  // make the write end of pipe go to stdout
241  if (_dup2(hPipe[WRITE_HANDLE], _fileno(stdout)) != 0)
242  {
243  fprintf(stderr, "could not set pipe output\n");
244  return NULL;
245  }
246 
247  // redirect read end of pipe to input file
248  if (_dup2(hPipe[READ_HANDLE], _fileno(stdin)) != 0)
249  {
250  fprintf(stderr, "could not redirect input file\n");
251  return NULL;
252  }
253 
254  // close original write end of pipe
255  close(hPipe[WRITE_HANDLE]);
256 
257  // Spawn process
258  HANDLE hProcess = (HANDLE) spawnlp(P_NOWAIT, "gzip", "gzip", "-dc", filename, NULL);
259 
260  // redirect stdout back into stdout
261  if (_dup2(hStdOut, _fileno(stdout)) != 0)
262  {
263  fprintf(stderr, "could not reconstruct stdout\n");
264  return NULL;
265  }
266 
267  // return redirected stdin
268  return stdin;
269  }
270  else
271  {
272  return NULL;
273  }
274 }
275 
276 static FILE* fopenRARed(const char* filename, const char* mode)
277 {
278  // check mode
279  if (mode[0] == 'r')
280  {
281  // create the pipe
282  int hPipe[2];
283  if (_pipe(hPipe, 2048, ((mode[1] =='b') ? _O_BINARY : _O_TEXT) | _O_NOINHERIT) == -1)
284  {
285  fprintf(stderr, "could not create pipe\n");
286  return NULL;
287  }
288 
289  // duplicate stdin/stdout handle so we can restore them later
290  int hStdOut = _dup(_fileno(stdout));
291 
292  // make the write end of pipe go to stdout
293  if (_dup2(hPipe[WRITE_HANDLE], _fileno(stdout)) != 0)
294  {
295  fprintf(stderr, "could not set pipe output\n");
296  return NULL;
297  }
298 
299  // redirect read end of pipe to input file
300  if (_dup2(hPipe[READ_HANDLE], _fileno(stdin)) != 0)
301  {
302  fprintf(stderr, "could not redirect input file\n");
303  return NULL;
304  }
305 
306  // close original write end of pipe
307  close(hPipe[WRITE_HANDLE]);
308 
309  // Spawn process
310  HANDLE hProcess = (HANDLE) spawnlp(P_NOWAIT, "unrar", "unrar", "p", "-ierr", filename, NULL);
311 
312  // redirect stdout back into stdout
313  if (_dup2(hStdOut, _fileno(stdout)) != 0)
314  {
315  fprintf(stderr, "could not reconstruct stdout\n");
316  return NULL;
317  }
318 
319  // return redirected stdin
320  return stdin;
321  }
322  else
323  {
324  return NULL;
325  }
326 }
327 #endif
328 
329 extern "C"
330 {
331 FILE* fopen_compressed(const char* filename, const char* mode, bool* piped)
332 {
333  FILE* file;
334 
335  if (strstr(filename, ".gz"))
336  {
337 #ifdef _WIN32
338  file = fopenGzipped(filename, mode);
339  if (piped) *piped = true;
340 #else
341  fprintf(stderr, "ERROR: no support for gzipped input\n");
342  return 0;
343 #endif
344  }
345  else if (strstr(filename, ".zip"))
346  {
347 #ifdef _WIN32
348  file = fopenZIPped(filename, mode);
349  if (piped) *piped = true;
350 #else
351  fprintf(stderr, "ERROR: no support for ZIPped input\n");
352  return 0;
353 #endif
354  }
355  else if (strstr(filename, ".7z"))
356  {
357 #ifdef _WIN32
358  file = fopen7zipped(filename, mode);
359  if (piped) *piped = true;
360 #else
361  fprintf(stderr, "ERROR: no support for 7zipped input\n");
362  return 0;
363 #endif
364  }
365  else if (strstr(filename, ".rar"))
366  {
367 #ifdef _WIN32
368  file = fopenRARed(filename, mode);
369  if (piped) *piped = true;
370 #else
371  fprintf(stderr, "ERROR: no support for RARed input\n");
372  return 0;
373 #endif
374  }
375  else
376  {
377  file = fopen(filename, mode);
378  if (piped) *piped = false;
379  }
380  return file;
381 }
382 }
FILE * fopen_compressed(const char *filename, const char *mode, bool *piped)
FILE * file
#define NULL
Definition: mydefs.hpp:141


lvr2
Author(s): Thomas Wiemann , Sebastian Pütz , Alexander Mock , Lars Kiesow , Lukas Kalbertodt , Tristan Igelbrink , Johan M. von Behren , Dominik Feldschnieders , Alexander Löhr
autogenerated on Mon Feb 28 2022 22:46:06