Subversion Repositories Kolibri OS

Rev

Rev 5728 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5728 serge 1
/* 7zArcIn.c -- 7z Input functions
2
2015-05-16 : Igor Pavlov : Public domain */
3
 
4
#include "Precomp.h"
5
 
6
#include 
7
 
8
#include "7z.h"
9
#include "7zBuf.h"
10
#include "7zCrc.h"
11
#include "CpuArch.h"
12
 
13
#define MY_ALLOC(T, p, size, alloc) { \
14
  if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; }
15
 
16
#define MY_ALLOC_ZE(T, p, size, alloc) { if ((size) == 0) p = 0; else MY_ALLOC(T, p, size, alloc) }
17
 
18
#define MY_ALLOC_AND_CPY(to, size, from, alloc) \
19
  { MY_ALLOC(Byte, to, size, alloc); memcpy(to, from, size); }
20
 
21
#define MY_ALLOC_ZE_AND_CPY(to, size, from, alloc) \
22
  { if ((size) == 0) p = 0; else { MY_ALLOC_AND_CPY(to, size, from, alloc) } }
23
 
24
#define k7zMajorVersion 0
25
 
26
enum EIdEnum
27
{
28
  k7zIdEnd,
29
  k7zIdHeader,
30
  k7zIdArchiveProperties,
31
  k7zIdAdditionalStreamsInfo,
32
  k7zIdMainStreamsInfo,
33
  k7zIdFilesInfo,
34
  k7zIdPackInfo,
35
  k7zIdUnpackInfo,
36
  k7zIdSubStreamsInfo,
37
  k7zIdSize,
38
  k7zIdCRC,
39
  k7zIdFolder,
40
  k7zIdCodersUnpackSize,
41
  k7zIdNumUnpackStream,
42
  k7zIdEmptyStream,
43
  k7zIdEmptyFile,
44
  k7zIdAnti,
45
  k7zIdName,
46
  k7zIdCTime,
47
  k7zIdATime,
48
  k7zIdMTime,
49
  k7zIdWinAttrib,
50
  k7zIdComment,
51
  k7zIdEncodedHeader,
52
  k7zIdStartPos,
53
  k7zIdDummy
54
  // k7zNtSecure,
55
  // k7zParent,
56
  // k7zIsReal
57
};
58
 
59
const Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
60
 
61
 
62
/*
63
static int SzFolder_FindBondForInStream(const CSzFolder *p, UInt32 inStreamIndex)
64
{
65
  UInt32 i;
66
  for (i = 0; i < p->NumBonds; i++)
67
    if (p->Bonds[i].InIndex == inStreamIndex)
68
      return i;
69
  return -1;
70
}
71
*/
72
 
73
#define SzBitUi32s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }
74
 
75
static SRes SzBitUi32s_Alloc(CSzBitUi32s *p, size_t num, ISzAlloc *alloc)
76
{
77
  if (num == 0)
78
  {
79
    p->Defs = 0;
80
    p->Vals = 0;
81
  }
82
  else
83
  {
5809 serge 84
  MY_ALLOC(Byte, p->Defs, (num + 7) >> 3, alloc);
85
  MY_ALLOC(UInt32, p->Vals, num, alloc);
5728 serge 86
  }
87
  return SZ_OK;
88
}
89
 
90
void SzBitUi32s_Free(CSzBitUi32s *p, ISzAlloc *alloc)
91
{
92
  IAlloc_Free(alloc, p->Defs); p->Defs = 0;
93
  IAlloc_Free(alloc, p->Vals); p->Vals = 0;
94
}
95
 
96
#define SzBitUi64s_Init(p) { (p)->Defs = 0; (p)->Vals = 0; }
97
 
98
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)
99
{
100
  IAlloc_Free(alloc, p->Defs); p->Defs = 0;
101
  IAlloc_Free(alloc, p->Vals); p->Vals = 0;
102
}
103
 
104
static void SzAr_Init(CSzAr *p)
105
{
106
  p->NumPackStreams = 0;
107
  p->NumFolders = 0;
108
  p->PackPositions = 0;
109
  SzBitUi32s_Init(&p->FolderCRCs);
110
  // p->Folders = 0;
111
  p->FoCodersOffsets = 0;
112
  p->FoSizesOffsets = 0;
113
  p->FoStartPackStreamIndex = 0;
114
 
115
  p->CodersData = 0;
116
  // p->CoderUnpackSizes = 0;
117
  p->UnpackSizesData = 0;
118
}
119
 
120
static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
121
{
122
  IAlloc_Free(alloc, p->UnpackSizesData);
123
  IAlloc_Free(alloc, p->CodersData);
124
  // IAlloc_Free(alloc, p->CoderUnpackSizes);
125
 
126
  IAlloc_Free(alloc, p->PackPositions);
127
 
128
  // IAlloc_Free(alloc, p->Folders);
129
  IAlloc_Free(alloc, p->FoCodersOffsets);
130
  IAlloc_Free(alloc, p->FoSizesOffsets);
131
  IAlloc_Free(alloc, p->FoStartPackStreamIndex);
132
 
133
  SzBitUi32s_Free(&p->FolderCRCs, alloc);
134
 
135
  SzAr_Init(p);
136
}
137
 
138
 
139
void SzArEx_Init(CSzArEx *p)
140
{
141
  SzAr_Init(&p->db);
142
  p->NumFiles = 0;
143
  p->dataPos = 0;
144
  // p->Files = 0;
145
  p->UnpackPositions = 0;
146
  // p->IsEmptyFiles = 0;
147
  p->IsDirs = 0;
148
  // p->FolderStartPackStreamIndex = 0;
149
  // p->PackStreamStartPositions = 0;
150
  p->FolderStartFileIndex = 0;
151
  p->FileIndexToFolderIndexMap = 0;
152
  p->FileNameOffsets = 0;
153
  p->FileNames = 0;
154
  SzBitUi32s_Init(&p->CRCs);
155
  SzBitUi32s_Init(&p->Attribs);
156
  // SzBitUi32s_Init(&p->Parents);
157
  SzBitUi64s_Init(&p->MTime);
158
  SzBitUi64s_Init(&p->CTime);
159
}
160
 
161
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
162
{
163
  // IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
164
  // IAlloc_Free(alloc, p->PackStreamStartPositions);
165
  IAlloc_Free(alloc, p->FolderStartFileIndex);
166
  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);
167
 
168
  IAlloc_Free(alloc, p->FileNameOffsets);
169
  IAlloc_Free(alloc, p->FileNames);
170
 
171
  SzBitUi64s_Free(&p->CTime, alloc);
172
  SzBitUi64s_Free(&p->MTime, alloc);
173
  SzBitUi32s_Free(&p->CRCs, alloc);
174
  // SzBitUi32s_Free(&p->Parents, alloc);
175
  SzBitUi32s_Free(&p->Attribs, alloc);
176
  IAlloc_Free(alloc, p->IsDirs);
177
  // IAlloc_Free(alloc, p->IsEmptyFiles);
178
  IAlloc_Free(alloc, p->UnpackPositions);
179
  // IAlloc_Free(alloc, p->Files);
180
 
181
  SzAr_Free(&p->db, alloc);
182
  SzArEx_Init(p);
183
}
184
 
185
static int TestSignatureCandidate(Byte *testBytes)
186
{
187
  unsigned i;
188
  for (i = 0; i < k7zSignatureSize; i++)
189
    if (testBytes[i] != k7zSignature[i])
190
      return 0;
191
  return 1;
192
}
193
 
194
#define SzData_Clear(p) { (p)->Data = 0; (p)->Size = 0; }
195
 
196
static SRes SzReadByte(CSzData *sd, Byte *b)
197
{
198
  if (sd->Size == 0)
199
    return SZ_ERROR_ARCHIVE;
200
  sd->Size--;
201
  *b = *sd->Data++;
202
  return SZ_OK;
203
}
204
 
205
#define SZ_READ_BYTE_SD(_sd_, dest) if ((_sd_)->Size == 0) return SZ_ERROR_ARCHIVE; (_sd_)->Size--; dest = *(_sd_)->Data++;
206
#define SZ_READ_BYTE(dest) SZ_READ_BYTE_SD(sd, dest)
207
#define SZ_READ_BYTE_2(dest) if (sd.Size == 0) return SZ_ERROR_ARCHIVE; sd.Size--; dest = *sd.Data++;
208
 
209
#define SKIP_DATA(sd, size) { sd->Size -= (size_t)(size); sd->Data += (size_t)(size); }
210
#define SKIP_DATA2(sd, size) { sd.Size -= (size_t)(size); sd.Data += (size_t)(size); }
211
 
212
#define SZ_READ_32(dest) if (sd.Size < 4) return SZ_ERROR_ARCHIVE; \
213
   dest = GetUi32(sd.Data); SKIP_DATA2(sd, 4);
214
 
215
static MY_NO_INLINE SRes ReadNumber(CSzData *sd, UInt64 *value)
216
{
217
  Byte firstByte, mask;
218
  unsigned i;
219
  UInt32 v;
220
 
221
  SZ_READ_BYTE(firstByte);
222
  if ((firstByte & 0x80) == 0)
223
  {
224
    *value = firstByte;
225
    return SZ_OK;
226
  }
227
  SZ_READ_BYTE(v);
228
  if ((firstByte & 0x40) == 0)
229
  {
230
    *value = (((UInt32)firstByte & 0x3F) << 8) | v;
231
    return SZ_OK;
232
  }
233
  SZ_READ_BYTE(mask);
234
  *value = v | ((UInt32)mask << 8);
235
  mask = 0x20;
236
  for (i = 2; i < 8; i++)
237
  {
238
    Byte b;
239
    if ((firstByte & mask) == 0)
240
    {
241
      UInt64 highPart = (unsigned)firstByte & (unsigned)(mask - 1);
242
      *value |= (highPart << (8 * i));
243
      return SZ_OK;
244
    }
245
    SZ_READ_BYTE(b);
246
    *value |= ((UInt64)b << (8 * i));
247
    mask >>= 1;
248
  }
249
  return SZ_OK;
250
}
251
 
