]>
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 /*{{{*/
19 #include <apt-pkg/arfile.h>
20 #include <apt-pkg/strutl.h>
21 #include <apt-pkg/fileutl.h>
22 #include <apt-pkg/error.h>
29 struct ARArchive::MemberHeader
40 // ARArchive::ARArchive - Constructor /*{{{*/
41 // ---------------------------------------------------------------------
43 ARArchive::ARArchive(FileFd
&File
) : List(0), File(File
)
48 // ARArchive::~ARArchive - Destructor /*{{{*/
49 // ---------------------------------------------------------------------
51 ARArchive::~ARArchive()
61 // ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
62 // ---------------------------------------------------------------------
63 /* AR files are structured with a 8 byte magic string followed by a 60
64 byte plain text header then the file data, another header, data, etc */
65 bool ARArchive::LoadHeaders()
67 signed long Left
= File
.Size();
69 // Check the magic byte
71 if (File
.Read(Magic
,sizeof(Magic
)) == false)
73 if (memcmp(Magic
,"!<arch>\012",sizeof(Magic
)) != 0)
74 return _error
->Error(_("Invalid archive signature"));
75 Left
-= sizeof(Magic
);
77 // Read the member list
81 if (File
.Read(&Head
,sizeof(Head
)) == false)
82 return _error
->Error(_("Error reading archive member header"));
85 // Convert all of the integer members
86 Member
*Memb
= new Member();
87 if (StrToNum(Head
.MTime
,Memb
->MTime
,sizeof(Head
.MTime
)) == false ||
88 StrToNum(Head
.UID
,Memb
->UID
,sizeof(Head
.UID
)) == false ||
89 StrToNum(Head
.GID
,Memb
->GID
,sizeof(Head
.GID
)) == false ||
90 StrToNum(Head
.Mode
,Memb
->Mode
,sizeof(Head
.Mode
),8) == false ||
91 StrToNum(Head
.Size
,Memb
->Size
,sizeof(Head
.Size
)) == false)
94 return _error
->Error(_("Invalid archive member header %s"), Head
.Name
);
97 // Check for an extra long name string
98 if (memcmp(Head
.Name
,"#1/",3) == 0)
102 if (StrToNum(Head
.Name
+3,Len
,sizeof(Head
.Size
)-3) == false ||
106 return _error
->Error(_("Invalid archive member header"));
108 if (File
.Read(S
,Len
) == false)
117 unsigned int I
= sizeof(Head
.Name
) - 1;
118 for (; Head
.Name
[I
] == ' ' || Head
.Name
[I
] == '/'; I
--);
119 Memb
->Name
= std::string(Head
.Name
,I
+1);
122 // Account for the AR header alignment
123 unsigned Skip
= Memb
->Size
% 2;
125 // Add it to the list
128 Memb
->Start
= File
.Tell();
129 if (File
.Skip(Memb
->Size
+ Skip
) == false)
131 if (Left
< (signed)(Memb
->Size
+ Skip
))
132 return _error
->Error(_("Archive is too short"));
133 Left
-= Memb
->Size
+ Skip
;
136 return _error
->Error(_("Failed to read the archive headers"));
141 // ARArchive::FindMember - Find a name in the member list /*{{{*/
142 // ---------------------------------------------------------------------
143 /* Find a member with the given name */
144 const ARArchive::Member
*ARArchive::FindMember(const char *Name
) const
146 const Member
*Res
= List
;
149 if (Res
->Name
== Name
)