1
// -*- mode: cpp; mode: fold -*-
3
// $Id: arfile.cc,v 1.2 2001/02/20 07:03:16 jgg Exp $
4
/* ######################################################################
6
AR File - Handle an 'AR' archive
8
AR Archives have plain text headers at the start of each file
9
section. The headers are aligned on a 2 byte boundry.
11
Information about the structure of AR files can be found in ar(5)
12
on a BSD system, or in the binutils source.
14
##################################################################### */
16
// Include Files /*{{{*/
18
#pragma implementation "apt-pkg/arfile.h"
20
#include <apt-pkg/arfile.h>
21
#include <apt-pkg/strutl.h>
22
#include <apt-pkg/error.h>
27
struct ARArchive::MemberHeader
38
// ARArchive::ARArchive - Constructor /*{{{*/
39
// ---------------------------------------------------------------------
41
ARArchive::ARArchive(FileFd &File) : List(0), File(File)
46
// ARArchive::~ARArchive - Destructor /*{{{*/
47
// ---------------------------------------------------------------------
49
ARArchive::~ARArchive()
59
// ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
60
// ---------------------------------------------------------------------
61
/* AR files are structured with a 8 byte magic string followed by a 60
62
byte plain text header then the file data, another header, data, etc */
63
bool ARArchive::LoadHeaders()
65
signed long Left = File.Size();
67
// Check the magic byte
69
if (File.Read(Magic,sizeof(Magic)) == false)
71
if (memcmp(Magic,"!<arch>\012",sizeof(Magic)) != 0)
72
return _error->Error("Invalid archive signature");
73
Left -= sizeof(Magic);
75
// Read the member list
79
if (File.Read(&Head,sizeof(Head)) == false)
80
return _error->Error("Error reading archive member header");
83
// Convert all of the integer members
84
Member *Memb = new Member();
85
if (StrToNum(Head.MTime,Memb->MTime,sizeof(Head.MTime)) == false ||
86
StrToNum(Head.UID,Memb->UID,sizeof(Head.UID)) == false ||
87
StrToNum(Head.GID,Memb->GID,sizeof(Head.GID)) == false ||
88
StrToNum(Head.Mode,Memb->Mode,sizeof(Head.Mode),8) == false ||
89
StrToNum(Head.Size,Memb->Size,sizeof(Head.Size)) == false)
92
return _error->Error("Invalid archive member header");
95
// Check for an extra long name string
96
if (memcmp(Head.Name,"#1/",3) == 0)
100
if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
104
return _error->Error("Invalid archive member header");
106
if (File.Read(S,Len) == false)
115
unsigned int I = sizeof(Head.Name) - 1;
116
for (; Head.Name[I] == ' '; I--);
117
Memb->Name = string(Head.Name,0,I+1);
120
// Account for the AR header alignment
121
unsigned Skip = Memb->Size % 2;
123
// Add it to the list
126
Memb->Start = File.Tell();
127
if (File.Skip(Memb->Size + Skip) == false)
129
if (Left < (signed)(Memb->Size + Skip))
130
return _error->Error("Archive is too short");
131
Left -= Memb->Size + Skip;
134
return _error->Error("Failed to read the archive headers");
139
// ARArchive::FindMember - Find a name in the member list /*{{{*/
140
// ---------------------------------------------------------------------
141
/* Find a member with the given name */
142
const ARArchive::Member *ARArchive::FindMember(const char *Name) const
144
const Member *Res = List;
147
if (Res->Name == Name)