252
/*
253
static MY_NO_INLINE const Byte *SzReadNumbers(const Byte *data, const Byte *dataLim, UInt64 *values, UInt32 num)
254
{
255
  for (; num != 0; num--)
256
  {
257
    Byte firstByte;
258
    Byte mask;
259
 
260
    unsigned i;
261
    UInt32 v;
262
    UInt64 value;
263
 
264
    if (data == dataLim)
265
      return NULL;
266
    firstByte = *data++;
267
 
268
    if ((firstByte & 0x80) == 0)
269
    {
270
      *values++ = firstByte;
271
      continue;
272
    }
273
    if (data == dataLim)
274
      return NULL;
275
    v = *data++;
276
    if ((firstByte & 0x40) == 0)
277
    {
278
      *values++ = (((UInt32)firstByte & 0x3F) << 8) | v;
279
      continue;
280
    }
281
    if (data == dataLim)
282
      return NULL;
283
    value = v | ((UInt32)*data++ << 8);
284
    mask = 0x20;
285
    for (i = 2; i < 8; i++)
286
    {
287
      if ((firstByte & mask) == 0)
288
      {
289
        UInt64 highPart = firstByte & (mask - 1);
290
        value |= (highPart << (8 * i));
291
        break;
292
      }
293
      if (data == dataLim)
294
        return NULL;
295
      value |= ((UInt64)*data++ << (8 * i));
296
      mask >>= 1;
297
    }
298
    *values++ = value;
299
  }
300
  return data;
301
}
302
*/
303
 
304
static MY_NO_INLINE SRes SzReadNumber32(CSzData *sd, UInt32 *value)
305
{
306
  Byte firstByte;
307
  UInt64 value64;
308
  if (sd->Size == 0)
309
    return SZ_ERROR_ARCHIVE;
310
  firstByte = *sd->Data;
311
  if ((firstByte & 0x80) == 0)
312
  {
313
    *value = firstByte;
314
    sd->Data++;
315
    sd->Size--;
316
    return SZ_OK;
317
  }
318
  RINOK(ReadNumber(sd, &value64));
319
  if (value64 >= (UInt32)0x80000000 - 1)
320
    return SZ_ERROR_UNSUPPORTED;
321
  if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 4)))
322
    return SZ_ERROR_UNSUPPORTED;
323
  *value = (UInt32)value64;
324
  return SZ_OK;
325
}
326
 
327
#define ReadID(sd, value) ReadNumber(sd, value)
328
 
329
static SRes SkipData(CSzData *sd)
330
{
331
  UInt64 size;
332
  RINOK(ReadNumber(sd, &size));
333
  if (size > sd->Size)
334
    return SZ_ERROR_ARCHIVE;
335
  SKIP_DATA(sd, size);
336
  return SZ_OK;
337
}
338
 
339
static SRes WaitId(CSzData *sd, UInt64 id)
340
{
341
  for (;;)
342
  {
343
    UInt64 type;
344
    RINOK(ReadID(sd, &type));
345
    if (type == id)
346
      return SZ_OK;
347
    if (type == k7zIdEnd)
348
      return SZ_ERROR_ARCHIVE;
349
    RINOK(SkipData(sd));
350
  }
351
}
352
 
353
static SRes RememberBitVector(CSzData *sd, UInt32 numItems, const Byte **v)
354
{
355
  UInt32 numBytes = (numItems + 7) >> 3;
356
  if (numBytes > sd->Size)
357
    return SZ_ERROR_ARCHIVE;
358
  *v = sd->Data;
359
  SKIP_DATA(sd, numBytes);
360
  return SZ_OK;
361
}
362
 
363
static UInt32 CountDefinedBits(const Byte *bits, UInt32 numItems)
364
{
365
  Byte b = 0;
366
  unsigned m = 0;
367
  UInt32 sum = 0;
368
  for (; numItems != 0; numItems--)
369
  {
370
    if (m == 0)
371
    {
372
      b = *bits++;
373
      m = 8;
374
    }
375
    m--;
376
    sum += ((b >> m) & 1);
377
  }
378
  return sum ;
379
}
380
 
381
static MY_NO_INLINE SRes ReadBitVector(CSzData *sd, UInt32 numItems, Byte **v, ISzAlloc *alloc)
382
{
383
  Byte allAreDefined;
384
  Byte *v2;
385
  UInt32 numBytes = (numItems + 7) >> 3;
386
  *v = NULL;
387
  RINOK(SzReadByte(sd, &allAreDefined));
388
  if (numBytes == 0)
389
    return SZ_OK;
390
  if (allAreDefined == 0)
391
  {
392
    if (numBytes > sd->Size)
393
      return SZ_ERROR_ARCHIVE;
394
    MY_ALLOC_AND_CPY(*v, numBytes, sd->Data, alloc);
395
    SKIP_DATA(sd, numBytes);
396
    return SZ_OK;
397
  }
398
  MY_ALLOC(Byte, *v, numBytes, alloc);
399
  v2 = *v;
400
  memset(v2, 0xFF, (size_t)numBytes);
401
  {
402
    unsigned numBits = (unsigned)numItems & 7;
403
    if (numBits != 0)
404
      v2[numBytes - 1] = (Byte)((((UInt32)1 << numBits) - 1) << (8 - numBits));
405
  }
406
  return SZ_OK;
407
}
408
 
409
static MY_NO_INLINE SRes ReadUi32s(CSzData *sd2, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)
410
{
411
  UInt32 i;
412
  CSzData sd;
413
  UInt32 *vals;
414
  const Byte *defs;
415
  MY_ALLOC_ZE(UInt32, crcs->Vals, numItems, alloc);
416
  sd = *sd2;
417
  defs = crcs->Defs;
418
  vals = crcs->Vals;
419
  for (i = 0; i < numItems; i++)
420
    if (SzBitArray_Check(defs, i))
421
    {
422
      SZ_READ_32(vals[i]);
423
    }
424
    else
425
      vals[i] = 0;
426
  *sd2 = sd;
427
  return SZ_OK;
428
}
429
 
430
static SRes ReadBitUi32s(CSzData *sd, UInt32 numItems, CSzBitUi32s *crcs, ISzAlloc *alloc)
431
{
432
  SzBitUi32s_Free(crcs, alloc);
433
  RINOK(ReadBitVector(sd, numItems, &crcs->Defs, alloc));
434
  return ReadUi32s(sd, numItems, crcs, alloc);
435
}
436
 
437
static SRes SkipBitUi32s(CSzData *sd, UInt32 numItems)
438
{
439
  Byte allAreDefined;
440
  UInt32 numDefined = numItems;
441
  RINOK(SzReadByte(sd, &allAreDefined));
442
  if (!allAreDefined)
443
  {
444
    size_t numBytes = (numItems + 7) >> 3;
445
    if (numBytes > sd->Size)
446
      return SZ_ERROR_ARCHIVE;
447
    numDefined = CountDefinedBits(sd->Data, numItems);
448
    SKIP_DATA(sd, numBytes);
449
  }
450
  if (numDefined > (sd->Size >> 2))
451
    return SZ_ERROR_ARCHIVE;
452
  SKIP_DATA(sd, (size_t)numDefined * 4);
453
  return SZ_OK;
454
}
455
 
456
static SRes ReadPackInfo(CSzAr *p, CSzData *sd, ISzAlloc *alloc)
457
{
458
  RINOK(SzReadNumber32(sd, &p->NumPackStreams));
459
 
460
  RINOK(WaitId(sd, k7zIdSize));
461
  MY_ALLOC(UInt64, p->PackPositions, (size_t)p->NumPackStreams + 1, alloc);
462
  {
463
    UInt64 sum = 0;
464
    UInt32 i;
465
    UInt32 numPackStreams = p->NumPackStreams;
466
    for (i = 0; i < numPackStreams; i++)
467
    {
468
      UInt64 packSize;
469
      p->PackPositions[i] = sum;
470
      RINOK(ReadNumber(sd, &packSize));
471
      sum += packSize;
472
      if (sum < packSize)
473
        return SZ_ERROR_ARCHIVE;
474
    }
475
    p->PackPositions[i] = sum;
476
  }
477
 
478
  for (;;)
479
  {
480
    UInt64 type;
481
    RINOK(ReadID(sd, &type));
482
    if (type == k7zIdEnd)
483
      return SZ_OK;
484
    if (type == k7zIdCRC)
485
    {
486
      /* CRC of packed streams is unused now */
487
      RINOK(SkipBitUi32s(sd, p->NumPackStreams));
488
      continue;
489
    }
490
    RINOK(SkipData(sd));
491
  }
492
}
493
 
494
/*
495
static SRes SzReadSwitch(CSzData *sd)
496
{
497
  Byte external;
498
  RINOK(SzReadByte(sd, &external));
499
  return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED;
500
}
501
*/
502
 
503
#define k_NumCodersStreams_in_Folder_MAX (SZ_NUM_BONDS_IN_FOLDER_MAX + SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
504
 
