OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [zlib/] [examples/] [gun.c] - Blame information for rev 867

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 745 jeremybenn
/* gun.c -- simple gunzip to give an example of the use of inflateBack()
2
 * Copyright (C) 2003, 2005 Mark Adler
3
 * For conditions of distribution and use, see copyright notice in zlib.h
4
   Version 1.3  12 June 2005  Mark Adler */
5
 
6
/* Version history:
7
   1.0  16 Feb 2003  First version for testing of inflateBack()
8
   1.1  21 Feb 2005  Decompress concatenated gzip streams
9
                     Remove use of "this" variable (C++ keyword)
10
                     Fix return value for in()
11
                     Improve allocation failure checking
12
                     Add typecasting for void * structures
13
                     Add -h option for command version and usage
14
                     Add a bunch of comments
15
   1.2  20 Mar 2005  Add Unix compress (LZW) decompression
16
                     Copy file attributes from input file to output file
17
   1.3  12 Jun 2005  Add casts for error messages [Oberhumer]
18
 */
19
 
20
/*
21
   gun [ -t ] [ name ... ]
22
 
23
   decompresses the data in the named gzip files.  If no arguments are given,
24
   gun will decompress from stdin to stdout.  The names must end in .gz, -gz,
25
   .z, -z, _z, or .Z.  The uncompressed data will be written to a file name
26
   with the suffix stripped.  On success, the original file is deleted.  On
27
   failure, the output file is deleted.  For most failures, the command will
28
   continue to process the remaining names on the command line.  A memory
29
   allocation failure will abort the command.  If -t is specified, then the
30
   listed files or stdin will be tested as gzip files for integrity (without
31
   checking for a proper suffix), no output will be written, and no files
32
   will be deleted.
33
 
34
   Like gzip, gun allows concatenated gzip streams and will decompress them,
35
   writing all of the uncompressed data to the output.  Unlike gzip, gun allows
36
   an empty file on input, and will produce no error writing an empty output
37
   file.
38
 
39
   gun will also decompress files made by Unix compress, which uses LZW
40
   compression.  These files are automatically detected by virtue of their
41
   magic header bytes.  Since the end of Unix compress stream is marked by the
42
   end-of-file, they cannot be concantenated.  If a Unix compress stream is
43
   encountered in an input file, it is the last stream in that file.
44
 
45
   Like gunzip and uncompress, the file attributes of the orignal compressed
46
   file are maintained in the final uncompressed file, to the extent that the
47
   user permissions allow it.
48
 
49
   On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
50
   1.2.4) is on the same file, when gun is linked with zlib 1.2.2.  Also the
51
   LZW decompression provided by gun is about twice as fast as the standard
52
   Unix uncompress command.
53
 */
54
 
55
/* external functions and related types and constants */
56
#include <stdio.h>          /* fprintf() */
57
#include <stdlib.h>         /* malloc(), free() */
58
#include <string.h>         /* strerror(), strcmp(), strlen(), memcpy() */
59
#include <errno.h>          /* errno */
60
#include <fcntl.h>          /* open() */
61
#include <unistd.h>         /* read(), write(), close(), chown(), unlink() */
62
#include <sys/types.h>
63
#include <sys/stat.h>       /* stat(), chmod() */
64
#include <utime.h>          /* utime() */
65
#include "zlib.h"           /* inflateBackInit(), inflateBack(), */
66
                            /* inflateBackEnd(), crc32() */
67
 
68
/* function declaration */
69
#define local static
70
 
71
/* buffer constants */
72
#define SIZE 32768U         /* input and output buffer sizes */
73
#define PIECE 16384         /* limits i/o chunks for 16-bit int case */
74
 
75
/* structure for infback() to pass to input function in() -- it maintains the
76
   input file and a buffer of size SIZE */
77
struct ind {
78
    int infile;
79
    unsigned char *inbuf;
80
};
81
 
82
/* Load input buffer, assumed to be empty, and return bytes loaded and a
83
   pointer to them.  read() is called until the buffer is full, or until it
84
   returns end-of-file or error.  Return 0 on error. */
