5 #include "Common/IntToString.h"
\r
7 #include "../../Common/StreamUtils.h"
\r
11 namespace NArchive {
\r
14 HRESULT COutArchive::WriteBytes(const void *buffer, UInt32 size)
\r
16 return WriteStream(m_Stream, buffer, size);
\r
19 void COutArchive::Create(ISequentialOutStream *outStream)
\r
21 m_Stream = outStream;
\r
24 static AString MakeOctalString(UInt64 value)
\r
27 ConvertUInt64ToString(value, s, 8);
\r
28 return AString(s) + ' ';
\r
31 static void MyStrNCpy(char *dest, const char *src, int size)
\r
33 for (int i = 0; i < size; i++)
\r
42 static bool MakeOctalString8(char *s, UInt32 value)
\r
44 AString tempString = MakeOctalString(value);
\r
46 const int kMaxSize = 8;
\r
47 if (tempString.Length() >= kMaxSize)
\r
49 int numSpaces = kMaxSize - (tempString.Length() + 1);
\r
50 for(int i = 0; i < numSpaces; i++)
\r
52 MyStringCopy(s + numSpaces, (const char *)tempString);
\r
56 static void MakeOctalString12(char *s, UInt64 value)
\r
58 AString tempString = MakeOctalString(value);
\r
59 const int kMaxSize = 12;
\r
60 if (tempString.Length() > kMaxSize)
\r
63 s[0] = (char)(Byte)0x80;
\r
64 s[1] = s[2] = s[3] = 0;
\r
65 for (int i = 0; i < 8; i++, value <<= 8)
\r
66 s[4 + i] = (char)(value >> 56);
\r
69 int numSpaces = kMaxSize - tempString.Length();
\r
70 for(int i = 0; i < numSpaces; i++)
\r
72 memmove(s + numSpaces, (const char *)tempString, tempString.Length());
\r
75 static bool CopyString(char *dest, const AString &src, int maxSize)
\r
77 if (src.Length() >= maxSize)
\r
79 MyStringCopy(dest, (const char *)src);
\r
83 #define RETURN_IF_NOT_TRUE(x) { if (!(x)) return E_FAIL; }
\r
85 HRESULT COutArchive::WriteHeaderReal(const CItem &item)
\r
87 char record[NFileHeader::kRecordSize];
\r
90 for (i = 0; i < NFileHeader::kRecordSize; i++)
\r
93 // RETURN_IF_NOT_TRUE(CopyString(header.Name, item.Name, NFileHeader::kNameSize));
\r
94 if (item.Name.Length() > NFileHeader::kNameSize)
\r
96 MyStrNCpy(cur, item.Name, NFileHeader::kNameSize);
\r
97 cur += NFileHeader::kNameSize;
\r
99 RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.Mode)); cur += 8;
\r
100 RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.UID)); cur += 8;
\r
101 RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.GID)); cur += 8;
\r
103 MakeOctalString12(cur, item.Size); cur += 12;
\r
104 MakeOctalString12(cur, item.MTime); cur += 12;
\r
106 memmove(cur, NFileHeader::kCheckSumBlanks, 8);
\r
109 *cur++ = item.LinkFlag;
\r
111 RETURN_IF_NOT_TRUE(CopyString(cur, item.LinkName, NFileHeader::kNameSize));
\r
112 cur += NFileHeader::kNameSize;
\r
114 memmove(cur, item.Magic, 8);
\r
117 RETURN_IF_NOT_TRUE(CopyString(cur, item.User, NFileHeader::kUserNameSize));
\r
118 cur += NFileHeader::kUserNameSize;
\r
119 RETURN_IF_NOT_TRUE(CopyString(cur, item.Group, NFileHeader::kGroupNameSize));
\r
120 cur += NFileHeader::kGroupNameSize;
\r
123 if (item.DeviceMajorDefined)
\r
124 RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMajor));
\r
127 if (item.DeviceMinorDefined)
\r
128 RETURN_IF_NOT_TRUE(MakeOctalString8(cur, item.DeviceMinor));
\r
132 UInt32 checkSumReal = 0;
\r
133 for(i = 0; i < NFileHeader::kRecordSize; i++)
\r
134 checkSumReal += Byte(record[i]);
\r
136 RETURN_IF_NOT_TRUE(MakeOctalString8(record + 148, checkSumReal));
\r
138 return WriteBytes(record, NFileHeader::kRecordSize);
\r
141 HRESULT COutArchive::WriteHeader(const CItem &item)
\r
143 int nameSize = item.Name.Length();
\r
144 if (nameSize < NFileHeader::kNameSize)
\r
145 return WriteHeaderReal(item);
\r
147 CItem modifiedItem = item;
\r
148 int nameStreamSize = nameSize + 1;
\r
149 modifiedItem.Size = nameStreamSize;
\r
150 modifiedItem.LinkFlag = 'L';
\r
151 modifiedItem.Name = NFileHeader::kLongLink;
\r
152 modifiedItem.LinkName.Empty();
\r
153 RINOK(WriteHeaderReal(modifiedItem));
\r
154 RINOK(WriteBytes(item.Name, nameStreamSize));
\r
155 RINOK(FillDataResidual(nameStreamSize));
\r
157 modifiedItem = item;
\r
158 modifiedItem.Name = item.Name.Left(NFileHeader::kNameSize - 1);
\r
159 return WriteHeaderReal(modifiedItem);
\r
162 HRESULT COutArchive::FillDataResidual(UInt64 dataSize)
\r
164 UInt32 lastRecordSize = UInt32(dataSize & (NFileHeader::kRecordSize - 1));
\r
165 if (lastRecordSize == 0)
\r
167 UInt32 residualSize = NFileHeader::kRecordSize - lastRecordSize;
\r
168 Byte residualBytes[NFileHeader::kRecordSize];
\r
169 for (UInt32 i = 0; i < residualSize; i++)
\r
170 residualBytes[i] = 0;
\r
171 return WriteBytes(residualBytes, residualSize);
\r
174 HRESULT COutArchive::WriteFinishHeader()
\r
176 Byte record[NFileHeader::kRecordSize];
\r
178 for (i = 0; i < NFileHeader::kRecordSize; i++)
\r
180 for (i = 0; i < 2; i++)
\r
182 RINOK(WriteBytes(record, NFileHeader::kRecordSize));
\r