Mercurial > vba-linux
comparison 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 |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // Archive/TarIn.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "TarIn.h" | |
6 #include "TarHeader.h" | |
7 | |
8 #include "Common/StringToInt.h" | |
9 #include "Windows/Defs.h" | |
10 | |
11 #include "../../Common/StreamUtils.h" | |
12 | |
13 namespace NArchive { | |
14 namespace NTar { | |
15 | |
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 } | |
26 | |
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 } | |
38 | |
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 } | |
47 | |
48 #define RIF(x) { if (!(x)) return S_FALSE; } | |
49 | |
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 } | |
57 | |
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 } | |
65 | |
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; | |
71 | |
72 filled = false; | |
73 | |
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; | |
80 | |
81 ReadString(p, NFileHeader::kNameSize, item.Name); p += NFileHeader::kNameSize; | |
82 | |
83 RIF(OctalToNumber32(p, 8, item.Mode)); p += 8; | |
84 | |
85 if (!OctalToNumber32(p, 8, item.UID)) item.UID = 0; p += 8; | |
86 if (!OctalToNumber32(p, 8, item.GID)) item.GID = 0; p += 8; | |
87 | |
88 RIF(OctalToNumber(p, 12, item.Size)); p += 12; | |
89 RIF(OctalToNumber32(p, 12, item.MTime)); p += 12; | |
90 | |
91 UInt32 checkSum; | |
92 RIF(OctalToNumber32(p, 8, checkSum)); | |
93 memcpy(p, NFileHeader::kCheckSumBlanks, 8); p += 8; | |
94 | |
95 item.LinkFlag = *p++; | |
96 | |
97 ReadString(p, NFileHeader::kNameSize, item.LinkName); p += NFileHeader::kNameSize; | |
98 | |
99 memcpy(item.Magic, p, 8); p += 8; | |
100 | |
101 ReadString(p, NFileHeader::kUserNameSize, item.UserName); p += NFileHeader::kUserNameSize; | |
102 ReadString(p, NFileHeader::kUserNameSize, item.GroupName); p += NFileHeader::kUserNameSize; | |
103 | |
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; | |
106 | |
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; | |
113 | |
114 if (item.LinkFlag == NFileHeader::NLinkFlag::kLink) | |
115 item.Size = 0; | |
116 | |
117 UInt32 checkSumReal = 0; | |
118 for (int i = 0; i < NFileHeader::kRecordSize; i++) | |
119 checkSumReal += (Byte)buf[i]; | |
120 | |
121 if (checkSumReal != checkSum) | |
122 return S_FALSE; | |
123 | |
124 filled = true; | |
125 return S_OK; | |
126 } | |
127 | |
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; | |
140 | |
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); | |
146 | |
147 RINOK(ReadStream_FALSE(stream, buffer, packSize)); | |
148 processedSize += packSize; | |
149 buffer[item.Size] = '\0'; | |
150 fullName.ReleaseBuffer(); | |
151 | |
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 } | |
175 | |
176 }} |