]>
git.saurik.com Git - apt.git/blob - apt-inst/contrib/arfile.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: arfile.cc,v 1.3 2002/09/20 04:42:25 tausq 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
] == ' ' || 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
)