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

« back to all changes in this revision

Viewing changes to CPP/7zip/Archive/Hfs/HfsHandler.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
// HfsHandler.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
#include "Common/ComTry.h"
 
6
#include "Windows/PropVariant.h"
 
7
#include "../../Common/StreamUtils.h"
 
8
#include "HfsHandler.h"
 
9
 
 
10
namespace NArchive {
 
11
namespace NHfs {
 
12
 
 
13
STATPROPSTG kProps[] =
 
14
{
 
15
  { NULL, kpidPath, VT_BSTR},
 
16
  { NULL, kpidIsDir, VT_BOOL},
 
17
  { NULL, kpidSize, VT_UI8},
 
18
  { NULL, kpidPackSize, VT_UI8},
 
19
  { NULL, kpidCTime, VT_FILETIME},
 
20
  { NULL, kpidMTime, VT_FILETIME},
 
21
  { NULL, kpidATime, VT_FILETIME}
 
22
};
 
23
 
 
24
STATPROPSTG kArcProps[] =
 
25
{
 
26
  { NULL, kpidMethod, VT_BSTR},
 
27
  { NULL, kpidClusterSize, VT_UI4},
 
28
  { NULL, kpidFreeSpace, VT_UI8},
 
29
  { NULL, kpidCTime, VT_FILETIME},
 
30
  { NULL, kpidMTime, VT_FILETIME}
 
31
};
 
32
 
 
33
IMP_IInArchive_Props
 
34
IMP_IInArchive_ArcProps
 
35
 
 
36
static void HfsTimeToProp(UInt32 hfsTime, NWindows::NCOM::CPropVariant &prop)
 
37
{
 
38
  FILETIME ft;
 
39
  HfsTimeToFileTime(hfsTime, ft);
 
40
  prop = ft;
 
41
}
 
42
 
 
43
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
 
44
{
 
45
  COM_TRY_BEGIN
 
46
  NWindows::NCOM::CPropVariant prop;
 
47
  switch(propID)
 
48
  {
 
49
    case kpidMethod: prop = _db.Header.IsHfsX() ? L"HFSX" : L"HFS+"; break;
 
50
    case kpidClusterSize: prop = (UInt32)1 << _db.Header.BlockSizeLog; break;
 
51
    case kpidFreeSpace: prop = (UInt64)_db.Header.NumFreeBlocks << _db.Header.BlockSizeLog; break;
 
52
    case kpidMTime: HfsTimeToProp(_db.Header.MTime, prop); break;
 
53
    case kpidCTime:
 
54
    {
 
55
      FILETIME localFt, ft;
 
56
      HfsTimeToFileTime(_db.Header.CTime, localFt);
 
57
      if (LocalFileTimeToFileTime(&localFt, &ft))
 
58
        prop = ft;
 
59
      break;
 
60
    }
 
61
  }
 
62
  prop.Detach(value);
 
63
  return S_OK;
 
64
  COM_TRY_END
 
65
}
 
66
 
 
67
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value)
 
68
{
 
69
  COM_TRY_BEGIN
 
70
  NWindows::NCOM::CPropVariant prop;
 
71
  const CItem &item = _db.Items[index];
 
72
  switch(propID)
 
73
  {
 
74
    case kpidPath: prop = _db.GetItemPath(index); break;
 
75
    case kpidIsDir: prop = item.IsDir(); break;
 
76
 
 
77
    case kpidCTime:  HfsTimeToProp(item.CTime, prop); break;
 
78
    case kpidMTime:  HfsTimeToProp(item.MTime, prop); break;
 
79
    case kpidATime:  HfsTimeToProp(item.ATime, prop); break;
 
80
 
 
81
    case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumBlocks << _db.Header.BlockSizeLog; break;
 
82
    case kpidSize:     if (!item.IsDir()) prop = item.Size; break;
 
83
  }
 
84
  prop.Detach(value);
 
85
  return S_OK;
 
86
  COM_TRY_END
 
87
}
 
88
 
 
89
class CProgressImp: public CProgressVirt
 
90
{
 
91
  CMyComPtr<IArchiveOpenCallback> _callback;
 
92
public:
 
93
  HRESULT SetTotal(UInt64 numFiles);
 
94
  HRESULT SetCompleted(UInt64 numFiles);
 
95
  CProgressImp(IArchiveOpenCallback *callback): _callback(callback) {}
 
96
};
 
97
 
 
98
HRESULT CProgressImp::SetTotal(UInt64 numFiles)
 
99
{
 
100
  if (_callback)
 
101
    return _callback->SetTotal(&numFiles, NULL);
 
102
  return S_OK;
 
103
}
 
104
 
 
105
HRESULT CProgressImp::SetCompleted(UInt64 numFiles)
 
106
{
 
107
  if (_callback)
 
108
    return _callback->SetCompleted(&numFiles, NULL);
 
109
  return S_OK;
 
110
}
 
111
 
 
112
STDMETHODIMP CHandler::Open(IInStream *inStream,
 
113
    const UInt64 * /* maxCheckStartPosition */,
 
114
    IArchiveOpenCallback *callback)
 
115
{
 
116
  COM_TRY_BEGIN
 
117
  Close();
 
118
  try
 
119
  {
 
120
    CProgressImp progressImp(callback);
 
121
    HRESULT res = _db.Open(inStream, &progressImp);
 
122
    if (res == E_ABORT)
 
123
      return res;
 
124
    if (res != S_OK)
 
125
      return S_FALSE;
 
126
    _stream = inStream;
 
127
  }
 
128
  catch(...) { return S_FALSE; }
 
129
  return S_OK;
 
130
  COM_TRY_END
 
131
}
 
132
 
 
133
STDMETHODIMP CHandler::Close()
 
134
{
 
135
  _stream.Release();
 
136
  _db.Clear();
 
137
  return S_OK;
 
138
}
 
139
 
 
140
STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems,
 
141
    Int32 _aTestMode, IArchiveExtractCallback *extractCallback)
 