85
local unsigned in(void *in_desc, unsigned char **buf)
86
{
87
    int ret;
88
    unsigned len;
89
    unsigned char *next;
90
    struct ind *me = (struct ind *)in_desc;
91
 
92
    next = me->inbuf;
93
    *buf = next;
94
    len = 0;
95
    do {
96
        ret = PIECE;
97
        if ((unsigned)ret > SIZE - len)
98
            ret = (int)(SIZE - len);
99
        ret = (int)read(me->infile, next, ret);
100
        if (ret == -1) {
101
            len = 0;
102
            break;
103
        }
104
        next += ret;
105
        len += ret;
106
    } while (ret != 0 && len < SIZE);
107
    return len;
108
}
109
 
110
/* structure for infback() to pass to output function out() -- it maintains the
111
   output file, a running CRC-32 check on the output and the total number of
112
   bytes output, both for checking against the gzip trailer.  (The length in
113
   the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
114
   the output is greater than 4 GB.) */
115
struct outd {
116
    int outfile;
117
    int check;                  /* true if checking crc and total */
118
    unsigned long crc;
119
    unsigned long total;
120
};
121
 
122
/* Write output buffer and update the CRC-32 and total bytes written.  write()
123
   is called until all of the output is written or an error is encountered.
124
   On success out() returns 0.  For a write failure, out() returns 1.  If the
125
   output file descriptor is -1, then nothing is written.
126
 */
127
local int out(void *out_desc, unsigned char *buf, unsigned len)
128
{
129
    int ret;
130
    struct outd *me = (struct outd *)out_desc;
131
 
132
    if (me->check) {
133
        me->crc = crc32(me->crc, buf, len);
134
        me->total += len;
135
    }
136
    if (me->outfile != -1)
137
        do {
138
            ret = PIECE;
139
            if ((unsigned)ret > len)
140
                ret = (int)len;
141
            ret = (int)write(me->outfile, buf, ret);
142
            if (ret == -1)
143
                return 1;
144
            buf += ret;
145
            len -= ret;
146
        } while (len != 0);
147
    return 0;
148
}
149
 
150
/* next input byte macro for use inside lunpipe() and gunpipe() */
151
#define NEXT() (have ? 0 : (have = in(indp, &next)), \
152
                last = have ? (have--, (int)(*next++)) : -1)
153
 
154
/* memory for gunpipe() and lunpipe() --
155
   the first 256 entries of prefix[] and suffix[] are never used, could
156
   have offset the index, but it's faster to waste the memory */
157
unsigned char inbuf[SIZE];              /* input buffer */
158
unsigned char outbuf[SIZE];             /* output buffer */
159
unsigned short prefix[65536];           /* index to LZW prefix string */
160
unsigned char suffix[65536];            /* one-character LZW suffix */
161
unsigned char match[65280 + 2];         /* buffer for reversed match or gzip
162
                                           32K sliding window */
163
 
164
/* throw out what's left in the current bits byte buffer (this is a vestigial
165
   aspect of the compressed data format derived from an implementation that
166
   made use of a special VAX machine instruction!) */
167
#define FLUSHCODE() \
168
    do { \
169
        left = 0; \
170
        rem = 0; \
171
        if (chunk > have) { \
172
            chunk -= have; \
173
            have = 0; \
174
            if (NEXT() == -1) \
175
                break; \
176
            chunk--; \
177
            if (chunk > have) { \
178
                chunk = have = 0; \
179
                break; \
180
            } \
181
        } \
182
        have -= chunk; \
183
        next += chunk; \
184
        chunk = 0; \
185
    } while (0)
186
 
187
/* Decompress a compress (LZW) file from indp to outfile.  The compress magic
188
   header (two bytes) has already been read and verified.  There are have bytes
189
   of buffered input at next.  strm is used for passing error information back
190
   to gunpipe().
191
 
192
   lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
193
   file, read error, or write error (a write error indicated by strm->next_in
194
   not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
195
 */
196
local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
197
                  int outfile, z_stream *strm)
