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:
Diffstat (limited to 'CPP/7zip/Archive/Tar/TarOut.cpp')
-rw-r--r--[-rwxr-xr-x]CPP/7zip/Archive/Tar/TarOut.cpp230
1 files changed, 138 insertions, 92 deletions
diff --git a/CPP/7zip/Archive/Tar/TarOut.cpp b/CPP/7zip/Archive/Tar/TarOut.cpp
index 6e699e28..51081e8b 100755..100644
--- a/CPP/7zip/Archive/Tar/TarOut.cpp
+++ b/CPP/7zip/Archive/Tar/TarOut.cpp
@@ -2,8 +2,6 @@
#include "StdAfx.h"
-#include "Common/IntToString.h"
-
#include "../../Common/StreamUtils.h"
#include "TarOut.h"
@@ -11,26 +9,15 @@
namespace NArchive {
namespace NTar {
-HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
-{
- return WriteStream(m_Stream, buffer, size);
-}
-
-void COutArchive::Create(ISequentialOutStream *outStream)
-{
- m_Stream = outStream;
-}
-
-static AString MakeOctalString(UInt64 value)
+HRESULT COutArchive::WriteBytes(const void *data, unsigned size)
{
- char s[32];
- ConvertUInt64ToString(value, s, 8);
- return AString(s) + ' ';
+ Pos += size;
+ return WriteStream(m_Stream, data, size);
}
-static void MyStrNCpy(char *dest, const char *src, int size)
+static void MyStrNCpy(char *dest, const char *src, unsigned size)
{
- for (int i = 0; i < size; i++)
+ for (unsigned i = 0; i < size; i++)
{
char c = src[i];
dest[i] = c;
@@ -39,54 +26,53 @@ static void MyStrNCpy(char *dest, const char *src, int size)
}
}
-static bool MakeOctalString8(char *s, UInt32 value)
+static bool WriteOctal_8(char *s, UInt32 val)
{
- AString tempString = MakeOctalString(value);
-
- const int kMaxSize = 8;
- if (tempString.Length() >= kMaxSize)
+ const unsigned kNumDigits = 8 - 1;
+ if (val >= ((UInt32)1 << (kNumDigits * 3)))
return false;
- int numSpaces = kMaxSize - (tempString.Length() + 1);
- for (int i = 0; i < numSpaces; i++)
- s[i] = ' ';
- MyStringCopy(s + numSpaces, (const char *)tempString);
+ for (unsigned i = 0; i < kNumDigits; i++)
+ {
+ s[kNumDigits - 1 - i] = (char)('0' + (val & 7));
+ val >>= 3;
+ }
return true;
}
-static void MakeOctalString12(char *s, UInt64 value)
+static void WriteOctal_12(char *s, UInt64 val)
{
- AString tempString = MakeOctalString(value);
- const int kMaxSize = 12;
- if (tempString.Length() > kMaxSize)
+ const unsigned kNumDigits = 12 - 1;
+ if (val >= ((UInt64)1 << (kNumDigits * 3)))
{
// GNU extension;
s[0] = (char)(Byte)0x80;
s[1] = s[2] = s[3] = 0;
- for (int i = 0; i < 8; i++, value <<= 8)
- s[4 + i] = (char)(value >> 56);
+ for (unsigned i = 0; i < 8; i++, val <<= 8)
+ s[4 + i] = (char)(val >> 56);
return;
}
- int numSpaces = kMaxSize - tempString.Length();
- for (int i = 0; i < numSpaces; i++)
- s[i] = ' ';
- memmove(s + numSpaces, (const char *)tempString, tempString.Length());
+ for (unsigned i = 0; i < kNumDigits; i++)
+ {
+ s[kNumDigits - 1 - i] = (char)('0' + (val & 7));
+ val >>= 3;
+ }
}
-static void MakeOctalString12_From_Int64(char *s, Int64 value)
+static void WriteOctal_12_Signed(char *s, Int64 val)
{
- if (value >= 0)
+ if (val >= 0)
{
- MakeOctalString12(s, value);
+ WriteOctal_12(s, val);
return;
}
s[0] = s[1] = s[2] = s[3] = (char)(Byte)0xFF;
- for (int i = 0; i < 8; i++, value <<= 8)
- s[4 + i] = (char)(value >> 56);
+ for (unsigned i = 0; i < 8; i++, val <<= 8)
+ s[4 + i] = (char)(val >> 56);
}
-static bool CopyString(char *dest, const AString &src, int maxSize)
+static bool CopyString(char *dest, const AString &src, unsigned maxSize)
{
- if (src.Length() >= maxSize)
+ if (src.Len() >= maxSize)
return false;
MyStringCopy(dest, (const char *)src);
return true;
@@ -97,25 +83,22 @@ static bool CopyString(char *dest, const AString &src, int maxSize)
HRESULT COutArchive::WriteHeaderReal(const CItem &item)
{
char record[NFileHeader::kRecordSize];
+ memset(record, 0, NFileHeader::kRecordSize);
char *cur = record;
- int i;
- for (i = 0; i < NFileHeader::kRecordSize; i++)
- record[i] = 0;
- // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));
- if (item.Name.Length() > NFileHeader::kNameSize)
+ if (item.Name.Len() > NFileHeader::kNameSize)
return E_FAIL;
MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
cur += NFileHeader::kNameSize;
- RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
- RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
- RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
+ RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.Mode)); cur += 8;
+ RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.UID)); cur += 8;
+ RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.GID)); cur += 8;
- MakeOctalString12(cur, item.PackSize); cur += 12;
- MakeOctalString12_From_Int64(cur, item.MTime); cur += 12;
+ WriteOctal_12(cur, item.PackSize); cur += 12;
+ WriteOctal_12_Signed(cur, item.MTime); cur += 12;
- memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+ memset(cur, ' ', 8);
cur += 8;
*cur++ = item.LinkFlag;
@@ -123,7 +106,7 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));
cur += NFileHeader::kNameSize;
- memmove(cur, item.Magic, 8);
+ memcpy(cur, item.Magic, 8);
cur += 8;
RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize));
@@ -132,64 +115,127 @@ HRESULT COutArchive::WriteHeaderReal(const CItem &item)
cur += NFileHeader::kGroupNameSize;
- if (item.DeviceMajorDefined)
- RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));
- cur += 8;
+ if (item.DeviceMajorDefined) RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.DeviceMajor)); cur += 8;
+ if (item.DeviceMinorDefined) RETURN_IF_NOT_TRUE(WriteOctal_8(cur, item.DeviceMinor)); cur += 8;
- if (item.DeviceMinorDefined)
- RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));
- cur += 8;
+ if (item.IsSparse())
+ {
+ record[482] = (char)(item.SparseBlocks.Size() > 4 ? 1 : 0);
+ WriteOctal_12(record + 483, item.Size);
+ for (unsigned i = 0; i < item.SparseBlocks.Size() && i < 4; i++)
+ {
+ const CSparseBlock &sb = item.SparseBlocks[i];
+ char *p = record + 386 + 24 * i;
+ WriteOctal_12(p, sb.Offset);
+ WriteOctal_12(p + 12, sb.Size);
+ }
+ }
+ {
+ UInt32 checkSum = 0;
+ {
+ for (unsigned i = 0; i < NFileHeader::kRecordSize; i++)
+ checkSum += (Byte)record[i];
+ }
+ /* we use GNU TAR scheme:
+ checksum field is formatted differently from the
+ other fields: it has [6] digits, a null, then a space. */
+ // RETURN_IF_NOT_TRUE(WriteOctal_8(record + 148, checkSum));
+ const unsigned kNumDigits = 6;
+ for (unsigned i = 0; i < kNumDigits; i++)
+ {
+ record[148 + kNumDigits - 1 - i] = (char)('0' + (checkSum & 7));
+ checkSum >>= 3;
+ }
+ record[148 + 6] = 0;
+ }
- UInt32 checkSumReal = 0;
- for (i = 0; i < NFileHeader::kRecordSize; i++)
- checkSumReal += Byte(record[i]);
+ RINOK(WriteBytes(record, NFileHeader::kRecordSize));
- RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
+ if (item.IsSparse())
+ {
+ for (unsigned i = 4; i < item.SparseBlocks.Size();)
+ {
+ memset(record, 0, NFileHeader::kRecordSize);
+ for (unsigned t = 0; t < 21 && i < item.SparseBlocks.Size(); t++, i++)
+ {
+ const CSparseBlock &sb = item.SparseBlocks[i];
+ char *p = record + 24 * t;
+ WriteOctal_12(p, sb.Offset);
+ WriteOctal_12(p + 12, sb.Size);
+ }
+ record[21 * 24] = (char)(i < item.SparseBlocks.Size() ? 1 : 0);
+ RINOK(WriteBytes(record, NFileHeader::kRecordSize));
+ }
+ }
- return WriteBytes(record, NFileHeader::kRecordSize);
+ return S_OK;
}
HRESULT COutArchive::WriteHeader(const CItem &item)
{
- int nameSize = item.Name.Length();
- if (nameSize < NFileHeader::kNameSize)
+ unsigned nameSize = item.Name.Len();
+ unsigned linkSize = item.LinkName.Len();
+
+ /* There two versions of GNU tar:
+ OLDGNU_FORMAT: it writes short name and zero at the end
+ GNU_FORMAT: it writes only short name without zero at the end
+ we write it as OLDGNU_FORMAT with zero at the end */
+
+ if (nameSize < NFileHeader::kNameSize &&
+ linkSize < NFileHeader::kNameSize)
return WriteHeaderReal(item);
- CItem modifiedItem = item;
- int nameStreamSize = nameSize + 1;
- modifiedItem.PackSize = nameStreamSize;
- modifiedItem.LinkFlag = 'L';
- modifiedItem.Name = NFileHeader::kLongLink;
- modifiedItem.LinkName.Empty();
- RINOK(WriteHeaderReal(modifiedItem));
- RINOK(WriteBytes(item.Name, nameStreamSize));
- RINOK(FillDataResidual(nameStreamSize));
-
- modifiedItem = item;
- modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1);
- return WriteHeaderReal(modifiedItem);
+ CItem mi = item;
+ mi.Name = NFileHeader::kLongLink;
+ mi.LinkName.Empty();
+ for (int i = 0; i < 2; i++)
+ {
+ const AString *name;
+ // We suppose that GNU tar also writes item for long link before item for LongName?
+ if (i == 0)
+ {
+ mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongLink;
+ name = &item.LinkName;
+ }
+ else
+ {
+ mi.LinkFlag = NFileHeader::NLinkFlag::kGnu_LongName;
+ name = &item.Name;
+ }
+ if (name->Len() < NFileHeader::kNameSize)
+ continue;
+ unsigned nameStreamSize = name->Len() + 1;
+ mi.PackSize = nameStreamSize;
+ RINOK(WriteHeaderReal(mi));
+ RINOK(WriteBytes((const char *)*name, nameStreamSize));
+ RINOK(FillDataResidual(nameStreamSize));
+ }
+
+ mi = item;
+ if (mi.Name.Len() >= NFileHeader::kNameSize)
+ mi.Name.SetFrom(item.Name, NFileHeader::kNameSize - 1);
+ if (mi.LinkName.Len() >= NFileHeader::kNameSize)
+ mi.LinkName.SetFrom(item.LinkName, NFileHeader::kNameSize - 1);
+ return WriteHeaderReal(mi);
}
HRESULT COutArchive::FillDataResidual(UInt64 dataSize)
{
- UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1));
+ unsigned lastRecordSize = ((unsigned)dataSize & (NFileHeader::kRecordSize - 1));
if (lastRecordSize == 0)
return S_OK;
- UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize;
- Byte residualBytes[NFileHeader::kRecordSize];
- for (UInt32 i = 0; i < residualSize; i++)
- residualBytes[i] = 0;
- return WriteBytes(residualBytes, residualSize);
+ unsigned rem = NFileHeader::kRecordSize - lastRecordSize;
+ Byte buf[NFileHeader::kRecordSize];
+ memset(buf, 0, rem);
+ return WriteBytes(buf, rem);
}
HRESULT COutArchive::WriteFinishHeader()
{
Byte record[NFileHeader::kRecordSize];
- int i;
- for (i = 0; i < NFileHeader::kRecordSize; i++)
- record[i] = 0;
- for (i = 0; i < 2; i++)
+ memset(record, 0, NFileHeader::kRecordSize);
+ for (unsigned i = 0; i < 2; i++)
{
RINOK(WriteBytes(record, NFileHeader::kRecordSize));
}