]>
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 boundary.
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>
25 #include <sys/types.h>
31 struct ARArchive::MemberHeader
42 // ARArchive::ARArchive - Constructor /*{{{*/
43 // ---------------------------------------------------------------------
45 ARArchive::ARArchive(FileFd
&File
) : List(0), File(File
)
50 // ARArchive::~ARArchive - Destructor /*{{{*/
51 // ---------------------------------------------------------------------
53 ARArchive::~ARArchive()
63 // ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
64 // ---------------------------------------------------------------------
65 /* AR files are structured with a 8 byte magic string followed by a 60
66 byte plain text header then the file data, another header, data, etc */
67 bool ARArchive::LoadHeaders()
69 off_t Left
= File
.Size();
71 // Check the magic byte
73 if (File
.Read(Magic
,sizeof(Magic
)) == false)
75 if (memcmp(Magic
,"!<arch>\012",sizeof(Magic
)) != 0)
76 return _error
->Error(_("Invalid archive signature"));
77 Left
-= sizeof(Magic
);
79 // Read the member list
83 if (File
.Read(&Head
,sizeof(Head
)) == false)
84 return _error
->Error(_("Error reading archive member header"));
87 // Convert all of the integer members
88 Member
*Memb
= new Member();
89 if (StrToNum(Head
.MTime
,Memb
->MTime
,sizeof(Head
.MTime
)) == false ||
90 StrToNum(Head
.UID
,Memb
->UID
,sizeof(Head
.UID
)) == false ||
91 StrToNum(Head
.GID
,Memb
->GID
,sizeof(Head
.GID
)) == false ||
92 StrToNum(Head
.Mode
,Memb
->Mode
,sizeof(Head
.Mode
),8) == false ||
93 StrToNum(Head
.Size
,Memb
->Size
,sizeof(Head
.Size
)) == false)
96 return _error
->Error(_("Invalid archive member header %s"), Head
.Name
);
99 // Check for an extra long name string
100 if (memcmp(Head
.Name
,"#1/",3) == 0)
104 if (StrToNum(Head
.Name
+3,Len
,sizeof(Head
.Size
)-3) == false ||
108 return _error
->Error(_("Invalid archive member header"));
110 if (File
.Read(S
,Len
) == false)
122 unsigned int I
= sizeof(Head
.Name
) - 1;
123 for (; Head
.Name
[I
] == ' ' || Head
.Name
[I
] == '/'; I
--);
124 Memb
->Name
= std::string(Head
.Name
,I
+1);
127 // Account for the AR header alignment
128 off_t Skip
= Memb
->Size
% 2;
130 // Add it to the list
133 Memb
->Start
= File
.Tell();
134 if (File
.Skip(Memb
->Size
+ Skip
) == false)
136 if (Left
< (off_t
)(Memb
->Size
+ Skip
))
137 return _error
->Error(_("Archive is too short"));
138 Left
-= Memb
->Size
+ Skip
;
141 return _error
->Error(_("Failed to read the archive headers"));
146 // ARArchive::FindMember - Find a name in the member list /*{{{*/
147 // ---------------------------------------------------------------------
148 /* Find a member with the given name */
149 const ARArchive::Member
*ARArchive::FindMember(const char *Name
) const
151 const Member
*Res
= List
;
154 if (Res
->Name
== Name
)