198
{
199
    int last;                   /* last byte read by NEXT(), or -1 if EOF */
200
    int chunk;                  /* bytes left in current chunk */
201
    int left;                   /* bits left in rem */
202
    unsigned rem;               /* unused bits from input */
203
    int bits;                   /* current bits per code */
204
    unsigned code;              /* code, table traversal index */
205
    unsigned mask;              /* mask for current bits codes */
206
    int max;                    /* maximum bits per code for this stream */
207
    int flags;                  /* compress flags, then block compress flag */
208
    unsigned end;               /* last valid entry in prefix/suffix tables */
209
    unsigned temp;              /* current code */
210
    unsigned prev;              /* previous code */
211
    unsigned final;             /* last character written for previous code */
212
    unsigned stack;             /* next position for reversed string */
213
    unsigned outcnt;            /* bytes in output buffer */
214
    struct outd outd;           /* output structure */
215
 
216
    /* set up output */
217
    outd.outfile = outfile;
218
    outd.check = 0;
219
 
220
    /* process remainder of compress header -- a flags byte */
221
    flags = NEXT();
222
    if (last == -1)
223
        return Z_BUF_ERROR;
224
    if (flags & 0x60) {
225
        strm->msg = (char *)"unknown lzw flags set";
226
        return Z_DATA_ERROR;
227
    }
228
    max = flags & 0x1f;
229
    if (max < 9 || max > 16) {
230
        strm->msg = (char *)"lzw bits out of range";
231
        return Z_DATA_ERROR;
232
    }
233
    if (max == 9)                           /* 9 doesn't really mean 9 */
234
        max = 10;
235
    flags &= 0x80;                          /* true if block compress */
236
 
237
    /* clear table */
238
    bits = 9;
239
    mask = 0x1ff;
240
    end = flags ? 256 : 255;
241
 
242
    /* set up: get first 9-bit code, which is the first decompressed byte, but
243
       don't create a table entry until the next code */
244
    if (NEXT() == -1)                       /* no compressed data is ok */
245
        return Z_OK;
246
    final = prev = (unsigned)last;          /* low 8 bits of code */
247
    if (NEXT() == -1)                       /* missing a bit */
248
        return Z_BUF_ERROR;
249
    if (last & 1) {                         /* code must be < 256 */
250
        strm->msg = (char *)"invalid lzw code";
251
        return Z_DATA_ERROR;
252
    }
253
    rem = (unsigned)last >> 1;              /* remaining 7 bits */
254
    left = 7;
255
    chunk = bits - 2;                       /* 7 bytes left in this chunk */
256
    outbuf[0] = (unsigned char)final;       /* write first decompressed byte */
257
    outcnt = 1;
258
 
259
    /* decode codes */
260
    stack = 0;
261
    for (;;) {
262
        /* if the table will be full after this, increment the code size */
263
        if (end >= mask && bits < max) {
264
            FLUSHCODE();
265
            bits++;
266
            mask <<= 1;
267
            mask++;
268
        }
269
 
270
        /* get a code of length bits */
271
        if (chunk == 0)                     /* decrement chunk modulo bits */
272
            chunk = bits;
273
        code = rem;                         /* low bits of code */
274
        if (NEXT() == -1) {                 /* EOF is end of compressed data */
275
            /* write remaining buffered output */
276
            if (outcnt && out(&outd, outbuf, outcnt)) {
277
                strm->next_in = outbuf;     /* signal write error */
278
                return Z_BUF_ERROR;
279
            }
280
            return Z_OK;
281
        }
282
        code += (unsigned)last << left;     /* middle (or high) bits of code */
283
        left += 8;
284
        chunk--;
285
        if (bits > left) {                  /* need more bits */
286
            if (NEXT() == -1)               /* can't end in middle of code */
287
                return Z_BUF_ERROR;
288
            code += (unsigned)last << left; /* high bits of code */
289
            left += 8;
290
            chunk--;
291
        }
292
        code &= mask;                       /* mask to current code length */
293
        left -= bits;                       /* number of unused bits */
294
        rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
295
 
296
        /* process clear code (256) */
297
        if (code == 256 && flags) {
298
            FLUSHCODE();
299
            bits = 9;                       /* initialize bits and mask */
300
            mask = 0x1ff;
301
            end = 255;                      /* empty table */
302
            continue;                       /* get next code */
303
        }
304
 
305
        /* special code to reuse last match */
306
        temp = code;                        /* save the current code */
307
        if (code > end) {
308
            /* Be picky on the allowed code here, and make sure that the code
309
               we drop through (prev) will be a valid index so that random
310
               input does not cause an exception.  The code != end + 1 check is
311
               empirically derived, and not checked in the original uncompress
312
               code.  If this ever causes a problem, that check could be safely
313
               removed.  Leaving this check in greatly improves gun's ability
314
               to detect random or corrupted input after a compress header.
315
               In any case, the prev > end check must be retained. */
316
            if (code != end + 1 || prev > end) {
317
                strm->msg = (char *)"invalid lzw code";
318
                return Z_DATA_ERROR;
319
            }
320
            match[stack++] = (unsigned char)final;
321
            code = prev;
322
        }
323
 
324
        /* walk through linked list to generate output in reverse order */
325
        while (code >= 256) {
326
            match[stack++] = suffix[code];
327
            code = prefix[code];
328
        }
329
        match[stack++] = (unsigned char)code;
330
        final = code;
331
 
332
        /* link new table entry */
333
        if (end < mask) {
334
            end++;
335
            prefix[end] = (unsigned short)prev;
336
            suffix[end] = (unsigned char)final;
337
        }
338
 
339
        /* set previous code for next iteration */
340
        prev = temp;
341
 
342
        /* write output in forward order */
343
        while (stack > SIZE - outcnt) {
344
            while (outcnt < SIZE)
345
                outbuf[outcnt++] = match[--stack];
346
            if (out(&outd, outbuf, outcnt)) {
347
                strm->next_in = outbuf; /* signal write error */
348
                return Z_BUF_ERROR;
349
            }
350
            outcnt = 0;
351
        }
352
        do {
353
            outbuf[outcnt++] = match[--stack];
354
        } while (stack);
355
 
356
        /* loop for next code with final and prev as the last match, rem and
357
           left provide the first 0..7 bits of the next code, end is the last
358
           valid table entry */
359
    }
360
}
361
 