505
SRes SzGetNextFolderItem(CSzFolder *f, CSzData *sd, CSzData *sdSizes)
506
{
507
  UInt32 numCoders, i;
508
  UInt32 numInStreams = 0;
509
  const Byte *dataStart = sd->Data;
510
 
511
  f->NumCoders = 0;
512
  f->NumBonds = 0;
513
  f->NumPackStreams = 0;
514
  f->UnpackStream = 0;
515
 
516
  RINOK(SzReadNumber32(sd, &numCoders));
517
  if (numCoders == 0 || numCoders > SZ_NUM_CODERS_IN_FOLDER_MAX)
518
    return SZ_ERROR_UNSUPPORTED;
519
 
520
  for (i = 0; i < numCoders; i++)
521
  {
522
    Byte mainByte;
523
    CSzCoderInfo *coder = f->Coders + i;
524
    unsigned idSize, j;
525
    UInt64 id;
526
 
527
    RINOK(SzReadByte(sd, &mainByte));
528
    if ((mainByte & 0xC0) != 0)
529
      return SZ_ERROR_UNSUPPORTED;
530
 
531
    idSize = (unsigned)(mainByte & 0xF);
532
    if (idSize > sizeof(id))
533
      return SZ_ERROR_UNSUPPORTED;
534
    if (idSize > sd->Size)
535
      return SZ_ERROR_ARCHIVE;
536
    id = 0;
537
    for (j = 0; j < idSize; j++)
538
    {
539
      id = ((id << 8) | *sd->Data);
540
      sd->Data++;
541
      sd->Size--;
542
    }
543
    if (id > (UInt32)0xFFFFFFFF)
544
      return SZ_ERROR_UNSUPPORTED;
545
    coder->MethodID = (UInt32)id;
546
 
547
    coder->NumStreams = 1;
548
    coder->PropsOffset = 0;
549
    coder->PropsSize = 0;
550
 
551
    if ((mainByte & 0x10) != 0)
552
    {
553
      UInt32 numStreams;
554
 
555
      RINOK(SzReadNumber32(sd, &numStreams));
556
      if (numStreams > k_NumCodersStreams_in_Folder_MAX)
557
        return SZ_ERROR_UNSUPPORTED;
558
      coder->NumStreams = (Byte)numStreams;
559
 
560
      RINOK(SzReadNumber32(sd, &numStreams));
561
      if (numStreams != 1)
562
        return SZ_ERROR_UNSUPPORTED;
563
    }
564
 
565
    numInStreams += coder->NumStreams;
566
 
567
    if (numInStreams > k_NumCodersStreams_in_Folder_MAX)
568
      return SZ_ERROR_UNSUPPORTED;
569
 
570
    if ((mainByte & 0x20) != 0)
571
    {
572
      UInt32 propsSize = 0;
573
      RINOK(SzReadNumber32(sd, &propsSize));
574
      if (propsSize > sd->Size)
575
        return SZ_ERROR_ARCHIVE;
576
      if (propsSize >= 0x80)
577
        return SZ_ERROR_UNSUPPORTED;
578
      coder->PropsOffset = sd->Data - dataStart;
579
      coder->PropsSize = (Byte)propsSize;
580
      sd->Data += (size_t)propsSize;
581
      sd->Size -= (size_t)propsSize;
582
    }
583
  }
584
 
585
  /*
586
  if (numInStreams == 1 && numCoders == 1)
587
  {
588
    f->NumPackStreams = 1;
589
    f->PackStreams[0] = 0;
590
  }
591
  else
592
  */
593
  {
594
    Byte streamUsed[k_NumCodersStreams_in_Folder_MAX];
595
    UInt32 numBonds, numPackStreams;
5809 serge 596
 
5728 serge 597
    numBonds = numCoders - 1;
598
    if (numInStreams < numBonds)
5809 serge 599
    return SZ_ERROR_ARCHIVE;
5728 serge 600
    if (numBonds > SZ_NUM_BONDS_IN_FOLDER_MAX)
5809 serge 601
    return SZ_ERROR_UNSUPPORTED;
5728 serge 602
    f->NumBonds = numBonds;
603
 
604
    numPackStreams = numInStreams - numBonds;
5809 serge 605
  if (numPackStreams > SZ_NUM_PACK_STREAMS_IN_FOLDER_MAX)
606
    return SZ_ERROR_UNSUPPORTED;
5728 serge 607
    f->NumPackStreams = numPackStreams;
608
 
5809 serge 609
  for (i = 0; i < numInStreams; i++)
5728 serge 610
      streamUsed[i] = False;
611
 
612
    if (numBonds != 0)
5809 serge 613
  {
5728 serge 614
      Byte coderUsed[SZ_NUM_CODERS_IN_FOLDER_MAX];
615
 
616
      for (i = 0; i < numCoders; i++)
617
        coderUsed[i] = False;
5809 serge 618
 
5728 serge 619
      for (i = 0; i < numBonds; i++)
620
      {
621
        CSzBond *bp = f->Bonds + i;
5809 serge 622
 
623
      RINOK(SzReadNumber32(sd, &bp->InIndex));
5728 serge 624
        if (bp->InIndex >= numInStreams || streamUsed[bp->InIndex])
5809 serge 625
        return SZ_ERROR_ARCHIVE;
5728 serge 626
        streamUsed[bp->InIndex] = True;
627
 
5809 serge 628
      RINOK(SzReadNumber32(sd, &bp->OutIndex));
5728 serge 629
        if (bp->OutIndex >= numCoders || coderUsed[bp->OutIndex])
5809 serge 630
        return SZ_ERROR_ARCHIVE;
5728 serge 631
        coderUsed[bp->OutIndex] = True;
5809 serge 632
    }
5728 serge 633
 
634
      for (i = 0; i < numCoders; i++)
635
        if (!coderUsed[i])
5809 serge 636
      {
5728 serge 637
          f->UnpackStream = i;
5809 serge 638
        break;
639
      }
5728 serge 640
 
641
      if (i == numCoders)
5809 serge 642
      return SZ_ERROR_ARCHIVE;
643
  }
644
 
645
  if (numPackStreams == 1)
646
  {
647
    for (i = 0; i < numInStreams; i++)
648
        if (!streamUsed[i])
649
        break;
650
    if (i == numInStreams)
651
      return SZ_ERROR_ARCHIVE;
652
    f->PackStreams[0] = i;
653
  }
654
  else
655
    for (i = 0; i < numPackStreams; i++)
5728 serge 656
    {
657
        UInt32 index;
658
        RINOK(SzReadNumber32(sd, &index));
659
        if (index >= numInStreams || streamUsed[index])
660
          return SZ_ERROR_ARCHIVE;
661
        streamUsed[index] = True;
662
        f->PackStreams[i] = index;
663
      }
5809 serge 664
    }
5728 serge 665
 
666
  for (i = 0; i < numCoders; i++)
667
  {
668
    RINOK(ReadNumber(sdSizes, f->CodersUnpackSizes + i));
669
  }
670
 
671
  f->NumCoders = numCoders;
672
 
673
  return SZ_OK;
674
}
675
 
676
static MY_NO_INLINE SRes SkipNumbers(CSzData *sd2, UInt32 num)
677
{
678
  CSzData sd;
679
  sd = *sd2;
680
  for (; num != 0; num--)
681
  {
682
    Byte firstByte, mask;
683
    unsigned i;
684
    SZ_READ_BYTE_2(firstByte);
685
    if ((firstByte & 0x80) == 0)
686
      continue;
687
    if ((firstByte & 0x40) == 0)
688
    {
689
      if (sd.Size == 0)
690
        return SZ_ERROR_ARCHIVE;
691
      sd.Size--;
692
      sd.Data++;
693
      continue;
694
    }
695
    mask = 0x20;
696
    for (i = 2; i < 8 && (firstByte & mask) != 0; i++)
697
      mask >>= 1;
698
    if (i > sd.Size)
699
      return SZ_ERROR_ARCHIVE;
700
    SKIP_DATA2(sd, i);
701
  }
702
  *sd2 = sd;
703
  return SZ_OK;
704
}
705
 
706
#define k_Scan_NumCoders_MAX 64
707
#define k_Scan_NumCodersStreams_in_Folder_MAX 64
708
 
709
static SRes ReadUnpackInfo(CSzAr *p,
710
    CSzData *sd2,
711
    UInt32 numFoldersMax,
712
    const CBuf *tempBufs, UInt32 numTempBufs,
713
    ISzAlloc *alloc)
