1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
|
// Archive/IsoIn.h
#ifndef __ARCHIVE_ISO_IN_H
#define __ARCHIVE_ISO_IN_H
#include "../../../Common/IntToString.h"
#include "../../../Common/MyCom.h"
#include "../../IStream.h"
#include "IsoHeader.h"
#include "IsoItem.h"
namespace NArchive {
namespace NIso {
struct CDir: public CDirRecord
{
CDir *Parent;
CObjectVector<CDir> _subItems;
void Clear()
{
Parent = 0;
_subItems.Clear();
}
AString GetPath(bool checkSusp, unsigned skipSize) const
{
AString s;
unsigned len = 0;
const CDir *cur = this;
for (;;)
{
unsigned curLen;
cur->GetNameCur(checkSusp, skipSize, curLen);
len += curLen;
cur = cur->Parent;
if (!cur || !cur->Parent)
break;
len++;
}
char *p = s.GetBuf_SetEnd(len) + len;
cur = this;
for (;;)
{
unsigned curLen;
const Byte *name = cur->GetNameCur(checkSusp, skipSize, curLen);
p -= curLen;
if (curLen != 0)
memcpy(p, name, curLen);
cur = cur->Parent;
if (!cur || !cur->Parent)
break;
p--;
*p = CHAR_PATH_SEPARATOR;
}
return s;
}
void GetPathU(UString &s) const
{
s.Empty();
unsigned len = 0;
const CDir *cur = this;
for (;;)
{
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
const Byte *fid = cur->FileId;
unsigned i;
for (i = 0; i < curLen; i++)
if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
break;
len += i;
cur = cur->Parent;
if (!cur || !cur->Parent)
break;
len++;
}
wchar_t *p = s.GetBuf_SetEnd(len) + len;
cur = this;
for (;;)
{
unsigned curLen = (unsigned)(cur->FileId.Size() / 2);
const Byte *fid = cur->FileId;
unsigned i;
for (i = 0; i < curLen; i++)
if (fid[i * 2] == 0 && fid[i * 2 + 1] == 0)
break;
curLen = i;
p -= curLen;
for (i = 0; i < curLen; i++)
p[i] = (wchar_t)(((wchar_t)fid[i * 2] << 8) | fid[i * 2 + 1]);
cur = cur->Parent;
if (!cur || !cur->Parent)
break;
p--;
*p = WCHAR_PATH_SEPARATOR;
}
}
};
struct CDateTime
{
UInt16 Year;
Byte Month;
Byte Day;
Byte Hour;
Byte Minute;
Byte Second;
Byte Hundredths;
signed char GmtOffset; // min intervals from -48 (West) to +52 (East) recorded.
bool NotSpecified() const { return Year == 0 && Month == 0 && Day == 0 &&
Hour == 0 && Minute == 0 && Second == 0 && GmtOffset == 0; }
bool GetFileTime(FILETIME &ft) const
{
UInt64 value;
bool res = NWindows::NTime::GetSecondsSince1601(Year, Month, Day, Hour, Minute, Second, value);
if (res)
{
value -= (Int64)((Int32)GmtOffset * 15 * 60);
value *= 10000000;
}
ft.dwLowDateTime = (DWORD)value;
ft.dwHighDateTime = (DWORD)(value >> 32);
return res;
}
};
struct CBootRecordDescriptor
{
Byte BootSystemId[32]; // a-characters
Byte BootId[32]; // a-characters
Byte BootSystemUse[1977];
};
struct CBootValidationEntry
{
Byte PlatformId;
Byte Id[24]; // to identify the manufacturer/developer of the CD-ROM.
};
struct CBootInitialEntry
{
bool Bootable;
Byte BootMediaType;
UInt16 LoadSegment;
/* This is the load segment for the initial boot image. If this
value is 0 the system will use the traditional segment of 7C0. If this value
is non-zero the system will use the specified segment. This applies to x86
architectures only. For "flat" model architectures (such as Motorola) this
is the address divided by 10. */
Byte SystemType; // This must be a copy of byte 5 (System Type) from the
// Partition Table found in the boot image.
UInt16 SectorCount; // This is the number of virtual/emulated sectors the system
// will store at Load Segment during the initial boot procedure.
UInt32 LoadRBA; // This is the start address of the virtual disk. CDs use
// Relative/Logical block addressing.
Byte VendorSpec[20];
UInt32 GetSize() const
{
// if (BootMediaType == NBootMediaType::k1d44Floppy) (1440 << 10);
return (UInt32)SectorCount * 512;
}
bool Parse(const Byte *p);
AString GetName() const;
};
struct CVolumeDescriptor
{
Byte VolFlags;
Byte SystemId[32]; // a-characters. An identification of a system
// which can recognize and act upon the content of the Logical
// Sectors with logical Sector Numbers 0 to 15 of the volume.
Byte VolumeId[32]; // d-characters. An identification of the volume.
UInt32 VolumeSpaceSize; // the number of Logical Blocks in which the Volume Space of the volume is recorded
Byte EscapeSequence[32];
UInt16 VolumeSetSize;
UInt16 VolumeSequenceNumber; // the ordinal number of the volume in the Volume Set of which the volume is a member.
UInt16 LogicalBlockSize;
UInt32 PathTableSize;
UInt32 LPathTableLocation;
UInt32 LOptionalPathTableLocation;
UInt32 MPathTableLocation;
UInt32 MOptionalPathTableLocation;
CDirRecord RootDirRecord;
Byte VolumeSetId[128];
Byte PublisherId[128];
Byte DataPreparerId[128];
Byte ApplicationId[128];
Byte CopyrightFileId[37];
Byte AbstractFileId[37];
Byte BibFileId[37];
CDateTime CTime;
CDateTime MTime;
CDateTime ExpirationTime;
CDateTime EffectiveTime;
Byte FileStructureVersion; // = 1;
Byte ApplicationUse[512];
bool IsJoliet() const
{
if ((VolFlags & 1) != 0)
return false;
Byte b = EscapeSequence[2];
return (EscapeSequence[0] == 0x25 && EscapeSequence[1] == 0x2F &&
(b == 0x40 || b == 0x43 || b == 0x45));
}
};
struct CRef
{
const CDir *Dir;
UInt32 Index;
UInt32 NumExtents;
UInt64 TotalSize;
};
const UInt32 kBlockSize = 1 << 11;
class CInArchive
{
IInStream *_stream;
UInt64 _position;
UInt32 m_BufferPos;
CDir _rootDir;
bool _bootIsDefined;
CBootRecordDescriptor _bootDesc;
void Skip(size_t size);
void SkipZeros(size_t size);
Byte ReadByte();
void ReadBytes(Byte *data, UInt32 size);
UInt16 ReadUInt16();
UInt32 ReadUInt32Le();
UInt32 ReadUInt32Be();
UInt32 ReadUInt32();
UInt64 ReadUInt64();
UInt32 ReadDigits(int numDigits);
void ReadDateTime(CDateTime &d);
void ReadRecordingDateTime(CRecordingDateTime &t);
void ReadDirRecord2(CDirRecord &r, Byte len);
void ReadDirRecord(CDirRecord &r);
void ReadBootRecordDescriptor(CBootRecordDescriptor &d);
void ReadVolumeDescriptor(CVolumeDescriptor &d);
void SeekToBlock(UInt32 blockIndex);
void ReadDir(CDir &d, int level);
void CreateRefs(CDir &d);
void ReadBootInfo();
HRESULT Open2();
public:
HRESULT Open(IInStream *inStream);
void Clear();
UInt64 _fileSize;
UInt64 PhySize;
CRecordVector<CRef> Refs;
CObjectVector<CVolumeDescriptor> VolDescs;
int MainVolDescIndex;
// UInt32 BlockSize;
CObjectVector<CBootInitialEntry> BootEntries;
bool IsArc;
bool UnexpectedEnd;
bool HeadersError;
bool IncorrectBigEndian;
bool TooDeepDirs;
bool SelfLinkedDirs;
CRecordVector<UInt32> UniqStartLocations;
Byte m_Buffer[kBlockSize];
void UpdatePhySize(UInt32 blockIndex, UInt64 size)
{
const UInt64 alignedSize = (size + kBlockSize - 1) & ~((UInt64)kBlockSize - 1);
const UInt64 end = (UInt64)blockIndex * kBlockSize + alignedSize;
if (PhySize < end)
PhySize = end;
}
bool IsJoliet() const { return VolDescs[MainVolDescIndex].IsJoliet(); }
UInt64 GetBootItemSize(int index) const
{
const CBootInitialEntry &be = BootEntries[index];
UInt64 size = be.GetSize();
if (be.BootMediaType == NBootMediaType::k1d2Floppy)
size = (1200 << 10);
else if (be.BootMediaType == NBootMediaType::k1d44Floppy)
size = (1440 << 10);
else if (be.BootMediaType == NBootMediaType::k2d88Floppy)
size = (2880 << 10);
UInt64 startPos = (UInt64)be.LoadRBA * kBlockSize;
if (startPos < _fileSize)
{
if (_fileSize - startPos < size)
size = _fileSize - startPos;
}
return size;
}
bool IsSusp;
unsigned SuspSkipSize;
};
}}
#endif
|