// This file is part of par2cmdline (a PAR 2.0 compatible file verification and
// repair tool). See http://parchive.sourceforge.net for details of PAR 2.0.
//
// Copyright (c) 2003 Peter Brian Clements
//
// par2cmdline is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// par2cmdline is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#ifndef __PAR2FILEFORMAT_H__
#define __PAR2FILEFORMAT_H__
// This file defines the format of a PAR2 file.
// PAR2 files consist of one or more "packets" that contain information
// that is required to be able to verify and repair damaged data files.
// All packets start with a short "header" which contains information
// used to describe what sort of data is stored in the rest of the packet
// and also to allow that data to be verified.
// This file details the format for the following packet types described
// in the PAR 2.0 specification:
// Main Packet struct MAINPACKET
// File Description Packet struct FILEDESCRIPTIONPACKET
// Input File Slice Checksum Packet struct FILEVERIFICATIONPACKET
// Recovery Slice Packet struct RECOVERYBLOCKPACKET
// Creator Packet struct CREATORPACKET
#ifdef WIN32
#pragma pack(push, 1)
#ifndef PACKED
#define PACKED
#endif
#else
#define PACKED __attribute__ ((packed))
#endif
#ifdef _MSC_VER
#pragma warning(disable:4200)
#endif
// All numeric fields in the file format are in LITTLE ENDIAN format.
// The types leu32 and leu64 are defined in letype.h
// Two simple types used in the packet header.
struct MAGIC {u8 magic[8];} PACKED;
struct PACKETTYPE {u8 type[16];} PACKED;
// Every packet starts with a packet header.
struct PACKET_HEADER
{
// Header
MAGIC magic; // = {'P', 'A', 'R', '2', '\0', 'P', 'K', 'T'}
leu64 length; // Length of entire packet including header
MD5Hash hash; // Hash of entire packet excepting the first 3 fields
MD5Hash setid; // Normally computed as the Hash of body of "Main Packet"
PACKETTYPE type; // Used to specify the meaning of the rest of the packet
} PACKED;
// The file verification packet is used to determine whether or not any
// parts of a damaged file are useable.
// It contains a FileId used to pair it with a corresponding file description
// packet, followed by an array of hash and crc values. The number of entries in
// the array can be determined from the packet_length.
struct FILEVERIFICATIONENTRY
{
MD5Hash hash;
leu32 crc;
} PACKED;
struct FILEVERIFICATIONPACKET
{
PACKET_HEADER header;
// Body
MD5Hash fileid; // MD5hash of file_hash_16k, file_length, file_name
FILEVERIFICATIONENTRY entries[];
} PACKED;
// The file description packet is used to record the name of the file,
// its size, and the Hash of both the whole file and the first 16k of
// the file.
// If the name of the file is an exact multiple of 4 characters in length
// then it may not have a NULL termination. If the name of the file is not
// an exact multiple of 4, then it will be padded with 0 bytes at the
// end to make it up to a multiple of 4.
struct FILEDESCRIPTIONPACKET
{
PACKET_HEADER header;
// Body
MD5Hash fileid; // MD5hash of [hash16k, length, name]
MD5Hash hashfull; // MD5 Hash of the whole file
MD5Hash hash16k; // MD5 Hash of the first 16k of the file
leu64 length; // Length of the file
u8 name[]; // Name of the file, padded with 1 to 3 zero bytes to reach
// a multiple of 4 bytes.
// Actual length can be determined from overall packet
// length and then working backwards to find the first non
// zero character.
//u8* name(void) {return (u8*)&this[1];}
//const u8* name(void) const {return (const u8*)&this[1];}
} PACKED;
// The main packet is used to tie together the other packets in a recovery file.
// It specifies the block size used to virtually slice the source files, a count
// of the number of source files, and an array of Hash values used to specify
// in what order the source files are processed.
// Each entry in the fileid array corresponds with the fileid value
// in a file description packet and a file verification packet.
// The fileid array may contain more entries than the count of the number
// of recoverable files. The extra entries correspond to files that were not
// used during the creation of the recovery files and which may not therefore
// be repaired if they are found to be damaged.
struct MAINPACKET
{
PACKET_HEADER header;
// Body
leu64 blocksize;
leu32 recoverablefilecount;
MD5Hash fileid[0];
//MD5Hash* fileid(void) {return (MD5Hash*)&this[1];}
//const MD5Hash* fileid(void) const {return (const MD5Hash*)&this[1];}
} PACKED;
// The creator packet is used to identify which program created a particular
// recovery file. It is not required for verification or recovery of damaged
// files.
struct CREATORPACKET
{
PACKET_HEADER header;
// Body
u8 client[];
//u8* client(void) {return (u8*)&this[1];}
} PACKED;
// The recovery block packet contains a single block of recovery data along
// with the exponent value used during the computation of that block.
struct RECOVERYBLOCKPACKET
{
PACKET_HEADER header;
// Body
leu32 exponent;
// unsigned long data[];
// unsigned long* data(void) {return (unsigned long*)&this[1];}
} PACKED;
#ifdef _MSC_VER
#pragma warning(default:4200)
#endif
#ifdef WIN32
#pragma pack(pop)
#endif
#undef PACKED
// Operators for comparing the MAGIC and PACKETTYPE values
inline bool operator == (const MAGIC &left, const MAGIC &right)
{
return (0==memcmp(&left, &right, sizeof(left)));
}
inline bool operator != (const MAGIC &left, const MAGIC &right)
{
return !operator==(left, right);
}
inline bool operator == (const PACKETTYPE &left, const PACKETTYPE &right)
{
return (0==memcmp(&left, &right, sizeof(left)));
}
inline bool operator != (const PACKETTYPE &left, const PACKETTYPE &right)
{
return !operator==(left, right);
}
extern MAGIC packet_magic;
extern PACKETTYPE fileverificationpacket_type;
extern PACKETTYPE filedescriptionpacket_type;
extern PACKETTYPE mainpacket_type;
extern PACKETTYPE recoveryblockpacket_type;
extern PACKETTYPE creatorpacket_type;
#endif //__PAR2FILEFORMAT_H__
syntax highlighted by Code2HTML, v. 0.9.1