diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 19:40:13 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-01-07 19:40:13 +0000 |
commit | 52933d47bd86d6d992f7290fad93d63b53f7a15f (patch) | |
tree | 1e7371ee6e4a7f8644e0d71c7987eff89ad9a43e /archival/gzip.c | |
parent | ef87d46b8c6ac3be21bcd6f1cad6533289e33f42 (diff) | |
download | busybox-w32-52933d47bd86d6d992f7290fad93d63b53f7a15f.tar.gz busybox-w32-52933d47bd86d6d992f7290fad93d63b53f7a15f.tar.bz2 busybox-w32-52933d47bd86d6d992f7290fad93d63b53f7a15f.zip |
gzip cleanup part #8
Diffstat (limited to 'archival/gzip.c')
-rw-r--r-- | archival/gzip.c | 346 |
1 files changed, 168 insertions, 178 deletions
diff --git a/archival/gzip.c b/archival/gzip.c index 76836951f..2c8f69d91 100644 --- a/archival/gzip.c +++ b/archival/gzip.c | |||
@@ -311,11 +311,6 @@ static void check_match(IPos start, IPos match, int length); | |||
311 | #endif | 311 | #endif |
312 | 312 | ||
313 | 313 | ||
314 | |||
315 | /* from zip.c: */ | ||
316 | static int zip(int in, int out); | ||
317 | static unsigned file_read(void *buf, unsigned size); | ||
318 | |||
319 | /* from deflate.c */ | 314 | /* from deflate.c */ |
320 | static void lm_init(ush * flags); | 315 | static void lm_init(ush * flags); |
321 | static ulg deflate(void); | 316 | static ulg deflate(void); |
@@ -605,22 +600,8 @@ static void copy_block(char *buf, unsigned len, int header) | |||
605 | * input characters, so that a running hash key can be computed from the | 600 | * input characters, so that a running hash key can be computed from the |
606 | * previous key instead of complete recalculation each time. | 601 | * previous key instead of complete recalculation each time. |
607 | */ | 602 | */ |
608 | #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) | 603 | #define UPDATE_HASH(h, c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK) |
609 | 604 | ||
610 | /* =========================================================================== | ||
611 | * Insert string s in the dictionary and set match_head to the previous head | ||
612 | * of the hash chain (the most recent string with same hash key). Return | ||
613 | * the previous length of the hash chain. | ||
614 | * IN assertion: all calls to to INSERT_STRING are made with consecutive | ||
615 | * input characters and the first MIN_MATCH bytes of s are valid | ||
616 | * (except for the last MIN_MATCH-1 bytes of the input file). | ||
617 | */ | ||
618 | #define INSERT_STRING(s, match_head) \ | ||
619 | { \ | ||
620 | UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \ | ||
621 | prev[(s) & WMASK] = match_head = head[ins_h]; \ | ||
622 | head[ins_h] = (s); \ | ||
623 | } | ||
624 | 605 | ||
625 | /* =========================================================================== | 606 | /* =========================================================================== |
626 | * Initialize the "longest match" routines for a new file | 607 | * Initialize the "longest match" routines for a new file |
@@ -834,9 +815,17 @@ static void fill_window(void) | |||
834 | 815 | ||
835 | 816 | ||
836 | /* =========================================================================== | 817 | /* =========================================================================== |
837 | * Flush the current block, with given end-of-file flag. | 818 | * Same as above, but achieves better compression. We use a lazy |
838 | * IN assertion: strstart is set to the end of the current match. | 819 | * evaluation for matches: a match is finally adopted only if there is |
820 | * no better match at the next window position. | ||
821 | * | ||
822 | * Processes a new input file and return its compressed length. Sets | ||
823 | * the compressed length, crc, deflate flags and internal file | ||
824 | * attributes. | ||
839 | */ | 825 | */ |
826 | |||
827 | /* Flush the current block, with given end-of-file flag. | ||
828 | * IN assertion: strstart is set to the end of the current match. */ | ||
840 | #define FLUSH_BLOCK(eof) \ | 829 | #define FLUSH_BLOCK(eof) \ |
841 | flush_block( \ | 830 | flush_block( \ |
842 | block_start >= 0L \ | 831 | block_start >= 0L \ |
@@ -846,16 +835,19 @@ static void fill_window(void) | |||
846 | (eof) \ | 835 | (eof) \ |
847 | ) | 836 | ) |
848 | 837 | ||
838 | /* Insert string s in the dictionary and set match_head to the previous head | ||
839 | * of the hash chain (the most recent string with same hash key). Return | ||
840 | * the previous length of the hash chain. | ||
841 | * IN assertion: all calls to to INSERT_STRING are made with consecutive | ||
842 | * input characters and the first MIN_MATCH bytes of s are valid | ||
843 | * (except for the last MIN_MATCH-1 bytes of the input file). */ | ||
844 | #define INSERT_STRING(s, match_head) \ | ||
845 | { \ | ||
846 | UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]); \ | ||
847 | prev[(s) & WMASK] = match_head = head[ins_h]; \ | ||
848 | head[ins_h] = (s); \ | ||
849 | } | ||
849 | 850 | ||
850 | /* =========================================================================== | ||
851 | * Same as above, but achieves better compression. We use a lazy | ||
852 | * evaluation for matches: a match is finally adopted only if there is | ||
853 | * no better match at the next window position. | ||
854 | * | ||
855 | * Processes a new input file and return its compressed length. Sets | ||
856 | * the compressed length, crc, deflate flags and internal file | ||
857 | * attributes. | ||
858 | */ | ||
859 | static ulg deflate(void) | 851 | static ulg deflate(void) |
860 | { | 852 | { |
861 | IPos hash_head; /* head of hash chain */ | 853 | IPos hash_head; /* head of hash chain */ |
@@ -959,152 +951,6 @@ static ulg deflate(void) | |||
959 | 951 | ||
960 | return FLUSH_BLOCK(1); /* eof */ | 952 | return FLUSH_BLOCK(1); /* eof */ |
961 | } | 953 | } |
962 | |||
963 | |||
964 | /* ======================================================================== */ | ||
965 | static void abort_gzip(int ATTRIBUTE_UNUSED ignored) | ||
966 | { | ||
967 | exit(1); | ||
968 | } | ||
969 | |||
970 | int gzip_main(int argc, char **argv) | ||
971 | { | ||
972 | enum { | ||
973 | OPT_tostdout = 0x1, | ||
974 | OPT_force = 0x2, | ||
975 | }; | ||
976 | |||
977 | unsigned opt; | ||
978 | int result; | ||
979 | int inFileNum; | ||
980 | int outFileNum; | ||
981 | struct stat statBuf; | ||
982 | char *delFileName; | ||
983 | |||
984 | opt = getopt32(argc, argv, "cf123456789qv" USE_GUNZIP("d")); | ||
985 | //if (opt & 0x1) // -c | ||
986 | //if (opt & 0x2) // -f | ||
987 | /* Ignore 1-9 (compression level) options */ | ||
988 | //if (opt & 0x4) // -1 | ||
989 | //if (opt & 0x8) // -2 | ||
990 | //if (opt & 0x10) // -3 | ||
991 | //if (opt & 0x20) // -4 | ||
992 | //if (opt & 0x40) // -5 | ||
993 | //if (opt & 0x80) // -6 | ||
994 | //if (opt & 0x100) // -7 | ||
995 | //if (opt & 0x200) // -8 | ||
996 | //if (opt & 0x400) // -9 | ||
997 | //if (opt & 0x800) // -q | ||
998 | //if (opt & 0x1000) // -v | ||
999 | #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ | ||
1000 | if (opt & 0x2000) { // -d | ||
1001 | /* FIXME: getopt32 should not depend on optind */ | ||
1002 | optind = 1; | ||
1003 | return gunzip_main(argc, argv); | ||
1004 | } | ||
1005 | #endif | ||
1006 | |||
1007 | foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; | ||
1008 | if (foreground) { | ||
1009 | (void) signal(SIGINT, abort_gzip); | ||
1010 | } | ||
1011 | #ifdef SIGTERM | ||
1012 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { | ||
1013 | (void) signal(SIGTERM, abort_gzip); | ||
1014 | } | ||
1015 | #endif | ||
1016 | #ifdef SIGHUP | ||
1017 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { | ||
1018 | (void) signal(SIGHUP, abort_gzip); | ||
1019 | } | ||
1020 | #endif | ||
1021 | |||
1022 | strncpy(z_suffix, ".gz", sizeof(z_suffix) - 1); | ||
1023 | |||
1024 | /* Allocate all global buffers (for DYN_ALLOC option) */ | ||
1025 | ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); | ||
1026 | ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); | ||
1027 | ALLOC(ush, d_buf, DIST_BUFSIZE); | ||
1028 | ALLOC(uch, window, 2L * WSIZE); | ||
1029 | ALLOC(ush, tab_prefix, 1L << BITS); | ||
1030 | |||
1031 | /* Initialise the CRC32 table */ | ||
1032 | crc_32_tab = crc32_filltable(0); | ||
1033 | |||
1034 | clear_bufs(); | ||
1035 | |||
1036 | if (optind == argc) { | ||
1037 | time_stamp = 0; | ||
1038 | zip(STDIN_FILENO, STDOUT_FILENO); | ||
1039 | } else { | ||
1040 | int i; | ||
1041 | |||
1042 | for (i = optind; i < argc; i++) { | ||
1043 | char *path = NULL; | ||
1044 | |||
1045 | clear_bufs(); | ||
1046 | if (LONE_DASH(argv[i])) { | ||
1047 | time_stamp = 0; | ||
1048 | inFileNum = STDIN_FILENO; | ||
1049 | outFileNum = STDOUT_FILENO; | ||
1050 | } else { | ||
1051 | inFileNum = xopen(argv[i], O_RDONLY); | ||
1052 | if (fstat(inFileNum, &statBuf) < 0) | ||
1053 | bb_perror_msg_and_die("%s", argv[i]); | ||
1054 | time_stamp = statBuf.st_ctime; | ||
1055 | |||
1056 | if (!(opt & OPT_tostdout)) { | ||
1057 | path = xasprintf("%s.gz", argv[i]); | ||
1058 | |||
1059 | /* Open output file */ | ||
1060 | #if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 && defined(O_NOFOLLOW) | ||
1061 | outFileNum = | ||
1062 | open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); | ||
1063 | #else | ||
1064 | outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL); | ||
1065 | #endif | ||
1066 | if (outFileNum < 0) { | ||
1067 | bb_perror_msg("%s", path); | ||
1068 | free(path); | ||
1069 | continue; | ||
1070 | } | ||
1071 | |||
1072 | /* Set permissions on the file */ | ||
1073 | fchmod(outFileNum, statBuf.st_mode); | ||
1074 | } else | ||
1075 | outFileNum = STDOUT_FILENO; | ||
1076 | } | ||
1077 | |||
1078 | if (path == NULL && isatty(outFileNum) && !(opt & OPT_force)) { | ||
1079 | bb_error_msg | ||
1080 | ("compressed data not written to a terminal. Use -f to force compression."); | ||
1081 | free(path); | ||
1082 | continue; | ||
1083 | } | ||
1084 | |||
1085 | result = zip(inFileNum, outFileNum); | ||
1086 | |||
1087 | if (path != NULL) { | ||
1088 | close(inFileNum); | ||
1089 | close(outFileNum); | ||
1090 | |||
1091 | /* Delete the original file */ | ||
1092 | if (result == 0) | ||
1093 | delFileName = argv[i]; | ||
1094 | else | ||
1095 | delFileName = path; | ||
1096 | |||
1097 | if (unlink(delFileName) < 0) | ||
1098 | bb_perror_msg("%s", delFileName); | ||
1099 | } | ||
1100 | |||
1101 | free(path); | ||
1102 | } | ||
1103 | } | ||
1104 | |||
1105 | return exit_code; | ||
1106 | } | ||
1107 | |||
1108 | /* trees.c -- output deflated data using Huffman coding | 954 | /* trees.c -- output deflated data using Huffman coding |
1109 | * Copyright (C) 1992-1993 Jean-loup Gailly | 955 | * Copyright (C) 1992-1993 Jean-loup Gailly |
1110 | * This is free software; you can redistribute it and/or modify it under the | 956 | * This is free software; you can redistribute it and/or modify it under the |
@@ -2109,7 +1955,7 @@ static ulg flush_block(char *buf, ulg stored_len, int eof) | |||
2109 | */ | 1955 | */ |
2110 | static int ct_tally(int dist, int lc) | 1956 | static int ct_tally(int dist, int lc) |
2111 | { | 1957 | { |
2112 | l_buf[last_lit++] = (uch) lc; | 1958 | l_buf[last_lit++] = lc; |
2113 | if (dist == 0) { | 1959 | if (dist == 0) { |
2114 | /* lc is the unmatched char */ | 1960 | /* lc is the unmatched char */ |
2115 | dyn_ltree[lc].Freq++; | 1961 | dyn_ltree[lc].Freq++; |
@@ -2278,3 +2124,147 @@ static int zip(int in, int out) | |||
2278 | flush_outbuf(); | 2124 | flush_outbuf(); |
2279 | return 0; | 2125 | return 0; |
2280 | } | 2126 | } |
2127 | |||
2128 | |||
2129 | /* ======================================================================== */ | ||
2130 | static void abort_gzip(int ATTRIBUTE_UNUSED ignored) | ||
2131 | { | ||
2132 | exit(1); | ||
2133 | } | ||
2134 | |||
2135 | int gzip_main(int argc, char **argv) | ||
2136 | { | ||
2137 | enum { | ||
2138 | OPT_tostdout = 0x1, | ||
2139 | OPT_force = 0x2, | ||
2140 | }; | ||
2141 | |||
2142 | unsigned opt; | ||
2143 | int result; | ||
2144 | int inFileNum; | ||
2145 | int outFileNum; | ||
2146 | int i; | ||
2147 | struct stat statBuf; | ||
2148 | char *delFileName; | ||
2149 | |||
2150 | opt = getopt32(argc, argv, "cf123456789qv" USE_GUNZIP("d")); | ||
2151 | //if (opt & 0x1) // -c | ||
2152 | //if (opt & 0x2) // -f | ||
2153 | /* Ignore 1-9 (compression level) options */ | ||
2154 | //if (opt & 0x4) // -1 | ||
2155 | //if (opt & 0x8) // -2 | ||
2156 | //if (opt & 0x10) // -3 | ||
2157 | //if (opt & 0x20) // -4 | ||
2158 | //if (opt & 0x40) // -5 | ||
2159 | //if (opt & 0x80) // -6 | ||
2160 | //if (opt & 0x100) // -7 | ||
2161 | //if (opt & 0x200) // -8 | ||
2162 | //if (opt & 0x400) // -9 | ||
2163 | //if (opt & 0x800) // -q | ||
2164 | //if (opt & 0x1000) // -v | ||
2165 | #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ | ||
2166 | if (opt & 0x2000) { // -d | ||
2167 | /* FIXME: getopt32 should not depend on optind */ | ||
2168 | optind = 1; | ||
2169 | return gunzip_main(argc, argv); | ||
2170 | } | ||
2171 | #endif | ||
2172 | |||
2173 | foreground = signal(SIGINT, SIG_IGN) != SIG_IGN; | ||
2174 | if (foreground) { | ||
2175 | signal(SIGINT, abort_gzip); | ||
2176 | } | ||
2177 | #ifdef SIGTERM | ||
2178 | if (signal(SIGTERM, SIG_IGN) != SIG_IGN) { | ||
2179 | signal(SIGTERM, abort_gzip); | ||
2180 | } | ||
2181 | #endif | ||
2182 | #ifdef SIGHUP | ||
2183 | if (signal(SIGHUP, SIG_IGN) != SIG_IGN) { | ||
2184 | signal(SIGHUP, abort_gzip); | ||
2185 | } | ||
2186 | #endif | ||
2187 | |||
2188 | strncpy(z_suffix, ".gz", sizeof(z_suffix) - 1); | ||
2189 | |||
2190 | /* Allocate all global buffers (for DYN_ALLOC option) */ | ||
2191 | ALLOC(uch, inbuf, INBUFSIZ + INBUF_EXTRA); | ||
2192 | ALLOC(uch, outbuf, OUTBUFSIZ + OUTBUF_EXTRA); | ||
2193 | ALLOC(ush, d_buf, DIST_BUFSIZE); | ||
2194 | ALLOC(uch, window, 2L * WSIZE); | ||
2195 | ALLOC(ush, tab_prefix, 1L << BITS); | ||
2196 | |||
2197 | /* Initialise the CRC32 table */ | ||
2198 | crc_32_tab = crc32_filltable(0); | ||
2199 | |||
2200 | clear_bufs(); | ||
2201 | |||
2202 | if (optind == argc) { | ||
2203 | time_stamp = 0; | ||
2204 | zip(STDIN_FILENO, STDOUT_FILENO); | ||
2205 | return exit_code; | ||
2206 | } | ||
2207 | |||
2208 | for (i = optind; i < argc; i++) { | ||
2209 | char *path = NULL; | ||
2210 | |||
2211 | clear_bufs(); | ||
2212 | if (LONE_DASH(argv[i])) { | ||
2213 | time_stamp = 0; | ||
2214 | inFileNum = STDIN_FILENO; | ||
2215 | outFileNum = STDOUT_FILENO; | ||
2216 | } else { | ||
2217 | inFileNum = xopen(argv[i], O_RDONLY); | ||
2218 | if (fstat(inFileNum, &statBuf) < 0) | ||
2219 | bb_perror_msg_and_die("%s", argv[i]); | ||
2220 | time_stamp = statBuf.st_ctime; | ||
2221 | |||
2222 | if (!(opt & OPT_tostdout)) { | ||
2223 | path = xasprintf("%s.gz", argv[i]); | ||
2224 | |||
2225 | /* Open output file */ | ||
2226 | #if defined(__GLIBC__) && __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 1 && defined(O_NOFOLLOW) | ||
2227 | outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW); | ||
2228 | #else | ||
2229 | outFileNum = open(path, O_RDWR | O_CREAT | O_EXCL); | ||
2230 | #endif | ||
2231 | if (outFileNum < 0) { | ||
2232 | bb_perror_msg("%s", path); | ||
2233 | free(path); | ||
2234 | continue; | ||
2235 | } | ||
2236 | |||
2237 | /* Set permissions on the file */ | ||
2238 | fchmod(outFileNum, statBuf.st_mode); | ||
2239 | } else | ||
2240 | outFileNum = STDOUT_FILENO; | ||
2241 | } | ||
2242 | |||
2243 | if (path == NULL && isatty(outFileNum) && !(opt & OPT_force)) { | ||
2244 | bb_error_msg("compressed data not written " | ||
2245 | "to a terminal. Use -f to force compression."); | ||
2246 | free(path); | ||
2247 | continue; | ||
2248 | } | ||
2249 | |||
2250 | result = zip(inFileNum, outFileNum); | ||
2251 | |||
2252 | if (path != NULL) { | ||
2253 | close(inFileNum); | ||
2254 | close(outFileNum); | ||
2255 | |||
2256 | /* Delete the original file */ | ||
2257 | if (result == 0) | ||
2258 | delFileName = argv[i]; | ||
2259 | else | ||
2260 | delFileName = path; | ||
2261 | |||
2262 | if (unlink(delFileName) < 0) | ||
2263 | bb_perror_msg("%s", delFileName); | ||
2264 | } | ||
2265 | |||
2266 | free(path); | ||
2267 | } | ||
2268 | |||
2269 | return exit_code; | ||
2270 | } | ||