Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-06-15 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:54 +0300
commit54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch)
treec3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive/Wim
parent0713a3ab803e57401f18432148b4139e5fe6e5dd (diff)
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive/Wim')
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.cpp67
-rw-r--r--CPP/7zip/Archive/Wim/WimHandler.h2
-rw-r--r--CPP/7zip/Archive/Wim/WimHandlerOut.cpp43
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.cpp90
-rw-r--r--CPP/7zip/Archive/Wim/WimIn.h4
-rw-r--r--CPP/7zip/Archive/Wim/WimRegister.cpp13
6 files changed, 146 insertions, 73 deletions
diff --git a/CPP/7zip/Archive/Wim/WimHandler.cpp b/CPP/7zip/Archive/Wim/WimHandler.cpp
index 886d8d77..bca551a6 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandler.cpp
@@ -37,7 +37,9 @@ static const Byte kProps[] =
kpidMethod,
kpidShortName,
kpidINode,
- kpidLinks
+ kpidLinks,
+ kpidIsAltStream,
+ kpidNumAltStreams,
#ifdef WIM_DETAILS
, kpidVolume
@@ -269,14 +271,12 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
res = kMethodLZX;
if (xpress)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodXpress;
}
if (copy)
{
- if (!res.IsEmpty())
- res += ' ';
+ res.Add_Space_if_NotEmpty();
res += kMethodCopy;
}
prop = res;
@@ -308,6 +308,26 @@ STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
AddErrorMessage(s, "Some files have incorrect reference count");
if (!s.IsEmpty())
prop = s;
+ break;
+ }
+
+ case kpidReadOnly:
+ {
+ bool readOnly = false;
+ if (ThereIsError())
+ readOnly = true;
+ else if (_volumes.Size() != 0)
+ {
+ if (_version != kWimVersion
+ || _volumes.Size() != 2
+ || _volumes[0].Stream
+ // || _db.Images.Size() > kNumImagesMax
+ )
+ readOnly = true;
+ }
+ if (readOnly)
+ prop = readOnly;
+ break;
}
}
prop.Detach(value);
@@ -397,6 +417,22 @@ STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *val
case kpidSize: prop = (UInt64)(si ? si->Resource.UnpackSize : 0); break;
case kpidIsDir: prop = item.IsDir; break;
case kpidIsAltStream: prop = item.IsAltStream; break;
+ case kpidNumAltStreams:
+ {
+ if (!item.IsAltStream && mainItem->HasMetadata())
+ {
+ UInt32 dirRecordSize = _db.IsOldVersion ? kDirRecordSizeOld : kDirRecordSize;
+ UInt32 numAltStreams = Get16(metadata + dirRecordSize - 6);
+ if (numAltStreams != 0)
+ {
+ if (!item.IsDir)
+ numAltStreams--;
+ prop = numAltStreams;
+ }
+ }
+ break;
+ }
+
case kpidAttrib:
if (!item.IsAltStream && mainItem->ImageIndex >= 0)
{
@@ -481,7 +517,7 @@ STDMETHODIMP CHandler::GetRootProp(PROPID propID, PROPVARIANT *value)
{
// COM_TRY_BEGIN
NCOM::CPropVariant prop;
- if (_db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (_db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -532,7 +568,7 @@ STDMETHODIMP CHandler::GetRootRawProp(PROPID propID, const void **data, UInt32 *
*data = 0;
*dataSize = 0;
*propType = 0;
- if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExludededItems != 0)
+ if (propID == kpidNtSecure && _db.Images.Size() != 0 && _db.NumExcludededItems != 0)
{
const CImage &image = _db.Images[_db.IndexOfUserImage];
const CItem &item = _db.Items[image.StartItem];
@@ -705,7 +741,7 @@ class CVolumeName
public:
void InitName(const UString &name)
{
- int dotPos = name.ReverseFind('.');
+ int dotPos = name.ReverseFind_Dot();
if (dotPos < 0)
dotPos = name.Len();
_before = name.Left(dotPos);
@@ -798,11 +834,11 @@ STDMETHODIMP CHandler::Open(IInStream *inStream, const UInt64 *, IArchiveOpenCal
if (_xmls.IsEmpty() || xml.Data != _xmls[0].Data)
{
- wchar_t sz[16];
+ char sz[16];
ConvertUInt32ToString(xml.VolIndex, sz);
xml.FileName = L'[';
- xml.FileName += sz;
- xml.FileName += L"].xml";
+ xml.FileName.AddAscii(sz);
+ xml.FileName.AddAscii("].xml");
_xmls.Add(xml);
}
@@ -957,11 +993,12 @@ STDMETHODIMP CHandler::Extract(const UInt32 *indices, UInt32 numItems,
int streamIndex = item.StreamIndex;
if (streamIndex < 0)
{
- if (!testMode && !realOutStream)
- continue;
+ if (!item.IsDir)
+ if (!testMode && !realOutStream)
+ continue;
RINOK(extractCallback->PrepareOperation(askMode));
realOutStream.Release();
- RINOK(extractCallback->SetOperationResult(_db.ItemHasStream(item) ?
+ RINOK(extractCallback->SetOperationResult(!item.IsDir && _db.ItemHasStream(item) ?
NExtract::NOperationResult::kDataError :
NExtract::NOperationResult::kOK));
continue;
@@ -1016,7 +1053,7 @@ CHandler::CHandler()
_xmlError = false;
}
-STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps)
+STDMETHODIMP CHandler::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
{
InitDefaults();
diff --git a/CPP/7zip/Archive/Wim/WimHandler.h b/CPP/7zip/Archive/Wim/WimHandler.h
index 416e11ca..00de1b87 100644
--- a/CPP/7zip/Archive/Wim/WimHandler.h
+++ b/CPP/7zip/Archive/Wim/WimHandler.h
@@ -70,7 +70,7 @@ public:
INTERFACE_IInArchive(;)
INTERFACE_IArchiveGetRawProps(;)
INTERFACE_IArchiveGetRootProps(;)
- STDMETHOD(SetProperties)(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps);
+ STDMETHOD(SetProperties)(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps);
STDMETHOD(KeepModeForNextOpen)();
INTERFACE_IOutArchive(;)
};
diff --git a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
index 149989d1..145ede42 100644
--- a/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
+++ b/CPP/7zip/Archive/Wim/WimHandlerOut.cpp
@@ -21,7 +21,7 @@
#include "../../Common/UniqBlocks.h"
#include "../../Crypto/RandGen.h"
-#include "../../Crypto/Sha1.h"
+#include "../../Crypto/Sha1Cls.h"
#include "WimHandler.h"
@@ -676,6 +676,8 @@ static void AddTrees(CObjectVector<CDir> &trees, CObjectVector<CMetaItem> &metaI
trees.AddNew().Dirs.AddNew().MetaIndex = metaItems.Add(ri);
}
+#define IS_LETTER_CHAR(c) ((c) >= 'a' && (c) <= 'z' || (c) >= 'A' && (c) <= 'Z')
+
STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 numItems, IArchiveUpdateCallback *callback)
{
COM_TRY_BEGIN
@@ -789,7 +791,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
unsigned imageIndex = (unsigned)val - 1;
if (imageIndex < _db.Images.Size())
isChangedImage[imageIndex] = true;
- if (_defaultImageNumber > 0 && val != _defaultImageNumber)
+ if (_defaultImageNumber > 0 && val != (unsigned)_defaultImageNumber)
return E_INVALIDARG;
}
}
@@ -1065,9 +1067,16 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
int colonPos = fileName.Find(L':');
if (colonPos < 0)
return E_INVALIDARG;
+
+ // we want to support cases of c::substream, where c: is drive name
+ if (colonPos == 1 && fileName[2] == L':' && IS_LETTER_CHAR(fileName[0]))
+ colonPos = 2;
const UString mainName = fileName.Left(colonPos);
unsigned indexOfDir;
- if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
+
+ if (mainName.IsEmpty())
+ ui.MetaIndex = curItem->MetaIndex;
+ else if (curItem->FindDir(db.MetaItems, mainName, indexOfDir))
ui.MetaIndex = curItem->Dirs[indexOfDir].MetaIndex;
else
{
@@ -1082,6 +1091,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
}
}
}
+
if (ui.MetaIndex >= 0)
{
CAltStream ss;
@@ -1126,7 +1136,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
NCOM::CPropVariant prop;
RINOK(GetOutProperty(callback, i, arcIndex, kpidShortName, &prop));
if (prop.vt == VT_BSTR)
- mi.ShortName = prop.bstrVal;
+ mi.ShortName.SetFromBstr(prop.bstrVal);
else if (prop.vt != VT_EMPTY)
return E_INVALIDARG;
}
@@ -1235,7 +1245,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CItem &item = _db.Items[k];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
}
@@ -1250,7 +1260,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
continue;
const CItem &item = _db.Items[_db.SortedItems[ui.InArcIndex]];
if (item.StreamIndex >= 0)
- streamsRefs[item.StreamIndex]++;
+ streamsRefs[(unsigned)item.StreamIndex]++;
}
else
{
@@ -1614,7 +1624,7 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
db.DefaultDirItem = ri;
pos += db.WriteTree_Dummy(tree);
- CByteBuffer meta(pos);
+ CByteArr meta(pos);
Set32((Byte *)meta + 4, secBufs.Size()); // num security entries
pos = kSecuritySize;
@@ -1637,8 +1647,11 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
{
const CByteBuffer &buf = secBufs[i];
size_t size = buf.Size();
- memcpy(meta + pos, buf, size);
- pos += size;
+ if (size != 0)
+ {
+ memcpy(meta + pos, buf, size);
+ pos += size;
+ }
}
while ((pos & 7) != 0)
meta[pos++] = 0;
@@ -1740,15 +1753,15 @@ STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outSeqStream, UInt32 nu
size_t xmlSize;
{
- UString utf16String;
- if (!ConvertUTF8ToUnicode(xml, utf16String))
+ UString utf16;
+ if (!ConvertUTF8ToUnicode(xml, utf16))
return S_FALSE;
- xmlSize = (utf16String.Len() + 1) * 2;
+ xmlSize = (utf16.Len() + 1) * 2;
- CByteBuffer xmlBuf(xmlSize);
+ CByteArr xmlBuf(xmlSize);
Set16((Byte *)xmlBuf, 0xFEFF);
- for (i = 0; i < (unsigned)utf16String.Len(); i++)
- Set16((Byte *)xmlBuf + 2 + i * 2, utf16String[i]);
+ for (i = 0; i < (unsigned)utf16.Len(); i++)
+ Set16((Byte *)xmlBuf + 2 + i * 2, utf16[i]);
RINOK(WriteStream(outStream, (const Byte *)xmlBuf, xmlSize));
}
diff --git a/CPP/7zip/Archive/Wim/WimIn.cpp b/CPP/7zip/Archive/Wim/WimIn.cpp
index cec037cc..12b8525c 100644
--- a/CPP/7zip/Archive/Wim/WimIn.cpp
+++ b/CPP/7zip/Archive/Wim/WimIn.cpp
@@ -325,10 +325,13 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
unsigned size = 0;
int index = index1;
- unsigned newLevel;
int imageIndex = Items[index].ImageIndex;
const CImage &image = Images[imageIndex];
- for (newLevel = 0;;)
+
+ unsigned newLevel = 0;
+ bool needColon = false;
+
+ for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
@@ -338,10 +341,11 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
meta += item.IsAltStream ?
(IsOldVersion ? 0x10 : 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
+ needColon = item.IsAltStream;
size += Get16(meta) / 2;
size += newLevel;
newLevel = 1;
- if ((UInt32)size >= ((UInt32)1 << 15))
+ if (size >= ((UInt32)1 << 15))
{
path = kLongPath;
return;
@@ -356,7 +360,9 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
size += image.RootName.Len();
size += newLevel;
}
-
+ else if (needColon)
+ size++;
+
wchar_t *s = path.AllocBstr(size);
s[size] = 0;
@@ -364,28 +370,31 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
{
MyStringCopy(s, (const wchar_t *)image.RootName);
if (newLevel)
- s[image.RootName.Len()] = WCHAR_PATH_SEPARATOR;
+ s[image.RootName.Len()] = (wchar_t)(needColon ? L':' : WCHAR_PATH_SEPARATOR);
}
+ else if (needColon)
+ s[0] = L':';
index = index1;
wchar_t separator = 0;
+
for (;;)
{
const CItem &item = Items[index];
index = item.Parent;
if (index >= 0 || image.NumEmptyRootItems == 0)
{
- if (separator)
+ if (separator != 0)
s[--size] = separator;
const Byte *meta = image.Meta + item.Offset;
meta += (item.IsAltStream) ?
(IsOldVersion ? 0x10: 0x24) :
(IsOldVersion ? kDirRecordSizeOld - 2 : kDirRecordSize - 2);
- UInt32 len = Get16(meta) / 2;
+ unsigned len = Get16(meta) / 2;
size -= len;
wchar_t *dest = s + size;
meta += 2;
- for (UInt32 i = 0; i < len; i++)
+ for (unsigned i = 0; i < len; i++)
dest[i] = Get16(meta + i * 2);
}
if (index < 0)
@@ -394,6 +403,14 @@ void CDatabase::GetItemPath(unsigned index1, bool showImageNumber, NWindows::NCO
}
}
+static bool IsEmptySha(const Byte *data)
+{
+ for (unsigned i = 0; i < kHashSize; i++)
+ if (data[i] != 0)
+ return false;
+ return true;
+}
+
// Root folders in OLD archives (ver = 1.10) conatin real items.
// Root folders in NEW archives (ver > 1.11) contain only one folder with empty name.
@@ -472,6 +489,8 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
pos += (size_t)len;
+ unsigned numItems2 = Items.Size();
+
for (UInt32 i = 0; i < numAltStreams; i++)
{
size_t rem = DirSize - pos;
@@ -522,7 +541,13 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
return S_FALSE;
}
- if (fileNameLen == 0)
+
+ /* wim uses alt sreams list, if there is at least one alt stream.
+ And alt stream without name is main stream. */
+
+ if (fileNameLen == 0 &&
+ (attrib & FILE_ATTRIBUTE_REPARSE_POINT
+ || !item.IsDir /* && (IsOldVersion || IsEmptySha(prevMeta + 0x40)) */ ))
{
Byte *prevMeta = DirData + item.Offset;
if (IsOldVersion)
@@ -546,7 +571,7 @@ HRESULT CDatabase::ParseDirItem(size_t pos, int parent)
if (parent < 0 && numItems == 0 && shortNameLen == 0 && fileNameLen == 0 && item.IsDir)
{
CImage &image = Images.Back();
- image.NumEmptyRootItems = Items.Size() - image.StartItem;
+ image.NumEmptyRootItems = numItems2 - image.StartItem; // Items.Size()
}
if (item.IsDir && subdirOffset != 0)
@@ -732,14 +757,6 @@ static HRESULT ReadStreams(IInStream *inStream, const CHeader &h, CDatabase &db)
return (i == offsetBuf.Size()) ? S_OK : S_FALSE;
}
-static bool IsEmptySha(const Byte *data)
-{
- for (unsigned i = 0; i < kHashSize; i++)
- if (data[i] != 0)
- return false;
- return true;
-}
-
HRESULT CDatabase::OpenXml(IInStream *inStream, const CHeader &h, CByteBuffer &xml)
{
return UnpackData(inStream, h.XmlResource, h.IsLzxMode(), xml, NULL);
@@ -1046,7 +1063,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
SortedItems.Clear();
VirtualRoots.Clear();
IndexOfUserImage = imageIndex;
- NumExludededItems = 0;
+ NumExcludededItems = 0;
ExludedItem = -1;
if (Images.Size() != 1 && imageIndex < 0)
@@ -1054,6 +1071,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
unsigned startItem = 0;
unsigned endItem = 0;
+
if (imageIndex < 0)
{
endItem = Items.Size();
@@ -1062,7 +1080,7 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
IndexOfUserImage = 0;
const CImage &image = Images[0];
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
}
else if ((unsigned)imageIndex < Images.Size())
@@ -1071,12 +1089,13 @@ HRESULT CDatabase::GenerateSortedItems(int imageIndex, bool showImageNumber)
startItem = image.StartItem;
endItem = startItem + image.NumItems;
if (!showImageNumber)
- NumExludededItems = image.NumEmptyRootItems;
+ NumExcludededItems = image.NumEmptyRootItems;
}
- if (NumExludededItems != 0)
+
+ if (NumExcludededItems != 0)
{
ExludedItem = startItem;
- startItem += NumExludededItems;
+ startItem += NumExcludededItems;
}
unsigned num = endItem - startItem;
@@ -1205,7 +1224,8 @@ HRESULT CDatabase::ExtractReparseStreams(const CObjectVector<CVolume> &volumes,
Byte *dest = (Byte *)reparse;
SetUi32(dest, tag);
SetUi32(dest + 4, (UInt32)buf.Size());
- memcpy(dest + 8, buf, buf.Size());
+ if (buf.Size() != 0)
+ memcpy(dest + 8, buf, buf.Size());
ItemToReparse[i] = ReparseItems.Size() - 1;
}
@@ -1278,20 +1298,28 @@ void CWimXml::ToUnicode(UString &s)
const Byte *p = Data;
if (Get16(p) != 0xFEFF)
return;
- wchar_t *chars = s.GetBuffer((unsigned)size / 2);
+ wchar_t *chars = s.GetBuf((unsigned)(size / 2));
for (size_t i = 2; i < size; i += 2)
- *chars++ = (wchar_t)Get16(p + i);
+ {
+ wchar_t c = Get16(p + i);
+ if (c == 0)
+ break;
+ *chars++ = c;
+ }
*chars = 0;
- s.ReleaseBuffer();
+ s.ReleaseBuf_SetLen((unsigned)(chars - (const wchar_t *)s));
}
bool CWimXml::Parse()
{
- UString s;
- ToUnicode(s);
AString utf;
- if (!ConvertUnicodeToUTF8(s, utf))
- return false;
+ {
+ UString s;
+ ToUnicode(s);
+ // if (!ConvertUnicodeToUTF8(s, utf)) return false;
+ ConvertUnicodeToUTF8(s, utf);
+ }
+
if (!Xml.Parse(utf))
return false;
if (Xml.Root.Name != "WIM")
diff --git a/CPP/7zip/Archive/Wim/WimIn.h b/CPP/7zip/Archive/Wim/WimIn.h
index 4b7c6d95..c3b93a8d 100644
--- a/CPP/7zip/Archive/Wim/WimIn.h
+++ b/CPP/7zip/Archive/Wim/WimIn.h
@@ -406,7 +406,7 @@ public:
CUIntVector SortedItems;
int IndexOfUserImage; // -1 : if more than one images was filled to Sorted Items
- unsigned NumExludededItems;
+ unsigned NumExcludededItems;
int ExludedItem; // -1 : if there are no exclude items
CUIntVector VirtualRoots; // we use them for old 1.10 WIM archives
@@ -418,7 +418,7 @@ public:
return 0;
if (imageIndex >= Images.Size())
return 0;
- return Images[imageIndex].NumItems - NumExludededItems;
+ return Images[imageIndex].NumItems - NumExcludededItems;
}
bool ItemHasStream(const CItem &item) const;
diff --git a/CPP/7zip/Archive/Wim/WimRegister.cpp b/CPP/7zip/Archive/Wim/WimRegister.cpp
index 35d78314..3063dec4 100644
--- a/CPP/7zip/Archive/Wim/WimRegister.cpp
+++ b/CPP/7zip/Archive/Wim/WimRegister.cpp
@@ -9,19 +9,14 @@
namespace NArchive {
namespace NWim {
-IMP_CreateArcIn
-IMP_CreateArcOut
-
-static CArcInfo g_ArcInfo =
- { "wim", "wim swm", 0, 0xE6,
- 8, { 'M', 'S', 'W', 'I', 'M', 0, 0, 0 },
+REGISTER_ARC_IO(
+ "wim", "wim swm", 0, 0xE6,
+ kSignature,
0,
NArcInfoFlags::kAltStreams |
NArcInfoFlags::kNtSecure |
NArcInfoFlags::kSymLinks |
NArcInfoFlags::kHardLinks
- , REF_CreateArc_Pair };
-
-REGISTER_ARC(Wim)
+ , NULL)
}}