Routino SVN Repository Browser

Check out the latest version of Routino: svn co http://routino.org/svn/trunk routino

ViewVC logotype

Contents of /branches/MSVC/src/uncompress.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1664 - (show annotations) (download) (as text)
Tue May 19 18:35:19 2015 UTC (9 years, 10 months ago) by amb
File MIME type: text/x-csrc
File size: 9568 byte(s)
Remove <unistd.h> where not needed at all or when compiling with
Microsoft C compiler (in which case add <io.h> and some macros to
replace read/write/open/close/lseek etc.) [inspired by patches from
Oliver Eichler].

1 /***************************************
2 File uncompression.
3
4 Part of the Routino routing software.
5 ******************/ /******************
6 This file Copyright 2012-2015 Andrew M. Bishop
7
8 This program is free software: you can redistribute it and/or modify
9 it under the terms of the GNU Affero General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU Affero General Public License for more details.
17
18 You should have received a copy of the GNU Affero General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ***************************************/
21
22
23 #include <stdlib.h>
24
25 #if defined(_MSC_VER)
26 #include <io.h>
27 #define read(fd,address,length) _read(fd,address,(unsigned int)(length))
28 #define write(fd,address,length) _write(fd,address,(unsigned int)(length))
29 #define close _close
30 #else
31 #include <unistd.h>
32 #endif
33
34 #include <signal.h>
35
36 #if defined(USE_BZIP2) && USE_BZIP2
37 #define BZ_NO_STDIO
38 #include <bzlib.h>
39 #endif
40
41 #if defined(USE_GZIP) && USE_GZIP
42 #include <zlib.h>
43 #endif
44
45 #if defined(USE_XZ) && USE_XZ
46 #include <lzma.h>
47 #endif
48
49 #include "logging.h"
50 #include "uncompress.h"
51
52
53 /* Local functions */
54
55 static int pipe_and_fork(int filefd,int *pipefd);
56
57 #if defined(USE_BZIP2) && USE_BZIP2
58 static void uncompress_bzip2_pipe(int filefd,int pipefd);
59 #endif
60
61 #if defined(USE_GZIP) && USE_GZIP
62 static void uncompress_gzip_pipe(int filefd,int pipefd);
63 #endif
64
65 #if defined(USE_XZ) && USE_XZ
66 static void uncompress_xz_pipe(int filefd,int pipefd);
67 #endif
68
69
70 /*++++++++++++++++++++++++++++++++++++++
71 Create a child process to uncompress data on a file descriptor as if it were a pipe.
72
73 int Uncompress_Bzip2 Returns the file descriptor of the uncompressed end of the pipe.
74
75 int filefd The file descriptor of the compressed end of the pipe.
76 ++++++++++++++++++++++++++++++++++++++*/
77
78 int Uncompress_Bzip2(int filefd)
79 {
80 #if defined(USE_BZIP2) && USE_BZIP2
81
82 int pipefd=-1;
83
84 if(pipe_and_fork(filefd,&pipefd))
85 return(pipefd);
86
87 uncompress_bzip2_pipe(filefd,pipefd);
88
89 exit(EXIT_SUCCESS);
90
91 #else /* USE_BZIP2 */
92
93 logassert(0,"No bzip2 compression support available (re-compile and try again)");
94
95 return(0);
96
97 #endif /* USE_BZIP2 */
98 }
99
100
101 /*++++++++++++++++++++++++++++++++++++++
102 Create a child process to uncompress data on a file descriptor as if it were a pipe.
103
104 int Uncompress_Gzip Returns the file descriptor of the uncompressed end of the pipe.
105
106 int filefd The file descriptor of the compressed end of the pipe.
107 ++++++++++++++++++++++++++++++++++++++*/
108
109 int Uncompress_Gzip(int filefd)
110 {
111 #if defined(USE_GZIP) && USE_GZIP
112
113 int pipefd=-1;
114
115 if(pipe_and_fork(filefd,&pipefd))
116 return(pipefd);
117
118 uncompress_gzip_pipe(filefd,pipefd);
119
120 exit(EXIT_SUCCESS);
121
122 #else /* USE_GZIP */
123
124 logassert(0,"No gzip compression support available (re-compile and try again)");
125
126 return(0);
127
128 #endif /* USE_GZIP */
129 }
130
131
132 /*++++++++++++++++++++++++++++++++++++++
133 Create a child process to uncompress data on a file descriptor as if it were a pipe.
134
135 int Uncompress_Xz Returns the file descriptor of the uncompressed end of the pipe.
136
137 int filefd The file descriptor of the compressed end of the pipe.
138 ++++++++++++++++++++++++++++++++++++++*/
139
140 int Uncompress_Xz(int filefd)
141 {
142 #if defined(USE_XZ) && USE_XZ
143
144 int pipefd=-1;
145
146 if(pipe_and_fork(filefd,&pipefd))
147 return(pipefd);
148
149 uncompress_xz_pipe(filefd,pipefd);
150
151 exit(EXIT_SUCCESS);
152
153 #else /* USE_XZ */
154
155 logassert(0,"No xz compression support available (re-compile and try again)");
156
157 return(0);
158
159 #endif /* USE_XZ */
160 }
161
162
163 /*++++++++++++++++++++++++++++++++++++++
164 Create a pipe and then fork returning in the parent and child with a different end of the pipe.
165
166 int pipe_and_fork Returns 1 for the reading (parent) end of the pipe and 0 for the writing (child) end.
167
168 int filefd The file descriptor of the file.
169
170 int *pipefd Returns the file descriptor for the end of the pipe.
171 ++++++++++++++++++++++++++++++++++++++*/
172
173 static int pipe_and_fork(int filefd,int *pipefd)
174 {
175 int pipe_fd[2]={-1,-1};
176 pid_t childpid;
177
178 #define PIPE_READER 0
179 #define PIPE_WRITER 1
180
181 if(pipe(pipe_fd))
182 {
183 logassert(0,"Cannot create pipe for uncompressor (try without using a compressed file)");
184 return(1);
185 }
186
187 if((childpid=fork()) == -1)
188 {
189 logassert(0,"Cannot create new process for uncompressor (try without using a compressed file)");
190 return(1);
191 }
192
193 if(childpid==0) /* The child */
194 {
195 int i;
196
197 *pipefd=pipe_fd[PIPE_WRITER];
198
199 /* Close all unneeded file descriptors */
200
201 for(i=0;i<255;i++)
202 if(i!=filefd && i!=*pipefd)
203 close(i);
204
205 return(0);
206 }
207 else /* The parent */
208 {
209 struct sigaction action;
210
211 *pipefd=pipe_fd[PIPE_READER];
212
213 /* Close all unneeded file descriptors */
214
215 close(pipe_fd[PIPE_WRITER]);
216 close(filefd);
217
218 /* Ignore child exiting and pipe signals */
219
220 /* SIGCHLD */
221 action.sa_handler=SIG_IGN;
222 sigemptyset(&action.sa_mask);
223 action.sa_flags=0;
224 sigaction(SIGCHLD,&action,NULL);
225
226 /* SIGPIPE */
227 action.sa_handler=SIG_IGN;
228 sigemptyset(&action.sa_mask);
229 action.sa_flags=0;
230 sigaction(SIGPIPE,&action,NULL);
231
232 return(1);
233 }
234 }
235
236
237 #if defined(USE_BZIP2) && USE_BZIP2
238
239 /*++++++++++++++++++++++++++++++++++++++
240 Uncompress a file using bzip2 as a pipeline.
241
242 int filefd The incoming, compressed, data.
243
244 int pipefd The outgoing, uncompressed, data.
245 ++++++++++++++++++++++++++++++++++++++*/
246
247 static void uncompress_bzip2_pipe(int filefd,int pipefd)
248 {
249 bz_stream bz={0};
250 char inbuffer[16384],outbuffer[16384];
251 int infinished=0;
252 int state;
253
254 if(BZ2_bzDecompressInit(&bz,0,0)!=BZ_OK)
255 exit(EXIT_FAILURE);
256
257 do
258 {
259 if(bz.avail_in==0 && !infinished)
260 {
261 ssize_t n=read(filefd,inbuffer,sizeof(inbuffer));
262
263 if(n<=0)
264 infinished=1;
265 else
266 {
267 bz.next_in=inbuffer;
268 bz.avail_in=n;
269 }
270 }
271
272 bz.next_out=outbuffer;
273 bz.avail_out=sizeof(outbuffer);
274
275 state=BZ2_bzDecompress(&bz);
276
277 if(state!=BZ_OK && state!=BZ_STREAM_END)
278 exit(EXIT_FAILURE);
279
280 if(bz.avail_out<sizeof(outbuffer))
281 {
282 char *p;
283 ssize_t m,n;
284
285 p=outbuffer;
286 n=sizeof(outbuffer)-bz.avail_out;
287
288 while(n>0)
289 {
290 m=write(pipefd,p,n);
291
292 if(m<=0)
293 exit(EXIT_FAILURE);
294
295 p+=m;
296 n-=m;
297 }
298 }
299 }
300 while(state!=BZ_STREAM_END);
301
302 if(BZ2_bzDecompressEnd(&bz)!=BZ_OK)
303 exit(EXIT_FAILURE);
304
305 exit(EXIT_SUCCESS);
306 }
307
308 #endif /* USE_BZIP2 */
309
310
311 #if defined(USE_GZIP) && USE_GZIP
312
313 /*++++++++++++++++++++++++++++++++++++++
314 Uncompress a file using gzip as a pipeline.
315
316 int filefd The incoming, compressed, data.
317
318 int pipefd The outgoing, uncompressed, data.
319 ++++++++++++++++++++++++++++++++++++++*/
320
321 static void uncompress_gzip_pipe(int filefd,int pipefd)
322 {
323 z_stream z={0};
324 unsigned char inbuffer[16384],outbuffer[16384];
325 int infinished=0;
326 int state;
327
328 if(inflateInit2(&z,15+32)!=Z_OK)
329 exit(EXIT_FAILURE);
330
331 do
332 {
333 if(z.avail_in==0 && !infinished)
334 {
335 ssize_t n=read(filefd,inbuffer,sizeof(inbuffer));
336
337 if(n<=0)
338 infinished=1;
339 else
340 {
341 z.next_in=inbuffer;
342 z.avail_in=n;
343 }
344 }
345
346 z.next_out=outbuffer;
347 z.avail_out=sizeof(outbuffer);
348
349 state=inflate(&z,Z_NO_FLUSH);
350
351 if(state!=Z_OK && state!=Z_STREAM_END)
352 {
353 exit(EXIT_FAILURE);
354 }
355
356 if(z.avail_out<sizeof(outbuffer))
357 {
358 unsigned char *p;
359 ssize_t n,m;
360
361 p=outbuffer;
362 n=sizeof(outbuffer)-z.avail_out;
363
364 while(n>0)
365 {
366 m=write(pipefd,p,n);
367
368 if(m<=0)
369 exit(EXIT_FAILURE);
370
371 p+=m;
372 n-=m;
373 }
374 }
375 }
376 while(state!=Z_STREAM_END);
377
378 if(inflateEnd(&z)!=Z_OK)
379 exit(EXIT_FAILURE);
380
381 exit(EXIT_SUCCESS);
382 }
383
384 #endif /* USE_GZIP */
385
386
387 #if defined(USE_XZ) && USE_XZ
388
389 /*++++++++++++++++++++++++++++++++++++++
390 Uncompress a file using xz as a pipeline.
391
392 int filefd The incoming, compressed, data.
393
394 int pipefd The outgoing, uncompressed, data.
395 ++++++++++++++++++++++++++++++++++++++*/
396
397 static void uncompress_xz_pipe(int filefd,int pipefd)
398 {
399 lzma_stream lzma=LZMA_STREAM_INIT;
400 unsigned char inbuffer[16384],outbuffer[16384];
401 int infinished=0;
402 lzma_ret retval;
403
404 if(lzma_stream_decoder(&lzma,UINT64_MAX,0)!=LZMA_OK)
405 exit(EXIT_FAILURE);
406
407 do
408 {
409 if(lzma.avail_in==0 && !infinished)
410 {
411 ssize_t n=read(filefd,inbuffer,sizeof(inbuffer));
412
413 if(n<=0)
414 infinished=1;
415 else
416 {
417 lzma.next_in=inbuffer;
418 lzma.avail_in=n;
419 }
420 }
421
422 lzma.next_out=outbuffer;
423 lzma.avail_out=sizeof(outbuffer);
424
425 retval=lzma_code(&lzma,LZMA_RUN);
426
427 if(retval!=LZMA_OK && retval!=LZMA_STREAM_END)
428 {
429 exit(EXIT_FAILURE);
430 }
431
432 if(lzma.avail_out<sizeof(outbuffer))
433 {
434 unsigned char *p;
435 ssize_t n,m;
436
437 p=outbuffer;
438 n=sizeof(outbuffer)-lzma.avail_out;
439
440 while(n>0)
441 {
442 m=write(pipefd,p,n);
443
444 if(m<=0)
445 exit(EXIT_FAILURE);
446
447 p+=m;
448 n-=m;
449 }
450 }
451 }
452 while(retval!=LZMA_STREAM_END);
453
454 lzma_end(&lzma);
455
456 exit(EXIT_SUCCESS);
457 }
458
459 #endif /* USE_XZ */