362
/* Decompress a gzip file from infile to outfile.  strm is assumed to have been
363
   successfully initialized with inflateBackInit().  The input file may consist
364
   of a series of gzip streams, in which case all of them will be decompressed
365
   to the output file.  If outfile is -1, then the gzip stream(s) integrity is
366
   checked and nothing is written.
367
 
368
   The return value is a zlib error code: Z_MEM_ERROR if out of memory,
369
   Z_DATA_ERROR if the header or the compressed data is invalid, or if the
370
   trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
371
   prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
372
   stream) follows a valid gzip stream.
373
 */
374
local int gunpipe(z_stream *strm, int infile, int outfile)
375
{
376
    int ret, first, last;
377
    unsigned have, flags, len;
378
    unsigned char *next;
379
    struct ind ind, *indp;
380
    struct outd outd;
381
 
382
    /* setup input buffer */
383
    ind.infile = infile;
384
    ind.inbuf = inbuf;
385
    indp = &ind;
386
 
387
    /* decompress concatenated gzip streams */
388
    have = 0;                               /* no input data read in yet */
389
    first = 1;                              /* looking for first gzip header */
390
    strm->next_in = Z_NULL;                 /* so Z_BUF_ERROR means EOF */
391
    for (;;) {
392
        /* look for the two magic header bytes for a gzip stream */
393
        if (NEXT() == -1) {
394
            ret = Z_OK;
395
            break;                          /* empty gzip stream is ok */
396
        }
397
        if (last != 31 || (NEXT() != 139 && last != 157)) {
398
            strm->msg = (char *)"incorrect header check";
399
            ret = first ? Z_DATA_ERROR : Z_ERRNO;
400
            break;                          /* not a gzip or compress header */
401
        }
402
        first = 0;                          /* next non-header is junk */
403
 
404
        /* process a compress (LZW) file -- can't be concatenated after this */
405
        if (last == 157) {
406
            ret = lunpipe(have, next, indp, outfile, strm);
407
            break;
408
        }
409
 
410
        /* process remainder of gzip header */
411
        ret = Z_BUF_ERROR;
412
        if (NEXT() != 8) {                  /* only deflate method allowed */
413
            if (last == -1) break;
414
            strm->msg = (char *)"unknown compression method";
415
            ret = Z_DATA_ERROR;
416
            break;
417
        }
418
        flags = NEXT();                     /* header flags */
419
        NEXT();                             /* discard mod time, xflgs, os */
420
        NEXT();
421
        NEXT();
422
        NEXT();
423
        NEXT();
424
        NEXT();
425
        if (last == -1) break;
426
        if (flags & 0xe0) {
427
            strm->msg = (char *)"unknown header flags set";
428
            ret = Z_DATA_ERROR;
429
            break;
430
        }
431
        if (flags & 4) {                    /* extra field */
432
            len = NEXT();
433
            len += (unsigned)(NEXT()) << 8;
434
            if (last == -1) break;
435
            while (len > have) {
436
                len -= have;
437
                have = 0;
438
                if (NEXT() == -1) break;
439
                len--;
440
            }
441
            if (last == -1) break;
442
            have -= len;
443
            next += len;
444
        }
445
        if (flags & 8)                      /* file name */
446
            while (NEXT() != 0 && last != -1)
447
                ;
448
        if (flags & 16)                     /* comment */
449
            while (NEXT() != 0 && last != -1)
450
                ;
451
        if (flags & 2) {                    /* header crc */
452
            NEXT();
453
            NEXT();
454
        }
455
        if (last == -1) break;
456
 
457
        /* set up output */
458
        outd.outfile = outfile;
459
        outd.check = 1;
460
        outd.crc = crc32(0L, Z_NULL, 0);
461
        outd.total = 0;
462
 
463
        /* decompress data to output */
464
        strm->next_in = next;
465
        strm->avail_in = have;
466
        ret = inflateBack(strm, in, indp, out, &outd);
467
        if (ret != Z_STREAM_END) break;
468
        next = strm->next_in;
469
        have = strm->avail_in;
470
        strm->next_in = Z_NULL;             /* so Z_BUF_ERROR means EOF */
471
 
472
        /* check trailer */
473
        ret = Z_BUF_ERROR;
474
        if (NEXT() != (outd.crc & 0xff) ||
475
            NEXT() != ((outd.crc >> 8) & 0xff) ||
476
            NEXT() != ((outd.crc >> 16) & 0xff) ||
477
            NEXT() != ((outd.crc >> 24) & 0xff)) {
478
            /* crc error */
479
            if (last != -1) {
480
                strm->msg = (char *)"incorrect data check";
481
                ret = Z_DATA_ERROR;
482
            }
483
            break;
484
        }
485
        if (NEXT() != (outd.total & 0xff) ||
486
            NEXT() != ((outd.total >> 8) & 0xff) ||
487
            NEXT() != ((outd.total >> 16) & 0xff) ||
488
            NEXT() != ((outd.total >> 24) & 0xff)) {
489
            /* length error */
490
            if (last != -1) {
491
                strm->msg = (char *)"incorrect length check";
492
                ret = Z_DATA_ERROR;
493
            }
494
            break;
495
        }
496
 
497
        /* go back and look for another gzip stream */
498
    }
499
 
500
    /* clean up and return */
501
    return ret;
502
}
503
 
