Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/archival/gunzip.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations) (download)
Sat Sep 1 22:45:15 2007 UTC (16 years, 8 months ago) by niro
File MIME type: text/plain
File size: 4580 byte(s)
-import if magellan mkinitrd; it is a fork of redhats mkinitrd-5.0.8 with all magellan patches and features; deprecates magellan-src/mkinitrd

1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * Gzip implementation for busybox
4     *
5     * Based on GNU gzip v1.2.4 Copyright (C) 1992-1993 Jean-loup Gailly.
6     *
7     * Originally adjusted for busybox by Sven Rudolph <sr1@inf.tu-dresden.de>
8     * based on gzip sources
9     *
10     * Adjusted further by Erik Andersen <andersen@codepoet.org> to support files as
11     * well as stdin/stdout, and to generally behave itself wrt command line
12     * handling.
13     *
14     * General cleanup to better adhere to the style guide and make use of standard
15     * busybox functions by Glenn McGrath <bug1@iinet.net.au>
16     *
17     * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
18     *
19     * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface
20     * Copyright (C) 1992-1993 Jean-loup Gailly
21     * The unzip code was written and put in the public domain by Mark Adler.
22     * Portions of the lzw code are derived from the public domain 'compress'
23     * written by Spencer Thomas, Joe Orost, James Woods, Jim McKie, Steve Davies,
24     * Ken Turkowski, Dave Mack and Peter Jannesen.
25     *
26     * See the license_msg below and the file COPYING for the software license.
27     * See the file algorithm.doc for the compression algorithms and file formats.
28     */
29    
30     #include "busybox.h"
31     #include "unarchive.h"
32    
33     #define GUNZIP_OPT_STDOUT 1
34     #define GUNZIP_OPT_FORCE 2
35     #define GUNZIP_OPT_TEST 4
36     #define GUNZIP_OPT_DECOMPRESS 8
37     #define GUNZIP_OPT_VERBOSE 0x10
38    
39     int gunzip_main(int argc, char **argv)
40     {
41     USE_DESKTOP(long long) int status;
42     int exitcode = 0;
43     unsigned opt;
44    
45     opt = getopt32(argc, argv, "cftdv");
46     /* if called as zcat */
47     if (strcmp(applet_name, "zcat") == 0) {
48     opt |= GUNZIP_OPT_STDOUT;
49     }
50    
51     do {
52     struct stat stat_buf;
53     char *old_path = argv[optind];
54     char *delete_path = NULL;
55     char *new_path = NULL;
56     int src_fd;
57     int dst_fd;
58    
59     optind++;
60    
61     if (old_path == NULL || LONE_DASH(old_path)) {
62     src_fd = STDIN_FILENO;
63     opt |= GUNZIP_OPT_STDOUT;
64     USE_DESKTOP(opt &= ~GUNZIP_OPT_VERBOSE;)
65     optind = argc; /* we don't handle "gunzip - a.gz b.gz" */
66     } else {
67     src_fd = xopen(old_path, O_RDONLY);
68     /* Get the time stamp on the input file. */
69     fstat(src_fd, &stat_buf);
70     }
71    
72     /* Check that the input is sane. */
73     if (isatty(src_fd) && !(opt & GUNZIP_OPT_FORCE)) {
74     bb_error_msg_and_die
75     ("compressed data not read from terminal, use -f to force it");
76     }
77    
78     /* Set output filename and number */
79     if (opt & GUNZIP_OPT_TEST) {
80     dst_fd = xopen(bb_dev_null, O_WRONLY); /* why does test use filenum 2 ? */
81     } else if (opt & GUNZIP_OPT_STDOUT) {
82     dst_fd = STDOUT_FILENO;
83     } else {
84     char *extension;
85    
86     new_path = xstrdup(old_path);
87    
88     extension = strrchr(new_path, '.');
89     #ifdef CONFIG_FEATURE_GUNZIP_UNCOMPRESS
90     if (extension && (strcmp(extension, ".Z") == 0)) {
91     *extension = '\0';
92     } else
93     #endif
94     if (extension && (strcmp(extension, ".gz") == 0)) {
95     *extension = '\0';
96     } else if (extension && (strcmp(extension, ".tgz") == 0)) {
97     extension[2] = 'a';
98     extension[3] = 'r';
99     } else {
100     // FIXME: should we die or just skip to next?
101     bb_error_msg_and_die("invalid extension");
102     }
103    
104     /* Open output file (with correct permissions) */
105     dst_fd = xopen3(new_path, O_WRONLY | O_CREAT | O_TRUNC,
106     stat_buf.st_mode);
107    
108     /* If unzip succeeds remove the old file */
109     delete_path = old_path;
110     }
111    
112     status = -1;
113     /* do the decompression, and cleanup */
114     if (xread_char(src_fd) == 0x1f) {
115     unsigned char magic2;
116    
117     magic2 = xread_char(src_fd);
118     if (ENABLE_FEATURE_GUNZIP_UNCOMPRESS && magic2 == 0x9d) {
119     status = uncompress(src_fd, dst_fd);
120     } else if (magic2 == 0x8b) {
121     check_header_gzip(src_fd); // FIXME: xfunc? _or_die?
122     status = inflate_gunzip(src_fd, dst_fd);
123     } else {
124     bb_error_msg("invalid magic");
125     exitcode = 1;
126     }
127     if (status < 0) {
128     bb_error_msg("error inflating");
129     exitcode = 1;
130     }
131     else if (ENABLE_DESKTOP && (opt & GUNZIP_OPT_VERBOSE)) {
132     fprintf(stderr, "%s: %u%% - replaced with %s\n",
133     old_path, (unsigned)(stat_buf.st_size*100 / (status+1)), new_path);
134     }
135     } else {
136     bb_error_msg("invalid magic");
137     exitcode = 1;
138     }
139     if (status < 0 && new_path) {
140     /* Unzip failed, remove new path instead of old path */
141     delete_path = new_path;
142     }
143    
144     if (dst_fd != STDOUT_FILENO) {
145     close(dst_fd);
146     }
147     if (src_fd != STDIN_FILENO) {
148     close(src_fd);
149     }
150    
151     /* delete_path will be NULL if in test mode or from stdin */
152     if (delete_path && (unlink(delete_path) == -1)) {
153     bb_error_msg("cannot remove %s", delete_path);
154     exitcode = 1;
155     }
156    
157     free(new_path);
158    
159     } while (optind < argc);
160    
161     return exitcode;
162     }