714
{
715
  CSzData sd;
716
 
717
  UInt32 fo, numFolders, numCodersOutStreams, packStreamIndex;
718
  const Byte *startBufPtr;
719
  Byte external;
720
 
721
  RINOK(WaitId(sd2, k7zIdFolder));
722
 
723
  RINOK(SzReadNumber32(sd2, &numFolders));
724
  if (numFolders > numFoldersMax)
725
    return SZ_ERROR_UNSUPPORTED;
726
  p->NumFolders = numFolders;
727
 
728
  SZ_READ_BYTE_SD(sd2, external);
729
  if (external == 0)
730
    sd = *sd2;
731
  else
732
  {
733
    UInt32 index;
734
    RINOK(SzReadNumber32(sd2, &index));
735
    if (index >= numTempBufs)
736
      return SZ_ERROR_ARCHIVE;
737
    sd.Data = tempBufs[index].data;
738
    sd.Size = tempBufs[index].size;
739
  }
740
 
741
  MY_ALLOC(size_t, p->FoCodersOffsets, (size_t)numFolders + 1, alloc);
742
  MY_ALLOC(size_t, p->FoSizesOffsets, (size_t)numFolders + 1, alloc);
743
  MY_ALLOC(UInt32, p->FoStartPackStreamIndex, (size_t)numFolders + 1, alloc);
744
 
745
  startBufPtr = sd.Data;
746
 
747
  packStreamIndex = 0;
748
  numCodersOutStreams = 0;
749
 
750
  for (fo = 0; fo < numFolders; fo++)
751
  {
752
    UInt32 numCoders, ci, numInStreams = 0;
753
 
754
    p->FoCodersOffsets[fo] = sd.Data - startBufPtr;
755
 
756
    RINOK(SzReadNumber32(&sd, &numCoders));
757
    if (numCoders == 0 || numCoders > k_Scan_NumCoders_MAX)
758
      return SZ_ERROR_UNSUPPORTED;
759
 
760
    for (ci = 0; ci < numCoders; ci++)
761
    {
762
      Byte mainByte;
763
      unsigned idSize;
764
      UInt32 coderInStreams;
765
 
766
      SZ_READ_BYTE_2(mainByte);
767
      if ((mainByte & 0xC0) != 0)
768
        return SZ_ERROR_UNSUPPORTED;
769
      idSize = (mainByte & 0xF);
770
      if (idSize > 8)
771
        return SZ_ERROR_UNSUPPORTED;
772
      if (idSize > sd.Size)
773
        return SZ_ERROR_ARCHIVE;
774
      SKIP_DATA2(sd, idSize);
775
 
776
      coderInStreams = 1;
777
 
778
      if ((mainByte & 0x10) != 0)
779
      {
780
        UInt32 coderOutStreams;
781
        RINOK(SzReadNumber32(&sd, &coderInStreams));
782
        RINOK(SzReadNumber32(&sd, &coderOutStreams));
783
        if (coderInStreams > k_Scan_NumCodersStreams_in_Folder_MAX || coderOutStreams != 1)
784
          return SZ_ERROR_UNSUPPORTED;
785
      }
786
 
787
      numInStreams += coderInStreams;
788
 
789
      if ((mainByte & 0x20) != 0)
790
      {
791
        UInt32 propsSize;
792
        RINOK(SzReadNumber32(&sd, &propsSize));
793
        if (propsSize > sd.Size)
794
          return SZ_ERROR_ARCHIVE;
795
        SKIP_DATA2(sd, propsSize);
796
      }
797
    }
798
 
799
    {
800
      UInt32 indexOfMainStream = 0;
801
      UInt32 numPackStreams = 1;
802
 
803
      if (numCoders != 1 || numInStreams != 1)
804
      {
805
        Byte streamUsed[k_Scan_NumCodersStreams_in_Folder_MAX];
806
        Byte coderUsed[k_Scan_NumCoders_MAX];
807
 
808
        UInt32 i;
809
        UInt32 numBonds = numCoders - 1;
810
        if (numInStreams < numBonds)
811
          return SZ_ERROR_ARCHIVE;
812
 
813
        if (numInStreams > k_Scan_NumCodersStreams_in_Folder_MAX)
814
          return SZ_ERROR_UNSUPPORTED;
815
 
816
        for (i = 0; i < numInStreams; i++)
817
          streamUsed[i] = False;
818
        for (i = 0; i < numCoders; i++)
819
          coderUsed[i] = False;
820
 
821
        for (i = 0; i < numBonds; i++)
822
        {
823
          UInt32 index;
824
 
825
          RINOK(SzReadNumber32(&sd, &index));
826
          if (index >= numInStreams || streamUsed[index])
827
            return SZ_ERROR_ARCHIVE;
828
          streamUsed[index] = True;
829
 
830
          RINOK(SzReadNumber32(&sd, &index));
831
          if (index >= numCoders || coderUsed[index])
832
            return SZ_ERROR_ARCHIVE;
833
          coderUsed[index] = True;
834
        }
835
 
836
        numPackStreams = numInStreams - numBonds;
837
 
838
        if (numPackStreams != 1)
839
          for (i = 0; i < numPackStreams; i++)
840
          {
841
            UInt32 index;
842
            RINOK(SzReadNumber32(&sd, &index));
843
            if (index >= numInStreams || streamUsed[index])
844
              return SZ_ERROR_ARCHIVE;
845
            streamUsed[index] = True;
846
          }
847
 
848
        for (i = 0; i < numCoders; i++)
849
          if (!coderUsed[i])
850
          {
851
            indexOfMainStream = i;
852
            break;
853
          }
854
 
855
        if (i == numCoders)
856
          return SZ_ERROR_ARCHIVE;
857
      }
858
 
859
      p->FoStartPackStreamIndex[fo] = packStreamIndex;
860
      p->FoSizesOffsets[fo] = (numCoders << 8) | indexOfMainStream;
861
      numCodersOutStreams += numCoders;
862
      if (numCodersOutStreams < numCoders)
863
        return SZ_ERROR_UNSUPPORTED;
864
 
865
      packStreamIndex += numPackStreams;
866
      if (packStreamIndex < numPackStreams)
867
        return SZ_ERROR_UNSUPPORTED;
868
 
869
      if (packStreamIndex > p->NumPackStreams)
870
        return SZ_ERROR_ARCHIVE;
871
    }
872
  }
873
 
874
  {
875
    size_t dataSize = sd.Data - startBufPtr;
876
    p->FoStartPackStreamIndex[fo] = packStreamIndex;
877
    p->FoCodersOffsets[fo] = dataSize;
878
    MY_ALLOC_ZE_AND_CPY(p->CodersData, dataSize, startBufPtr, alloc);
879
  }
880
 
881
  if (external != 0)
882
  {
883
    if (sd.Size != 0)
884
      return SZ_ERROR_ARCHIVE;
885
    sd = *sd2;
886
  }
887
 
888
  RINOK(WaitId(&sd, k7zIdCodersUnpackSize));
889
 
890
  // MY_ALLOC_ZE(UInt64, p->CoderUnpackSizes, (size_t)numCodersOutStreams, alloc);
891
  {
892
    size_t dataSize = sd.Size;
893
    /*
894
    UInt32 i;
895
    for (i = 0; i < numCodersOutStreams; i++)
896
    {
897
    RINOK(ReadNumber(&sd, p->CoderUnpackSizes + i));
898
    }
899
    */
900
    RINOK(SkipNumbers(&sd, numCodersOutStreams));
901
    dataSize -= sd.Size;
902
    MY_ALLOC_ZE_AND_CPY(p->UnpackSizesData, dataSize, sd.Data - dataSize, alloc);
903
    p->UnpackSizesDataSize = dataSize;
904
    /*
905
    const Byte *data = SzReadNumbers(sd.Data, sd.Data + sd.Size, p->CoderUnpackSizes, numCodersOutStreams);
906
    if (data == NULL)
907
    return SZ_ERROR_ARCHIVE;
908
    sd.Size = sd.Data + sd.Size - data;
909
    sd.Data = data;
910
    */
911
  }
912
 
913
  for (;;)
914
  {
915
    UInt64 type;
916
    RINOK(ReadID(&sd, &type));
917
    if (type == k7zIdEnd)
918
    {
919
      *sd2 = sd;
920
      return SZ_OK;
921
    }
922
    if (type == k7zIdCRC)
923
    {
924
      RINOK(ReadBitUi32s(&sd, numFolders, &p->FolderCRCs, alloc));
925
      continue;
926
    }
927
    RINOK(SkipData(&sd));
928
  }
929
}
930
 
931
typedef struct
932
{
933
  UInt32 NumTotalSubStreams;
934
  UInt32 NumSubDigests;
935
  CSzData sdNumSubStreams;
936
  CSzData sdSizes;
937
  CSzData sdCRCs;
938
} CSubStreamInfo;
939
 
940
#define SzUi32IndexMax (((UInt32)1 << 31) - 2)
941
 
942
static SRes ReadSubStreamsInfo(CSzAr *p, CSzData *sd, CSubStreamInfo *ssi)
943
{
944
  UInt64 type = 0;
945
  UInt32 i;
946
  UInt32 numSubDigests = 0;
947
  UInt32 numFolders = p->NumFolders;
948
  UInt32 numUnpackStreams = numFolders;
949
  UInt32 numUnpackSizesInData = 0;
950
 
951
  for (;;)
952
  {
953
    RINOK(ReadID(sd, &type));
954
    if (type == k7zIdNumUnpackStream)
955
    {
956
      ssi->sdNumSubStreams.Data = sd->Data;
957
      numUnpackStreams = 0;
958
      numSubDigests = 0;
959
      for (i = 0; i < numFolders; i++)
960
      {
961
        UInt32 numStreams;
962
        RINOK(SzReadNumber32(sd, &numStreams));
963
        if (numUnpackStreams > numUnpackStreams + numStreams)
964
          return SZ_ERROR_UNSUPPORTED;
965
        numUnpackStreams += numStreams;
966
        if (numStreams != 0)
967
          numUnpackSizesInData += (numStreams - 1);
968
        if (numStreams != 1 || !SzBitWithVals_Check(&p->FolderCRCs, i))
969
          numSubDigests += numStreams;
970
      }
971
      ssi->sdNumSubStreams.Size = sd->Data - ssi->sdNumSubStreams.Data;
972
      continue;
973
    }
974
    if (type == k7zIdCRC || type == k7zIdSize || type == k7zIdEnd)
975
      break;
976
    RINOK(SkipData(sd));
977
  }
978
 
979
  if (!ssi->sdNumSubStreams.Data)
980
  {
981
    numSubDigests = numFolders;
982
    if (p->FolderCRCs.Defs)
983
      numSubDigests = numFolders - CountDefinedBits(p->FolderCRCs.Defs, numFolders);
984
  }
985
 
986
  ssi->NumTotalSubStreams = numUnpackStreams;
987
  ssi->NumSubDigests = numSubDigests;
988
 
989
  if (type == k7zIdSize)
990
  {
991
    ssi->sdSizes.Data = sd->Data;
992
    RINOK(SkipNumbers(sd, numUnpackSizesInData));
993
    ssi->sdSizes.Size = sd->Data - ssi->sdSizes.Data;
994
    RINOK(ReadID(sd, &type));
995
  }
996
 
997
  for (;;)
998
  {
999
    if (type == k7zIdEnd)
1000
      return SZ_OK;
1001
    if (type == k7zIdCRC)
1002
    {
1003
      ssi->sdCRCs.Data = sd->Data;
1004
      RINOK(SkipBitUi32s(sd, numSubDigests));
1005
      ssi->sdCRCs.Size = sd->Data - ssi->sdCRCs.Data;
1006
    }
1007
    else
1008
    {
1009
      RINOK(SkipData(sd));
1010
    }
1011
    RINOK(ReadID(sd, &type));
1012
  }
1013
}
1014
 
