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>2007-01-20 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:15:49 +0300
commitd9666cf046a8453b33b3e2fbf4d82295a9f87df3 (patch)
treec722ed19b844b53042aec0c1d7d2f8381140a5ed /CPP/7zip/Archive/Tar/TarIn.cpp
parent804edc5756fede54dbb1aefda6d39d306111938d (diff)
4.44 beta
Diffstat (limited to 'CPP/7zip/Archive/Tar/TarIn.cpp')
-rwxr-xr-xCPP/7zip/Archive/Tar/TarIn.cpp248
1 files changed, 248 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Tar/TarIn.cpp b/CPP/7zip/Archive/Tar/TarIn.cpp
new file mode 100755
index 00000000..86afc482
--- /dev/null
+++ b/CPP/7zip/Archive/Tar/TarIn.cpp
@@ -0,0 +1,248 @@
+// Archive/TarIn.cpp
+
+#include "StdAfx.h"
+
+#include "TarIn.h"
+#include "TarHeader.h"
+
+#include "Common/StringToInt.h"
+#include "Windows/Defs.h"
+
+#include "../../Common/StreamUtils.h"
+
+namespace NArchive {
+namespace NTar {
+
+HRESULT CInArchive::ReadBytes(void *data, UInt32 size, UInt32 &processedSize)
+{
+ RINOK(ReadStream(m_Stream, data, size, &processedSize));
+ m_Position += processedSize;
+ return S_OK;
+}
+
+HRESULT CInArchive::Open(IInStream *inStream)
+{
+ RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_Position));
+ m_Stream = inStream;
+ return S_OK;
+}
+
+static void MyStrNCpy(char *dest, const char *src, int size)
+{
+ for (int i = 0; i < size; i++)
+ {
+ char c = src[i];
+ dest[i] = c;
+ if (c == 0)
+ break;
+ }
+}
+
+static bool OctalToNumber(const char *srcString, int size, UInt64 &res)
+{
+ char sz[32];
+ MyStrNCpy(sz, srcString, size);
+ sz[size] = 0;
+ const char *end;
+ int i;
+ for (i = 0; sz[i] == ' '; i++);
+ res = ConvertOctStringToUInt64(sz + i, &end);
+ return (*end == ' ' || *end == 0);
+}
+
+static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)
+{
+ UInt64 res64;
+ if (!OctalToNumber(srcString, size, res64))
+ return false;
+ res = (UInt32)res64;
+ return (res64 <= 0xFFFFFFFF);
+}
+
+#define RIF(x) { if (!(x)) return S_FALSE; }
+
+static bool IsRecordLast(const char *record)
+{
+ for (int i = 0; i < NFileHeader::kRecordSize; i++)
+ if (record[i] != 0)
+ return false;
+ return true;
+}
+
+static void ReadString(const char *s, int size, AString &result)
+{
+ if (size > NFileHeader::kRecordSize)
+ size = NFileHeader::kNameSize;
+ char tempString[NFileHeader::kRecordSize + 1];
+ MyStrNCpy(tempString, s, size);
+ tempString[size] = '\0';
+ result = tempString;
+}
+
+static char GetHex(Byte value)
+{
+ return (char)((value < 10) ? ('0' + value) : ('A' + (value - 10)));
+}
+
+HRESULT CInArchive::GetNextItemReal(bool &filled, CItemEx &item)
+{
+ item.LongLinkSize = 0;
+ // NFileHeader::CRecord record;
+ char record[NFileHeader::kRecordSize];
+ char *cur = record;
+
+ filled = false;
+
+ UInt32 processedSize;
+ item.HeaderPosition = m_Position;
+ RINOK(ReadBytes(record, NFileHeader::kRecordSize, processedSize));
+ if (processedSize == 0 ||
+ (processedSize == NFileHeader::kRecordSize && IsRecordLast(record)))
+ return S_OK;
+ if (processedSize < NFileHeader::kRecordSize)
+ return S_FALSE;
+
+ // NFileHeader::CHeader &header = record.Header;
+
+ AString name;
+ ReadString(cur, NFileHeader::kNameSize, name);
+ cur += NFileHeader::kNameSize;
+
+ item.Name.Empty();
+ int i;
+ for (i = 0; i < name.Length(); i++)
+ {
+ char c = name[i];
+ if (((Byte)c) < 0x08)
+ {
+ return S_FALSE;
+ }
+ if (((Byte)c) < 0x20)
+ {
+ item.Name += '[';
+ item.Name += GetHex((Byte)(((Byte)c) >> 4));
+ item.Name += GetHex((Byte)(((Byte)c) & 0xF));
+ item.Name += ']';
+ }
+ else
+ item.Name += c;
+ }
+
+ RIF(OctalToNumber32(cur, 8, item.Mode));
+ cur += 8;
+
+ if (!OctalToNumber32(cur, 8, item.UID))
+ item.UID = 0;
+ cur += 8;
+
+ if (!OctalToNumber32(cur, 8, item.GID))
+ item.GID = 0;
+ cur += 8;
+
+ RIF(OctalToNumber(cur, 12, item.Size));
+ cur += 12;
+
+ RIF(OctalToNumber32(cur, 12, item.ModificationTime));
+ cur += 12;
+
+ UInt32 checkSum;
+ RIF(OctalToNumber32(cur, 8, checkSum));
+ memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+ cur += 8;
+
+ item.LinkFlag = *cur++;
+
+ ReadString(cur, NFileHeader::kNameSize, item.LinkName);
+ cur += NFileHeader::kNameSize;
+
+ memmove(item.Magic, cur, 8);
+ cur += 8;
+
+ ReadString(cur, NFileHeader::kUserNameSize, item.UserName);
+ cur += NFileHeader::kUserNameSize;
+ ReadString(cur, NFileHeader::kUserNameSize, item.GroupName);
+ cur += NFileHeader::kUserNameSize;
+
+ item.DeviceMajorDefined = (cur[0] != 0);
+ RIF(OctalToNumber32(cur, 8, item.DeviceMajor));
+ cur += 8;
+
+ item.DeviceMinorDefined = (cur[0] != 0);
+ RIF(OctalToNumber32(cur, 8, item.DeviceMinor));
+ cur += 8;
+
+ AString prefix;
+ ReadString(cur, NFileHeader::kPrefixSize, prefix);
+ cur += NFileHeader::kPrefixSize;
+ if (!prefix.IsEmpty() && item.IsMagic())
+ item.Name = prefix + AString('/') + item.Name;
+
+ if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
+ item.Size = 0;
+
+
+ UInt32 checkSumReal = 0;
+ for(i = 0; i < NFileHeader::kRecordSize; i++)
+ checkSumReal += Byte(record[i]);
+
+ if (checkSumReal != checkSum)
+ return S_FALSE;
+
+ filled = true;
+ return S_OK;
+}
+
+HRESULT CInArchive::GetNextItem(bool &filled, CItemEx &item)
+{
+ RINOK(GetNextItemReal(filled, item));
+ if (!filled)
+ return S_OK;
+ // GNUtar extension
+ if (item.LinkFlag == 'L')
+ {
+ if (item.Name.Compare(NFileHeader::kLongLink) != 0)
+ if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
+ return S_FALSE;
+ UInt64 headerPosition = item.HeaderPosition;
+
+ UInt32 processedSize;
+ AString fullName;
+ char *buffer = fullName.GetBuffer((UInt32)item.Size + 1);
+ RINOK(ReadBytes(buffer, (UInt32)item.Size, processedSize));
+ buffer[item.Size] = '\0';
+ fullName.ReleaseBuffer();
+ if (processedSize != item.Size)
+ return S_FALSE;
+ RINOK(Skeep((0 - item.Size) & 0x1FF));
+ RINOK(GetNextItemReal(filled, item));
+ item.Name = fullName;
+ item.LongLinkSize = item.HeaderPosition - headerPosition;
+ item.HeaderPosition = headerPosition;
+ }
+ else if (item.LinkFlag == 'g' || item.LinkFlag == 'x')
+ {
+ // pax Extended Header
+ return S_OK;
+ }
+ else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
+ return S_FALSE;
+ return S_OK;
+}
+
+HRESULT CInArchive::Skeep(UInt64 numBytes)
+{
+ UInt64 newPostion;
+ RINOK(m_Stream->Seek(numBytes, STREAM_SEEK_CUR, &newPostion));
+ m_Position += numBytes;
+ if (m_Position != newPostion)
+ return E_FAIL;
+ return S_OK;
+}
+
+
+HRESULT CInArchive::SkeepDataRecords(UInt64 dataSize)
+{
+ return Skeep((dataSize + 0x1FF) & (~((UInt64)0x1FF)));
+}
+
+}}