Coverage Report

Created: 2026-10-28 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/main/dounzip.c
Line
Count
Source
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  file dounzip.c
4
 *  first part  Copyright (C) 2002-2026 The R Core Team
5
 *  second part Copyright (C) 1998-2010 Gilles Vollant
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2 of the License, or
10
 *  (at your option) any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, a copy is available at
19
 *  https://www.R-project.org/Licenses/
20
 */
21
22
#ifdef HAVE_CONFIG_H
23
#include <config.h>
24
#endif
25
26
#define HAVE_BZIP2
27
28
#define R_USE_SIGNALS 1
29
#include <Defn.h>
30
#include <Fileio.h> /* for R_fopen */
31
#include "unzip.h"
32
#ifdef HAVE_SYS_STAT_H
33
# include <sys/stat.h>
34
#endif
35
#include <errno.h>
36
#include <stdlib.h>
37
#include <string.h>
38
39
#ifdef Win32
40
#include <io.h> /* for mkdir */
41
#endif
42
43
/* cf do_dircreate in platform.c */
44
static int R_mkdir(char *path)
45
0
{
46
#ifdef Win32
47
    char *local = (char *)malloc(strlen(path) + 1);
48
    if (!local) {
49
  errno = ENOMEM;
50
  return -1;
51
    }
52
    strcpy(local, path);
53
    /* needed DOS paths on Win 9x */
54
    R_fixbackslash(local);
55
    int res = mkdir(local);
56
    free(local);
57
    return res;
58
#endif
59
0
#ifdef Unix
60
0
    return mkdir(path, 0777);
61
0
#endif
62
0
}
63
64
#ifdef Win32
65
#include <windows.h>
66
static void setFileTime(const char *fn, uLong dosdate)
67
{
68
    HANDLE hFile;
69
    FILETIME ftm, ftLocal;
70
71
    hFile = CreateFileA(fn, GENERIC_READ | GENERIC_WRITE,
72
      0, NULL, OPEN_EXISTING, 0, NULL);
73
    if (hFile == INVALID_HANDLE_VALUE) return;
74
    DosDateTimeToFileTime((WORD)(dosdate >> 16), (WORD)dosdate, &ftLocal);
75
    LocalFileTimeToFileTime(&ftLocal, &ftm);
76
    SetFileTime(hFile, &ftm, NULL, &ftm);
77
    CloseHandle(hFile);
78
}
79
#else
80
# include <time.h>
81
# ifdef HAVE_UTIMES
82
#  include <sys/time.h>
83
# endif
84
# ifdef HAVE_UTIME_H
85
#  include <utime.h>
86
# endif
87
static void setFileTime(const char *fn, tm_unz tmu_date)
88
0
{
89
0
    struct tm dt;
90
0
    dt.tm_sec = tmu_date.tm_sec;
91
0
    dt.tm_min = tmu_date.tm_min;
92
0
    dt.tm_hour = tmu_date.tm_hour;
93
0
    dt.tm_mday = tmu_date.tm_mday;
94
0
    dt.tm_mon = tmu_date.tm_mon;
95
0
    if (tmu_date.tm_year > 1900)
96
0
  dt.tm_year = tmu_date.tm_year - 1900;
97
0
    else
98
0
  dt.tm_year = tmu_date.tm_year;
99
0
    dt.tm_isdst = -1;
100
0
    time_t ftime = mktime(&dt);
101
0
#if defined(HAVE_UTIMES)
102
0
    struct timeval times[2];
103
104
0
    times[0].tv_sec = times[1].tv_sec = ftime;
105
0
    times[0].tv_usec = times[1].tv_usec = 0;
106
0
    utimes(fn, times);
107
#elif defined(HAVE_UTIME)
108
    struct utimbuf settime;
109
    settime.actime = settime.modtime = ftime;
110
    utime(fn, &settime);
111
#endif
112
0
}
113
#endif
114
115
0
#define UNZ_UNSAFE_LINK -201
116
117
/* The caller chooses 'dest' itself.  Below it, refuse to create anything
118
   through a symbolic link, whether an intermediate component or a
119
   pre-existing final component (which fopen() would follow).  Must run on
120
   the path as it will be used, i.e. after "../" components are removed. */
121
static int isExtractLink(const char *path)
122
750
{
123
#ifdef Win32
124
    DWORD attrs = GetFileAttributesA(path);
125
    return attrs != INVALID_FILE_ATTRIBUTES &&
126
  (attrs & FILE_ATTRIBUTE_REPARSE_POINT);
127
#else
128
750
    struct stat st;
129
750
    return lstat(path, &st) == 0 && S_ISLNK(st.st_mode);
130
750
#endif
131
750
}
132
133
static int hasExtractLink(const char *dest, const char *outname)
134
750
{
135
750
    char path[R_PATH_MAX];
136
750
    size_t len = strlen(outname), base = strlen(dest) + 1;
137
750
    strcpy(path, outname); /* extract_one has already checked its length */
138
20.1k
    for (size_t i = base; i < len; i++) {
139
19.3k
  if (path[i] == '/') {
140
0
      path[i] = '\0';
141
0
      int linked = isExtractLink(path);
142
0
      path[i] = '/';
143
0
      if (linked) return 1;
144
0
  }
145
19.3k
    }
146
750
    return len > base && isExtractLink(path);
147
750
}
148
149
/* Remove "../" components below 'dest', as unzip 6.00 does, warning once. */
150
static void stripDotDot(const char *dest, char *outname, const char *fn)
151
780
{
152
780
    char *pp = outname + strlen(dest) + 1, *p;
153
780
    bool warned = FALSE;
154
781
    while ((p = Rf_strchr(pp, '/'))) {
155
1
  if (p - pp == 2 && !strncmp(pp, "..", 2)) {
156
0
      if (!warned) {
157
0
    warning(_("skipped \"../\" path component(s) in '%s'"), fn);
158
0
    warned = true;
159
0
      }
160
0
      memmove(pp, p + 1, strlen(p + 1) + 1);
161
1
  } else {
162
1
      pp = p + 1;
163
1
  }
164
1
    }
165
780
}
166
167
/* Create missing parents of 'outname' below 'dest' (which exists).
168
   Returns 0, or -1 with errno set and the failing directory in 'dirs'. */
169
static int makeParents(const char *dest, const char *outname, char *dirs)
170
750
{
171
750
    const char *pp = outname + strlen(dest) + 1, *p;
172
750
    while ((p = Rf_strchr_const(pp, '/'))) {
173
0
  strcpy(dirs, outname);
174
0
  dirs[p - outname] = '\0';
175
0
  if (!R_FileExists(dirs) && R_mkdir(dirs)) return -1;
176
0
  pp = p + 1;
177
0
    }
178
750
    return 0;
179
750
}
180
181
9.01k
#define BUF_SIZE 4096
182
static int
183
extract_one(unzFile uf, const char *const dest, const char * const filename,
184
      SEXP names, int *nnames, int overwrite, int junk, int setTime)
185
932
{
186
932
    int err = UNZ_OK;
187
932
    FILE *fout;
188
932
    char  outname[R_PATH_MAX], dirs[R_PATH_MAX], buf[BUF_SIZE], *p;
189
932
    char *fn, fn0[R_PATH_MAX];
190
191
932
    err = unzOpenCurrentFile(uf);
192
932
    if (err != UNZ_OK) return err;
193
782
    if (strlen(dest) > R_PATH_MAX - 2) {
194
0
  unzCloseCurrentFile(uf);
195
0
  return 1;
196
0
    }
197
782
    strcpy(outname, dest);
198
782
    strcat(outname, FILESEP);
199
782
    unz_file_info64 file_info;
200
782
    char filename_inzip[R_PATH_MAX];
201
782
    err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip,
202
782
          sizeof(filename_inzip), NULL, 0, NULL, 0);
203
782
    fn = filename_inzip; /* might be UTF-8 ... */
204
782
    if (filename) {
205
0
  if (strlen(filename) > R_PATH_MAX - 1) {
206
0
      unzCloseCurrentFile(uf);
207
0
      return 1;
208
0
  }
209
0
  strcpy(fn0, filename);
210
0
  fn = fn0;
211
782
    } else if (err != UNZ_OK
212
781
               || file_info.size_filename >= sizeof(filename_inzip)) {
213
2
  unzCloseCurrentFile(uf);
214
2
  return 1;
215
2
    }
216
#ifdef Win32
217
    R_fixslash(fn);
218
#endif
219
780
    if (junk && strlen(fn) >= 2) { /* need / and basename */
220
764
  p = Rf_strrchr(fn, '/');
221
764
  if (p) fn = p+1;
222
764
    }
223
780
    if (strlen(outname) + strlen(fn) > R_PATH_MAX - 1) {
224
0
  unzCloseCurrentFile(uf);
225
0
  return 1;
226
0
    }
227
780
    strcat(outname, fn);
228
229
#ifdef Win32
230
    R_fixslash(outname); /* ensure path separator is / */
231
#endif
232
    /* Normalize before looking at the file system, so that the symlink
233
       check and the directory creation see the same path. */
234
780
    stripDotDot(dest, outname, fn);
235
780
    p = outname + strlen(outname) - 1;
236
780
    bool isdir = (*p == '/'); /* Directories are stored with trailing slash */
237
780
    if (isdir) {
238
30
  if (junk) { /* nothing to create */
239
30
      unzCloseCurrentFile(uf);
240
30
      return UNZ_OK;
241
30
  }
242
0
  *p = '\0';
243
0
    }
244
750
    if (hasExtractLink(dest, outname)) {
245
0
  warning(_("cannot extract '%s' through a symbolic link"), fn);
246
0
  unzCloseCurrentFile(uf);
247
0
  return UNZ_UNSAFE_LINK;
248
0
    }
249
    /* make parents as required: have already checked dest exists */
250
750
    if (makeParents(dest, outname, dirs)) {
251
0
  int serrno = errno;
252
0
  unzCloseCurrentFile(uf);
253
0
  error(_("cannot create directory '%s': %s"), dirs, strerror(serrno));
254
0
    }
255
750
    if (isdir) {
256
0
  if (!R_FileExists(outname) && R_mkdir(outname)) {
257
0
      int serrno = errno;
258
0
      unzCloseCurrentFile(uf);
259
0
      error(_("cannot create directory '%s': %s"), outname,
260
0
      strerror(serrno));
261
0
  }
262
750
    } else {
263
  /* Rprintf("extracting %s\n", outname); */
264
750
  if (!overwrite && R_FileExists(outname)) {
265
0
      warning(_(" not overwriting file '%s"), outname);
266
0
      unzCloseCurrentFile(uf);
267
0
      return err;
268
0
  }
269
750
  fout = R_fopen(outname, "wb");
270
750
  int serrno = errno;
271
750
  if (!fout) {
272
52
      unzCloseCurrentFile(uf);
273
52
      error(_("cannot open file '%s': %s"), outname, strerror(serrno));
274
52
      return 3;   /* not reached */
275
52
  }
276
4.55k
  while (1) {
277
4.55k
      err = unzReadCurrentFile(uf, buf, BUF_SIZE);
278
      /* Rprintf("read %d bytes\n", err); */
279
4.55k
      if (err <= 0) break;
280
4.45k
      if (fwrite(buf, err, 1, fout) != 1) { err = -200; break; }
281
4.45k
      if (err < BUF_SIZE) { err = 0; break; }
282
4.45k
  }
283
698
  fclose(fout);
284
698
  SET_STRING_ELT(names, (*nnames)++, mkChar(outname));
285
698
    }
286
698
    unzCloseCurrentFile(uf);
287
#ifdef Win32
288
    if (setTime) setFileTime(outname, file_info.dosDate);
289
#else
290
698
    if (setTime) setFileTime(outname, file_info.tmu_date);
291
698
#endif
292
698
    return err;
293
750
}
294
295
296
static void unz_cleanup(void *data)
297
201
{
298
201
    unzClose((unzFile) data);
299
201
}
300
301
static int
302
zipunzip(const char *zipname, const char *dest, int nfiles, const char **files,
303
   SEXP *pnames, int *nnames, int overwrite, int junk, int setTime)