1015
static SRes SzReadStreamsInfo(CSzAr *p,
1016
    CSzData *sd,
1017
    UInt32 numFoldersMax, const CBuf *tempBufs, UInt32 numTempBufs,
1018
    UInt64 *dataOffset,
1019
    CSubStreamInfo *ssi,
1020
    ISzAlloc *alloc)
1021
{
1022
  UInt64 type;
1023
 
1024
  SzData_Clear(&ssi->sdSizes);
1025
  SzData_Clear(&ssi->sdCRCs);
1026
  SzData_Clear(&ssi->sdNumSubStreams);
1027
 
1028
  *dataOffset = 0;
1029
  RINOK(ReadID(sd, &type));
1030
  if (type == k7zIdPackInfo)
1031
  {
1032
    RINOK(ReadNumber(sd, dataOffset));
1033
    RINOK(ReadPackInfo(p, sd, alloc));
1034
    RINOK(ReadID(sd, &type));
1035
  }
1036
  if (type == k7zIdUnpackInfo)
1037
  {
1038
    RINOK(ReadUnpackInfo(p, sd, numFoldersMax, tempBufs, numTempBufs, alloc));
1039
    RINOK(ReadID(sd, &type));
1040
  }
1041
  if (type == k7zIdSubStreamsInfo)
1042
  {
1043
    RINOK(ReadSubStreamsInfo(p, sd, ssi));
1044
    RINOK(ReadID(sd, &type));
1045
  }
1046
  else
1047
  {
1048
    ssi->NumTotalSubStreams = p->NumFolders;
1049
    // ssi->NumSubDigests = 0;
1050
  }
1051
 
1052
  return (type == k7zIdEnd ? SZ_OK : SZ_ERROR_UNSUPPORTED);
1053
}
1054
 
1055
static SRes SzReadAndDecodePackedStreams(
1056
    ILookInStream *inStream,
1057
    CSzData *sd,
1058
    CBuf *tempBufs,
1059
    UInt32 numFoldersMax,
1060
    UInt64 baseOffset,
1061
    CSzAr *p,
1062
    ISzAlloc *allocTemp)
1063
{
1064
  UInt64 dataStartPos;
1065
  UInt32 fo;
1066
  CSubStreamInfo ssi;
1067
  CSzData sdCodersUnpSizes;
1068
 
1069
  RINOK(SzReadStreamsInfo(p, sd, numFoldersMax, NULL, 0, &dataStartPos, &ssi, allocTemp));
1070
 
1071
  dataStartPos += baseOffset;
1072
  if (p->NumFolders == 0)
1073
    return SZ_ERROR_ARCHIVE;
1074
 
1075
  sdCodersUnpSizes.Data = p->UnpackSizesData;
1076
  sdCodersUnpSizes.Size = p->UnpackSizesDataSize;
1077
 
1078
  for (fo = 0; fo < p->NumFolders; fo++)
1079
    Buf_Init(tempBufs + fo);
1080
 
1081
  for (fo = 0; fo < p->NumFolders; fo++)
1082
  {
1083
    CBuf *tempBuf = tempBufs + fo;
1084
    // folder = p->Folders;
1085
    // unpackSize = SzAr_GetFolderUnpackSize(p, 0);
1086
    UInt32 mix = (UInt32)p->FoSizesOffsets[fo];
1087
    UInt32 mainIndex = mix & 0xFF;
1088
    UInt32 numOutStreams = mix >> 8;
1089
    UInt32 si;
1090
    UInt64 unpackSize = 0;
1091
    p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;
1092
    for (si = 0; si < numOutStreams; si++)
1093
    {
1094
      UInt64 curSize;
1095
      RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));
1096
      if (si == mainIndex)
1097
      {
1098
        unpackSize = curSize;
1099
        break;
1100
      }
1101
    }
1102
    if (si == numOutStreams)
1103
      return SZ_ERROR_FAIL;
1104
    if ((size_t)unpackSize != unpackSize)
1105
      return SZ_ERROR_MEM;
1106
    if (!Buf_Create(tempBuf, (size_t)unpackSize, allocTemp))
1107
      return SZ_ERROR_MEM;
1108
  }
1109
 
1110
  p->FoSizesOffsets[fo] = sdCodersUnpSizes.Data - p->UnpackSizesData;
1111
 
1112
  for (fo = 0; fo < p->NumFolders; fo++)
1113
  {
1114
    const CBuf *tempBuf = tempBufs + fo;
1115
    RINOK(LookInStream_SeekTo(inStream, dataStartPos));
1116
    RINOK(SzAr_DecodeFolder(p, fo, inStream, dataStartPos, tempBuf->data, tempBuf->size, allocTemp));
1117
    if (SzBitWithVals_Check(&p->FolderCRCs, fo))
1118
      if (CrcCalc(tempBuf->data, tempBuf->size) != p->FolderCRCs.Vals[fo])
1119
        return SZ_ERROR_CRC;
1120
  }
1121
 
1122
  return SZ_OK;
1123
}
1124
 
1125
static SRes SzReadFileNames(const Byte *data, size_t size, UInt32 numFiles, size_t *offsets)
1126
{
1127
  size_t pos = 0;
1128
  *offsets++ = 0;
1129
  if (numFiles == 0)
1130
    return (size == 0) ? SZ_OK : SZ_ERROR_ARCHIVE;
1131
  if (size < 2)
1132
    return SZ_ERROR_ARCHIVE;
1133
  if (data[size - 2] != 0 || data[size - 1] != 0)
1134
    return SZ_ERROR_ARCHIVE;
1135
  do
1136
  {
1137
    const Byte *p;
1138
    if (pos == size)
1139
      return SZ_ERROR_ARCHIVE;
1140
    for (p = data + pos;
1141
      #ifdef _WIN32
1142
      *(const UInt16 *)p != 0
1143
      #else
1144
      p[0] != 0 || p[1] != 0
1145
      #endif
1146
      ; p += 2);
1147
    pos = p - data + 2;
1148
    *offsets++ = (pos >> 1);
1149
  }
1150
  while (--numFiles);
1151
  return (pos == size) ? SZ_OK : SZ_ERROR_ARCHIVE;
1152
}
1153
 
1154
static MY_NO_INLINE SRes ReadTime(CSzBitUi64s *p, UInt32 num,
1155
    CSzData *sd2,
1156
    const CBuf *tempBufs, UInt32 numTempBufs,
1157
    ISzAlloc *alloc)
1158
{
1159
  CSzData sd;
1160
  UInt32 i;
1161
  CNtfsFileTime *vals;
1162
  Byte *defs;
1163
  Byte external;
1164
 
1165
  RINOK(ReadBitVector(sd2, num, &p->Defs, alloc));
1166
 
1167
  RINOK(SzReadByte(sd2, &external));
1168
  if (external == 0)
1169
    sd = *sd2;
1170
  else
1171
  {
1172
    UInt32 index;
1173
    RINOK(SzReadNumber32(sd2, &index));
1174
    if (index >= numTempBufs)
1175
      return SZ_ERROR_ARCHIVE;
1176
    sd.Data = tempBufs[index].data;
1177
    sd.Size = tempBufs[index].size;
1178
  }
1179
 
1180
  MY_ALLOC_ZE(CNtfsFileTime, p->Vals, num, alloc);
1181
  vals = p->Vals;
1182
  defs = p->Defs;
1183
  for (i = 0; i < num; i++)
1184
    if (SzBitArray_Check(defs, i))
1185
    {
1186
      if (sd.Size < 8)
1187
        return SZ_ERROR_ARCHIVE;
1188
      vals[i].Low = GetUi32(sd.Data);
1189
      vals[i].High = GetUi32(sd.Data + 4);
1190
      SKIP_DATA2(sd, 8);
1191
    }
1192
    else
1193
      vals[i].High = vals[i].Low = 0;
1194
 
1195
  if (external == 0)
1196
    *sd2 = sd;
1197
 
1198
  return SZ_OK;
1199
}
1200
 
1201
#define NUM_ADDITIONAL_STREAMS_MAX 8
1202
 
