]>
git.saurik.com Git - apt.git/blob - apt-inst/contrib/arfile.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: arfile.cc,v 1.6.2.1 2004/01/16 18:58:50 mdz 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>
28 struct ARArchive::MemberHeader
39 // ARArchive::ARArchive - Constructor /*{{{*/
40 // ---------------------------------------------------------------------
42 ARArchive::ARArchive(FileFd
&File
) : List(0), File(File
)
47 // ARArchive::~ARArchive - Destructor /*{{{*/
48 // ---------------------------------------------------------------------
50 ARArchive::~ARArchive()
60 // ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
61 // ---------------------------------------------------------------------
62 /* AR files are structured with a 8 byte magic string followed by a 60
63 byte plain text header then the file data, another header, data, etc */
64 bool ARArchive::LoadHeaders()
66 signed long Left
= File
.Size();
68 // Check the magic byte
70 if (File
.Read(Magic
,sizeof(Magic
)) == false)
72 if (memcmp(Magic
,"!<arch>\012",sizeof(Magic
)) != 0)
73 return _error
->Error(_("Invalid archive signature"));
74 Left
-= sizeof(Magic
);
76 // Read the member list
80 if (File
.Read(&Head
,sizeof(Head
)) == false)
81 return _error
->Error(_("Error reading archive member header"));
84 // Convert all of the integer members
85 Member
*Memb
= new Member();
86 if (StrToNum(Head
.MTime
,Memb
->MTime
,sizeof(Head
.MTime
)) == false ||
87 StrToNum(Head
.UID
,Memb
->UID
,sizeof(Head
.UID
)) == false ||
88 StrToNum(Head
.GID
,Memb
->GID
,sizeof(Head
.GID
)) == false ||
89 StrToNum(Head
.Mode
,Memb
->Mode
,sizeof(Head
.Mode
),8) == false ||
90 StrToNum(Head
.Size
,Memb
->Size
,sizeof(Head
.Size
)) == false)
93 return _error
->Error(_("Invalid archive member header"));
96 // Check for an extra long name string
97 if (memcmp(Head
.Name
,"#1/",3) == 0)
101 if (StrToNum(Head
.Name
+3,Len
,sizeof(Head
.Size
)-3) == false ||
105 return _error
->Error(_("Invalid archive member header"));
107 if (File
.Read(S
,Len
) == false)
116 unsigned int I
= sizeof(Head
.Name
) - 1;
117 for (; Head
.Name
[I
] == ' '; I
--);
118 Memb
->Name
= string(Head
.Name
,I
+1);
121 // Account for the AR header alignment
122 unsigned Skip
= Memb
->Size
% 2;
124 // Add it to the list
127 Memb
->Start
= File
.Tell();
128 if (File
.Skip(Memb
->Size
+ Skip
) == false)
130 if (Left
< (signed)(Memb
->Size
+ Skip
))
131 return _error
->Error(_("Archive is too short"));
132 Left
-= Memb
->Size
+ Skip
;
135 return _error
->Error(_("Failed to read the archive headers"));
140 // ARArchive::FindMember - Find a name in the member list /*{{{*/
141 // ---------------------------------------------------------------------
142 /* Find a member with the given name */
143 const ARArchive::Member
*ARArchive::FindMember(const char *Name
) const
145 const Member
*Res
= List
;
148 if (Res
->Name
== Name
)