504
/* Copy file attributes, from -> to, as best we can.  This is best effort, so
505
   no errors are reported.  The mode bits, including suid, sgid, and the sticky
506
   bit are copied (if allowed), the owner's user id and group id are copied
507
   (again if allowed), and the access and modify times are copied. */
508
local void copymeta(char *from, char *to)
509
{
510
    struct stat was;
511
    struct utimbuf when;
512
 
513
    /* get all of from's Unix meta data, return if not a regular file */
514
    if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
515
        return;
516
 
517
    /* set to's mode bits, ignore errors */
518
    (void)chmod(to, was.st_mode & 07777);
519
 
520
    /* copy owner's user and group, ignore errors */
521
    (void)chown(to, was.st_uid, was.st_gid);
522
 
523
    /* copy access and modify times, ignore errors */
524
    when.actime = was.st_atime;
525
    when.modtime = was.st_mtime;
526
    (void)utime(to, &when);
527
}
528
 
529
/* Decompress the file inname to the file outnname, of if test is true, just
530
   decompress without writing and check the gzip trailer for integrity.  If
531
   inname is NULL or an empty string, read from stdin.  If outname is NULL or
532
   an empty string, write to stdout.  strm is a pre-initialized inflateBack
533
   structure.  When appropriate, copy the file attributes from inname to
534
   outname.
535
 
536
   gunzip() returns 1 if there is an out-of-memory error or an unexpected
537
   return code from gunpipe().  Otherwise it returns 0.
538
 */