1203
static SRes SzReadHeader2(
1204
    CSzArEx *p,   /* allocMain */
1205
    CSzData *sd,
1206
    // Byte **emptyStreamVector, /* allocTemp */
1207
    // Byte **emptyFileVector,   /* allocTemp */
1208
    // Byte **lwtVector,         /* allocTemp */
1209
    ILookInStream *inStream,
1210
    CBuf *tempBufs, UInt32 *numTempBufs,
1211
    ISzAlloc *allocMain,
1212
    ISzAlloc *allocTemp
1213
    )
1214
{
1215
  UInt64 type;
1216
  UInt32 numFiles = 0;
1217
  UInt32 numEmptyStreams = 0;
1218
  UInt32 i;
1219
  CSubStreamInfo ssi;
1220
  const Byte *emptyStreams = 0;
1221
  const Byte *emptyFiles = 0;
1222
 
1223
  SzData_Clear(&ssi.sdSizes);
1224
  SzData_Clear(&ssi.sdCRCs);
1225
  SzData_Clear(&ssi.sdNumSubStreams);
1226
 
1227
  ssi.NumSubDigests = 0;
1228
  ssi.NumTotalSubStreams = 0;
1229
 
1230
  RINOK(ReadID(sd, &type));
1231
 
1232
  if (type == k7zIdArchiveProperties)
1233
  {
1234
    for (;;)
1235
    {
1236
      UInt64 type;
1237
      RINOK(ReadID(sd, &type));
1238
      if (type == k7zIdEnd)
1239
        break;
1240
      RINOK(SkipData(sd));
1241
    }
1242
    RINOK(ReadID(sd, &type));
1243
  }
1244
 
1245
  // if (type == k7zIdAdditionalStreamsInfo)     return SZ_ERROR_UNSUPPORTED;
1246
 
1247
  if (type == k7zIdAdditionalStreamsInfo)
1248
  {
1249
    CSzAr tempAr;
1250
    SRes res;
1251
    UInt32 numTempFolders;
1252
 
1253
    SzAr_Init(&tempAr);
1254
    res = SzReadAndDecodePackedStreams(inStream, sd, tempBufs, NUM_ADDITIONAL_STREAMS_MAX,
1255
        p->startPosAfterHeader, &tempAr, allocTemp);
1256
    numTempFolders = tempAr.NumFolders;
1257
    SzAr_Free(&tempAr, allocTemp);
1258
    if (res != SZ_OK)
1259
      return res;
1260
    *numTempBufs = numTempFolders;
1261
    RINOK(ReadID(sd, &type));
1262
  }
1263
 
1264
  if (type == k7zIdMainStreamsInfo)
1265
  {
1266
    RINOK(SzReadStreamsInfo(&p->db, sd, (UInt32)1 << 30, tempBufs, *numTempBufs,
1267
        &p->dataPos, &ssi, allocMain));
1268
    p->dataPos += p->startPosAfterHeader;
1269
    RINOK(ReadID(sd, &type));
1270
  }
1271
 
1272
  if (type == k7zIdEnd)
1273
  {
1274
    // *sd2 = sd;
1275
    return SZ_OK;
1276
  }
1277
  if (type != k7zIdFilesInfo)
1278
    return SZ_ERROR_ARCHIVE;
1279
 
1280
  RINOK(SzReadNumber32(sd, &numFiles));
1281
  p->NumFiles = numFiles;
1282
 
1283
  for (;;)
1284
  {
1285
    UInt64 type;
1286
    UInt64 size;
1287
    RINOK(ReadID(sd, &type));
1288
    if (type == k7zIdEnd)
1289
      break;
1290
    RINOK(ReadNumber(sd, &size));
1291
    if (size > sd->Size)
1292
      return SZ_ERROR_ARCHIVE;
1293
 
1294
    if (type >= ((UInt32)1 << 8))
1295
    {
1296
      SKIP_DATA(sd, size);
1297
    }
1298
    else switch((unsigned)type)
1299
    {
1300
      case k7zIdName:
1301
      {
1302
        size_t namesSize;
1303
        const Byte *namesData;
1304
        Byte external;
1305
 
1306
        SZ_READ_BYTE(external);
1307
        if (external == 0)
1308
        {
1309
          namesSize = (size_t)size - 1;
1310
          namesData = sd->Data;
1311
        }
1312
        else
1313
        {
1314
          UInt32 index;
1315
          RINOK(SzReadNumber32(sd, &index));
1316
          if (index >= *numTempBufs)
1317
            return SZ_ERROR_ARCHIVE;
1318
          namesData = (tempBufs)[index].data;
1319
          namesSize = (tempBufs)[index].size;
1320
        }
1321
 
1322
        if ((namesSize & 1) != 0)
1323
          return SZ_ERROR_ARCHIVE;
1324
        MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
1325
        MY_ALLOC_ZE_AND_CPY(p->FileNames, namesSize, namesData, allocMain);
1326
        RINOK(SzReadFileNames(p->FileNames, namesSize, numFiles, p->FileNameOffsets))
1327
        if (external == 0)
1328
        {
1329
          SKIP_DATA(sd, namesSize);
1330
        }
1331
        break;
1332
      }
1333
      case k7zIdEmptyStream:
1334
      {
1335
        RINOK(RememberBitVector(sd, numFiles, &emptyStreams));
1336
        numEmptyStreams = CountDefinedBits(emptyStreams, numFiles);
1337
        break;
1338
      }
1339
      case k7zIdEmptyFile:
1340
      {
1341
        RINOK(RememberBitVector(sd, numEmptyStreams, &emptyFiles));
1342
        break;
1343
      }
1344
      case k7zIdWinAttrib:
1345
      {
1346
        Byte external;
1347
        CSzData sdSwitch;
1348
        CSzData *sdPtr;
1349
        SzBitUi32s_Free(&p->Attribs, allocMain);
1350
        RINOK(ReadBitVector(sd, numFiles, &p->Attribs.Defs, allocMain));
1351
 
1352
        SZ_READ_BYTE(external);
1353
        if (external == 0)
1354
          sdPtr = sd;
1355
        else
1356
        {
1357
          UInt32 index;
1358
          RINOK(SzReadNumber32(sd, &index));
1359
          if (index >= *numTempBufs)
1360
            return SZ_ERROR_ARCHIVE;
1361
          sdSwitch.Data = (tempBufs)[index].data;
1362
          sdSwitch.Size = (tempBufs)[index].size;
1363
          sdPtr = &sdSwitch;
1364
        }
1365
        RINOK(ReadUi32s(sdPtr, numFiles, &p->Attribs, allocMain));
1366
        break;
1367
      }
1368
      /*
1369
      case k7zParent:
1370
      {
1371
        SzBitUi32s_Free(&p->Parents, allocMain);
1372
        RINOK(ReadBitVector(sd, numFiles, &p->Parents.Defs, allocMain));
1373
        RINOK(SzReadSwitch(sd));
1374
        RINOK(ReadUi32s(sd, numFiles, &p->Parents, allocMain));
1375
        break;
1376
      }
1377
      */
1378
      case k7zIdMTime: RINOK(ReadTime(&p->MTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1379
      case k7zIdCTime: RINOK(ReadTime(&p->CTime, numFiles, sd, tempBufs, *numTempBufs, allocMain)); break;
1380
      default:
1381
      {
1382
        SKIP_DATA(sd, size);
1383
      }
1384
    }
1385
  }
1386
 
1387
  if (numFiles - numEmptyStreams != ssi.NumTotalSubStreams)
1388
    return SZ_ERROR_ARCHIVE;
1389
 
1390
  for (;;)
1391
  {
1392
    UInt64 type;
1393
    RINOK(ReadID(sd, &type));
1394
    if (type == k7zIdEnd)
1395
      break;
1396
    RINOK(SkipData(sd));
1397
  }
1398
 
1399
  {
1400
    UInt32 emptyFileIndex = 0;
1401
 
1402
    UInt32 folderIndex = 0;
1403
    UInt32 indexInFolder = 0;
1404
    UInt64 unpackPos = 0;
1405
    const Byte *digestsDefs = 0;
1406
    const Byte *digestsVals = 0;
1407
    UInt32 digestsValsIndex = 0;
1408
    UInt32 digestIndex;
1409
    Byte allDigestsDefined = 0;
1410
    UInt32 curNumSubStreams = (UInt32)(Int32)-1;
1411
    Byte isDirMask = 0;
1412
    Byte crcMask = 0;
1413
    Byte mask = 0x80;
1414
    // size_t unpSizesOffset = 0;
1415
    CSzData sdCodersUnpSizes;
1416
    sdCodersUnpSizes.Data = p->db.UnpackSizesData;
1417
    sdCodersUnpSizes.Size = p->db.UnpackSizesDataSize;
1418
 
1419
    MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders + 1, allocMain);
1420
    MY_ALLOC_ZE(UInt32, p->FileIndexToFolderIndexMap, p->NumFiles, allocMain);
1421
    MY_ALLOC(UInt64, p->UnpackPositions, p->NumFiles + 1, allocMain);
1422
    MY_ALLOC_ZE(Byte, p->IsDirs, (p->NumFiles + 7) >> 3, allocMain);
1423
 
1424
    RINOK(SzBitUi32s_Alloc(&p->CRCs, p->NumFiles, allocMain));
1425
 
1426
    if (ssi.sdCRCs.Size != 0)
1427
    {
1428
      RINOK(SzReadByte(&ssi.sdCRCs, &allDigestsDefined));
1429
      if (allDigestsDefined)
1430
        digestsVals = ssi.sdCRCs.Data;
1431
      else
1432
      {
1433
        size_t numBytes = (ssi.NumSubDigests + 7) >> 3;
1434
        digestsDefs = ssi.sdCRCs.Data;
1435
        digestsVals = digestsDefs + numBytes;
1436
      }
1437
    }
1438
 
1439
    digestIndex = 0;
1440
    for (i = 0; i < numFiles; i++, mask >>= 1)
1441
    {
1442
      if (mask == 0)
1443
      {
1444
        UInt32 byteIndex = (i - 1) >> 3;
1445
        p->IsDirs[byteIndex] = isDirMask;
1446
        p->CRCs.Defs[byteIndex] = crcMask;
1447
        isDirMask = 0;
1448
        crcMask = 0;
1449
        mask = 0x80;
1450
      }
1451
 
1452
      p->UnpackPositions[i] = unpackPos;
1453
      p->CRCs.Vals[i] = 0;
1454
      // p->CRCs.Defs[i] = 0;
1455
      if (emptyStreams && SzBitArray_Check(emptyStreams , i))
1456
      {
1457
        if (!emptyFiles || !SzBitArray_Check(emptyFiles, emptyFileIndex))
1458
          isDirMask |= mask;
1459
        emptyFileIndex++;
1460
        if (indexInFolder == 0)
1461
        {
1462
          p->FileIndexToFolderIndexMap[i] = (UInt32)-1;
1463
          continue;
1464
        }
1465
      }
1466
      if (indexInFolder == 0)
1467
      {
1468
        /*
1469
        v3.13 incorrectly worked with empty folders
1470
        v4.07: Loop for skipping empty folders
1471
        */
1472
        for (;;)
1473
        {
1474
          if (folderIndex >= p->db.NumFolders)
1475
            return SZ_ERROR_ARCHIVE;
1476
          p->FolderStartFileIndex[folderIndex] = i;
1477
          if (curNumSubStreams == (UInt32)(Int32)-1);
1478
          {
1479
            curNumSubStreams = 1;
1480
            if (ssi.sdNumSubStreams.Data != 0)
1481
            {
1482
              RINOK(SzReadNumber32(&ssi.sdNumSubStreams, &curNumSubStreams));
1483
            }
1484
          }
1485
          if (curNumSubStreams != 0)
1486
            break;
1487
          curNumSubStreams = (UInt32)(Int32)-1;
1488
          folderIndex++; // check it
1489
        }
1490
      }
1491
      p->FileIndexToFolderIndexMap[i] = folderIndex;
1492
      if (emptyStreams && SzBitArray_Check(emptyStreams , i))
1493
        continue;
1494
 
1495
      indexInFolder++;
1496
      if (indexInFolder >= curNumSubStreams)
1497
      {
1498
        UInt64 folderUnpackSize = 0;
1499
        UInt64 startFolderUnpackPos;
1500
        {
1501
          UInt32 mix = (UInt32)p->db.FoSizesOffsets[folderIndex];
1502
          UInt32 mainIndex = mix & 0xFF;
1503
          UInt32 numOutStreams = mix >> 8;
1504
          UInt32 si;
1505
          p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;
1506
          for (si = 0; si < numOutStreams; si++)
1507
          {
1508
            UInt64 curSize;
1509
            RINOK(ReadNumber(&sdCodersUnpSizes, &curSize));
1510
            if (si == mainIndex)
1511
            {
1512
              folderUnpackSize = curSize;
1513
              break;
1514
            }
1515
          }
1516
          if (si == numOutStreams)
1517
            return SZ_ERROR_FAIL;
1518
        }
1519
 
1520
        // UInt64 folderUnpackSize = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1521
        startFolderUnpackPos = p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];
1522
        if (folderUnpackSize < unpackPos - startFolderUnpackPos)
1523
          return SZ_ERROR_ARCHIVE;
1524
        unpackPos = startFolderUnpackPos + folderUnpackSize;
1525
 
1526
        if (curNumSubStreams == 1 && SzBitWithVals_Check(&p->db.FolderCRCs, i))
1527
        {
1528
          p->CRCs.Vals[i] = p->db.FolderCRCs.Vals[folderIndex];
1529
          crcMask |= mask;
1530
        }
1531
        else if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1532
        {
1533
          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1534
          digestsValsIndex++;
1535
          crcMask |= mask;
1536
        }
1537
        folderIndex++;
1538
        indexInFolder = 0;
1539
      }
1540
      else
1541
      {
1542
        UInt64 v;
1543
        RINOK(ReadNumber(&ssi.sdSizes, &v));
1544
        unpackPos += v;
1545
        if (allDigestsDefined || (digestsDefs && SzBitArray_Check(digestsDefs, digestIndex)))
1546
        {
1547
          p->CRCs.Vals[i] = GetUi32(digestsVals + (size_t)digestsValsIndex * 4);
1548
          digestsValsIndex++;
1549
          crcMask |= mask;
1550
        }
1551
      }
1552
    }
1553
    if (mask != 0x80)
1554
    {
1555
      UInt32 byteIndex = (i - 1) >> 3;
1556
      p->IsDirs[byteIndex] = isDirMask;
1557
      p->CRCs.Defs[byteIndex] = crcMask;
1558
    }
1559
    p->UnpackPositions[i] = unpackPos;
1560
    p->FolderStartFileIndex[folderIndex] = i;
1561
    p->db.FoSizesOffsets[folderIndex] = sdCodersUnpSizes.Data - p->db.UnpackSizesData;
1562
  }
1563
  return SZ_OK;
1564
}
1565
 
