summaryrefslogtreecommitdiffstats
path: root/src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp')
-rw-r--r--src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp187
1 files changed, 187 insertions, 0 deletions
diff --git a/src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp b/src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp
new file mode 100644
index 000000000..e542a3b2f
--- /dev/null
+++ b/src/libs/7zip/win/CPP/7zip/Archive/Tar/TarOut.cpp
@@ -0,0 +1,187 @@
+// TarOut.cpp
+
+#include "StdAfx.h"
+
+#include "Common/IntToString.h"
+
+#include "../../Common/StreamUtils.h"
+
+#include "TarOut.h"
+
+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)
+{
+ char s[32];
+ ConvertUInt64ToString(value, s, 8);
+ return AString(s) + ' ';
+}
+
+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 MakeOctalString8(char *s, UInt32 value)
+{
+ AString tempString = MakeOctalString(value);
+
+ const int kMaxSize = 8;
+ if (tempString.Length() >= kMaxSize)
+ return false;
+ int numSpaces = kMaxSize - (tempString.Length() + 1);
+ for(int i = 0; i < numSpaces; i++)
+ s[i] = ' ';
+ MyStringCopy(s + numSpaces, (const char *)tempString);
+ return true;
+}
+
+static void MakeOctalString12(char *s, UInt64 value)
+{
+ AString tempString = MakeOctalString(value);
+ const int kMaxSize = 12;
+ if (tempString.Length() > kMaxSize)
+ {
+ // 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);
+ return;
+ }
+ int numSpaces = kMaxSize - tempString.Length();
+ for(int i = 0; i < numSpaces; i++)
+ s[i] = ' ';
+ memmove(s + numSpaces, (const char *)tempString, tempString.Length());
+}
+
+static bool CopyString(char *dest, const AString &src, int maxSize)
+{
+ if (src.Length() >= maxSize)
+ return false;
+ MyStringCopy(dest, (const char *)src);
+ return true;
+}
+
+#define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; }
+
+HRESULT COutArchive::WriteHeaderReal(const CItem &item)
+{
+ char record[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)
+ 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;
+
+ MakeOctalString12(cur, item.Size); cur += 12;
+ MakeOctalString12(cur, item.MTime); cur += 12;
+
+ memmove(cur, NFileHeader::kCheckSumBlanks, 8);
+ cur += 8;
+
+ *cur++ = item.LinkFlag;
+
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));
+ cur += NFileHeader::kNameSize;
+
+ memmove(cur, item.Magic, 8);
+ cur += 8;
+
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize));
+ cur += NFileHeader::kUserNameSize;
+ RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize));
+ cur += NFileHeader::kGroupNameSize;
+
+
+ if (item.DeviceMajorDefined)
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));
+ cur += 8;
+
+ if (item.DeviceMinorDefined)
+ RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));
+ cur += 8;
+
+
+ UInt32 checkSumReal = 0;
+ for(i = 0; i < NFileHeader::kRecordSize; i++)
+ checkSumReal += Byte(record[i]);
+
+ RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
+
+ return WriteBytes(record, NFileHeader::kRecordSize);
+}
+
+HRESULT COutArchive::WriteHeader(const CItem &item)
+{
+ int nameSize = item.Name.Length();
+ if (nameSize < NFileHeader::kNameSize)
+ return WriteHeaderReal(item);
+
+ CItem modifiedItem = item;
+ int nameStreamSize = nameSize + 1;
+ modifiedItem.Size = 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);
+}
+
+HRESULT COutArchive::FillDataResidual(UInt64 dataSize)
+{
+ UInt32 lastRecordSize = UInt32(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);
+}
+
+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++)
+ {
+ RINOK(WriteBytes(record, NFileHeader::kRecordSize));
+ }
+ return S_OK;
+}
+
+}}