Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengzlib.c
Go to the documentation of this file.
00001 /* gzlib.c -- zlib functions common to reading and writing gzip files 00002 * Copyright (C) 2004, 2010 Mark Adler 00003 * For conditions of distribution and use, see copyright notice in zlib.h 00004 */ 00005 00006 #include "gzguts.h" 00007 00008 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 00009 # define LSEEK lseek64 00010 #else 00011 # define LSEEK lseek 00012 #endif 00013 00014 /* Local functions */ 00015 local void gz_reset OF((gz_statep)); 00016 local gzFile gz_open OF((const char *, int, const char *)); 00017 00018 #if defined UNDER_CE 00019 00020 /* Map the Windows error number in ERROR to a locale-dependent error message 00021 string and return a pointer to it. Typically, the values for ERROR come 00022 from GetLastError. 00023 00024 The string pointed to shall not be modified by the application, but may be 00025 overwritten by a subsequent call to gz_strwinerror 00026 00027 The gz_strwinerror function does not change the current setting of 00028 GetLastError. */ 00029 char ZLIB_INTERNAL *gz_strwinerror (error) 00030 DWORD error; 00031 { 00032 static char buf[1024]; 00033 00034 wchar_t *msgbuf; 00035 DWORD lasterr = GetLastError(); 00036 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM 00037 | FORMAT_MESSAGE_ALLOCATE_BUFFER, 00038 NULL, 00039 error, 00040 0, /* Default language */ 00041 (LPVOID)&msgbuf, 00042 0, 00043 NULL); 00044 if (chars != 0) { 00045 /* If there is an \r\n appended, zap it. */ 00046 if (chars >= 2 00047 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { 00048 chars -= 2; 00049 msgbuf[chars] = 0; 00050 } 00051 00052 if (chars > sizeof (buf) - 1) { 00053 chars = sizeof (buf) - 1; 00054 msgbuf[chars] = 0; 00055 } 00056 00057 wcstombs(buf, msgbuf, chars + 1); 00058 LocalFree(msgbuf); 00059 } 00060 else { 00061 sprintf(buf, "unknown win32 error (%ld)", error); 00062 } 00063 00064 SetLastError(lasterr); 00065 return buf; 00066 } 00067 00068 #endif /* UNDER_CE */ 00069 00070 /* Reset gzip file state */ 00071 local void gz_reset(state) 00072 gz_statep state; 00073 { 00074 if (state->mode == GZ_READ) { /* for reading ... */ 00075 state->have = 0; /* no output data available */ 00076 state->eof = 0; /* not at end of file */ 00077 state->how = LOOK; /* look for gzip header */ 00078 state->direct = 1; /* default for empty file */ 00079 } 00080 state->seek = 0; /* no seek request pending */ 00081 gz_error(state, Z_OK, NULL); /* clear error */ 00082 state->pos = 0; /* no uncompressed data yet */ 00083 state->strm.avail_in = 0; /* no input data yet */ 00084 } 00085 00086 /* Open a gzip file either by name or file descriptor. */ 00087 local gzFile gz_open(path, fd, mode) 00088 const char *path; 00089 int fd; 00090 const char *mode; 00091 { 00092 gz_statep state; 00093 00094 /* allocate gzFile structure to return */ 00095 state = malloc(sizeof(gz_state)); 00096 if (state == NULL) 00097 return NULL; 00098 state->size = 0; /* no buffers allocated yet */ 00099 state->want = GZBUFSIZE; /* requested buffer size */ 00100 state->msg = NULL; /* no error message yet */ 00101 00102 /* interpret mode */ 00103 state->mode = GZ_NONE; 00104 state->level = Z_DEFAULT_COMPRESSION; 00105 state->strategy = Z_DEFAULT_STRATEGY; 00106 while (*mode) { 00107 if (*mode >= '0' && *mode <= '9') 00108 state->level = *mode - '0'; 00109 else 00110 switch (*mode) { 00111 case 'r': 00112 state->mode = GZ_READ; 00113 break; 00114 #ifndef NO_GZCOMPRESS 00115 case 'w': 00116 state->mode = GZ_WRITE; 00117 break; 00118 case 'a': 00119 state->mode = GZ_APPEND; 00120 break; 00121 #endif 00122 case '+': /* can't read and write at the same time */ 00123 free(state); 00124 return NULL; 00125 case 'b': /* ignore -- will request binary anyway */ 00126 break; 00127 case 'f': 00128 state->strategy = Z_FILTERED; 00129 break; 00130 case 'h': 00131 state->strategy = Z_HUFFMAN_ONLY; 00132 break; 00133 case 'R': 00134 state->strategy = Z_RLE; 00135 break; 00136 case 'F': 00137 state->strategy = Z_FIXED; 00138 default: /* could consider as an error, but just ignore */ 00139 ; 00140 } 00141 mode++; 00142 } 00143 00144 /* must provide an "r", "w", or "a" */ 00145 if (state->mode == GZ_NONE) { 00146 free(state); 00147 return NULL; 00148 } 00149 00150 /* save the path name for error messages */ 00151 state->path = malloc(strlen(path) + 1); 00152 if (state->path == NULL) { 00153 free(state); 00154 return NULL; 00155 } 00156 strcpy(state->path, path); 00157 00158 /* open the file with the appropriate mode (or just use fd) */ 00159 state->fd = fd != -1 ? fd : 00160 open(path, 00161 #ifdef O_LARGEFILE 00162 O_LARGEFILE | 00163 #endif 00164 #ifdef O_BINARY 00165 O_BINARY | 00166 #endif 00167 (state->mode == GZ_READ ? 00168 O_RDONLY : 00169 (O_WRONLY | O_CREAT | ( 00170 state->mode == GZ_WRITE ? 00171 O_TRUNC : 00172 O_APPEND))), 00173 0666); 00174 if (state->fd == -1) { 00175 free(state->path); 00176 free(state); 00177 return NULL; 00178 } 00179 if (state->mode == GZ_APPEND) 00180 state->mode = GZ_WRITE; /* simplify later checks */ 00181 00182 /* save the current position for rewinding (only if reading) */ 00183 if (state->mode == GZ_READ) { 00184 state->start = LSEEK(state->fd, 0, SEEK_CUR); 00185 if (state->start == -1) state->start = 0; 00186 } 00187 00188 /* initialize stream */ 00189 gz_reset(state); 00190 00191 /* return stream */ 00192 return (gzFile)state; 00193 } 00194 00195 /* -- see zlib.h -- */ 00196 gzFile ZEXPORT gzopen(path, mode) 00197 const char *path; 00198 const char *mode; 00199 { 00200 return gz_open(path, -1, mode); 00201 } 00202 00203 /* -- see zlib.h -- */ 00204 gzFile ZEXPORT gzopen64(path, mode) 00205 const char *path; 00206 const char *mode; 00207 { 00208 return gz_open(path, -1, mode); 00209 } 00210 00211 /* -- see zlib.h -- */ 00212 gzFile ZEXPORT gzdopen(fd, mode) 00213 int fd; 00214 const char *mode; 00215 { 00216 char *path; /* identifier for error messages */ 00217 gzFile gz; 00218 00219 if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL) 00220 return NULL; 00221 sprintf(path, "<fd:%d>", fd); /* for debugging */ 00222 gz = gz_open(path, fd, mode); 00223 free(path); 00224 return gz; 00225 } 00226 00227 /* -- see zlib.h -- */ 00228 int ZEXPORT gzbuffer(file, size) 00229 gzFile file; 00230 unsigned size; 00231 { 00232 gz_statep state; 00233 00234 /* get internal structure and check integrity */ 00235 if (file == NULL) 00236 return -1; 00237 state = (gz_statep)file; 00238 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00239 return -1; 00240 00241 /* make sure we haven't already allocated memory */ 00242 if (state->size != 0) 00243 return -1; 00244 00245 /* check and set requested size */ 00246 if (size == 0) 00247 return -1; 00248 state->want = size; 00249 return 0; 00250 } 00251 00252 /* -- see zlib.h -- */ 00253 int ZEXPORT gzrewind(file) 00254 gzFile file; 00255 { 00256 gz_statep state; 00257 00258 /* get internal structure */ 00259 if (file == NULL) 00260 return -1; 00261 state = (gz_statep)file; 00262 00263 /* check that we're reading and that there's no error */ 00264 if (state->mode != GZ_READ || state->err != Z_OK) 00265 return -1; 00266 00267 /* back up and start over */ 00268 if (LSEEK(state->fd, state->start, SEEK_SET) == -1) 00269 return -1; 00270 gz_reset(state); 00271 return 0; 00272 } 00273 00274 /* -- see zlib.h -- */ 00275 z_off64_t ZEXPORT gzseek64(file, offset, whence) 00276 gzFile file; 00277 z_off64_t offset; 00278 int whence; 00279 { 00280 unsigned n; 00281 z_off64_t ret; 00282 gz_statep state; 00283 00284 /* get internal structure and check integrity */ 00285 if (file == NULL) 00286 return -1; 00287 state = (gz_statep)file; 00288 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00289 return -1; 00290 00291 /* check that there's no error */ 00292 if (state->err != Z_OK) 00293 return -1; 00294 00295 /* can only seek from start or relative to current position */ 00296 if (whence != SEEK_SET && whence != SEEK_CUR) 00297 return -1; 00298 00299 /* normalize offset to a SEEK_CUR specification */ 00300 if (whence == SEEK_SET) 00301 offset -= state->pos; 00302 else if (state->seek) 00303 offset += state->skip; 00304 state->seek = 0; 00305 00306 /* if within raw area while reading, just go there */ 00307 if (state->mode == GZ_READ && state->how == COPY && 00308 state->pos + offset >= state->raw) { 00309 ret = LSEEK(state->fd, offset - state->have, SEEK_CUR); 00310 if (ret == -1) 00311 return -1; 00312 state->have = 0; 00313 state->eof = 0; 00314 state->seek = 0; 00315 gz_error(state, Z_OK, NULL); 00316 state->strm.avail_in = 0; 00317 state->pos += offset; 00318 return state->pos; 00319 } 00320 00321 /* calculate skip amount, rewinding if needed for back seek when reading */ 00322 if (offset < 0) { 00323 if (state->mode != GZ_READ) /* writing -- can't go backwards */ 00324 return -1; 00325 offset += state->pos; 00326 if (offset < 0) /* before start of file! */ 00327 return -1; 00328 if (gzrewind(file) == -1) /* rewind, then skip to offset */ 00329 return -1; 00330 } 00331 00332 /* if reading, skip what's in output buffer (one less gzgetc() check) */ 00333 if (state->mode == GZ_READ) { 00334 n = GT_OFF(state->have) || (z_off64_t)state->have > offset ? 00335 (unsigned)offset : state->have; 00336 state->have -= n; 00337 state->next += n; 00338 state->pos += n; 00339 offset -= n; 00340 } 00341 00342 /* request skip (if not zero) */ 00343 if (offset) { 00344 state->seek = 1; 00345 state->skip = offset; 00346 } 00347 return state->pos + offset; 00348 } 00349 00350 /* -- see zlib.h -- */ 00351 z_off_t ZEXPORT gzseek(file, offset, whence) 00352 gzFile file; 00353 z_off_t offset; 00354 int whence; 00355 { 00356 z_off64_t ret; 00357 00358 ret = gzseek64(file, (z_off64_t)offset, whence); 00359 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 00360 } 00361 00362 /* -- see zlib.h -- */ 00363 z_off64_t ZEXPORT gztell64(file) 00364 gzFile file; 00365 { 00366 gz_statep state; 00367 00368 /* get internal structure and check integrity */ 00369 if (file == NULL) 00370 return -1; 00371 state = (gz_statep)file; 00372 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00373 return -1; 00374 00375 /* return position */ 00376 return state->pos + (state->seek ? state->skip : 0); 00377 } 00378 00379 /* -- see zlib.h -- */ 00380 z_off_t ZEXPORT gztell(file) 00381 gzFile file; 00382 { 00383 z_off64_t ret; 00384 00385 ret = gztell64(file); 00386 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 00387 } 00388 00389 /* -- see zlib.h -- */ 00390 z_off64_t ZEXPORT gzoffset64(file) 00391 gzFile file; 00392 { 00393 z_off64_t offset; 00394 gz_statep state; 00395 00396 /* get internal structure and check integrity */ 00397 if (file == NULL) 00398 return -1; 00399 state = (gz_statep)file; 00400 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00401 return -1; 00402 00403 /* compute and return effective offset in file */ 00404 offset = LSEEK(state->fd, 0, SEEK_CUR); 00405 if (offset == -1) 00406 return -1; 00407 if (state->mode == GZ_READ) /* reading */ 00408 offset -= state->strm.avail_in; /* don't count buffered input */ 00409 return offset; 00410 } 00411 00412 /* -- see zlib.h -- */ 00413 z_off_t ZEXPORT gzoffset(file) 00414 gzFile file; 00415 { 00416 z_off64_t ret; 00417 00418 ret = gzoffset64(file); 00419 return ret == (z_off_t)ret ? (z_off_t)ret : -1; 00420 } 00421 00422 /* -- see zlib.h -- */ 00423 int ZEXPORT gzeof(file) 00424 gzFile file; 00425 { 00426 gz_statep state; 00427 00428 /* get internal structure and check integrity */ 00429 if (file == NULL) 00430 return 0; 00431 state = (gz_statep)file; 00432 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00433 return 0; 00434 00435 /* return end-of-file state */ 00436 return state->mode == GZ_READ ? 00437 (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0; 00438 } 00439 00440 /* -- see zlib.h -- */ 00441 const char * ZEXPORT gzerror(file, errnum) 00442 gzFile file; 00443 int *errnum; 00444 { 00445 gz_statep state; 00446 00447 /* get internal structure and check integrity */ 00448 if (file == NULL) 00449 return NULL; 00450 state = (gz_statep)file; 00451 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00452 return NULL; 00453 00454 /* return error information */ 00455 if (errnum != NULL) 00456 *errnum = state->err; 00457 return state->msg == NULL ? "" : state->msg; 00458 } 00459 00460 /* -- see zlib.h -- */ 00461 void ZEXPORT gzclearerr(file) 00462 gzFile file; 00463 { 00464 gz_statep state; 00465 00466 /* get internal structure and check integrity */ 00467 if (file == NULL) 00468 return; 00469 state = (gz_statep)file; 00470 if (state->mode != GZ_READ && state->mode != GZ_WRITE) 00471 return; 00472 00473 /* clear error and end-of-file */ 00474 if (state->mode == GZ_READ) 00475 state->eof = 0; 00476 gz_error(state, Z_OK, NULL); 00477 } 00478 00479 /* Create an error message in allocated memory and set state->err and 00480 state->msg accordingly. Free any previous error message already there. Do 00481 not try to free or allocate space if the error is Z_MEM_ERROR (out of 00482 memory). Simply save the error message as a static string. If there is an 00483 allocation failure constructing the error message, then convert the error to 00484 out of memory. */ 00485 void ZLIB_INTERNAL gz_error(state, err, msg) 00486 gz_statep state; 00487 int err; 00488 const char *msg; 00489 { 00490 /* free previously allocated message and clear */ 00491 if (state->msg != NULL) { 00492 if (state->err != Z_MEM_ERROR) 00493 free(state->msg); 00494 state->msg = NULL; 00495 } 00496 00497 /* set error code, and if no message, then done */ 00498 state->err = err; 00499 if (msg == NULL) 00500 return; 00501 00502 /* for an out of memory error, save as static string */ 00503 if (err == Z_MEM_ERROR) { 00504 state->msg = (char *)msg; 00505 return; 00506 } 00507 00508 /* construct error message with path */ 00509 if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) { 00510 state->err = Z_MEM_ERROR; 00511 state->msg = (char *)"out of memory"; 00512 return; 00513 } 00514 strcpy(state->msg, state->path); 00515 strcat(state->msg, ": "); 00516 strcat(state->msg, msg); 00517 return; 00518 } 00519 00520 #ifndef INT_MAX 00521 /* portably return maximum value for an int (when limits.h presumed not 00522 available) -- we need to do this to cover cases where 2's complement not 00523 used, since C standard permits 1's complement and sign-bit representations, 00524 otherwise we could just use ((unsigned)-1) >> 1 */ 00525 unsigned ZLIB_INTERNAL gz_intmax() 00526 { 00527 unsigned p, q; 00528 00529 p = 1; 00530 do { 00531 q = p; 00532 p <<= 1; 00533 p++; 00534 } while (p > q); 00535 return q >> 1; 00536 } 00537 #endif Generated on Sat May 26 2012 04:34:50 for ReactOS by
1.7.6.1
|