1566
static SRes SzReadHeader(
1567
    CSzArEx *p,
1568
    CSzData *sd,
1569
    ILookInStream *inStream,
1570
    ISzAlloc *allocMain
1571
    ,ISzAlloc *allocTemp
1572
    )
1573
{
1574
  // Byte *emptyStreamVector = 0;
1575
  // Byte *emptyFileVector = 0;
1576
  // Byte *lwtVector = 0;
1577
  UInt32 i;
1578
  UInt32 numTempBufs = 0;
1579
  SRes res;
1580
  CBuf tempBufs[NUM_ADDITIONAL_STREAMS_MAX];
1581
 
1582
  for (i = 0; i < NUM_ADDITIONAL_STREAMS_MAX; i++)
1583
    Buf_Init(tempBufs + i);
1584
  // SzBitUi32s_Init(&digests);
1585
 
1586
  res = SzReadHeader2(p, sd,
1587
      // &emptyStreamVector,
1588
      // &emptyFileVector,
1589
      // &lwtVector,
1590
      inStream,
1591
      tempBufs, &numTempBufs,
1592
      allocMain, allocTemp
1593
      );
1594
 
1595
  for (i = 0; i < numTempBufs; i++)
1596
    Buf_Free(tempBufs + i, allocTemp);
1597
 
1598
  // IAlloc_Free(allocTemp, emptyStreamVector);
1599
  // IAlloc_Free(allocTemp, emptyFileVector);
1600
  // IAlloc_Free(allocTemp, lwtVector);
1601
 
1602
  RINOK(res);
1603
  {
1604
    if (sd->Size != 0)
1605
      return SZ_ERROR_FAIL;
1606
  }
1607
 
1608
  return res;
1609
}
1610
 
1611
/*
1612
static UInt64 SzAr_GetFolderUnpackSize(const CSzAr *p, UInt32 folderIndex)
1613
{
1614
  const CSzFolder2 *f = p->Folders + folderIndex;
1615
 
1616
  // return p->CoderUnpackSizes[f->StartCoderUnpackSizesIndex + f->IndexOfMainOutStream];
1617
 
1618
  UInt32 si;
1619
  CSzData sdCodersUnpSizes;
1620
  sdCodersUnpSizes.Data = p->UnpackSizesData + f->UnpackSizeDataOffset;
1621
  sdCodersUnpSizes.Size = p->UnpackSizesDataSize - f->UnpackSizeDataOffset;
1622
  for (si = 0; si < numOutStreams; si++)
1623
  {
1624
    UInt64 curSize;
1625
    ReadNumber(&sdCodersUnpSizes, &curSize);
1626
    if (si == mainIndex)
1627
      return curSize;
1628
  }
1629
  return 0;
1630
}
1631
*/
1632
 
1633
static SRes SzArEx_Open2(
1634
    CSzArEx *p,
1635
    ILookInStream *inStream,
1636
    ISzAlloc *allocMain,
1637
    ISzAlloc *allocTemp)
1638
{
1639
  Byte header[k7zStartHeaderSize];
1640
  Int64 startArcPos;
1641
  UInt64 nextHeaderOffset, nextHeaderSize;
1642
  size_t nextHeaderSizeT;
1643
  UInt32 nextHeaderCRC;
1644
  CBuf buf;
1645
  SRes res;
1646
 
1647
  startArcPos = 0;
1648
  RINOK(inStream->Seek(inStream, &startArcPos, SZ_SEEK_CUR));
1649
 
1650
  RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE));
1651
 
1652
  if (!TestSignatureCandidate(header))
1653
    return SZ_ERROR_NO_ARCHIVE;
1654
  if (header[6] != k7zMajorVersion)
1655
    return SZ_ERROR_UNSUPPORTED;
1656
 
1657
  nextHeaderOffset = GetUi64(header + 12);
1658
  nextHeaderSize = GetUi64(header + 20);
1659
  nextHeaderCRC = GetUi32(header + 28);
1660
 
1661
  p->startPosAfterHeader = startArcPos + k7zStartHeaderSize;
1662
 
1663
  if (CrcCalc(header + 12, 20) != GetUi32(header + 8))
1664
    return SZ_ERROR_CRC;
1665
 
1666
  nextHeaderSizeT = (size_t)nextHeaderSize;
