]>
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 /*{{{*/
17 #include <apt-pkg/arfile.h>
18 #include <apt-pkg/strutl.h>
19 #include <apt-pkg/error.h>
25 struct ARArchive::MemberHeader
36 // ARArchive::ARArchive - Constructor /*{{{*/
37 // ---------------------------------------------------------------------
39 ARArchive::ARArchive(FileFd
&File
) : List(0), File(File
)
44 // ARArchive::~ARArchive - Destructor /*{{{*/
45 // ---------------------------------------------------------------------
47 ARArchive::~ARArchive()
57 // ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
58 // ---------------------------------------------------------------------
59 /* AR files are structured with a 8 byte magic string followed by a 60
60 byte plain text header then the file data, another header, data, etc */
61 bool ARArchive::LoadHeaders()
63 signed long Left
= File
.Size();
65 // Check the magic byte
67 if (File
.Read(Magic
,sizeof(Magic
)) == false)
69 if (memcmp(Magic
,"!<arch>\012",sizeof(Magic
)) != 0)
70 return _error
->Error(_("Invalid archive signature"));
71 Left
-= sizeof(Magic
);
73 // Read the member list
77 if (File
.Read(&Head
,sizeof(Head
)) == false)
78 return _error
->Error(_("Error reading archive member header"));
81 // Convert all of the integer members
82 Member
*Memb
= new Member();
83 if (StrToNum(Head
.MTime
,Memb
->MTime
,sizeof(Head
.MTime
)) == false ||
84 StrToNum(Head
.UID
,Memb
->UID
,sizeof(Head
.UID
)) == false ||
85 StrToNum(Head
.GID
,Memb
->GID
,sizeof(Head
.GID
)) == false ||
86 StrToNum(Head
.Mode
,Memb
->Mode
,sizeof(Head
.Mode
),8) == false ||
87 StrToNum(Head
.Size
,Memb
->Size
,sizeof(Head
.Size
)) == false)
90 return _error
->Error(_("Invalid archive member header"));
93 // Check for an extra long name string
94 if (memcmp(Head
.Name
,"#1/",3) == 0)
98 if (StrToNum(Head
.Name
+3,Len
,sizeof(Head
.Size
)-3) == false ||
102 return _error
->Error(_("Invalid archive member header"));
104 if (File
.Read(S
,Len
) == false)
113 unsigned int I
= sizeof(Head
.Name
) - 1;
114 for (; Head
.Name
[I
] == ' ' || Head
.Name
[I
] == '/'; I
--);
115 Memb
->Name
= string(Head
.Name
,I
+1);
118 // Account for the AR header alignment
119 unsigned Skip
= Memb
->Size
% 2;
121 // Add it to the list
124 Memb
->Start
= File
.Tell();
125 if (File
.Skip(Memb
->Size
+ Skip
) == false)
127 if (Left
< (signed)(Memb
->Size
+ Skip
))
128 return _error
->Error(_("Archive is too short"));
129 Left
-= Memb
->Size
+ Skip
;
132 return _error
->Error(_("Failed to read the archive headers"));
137 // ARArchive::FindMember - Find a name in the member list /*{{{*/
138 // ---------------------------------------------------------------------
139 /* Find a member with the given name */
140 const ARArchive::Member
*ARArchive::FindMember(const char *Name
) const
142 const Member
*Res
= List
;
145 if (Res
->Name
== Name
)