142
{
 
143
  COM_TRY_BEGIN
 
144
  bool testMode = (_aTestMode != 0);
 
145
  bool allFilesMode = (numItems == UInt32(-1));
 
146
  if (allFilesMode)
 
147
    numItems = _db.Items.Size();
 
148
  if (numItems == 0)
 
149
    return S_OK;
 
150
  UInt32 i;
 
151
  UInt64 totalSize = 0;
 
152
  for (i = 0; i < numItems; i++)
 
153
  {
 
154
    const CItem &item = _db.Items[allFilesMode ? i : indices[i]];
 
155
    if (!item.IsDir())
 
156
      totalSize += item.Size;
 
157
  }
 
158
  RINOK(extractCallback->SetTotal(totalSize));
 
159
 
 
160
  UInt64 currentTotalSize = 0, currentItemSize = 0;
 
161
  
 
162
  CByteBuffer buf;
 
163
  const UInt32 kBufSize = (1 << 16);
 
164
  buf.SetCapacity(kBufSize);
 
165
 
 
166
  for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
 
167
  {
 
168
    RINOK(extractCallback->SetCompleted(&currentTotalSize));
 
169
    Int32 index = allFilesMode ? i : indices[i];
 
170
    const CItem &item = _db.Items[index];
 
171
    currentItemSize = 0;
 
172
    if (!item.IsDir())
 
173
      currentItemSize = item.Size;
 
174
 
 
175
    CMyComPtr<ISequentialOutStream> realOutStream;
 
176
    Int32 askMode = testMode ?
 
177
        NArchive::NExtract::NAskMode::kTest :
 
178
        NArchive::NExtract::NAskMode::kExtract;
 
179
    RINOK(extractCallback->GetStream(index, &realOutStream, askMode));
 
180
 
 
181
    if (item.IsDir())
 
182
    {
 
183
      RINOK(extractCallback->PrepareOperation(askMode));
 
184
      RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK));
 
185
      continue;
 
186
    }
 
187
    if (!testMode && (!realOutStream))
 
188
      continue;
 
189
    RINOK(extractCallback->PrepareOperation(askMode));
 
190
    UInt64 pos = 0;
 
191
    int res = NArchive::NExtract::NOperationResult::kOK;
 
192
    int i;
 
193
    for (i = 0; i < item.Extents.Size(); i++)
 
194
    {
 
195
      if (item.Size == pos)
 
196
        break;
 
197
      if (res != NArchive::NExtract::NOperationResult::kOK)
 
198
        break;
 
199
      const CExtent &e = item.Extents[i];
 
200
      RINOK(_stream->Seek((UInt64)e.Pos << _db.Header.BlockSizeLog, STREAM_SEEK_SET, NULL));
 
201
      UInt64 extentSize = (UInt64)e.NumBlocks << _db.Header.BlockSizeLog;
 
202
      for (;;)
 
203
      {
 
204
        if (extentSize == 0)
 
205
          break;
 
206
        UInt64 rem = item.Size - pos;
 
207
        if (rem == 0)
 
208
        {
 
209
          if (extentSize >= (UInt64)((UInt32)1 << _db.Header.BlockSizeLog))
 
210
            res = NArchive::NExtract::NOperationResult::kDataError;
 
211
          break;
 
212
        }
 
213
        UInt32 curSize = kBufSize;
 
214
        if (curSize > rem)
 
215
          curSize = (UInt32)rem;
 
216
        if (curSize > extentSize)
 
217
          curSize = (UInt32)extentSize;
 
218
        RINOK(ReadStream_FALSE(_stream, buf, curSize));
 
219
        if (realOutStream)
 
220
        {
 
221
          RINOK(WriteStream(realOutStream, buf, curSize));
 
222
        }
 
223
        pos += curSize;
 
224
        extentSize -= curSize;
 
225
        UInt64 processed = currentTotalSize + pos;
 
226
        RINOK(extractCallback->SetCompleted(&processed));
 
227
      }
 
228
    }
 
229
    if (i != item.Extents.Size() || item.Size != pos)
 
230
      res = NArchive::NExtract::NOperationResult::kDataError;
 
231
    realOutStream.Release();
 
232
    RINOK(extractCallback->SetOperationResult(res));
 
233
  }
 
234
  return S_OK;
 
235
  COM_TRY_END
 
236
}
 
237
 
 
238
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
 
239
{
 
240
  *numItems = _db.Items.Size();
 
241
  return S_OK;
 
242
}
 
243
 
 
244
}}