Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenminigzip.c
Go to the documentation of this file.
00001 /* minigzip.c -- simulate gzip using the zlib compression library 00002 * Copyright (C) 1995-2006, 2010 Jean-loup Gailly. 00003 * For conditions of distribution and use, see copyright notice in zlib.h 00004 */ 00005 00006 /* 00007 * minigzip is a minimal implementation of the gzip utility. This is 00008 * only an example of using zlib and isn't meant to replace the 00009 * full-featured gzip. No attempt is made to deal with file systems 00010 * limiting names to 14 or 8+3 characters, etc... Error checking is 00011 * very limited. So use minigzip only for testing; use gzip for the 00012 * real thing. On MSDOS, use only on file names without extension 00013 * or in pipe mode. 00014 */ 00015 00016 /* @(#) $Id: minigzip.c 47691 2010-06-08 01:37:58Z tkreuzer $ */ 00017 00018 #include "zlib.h" 00019 #include <stdio.h> 00020 00021 #ifdef STDC 00022 # include <string.h> 00023 # include <stdlib.h> 00024 #endif 00025 00026 #ifdef USE_MMAP 00027 # include <sys/types.h> 00028 # include <sys/mman.h> 00029 # include <sys/stat.h> 00030 #endif 00031 00032 #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) 00033 # include <fcntl.h> 00034 # include <io.h> 00035 # ifdef UNDER_CE 00036 # include <stdlib.h> 00037 # endif 00038 # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 00039 #else 00040 # define SET_BINARY_MODE(file) 00041 #endif 00042 00043 #ifdef VMS 00044 # define unlink delete 00045 # define GZ_SUFFIX "-gz" 00046 #endif 00047 #ifdef RISCOS 00048 # define unlink remove 00049 # define GZ_SUFFIX "-gz" 00050 # define fileno(file) file->__file 00051 #endif 00052 #if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os 00053 # include <unix.h> /* for fileno */ 00054 #endif 00055 00056 #if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE) 00057 #ifndef WIN32 /* unlink already in stdio.h for WIN32 */ 00058 extern int unlink OF((const char *)); 00059 #endif 00060 #endif 00061 00062 #if defined(UNDER_CE) 00063 # include <windows.h> 00064 # define perror(s) pwinerror(s) 00065 00066 /* Map the Windows error number in ERROR to a locale-dependent error 00067 message string and return a pointer to it. Typically, the values 00068 for ERROR come from GetLastError. 00069 00070 The string pointed to shall not be modified by the application, 00071 but may be overwritten by a subsequent call to strwinerror 00072 00073 The strwinerror function does not change the current setting 00074 of GetLastError. */ 00075 00076 static char *strwinerror (error) 00077 DWORD error; 00078 { 00079 static char buf[1024]; 00080 00081 wchar_t *msgbuf; 00082 DWORD lasterr = GetLastError(); 00083 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 00084 | FORMAT_MESSAGE_ALLOCATE_BUFFER, 00085 NULL, 00086 error, 00087 0, /* Default language */ 00088 (LPVOID)&msgbuf, 00089 0, 00090 NULL); 00091 if (chars != 0) { 00092 /* If there is an \r\n appended, zap it. */ 00093 if (chars >= 2 00094 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 00095 chars -= 2; 00096 msgbuf[chars] = 0; 00097 } 00098 00099 if (chars > sizeof (buf) - 1) { 00100 chars = sizeof (buf) - 1; 00101 msgbuf[chars] = 0; 00102 } 00103 00104 wcstombs(buf, msgbuf, chars + 1); 00105 LocalFree(msgbuf); 00106 } 00107 else { 00108 sprintf(buf, "unknown win32 error (%ld)", error); 00109 } 00110 00111 SetLastError(lasterr); 00112 return buf; 00113 } 00114 00115 static void pwinerror (s) 00116 const char *s; 00117 { 00118 if (s && *s) 00119 fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ())); 00120 else 00121 fprintf(stderr, "%s\n", strwinerror(GetLastError ())); 00122 } 00123 00124 #endif /* UNDER_CE */ 00125 00126 #ifndef GZ_SUFFIX 00127 # define GZ_SUFFIX ".gz" 00128 #endif 00129 #define SUFFIX_LEN (sizeof(GZ_SUFFIX)-1) 00130 00131 #define BUFLEN 16384 00132 #define MAX_NAME_LEN 1024 00133 00134 #ifdef MAXSEG_64K 00135 # define local static 00136 /* Needed for systems with limitation on stack size. */ 00137 #else 00138 # define local 00139 #endif 00140 00141 char *prog; 00142 00143 void error OF((const char *msg)); 00144 void gz_compress OF((FILE *in, gzFile out)); 00145 #ifdef USE_MMAP 00146 int gz_compress_mmap OF((FILE *in, gzFile out)); 00147 #endif 00148 void gz_uncompress OF((gzFile in, FILE *out)); 00149 void file_compress OF((char *file, char *mode)); 00150 void file_uncompress OF((char *file)); 00151 int main OF((int argc, char *argv[])); 00152 00153 /* =========================================================================== 00154 * Display error message and exit 00155 */ 00156 void error(msg) 00157 const char *msg; 00158 { 00159 fprintf(stderr, "%s: %s\n", prog, msg); 00160 exit(1); 00161 } 00162 00163 /* =========================================================================== 00164 * Compress input to output then close both files. 00165 */ 00166 00167 void gz_compress(in, out) 00168 FILE *in; 00169 gzFile out; 00170 { 00171 local char buf[BUFLEN]; 00172 int len; 00173 int err; 00174 00175 #ifdef USE_MMAP 00176 /* Try first compressing with mmap. If mmap fails (minigzip used in a 00177 * pipe), use the normal fread loop. 00178 */ 00179 if (gz_compress_mmap(in, out) == Z_OK) return; 00180 #endif 00181 for (;;) { 00182 len = (int)fread(buf, 1, sizeof(buf), in); 00183 if (ferror(in)) { 00184 perror("fread"); 00185 exit(1); 00186 } 00187 if (len == 0) break; 00188 00189 if (gzwrite(out, buf, (unsigned)len) != len) error(gzerror(out, &err)); 00190 } 00191 fclose(in); 00192 if (gzclose(out) != Z_OK) error("failed gzclose"); 00193 } 00194 00195 #ifdef USE_MMAP /* MMAP version, Miguel Albrecht <malbrech@eso.org> */ 00196 00197 /* Try compressing the input file at once using mmap. Return Z_OK if 00198 * if success, Z_ERRNO otherwise. 00199 */ 00200 int gz_compress_mmap(in, out) 00201 FILE *in; 00202 gzFile out; 00203 { 00204 int len; 00205 int err; 00206 int ifd = fileno(in); 00207 caddr_t buf; /* mmap'ed buffer for the entire input file */ 00208 off_t buf_len; /* length of the input file */ 00209 struct stat sb; 00210 00211 /* Determine the size of the file, needed for mmap: */ 00212 if (fstat(ifd, &sb) < 0) return Z_ERRNO; 00213 buf_len = sb.st_size; 00214 if (buf_len <= 0) return Z_ERRNO; 00215 00216 /* Now do the actual mmap: */ 00217 buf = mmap((caddr_t) 0, buf_len, PROT_READ, MAP_SHARED, ifd, (off_t)0); 00218 if (buf == (caddr_t)(-1)) return Z_ERRNO; 00219 00220 /* Compress the whole file at once: */ 00221 len = gzwrite(out, (char *)buf, (unsigned)buf_len); 00222 00223 if (len != (int)buf_len) error(gzerror(out, &err)); 00224 00225 munmap(buf, buf_len); 00226 fclose(in); 00227 if (gzclose(out) != Z_OK) error("failed gzclose"); 00228 return Z_OK; 00229 } 00230 #endif /* USE_MMAP */ 00231 00232 /* =========================================================================== 00233 * Uncompress input to output then close both files. 00234 */ 00235 void gz_uncompress(in, out) 00236 gzFile in; 00237 FILE *out; 00238 { 00239 local char buf[BUFLEN]; 00240 int len; 00241 int err; 00242 00243 for (;;) { 00244 len = gzread(in, buf, sizeof(buf)); 00245 if (len < 0) error (gzerror(in, &err)); 00246 if (len == 0) break; 00247 00248 if ((int)fwrite(buf, 1, (unsigned)len, out) != len) { 00249 error("failed fwrite"); 00250 } 00251 } 00252 if (fclose(out)) error("failed fclose"); 00253 00254 if (gzclose(in) != Z_OK) error("failed gzclose"); 00255 } 00256 00257 00258 /* =========================================================================== 00259 * Compress the given file: create a corresponding .gz file and remove the 00260 * original. 00261 */ 00262 void file_compress(file, mode) 00263 char *file; 00264 char *mode; 00265 { 00266 local char outfile[MAX_NAME_LEN]; 00267 FILE *in; 00268 gzFile out; 00269 00270 if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) { 00271 fprintf(stderr, "%s: filename too long\n", prog); 00272 exit(1); 00273 } 00274 00275 strcpy(outfile, file); 00276 strcat(outfile, GZ_SUFFIX); 00277 00278 in = fopen(file, "rb"); 00279 if (in == NULL) { 00280 perror(file); 00281 exit(1); 00282 } 00283 out = gzopen(outfile, mode); 00284 if (out == NULL) { 00285 fprintf(stderr, "%s: can't gzopen %s\n", prog, outfile); 00286 exit(1); 00287 } 00288 gz_compress(in, out); 00289 00290 unlink(file); 00291 } 00292 00293 00294 /* =========================================================================== 00295 * Uncompress the given file and remove the original. 00296 */ 00297 void file_uncompress(file) 00298 char *file; 00299 { 00300 local char buf[MAX_NAME_LEN]; 00301 char *infile, *outfile; 00302 FILE *out; 00303 gzFile in; 00304 size_t len = strlen(file); 00305 00306 if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) { 00307 fprintf(stderr, "%s: filename too long\n", prog); 00308 exit(1); 00309 } 00310 00311 strcpy(buf, file); 00312 00313 if (len > SUFFIX_LEN && strcmp(file+len-SUFFIX_LEN, GZ_SUFFIX) == 0) { 00314 infile = file; 00315 outfile = buf; 00316 outfile[len-3] = '\0'; 00317 } else { 00318 outfile = file; 00319 infile = buf; 00320 strcat(infile, GZ_SUFFIX); 00321 } 00322 in = gzopen(infile, "rb"); 00323 if (in == NULL) { 00324 fprintf(stderr, "%s: can't gzopen %s\n", prog, infile); 00325 exit(1); 00326 } 00327 out = fopen(outfile, "wb"); 00328 if (out == NULL) { 00329 perror(file); 00330 exit(1); 00331 } 00332 00333 gz_uncompress(in, out); 00334 00335 unlink(infile); 00336 } 00337 00338 00339 /* =========================================================================== 00340 * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...] 00341 * -c : write to standard output 00342 * -d : decompress 00343 * -f : compress with Z_FILTERED 00344 * -h : compress with Z_HUFFMAN_ONLY 00345 * -r : compress with Z_RLE 00346 * -1 to -9 : compression level 00347 */ 00348 00349 int main(argc, argv) 00350 int argc; 00351 char *argv[]; 00352 { 00353 int copyout = 0; 00354 int uncompr = 0; 00355 gzFile file; 00356 char *bname, outmode[20]; 00357 00358 strcpy(outmode, "wb6 "); 00359 00360 prog = argv[0]; 00361 bname = strrchr(argv[0], '/'); 00362 if (bname) 00363 bname++; 00364 else 00365 bname = argv[0]; 00366 argc--, argv++; 00367 00368 if (!strcmp(bname, "gunzip")) 00369 uncompr = 1; 00370 else if (!strcmp(bname, "zcat")) 00371 copyout = uncompr = 1; 00372 00373 while (argc > 0) { 00374 if (strcmp(*argv, "-c") == 0) 00375 copyout = 1; 00376 else if (strcmp(*argv, "-d") == 0) 00377 uncompr = 1; 00378 else if (strcmp(*argv, "-f") == 0) 00379 outmode[3] = 'f'; 00380 else if (strcmp(*argv, "-h") == 0) 00381 outmode[3] = 'h'; 00382 else if (strcmp(*argv, "-r") == 0) 00383 outmode[3] = 'R'; 00384 else if ((*argv)[0] == '-' && (*argv)[1] >= '1' && (*argv)[1] <= '9' && 00385 (*argv)[2] == 0) 00386 outmode[2] = (*argv)[1]; 00387 else 00388 break; 00389 argc--, argv++; 00390 } 00391 if (outmode[3] == ' ') 00392 outmode[3] = 0; 00393 if (argc == 0) { 00394 SET_BINARY_MODE(stdin); 00395 SET_BINARY_MODE(stdout); 00396 if (uncompr) { 00397 file = gzdopen(fileno(stdin), "rb"); 00398 if (file == NULL) error("can't gzdopen stdin"); 00399 gz_uncompress(file, stdout); 00400 } else { 00401 file = gzdopen(fileno(stdout), outmode); 00402 if (file == NULL) error("can't gzdopen stdout"); 00403 gz_compress(stdin, file); 00404 } 00405 } else { 00406 if (copyout) { 00407 SET_BINARY_MODE(stdout); 00408 } 00409 do { 00410 if (uncompr) { 00411 if (copyout) { 00412 file = gzopen(*argv, "rb"); 00413 if (file == NULL) 00414 fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv); 00415 else 00416 gz_uncompress(file, stdout); 00417 } else { 00418 file_uncompress(*argv); 00419 } 00420 } else { 00421 if (copyout) { 00422 FILE * in = fopen(*argv, "rb"); 00423 00424 if (in == NULL) { 00425 perror(*argv); 00426 } else { 00427 file = gzdopen(fileno(stdout), outmode); 00428 if (file == NULL) error("can't gzdopen stdout"); 00429 00430 gz_compress(in, file); 00431 } 00432 00433 } else { 00434 file_compress(*argv, outmode); 00435 } 00436 } 00437 } while (argv++, --argc); 00438 } 00439 return 0; 00440 } Generated on Sat May 26 2012 04:34:50 for ReactOS by
1.7.6.1
|