539
local int gunzip(z_stream *strm, char *inname, char *outname, int test)
540
{
541
    int ret;
542
    int infile, outfile;
543
 
544
    /* open files */
545
    if (inname == NULL || *inname == 0) {
546
        inname = "-";
547
        infile = 0;     /* stdin */
548
    }
549
    else {
550
        infile = open(inname, O_RDONLY, 0);
551
        if (infile == -1) {
552
            fprintf(stderr, "gun cannot open %s\n", inname);
553
            return 0;
554
        }
555
    }
556
    if (test)
557
        outfile = -1;
558
    else if (outname == NULL || *outname == 0) {
559
        outname = "-";
560
        outfile = 1;    /* stdout */
561
    }
562
    else {
563
        outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
564
        if (outfile == -1) {
565
            close(infile);
566
            fprintf(stderr, "gun cannot create %s\n", outname);
567
            return 0;
568
        }
569
    }
570
    errno = 0;
571
 
572
    /* decompress */
573
    ret = gunpipe(strm, infile, outfile);
574
    if (outfile > 2) close(outfile);
575
    if (infile > 2) close(infile);
576
 
577
    /* interpret result */
578
    switch (ret) {
579
    case Z_OK:
580
    case Z_ERRNO:
581
        if (infile > 2 && outfile > 2) {
582
            copymeta(inname, outname);          /* copy attributes */
583
            unlink(inname);
584
        }
585
        if (ret == Z_ERRNO)
586
            fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
587
                    inname);
588
        break;
589
    case Z_DATA_ERROR:
590
        if (outfile > 2) unlink(outname);
591
        fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
592
        break;
593
    case Z_MEM_ERROR:
594
        if (outfile > 2) unlink(outname);
595
        fprintf(stderr, "gun out of memory error--aborting\n");
596
        return 1;
597
    case Z_BUF_ERROR:
598
        if (outfile > 2) unlink(outname);
599
        if (strm->next_in != Z_NULL) {
600
            fprintf(stderr, "gun write error on %s: %s\n",
601
                    outname, strerror(errno));
602
        }
603
        else if (errno) {
604
            fprintf(stderr, "gun read error on %s: %s\n",
605
                    inname, strerror(errno));
606
        }
607
        else {
608
            fprintf(stderr, "gun unexpected end of file on %s\n",
609
                    inname);
610
        }
611
        break;
612
    default:
613
        if (outfile > 2) unlink(outname);
614
        fprintf(stderr, "gun internal error--aborting\n");
615
        return 1;
616
    }
617
    return 0;
618
}
619
 
620
/* Process the gun command line arguments.  See the command syntax near the
621
   beginning of this source file. */
622
int main(int argc, char **argv)
623
{
624
    int ret, len, test;
625
    char *outname;
626
    unsigned char *window;
627
    z_stream strm;
628
 
629
    /* initialize inflateBack state for repeated use */
630
    window = match;                         /* reuse LZW match buffer */
631
    strm.zalloc = Z_NULL;
632
    strm.zfree = Z_NULL;
633
    strm.opaque = Z_NULL;
634
    ret = inflateBackInit(&strm, 15, window);
635
    if (ret != Z_OK) {
636
        fprintf(stderr, "gun out of memory error--aborting\n");
637
        return 1;
638
    }
639
 
640
    /* decompress each file to the same name with the suffix removed */
641
    argc--;
642
    argv++;
643
    test = 0;
644
    if (argc && strcmp(*argv, "-h") == 0) {
645
        fprintf(stderr, "gun 1.3 (12 Jun 2005)\n");
646
        fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
647
        fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
648
        return 0;
649
    }
650
    if (argc && strcmp(*argv, "-t") == 0) {
651
        test = 1;
652
        argc--;
653
        argv++;
654
    }
655
    if (argc)
656
        do {
657
            if (test)
658
                outname = NULL;
659
            else {
660
                len = (int)strlen(*argv);
661
                if (strcmp(*argv + len - 3, ".gz") == 0 ||
662
                    strcmp(*argv + len - 3, "-gz") == 0)
663
                    len -= 3;
664
                else if (strcmp(*argv + len - 2, ".z") == 0 ||
665
                    strcmp(*argv + len - 2, "-z") == 0 ||
666
                    strcmp(*argv + len - 2, "_z") == 0 ||
667
                    strcmp(*argv + len - 2, ".Z") == 0)
668
                    len -= 2;
669
                else {
670
                    fprintf(stderr, "gun error: no gz type on %s--skipping\n",
671
                            *argv);
672
                    continue;
673
                }
674
                outname = malloc(len + 1);
675
                if (outname == NULL) {
676
                    fprintf(stderr, "gun out of memory error--aborting\n");
677
                    ret = 1;
678
                    break;
679
                }
680
                memcpy(outname, *argv, len);
681
                outname[len] = 0;
682
            }
683
            ret = gunzip(&strm, *argv, outname, test);
684
            if (outname != NULL) free(outname);
685
            if (ret) break;
686
        } while (argv++, --argc);
687
    else
688
        ret = gunzip(&strm, NULL, NULL, test);
689
 
690
    /* clean up */
691
    inflateBackEnd(&strm);
692
    return ret;
693
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.