1 /* minigzip.c -- simulate gzip using the zlib compression library 2 * Copyright (C) 1995-1996 Jean-loup Gailly. 3 * For conditions of distribution and use, see copyright notice in zlib.h 4 */ 5 6 /* 7 * minigzip is a minimal implementation of the gzip utility. This is 8 * only an example of using zlib and isn't meant to replace the 9 * full-featured gzip. No attempt is made to deal with file systems 10 * limiting names to 14 or 8+3 characters, etc... Error checking is 11 * very limited. So use minigzip only for testing; use gzip for the 12 * real thing. On MSDOS, use only on file names without extension 13 * or in pipe mode. 14 */ 15 16 /* $Id: minigzip.c,v 1.10 1996/07/24 13:41:04 me Exp $ */ 17 18 #include <stdio.h> 19 #include "zlib.h" 20 21 #ifdef STDC 22 # include <string.h> 23 # include <stdlib.h> 24 #else 25 extern void exit OF((int)); 26 #endif 27 28 29 #if defined(MSDOS) || defined(OS2) || defined(WIN32) 30 # include <fcntl.h> 31 # include <io.h> 32 # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 33 #else 34 # define SET_BINARY_MODE(file) 35 #endif 36 37 #ifdef VMS 38 # define unlink delete 39 # define GZ_SUFFIX "-gz" 40 #endif 41 #ifdef RISCOS 42 # define unlink remove 43 # define GZ_SUFFIX "-gz" 44 # define fileno(file) file->__file 45 #endif 46 47 #ifndef GZ_SUFFIX 48 # define GZ_SUFFIX ".gz" 49 #endif 50 #define SUFFIX_LEN sizeof(GZ_SUFFIX) 51 52 extern int unlink OF((const char *)); 53 54 #define BUFLEN 4096 55 #define MAX_NAME_LEN 1024 56 57 #define local static 58 /* For MSDOS and other systems with limitation on stack size. For Unix, 59 #define local 60 works also. 61 */ 62 63 char *prog; 64 65 void error OF((const char *msg)); 66 void gz_compress OF((FILE *in, gzFile out)); 67 void gz_uncompress OF((gzFile in, FILE *out)); 68 void file_compress OF((char *file)); 69 void file_uncompress OF((char *file)); 70 int main OF((int argc, char *argv[])); 71 72 /* =========================================================================== 73 * Display error message and exit 74 */ 75 void error(msg) 76 const char *msg; 77 { 78 fprintf(stderr, "%s: %s\n", prog, msg); 79 exit(1); 80 } 81 82 /* =========================================================================== 83 * Compress input to output then close both files. 84 */ 85 void gz_compress(in, out) 86 FILE *in; 87 gzFile out; 88 { 89 local char buf[BUFLEN]; 90 int len; 91 int err; 92 93 for (;;) { 94 len = fread(buf, 1, sizeof(buf), in); 95 if (ferror(in)) { 96 perror("fread"); 97 exit(1); 98 } 99 if (len == 0) break; 100 101 if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); 102 } 103 fclose(in); 104 if (gzclose(out) != Z_OK) error("failed gzclose"); 105 } 106 107 /* =========================================================================== 108 * Uncompress input to output then close both files. 109 */ 110 void gz_uncompress(in, out) 111 gzFile in; 112 FILE *out; 113 { 114 local char buf[BUFLEN]; 115 int len; 116 int err; 117 118 for (;;) { 119 len = gzread(in, buf, sizeof(buf)); 120 if (len < 0) error (gzerror(in, &err)); 121 if (len == 0) break; 122 123 if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { 124 error("failed fwrite"); 125 } 126 } 127 if (fclose(out)) error("failed fclose"); 128 129 if (gzclose(in) != Z_OK) error("failed gzclose"); 130 } 131 132 133 /* =========================================================================== 134 * Compress the given file: create a corresponding .gz file and remove the 135 * original. 136 */ 137 void file_compress(file) 138 char *file; 139 { 140 local char outfile[MAX_NAME_LEN]; 141 FILE *in; 142 gzFile out; 143 144 strcpy(outfile, file); 145 strcat(outfile, GZ_SUFFIX); 146 147 in = fopen(file, "rb"); 148 if (in == NULL) { 149 perror(file); 150 exit(1); 151 } 152 out = gzopen(outfile, "wb"); /* use "wb9" for maximal compression */ 153 if (out == NULL) { 154 fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); 155 exit(1); 156 } 157 gz_compress(in, out); 158 159 unlink(file); 160 } 161 162 163 /* =========================================================================== 164 * Uncompress the given file and remove the original. 165 */ 166 void file_uncompress(file) 167 char *file; 168 { 169 local char buf[MAX_NAME_LEN]; 170 char *infile, *outfile; 171 FILE *out; 172 gzFile in; 173 int len = strlen(file); 174 175 strcpy(buf, file); 176 177 if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { 178 infile = file; 179 outfile = buf; 180 outfile[len-3] = '\0'; 181 } else { 182 outfile = file; 183 infile = buf; 184 strcat(infile, GZ_SUFFIX); 185 } 186 in = gzopen(infile, "rb"); 187 if (in == NULL) { 188 fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); 189 exit(1); 190 } 191 out = fopen(outfile, "wb"); 192 if (out == NULL) { 193 perror(file); 194 exit(1); 195 } 196 197 gz_uncompress(in, out); 198 199 unlink(infile); 200 } 201 202 203 /* =========================================================================== 204 * Usage: minigzip [-d] [files...] 205 */ 206 207 int main(argc, argv) 208 int argc; 209 char *argv[]; 210 { 211 int uncompr = 0; 212 gzFile file; 213 214 prog = argv[0]; 215 argc--, argv++; 216 217 if (argc > 0) { 218 uncompr = (strcmp(*argv, "-d") == 0); 219 if (uncompr) { 220 argc--, argv++; 221 } 222 } 223 if (argc == 0) { 224 SET_BINARY_MODE(stdin); 225 SET_BINARY_MODE(stdout); 226 if (uncompr) { 227 file = gzdopen(fileno(stdin), "rb"); 228 if (file == NULL) error("can't gzdopen stdin"); 229 gz_uncompress(file, stdout); 230 } else { 231 file = gzdopen(fileno(stdout), "wb"); /* "wb9" for max compr. */ 232 if (file == NULL) error("can't gzdopen stdout"); 233 gz_compress(stdin, file); 234 } 235 } else { 236 do { 237 if (uncompr) { 238 file_uncompress(*argv); 239 } else { 240 file_compress(*argv); 241 } 242 } while (argv++, --argc); 243 } 244 exit(0); 245 return 0; /* to avoid warning */ 246 } 247