view src/win32/7zip/7z/CPP/7zip/Archive/Tar/TarIn.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 // Archive/TarIn.cpp
3 #include "StdAfx.h"
5 #include "TarIn.h"
6 #include "TarHeader.h"
8 #include "Common/StringToInt.h"
9 #include "Windows/Defs.h"
11 #include "../../Common/StreamUtils.h"
13 namespace NArchive {
14 namespace NTar {
16 static void MyStrNCpy(char *dest, const char *src, int size)
17 {
18 for (int i = 0; i < size; i++)
19 {
20 char c = src[i];
21 dest[i] = c;
22 if (c == 0)
23 break;
24 }
25 }
27 static bool OctalToNumber(const char *srcString, int size, UInt64 &res)
28 {
29 char sz[32];
30 MyStrNCpy(sz, srcString, size);
31 sz[size] = 0;
32 const char *end;
33 int i;
34 for (i = 0; sz[i] == ' '; i++);
35 res = ConvertOctStringToUInt64(sz + i, &end);
36 return (*end == ' ' || *end == 0);
37 }
39 static bool OctalToNumber32(const char *srcString, int size, UInt32 &res)
40 {
41 UInt64 res64;
42 if (!OctalToNumber(srcString, size, res64))
43 return false;
44 res = (UInt32)res64;
45 return (res64 <= 0xFFFFFFFF);
46 }
48 #define RIF(x) { if (!(x)) return S_FALSE; }
50 static bool IsRecordLast(const char *buf)
51 {
52 for (int i = 0; i < NFileHeader::kRecordSize; i++)
53 if (buf[i] != 0)
54 return false;
55 return true;
56 }
58 static void ReadString(const char *s, int size, AString &result)
59 {
60 char temp[NFileHeader::kRecordSize + 1];
61 MyStrNCpy(temp, s, size);
62 temp[size] = '\0';
63 result = temp;
64 }
66 static HRESULT GetNextItemReal(ISequentialInStream *stream, bool &filled, CItemEx &item, size_t &processedSize)
67 {
68 item.LongLinkSize = 0;
69 char buf[NFileHeader::kRecordSize];
70 char *p = buf;
72 filled = false;
74 processedSize = NFileHeader::kRecordSize;
75 RINOK(ReadStream(stream, buf, &processedSize));
76 if (processedSize == 0 || (processedSize == NFileHeader::kRecordSize && IsRecordLast(buf)))
77 return S_OK;
78 if (processedSize < NFileHeader::kRecordSize)
79 return S_FALSE;
81 ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize;
83 RIF(OctalToNumber32(p, 8, item.Mode)); p += 8;
85 if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8;
86 if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8;
88 RIF(OctalToNumber(p, 12, item.Size)); p += 12;
89 RIF(OctalToNumber32(p, 12, item.MTime)); p += 12;
91 UInt32 checkSum;
92 RIF(OctalToNumber32(p, 8, checkSum));
93 memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8;
95 item.LinkFlag = *p++;
97 ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize;
99 memcpy(item.Magic, p, 8); p += 8;
101 ReadString(p, NFileHeader::kUserNameSize, item.UserName); p += NFileHeader::kUserNameSize;
102 ReadString(p, NFileHeader::kUserNameSize, item.GroupName); p += NFileHeader::kUserNameSize;
104 item.DeviceMajorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMajor)); p += 8;
105 item.DeviceMinorDefined = (p[0] != 0); RIF(OctalToNumber32(p, 8, item.DeviceMinor)); p += 8;
107 AString prefix;
108 ReadString(p, NFileHeader::kPrefixSize, prefix);
109 p += NFileHeader::kPrefixSize;
110 if (!prefix.IsEmpty() && item.IsMagic() &&
111 (item.LinkFlag != 'L' /* || prefix != "00000000000" */ ))
112 item.Name = prefix + AString('/') + item.Name;
114 if (item.LinkFlag == NFileHeader::NLinkFlag::kLink)
115 item.Size = 0;
117 UInt32 checkSumReal = 0;
118 for (int i = 0; i < NFileHeader::kRecordSize; i++)
119 checkSumReal += (Byte)buf[i];
121 if (checkSumReal != checkSum)
122 return S_FALSE;
124 filled = true;
125 return S_OK;
126 }
128 HRESULT ReadItem(ISequentialInStream *stream, bool &filled, CItemEx &item)
129 {
130 size_t processedSize;
131 RINOK(GetNextItemReal(stream, filled, item, processedSize));
132 if (!filled)
133 return S_OK;
134 // GNUtar extension
135 if (item.LinkFlag == 'L')
136 {
137 if (item.Name.Compare(NFileHeader::kLongLink) != 0)
138 if (item.Name.Compare(NFileHeader::kLongLink2) != 0)
139 return S_FALSE;
141 AString fullName;
142 if (item.Size > (1 << 15))
143 return S_FALSE;
144 int packSize = (int)item.GetPackSize();
145 char *buffer = fullName.GetBuffer(packSize + 1);
147 RINOK(ReadStream_FALSE(stream, buffer, packSize));
148 processedSize += packSize;
149 buffer[item.Size] = '\0';
150 fullName.ReleaseBuffer();
152 UInt64 headerPosition = item.HeaderPosition;
153 {
154 size_t processedSize2;
155 RINOK(GetNextItemReal(stream, filled, item, processedSize2));
156 }
157 item.LongLinkSize = (unsigned)processedSize;
158 item.Name = fullName;
159 item.HeaderPosition = headerPosition;
160 }
161 else if (item.LinkFlag == 'g' || item.LinkFlag == 'x' || item.LinkFlag == 'X')
162 {
163 // pax Extended Header
164 return S_OK;
165 }
166 else if (item.LinkFlag == NFileHeader::NLinkFlag::kDumpDir)
167 {
168 // GNU Extensions to the Archive Format
169 return S_OK;
170 }
171 else if (item.LinkFlag > '7' || (item.LinkFlag < '0' && item.LinkFlag != 0))
172 return S_FALSE;
173 return S_OK;
174 }
176 }}