304
435
{
305
435
    int   i, err = UNZ_OK;
306
435
    unzFile uf;
307
435
    SEXP names = *pnames;
308
435
    RCNTXT cntxt;
309
310
435
    uf = unzOpen64(zipname);
311
435
    if (!uf) return 1;
312
    /* extract_one() raises an R error when an output file cannot be opened.
313
       => make sure we unwind at unzClose() below and don't leak with this context: */
314
335
    begincontext(&cntxt, CTXT_CCODE, R_NilValue, R_BaseEnv, R_BaseEnv,
315
335
     R_NilValue, R_NilValue);
316
335
    cntxt.cend = &unz_cleanup;
317
335
    cntxt.cenddata = uf;
318
335
    if (nfiles == 0) { /* all files */
319
335
  unz_global_info64 gi;
320
335
  unzGetGlobalInfo64(uf, &gi);
321
335
  PROTECT(names = allocVector(STRSXP, 5000));
322
1.04k
  for (i = 0; i < gi.number_entry; i++) {
323
947
      if (i > 0) if ((err = unzGoToNextFile(uf)) != UNZ_OK) break;
324
932
      if (*nnames+1 >= LENGTH(names)) {
325
0
    SEXP onames = names;
326
0
    names = allocVector(STRSXP, 2*LENGTH(names));
327
0
    UNPROTECT(1);
328
0
    PROTECT(names);
329
0
    copyVector(names, onames);
330
0
      }
331
932
      if ((err = extract_one(uf, dest, NULL, names, nnames,
332
932
           overwrite, junk, setTime)) != UNZ_OK) break;
333
#ifdef Win32
334
      R_ProcessEvents();
335
#else
336
709
      R_CheckUserInterrupt();
337
709
#endif
338
709
  }
339
335
    } else {
340
0
  PROTECT(names = allocVector(STRSXP, nfiles));
341
0
  for (i = 0; i < nfiles; i++) {
342
0
      if ((err = unzLocateFile(uf, files[i], 1)) != UNZ_OK) break;
343
0
      if ((err = extract_one(uf, dest, files[i], names, nnames,
344
0
           overwrite, junk, setTime)) != UNZ_OK) break;
345
#ifdef Win32
346
      R_ProcessEvents();
347
#else
348
0
      R_CheckUserInterrupt();
349
0
#endif
350
0
  }
351
0
    }
352
335
    *pnames = names;
353
335
    endcontext(&cntxt);
354
335
    unzClose(uf);
355
335
    UNPROTECT(1); /* names */
356
335
    return err;
357
435
}
358
359
static SEXP ziplist(const char *zipname)
360
1.37k
{
361
1.37k
    unzFile uf = unzOpen64(zipname);
362
1.37k
    if (!uf) error(_("zip file '%s' cannot be opened"), zipname);
363
    /* allocVector() below raises an R error when the entry count read
364
       from the central directory is not a usable length.
365
       => open context, also covering explicit errors here. */
366
1.37k
    RCNTXT cntxt;
367
1.37k
    begincontext(&cntxt, CTXT_CCODE, R_NilValue, R_BaseEnv, R_BaseEnv,
368
1.37k
     R_NilValue, R_NilValue);
369
1.37k
    cntxt.cend = &unz_cleanup;
370
1.37k
    cntxt.cenddata = uf;
371
372
1.37k
    unz_global_info64 gi;
373
1.37k
    gi.number_entry = 0; /* =Wall */
374
1.37k
    int err = unzGetGlobalInfo64 (uf, &gi);
375
1.37k
    if (err != UNZ_OK)
376
0
  error("error %d with zipfile in unzGetGlobalInfo", err);
377
1.37k
    int nfiles = (int) gi.number_entry;
378
    /* name, length, datetime */
379
1.37k
    SEXP ans = PROTECT(allocVector(VECSXP, 3)), names, lengths, dates;
380
1.37k
    SET_VECTOR_ELT(ans, 0, names   = allocVector(STRSXP, nfiles));
381
1.37k
    SET_VECTOR_ELT(ans, 1, lengths = allocVector(REALSXP, nfiles));
382
1.37k
    SET_VECTOR_ELT(ans, 2, dates   = allocVector(STRSXP, nfiles));
383
2.85k
    for (uLong i = 0; i < nfiles; i++) {
384
1.48k
  char filename_inzip[R_PATH_MAX], date[50];
385
1.48k
  unz_file_info64 file_info;
386
387
1.48k
  err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip,
388
1.48k
              sizeof(filename_inzip), NULL, 0, NULL, 0);
389
1.48k
  if (err != UNZ_OK ||
390
1.36k
      file_info.size_filename >= sizeof(filename_inzip))
391
120
      error("error %d with zipfile in unzGetCurrentFileInfo\n", err);
392
  /* In theory at least bit 11 of the flag tells us that the
393
     filename is in UTF-8, so FIXME */
394
1.48k
  SET_STRING_ELT(names, i, mkChar(filename_inzip));
395
1.48k
  REAL(lengths)[i] = (double) file_info.uncompressed_size;
396
1.48k
  snprintf(date, 50, "%d-%02d-%02d %02d:%02d",
397
1.48k
     file_info.tmu_date.tm_year,
398
1.48k
     file_info.tmu_date.tm_mon + 1,
399
1.48k
     file_info.tmu_date.tm_mday,
400
1.48k
     file_info.tmu_date.tm_hour,
401
1.48k
     file_info.tmu_date.tm_min);
402
1.48k
  SET_STRING_ELT(dates, i, mkChar(date));
403
404
1.48k
  if (i < nfiles - 1) {
405
595
      err = unzGoToNextFile(uf);
406
595
      if (err != UNZ_OK)
407
28
    error("error %d with zipfile in unzGoToNextFile\n", err);
408
595
  }
409
1.48k
    }
410
1.37k
    endcontext(&cntxt);
411
1.37k
    unzClose(uf);
412
413
1.37k
    UNPROTECT(1);
414
1.37k
    return ans;
415
1.37k
}
416
417
/* called from a .External in package 'utils', so managing
418
   the R_alloc stack here is prudence */
419
SEXP Runzip(SEXP args)
420
1.80k
{
421
1.80k
    SEXP  fn, ans, names = R_NilValue;
422
1.80k
    char  zipname[R_PATH_MAX], dest[R_PATH_MAX];
423
1.80k
    const char *p, **topics = NULL;
424
1.80k
    int   i, ntopics, list, overwrite, junk, setTime, rc, nnames = 0;
425
1.80k
    const void *vmax = vmaxget();
426
427
1.80k
    if (!isString(CAR(args)) || LENGTH(CAR(args)) != 1)
428
0
  error(_("invalid zip name argument"));
429
1.80k
    p = R_ExpandFileName(translateCharFP(STRING_ELT(CAR(args), 0)));
430
1.80k
    if (strlen(p) > R_PATH_MAX - 1)
431
0
  error(_("zip path is too long"));
432
1.80k
    strcpy(zipname, p);
433
1.80k
    args = CDR(args);
434
1.80k
    fn = CAR(args);
435
1.80k
    ntopics = length(fn);
436
1.80k
    if (ntopics > 0) {
437
0
  if (!isString(fn))
438
0
      error(_("invalid '%s' argument"), "files");
439
0
  topics = (const char **) R_alloc(ntopics, sizeof(char *));
440
0
  for (i = 0; i < ntopics; i++)
441
0
      topics[i] = translateCharFP(STRING_ELT(fn, i));
442
0
    }
443
1.80k
    args = CDR(args);
444
1.80k
    if (!isString(CAR(args)) || LENGTH(CAR(args)) != 1)
445
0
  error(_("invalid '%s' argument"), "exdir");
446
1.80k
    p = R_ExpandFileName(translateCharFP(STRING_ELT(CAR(args), 0)));
447
1.80k
    if (strlen(p) > R_PATH_MAX - 1)
448
0
  error(_("'exdir' is too long"));
449
1.80k
    strcpy(dest, p);
450
1.80k
    if (!R_FileExists(dest))
451
0
  error(_("'exdir' does not exist"));
452
1.80k
    args = CDR(args);
453
1.80k
    list = asLogical(CAR(args));
454
1.80k
    if (list == NA_LOGICAL)
455
0
  error(_("invalid '%s' argument"), "list");
456
1.80k
    if (list) return(ziplist(zipname));
457
435
    args = CDR(args);
458
435
    overwrite = asLogical(CAR(args));
459
435
    if (overwrite == NA_LOGICAL)
460
0
  error(_("invalid '%s' argument"), "overwrite");
461
435
    args = CDR(args);
462
435
    junk = asLogical(CAR(args));
463
435
    if (junk == NA_LOGICAL)
464
0
  error(_("invalid '%s' argument"), "junkpaths");
465
435
    args = CDR(args);
466
435
    setTime = asLogical(CAR(args));
467
435
    if (setTime == NA_LOGICAL)
468
0
  error(_("invalid '%s' argument"), "setTime");
469
470
435
    rc = zipunzip(zipname, dest, ntopics, topics, &names, &nnames,
471
435
      overwrite, junk, setTime);
472
435
    PROTECT(names);
473
435
    if (rc != UNZ_OK)
474
338
  switch(rc) {
475
0
  case UNZ_END_OF_LIST_OF_FILE:
476
0
      warning(_("requested file not found in the zip file"));
477
0
      break;
478
155
  case UNZ_BADZIPFILE:
479
155
      warning(_("zip file is corrupt"));
480
155
      break;
481
0
  case UNZ_CRCERROR:
482
0
      warning(_("CRC error in zip file"));
483
0
      break;
484
10
  case UNZ_PARAMERROR:
485
10
  case UNZ_INTERNALERROR:
486
10
      warning("internal error in 'unz' code");
487
10
      break;
488
0
  case -200:
489
0
      warning(_("write error in extracting from zip file"));
490
0
      break;
491
0
  case UNZ_UNSAFE_LINK: /* already warned, naming the member */
492
0
      break;
493
173
  default:
494
173
      warning(_("error %d in extracting from zip file"), rc);
495
338
  }
496
435
    PROTECT(ans = ScalarInteger(rc));
497
435
    PROTECT(names = lengthgets(names, nnames));
498
435
    setAttrib(ans, install("extracted"), names);
499
435
    UNPROTECT(3); /* old names, ans, names */
500
435
    vmaxset(vmax);
501
435
    return ans;
502
435
}
503
504
/* ------------------- unz connections --------------------- */
505
506
#include <Rconnections.h>
507
508
typedef struct unzconn {
509
    void *uf;
510
} *Runzconn;
511
512
static Rboolean unz_open(Rconnection con)
513
676
{
514
676
    unzFile uf;
515
676
    char path[2*R_PATH_MAX], *p;
516
676
    const char *tmp;
517
676
    int mlen;
518
519
676
    if(con->mode[0] != 'r') {
520
0
  warning(_("unz connections can only be opened for reading"));
521
0
  return FALSE;
522
0
    }
523
676
    tmp = R_ExpandFileName(con->description);
524
676
    if (strlen(tmp) > R_PATH_MAX - 1) {
525
0
  warning(_("zip path is too long"));
526
0
  return FALSE;
527
0
    }
528
676
    strcpy(path, tmp);
529
676
    p = Rf_strrchr(path, ':');
530
676
    if(!p) {
531
0
  warning(_("invalid description of 'unz' connection"));
532
0
  return FALSE;
533
0
    }
534
676
    *p = '\0';
535
676
    uf = unzOpen64(path);
536
676
    if(!uf) {
537
30
  warning(_("cannot open zip file '%s'"), path);
538
30
  return FALSE;
539
30
    }
540
646
    if (unzLocateFile(uf, p+1, 1) != UNZ_OK) {
541
  /* close first: the warning is an error under options(warn = 2) */
542
3
  unzClose(uf);
543
3
  warning(_("cannot locate file '%s' in zip file '%s'"), p+1, path);
544
3
  return FALSE;
545
3
    }
546
643
    unzOpenCurrentFile(uf);
547
643
    ((Runzconn)(con->private))->uf = uf;
548
643
    con->isopen = TRUE;
549
643
    con->canwrite = FALSE;
550
643
    con->canread = TRUE;
551
643
    mlen = (int) strlen(con->mode);
552
643
    if(mlen >= 2 && con->mode[mlen - 1] == 'b') con->text = FALSE;
553
423
    else con->text = TRUE;
554
    /* set_iconv(); not yet */
555
643
    con->save = -1000;
556
643
    return TRUE;
557
646
}
558
559
static void unz_close(Rconnection con)
560
643
{
561
643
    unzFile uf = ((Runzconn)(con->private))->uf;
562
643
    unzCloseCurrentFile(uf);
563
643
    unzClose(uf);
564
643
    con->isopen = FALSE;
565
643
}
566
567
static int unz_fgetc_internal(Rconnection con)
568
784M
{
569
784M
    unzFile uf = ((Runzconn)(con->private))->uf;
570
784M
    char buf[1];
571
784M
    int err, p;
572
573
784M
    err = unzReadCurrentFile(uf, buf, 1);
574
784M
    p = buf[0] % 256;
575
784M
    return (err < 1) ? R_EOF : p;
576
784M
}
577
578
static size_t unz_read(void *ptr, size_t size, size_t nitems,
579
           Rconnection con)
580
262
{
581
262
    unzFile uf = ((Runzconn)(con->private))->uf;
582
262
    return unzReadCurrentFile(uf, ptr, (unsigned int)(size*nitems))/size;
583
262
}
584
585
NORET static int null_vfprintf(Rconnection con, const char *format, va_list ap)
586
0
{
587
0
    error(_("printing not enabled for this connection"));
588
0
}
589
590
NORET static size_t null_write(const void *ptr, size_t size, size_t nitems,
591
       Rconnection con)