1667
  if (nextHeaderSizeT != nextHeaderSize)
1668
    return SZ_ERROR_MEM;
1669
  if (nextHeaderSizeT == 0)
1670
    return SZ_OK;
1671
  if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize ||
1672
      nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize)
1673
    return SZ_ERROR_NO_ARCHIVE;
1674
 
1675
  {
1676
    Int64 pos = 0;
1677
    RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END));
1678
    if ((UInt64)pos < startArcPos + nextHeaderOffset ||
1679
        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset ||
1680
        (UInt64)pos < startArcPos + k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize)
1681
      return SZ_ERROR_INPUT_EOF;
1682
  }
1683
 
1684
  RINOK(LookInStream_SeekTo(inStream, startArcPos + k7zStartHeaderSize + nextHeaderOffset));
1685
 
1686
  if (!Buf_Create(&buf, nextHeaderSizeT, allocTemp))
1687
    return SZ_ERROR_MEM;
1688
 
1689
  res = LookInStream_Read(inStream, buf.data, nextHeaderSizeT);
1690
  if (res == SZ_OK)
1691
  {
1692
    res = SZ_ERROR_ARCHIVE;
1693
    if (CrcCalc(buf.data, nextHeaderSizeT) == nextHeaderCRC)
1694
    {
1695
      CSzData sd;
1696
      UInt64 type;
1697
      sd.Data = buf.data;
1698
      sd.Size = buf.size;
1699
      res = ReadID(&sd, &type);
1700
      if (res == SZ_OK && type == k7zIdEncodedHeader)
1701
      {
1702
        CSzAr tempAr;
1703
        CBuf tempBuf;
1704
        Buf_Init(&tempBuf);
1705
 
1706
        SzAr_Init(&tempAr);
1707
        res = SzReadAndDecodePackedStreams(inStream, &sd, &tempBuf, 1, p->startPosAfterHeader, &tempAr, allocTemp);
1708
        SzAr_Free(&tempAr, allocTemp);
1709
 
1710
        if (res != SZ_OK)
1711
        {
1712
          Buf_Free(&tempBuf, allocTemp);
1713
        }
1714
        else
1715
        {
1716
          Buf_Free(&buf, allocTemp);
1717
          buf.data = tempBuf.data;
1718
          buf.size = tempBuf.size;
1719
          sd.Data = buf.data;
1720
          sd.Size = buf.size;
1721
          res = ReadID(&sd, &type);
1722
        }
1723
      }
1724
      if (res == SZ_OK)
1725
      {
1726
        if (type == k7zIdHeader)
1727
        {
1728
          /*
1729
          CSzData sd2;
1730
          unsigned ttt;
1731
          for (ttt = 0; ttt < 40000; ttt++)
1732
          {
1733
            SzArEx_Free(p, allocMain);
1734
            sd2 = sd;
1735
            res = SzReadHeader(p, &sd2, inStream, allocMain, allocTemp);
1736
            if (res != SZ_OK)
1737
              break;
1738
          }
1739
          */
1740
          res = SzReadHeader(p, &sd, inStream, allocMain, allocTemp);
1741
        }
1742
        else
1743
          res = SZ_ERROR_UNSUPPORTED;
1744
      }
1745
    }
1746
  }
1747
  Buf_Free(&buf, allocTemp);
1748
  return res;
1749
}
1750
 
1751
// #include 
1752
 
1753
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream,
1754
    ISzAlloc *allocMain, ISzAlloc *allocTemp)
1755
{
1756
  SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp);
1757
  if (res != SZ_OK)
1758
    SzArEx_Free(p, allocMain);
1759
  // printf ("\nrrr=%d\n", rrr);
1760
  return res;
1761
}
1762
 
1763
SRes SzArEx_Extract(
1764
    const CSzArEx *p,
1765
    ILookInStream *inStream,
1766
    UInt32 fileIndex,
1767
    UInt32 *blockIndex,
1768
    Byte **tempBuf,
1769
    size_t *outBufferSize,
1770
    size_t *offset,
1771
    size_t *outSizeProcessed,
1772
    ISzAlloc *allocMain,
1773
    ISzAlloc *allocTemp)
1774
{
1775
  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
1776
  SRes res = SZ_OK;
1777
  *offset = 0;
1778
  *outSizeProcessed = 0;
1779
  if (folderIndex == (UInt32)-1)
1780
  {
1781
    IAlloc_Free(allocMain, *tempBuf);
1782
    *blockIndex = folderIndex;
1783
    *tempBuf = 0;
1784
    *outBufferSize = 0;
1785
    return SZ_OK;
1786
  }
1787
 
1788
  if (*tempBuf == 0 || *blockIndex != folderIndex)
1789
  {
1790
    // UInt64 unpackSizeSpec = SzAr_GetFolderUnpackSize(&p->db, folderIndex);
1791
    UInt64 unpackSizeSpec =
1792
        p->UnpackPositions[p->FolderStartFileIndex[folderIndex + 1]] -
1793
        p->UnpackPositions[p->FolderStartFileIndex[folderIndex]];
1794
    size_t unpackSize = (size_t)unpackSizeSpec;
1795
 
1796
    if (unpackSize != unpackSizeSpec)
1797
      return SZ_ERROR_MEM;
1798
    *blockIndex = folderIndex;
1799
    IAlloc_Free(allocMain, *tempBuf);
1800
    *tempBuf = 0;
1801
 
1802
    // RINOK(LookInStream_SeekTo(inStream, startOffset));
1803
 
1804
    if (res == SZ_OK)
1805
    {
1806
      *outBufferSize = unpackSize;
1807
      if (unpackSize != 0)
1808
      {
1809
        *tempBuf = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
1810
        if (*tempBuf == 0)
1811
          res = SZ_ERROR_MEM;
1812
      }
1813
      if (res == SZ_OK)
1814
      {
1815
        res = SzAr_DecodeFolder(&p->db, folderIndex,
1816
          inStream,
1817
          p->dataPos,
1818
          *tempBuf, unpackSize, allocTemp);
1819
        if (res == SZ_OK)
1820
        {
1821
          if (SzBitWithVals_Check(&p->db.FolderCRCs, folderIndex))
1822
          {
1823
            if (CrcCalc(*tempBuf, unpackSize) != p->db.FolderCRCs.Vals[folderIndex])
1824
              res = SZ_ERROR_CRC;
1825
          }
1826
        }
1827
      }
1828
    }
1829
  }
1830
  if (res == SZ_OK)
1831
  {
1832
    UInt64 unpackPos = p->UnpackPositions[fileIndex];
1833
    *offset = (size_t)(unpackPos - p->UnpackPositions[p->FolderStartFileIndex[folderIndex]]);
1834
    *outSizeProcessed = (size_t)(p->UnpackPositions[fileIndex + 1] - unpackPos);
1835
    if (*offset + *outSizeProcessed > *outBufferSize)
1836
      return SZ_ERROR_FAIL;
1837
    if (SzBitWithVals_Check(&p->CRCs, fileIndex) && CrcCalc(*tempBuf + *offset, *outSizeProcessed) != p->CRCs.Vals[fileIndex])
1838
      res = SZ_ERROR_CRC;
1839
  }
1840
  return res;
1841
}
1842
 
1843
 
1844
size_t SzArEx_GetFileNameUtf16(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1845
{
1846
  size_t offs = p->FileNameOffsets[fileIndex];
1847
  size_t len = p->FileNameOffsets[fileIndex + 1] - offs;
1848
  if (dest != 0)
1849
  {
1850
    size_t i;
1851
    const Byte *src = p->FileNames + offs * 2;
1852
    for (i = 0; i < len; i++)
1853
      dest[i] = GetUi16(src + i * 2);
1854
  }
1855
  return len;
1856
}
1857
 
1858
/*
1859
size_t SzArEx_GetFullNameLen(const CSzArEx *p, size_t fileIndex)
1860
{
1861
  size_t len;
1862
  if (!p->FileNameOffsets)
1863
    return 1;
1864
  len = 0;
1865
  for (;;)
1866
  {
1867
    UInt32 parent = (UInt32)(Int32)-1;
1868
    len += p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1869
    if SzBitWithVals_Check(&p->Parents, fileIndex)
1870
      parent = p->Parents.Vals[fileIndex];
1871
    if (parent == (UInt32)(Int32)-1)
1872
      return len;
1873
    fileIndex = parent;
1874
  }
1875
}
1876
 
1877
UInt16 *SzArEx_GetFullNameUtf16_Back(const CSzArEx *p, size_t fileIndex, UInt16 *dest)
1878
{
1879
  Bool needSlash;
1880
  if (!p->FileNameOffsets)
1881
  {
1882
    *(--dest) = 0;
1883
    return dest;
1884
  }
1885
  needSlash = False;
1886
  for (;;)
1887
  {
1888
    UInt32 parent = (UInt32)(Int32)-1;
1889
    size_t curLen = p->FileNameOffsets[fileIndex + 1] - p->FileNameOffsets[fileIndex];
1890
    SzArEx_GetFileNameUtf16(p, fileIndex, dest - curLen);
1891
    if (needSlash)
1892
      *(dest - 1) = '/';
1893
    needSlash = True;
1894
    dest -= curLen;
1895
 
1896
    if SzBitWithVals_Check(&p->Parents, fileIndex)
1897
      parent = p->Parents.Vals[fileIndex];
1898
    if (parent == (UInt32)(Int32)-1)
1899
      return dest;
1900
    fileIndex = parent;
1901
  }
1902
}
1903
*/