1
// This file is part of par2cmdline (a PAR 2.0 compatible file verification and
2
// repair tool). See http://parchive.sourceforge.net for details of PAR 2.0.
4
// Copyright (c) 2003 Peter Brian Clements
6
// par2cmdline is free software; you can redistribute it and/or modify
7
// it under the terms of the GNU General Public License as published by
8
// the Free Software Foundation; either version 2 of the License, or
9
// (at your option) any later version.
11
// par2cmdline is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
// GNU General Public License for more details.
16
// You should have received a copy of the GNU General Public License
17
// along with this program; if not, write to the Free Software
18
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20
#include "par2cmdline.h"
25
static char THIS_FILE[]=__FILE__;
30
// Construct the main packet from the source files and the block size
32
bool MainPacket::Create(vector<Par2CreatorSourceFile*> &sourcefiles, u64 _blocksize)
34
recoverablefilecount = totalfilecount =(u32)sourcefiles.size();
35
blocksize = _blocksize;
37
// Allocate memory for the main packet with enough fileid entries
38
MAINPACKET *packet = (MAINPACKET *)AllocatePacket(sizeof(MAINPACKET) + totalfilecount * sizeof(MD5Hash));
40
// Record the details we already know in the packet
41
packet->header.magic = packet_magic;
42
packet->header.length = packetlength;
43
//packet->header.hash; // Compute shortly
44
//packet->header.setid; // Compute shortly
45
packet->header.type = mainpacket_type;
47
packet->blocksize = _blocksize;
48
packet->recoverablefilecount = totalfilecount;
49
//packet->fileid; // Compute shortly
51
// Sort the source files according to their fileid values
52
if (totalfilecount > 1)
54
sort(sourcefiles.begin(), sourcefiles.end(), Par2CreatorSourceFile::CompareLess);
57
// Store the fileid values in the main packet
58
vector<Par2CreatorSourceFile*>::const_iterator sourcefile;
60
for ((sourcefile=sourcefiles.begin()),(hash=packet->fileid);
61
sourcefile!=sourcefiles.end();
64
*hash = (*sourcefile)->FileId();
67
// Compute the set_id_hash
68
MD5Context setidcontext;
69
setidcontext.Update(&packet->blocksize, packetlength - offsetof(MAINPACKET, blocksize));
70
setidcontext.Final(packet->header.setid);
72
// Compute the packet_hash
73
MD5Context packetcontext;
74
packetcontext.Update(&packet->header.setid, packetlength - offsetof(MAINPACKET, header.setid));
75
packetcontext.Final(packet->header.hash);
80
// Load a main packet from a specified file
82
bool MainPacket::Load(DiskFile *diskfile, u64 offset, PACKET_HEADER &header)
84
// Is the packet large enough
85
if (header.length < sizeof(MAINPACKET))
90
// Is there a whole number of fileid values
91
if (0 < (header.length - sizeof(MAINPACKET)) % sizeof(MD5Hash))
96
// Is the packet too large
97
if (header.length > sizeof(MAINPACKET) + 32768 * sizeof(MD5Hash))
102
// Compute the total number of entries in the fileid array
103
totalfilecount = (u32)(((size_t)header.length - sizeof(MAINPACKET)) / sizeof(MD5Hash));
105
MAINPACKET *packet = (MAINPACKET *)AllocatePacket((size_t)header.length);
107
packet->header = header;
109
// Read the rest of the packet from disk
110
if (!diskfile->Read(offset + sizeof(PACKET_HEADER),
112
(size_t)packet->header.length - sizeof(PACKET_HEADER)))
115
// Does the packet have enough fileid values
116
recoverablefilecount = packet->recoverablefilecount;
117
if (recoverablefilecount > totalfilecount)
122
// Is the block size valid
123
blocksize = packet->blocksize;
124
if (blocksize == 0 || (blocksize & 3) != 0)