592
0
{
593
0
    error(_("write not enabled for this connection"));
594
0
}
595
596
NORET static double null_seek(Rconnection con, double where, int origin, int rw)
597
0
{
598
0
    error(_("seek not enabled for this connection"));
599
0
}
600
601
static int null_fflush(Rconnection con)
602
0
{
603
0
    return 0;
604
0
}
605
606
attribute_hidden Rconnection
607
R_newunz(const char *description, const char *const mode)
608
676
{
609
676
    Rconnection new;
610
676
    new = (Rconnection) malloc(sizeof(struct Rconn));
611
676
    if(!new) error(_("allocation of 'unz' connection failed"));
612
676
    new->class = (char *) malloc(strlen("unz") + 1);
613
676
    if(!new->class) {
614
0
  free(new);
615
0
  error(_("allocation of 'unz' connection failed"));
616
0
  /* for Solaris 12.5 */ new = NULL;
617
0
    }
618
676
    strcpy(new->class, "unz");
619
676
    new->description = (char *) malloc(strlen(description) + 1);
620
676
    if(!new->description) {
621
0
  free(new->class); free(new);
622
0
  error(_("allocation of 'unz' connection failed"));
623
0
  /* for Solaris 12.5 */ new = NULL;
624
0
    }
625
676
    init_con(new, description, CE_NATIVE, mode);
626
627
676
    new->canseek = TRUE;
628
676
    new->open = &unz_open;
629
676
    new->close = &unz_close;
630
676
    new->vfprintf = &null_vfprintf;
631
676
    new->fgetc_internal = &unz_fgetc_internal;
632
676
    new->fgetc = &dummy_fgetc;
633
676
    new->seek = &null_seek;
634
676
    new->fflush = &null_fflush;
635
676
    new->read = &unz_read;
636
676
    new->write = &null_write;
637
676
    new->private = (void *) malloc(sizeof(struct unzconn));
638
676
    if(!new->private) {
639
0
  free(new->description); free(new->class); free(new);
640
0
  error(_("allocation of 'unz' connection failed"));
641
0
  /* for Solaris 12.5 */ new = NULL;
642
0
    }
643
676
    return new;
644
676
}
645
646
       /* =================== second part ====================== */
647
648
/* From minizip contribution to zlib 1.2.3, updated for 1.2.5 */
649
/* cherry-picked fix for PR18390 */
650
651
/* unzip.c -- IO for uncompress .zip files using zlib
652
   Version 1.01e, February 12th, 2005
653
654
   Copyright (C) 1998-2005 Gilles Vollant
655
656
   Read unzip.h for more info
657
*/
658
659
#include <stdio.h>
660
#include <stdlib.h>
661
#include <string.h>
662
#include "zlib.h"
663
#include "unzip.h"
664
/*
665
#ifdef HAVE_ERRNO_H
666
#include <errno.h>
667
#else
668
extern int errno;
669
#endif
670
*/
671
672
#define local static
673
674
#ifndef CASESENSITIVITYDEFAULT_NO
675
#  if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES)
676
#    define CASESENSITIVITYDEFAULT_NO
677
#  endif
678
#endif
679
680
681
#ifndef UNZ_BUFSIZE
682
967
#define UNZ_BUFSIZE (16384)
683
#endif
684
685
#ifndef UNZ_MAXFILENAMEINZIP
686
1.28k
#define UNZ_MAXFILENAMEINZIP (256)
687
#endif
688
689
#ifndef ALLOC
690
8.63k
# define ALLOC(size) (malloc(size))
691
#endif
692
#ifndef TRYFREE
693
8.63k
# define TRYFREE(p) {if (p) free(p);}
694
#endif
695
696
1.21k
#define SIZECENTRALDIRITEM (0x2e)
697
2.61k
#define SIZEZIPLOCALHEADER (0x1e)
698
699
700
static const char unz_copyright[] =
701
   " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll";
702
703
/* unz_file_info_interntal contain internal info about a file in zipfile*/
704
typedef struct unz_file_info64_internal_s
705
{
706
    ZPOS64_T offset_curfile;/* relative offset of local header 8 bytes */
707
} unz_file_info64_internal;
708
709
710
/* file_in_zip_read_info_s contain internal information about a file in zipfile,
711
    when reading and decompress it */
712
typedef struct
713
{
714
    char  *read_buffer;         /* internal buffer for compressed data */
715
    z_stream stream;            /* zLib stream structure for inflate */
716
717
#ifdef HAVE_BZIP2
718
    bz_stream bstream;          /* bzLib stream structure for bziped */
719
#endif
720
721
    ZPOS64_T pos_in_zipfile;       /* position in byte on the zipfile, for fseek*/
722
    uLong stream_initialised;   /* flag set if stream structure is initialised*/
723
724
    ZPOS64_T offset_local_extrafield;/* offset of the local extra field */
725
    uInt  size_local_extrafield;  /* size of the local extra field */
726
    ZPOS64_T pos_local_extrafield;   /* position in the local extra field in read*/
727
    ZPOS64_T total_out_64;
728
729
    uLong crc32;                /* crc32 of all data uncompressed */
730
    uLong crc32_wait;           /* crc32 we must obtain after decompress all */
731
    ZPOS64_T rest_read_compressed; /* number of byte to be decompressed */
732
    ZPOS64_T rest_read_uncompressed;/*number of byte to be obtained after decomp*/
733
    voidpf filestream;        /* io structure of the zipfile */
734
    uLong compression_method;   /* compression method (0 == store) */
735
    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
736
    int   raw;
737
} file_in_zip64_read_info_s;
738
739
740
/* unz64_s contain internal information about the zipfile
741
*/
742
typedef struct
743
{
744
    int is64bitOpenFunction;
745
    voidpf filestream;        /* io structure of the zipfile */
746
    unz_global_info64 gi;       /* public global information */
747
    ZPOS64_T byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
748
    ZPOS64_T num_file;             /* number of the current file in the zipfile*/
749
    ZPOS64_T pos_in_central_dir;   /* pos of the current file in the central dir*/
750
    ZPOS64_T current_file_ok;      /* flag about the usability of the current file*/
751
    ZPOS64_T central_pos;          /* position of the beginning of the central dir*/
752
753
    ZPOS64_T size_central_dir;     /* size of the central directory  */
754
    ZPOS64_T offset_central_dir;   /* offset of start of central directory with
755
           respect to the starting disk number */
756
757
    unz_file_info64 cur_file_info; /* public info about the current file in zip*/
758
    unz_file_info64_internal cur_file_info_internal; /* private info about it*/
759
    file_in_zip64_read_info_s* pfile_in_zip_read; /* structure about the current
760
          file if we are decompressing it */
761
    int encrypted;
762
763
    int isZip64;
764
} unz64_s;
765
766
767
/* ===========================================================================
768
     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
769
   for end of file.
770
   IN assertion: the stream s has been successfully opened for reading.
771
*/
772
773
local int unz64local_getByte(voidpf filestream, int *pi)
774
8.06M
{
775
8.06M
    unsigned char c;
776
8.06M
    int err = (int) fread_func(filestream, &c, 1);
777
8.06M
    if (err == 1)
778
444k
    {
779
444k
  *pi = (int)c;
780
444k
  return UNZ_OK;
781
444k
    }
782
7.61M
    else
783
7.61M
    {
784
7.61M
  if (ferror_func(filestream))
785
0
      return UNZ_ERRNO;
786
7.61M
  else
787
7.61M
      return UNZ_EOF;
788
7.61M
    }
789
8.06M
}
790
791
792
/* ===========================================================================
793
   Reads a long in LSB order from the given gz_stream. Sets
794
*/
795
local int unz64local_getShort (voidpf filestream, uLong *pX)
796
3.89M
{
797
3.89M
    uLong x ;
798
3.89M
    int i = 0;
799
3.89M
    int err;
800
801
3.89M
    err = unz64local_getByte(filestream,&i);
802
3.89M
    x = (uLong)i;
803
804
3.89M
    if (err == UNZ_OK)
805
3.89M
  err = unz64local_getByte(filestream,&i);
806
3.89M
    x |= ((uLong)i)<<8;
807
808
3.89M
    if (err == UNZ_OK)
809
3.89M
  *pX = x;
810
0
    else
811
0
  *pX = 0;
812
3.89M
    return err;
813
3.89M
}
814
815
local int unz64local_getLong (voidpf filestream, uLong *pX)
816
64.5k
{
817
64.5k
    uLong x ;
818
64.5k
    int i = 0;
819
64.5k
    int err;
820
821
64.5k
    err = unz64local_getByte(filestream, &i);
822
64.5k
    x = (uLong)i;
823
824
64.5k
    if (err == UNZ_OK)
825
64.5k
  err = unz64local_getByte(filestream, &i);
826
64.5k
    x |= ((uLong)i)<<8;
827
828
64.5k
    if (err == UNZ_OK)
829
64.5k
  err = unz64local_getByte(filestream, &i);
830
64.5k
    x |= ((uLong)i)<<16;
831
832
64.5k
    if (err == UNZ_OK)
833
64.5k
  err = unz64local_getByte(filestream, &i);
834
64.5k
    x += ((uLong)i)<<24;
835
836
64.5k
    if (err == UNZ_OK)
837
64.5k
  *pX = x;
838
0
    else
839
0
  *pX = 0;
840
64.5k
    return err;
841
64.5k
}
842
843
local int unz64local_getLong64 (voidpf filestream, ZPOS64_T *pX)
844
2.99k
{
845
2.99k
    ZPOS64_T x ;
846
2.99k
    int i = 0;
847
2.99k
    int err;
848
849
2.99k
    err = unz64local_getByte(filestream,&i);
850
2.99k
    x = (ZPOS64_T)i;
851
852
2.99k
    if (err == UNZ_OK)
853
2.99k
  err = unz64local_getByte(filestream,&i);
854
2.99k
    x |= ((ZPOS64_T)i) << 8;
855
856
2.99k
    if (err == UNZ_OK)
857
2.99k
  err = unz64local_getByte(filestream,&i);
858
2.99k
    x |= ((ZPOS64_T)i) << 16;
859
860
2.99k
    if (err == UNZ_OK)
861
2.99k
  err = unz64local_getByte(filestream,&i);
862
2.99k
    x |= ((ZPOS64_T)i) << 24;
863
864
2.99k
    if (err == UNZ_OK)
865
2.99k
  err = unz64local_getByte(filestream,&i);
866
2.99k
    x |= ((ZPOS64_T)i) << 32;
867
868
2.99k
    if (err == UNZ_OK)
869
2.99k
  err = unz64local_getByte(filestream,&i);
870
2.99k
    x |= ((ZPOS64_T)i) << 40;
871
872
2.99k
    if (err == UNZ_OK)
873
2.99k
  err = unz64local_getByte(filestream,&i);
874
2.99k
    x |= ((ZPOS64_T)i) << 48;
875
876
2.99k
    if (err == UNZ_OK)
877
2.99k
  err = unz64local_getByte(filestream,&i);
878
2.99k
    x |= ((ZPOS64_T)i) << 56;
879
880
2.99k
    if (err == UNZ_OK)
881
2.99k
  *pX = x;
882
0
    else
883
0
  *pX = 0;
884
2.99k
    return err;
885
2.99k
}
886
887
/* My own strcmpi / strcasecmp */
888
local int
889
strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2)
890
0
{
891
0
    for (;;)
892
0
    {
893
0
  char c1 = *(fileName1++);
894
0
  char c2 = *(fileName2++);
895
0
  if ((c1 >= 'a') && (c1 <= 'z'))
896
0
      c1 -= 0x20;
897
0
  if ((c2 >= 'a') && (c2 <= 'z'))
898
0
      c2 -= 0x20;
899
0
  if (c1 == '\0')
900
0
      return ((c2 == '\0') ? 0 : -1);
901
0
  if (c2 == '\0')
902
0
      return 1;
903
0
  if (c1 < c2)
904
0
      return -1;
905
0
  if (c1 > c2)
906
0
      return 1;
907
0
    }
908
0
}
909
910
911
#ifdef  CASESENSITIVITYDEFAULT_NO
912
#define CASESENSITIVITYDEFAULTVALUE 2
913
#else
914
0
#define CASESENSITIVITYDEFAULTVALUE 1
915
#endif
916
917
#ifndef STRCMPCASENOSENTIVEFUNCTION
918
0
#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
919
#endif
920
921
/*
922
   Compare two filename (fileName1,fileName2).
923
   If iCaseSenisivity = 1, comparison is case sensitivity (like strcmp)
924
   If iCaseSenisivity = 2, comparison is not case sensitivity (like strcmpi
925
                or strcasecmp)
926
   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
927
  (like 1 on Unix, 2 on Windows)
928
929
*/
930
extern int ZEXPORT unzStringFileNameCompare (const char*  fileName1,
931
               const char*  fileName2,
932
               int iCaseSensitivity)
