Update to 7-Zip Version 22.01

See: https://sourceforge.net/p/sevenzip/discussion/45797/thread/c43cbc5f18/
This commit is contained in:
Tino Reichardt
2022-08-07 10:03:34 +02:00
parent 57558682a8
commit f9e0730191
47 changed files with 2485 additions and 812 deletions

View File

@@ -32,6 +32,8 @@
#include "Common/ItemNameUtils.h"
#include "HfsHandler.h"
// if APFS_SHOW_ALT_STREAMS is defined, the handler will show attribute files.
#define APFS_SHOW_ALT_STREAMS
@@ -934,11 +936,12 @@ struct CItem
unsigned RefIndex;
// unsigned iNode_Index;
CItem():
ParentItemIndex(VI_MINUS1),
RefIndex(VI_MINUS1)
// iNode_Index(VI_MINUS1)
{}
void Clear()
{
Name.Empty();
ParentItemIndex = VI_MINUS1;
RefIndex = VI_MINUS1;
}
};
@@ -956,9 +959,9 @@ struct CItem
#define UNIFIED_ID_SPACE_MARK 0x0800000000000000
*/
/*
typedef enum
{
/*
INODE_IS_APFS_PRIVATE = 0x00000001,
INODE_MAINTAIN_DIR_STATS = 0x00000002,
INODE_DIR_STATS_ORIGIN = 0x00000004,
@@ -973,11 +976,15 @@ INODE_WAS_EVER_CLONED = 0x00000400,
INODE_ACTIVE_FILE_TRIMMED = 0x00000800,
INODE_PINNED_TO_MAIN = 0x00001000,
INODE_PINNED_TO_TIER2 = 0x00002000,
*/
INODE_HAS_RSRC_FORK = 0x00004000,
/*
INODE_NO_RSRC_FORK = 0x00008000,
INODE_ALLOCATION_SPILLEDOVER = 0x00010000,
INODE_FAST_PROMOTE = 0x00020000,
*/
INODE_HAS_UNCOMPRESSED_SIZE = 0x00040000,
/*
INODE_IS_PURGEABLE = 0x00080000,
INODE_WANTS_TO_BE_PURGEABLE = 0x00100000,
INODE_IS_SYNC_ROOT = 0x00200000,
@@ -993,10 +1000,12 @@ INODE_CLONED_INTERNAL_FLAGS = \
| INODE_NO_RSRC_FORK \
| INODE_HAS_FINDER_INFO \
| INODE_SNAPSHOT_COW_EXEMPTION),
*/
}
j_inode_flags;
/*
#define APFS_VALID_INTERNAL_INODE_FLAGS \
( INODE_IS_APFS_PRIVATE \
| INODE_MAINTAIN_DIR_STATS \
@@ -1192,22 +1201,34 @@ struct CAttr
{
AString Name;
UInt32 flags;
bool dstream_defined;
bool NeedShow;
CByteBuffer Data;
j_dstream dstream;
bool dstream_defined;
UInt64 Id;
bool Is_dstream_OK_for_SymLink() const
{
return dstream_defined && dstream.size <= (1 << 12) && dstream.size != 0;
}
CAttr():
dstream_defined(false)
{}
bool Is_STREAM() const { return (flags & XATTR_DATA_STREAM) != 0; }
UInt64 GetSize() const
{
if (dstream_defined) // dstream has more priority
return dstream.size;
return Data.Size();
}
void Clear()
{
dstream_defined = false;
NeedShow = true;
Data.Free();
Name.Empty();
}
bool Is_STREAM() const { return (flags & XATTR_DATA_STREAM) != 0; }
bool Is_EMBEDDED() const { return (flags & XATTR_DATA_EMBEDDED) != 0; }
};
@@ -1245,16 +1266,22 @@ struct CNode
MY__gid_t group;
MY__mode_t mode;
UInt16 pad1;
// UInt64 uncompressed_size;
UInt64 uncompressed_size;
j_dstream dstream;
AString PrimaryName;
bool dstream_defined;
bool refcnt_defined;
UInt32 refcnt; // j_dstream_id_val_t
CRecordVector<CExtent> Extents;
CObjectVector<CAttr> Attrs;
unsigned SymLinkIndex; // index in Attrs
unsigned DecmpfsIndex; // index in Attrs
unsigned ResourceIndex; // index in Attrs
NHfs::CCompressHeader CompressHeader;
CNode():
ItemIndex(VI_MINUS1),
@@ -1262,11 +1289,16 @@ struct CNode
// NumItems(0),
dstream_defined(false),
refcnt_defined(false),
SymLinkIndex(VI_MINUS1)
SymLinkIndex(VI_MINUS1),
DecmpfsIndex(VI_MINUS1),
ResourceIndex(VI_MINUS1)
{}
bool IsDir() const { return MY_LIN_S_ISDIR(mode); }
bool IsSymLink() const { return MY_LIN_S_ISLNK(mode); }
bool Has_UNCOMPRESSED_SIZE() const { return (internal_flags & INODE_HAS_UNCOMPRESSED_SIZE) != 0; }
unsigned Get_Type_From_mode() const { return mode >> 12; }
bool GetSize(unsigned attrIndex, UInt64 &size) const
@@ -1278,6 +1310,12 @@ struct CNode
size = dstream.size;
return true;
}
size = 0;
if (Has_UNCOMPRESSED_SIZE())
{
size = uncompressed_size;
return true;
}
if (!IsSymLink())
return false;
attrIndex = SymLinkIndex;
@@ -1301,9 +1339,23 @@ struct CNode
size = dstream.alloced_size;
return true;
}
if (!IsSymLink())
return false;
attrIndex = SymLinkIndex;
size = 0;
if (IsSymLink())
attrIndex = SymLinkIndex;
else
{
if (!CompressHeader.IsCorrect ||
!CompressHeader.IsSupported)
return false;
const CAttr &attr = Attrs[DecmpfsIndex];
if (!CompressHeader.IsMethod_Resource())
{
size = attr.Data.Size() - CompressHeader.DataPos;
return true;
}
attrIndex = ResourceIndex;
}
if (IsViNotDef(attrIndex))
return false;
}
@@ -1339,17 +1391,17 @@ void CNode::Parse(const Byte *p)
G64 (0x28, access_time);
G64 (0x30, internal_flags);
{
G32(0x38, nchildren);
// G32(0x38, nlink);
G32 (0x38, nchildren);
// G32 (0x38, nlink);
}
// G32(0x3c, default_protection_class);
G32(0x40, write_generation_counter);
G32(0x44, bsd_flags);
G32(0x48, owner);
G32(0x4c, group);
G16(0x50, mode);
// G16(0x52, pad1);
// G64 (0x54, uncompressed_size);
// G32 (0x3c, default_protection_class);
G32 (0x40, write_generation_counter);
G32 (0x44, bsd_flags);
G32 (0x48, owner);
G32 (0x4c, group);
G16 (0x50, mode);
// G16 (0x52, pad1);
G64 (0x54, uncompressed_size);
}
@@ -1364,6 +1416,7 @@ struct CRef
bool IsAltStream() const { return IsViDef(AttrIndex); }
unsigned GetAttrIndex() const { return AttrIndex; };
#else
// bool IsAltStream() const { return false; }
unsigned GetAttrIndex() const { return VI_MINUS1; };
#endif
};
@@ -1667,6 +1720,7 @@ struct CDatabase
UInt64 ProgressVal_NumFilesTotal;
CObjectVector<CByteBuffer> Buffers;
UInt32 MethodsMask;
UInt64 GetSize(const UInt32 index) const;
void Clear()
@@ -1678,6 +1732,8 @@ struct CDatabase
ProgressVal_Cur = 0;
ProgressVal_Prev = 0;
ProgressVal_NumFilesTotal = 0;
MethodsMask = 0;
Vols.Clear();
Refs2.Clear();
@@ -1691,6 +1747,12 @@ struct CDatabase
HRESULT OpenVolume(const CObjectMap &omap, const oid_t fs_oid);
HRESULT Open2();
HRESULT GetAttrStream(IInStream *apfsInStream, const CVol &vol,
const CAttr &attr, ISequentialInStream **stream);
HRESULT GetAttrStream_dstream(IInStream *apfsInStream, const CVol &vol,
const CAttr &attr, ISequentialInStream **stream);
HRESULT GetStream2(
IInStream *apfsInStream,
const CRecordVector<CExtent> *extents, UInt64 rem,
@@ -2070,7 +2132,7 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
RINOK(ReadMap(ov.paddr, map, 0));
}
bool NeedReadSymLink = false;
bool needParseAttr = false;
{
const bool isHashed = apfs.IsHashedName();
@@ -2094,6 +2156,9 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
}
}
CAttr attr;
CItem item;
FOR_VECTOR (i, map.Pairs)
{
if (OpenCallback && (i & 0xffff) == 1)
@@ -2232,7 +2297,7 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
if (nameOffset + len != pair.Key.Size())
return S_FALSE;
CAttr attr;
attr.Clear();
attr.Name.SetFrom_CalcLen((const char *)p + nameOffset, len);
if (attr.Name.Len() != len - 1)
return S_FALSE;
@@ -2287,15 +2352,25 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
// UnsupportedFeature = true;
// continue;
}
CNode &inode = vol.Nodes.Back();
if (attr.Name.IsEqualTo("com.apple.fs.symlink"))
{
inode.SymLinkIndex = inode.Attrs.Size();
if (attr.Is_dstream_OK_for_SymLink())
NeedReadSymLink = true;
needParseAttr = true;
}
else if (attr.Name.IsEqualTo("com.apple.decmpfs"))
{
inode.DecmpfsIndex = inode.Attrs.Size();
// if (attr.dstream_defined)
needParseAttr = true;
}
else if (attr.Name.IsEqualTo("com.apple.ResourceFork"))
{
inode.ResourceIndex = inode.Attrs.Size();
}
else
vol.NumAltStreams++;
inode.Attrs.Add(attr);
continue;
}
@@ -2431,7 +2506,10 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
}
if (nameOffset + len != pair.Key.Size())
return S_FALSE;
CItem item;
// CItem item;
item.Clear();
item.ParentId = id;
item.Name.SetFrom_CalcLen((const char *)p + nameOffset, len);
if (item.Name.Len() != len - 1)
@@ -2471,39 +2549,86 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
ProgressVal_NumFilesTotal += vol.Items.Size();
}
if (NeedReadSymLink)
if (needParseAttr)
{
/* we read external streams for SymLinks to CAttr.Data
/* we read external streams for attributes
So we can get SymLink for GetProperty(kpidSymLink) later */
FOR_VECTOR (i, vol.Nodes)
{
CNode &node = vol.Nodes[i];
if (IsViNotDef(node.SymLinkIndex))
continue;
CAttr &attr = node.Attrs[(unsigned)node.SymLinkIndex];
// FOR_VECTOR (k, node.Attrs) { CAttr &attr = node.Attrs[(unsigned)k]; // for debug
if (attr.Data.Size() != 0
|| !attr.Is_dstream_OK_for_SymLink())
continue;
const UInt32 size = (UInt32)attr.dstream.size;
const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id);
if (idIndex == -1)
continue;
CMyComPtr<ISequentialInStream> inStream;
const HRESULT res = GetStream2(
OpenInStream,
&vol.SmallNodes[(unsigned)idIndex].Extents,
size, &inStream);
if (res == S_OK && inStream)
FOR_VECTOR (a, node.Attrs)
{
CByteBuffer buf2;
buf2.Alloc(size);
if (ReadStream_FAIL(inStream, buf2, size) == S_OK)
attr.Data = buf2;
CAttr &attr = node.Attrs[a];
if (attr.Data.Size() != 0 || !attr.dstream_defined)
continue;
if (a == node.SymLinkIndex)
{
if (!attr.Is_dstream_OK_for_SymLink())
continue;
}
else
{
if (a != node.DecmpfsIndex
// && a != node.ResourceIndex
)
continue;
}
// we don't expect big streams here
// largest dstream for Decmpfs attribute is (2Kib+17)
if (attr.dstream.size > ((UInt32)1 << 16))
continue;
CMyComPtr<ISequentialInStream> inStream;
const HRESULT res = GetAttrStream_dstream(OpenInStream, vol, attr, &inStream);
if (res == S_OK && inStream)
{
CByteBuffer buf2;
const size_t size = (size_t)attr.dstream.size;
buf2.Alloc(size);
if (ReadStream_FAIL(inStream, buf2, size) == S_OK)
attr.Data = buf2;
ProgressVal_Cur += size;
if (OpenCallback)
if (ProgressVal_Cur - ProgressVal_Prev >= (1 << 22))
{
RINOK(OpenCallback->SetCompleted(
&ProgressVal_NumFilesTotal,
&ProgressVal_Cur));
ProgressVal_Prev = ProgressVal_Cur;
}
}
}
if (node.Has_UNCOMPRESSED_SIZE())
if (IsViDef(node.DecmpfsIndex))
{
CAttr &attr = node.Attrs[node.DecmpfsIndex];
node.CompressHeader.Parse(attr.Data, attr.Data.Size());
if (node.CompressHeader.IsCorrect)
if (node.CompressHeader.Method < sizeof(MethodsMask) * 8)
MethodsMask |= ((UInt32)1 << node.CompressHeader.Method);
if (node.CompressHeader.IsCorrect
&& node.CompressHeader.IsSupported
&& node.CompressHeader.UnpackSize == node.uncompressed_size)
{
attr.NeedShow = false;
if (node.CompressHeader.IsMethod_Resource()
&& IsViDef(node.ResourceIndex))
node.Attrs[node.ResourceIndex].NeedShow = false;
}
else
{
vol.UnsupportedFeature = true;
}
}
}
}
const HRESULT res = vol.FillRefs();
if (vol.ThereAreErrors())
@@ -2521,9 +2646,10 @@ HRESULT CDatabase::OpenVolume(const CObjectMap &omap, const oid_t fs_oid)
HRESULT CVol::FillRefs()
{
{
Refs.Reserve(Items.Size());
// we fill Refs[*]
// we
// and set Nodes[*].ItemIndex for Nodes that are dictories;
// and set Nodes[*].ItemIndex for Nodes that are directories;
FOR_VECTOR (i, Items)
{
CItem &item = Items[i];
@@ -2593,12 +2719,17 @@ HRESULT CVol::FillRefs()
ref.ParentRefIndex = item.RefIndex;
for (unsigned k = 0; k < numAttrs; k++)
{
// comment it for debug
const CAttr &attr = inode.Attrs[k];
if (!attr.NeedShow)
continue;
if (k == inode.SymLinkIndex)
continue;
ref.AttrIndex = k;
NumAltStreams++;
Refs.Add(ref);
/*
const CAttr &attr = inode.Attrs[k];
if (attr.dstream_defined)
{
const int idIndex = SmallNodeIDs.FindInSorted(attr.Id);
@@ -2780,6 +2911,7 @@ enum
kpidAddTime,
kpidGeneration,
kpidBsdFlags
// kpidUncompressedSize
};
static const CStatProp kProps[] =
@@ -2793,11 +2925,13 @@ static const CStatProp kProps[] =
{ NULL, kpidATime, VT_FILETIME },
{ NULL, kpidChangeTime, VT_FILETIME },
{ "Added Time", kpidAddTime, VT_FILETIME },
{ NULL, kpidMethod, VT_BSTR },
{ NULL, kpidINode, VT_UI8 },
{ NULL, kpidLinks, VT_UI4 },
{ NULL, kpidSymLink, VT_BSTR },
{ NULL, kpidUserId, VT_UI4 },
{ NULL, kpidGroupId, VT_UI4 },
{ NULL, kpidCharacts, VT_BSTR },
#ifdef APFS_SHOW_ALT_STREAMS
{ NULL, kpidIsAltStream, VT_BOOL },
#endif
@@ -2807,12 +2941,14 @@ static const CStatProp kProps[] =
{ "Written Size", kpidBytesWritten, VT_UI8 },
{ "Read Size", kpidBytesRead, VT_UI8 },
{ "BSD Flags", kpidBsdFlags, VT_UI4 }
// , { "Uncompressed Size", kpidUncompressedSize, VT_UI8 }
};
static const Byte kArcProps[] =
{
kpidName,
kpidCharacts,
kpidId,
kpidClusterSize,
kpidCTime,
@@ -2848,6 +2984,7 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
prop = (UInt64)sb.block_count << sb.block_size_Log;
break;
case kpidClusterSize: prop = (UInt32)(sb.block_size); break;
case kpidCharacts: NHfs::MethodsMaskToProp(MethodsMask, prop); break;
case kpidMTime:
if (apfs)
ApfsTimeToProp(apfs->modified_by[0].timestamp, prop);
@@ -2953,7 +3090,6 @@ STDMETHODIMP CHandler::GetParent(UInt32 index, UInt32 *parent, UInt32 *parentTyp
const CRef2 &ref2 = Refs2[index];
const CVol &vol = Vols[ref2.VolIndex];
UInt32 parentIndex = (UInt32)(Int32)-1;
*parentType = NParentType::kDir;
if (IsViDef(ref2.RefIndex))
{
@@ -3017,6 +3153,7 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::
{
const CRef &ref = vol.Refs[ref2.RefIndex];
unsigned cur = ref.ItemIndex;
UString s2;
if (IsViNotDef(cur))
{
if (inode)
@@ -3032,14 +3169,13 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::
break;
}
const CItem &item = vol.Items[(unsigned)cur];
UString s2;
Utf8Name_to_InterName(item.Name, s2);
// s2 += "a\\b"; // for debug
s.Insert(0, s2);
cur = item.ParentItemIndex;
if (IsViNotDef(cur))
break;
// ParentItemIndex was not set for sch items
// ParentItemIndex was not set for such items
// if (item.ParentId == ROOT_DIR_INO_NUM) break;
s.InsertAtFront(WCHAR_PATH_SEPARATOR);
}
@@ -3049,7 +3185,6 @@ void CDatabase::GetItemPath(unsigned index, const CNode *inode, NWindows::NCOM::
if (IsViDef(ref.AttrIndex) && inode)
{
s += ':';
UString s2;
Utf8Name_to_InterName(inode->Attrs[(unsigned)ref.AttrIndex].Name, s2);
// s2 += "a\\b"; // for debug
s += s2;
@@ -3110,11 +3245,10 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
case kpidPrimeName:
{
if (inode
#ifdef APFS_SHOW_ALT_STREAMS
&& !ref.IsAltStream()
#endif
&& !inode->PrimaryName.IsEmpty())
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode && !inode->PrimaryName.IsEmpty())
{
UString s;
ConvertUTF8ToUnicode(inode->PrimaryName, s);
@@ -3155,6 +3289,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
}
case kpidSymLink:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode)
{
if (inode->IsSymLink() && IsViDef(inode->SymLinkIndex))
@@ -3178,8 +3315,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize:
if (inode)
{
UInt64 size;
if (inode->GetSize(ref.GetAttrIndex(), size))
UInt64 size = 0;
if (inode->GetSize(ref.GetAttrIndex(), size) ||
!inode->IsDir())
prop = size;
}
break;
@@ -3188,18 +3326,53 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
if (inode)
{
UInt64 size;
if (inode->GetPackSize(ref.GetAttrIndex(), size))
if (inode->GetPackSize(ref.GetAttrIndex(), size) ||
!inode->IsDir())
prop = size;
}
break;
case kpidMethod:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode)
{
if (inode->CompressHeader.IsCorrect)
inode->CompressHeader.MethodToProp(prop);
else if (IsViDef(inode->DecmpfsIndex))
prop = "decmpfs";
else if (!inode->IsDir() && !inode->dstream_defined)
{
if (inode->IsSymLink())
{
if (IsViDef(inode->SymLinkIndex))
prop = "symlink";
}
// else prop = "no_dstream";
}
}
break;
/*
case kpidUncompressedSize:
if (inode && inode->Has_UNCOMPRESSED_SIZE())
prop = inode->uncompressed_size;
break;
*/
case kpidIsDir:
{
bool isDir = false;
if (inode)
isDir = inode->IsDir();
else if (item)
isDir = item->Val.IsFlags_Dir();
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
{
if (inode)
isDir = inode->IsDir();
else if (item)
isDir = item->Val.IsFlags_Dir();
}
prop = isDir;
break;
}
@@ -3251,6 +3424,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
#endif
case kpidCharacts:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode)
{
FLAGS_TO_PROP(g_INODE_Flags, (UInt32)inode->internal_flags, prop);
@@ -3258,6 +3434,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
case kpidBsdFlags:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode)
{
FLAGS_TO_PROP(g_INODE_BSD_Flags, inode->bsd_flags, prop);
@@ -3265,6 +3444,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
case kpidGeneration:
#ifdef APFS_SHOW_ALT_STREAMS
// if (!ref.IsAltStream())
#endif
if (inode)
prop = inode->write_generation_counter;
break;
@@ -3280,6 +3462,9 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
break;
case kpidLinks:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode && !inode->IsDir())
prop = (UInt32)inode->nlink;
break;
@@ -3287,13 +3472,16 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidINode:
#ifdef APFS_SHOW_ALT_STREAMS
// here we can disable iNode for alt stream.
// if (!ref.IsAltStream())
if (!ref.IsAltStream())
#endif
if (IsViDef(ref.NodeIndex))
prop = (UInt32)vol.NodeIDs[ref.NodeIndex];
break;
case kpidParentINode:
#ifdef APFS_SHOW_ALT_STREAMS
if (!ref.IsAltStream())
#endif
if (inode)
prop = (UInt32)inode->parent_id;
break;
@@ -3351,6 +3539,8 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder();
CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec;
NHfs::CDecoder decoder;
for (i = 0; i < numItems; i++, currentTotalSize += currentItemSize)
{
lps->InSize = currentTotalSize;
@@ -3399,15 +3589,68 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
RINOK(extractCallback->PrepareOperation(askMode));
int opRes = NExtract::NOperationResult::kDataError;
CMyComPtr<ISequentialInStream> inStream;
if (GetStream(index, &inStream) == S_OK && inStream)
if (IsViDef(ref.NodeIndex))
{
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
opRes = NExtract::NOperationResult::kDataError;
if (copyCoderSpec->TotalSize == currentItemSize)
opRes = NExtract::NOperationResult::kOK;
else if (copyCoderSpec->TotalSize < currentItemSize)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
const CNode &inode = vol.Nodes[ref.NodeIndex];
if (
#ifdef APFS_SHOW_ALT_STREAMS
!ref.IsAltStream() &&
#endif
!inode.dstream_defined
&& inode.Extents.IsEmpty()
&& inode.Has_UNCOMPRESSED_SIZE()
&& inode.uncompressed_size == inode.CompressHeader.UnpackSize)
{
if (inode.CompressHeader.IsSupported)
{
CMyComPtr<ISequentialInStream> inStreamFork;
UInt64 forkSize = 0;
const CByteBuffer *decmpfs_Data = NULL;
if (inode.CompressHeader.IsMethod_Resource())
{
if (IsViDef(inode.ResourceIndex))
{
const CAttr &attr = inode.Attrs[inode.ResourceIndex];
forkSize = attr.GetSize();
GetAttrStream(_stream, vol, attr, &inStreamFork);
}
}
else
{
const CAttr &attr = inode.Attrs[inode.DecmpfsIndex];
decmpfs_Data = &attr.Data;
}
if (inStreamFork || decmpfs_Data)
{
const HRESULT hres = decoder.Extract(
inStreamFork, realOutStream,
forkSize,
inode.CompressHeader,
decmpfs_Data,
currentTotalSize, extractCallback,
opRes);
if (hres != S_FALSE && hres != S_OK)
return hres;
}
}
else
opRes = NExtract::NOperationResult::kUnsupportedMethod;
}
else
{
CMyComPtr<ISequentialInStream> inStream;
if (GetStream(index, &inStream) == S_OK && inStream)
{
RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress));
opRes = NExtract::NOperationResult::kDataError;
if (copyCoderSpec->TotalSize == currentItemSize)
opRes = NExtract::NOperationResult::kOK;
else if (copyCoderSpec->TotalSize < currentItemSize)
opRes = NExtract::NOperationResult::kUnexpectedEnd;
}
}
}
realOutStream.Release();
@@ -3478,7 +3721,14 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (inode.IsDir())
return S_FALSE;
if (inode.dstream_defined)
{
rem = inode.dstream.size;
}
else
{
// return S_FALSE; // check it !!! How zero size files are stored with dstream_defined?
}
extents = &inode.Extents;
}
return GetStream2(_stream, extents, rem, stream);
@@ -3486,6 +3736,35 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
HRESULT CDatabase::GetAttrStream(IInStream *apfsInStream, const CVol &vol,
const CAttr &attr, ISequentialInStream **stream)
{
*stream = NULL;
if (!attr.dstream_defined)
{
CBufInStream *streamSpec = new CBufInStream;
CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
streamSpec->Init(attr.Data, attr.Data.Size(), (IInArchive *)this);
*stream = streamTemp.Detach();
return S_OK;
}
return GetAttrStream_dstream(apfsInStream, vol, attr, stream);
}
HRESULT CDatabase::GetAttrStream_dstream( IInStream *apfsInStream, const CVol &vol,
const CAttr &attr, ISequentialInStream **stream)
{
const int idIndex = vol.SmallNodeIDs.FindInSorted(attr.Id);
if (idIndex == -1)
return S_FALSE;
return GetStream2(apfsInStream,
&vol.SmallNodes[(unsigned)idIndex].Extents,
attr.dstream.size,
stream);
}
HRESULT CDatabase::GetStream2(
IInStream *apfsInStream,
const CRecordVector<CExtent> *extents, UInt64 rem,

View File

@@ -126,6 +126,7 @@ struct CLzxInfo
CLzxInfo():
Version(0),
ResetIntervalBits(0),
WindowSizeBits(0),
CacheSize(0)
{}

View File

@@ -1063,6 +1063,8 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
subName.DeleteFrom(pos1);
}
}
else
subName = item.Name; // new apfs dmg can be without braces
subName.Trim();
if (!subName.IsEmpty())
{

View File

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,85 @@
// HfsHandler.h
#ifndef __HFS_HANDLER_H
#define __HFS_HANDLER_H
#include "../../Windows/PropVariant.h"
#include "../Compress/LzfseDecoder.h"
#include "../Compress/ZlibDecoder.h"
namespace NArchive {
namespace NHfs {
static const UInt32 k_decmpfs_HeaderSize = 16;
struct CCompressHeader
{
UInt64 UnpackSize;
UInt32 Method;
Byte DataPos;
bool IsCorrect;
bool IsSupported;
bool IsResource;
bool IsMethod_Compressed_Inline() const { return DataPos == k_decmpfs_HeaderSize; }
bool IsMethod_Uncompressed_Inline() const { return DataPos == k_decmpfs_HeaderSize + 1; }
bool IsMethod_Resource() const { return IsResource; }
void Parse(const Byte *p, size_t size);
void Clear()
{
UnpackSize = 0;
Method = 0;
DataPos = 0;
IsCorrect = false;
IsSupported = false;
IsResource = false;
}
CCompressHeader() { Clear(); }
void MethodToProp(NWindows::NCOM::CPropVariant &prop) const;
};
void MethodsMaskToProp(UInt32 methodsMask, NWindows::NCOM::CPropVariant &prop);
class CDecoder
{
NCompress::NZlib::CDecoder *_zlibDecoderSpec;
CMyComPtr<ICompressCoder> _zlibDecoder;
NCompress::NLzfse::CDecoder *_lzfseDecoderSpec;
CMyComPtr<ICompressCoder> _lzfseDecoder;
CByteBuffer _tableBuf;
CByteBuffer _buf;
HRESULT ExtractResourceFork_ZLIB(
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
UInt64 forkSize, UInt64 unpackSize,
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
HRESULT ExtractResourceFork_LZFSE(
ISequentialInStream *inStream, ISequentialOutStream *realOutStream,
UInt64 forkSize, UInt64 unpackSize,
UInt64 progressStart, IArchiveExtractCallback *extractCallback);
public:
HRESULT Extract(
ISequentialInStream *inStreamFork, ISequentialOutStream *realOutStream,
UInt64 forkSize,
const CCompressHeader &compressHeader,
const CByteBuffer *data,
UInt64 progressStart, IArchiveExtractCallback *extractCallback,
int &opRes);
CDecoder();
};
}}
#endif

View File

@@ -48,14 +48,22 @@ static const Byte kProps[] =
kpidPackSize,
kpidMTime,
kpidATime,
kpidChangeTime
kpidCTime,
kpidChangeTime,
// kpidUserId,
// kpidGroupId,
// kpidPosixAttrib,
kpidLinks
};
static const Byte kArcProps[] =
{
kpidComment,
kpidUnpackVer,
kpidClusterSize,
kpidCTime
kpidSectorSize,
kpidCTime,
kpidMTime,
kpidComment
};
IMP_IInArchive_Props
@@ -69,6 +77,18 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
{
case kpidPhySize: prop = _archive.PhySize; break;
case kpidUnpackVer:
{
if (_archive.LogVols.Size() == 1)
{
UString s;
const CLogVol &vol = _archive.LogVols[0];
vol.DomainId.AddUdfVersionTo(s);
if (!s.IsEmpty())
prop = s;
}
break;
}
case kpidComment:
{
UString comment = _archive.GetComment();
@@ -90,12 +110,21 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
}
break;
case kpidSectorSize: prop = ((UInt32)1 << _archive.SecLogSize); break;
case kpidCTime:
if (_archive.LogVols.Size() == 1)
{
const CLogVol &vol = _archive.LogVols[0];
if (vol.FileSets.Size() >= 1)
UdfTimeToFileTime(vol.FileSets[0].RecodringTime, prop);
UdfTimeToFileTime(vol.FileSets[0].RecordingTime, prop);
}
break;
case kpidMTime:
if (_archive.PrimeVols.Size() == 1)
{
const CPrimeVol &pv = _archive.PrimeVols[0];
UdfTimeToFileTime(pv.RecordingTime, prop);
}
break;
@@ -160,6 +189,7 @@ STDMETHODIMP CHandler::Open(IInStream *stream, const UInt64 *, IArchiveOpenCallb
{
const CLogVol &vol = _archive.LogVols[volIndex];
bool showFileSetName = (vol.FileSets.Size() > 1);
// showFileSetName = true; // for debug
FOR_VECTOR (fsIndex, vol.FileSets)
{
const CFileSet &fs = vol.FileSets[fsIndex];
@@ -212,7 +242,15 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidPackSize: if (!item.IsDir()) prop = (UInt64)item.NumLogBlockRecorded * vol.BlockSize; break;
case kpidMTime: UdfTimeToFileTime(item.MTime, prop); break;
case kpidATime: UdfTimeToFileTime(item.ATime, prop); break;
case kpidCTime:
if (item.IsExtended)
UdfTimeToFileTime(item.CreateTime, prop);
break;
case kpidChangeTime: UdfTimeToFileTime(item.AttribTime, prop); break;
// case kpidUserId: prop = item.Uid; break;
// case kpidGroupId: prop = item.Gid; break;
// case kpidPosixAttrib: prop = (UInt32)item.Permissions; break;
case kpidLinks: prop = (UInt32)item.FileLinkCount; break;
}
}
prop.Detach(value);
@@ -255,7 +293,7 @@ STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
if (size < len)
return S_FALSE;
int partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;
const unsigned partitionIndex = vol.PartitionMaps[extent.PartitionRef].PartitionIndex;
UInt32 logBlockNumber = extent.Pos;
const CPartition &partition = _archive.Partitions[partitionIndex];
UInt64 offset = ((UInt64)partition.Pos << _archive.SecLogSize) +

View File

@@ -24,9 +24,9 @@ class CHandler:
public IInArchiveGetStream,
public CMyUnknownImp
{
CRecordVector<CRef2> _refs2;
CMyComPtr<IInStream> _inStream;
CInArchive _archive;
CRecordVector<CRef2> _refs2;
public:
MY_UNKNOWN_IMP2(IInArchive, IInArchiveGetStream)
INTERFACE_IInArchive(;)

View File

File diff suppressed because it is too large Load Diff

View File

@@ -17,16 +17,15 @@ namespace NUdf {
// ---------- ECMA Part 1 ----------
// ECMA 1/7.2.12
// UDF 2.1.3
/*
struct CDString32
{
Byte Data[32];
void Parse(const Byte *buf);
// UString GetString() const;
void Parse(const Byte *buf) { memcpy(Data, buf, sizeof(Data)); }
UString GetString() const;
};
*/
struct CDString128
{
@@ -46,6 +45,7 @@ struct CDString
// ECMA 1/7.3
// UDF 2.1.4 timestamp
struct CTime
{
@@ -65,9 +65,9 @@ struct CTime
};
// ECMA 1/7.4
// ECMA 1/7.4 regid
// UDF 2.1.5 EntityID
/*
struct CRegId
{
Byte Flags;
@@ -75,44 +75,97 @@ struct CRegId
char Suffix[8];
void Parse(const Byte *buf);
void AddCommentTo(UString &s) const;
void AddUdfVersionTo(UString &s) const;
};
*/
// ---------- ECMA Part 3: Volume Structure ----------
// ECMA 3/7.1
struct CExtent
{
UInt32 Len;
UInt32 Pos; // logical sector number
void Parse(const Byte *p);
};
// ECMA 3/10.1
// UDF 2.2.2 PrimaryVolumeDescriptor
struct CPrimeVol
{
// UInt32 VolumeDescriptorSequenceNumber;
UInt32 PrimaryVolumeDescriptorNumber;
CDString32 VolumeId;
UInt16 VolumeSequenceNumber;
UInt16 MaximumVolumeSequenceNumber;
// UInt16 InterchangeLevel;
// UInt16 MaximumInterchangeLevel;
// UInt32 CharacterSetList;
// UInt32 MaximumCharacterSetList;
CDString128 VolumeSetId;
// charspec DescriptorCharacterSet; // (1/7.2.1)
// charspec ExplanatoryCharacterSet; // (1/7.2.1)
// CExtent VolumeAbstract;
// CExtent VolumeCopyrightNotice;
CRegId ApplicationId;
CTime RecordingTime;
CRegId ImplId;
// bytes ImplementationUse
// UInt32 PredecessorVolumeDescriptorSequenceLocation;
// UInt16 Flags;
void Parse(const Byte *p);
};
// ECMA 3/10.5
// UDF 2.2.14 PartitionDescriptor
struct CPartition
{
// UInt16 Flags;
UInt16 Number;
// CRegId ContentsId;
// Byte ContentsUse[128];
// UInt32 AccessType;
UInt32 Pos;
UInt32 Len;
// CRegId ImplId;
UInt16 Flags;
UInt16 Number;
CRegId ContentsId;
// Byte ContentsUse[128];
UInt32 AccessType;
CRegId ImplId;
// Byte ImplUse[128];
int VolIndex;
// int VolIndex;
CMap32 Map;
CPartition(): VolIndex(-1) {}
bool IsMetadata;
CPartition():
// VolIndex(-1),
IsMetadata(false) {}
// bool IsNsr() const { return (strncmp(ContentsId.Id, "+NSR0", 5) == 0); }
// bool IsAllocated() const { return ((Flags & 1) != 0); }
};
// ECMA 4/7.1 lb_addr
struct CLogBlockAddr
{
UInt32 Pos;
UInt16 PartitionRef;
void Parse(const Byte *buf);
void Parse(const Byte *p);
};
enum EShortAllocDescType
{
SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated = 0,
@@ -121,16 +174,18 @@ enum EShortAllocDescType
SHORT_ALLOC_DESC_TYPE_NextExtent = 3
};
// ECMA 4/14.14.1 short_ad
struct CShortAllocDesc
{
UInt32 Len;
UInt32 Pos;
// 4/14.14.1
// UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
// UInt32 GetType() const { return Len >> 30; }
// bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
void Parse(const Byte *buf);
void Parse(const Byte *p);
};
/*
@@ -138,10 +193,13 @@ struct CADImpUse
{
UInt16 Flags;
UInt32 UdfUniqueId;
void Parse(const Byte *buf);
void Parse(const Byte *p);
};
*/
// ECMA 4/14.14.2 long_ad
// UDF 2.3.10.1
struct CLongAllocDesc
{
UInt32 Len;
@@ -153,29 +211,48 @@ struct CLongAllocDesc
UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
UInt32 GetType() const { return Len >> 30; }
bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
void Parse(const Byte *buf);
void Parse(const Byte *p);
};
// ECMA 3/10.7 Partition maps
// UDF 2.2.8-2.2.10 Partition Maps
struct CPartitionMap
{
unsigned PartitionIndex;
Byte Type;
// Byte Len;
// Type - 1
// UInt16 VolSeqNumber;
// ECMA 10.7.2
UInt16 VolumeSequenceNumber;
UInt16 PartitionNumber;
CRegId PartitionTypeId;
// UDF 2.2.10 Metadata Partition Map
UInt32 MetadataFileLocation;
// UInt32 MetadataMirrorFileLocation;
// UInt32 MetadataBitmapFileLocation;
// UInt32 AllocationUnitSize; // (Blocks)
// UInt16 AlignmentUnitSize; // (Blocks)
// Byte Flags;
// Byte Data[256];
int PartitionIndex;
// CPartitionMap(): PartitionIndex(-1) {}
};
// ECMA 4/14.6
// ECMA 4/14.6.6
enum EIcbFileType
{
ICB_FILE_TYPE_DIR = 4,
ICB_FILE_TYPE_FILE = 5
ICB_FILE_TYPE_FILE = 5,
ICB_FILE_TYPE_METADATA = 250, // 2.2.13.1 Metadata File
ICB_FILE_TYPE_METADATA_MIRROR = 251
};
enum EIcbDescriptorType
@@ -186,6 +263,9 @@ enum EIcbDescriptorType
ICB_DESC_TYPE_INLINE = 3
};
// ECMA 4/14.6
// UDF 3.3.2
struct CIcbTag
{
// UInt32 PriorDirectNum;
@@ -201,33 +281,35 @@ struct CIcbTag
void Parse(const Byte *p);
};
// ECMA 4/14.4.3
// const Byte FILEID_CHARACS_Existance = (1 << 0);
const Byte FILEID_CHARACS_Parent = (1 << 3);
struct CFile
{
int ItemIndex;
// UInt16 FileVersion;
// Byte FileCharacteristics;
// CByteBuffer ImplUse;
CDString Id;
int ItemIndex;
CFile(): /* FileVersion(0), FileCharacteristics(0), */ ItemIndex(-1) {}
UString GetName() const { return Id.GetString(); }
};
struct CMyExtent
{
UInt32 Pos;
UInt32 Len;
unsigned PartitionRef;
unsigned PartitionRef; // index in CLogVol::PartitionMaps
UInt32 GetLen() const { return Len & 0x3FFFFFFF; }
UInt32 GetType() const { return Len >> 30; }
bool IsRecAndAlloc() const { return GetType() == SHORT_ALLOC_DESC_TYPE_RecordedAndAllocated; }
};
struct CItem
{
CIcbTag IcbTag;
@@ -235,26 +317,30 @@ struct CItem
// UInt32 Uid;
// UInt32 Gid;
// UInt32 Permissions;
// UInt16 FileLinkCount;
UInt16 FileLinkCount;
// Byte RecordFormat;
// Byte RecordDisplayAttr;
// UInt32 RecordLen;
UInt64 Size;
UInt64 NumLogBlockRecorded;
// UInt64 ObjectSize;
CTime ATime;
CTime MTime;
CTime AttribTime; // Attribute time : most recent date and time of the day of file creation or modification of the attributes of.
CTime CreateTime;
// UInt32 CheckPoint;
// CLongAllocDesc ExtendedAttrIcb;
// CRegId ImplId;
// UInt64 UniqueId;
bool IsExtended;
bool IsInline;
CByteBuffer InlineData;
CRecordVector<CMyExtent> Extents;
CUIntVector SubFiles;
void Parse(const Byte *buf);
void Parse(const Byte *p);
bool IsRecAndAlloc() const
{
@@ -279,53 +365,65 @@ struct CItem
bool IsDir() const { return IcbTag.IsDir(); }
};
struct CRef
{
int Parent;
unsigned FileIndex;
int Parent;
};
// ECMA 4 / 14.1
struct CFileSet
{
CTime RecodringTime;
CRecordVector<CRef> Refs;
CTime RecordingTime;
// UInt16 InterchangeLevel;
// UInt16 MaxInterchangeLevel;
// UInt32 FileSetNumber;
// UInt32 FileSetDescNumber;
// CDString32 Id;
// CDString32 CopyrightId;
// CDString32 AbstractId;
UInt32 FileSetNumber;
UInt32 FileSetDescNumber;
CDString128 LogicalVolumeId;
CDString32 Id;
CDString32 CopyrightId;
CDString32 AbstractId;
CLongAllocDesc RootDirICB;
// CRegId DomainId;
CRegId DomainId;
// CLongAllocDesc SystemStreamDirICB;
CRecordVector<CRef> Refs;
};
/* 8.3 Volume descriptors
8.4
A Volume Descriptor Sequence:
shall contain one or more Primary Volume Descriptors.
*/
// ECMA 3/10.6
// UDF 2.2.4 LogicalVolumeDescriptor
struct CLogVol
{
CDString128 Id;
CObjectVector<CPartitionMap> PartitionMaps;
CObjectVector<CFileSet> FileSets;
UInt32 BlockSize;
// CRegId DomainId;
CDString128 Id;
CRegId DomainId;
// Byte ContentsUse[16];
CLongAllocDesc FileSetLocation; // UDF
// CRegId ImplId;
CRegId ImplId;
// Byte ImplUse[128];
CObjectVector<CPartitionMap> PartitionMaps;
CObjectVector<CFileSet> FileSets;
// CExtent IntegritySequenceExtent;
UString GetName() const { return Id.GetString(); }
};
struct CProgressVirt
{
virtual HRESULT SetTotal(UInt64 numBytes) PURE;
@@ -335,33 +433,11 @@ struct CProgressVirt
class CInArchive
{
IInStream *_stream;
CProgressVirt *_progress;
HRESULT Read(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);
HRESULT Read(int volIndex, const CLongAllocDesc &lad, Byte *buf);
HRESULT ReadFromFile(int volIndex, const CItem &item, CByteBuffer &buf);
HRESULT ReadFileItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT ReadItem(int volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT Open2();
HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);
UInt64 _processedProgressBytes;
UInt64 _fileNameLengthTotal;
unsigned _numRefs;
UInt32 _numExtents;
UInt64 _inlineExtentsSize;
bool CheckExtent(int volIndex, int partitionRef, UInt32 blockPos, UInt32 len) const;
public:
CObjectVector<CPartition> Partitions;
CObjectVector<CLogVol> LogVols;
CObjectVector<CItem> Items;
CObjectVector<CFile> Files;
CObjectVector<CPartition> Partitions;
unsigned SecLogSize;
UInt64 PhySize;
@@ -372,19 +448,49 @@ public:
bool UnexpectedEnd;
bool NoEndAnchor;
CObjectVector<CPrimeVol> PrimeVols;
HRESULT Open(IInStream *inStream, CProgressVirt *progress);
void Clear();
UString GetComment() const;
UString GetItemPath(unsigned volIndex, unsigned fsIndex, unsigned refIndex,
bool showVolName, bool showFsName) const;
bool CheckItemExtents(unsigned volIndex, const CItem &item) const;
private:
IInStream *_stream;
CProgressVirt *_progress;
HRESULT Read(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len, Byte *buf);
HRESULT ReadLad(unsigned volIndex, const CLongAllocDesc &lad, Byte *buf);
HRESULT ReadFromFile(unsigned volIndex, const CItem &item, CByteBuffer &buf);
HRESULT ReadFileItem(unsigned volIndex, unsigned fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT ReadItem(unsigned volIndex, int fsIndex, const CLongAllocDesc &lad, int numRecurseAllowed);
HRESULT Open2();
HRESULT FillRefs(CFileSet &fs, unsigned fileIndex, int parent, int numRecurseAllowed);
UInt64 _processedProgressBytes;
UInt64 _fileNameLengthTotal;
unsigned _numRefs;
UInt32 _numExtents;
UInt64 _inlineExtentsSize;
bool CheckExtent(unsigned volIndex, unsigned partitionRef, UInt32 blockPos, UInt32 len) const;
void UpdatePhySize(UInt64 val)
{
if (PhySize < val)
PhySize = val;
}
HRESULT Open(IInStream *inStream, CProgressVirt *progress);
void Clear();
UString GetComment() const;
UString GetItemPath(int volIndex, int fsIndex, int refIndex,
bool showVolName, bool showFsName) const;
bool CheckItemExtents(int volIndex, const CItem &item) const;
void UpdatePhySize(const CExtent &e)
{
UpdatePhySize(((UInt64)e.Pos << SecLogSize) + e.Len);
}
};
API_FUNC_IsArc IsArc_Udf(const Byte *p, size_t size);