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