933
934
643
{
935
643
    if (iCaseSensitivity == 0)
936
0
  iCaseSensitivity = CASESENSITIVITYDEFAULTVALUE;
937
938
643
    if (iCaseSensitivity == 1)
939
643
  return strcmp(fileName1, fileName2);
940
941
0
    return STRCMPCASENOSENTIVEFUNCTION(fileName1, fileName2);
942
643
}
943
944
#ifndef BUFREADCOMMENT
945
27.7k
#define BUFREADCOMMENT (0x400)
946
#endif
947
948
/*
949
  Locate the Central directory of a zipfile (at the end, just before
950
    the global comment)
951
*/
952
local ZPOS64_T unz64local_SearchCentralDir(voidpf filestream)
953
2.07k
{
954
2.07k
    unsigned char* buf;
955
2.07k
    ZPOS64_T uSizeFile;
956
2.07k
    ZPOS64_T uBackRead;
957
2.07k
    ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
958
2.07k
    ZPOS64_T uPosFound = 0;
959
960
2.07k
    if (fseek_func(filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
961
0
  return 0;
962
963
964
2.07k
    uSizeFile = ftell_func(filestream);
965
966
2.07k
    if (uMaxBack>uSizeFile)
967
2.07k
  uMaxBack = uSizeFile;
968
969
2.07k
    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
970
2.07k
    if (buf == NULL)
971
0
  return 0;
972
973
2.07k
    uBackRead = 4;
974
4.29k
    while (uBackRead < uMaxBack)
975
4.00k
    {
976
4.00k
  size_t uReadSize;
977
4.00k
  ZPOS64_T uReadPos ;
978
4.00k
  int i;
979
4.00k
  if (uBackRead+BUFREADCOMMENT > uMaxBack)
980
1.90k
      uBackRead = uMaxBack;
981
2.10k
  else
982
2.10k
      uBackRead += BUFREADCOMMENT;
983
4.00k
  uReadPos = uSizeFile - uBackRead ;
984
985
4.00k
  uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
986
2.04k
         (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
987
4.00k
  if (fseek_func(filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
988
0
      break;
989
990
4.00k
  if (fread_func(filestream, buf, uReadSize) != uReadSize)
991
0
      break;
992
993
2.18M
  for (i = (int)uReadSize-3; (i--) > 0;)
994
2.18M
      if (((*(buf+i)) == 0x50) && ((*(buf+i+1)) == 0x4b) &&
995
22.9k
    ((*(buf+i+2)) == 0x05) && ((*(buf+i+3)) == 0x06))
996
1.78k
      {
997
1.78k
    uPosFound = uReadPos+i;
998
1.78k
    break;
999
1.78k
      }
1000
1001
4.00k
  if (uPosFound != 0)
1002
1.78k
      break;
1003
4.00k
    }
1004
2.07k
    TRYFREE(buf);
1005
2.07k
    return uPosFound;
1006
2.07k
}
1007
1008
1009
/*
1010
  Locate the Central directory 64 of a zipfile (at the end, just before
1011
    the global comment)
1012
*/
1013
local ZPOS64_T
1014
unz64local_SearchCentralDir64(voidpf filestream)
1015
2.45k
{
1016
2.45k
    unsigned char* buf;
1017
2.45k
    ZPOS64_T uSizeFile;
1018
2.45k
    ZPOS64_T uBackRead;
1019
2.45k
    ZPOS64_T uMaxBack = 0xffff; /* maximum size of global comment */
1020
2.45k
    ZPOS64_T uPosFound = 0;
1021
2.45k
    uLong uL;
1022
2.45k
    ZPOS64_T relativeOffset;
1023
1024
2.45k
    if (fseek_func(filestream, 0, ZLIB_FILEFUNC_SEEK_END) != 0)
1025
0
  return 0;
1026
1027
1028
2.45k
    uSizeFile = ftell_func(filestream);
1029
1030
2.45k
    if (uMaxBack > uSizeFile)
1031
2.45k
  uMaxBack = uSizeFile;
1032
1033
2.45k
    buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
1034
2.45k
    if (buf == NULL)
1035
0
  return 0;
1036
1037
2.45k
    uBackRead = 4;
1038
6.89k
    while (uBackRead<uMaxBack)
1039
5.10k
    {
1040
5.10k
  size_t uReadSize;
1041
5.10k
  ZPOS64_T uReadPos;
1042
5.10k
  int i;
1043
5.10k
  if (uBackRead+BUFREADCOMMENT>uMaxBack)
1044
2.37k
      uBackRead = uMaxBack;
1045
2.73k
  else
1046
2.73k
      uBackRead += BUFREADCOMMENT;
1047
5.10k
  uReadPos = uSizeFile - uBackRead ;
1048
1049
5.10k
  uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
1050
2.68k
         (BUFREADCOMMENT+4) : (uLong)(uSizeFile-uReadPos);
1051
5.10k
  if (fseek_func(filestream, uReadPos, ZLIB_FILEFUNC_SEEK_SET) != 0)
1052
0
      break;
1053
1054
5.10k
  if (fread_func(filestream, buf, uReadSize) != uReadSize)
1055
0
      break;
1056
1057
3.22M
  for (i = (int)uReadSize-3; (i--) > 0;)
1058
3.22M
      if (((*(buf+i)) == 0x50) && ((*(buf+i+1)) == 0x4b) &&
1059
31.4k
    ((*(buf+i+2)) == 0x06) && ((*(buf+i+3)) == 0x07))
1060
664
      {
1061
664
    uPosFound = uReadPos+i;
1062
664
    break;
1063
664
      }
1064
1065
5.10k
  if (uPosFound != 0)
1066
664
      break;
1067
5.10k
    }
1068
2.45k
    TRYFREE(buf);
1069
2.45k
    if (uPosFound == 0)
1070
1.78k
  return 0;
1071
1072
    /* Zip64 end of central directory locator */
1073
664
    if (fseek_func(filestream, uPosFound, ZLIB_FILEFUNC_SEEK_SET) != 0)
1074
0
  return 0;
1075
1076
    /* the signature, already checked */
1077
664
    if (unz64local_getLong(filestream, &uL) != UNZ_OK)
1078
0
  return 0;
1079
1080
    /* number of the disk with the start of the zip64 end of  central directory */
1081
664
    if (unz64local_getLong(filestream, &uL) != UNZ_OK)
1082
0
  return 0;
1083
664
    if (uL != 0)
1084
150
  return 0;
1085
1086
    /* relative offset of the zip64 end of central directory record */
1087
514
    if (unz64local_getLong64(filestream, &relativeOffset) != UNZ_OK)
1088
0
  return 0;
1089
1090
    /* total number of disks */
1091
514
    if (unz64local_getLong(filestream, &uL) != UNZ_OK)
1092
0
  return 0;
1093
514
    if (uL != 1)
1094
73
  return 0;
1095
1096
    /* Goto end of central directory record */
1097
441
    if (fseek_func(filestream, relativeOffset, ZLIB_FILEFUNC_SEEK_SET) != 0)
1098
3
  return 0;
1099
1100
     /* the signature */
1101
438
    if (unz64local_getLong(filestream, &uL) != UNZ_OK)
1102
0
  return 0;
1103
1104
438
    if (uL != 0x06064b50)
1105
61
  return 0;
1106
1107
377
    return relativeOffset;
1108
438
}
1109
1110
/*
1111
  Open a Zip file. path contain the full pathname (by example,
1112
     on a Windows NT computer "c:\\test\\zlib114.zip" or on an Unix computer
1113
     "zlib/zlib114.zip".
1114
     If the zipfile cannot be opened (file doesn't exist or in not valid), the
1115
       return value is NULL.
1116
     Else, the return value is a unzFile Handle, usable with other function
1117
       of this unzip package.
1118
*/
1119
local unzFile unzOpenInternal (const void *path, int is64bitOpenFunction)
1120
2.48k
{
1121
2.48k
    unz64_s us;
1122
2.48k
    unz64_s *s;
1123
2.48k
    ZPOS64_T central_pos;
1124
2.48k
    uLong   uL;
1125
1126
2.48k
    uLong number_disk;          /* number of the current dist, used for
1127
           spaning ZIP, unsupported, always 0*/
1128
2.48k
    uLong number_disk_with_CD;  /* number the disk with central dir, used
1129
           for spaning ZIP, unsupported, always 0*/
1130
2.48k
    ZPOS64_T number_entry_CD;      /* total number of entries in
1131
           the central dir
1132
           (same than number_entry on nospan) */
1133
1134
2.48k
    int err=UNZ_OK;
1135
1136
2.48k
    if (unz_copyright[0] != ' ')
1137
0
  return NULL;
1138
1139
2.48k
    us.is64bitOpenFunction = is64bitOpenFunction;
1140
1141
1142
1143
2.48k
    us.filestream = fopen_func(path,
1144
2.48k
             ZLIB_FILEFUNC_MODE_READ |
1145
2.48k
             ZLIB_FILEFUNC_MODE_EXISTING);
1146
2.48k
    if (us.filestream == NULL)
1147
30
  return NULL;
1148
1149
2.45k
    central_pos = unz64local_SearchCentralDir64(us.filestream);
1150
2.45k
    if (central_pos)
1151
377
    {
1152
377
  uLong uS;
1153
377
  ZPOS64_T uL64;
1154
1155
377
  us.isZip64 = 1;
1156
1157
377
  if (fseek_func(us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
1158
0
  err = UNZ_ERRNO;
1159
1160
  /* the signature, already checked */
1161
377
  if (unz64local_getLong(us.filestream, &uL) != UNZ_OK)
1162
0
      err = UNZ_ERRNO;
1163
1164
  /* size of zip64 end of central directory record */
1165
377
  if (unz64local_getLong64(us.filestream, &uL64) != UNZ_OK)
1166
0
      err = UNZ_ERRNO;
1167
1168
  /* version made by */
1169
377
  if (unz64local_getShort(us.filestream, &uS) != UNZ_OK)
1170
0
      err = UNZ_ERRNO;
1171
1172
  /* version needed to extract */
1173
377
  if (unz64local_getShort(us.filestream, &uS) != UNZ_OK)
1174
0
      err = UNZ_ERRNO;
1175
1176
  /* number of this disk */
1177
377
  if (unz64local_getLong(us.filestream, &number_disk) != UNZ_OK)
1178
0
      err = UNZ_ERRNO;
1179
1180
  /* number of the disk with the start of the central directory */
1181
377
  if (unz64local_getLong(us.filestream, &number_disk_with_CD) != UNZ_OK)
1182
0
      err = UNZ_ERRNO;
1183
1184
  /* total number of entries in the central directory on this disk */
1185
377
  if (unz64local_getLong64(us.filestream, &us.gi.number_entry) != UNZ_OK)
1186
0
      err = UNZ_ERRNO;
1187
1188
  /* total number of entries in the central directory */
1189
377
  if (unz64local_getLong64(us.filestream, &number_entry_CD) != UNZ_OK)
1190
0
      err = UNZ_ERRNO;
1191
1192
377
  if ((number_entry_CD != us.gi.number_entry) ||
1193
230
      (number_disk_with_CD != 0) ||
1194
198
      (number_disk != 0))
1195
208
      err = UNZ_BADZIPFILE;
1196
1197
  /* size of the central directory */
1198
377
  if (unz64local_getLong64(us.filestream, &us.size_central_dir) != UNZ_OK)
1199
0
      err = UNZ_ERRNO;
1200
1201
  /* offset of start of central directory with respect to the
1202
    starting disk number */
1203
377
  if (unz64local_getLong64(us.filestream, &us.offset_central_dir) != UNZ_OK)
1204
0
      err = UNZ_ERRNO;
1205
1206
377
  us.gi.size_comment = 0;
1207
377
    }
1208
2.07k
    else
1209
2.07k
    {
1210
2.07k
  central_pos = unz64local_SearchCentralDir(us.filestream);
1211
2.07k
  if (central_pos == 0)
1212
289
      err = UNZ_ERRNO;
1213
1214
2.07k
  us.isZip64 = 0;
1215
1216
2.07k
  if (fseek_func(us.filestream, central_pos, ZLIB_FILEFUNC_SEEK_SET) != 0)
1217
0
      err = UNZ_ERRNO;
1218
1219
  /* the signature, already checked */
1220
2.07k
  if (unz64local_getLong(us.filestream, &uL) != UNZ_OK)
1221
0
      err = UNZ_ERRNO;
1222
1223
  /* number of this disk */
1224
2.07k
  if (unz64local_getShort(us.filestream, &number_disk) != UNZ_OK)
1225
0
      err = UNZ_ERRNO;
1226
1227
  /* number of the disk with the start of the central directory */
1228
2.07k
  if (unz64local_getShort(us.filestream, &number_disk_with_CD) != UNZ_OK)
1229
0
      err = UNZ_ERRNO;
1230
1231
  /* total number of entries in the central dir on this disk */
1232
2.07k
  if (unz64local_getShort(us.filestream, &uL) != UNZ_OK)
1233
0
      err = UNZ_ERRNO;
1234
2.07k
  us.gi.number_entry = uL;
1235
1236
  /* total number of entries in the central dir */
1237
2.07k
  if (unz64local_getShort(us.filestream ,&uL) != UNZ_OK)
1238
0
      err = UNZ_ERRNO;
1239
2.07k
  number_entry_CD = uL;
1240
1241
2.07k
  if ((number_entry_CD != us.gi.number_entry) ||
1242
1.88k
      (number_disk_with_CD != 0) ||
1243
1.84k
      (number_disk != 0))
1244
268
      err = UNZ_BADZIPFILE;
1245
1246
  /* size of the central directory */
1247
2.07k
  if (unz64local_getLong(us.filestream, &uL) != UNZ_OK)
1248
0
      err = UNZ_ERRNO;
1249
2.07k
  us.size_central_dir = uL;
1250
1251
  /* offset of start of central directory with respect to the
1252
      starting disk number */
1253
2.07k
  if (unz64local_getLong(us.filestream, &uL) != UNZ_OK)
1254
0
      err = UNZ_ERRNO;
1255
2.07k
  us.offset_central_dir = uL;
1256
1257
  /* zipfile comment length */
1258
2.07k
  if (unz64local_getShort(us.filestream, &us.gi.size_comment) != UNZ_OK)
1259
0
      err = UNZ_ERRNO;
1260
2.07k
    }
1261
1262
2.45k
    if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
1263
345
  (err == UNZ_OK))
1264
6
  err = UNZ_BADZIPFILE;
1265
1266
2.45k
    if (err != UNZ_OK)
1267
517
    {
1268
517
  fclose_func(us.filestream);
1269
517
  return NULL;
1270
517
    }
1271
1272
1.93k
    us.byte_before_the_zipfile = central_pos -
1273
1.93k
          (us.offset_central_dir+us.size_central_dir);
1274
1.93k
    us.central_pos = central_pos;
1275
1.93k
    us.pfile_in_zip_read = NULL;
1276
1.93k
    us.encrypted = 0;
1277
1278
1279
1.93k
    s=(unz64_s*)ALLOC(sizeof(unz64_s));
1280
1.93k
    if( s != NULL)
1281
1.93k
    {
1282
1.93k
  *s = us;
1283
1.93k
  unzGoToFirstFile((unzFile)s);
1284
1.93k
    }
1285
1.93k
    return (unzFile)s;
1286
2.45k
}
1287
1288
1289
#ifdef UNUSED
1290
extern unzFile ZEXPORT unzOpen (const char *path)
1291
{
1292
    return unzOpenInternal(path, 0);
1293
}
1294
#endif
1295
1296
extern unzFile ZEXPORT unzOpen64 (const void *path)
1297
2.48k
{
1298
2.48k
    return unzOpenInternal(path, 1);
1299
2.48k
}
1300
1301
/*
1302
  Close a ZipFile opened with unzipOpen.
1303
  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
1304
    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
1305
  return UNZ_OK if there is no problem. */
1306
extern int ZEXPORT unzClose (unzFile file)
1307
1.93k
{
1308
1.93k
    unz64_s* s;
1309
1.93k
    if (file == NULL)
1310
0
  return UNZ_PARAMERROR;
1311
1.93k
    s = (unz64_s*) file;
1312
1313
1.93k
    if (s->pfile_in_zip_read != NULL)
1314
0
  unzCloseCurrentFile(file);
1315
1316
1.93k
    fclose_func(s->filestream);
1317
1.93k
    TRYFREE(s);
1318
1.93k
    return UNZ_OK;
1319
1.93k
}
1320
1321
1322
/*
1323
  Write info about the ZipFile in the *pglobal_info structure.
1324
  No preparation of the structure is needed
1325
  return UNZ_OK if there is no problem. */
1326
extern int ZEXPORT
1327
unzGetGlobalInfo64 (unzFile file, unz_global_info64* pglobal_info)
1328
1.29k
{
1329
1.29k
    unz64_s* s;
1330
1.29k
    if (file == NULL)
1331
0
  return UNZ_PARAMERROR;
1332
1.29k
    s = (unz64_s*)file;
1333
1.29k
    *pglobal_info = s->gi;
1334
1.29k
    return UNZ_OK;
1335
1.29k
}
1336
1337
/*
1338
   Translate date/time from Dos format to tm_unz (readable more easily)
1339
*/
1340
local void unz64local_DosDateToTmuDate (ZPOS64_T ulDosDate, tm_unz* ptm)
1341
6.69k
{
1342
6.69k
    ZPOS64_T uDate;
1343
6.69k
    uDate = (ZPOS64_T)(ulDosDate>>16);
1344
6.69k
    ptm->tm_mday = (uInt)(uDate&0x1f) ;
1345
6.69k
    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
1346
6.69k
    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
1347
1348
6.69k
    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
1349
6.69k
    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
1350
6.69k
    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
1351
6.69k
}
1352
1353
/*
1354
  Get Info about the current file in the zipfile, with internal only info
1355
*/
1356
local int unz64local_GetCurrentFileInfoInternal (unzFile file,
1357
              unz_file_info64 *pfile_info,
1358
              unz_file_info64_internal
1359
              *pfile_info_internal,
1360
              char *szFileName,
1361
              uLong fileNameBufferSize,
1362
              void *extraField,
1363
              uLong extraFieldBufferSize,
1364
              char *szComment,
1365
              uLong commentBufferSize)
1366
6.69k
{
1367
6.69k
    unz64_s* s;
1368
6.69k
    unz_file_info64 file_info;
1369
6.69k
    unz_file_info64_internal file_info_internal;
1370
6.69k
    int err = UNZ_OK;
1371
6.69k
    uLong uMagic;
1372
6.69k
    long lSeek = 0;
1373
6.69k
    uLong uL;
1374
1375
6.69k
    if (file == NULL)
1376
0
  return UNZ_PARAMERROR;
1377
6.69k
    s = (unz64_s*)file;
1378
6.69k
    if (fseek_func(s->filestream,
1379
6.69k
       s->pos_in_central_dir+s->byte_before_the_zipfile,
1380
6.69k
       ZLIB_FILEFUNC_SEEK_SET) != 0)
1381
1
  err = UNZ_ERRNO;
1382
1383
1384
    /* we check the magic */
1385
6.69k
    if (err == UNZ_OK)
1386
6.69k
    {
1387
6.69k
  if (unz64local_getLong(s->filestream,&uMagic) != UNZ_OK)
1388
0
      err = UNZ_ERRNO;
1389
6.69k
  else if (uMagic != 0x02014b50)
1390
260
      err = UNZ_BADZIPFILE;
1391
6.69k
    }
1392
1393
6.69k
    if (unz64local_getShort(s->filestream,&file_info.version) != UNZ_OK)
1394
0
  err = UNZ_ERRNO;
1395
1396
6.69k
    if (unz64local_getShort(s->filestream,&file_info.version_needed) != UNZ_OK)
1397
0
  err = UNZ_ERRNO;
1398
1399
6.69k
    if (unz64local_getShort(s->filestream,&file_info.flag) != UNZ_OK)
1400
0
  err = UNZ_ERRNO;
1401
1402
6.69k
    if (unz64local_getShort(s->filestream,&file_info.compression_method) != UNZ_OK)
1403
0
  err = UNZ_ERRNO;
1404
1405
6.69k
    if (unz64local_getLong(s->filestream,&file_info.dosDate) != UNZ_OK)
1406
0
  err = UNZ_ERRNO;
1407
1408
6.69k
    unz64local_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
1409
1410
6.69k
    if (unz64local_getLong(s->filestream,&file_info.crc) != UNZ_OK)
1411
0
  err = UNZ_ERRNO;
1412
1413
6.69k
    if (unz64local_getLong(s->filestream,&uL) != UNZ_OK)
1414
0
  err = UNZ_ERRNO;
1415
6.69k
    file_info.compressed_size = uL;
1416
1417
6.69k
    if (unz64local_getLong(s->filestream,&uL) != UNZ_OK)
1418
0
  err = UNZ_ERRNO;
1419
6.69k
    file_info.uncompressed_size = uL;
1420
1421
6.69k
    if (unz64local_getShort(s->filestream,&file_info.size_filename) != UNZ_OK)
1422
0
  err = UNZ_ERRNO;
1423
1424
6.69k
    if (unz64local_getShort(s->filestream,&file_info.size_file_extra) != UNZ_OK)
1425
0
  err = UNZ_ERRNO;
1426
1427
6.69k
    if (unz64local_getShort(s->filestream,&file_info.size_file_comment) != UNZ_OK)
1428
0
  err = UNZ_ERRNO;
1429
1430
6.69k
    if (unz64local_getShort(s->filestream,&file_info.disk_num_start) != UNZ_OK)
1431
0
  err = UNZ_ERRNO;
1432
1433
6.69k
    if (unz64local_getShort(s->filestream,&file_info.internal_fa) != UNZ_OK)
1434
0
  err = UNZ_ERRNO;
1435
1436
6.69k
    if (unz64local_getLong(s->filestream,&file_info.external_fa) != UNZ_OK)
1437
0
  err = UNZ_ERRNO;
1438
1439
    // relative offset of local header
1440
6.69k
    if (unz64local_getLong(s->filestream,&uL) != UNZ_OK)
1441
0
  err = UNZ_ERRNO;
1442
6.69k
    file_info_internal.offset_curfile = uL;
1443
1444
6.69k
    lSeek += file_info.size_filename;
1445
6.69k
    if ((err == UNZ_OK) && (szFileName != NULL))
1446
2.82k
    {
1447
2.82k
  size_t uSizeRead ;
1448
2.82k
  if (file_info.size_filename<fileNameBufferSize)
1449
2.78k
  {
1450
2.78k
      *(szFileName+file_info.size_filename)='\0';
1451
2.78k
      uSizeRead = file_info.size_filename;
1452
2.78k
  }
1453
45
  else
1454
45
      uSizeRead = fileNameBufferSize;
1455
1456
2.82k
  if ((file_info.size_filename>0) && (fileNameBufferSize>0))
1457
2.71k
      if (fread_func(s->filestream, szFileName, uSizeRead) != uSizeRead)
1458
38
    err = UNZ_ERRNO;
1459
2.82k
  lSeek -= uSizeRead;
1460
2.82k
    }
1461
1462
    // Read extrafield
1463
6.69k
    if ((err == UNZ_OK) && (extraField != NULL))
1464
0
    {
1465
0
  size_t uSizeRead;
1466
0
  if (file_info.size_file_extra < extraFieldBufferSize)
1467
0
      uSizeRead = file_info.size_file_extra;
1468
0
  else
1469
0
      uSizeRead = extraFieldBufferSize;
1470
1471
0
  if (lSeek != 0)
1472
0
  {
1473
0
      if (fseek_func(s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
1474
0
    lSeek = 0;
1475
0
      else
1476
0
    err = UNZ_ERRNO;
1477
0
  }
1478
1479
0
  if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
1480
0
      if (fread_func(s->filestream, extraField, (size_t) uSizeRead)
1481
0
    != uSizeRead) err = UNZ_ERRNO;
1482
1483
0
  lSeek += file_info.size_file_extra - (uLong)uSizeRead;
1484
0
    }
1485
6.69k
    else
1486
6.69k
  lSeek += file_info.size_file_extra;
1487
1488
1489
6.69k
    if ((err == UNZ_OK) && (file_info.size_file_extra != 0))
1490
1.75k
    {
1491
1.75k
  uLong acc = 0;
1492
1493
  // since lSeek now points to after the extra field we need to move back
1494
1.75k
  lSeek -= file_info.size_file_extra;
1495
1496
1.75k
  if (lSeek != 0)
1497
924
  {
1498
924
      if (fseek_func(s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) == 0)
1499
924
    lSeek = 0;
1500
0
      else
1501
0
    err = UNZ_ERRNO;
1502
924
  }
1503
1504
1.90M
  while(acc < file_info.size_file_extra)
1505
1.90M
  {
1506
1.90M
      uLong headerId;
1507
1.90M
      uLong dataSize;
1508
1509
1.90M
      if (unz64local_getShort(s->filestream,&headerId) != UNZ_OK)
1510
0
    err = UNZ_ERRNO;
1511
1512
1.90M
      if (unz64local_getShort(s->filestream,&dataSize) != UNZ_OK)
1513
0
    err = UNZ_ERRNO;
1514
1515
      /* ZIP64 extra fields */
1516
1.90M
      if (headerId == 0x0001)
1517
1.46k
      {
1518
1.46k
    uLong uL;
1519
1520
1.46k
    if(file_info.uncompressed_size == MAXU32)
1521
252
    {
1522
252
        if (unz64local_getLong64(s->filestream,
1523
252
               &file_info.uncompressed_size) != UNZ_OK)
1524
0
      err = UNZ_ERRNO;
1525
252
    }
1526
1527
1.46k
    if(file_info.compressed_size == MAXU32)
1528
174
    {
1529
174
        if (unz64local_getLong64(s->filestream,
1530
174
               &file_info.compressed_size) != UNZ_OK)
1531
0
      err = UNZ_ERRNO;
1532
174
    }
1533
1534
1.46k
    if(file_info_internal.offset_curfile == MAXU32)
1535
174
    {
1536
        /* Relative Header offset */
1537
174
        if (unz64local_getLong64(s->filestream,
1538
174
               &file_info_internal.offset_curfile) != UNZ_OK)
1539
0
      err = UNZ_ERRNO;
1540
174
    }
1541
1542
1.46k
    if(file_info.disk_num_start == 0xffff)
1543
        /* minizip checks against MAXU32, but the specification
1544
           says 0xffff, see also PR18390 */
1545
336
    {
1546
        /* Disk Start Number */
1547
336
        if (unz64local_getLong(s->filestream,&uL) != UNZ_OK)
1548
0
      err = UNZ_ERRNO;
1549
336
    }
1550
1551
1.46k
      }
1552
1.90M
      else
1553
1.90M
      {
1554
1.90M
    if (fseek_func(s->filestream, dataSize, ZLIB_FILEFUNC_SEEK_CUR) != 0)
1555
0
        err = UNZ_ERRNO;
1556
1.90M
      }
1557
1558
1.90M
      acc += 2 + 2 + dataSize;
1559
1.90M
  }
1560
1.75k
    }
1561
1562
6.69k
    if ((err == UNZ_OK) && (szComment != NULL))
1563
0
    {
1564
0
  size_t uSizeRead ;
1565
0
  if (file_info.size_file_comment<commentBufferSize)
1566
0
  {
1567
0
      *(szComment+file_info.size_file_comment) = '\0';
1568
0
      uSizeRead = file_info.size_file_comment;
1569
0
  }
1570
0
  else
1571
0
      uSizeRead = commentBufferSize;
1572
1573
0
  if (lSeek != 0)
1574
0
  {
1575
0
      if (fseek_func(s->filestream, lSeek, ZLIB_FILEFUNC_SEEK_CUR) ==  0)
1576
0
    lSeek = 0;
1577
0
      else
1578
0
    err = UNZ_ERRNO;
1579
0
  }
1580
1581
0
  if ((file_info.size_file_comment>0) && (commentBufferSize>0))
1582
0
      if (fread_func(s->filestream,szComment,uSizeRead) != uSizeRead)
1583
0
    err = UNZ_ERRNO;
1584
0
  lSeek += file_info.size_file_comment - uSizeRead;
1585
0
    }
1586
6.69k
    else
1587
6.69k
  lSeek += file_info.size_file_comment;
1588
1589
1590
6.69k
    if ((err == UNZ_OK) && (pfile_info != NULL))
1591
5.75k
  *pfile_info = file_info;
1592
1593
6.69k
    if ((err == UNZ_OK) && (pfile_info_internal != NULL))
1594
3.61k
  *pfile_info_internal = file_info_internal;
1595
1596
6.69k
    return err;
1597
6.69k
}
1598
1599
1600
1601
/*
1602
  Write info about the ZipFile in the *pglobal_info structure.
1603
  No preparation of the structure is needed
1604
  return UNZ_OK if there is no problem.
1605
*/
1606
extern int ZEXPORT
1607
unzGetCurrentFileInfo64 (unzFile file,
1608
       unz_file_info64 * pfile_info,
1609
       char * szFileName, uLong fileNameBufferSize,
1610
       void *extraField, uLong extraFieldBufferSize,
1611
       char* szComment,  uLong commentBufferSize)
1612
2.90k
{
1613
2.90k
    return unz64local_GetCurrentFileInfoInternal(file,pfile_info,NULL,
1614
2.90k
            szFileName,fileNameBufferSize,
1615
2.90k
            extraField,extraFieldBufferSize,
1616
2.90k
            szComment,commentBufferSize);
1617
2.90k
}
1618
1619
/*
1620
  Set the current file of the zipfile to the first file.
1621
  return UNZ_OK if there is no problem
1622
*/
1623
extern int ZEXPORT unzGoToFirstFile (unzFile file)
1624
2.57k
{
1625
2.57k
    int err = UNZ_OK;
1626
2.57k
    unz64_s* s;
1627
2.57k
    if (file == NULL)
1628
0
  return UNZ_PARAMERROR;
1629
2.57k
    s = (unz64_s*)file;
1630
2.57k
    s->pos_in_central_dir = s->offset_central_dir;
1631
2.57k
    s->num_file = 0;
1632
2.57k
    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1633
2.57k
            &s->cur_file_info_internal,
1634
2.57k
            NULL,0,NULL,0,NULL,0);
1635
2.57k
    s->current_file_ok = (err == UNZ_OK);
1636
2.57k
    return err;
1637
2.57k
}
1638
1639
/*
1640
  Set the current file of the zipfile to the next file.
1641
  return UNZ_OK if there is no problem
1642
  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
1643
*/
1644
extern int ZEXPORT unzGoToNextFile (unzFile  file)
1645
1.21k
{
1646
1.21k
    unz64_s* s;
1647
1.21k
    int err;
1648
1649
1.21k
    if (file == NULL)
1650
0
  return UNZ_PARAMERROR;
1651
1.21k
    s = (unz64_s*)file;
1652
1.21k
    if (!s->current_file_ok)
1653
0
  return UNZ_END_OF_LIST_OF_FILE;
1654
1.21k
    if (s->gi.number_entry != 0xffff)    /* 2^16 files overflow hack */
1655
1.19k
      if (s->num_file+1 == s->gi.number_entry)
1656
0
  return UNZ_END_OF_LIST_OF_FILE;
1657
1658
1.21k
    s->pos_in_central_dir +=
1659
1.21k
  SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
1660
1.21k
  s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
1661
1.21k
    s->num_file++;
1662
1.21k
    err = unz64local_GetCurrentFileInfoInternal(file,&s->cur_file_info,
1663
1.21k
                 &s->cur_file_info_internal,
1664
1.21k
                 NULL,0,NULL,0,NULL,0);
1665
1.21k
    s->current_file_ok = (err == UNZ_OK);
1666
1.21k
    return err;
1667
1.21k
}
1668
1669
1670
/*
1671
  Try locate the file szFileName in the zipfile.
1672
  For the iCaseSensitivity signification, see unzipStringFileNameCompare
1673
1674
  return value :
1675
  UNZ_OK if the file is found. It becomes the current file.
1676
  UNZ_END_OF_LIST_OF_FILE if the file is not found
1677
*/
1678
extern int ZEXPORT unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
1679
646
{
1680
646
    unz64_s* s;
1681
646
    int err;
1682
1683
    /* We remember the 'current' position in the file so that we can jump
1684
     * back there if we fail.
1685
     */
1686
646
    unz_file_info64 cur_file_infoSaved;
1687
646
    unz_file_info64_internal cur_file_info_internalSaved;
1688
646
    ZPOS64_T num_fileSaved;
1689
646
    ZPOS64_T pos_in_central_dirSaved;
1690
1691
1692
646
    if (file == NULL)
1693
0
  return UNZ_PARAMERROR;
1694
1695
646
    if (strlen(szFileName) >= UNZ_MAXFILENAMEINZIP)
1696
3
  return UNZ_PARAMERROR;
1697
1698
643
    s = (unz64_s*)file;
1699
643
    if (!s->current_file_ok)
1700
0
  return UNZ_END_OF_LIST_OF_FILE;
1701
1702
    /* Save the current state */
1703
643
    num_fileSaved = s->num_file;
1704
643
    pos_in_central_dirSaved = s->pos_in_central_dir;
1705
643
    cur_file_infoSaved = s->cur_file_info;
1706
643
    cur_file_info_internalSaved = s->cur_file_info_internal;
1707
1708
643
    err = unzGoToFirstFile(file);
1709
1710
643
    while (err == UNZ_OK)
1711
643
    {
1712
643
  char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
1713
643
  szCurrentFileName[UNZ_MAXFILENAMEINZIP] = '\0';
1714
643
  err = unzGetCurrentFileInfo64(file, NULL,
1715
643
              szCurrentFileName,
1716
643
              sizeof(szCurrentFileName)-1,
1717
643
              NULL, 0, NULL, 0);
1718
643
  if (err == UNZ_OK)
1719
643
  {
1720
643
      if (unzStringFileNameCompare(szCurrentFileName,
1721
643
           szFileName,iCaseSensitivity) == 0)
1722
643
    return UNZ_OK;
1723
0
      err = unzGoToNextFile(file);
1724
0
  }
1725
643
    }
1726
1727
    /* We failed, so restore the state of the 'current file' to where we
1728
     * were.
1729
     */
1730
0
    s->num_file = num_fileSaved ;
1731
0
    s->pos_in_central_dir = pos_in_central_dirSaved ;
1732
0
    s->cur_file_info = cur_file_infoSaved;
1733
0
    s->cur_file_info_internal = cur_file_info_internalSaved;
1734
0
    return err;
1735
643
}
1736
1737
1738
/*
1739
///////////////////////////////////////////
1740
// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net)
1741
// I need random access
1742
//
1743
// Further optimization could be realized by adding an ability
1744
// to cache the directory in memory. The goal being a single
1745
// comprehensive file read to put the file I need in a memory.
1746
*/
1747
1748
1749
/*
1750
// Unzip Helper Functions - should be here?
1751
///////////////////////////////////////////
1752
*/
1753
1754
/*
1755
  Read the local header of the current zipfile
1756
  Check the coherency of the local header and info in the end of central
1757
  directory about this file
1758
  store in *piSizeVar the size of extra info in local header
1759
  (filename and size of extra field data)
1760
*/
1761
local int
1762
unz64local_CheckCurrentFileCoherencyHeader (unz64_s* s, uInt* piSizeVar,
1763
              ZPOS64_T * poffset_local_extrafield,
1764
              uInt  * psize_local_extrafield)
1765
1.56k
{
1766
1.56k
    uLong uMagic,uData,uFlags;
1767
1.56k
    uLong size_filename;
1768
1.56k
    uLong size_extra_field;
1769
1.56k
    int err = UNZ_OK;
1770
1771
1.56k
    *piSizeVar = 0;
1772
1.56k
    *poffset_local_extrafield = 0;
1773
1.56k
    *psize_local_extrafield = 0;
1774
1775
1.56k
    if (fseek_func(s->filestream,s->cur_file_info_internal.offset_curfile +
1776
1.56k
       s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET) != 0)
1777
36
  return UNZ_ERRNO;
1778
1779
1780
1.52k
    if (err == UNZ_OK)
1781
1.52k
    {
1782
1.52k
  if (unz64local_getLong(s->filestream,&uMagic) != UNZ_OK)
1783
0
      err = UNZ_ERRNO;
1784
1.52k
  else if (uMagic!=0x04034b50)
1785
296
      err = UNZ_BADZIPFILE;
1786
1.52k
    }
1787
1788
1.52k
    if (unz64local_getShort(s->filestream,&uData) != UNZ_OK)
1789
0
  err = UNZ_ERRNO;
1790
/*
1791
    else if ((err == UNZ_OK) && (uData!=s->cur_file_info.wVersion))
1792
  err=UNZ_BADZIPFILE;
1793
*/
1794
1.52k
    if (unz64local_getShort(s->filestream,&uFlags)  !=  UNZ_OK)
1795
0
  err = UNZ_ERRNO;
1796
1797
1.52k
    if (unz64local_getShort(s->filestream,&uData) != UNZ_OK)
1798
0
  err = UNZ_ERRNO;
1799
1.52k
    else if ((err == UNZ_OK) && (uData != s->cur_file_info.compression_method))
1800
23
  err = UNZ_BADZIPFILE;
1801
1802
1.52k
    if ((err == UNZ_OK) && (s->cur_file_info.compression_method != 0) &&
1803
/* #ifdef HAVE_BZIP2 */
1804
824
       (s->cur_file_info.compression_method != Z_BZIP2ED) &&
1805
/* #endif */
1806
698
       (s->cur_file_info.compression_method != Z_DEFLATED))
1807
2
  err = UNZ_BADZIPFILE;
1808
1809
1.52k
    if (unz64local_getLong(s->filestream,&uData) != UNZ_OK) /* date/time */
1810
0
  err = UNZ_ERRNO;
1811
1812
1.52k
    if (unz64local_getLong(s->filestream,&uData) != UNZ_OK) /* crc */
1813
0
  err = UNZ_ERRNO;
1814
1.52k
    else if ((err == UNZ_OK) && (uData != s->cur_file_info.crc) &&
1815
317
       ((uFlags & 8) == 0))
1816
22
  err = UNZ_BADZIPFILE;
1817
1818
1.52k
    if (unz64local_getLong(s->filestream,&uData) != UNZ_OK) /* size compr */
1819
0
  err = UNZ_ERRNO;
1820
1.52k
    else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1821
1.10k
       (uData != s->cur_file_info.compressed_size) && ((uFlags & 8) == 0))
1822
15
  err = UNZ_BADZIPFILE;
1823
1824
1.52k
    if (unz64local_getLong(s->filestream,&uData) != UNZ_OK) /* size uncompr */
1825
0
  err = UNZ_ERRNO;
1826
1.52k
    else if (uData != 0xFFFFFFFF && (err == UNZ_OK) &&
1827
1.09k
       (uData != s->cur_file_info.uncompressed_size) && ((uFlags & 8) == 0))
1828
35
  err = UNZ_BADZIPFILE;
1829
1830
1.52k
    if (unz64local_getShort(s->filestream,&size_filename) != UNZ_OK)
1831
0
  err = UNZ_ERRNO;
1832
1.52k
    else if ((err == UNZ_OK) && (size_filename != s->cur_file_info.size_filename))
1833
53
  err = UNZ_BADZIPFILE;
1834
1835
1.52k
    *piSizeVar += (uInt)size_filename;
1836
1837
1.52k
    if (unz64local_getShort(s->filestream,&size_extra_field) != UNZ_OK)
1838
0
  err=UNZ_ERRNO;
1839
1.52k
    *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
1840
1.52k
            SIZEZIPLOCALHEADER + size_filename;
1841
1.52k
    *psize_local_extrafield = (uInt)size_extra_field;
1842
1843
1.52k
    *piSizeVar += (uInt)size_extra_field;
1844
1845
1.52k
    return err;
1846
1.56k
}
1847
1848
/*
1849
  Open for reading data the current file in the zipfile.
1850
  If there is no error and the file is opened, the return value is UNZ_OK.
1851
*/
1852
static int unzOpenCurrentFile3 (unzFile file, int* method,
1853
        int* level, int raw, const char* password)
1854
1.57k
{
1855
1.57k
    int err = UNZ_OK;
1856
1.57k
    uInt iSizeVar;
1857
1.57k
    unz64_s* s;
1858
1.57k
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
1859
1.57k
    ZPOS64_T offset_local_extrafield;  /* offset of the local extra field */
1860
1.57k
    uInt  size_local_extrafield;    /* size of the local extra field */
1861
1.57k
    if (password != NULL) return UNZ_PARAMERROR;
1862
1863
1.57k
    if (file == NULL)
1864
0
  return UNZ_PARAMERROR;
1865
1.57k
    s = (unz64_s*)file;
1866
1.57k
    if (!s->current_file_ok)
1867
10
  return UNZ_PARAMERROR;
1868
1869
1.56k
    if (s->pfile_in_zip_read != NULL)
1870
0
  unzCloseCurrentFile(file);
1871
1872
1.56k
    if (unz64local_CheckCurrentFileCoherencyHeader(s, &iSizeVar,
1873
1.56k
               &offset_local_extrafield,&size_local_extrafield) != UNZ_OK)
1874
482
  return UNZ_BADZIPFILE;
1875
1876
1.08k
    pfile_in_zip_read_info =
1877
1.08k
  (file_in_zip64_read_info_s*)ALLOC(sizeof(file_in_zip64_read_info_s));
1878
1.08k
    if (pfile_in_zip_read_info == NULL)
1879
0
  return UNZ_INTERNALERROR;
1880
1881
1.08k
    pfile_in_zip_read_info->read_buffer = (char*)ALLOC(UNZ_BUFSIZE);
1882
1.08k
    pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
1883
1.08k
    pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
1884
1.08k
    pfile_in_zip_read_info->pos_local_extrafield = 0;
1885
1.08k
    pfile_in_zip_read_info->raw = raw;
1886
1887
1.08k
    if (pfile_in_zip_read_info->read_buffer == NULL)
1888
0
    {
1889
0
  TRYFREE(pfile_in_zip_read_info);
1890
0
  return UNZ_INTERNALERROR;
1891
0
    }
1892
1893
1.08k
    pfile_in_zip_read_info->stream_initialised = 0;
1894
1895
1.08k
    if (method != NULL)
1896
0
  *method = (int)s->cur_file_info.compression_method;
1897
1898
1.08k
    if (level != NULL)
1899
0
    {
1900
0
  *level = 6;
1901
0
  switch (s->cur_file_info.flag & 0x06)
1902
0
  {
1903
0
    case 6 : *level = 1; break;
1904
0
    case 4 : *level = 2; break;
1905
0
    case 2 : *level = 9; break;
1906
0
  }
1907
0
    }
1908
1909
1.08k
    if ((s->cur_file_info.compression_method != 0) &&
1910
/* #ifdef HAVE_BZIP2 */
1911
785
  (s->cur_file_info.compression_method != Z_BZIP2ED) &&
1912
/* #endif */
1913
661
  (s->cur_file_info.compression_method != Z_DEFLATED))
1914
1915
0
  err=UNZ_BADZIPFILE;
1916
1917
1.08k
    pfile_in_zip_read_info->crc32_wait = s->cur_file_info.crc;
1918
1.08k
    pfile_in_zip_read_info->crc32 = 0;
1919
1.08k
    pfile_in_zip_read_info->total_out_64 = 0;
1920
1.08k
    pfile_in_zip_read_info->compression_method =
1921
1.08k
  s->cur_file_info.compression_method;
1922
1.08k
    pfile_in_zip_read_info->filestream = s->filestream;
1923
1.08k
    pfile_in_zip_read_info->byte_before_the_zipfile =
1924
1.08k
  s->byte_before_the_zipfile;
1925
1926
1.08k
    pfile_in_zip_read_info->stream.total_out = 0;
1927
1928
1.08k
    if ((s->cur_file_info.compression_method == Z_BZIP2ED) && (!raw))
1929
124
    {
1930
124
#ifdef HAVE_BZIP2
1931
124
      pfile_in_zip_read_info->bstream.bzalloc = (void *(*) (void *, int, int))0;
1932
124
      pfile_in_zip_read_info->bstream.bzfree = (free_func)0;
1933
124
      pfile_in_zip_read_info->bstream.opaque = (voidpf)0;
1934
124
      pfile_in_zip_read_info->bstream.state = (voidpf)0;
1935
1936
124
      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1937
124
      pfile_in_zip_read_info->stream.zfree = (free_func)0;
1938
124
      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1939
124
      pfile_in_zip_read_info->stream.next_in = (voidpf)0;
1940
124
      pfile_in_zip_read_info->stream.avail_in = 0;
1941
1942
124
      err = BZ2_bzDecompressInit(&pfile_in_zip_read_info->bstream, 0, 0);
1943
124
      if (err == Z_OK)
1944
124
  pfile_in_zip_read_info->stream_initialised = Z_BZIP2ED;
1945
0
      else
1946
0
      {
1947
0
  TRYFREE(pfile_in_zip_read_info);
1948
0
  return err;
1949
0
      }
1950
#else
1951
      pfile_in_zip_read_info->raw = 1;
1952
#endif
1953
124
    }
1954
959
    else if ((s->cur_file_info.compression_method == Z_DEFLATED) && (!raw))
1955
661
    {
1956
661
      pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
1957
661
      pfile_in_zip_read_info->stream.zfree = (free_func)0;
1958
661
      pfile_in_zip_read_info->stream.opaque = (voidpf)0;
1959
661
      pfile_in_zip_read_info->stream.next_in = 0;
1960
661
      pfile_in_zip_read_info->stream.avail_in = 0;
1961
1962
661
      err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
1963
661
      if (err == Z_OK)
1964
661
  pfile_in_zip_read_info->stream_initialised = Z_DEFLATED;
1965
0
      else
1966
0
      {
1967
0
  TRYFREE(pfile_in_zip_read_info);
1968
0
  return err;
1969
0
      }
1970
  /* windowBits is passed < 0 to tell that there is no zlib header.
1971
   * Note that in this case inflate *requires* an extra "dummy" byte
1972
   * after the compressed stream in order to complete decompression and
1973
   * return Z_STREAM_END.
1974
   * In unzip, i don't wait absolutely Z_STREAM_END because I known the
1975
   * size of both compressed and uncompressed data
1976
   */
1977
661
    }
1978
1.08k
    pfile_in_zip_read_info->rest_read_compressed =
1979
1.08k
      s->cur_file_info.compressed_size ;
1980
1.08k
    pfile_in_zip_read_info->rest_read_uncompressed =
1981
1.08k
      s->cur_file_info.uncompressed_size ;
1982
1983
1984
1.08k
    pfile_in_zip_read_info->pos_in_zipfile =
1985
1.08k
      s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
1986
1.08k
        iSizeVar;
1987
1988
1.08k
    pfile_in_zip_read_info->stream.avail_in = (uInt)0;
1989
1990
1.08k
    s->pfile_in_zip_read = pfile_in_zip_read_info;
1991
1.08k
    s->encrypted = 0;
1992
1993
1.08k
    return UNZ_OK;
1994
1.08k
}
1995
1996
static int unzOpenCurrentFile (unzFile file)
1997
1.57k
{
1998
1.57k
    return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL);
1999
1.57k
}
2000
2001
/*
2002
  Read bytes from the current file.
2003
  buf contain buffer where data must be copied
2004
  len the size of buf.
2005
2006
  return the number of byte copied if somes bytes are copied
2007
  return 0 if the end of file was reached
2008
  return <0 with error code if there is an error
2009
    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
2010
*/
2011
static int unzReadCurrentFile  (unzFile file, voidp buf, unsigned len)
2012
784M
{
2013
784M
    int err = UNZ_OK;
2014
784M
    uInt iRead = 0;
2015
784M
    unz64_s* s;
2016
784M
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
2017
784M
    if (file == NULL)
2018
0
  return UNZ_PARAMERROR;
2019
784M
    s = (unz64_s*)file;
2020
784M
    pfile_in_zip_read_info = s->pfile_in_zip_read;
2021
2022
784M
    if (pfile_in_zip_read_info == NULL)
2023
342
  return UNZ_PARAMERROR;
2024
2025
2026
784M
    if (pfile_in_zip_read_info->read_buffer == NULL)
2027
0
  return UNZ_END_OF_LIST_OF_FILE;
2028
784M
    if (len == 0)
2029
0
  return 0;
2030
2031
784M
    pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
2032
2033
784M
    pfile_in_zip_read_info->stream.avail_out = (uInt)len;
2034
2035
784M
    if ((len>pfile_in_zip_read_info->rest_read_uncompressed) &&
2036
677
  (!(pfile_in_zip_read_info->raw)))
2037
677
  pfile_in_zip_read_info->stream.avail_out =
2038
677
      (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
2039
2040
784M
    if ((len>pfile_in_zip_read_info->rest_read_compressed+
2041
784M
     pfile_in_zip_read_info->stream.avail_in) &&
2042
5.92k
   (pfile_in_zip_read_info->raw))
2043
0
  pfile_in_zip_read_info->stream.avail_out =
2044
0
      (uInt)pfile_in_zip_read_info->rest_read_compressed+
2045
0
      pfile_in_zip_read_info->stream.avail_in;
2046
2047
1.56G
    while (pfile_in_zip_read_info->stream.avail_out>0)
2048
784M
    {
2049
784M
  if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
2050
2.37k
      (pfile_in_zip_read_info->rest_read_compressed>0))
2051
967
  {
2052
967
      size_t uReadThis = UNZ_BUFSIZE;
2053
967
      if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
2054
845
    uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
2055
967
      if (uReadThis == 0)
2056
0
    return UNZ_EOF;
2057
967
      if (fseek_func(pfile_in_zip_read_info->filestream,
2058
967
         pfile_in_zip_read_info->pos_in_zipfile +
2059
967
         pfile_in_zip_read_info->byte_before_the_zipfile,
2060
967
         ZLIB_FILEFUNC_SEEK_SET) != 0)
2061
0
    return UNZ_ERRNO;
2062
967
      if (fread_func(pfile_in_zip_read_info->filestream,
2063
967
         pfile_in_zip_read_info->read_buffer,
2064
967
         uReadThis) != uReadThis)
2065
134
    return UNZ_ERRNO;
2066
2067
833
      pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
2068
2069
833
      pfile_in_zip_read_info->rest_read_compressed -= uReadThis;
2070
2071
833
      pfile_in_zip_read_info->stream.next_in =
2072
833
    (Bytef*)pfile_in_zip_read_info->read_buffer;
2073
833
      pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
2074
833
  }
2075
2076
784M
  if ((pfile_in_zip_read_info->compression_method == 0) ||
2077
784M
      (pfile_in_zip_read_info->raw))
2078
141k
  {
2079
141k
      uInt uDoCopy,i ;
2080
2081
141k
      if ((pfile_in_zip_read_info->stream.avail_in == 0) &&
2082
61
    (pfile_in_zip_read_info->rest_read_compressed == 0))
2083
61
    return (iRead == 0) ? UNZ_EOF : iRead;
2084
2085
141k
      if (pfile_in_zip_read_info->stream.avail_out <
2086
141k
          pfile_in_zip_read_info->stream.avail_in)
2087
141k
    uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
2088
88
      else
2089
88
    uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
2090
2091
448k
      for (i = 0; i < uDoCopy; i++)
2092
307k
    *(pfile_in_zip_read_info->stream.next_out+i) =
2093
307k
      *(pfile_in_zip_read_info->stream.next_in+i);
2094
2095
141k
      pfile_in_zip_read_info->total_out_64 =
2096
141k
    pfile_in_zip_read_info->total_out_64 + uDoCopy;
2097
2098
141k
      pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
2099
141k
        pfile_in_zip_read_info->stream.next_out,
2100
141k
        uDoCopy);
2101
141k
      pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
2102
141k
      pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
2103
141k
      pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
2104
141k
      pfile_in_zip_read_info->stream.next_out += uDoCopy;
2105
141k
      pfile_in_zip_read_info->stream.next_in += uDoCopy;
2106
141k
      pfile_in_zip_read_info->stream.total_out += uDoCopy;
2107
141k
      iRead += uDoCopy;
2108
141k
  }
2109
784M
  else if (pfile_in_zip_read_info->compression_method == Z_BZIP2ED)
2110
784M
  {
2111
784M
#ifdef HAVE_BZIP2
2112
784M
      uLong uTotalOutBefore,uTotalOutAfter;
2113
784M
      const Bytef *bufBefore;
2114
784M
      uLong uOutThis;
2115
2116
784M
      pfile_in_zip_read_info->bstream.next_in        =
2117
784M
    (char*)pfile_in_zip_read_info->stream.next_in;
2118
784M
      pfile_in_zip_read_info->bstream.avail_in       =
2119
784M
    pfile_in_zip_read_info->stream.avail_in;
2120
784M
      pfile_in_zip_read_info->bstream.total_in_lo32  =
2121
784M
    (unsigned int) pfile_in_zip_read_info->stream.total_in;
2122
784M
      pfile_in_zip_read_info->bstream.total_in_hi32  = 0;
2123
784M
      pfile_in_zip_read_info->bstream.next_out       =
2124
784M
    (char*)pfile_in_zip_read_info->stream.next_out;
2125
784M
      pfile_in_zip_read_info->bstream.avail_out      =
2126
784M
    pfile_in_zip_read_info->stream.avail_out;
2127
784M
      pfile_in_zip_read_info->bstream.total_out_lo32 =
2128
784M
    (unsigned int) pfile_in_zip_read_info->stream.total_out;
2129
784M
      pfile_in_zip_read_info->bstream.total_out_hi32 = 0;
2130
2131
784M
      uTotalOutBefore = pfile_in_zip_read_info->bstream.total_out_lo32;
2132
784M
      bufBefore = (const Bytef *)pfile_in_zip_read_info->bstream.next_out;
2133
2134
784M
      err = BZ2_bzDecompress(&pfile_in_zip_read_info->bstream);
2135
2136
784M
      uTotalOutAfter = pfile_in_zip_read_info->bstream.total_out_lo32;
2137
784M
      uOutThis = uTotalOutAfter-uTotalOutBefore;
2138
2139
784M
      pfile_in_zip_read_info->total_out_64 =
2140
784M
    pfile_in_zip_read_info->total_out_64 + uOutThis;
2141
2142
784M
      pfile_in_zip_read_info->crc32 =
2143
784M
    crc32(pfile_in_zip_read_info->crc32,bufBefore,
2144
784M
          (uInt)(uOutThis));
2145
784M
      pfile_in_zip_read_info->rest_read_uncompressed -= uOutThis;
2146
784M
      iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
2147
2148
784M
      pfile_in_zip_read_info->stream.next_in   =
2149
784M
    (Bytef*)pfile_in_zip_read_info->bstream.next_in;
2150
784M
      pfile_in_zip_read_info->stream.avail_in  =
2151
784M
    pfile_in_zip_read_info->bstream.avail_in;
2152
784M
      pfile_in_zip_read_info->stream.total_in  =
2153
784M
    pfile_in_zip_read_info->bstream.total_in_lo32;
2154
784M
      pfile_in_zip_read_info->stream.next_out  =
2155
784M
    (Bytef*)pfile_in_zip_read_info->bstream.next_out;
2156
784M
      pfile_in_zip_read_info->stream.avail_out =
2157
784M
    pfile_in_zip_read_info->bstream.avail_out;
2158
784M
      pfile_in_zip_read_info->stream.total_out =
2159
784M
    pfile_in_zip_read_info->bstream.total_out_lo32;
2160
2161
784M
      if (err == BZ_STREAM_END)
2162
1
        return (iRead == 0) ? UNZ_EOF : iRead;
2163
784M
      if (err != BZ_OK)
2164
73
        break;
2165
      /* BZ_OK with no output means the decoder wants more input.
2166
         With the entry's compressed bytes all consumed there is
2167
         none, so the stream is truncated and this loop would never
2168
         end.  (inflate() reports Z_BUF_ERROR in that state.) */
2169
784M
      if (uOutThis == 0 &&
2170
2
    pfile_in_zip_read_info->stream.avail_in == 0 &&
2171
2
    pfile_in_zip_read_info->rest_read_compressed == 0)
2172
2
      {
2173
2
    err = BZ_UNEXPECTED_EOF;
2174
2
    break;
2175
2
      }
2176
784M
#endif
2177
784M
  } // end Z_BZIP2ED
2178
64.7k
  else
2179
64.7k
  {
2180
64.7k
      ZPOS64_T uTotalOutBefore,uTotalOutAfter;
2181
64.7k
      const Bytef *bufBefore;
2182
64.7k
      ZPOS64_T uOutThis;
2183
64.7k
      int flush = Z_SYNC_FLUSH;
2184
2185
64.7k
      uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
2186
64.7k
      bufBefore = pfile_in_zip_read_info->stream.next_out;
2187
2188
      /*
2189
      if ((pfile_in_zip_read_info->rest_read_uncompressed ==
2190
         pfile_in_zip_read_info->stream.avail_out) &&
2191
    (pfile_in_zip_read_info->rest_read_compressed == 0))
2192
    flush = Z_FINISH;
2193
      */
2194
64.7k
      err = inflate(&pfile_in_zip_read_info->stream, flush);
2195
2196
64.7k
      if ((err >= 0) && (pfile_in_zip_read_info->stream.msg != NULL))
2197
0
        err = Z_DATA_ERROR;
2198
2199
64.7k
      uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
2200
64.7k
      uOutThis = uTotalOutAfter-uTotalOutBefore;
2201
2202
64.7k
      pfile_in_zip_read_info->total_out_64 =
2203
64.7k
    pfile_in_zip_read_info->total_out_64 + uOutThis;
2204
2205
64.7k
      pfile_in_zip_read_info->crc32 =
2206
64.7k
    crc32(pfile_in_zip_read_info->crc32,bufBefore,
2207
64.7k
      (uInt)(uOutThis));
2208
2209
64.7k
      pfile_in_zip_read_info->rest_read_uncompressed -=
2210
64.7k
    uOutThis;
2211
2212
64.7k
      iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
2213
      // R addition for 3.2.0
2214
64.7k
      if(iRead < len && uTotalOutAfter == 4294967295U)
2215
0
    warning("possible truncation of >= 4GB file");
2216
2217
64.7k
      if (err == Z_STREAM_END)
2218
562
    return (iRead == 0) ? UNZ_EOF : iRead;
2219
64.1k
      if (err != Z_OK)
2220
20
    break;
2221
64.1k
  }
2222
784M
    }
2223
2224
784M
    if (err == Z_OK)
2225
784M
  return iRead;
2226
95
    return err;
2227
784M
}
2228
2229
/*
2230
  Close the file in zip opened with unzipOpenCurrentFile
2231
  Return UNZ_CRCERROR if all the file was read but the CRC is not good
2232
*/
2233
static int unzCloseCurrentFile (unzFile file)
2234
1.42k
{
2235
1.42k
    int err = UNZ_OK;
2236
2237
1.42k
    unz64_s* s;
2238
1.42k
    file_in_zip64_read_info_s* pfile_in_zip_read_info;
2239
1.42k
    if (file == NULL)
2240
0
  return UNZ_PARAMERROR;
2241
1.42k
    s = (unz64_s*)file;
2242
1.42k
    pfile_in_zip_read_info = s->pfile_in_zip_read;
2243
2244
1.42k
    if (pfile_in_zip_read_info == NULL)
2245
342
  return UNZ_PARAMERROR;
2246
2247
2248
1.08k
    if ((pfile_in_zip_read_info->rest_read_uncompressed == 0) &&
2249
681
  (!pfile_in_zip_read_info->raw))
2250
681
    {
2251
681
  if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
2252
87
      err = UNZ_CRCERROR;
2253
681
    }
2254
2255
2256
1.08k
    TRYFREE(pfile_in_zip_read_info->read_buffer);
2257
1.08k
    pfile_in_zip_read_info->read_buffer = NULL;
2258
1.08k
    if (pfile_in_zip_read_info->stream_initialised == Z_DEFLATED)
2259
661
  inflateEnd(&pfile_in_zip_read_info->stream);
2260
422
#ifdef HAVE_BZIP2
2261
422
    else if (pfile_in_zip_read_info->stream_initialised == Z_BZIP2ED)
2262
124
  BZ2_bzDecompressEnd(&pfile_in_zip_read_info->bstream);
2263
1.08k
#endif
2264
2265
2266
1.08k
    pfile_in_zip_read_info->stream_initialised = 0;
2267
1.08k
    TRYFREE(pfile_in_zip_read_info);
2268
2269
1.08k
    s->pfile_in_zip_read = NULL;
2270
2271
1.08k
    return err;
2272
1.42k
}
2273
2274
2275
#ifdef Win32
2276
# define f_seek fseeko64
2277
# define f_tell ftello64
2278
#elif defined(HAVE_OFF_T) && defined(HAVE_FSEEKO)
2279
1.93M
# define f_seek fseeko
2280
4.52k
# define f_tell ftello
2281
#else
2282
# define f_seek fseek
2283
# define f_tell ftell
2284
#endif
2285
2286
static voidpf fopen_func(const void* filename, int mode)
2287
2.48k
{
2288
2.48k
    FILE* file = NULL;
2289
2.48k
    const char* mode_fopen = NULL;
2290
2.48k
    if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER) == ZLIB_FILEFUNC_MODE_READ)
2291
2.48k
  mode_fopen = "rb";
2292
0
    else if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
2293
0
  mode_fopen = "r+b";
2294
0
    else if (mode & ZLIB_FILEFUNC_MODE_CREATE)
2295
0
  mode_fopen = "wb";
2296
2297
2.48k
    if ((filename != NULL) && (mode_fopen != NULL))
2298
2.48k
  file = fopen(filename, mode_fopen);
2299
2.48k
    return file;
2300
2.48k
}
2301
2302
2303
static ZPOS64_T ftell_func (voidpf stream)
2304
4.52k
{
2305
4.52k
    return f_tell((FILE *)stream);
2306
4.52k
}
2307
2308
static int fseek_func (voidpf stream, ZPOS64_T offset, int origin)
2309
1.93M
{
2310
1.93M
    int fseek_origin = 0;
2311
1.93M
    int ret;
2312
1.93M
    switch (origin)
2313
1.93M
    {
2314
1.90M
    case ZLIB_FILEFUNC_SEEK_CUR :
2315
1.90M
  fseek_origin = SEEK_CUR;
2316
1.90M
  break;
2317
4.52k
    case ZLIB_FILEFUNC_SEEK_END :
2318
4.52k
  fseek_origin = SEEK_END;
2319
4.52k
  break;
2320
21.9k
    case ZLIB_FILEFUNC_SEEK_SET :
2321
21.9k
  fseek_origin = SEEK_SET;
2322
21.9k
  break;
2323
0
    default: return -1;
2324
1.93M
    }
2325
1.93M
    ret = 0;
2326
1.93M
    if (f_seek((FILE *)stream, offset, fseek_origin) != 0) ret = -1;
2327
1.93M
    return ret;
2328
1.93M
}
2329
2330
static size_t fread_func (voidpf stream, void* buf, size_t size)
2331
8.07M
{
2332
8.07M
    uLong ret;
2333
8.07M
    ret = (uLong)fread(buf, 1, size, (FILE *) stream);
2334
8.07M
    return ret;
2335
8.07M
}
2336
2337
static int fclose_func (voidpf stream)
2338
2.45k
{
2339
2.45k
    int ret;
2340
2.45k
    ret = fclose((FILE *)stream);
2341
2.45k
    return ret;
2342
2.45k
}
2343
2344
static int ferror_func (voidpf stream)
2345
7.61M
{
2346
7.61M
    int ret;
2347
7.61M
    ret = ferror((FILE *)stream);
2348
7.61M
    return ret;
2349
7.61M
}