~ubuntu-branches/ubuntu/precise/p7zip/precise-updates

« back to all changes in this revision

Viewing changes to CPP/7zip/Archive/MubHandler.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mohammed Adnène Trojette
  • Date: 2009-02-14 20:12:27 UTC
  • mfrom: (1.1.11 upstream) (2.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090214201227-go63qxm9ozfdma60
Tags: 4.65~dfsg.1-1
* New upstream release.
* Remove wx2.8 Build-Depends added by mistakes (7zG is not yet
  intended to be built).
* Use dh_clean without -k.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// MubHandler.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
#include "../../../C/CpuArch.h"
 
6
 
 
7
#include "Common/ComTry.h"
 
8
 
 
9
#include "Windows/PropVariant.h"
 
10
 
 
11
#include "../Common/LimitedStreams.h"
 
12
#include "../Common/ProgressUtils.h"
 
13
#include "../Common/RegisterArc.h"
 
14
#include "../Common/StreamUtils.h"
 
15
 
 
16
#include "../Compress/CopyCoder.h"
 
17
 
 
18
#define Get32(p) GetBe32(p)
 
19
 
 
20
namespace NArchive {
 
21
namespace NMub {
 
22
 
 
23
struct CItem
 
24
{
 
25
  UInt32 Type;
 
26
  UInt32 SubType;
 
27
  UInt64 Offset;
 
28
  UInt64 Size;
 
29
  UInt32 Align;
 
30
  bool IsTail;
 
31
};
 
32
 
 
33
const UInt32 kNumFilesMax = 10;
 
34
 
 
35
class CHandler:
 
36
  public IInArchive,
 
37
  public CMyUnknownImp
 
38
{
 
39
  UInt64 _startPos;
 
40
  CMyComPtr<IInStream> _inStream;
 
41
  UInt32 _numItems;
 
42
  CItem _items[kNumFilesMax + 1];
 
43
  HRESULT Open2(IInStream *stream);
 
44
public:
 
45
  MY_UNKNOWN_IMP1(IInArchive)
 
46
  INTERFACE_IInArchive(;)
 
47
};
 
48
 
 
49
STATPROPSTG kProps[] =
 
50
{
 
51
  { NULL, kpidSize, VT_UI8},
 
52
  { NULL, kpidPackSize, VT_UI8}
 
53
};
 
54
 
 
55
IMP_IInArchive_Props
 
56
IMP_IInArchive_ArcProps_NO
 
57
 
 
58
#define MACH_ARCH_ABI64  0x1000000
 
59
#define MACH_MACHINE_386   7
 
60
#define MACH_MACHINE_ARM   12
 
61
#define MACH_MACHINE_SPARC 14
 
62
#define MACH_MACHINE_PPC   18
 
63
 
 
64
#define MACH_MACHINE_PPC64 (MACH_MACHINE_PPC | MACH_ARCH_ABI64)
 
65
#define MACH_MACHINE_AMD64 (MACH_MACHINE_386 | MACH_ARCH_ABI64)
 
66
 
 
67
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
 
68
{
 
69
  NWindows::NCOM::CPropVariant prop;
 
70
  const CItem &item = _items[index];
 
71
  switch(propID)
 
72
  {
 
73
    case kpidExtension:
 
74
    {
 
75
      const wchar_t *ext;
 
76
      if (item.IsTail)
 
77
        ext = L"tail";
 
78
      else
 
79
      {
 
80
        switch(item.Type)
 
81
        {
 
82
          case MACH_MACHINE_386:   ext = L"86";    break;
 
83
          case MACH_MACHINE_ARM:   ext = L"arm";   break;
 
84
          case MACH_MACHINE_SPARC: ext = L"sparc"; break;
 
85
          case MACH_MACHINE_PPC:   ext = L"ppc";   break;
 
86
          case MACH_MACHINE_PPC64: ext = L"ppc64"; break;
 
87
          case MACH_MACHINE_AMD64: ext = L"x64";   break;
 
88
          default: ext = L"unknown"; break;
 
89
        }
 
90
      }
 
91
      prop = ext;
 
92
      break;
 
93
    }
 
94
    case kpidSize:
 
95
    case kpidPackSize:
 
96
      prop = (UInt64)item.Size;
 
97
      break;
 
98
  }
 
99
  prop.Detach(value);
 
100
  return S_OK;
 
101
}
 
102
 
 
103
#define MACH_TYPE_ABI64 (1 << 24)
 
104
#define MACH_SUBTYPE_ABI64 (1 << 31)
 
105
 
 
106
HRESULT CHandler::Open2(IInStream *stream)
 
107
{
 
108
  RINOK(stream->Seek(0, STREAM_SEEK_SET, &_startPos));
 
109
 
 
110
  const UInt32 kHeaderSize = 8;
 
111
  const UInt32 kRecordSize = 5 * 4;
 
112
  const UInt32 kBufSize = kHeaderSize + kNumFilesMax * kRecordSize;
 
113
  Byte buf[kBufSize];
 
114
  size_t processed = kBufSize;
 
115
  RINOK(ReadStream(stream, buf, &processed));
 
116
  if (processed < kHeaderSize)
 
117
    return S_FALSE;
 
118
  UInt32 num = Get32(buf + 4);
 
119
  if (Get32(buf) != 0xCAFEBABE || num > kNumFilesMax || processed < kHeaderSize + num * kRecordSize)
 
120
    return S_FALSE;
 
121
  UInt64 endPosMax = kHeaderSize;
 
122
  for (UInt32 i = 0; i < num; i++)
 
123
  {
 
124
    const Byte *p = buf + kHeaderSize + i * kRecordSize;
 
125
    CItem &sb = _items[i];
 
126
    sb.IsTail = false;
 
127
    sb.Type = Get32(p);
 
128
    sb.SubType = Get32(p + 4);
 
129
    sb.Offset = Get32(p + 8);
 
130
    sb.Size = Get32(p + 12);
 
131
    sb.Align = Get32(p + 16);
 
132
 
 
133
    if ((sb.Type & ~MACH_TYPE_ABI64) >= 0x100 ||
 
134
        (sb.SubType & ~MACH_SUBTYPE_ABI64) >= 0x100 ||
 
135
        sb.Align > 31)
 
136
      return S_FALSE;
 
137
 
 
138
    UInt64 endPos = (UInt64)sb.Offset + sb.Size;
 
139
    if (endPos > endPosMax)
 
140
      endPosMax = endPos;
 
141
  }
 
142
  UInt64 fileSize;
 
143
  RINOK(stream->Seek(0, STREAM_SEEK_END, &fileSize));
 
144
  fileSize -= _startPos;
 
145
  _numItems = num;
 
146
  if (fileSize > endPosMax)
 
147
  {
 
148
    CItem &sb = _items[_numItems++];
 
149
    sb.IsTail = true;
 
150
    sb.Type = 0;
 
151
    sb.SubType = 0;
 
152
    sb.Offset = endPosMax;
 
153
    sb.Size = fileSize - endPosMax;
 
154
    sb.Align = 0;
 
155
  }
 
156
  return S_OK;
 
157
}
 
158
 
 
159
STDMETHODIMP CHandler::Open(IInStream *inStream,
 
160
    const UInt64 * /* maxCheckStartPosition */,
 
161
    IArchiveOpenCallback * /* openArchiveCallback */)
 
162
{
 
163
  COM_TRY_BEGIN
 
164
  Close();
 
165
  try
 
166
  {
 
167
    if (Open2(inStream) != S_OK)
 
168
      return S_FALSE;
 
169
    _inStream = inStream;
 
170
  }
 
171
  catch(...) { return S_FALSE; }
 
172
  return S_OK;
 
173
  COM_TRY_END
 
174
}
 
175
 
 
176
STDMETHODIMP CHandler::Close()
 
177
{
 
178
  _inStream.Release();
 
179
  _numItems = 0;
 
180
  return S_OK;
 
181
}
 
182
 
 
183
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
 
184
{
 
185
  *numItems = _numItems;
 
186
  return S_OK;
 
187
}
 
188
 
 
189
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
 
190
    Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
 
191
{
 
192
  COM_TRY_BEGIN
 
193
  bool testMode = (_aTestMode != 0);
 
194
  bool allFilesMode = (numItems == UInt32(-1));
 
195
  if (allFilesMode)
 
196
    numItems = _numItems;
 
197
  if (numItems == 0)
 
198
    return S_OK;
 
199
  UInt64 totalSize = 0;
 
200
  UInt32 i;
 
201
  for (i = 0; i < numItems; i++)
 
202
    totalSize += _items[allFilesMode ? i : indices[i]].Size;
 
203
  extractCallback->SetTotal(totalSize);
 
204
 
 
205
  UInt64 currentTotalSize = 0;
 
206
  UInt64 currentItemSize;
 
207
  
 
208
  NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
 
209
  CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
 
210
 
 
211
  CLocalProgress *lps = new CLocalProgress;
 
212
  CMyComPtr<ICompressProgressInfo> progress = lps;
 
213
  lps->Init(extractCallback, false);
 
214
 
 
215
  CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
 
216
  CMyComPtr<ISequentialInStream> inStream(streamSpec);
 
217
  streamSpec->SetStream(_inStream);
 
218
 
 
219
  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
 
220
  {
 
221
    lps->InSize = lps->OutSize = currentTotalSize;
 
222
    RINOK(lps->SetCur());
 
223
    CMyComPtr<ISequentialOutStream> realOutStream;
 
224
    Int32 askMode = testMode ?
 
225
        NArchive::NExtract::NAskMode::kTest :
 
226
        NArchive::NExtract::NAskMode::kExtract;
 
227
    UInt32 index = allFilesMode ? i : indices[i];
 
228
    const CItem &item = _items[index];
 
229
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
 
230
    currentItemSize = item.Size;
 
231
    
 
232
    
 
233
    
 
234
    
 
235
    
 
236
    
 
237
    if (!testMode && (!realOutStream))
 
238
      continue;
 
239
    RINOK(extractCallback->PrepareOperation(askMode));
 
240
    if (testMode)
 
241
    {
 
242
      RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
 
243
      continue;
 
244
    }
 
245
    RINOK(_inStream->Seek(_startPos + item.Offset, STREAM_SEEK_SET, NULL));
 
246
    streamSpec->Init(item.Size);
 
247
    RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
 
248
    realOutStream.Release();
 
249
    RINOK(extractCallback->SetOperationResult((copyCoderSpec->TotalSize == item.Size) ?
 
250
        NArchive::NExtract::NOperationResult::kOK:
 
251
        NArchive::NExtract::NOperationResult::kDataError));
 
252
  }
 
253
  return S_OK;
 
254
  COM_TRY_END
 
255
}
 
256
 
 
257
static IInArchive *CreateArc() { return new CHandler; }
 
258
 
 
259
static CArcInfo g_ArcInfo =
 
260
  { L"Mub", L"", 0, 0xE2, { 0xCA, 0xFE, 0xBA, 0xBE, 0, 0, 0 }, 7, false, CreateArc, 0 };
 
261
 
 
262
REGISTER_ARC(Mub)
 
263
 
 
264
}}