]> git.saurik.com Git - apt.git/blame - apt-inst/contrib/arfile.cc
move defines for version to macros.h
[apt.git] / apt-inst / contrib / arfile.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
b3d44315 3// $Id: arfile.cc,v 1.6.2.1 2004/01/16 18:58:50 mdz Exp $
b2e465d6
AL
4/* ######################################################################
5
6 AR File - Handle an 'AR' archive
7
8 AR Archives have plain text headers at the start of each file
1e3f4083 9 section. The headers are aligned on a 2 byte boundary.
b2e465d6
AL
10
11 Information about the structure of AR files can be found in ar(5)
12 on a BSD system, or in the binutils source.
13
14 ##################################################################### */
15 /*}}}*/
16// Include Files /*{{{*/
ea542140
DK
17#include<config.h>
18
b2e465d6
AL
19#include <apt-pkg/arfile.h>
20#include <apt-pkg/strutl.h>
472ff00e 21#include <apt-pkg/fileutl.h>
b2e465d6
AL
22#include <apt-pkg/error.h>
23
24#include <stdlib.h>
ea542140 25
d77559ac 26#include <apti18n.h>
ea542140 27 /*}}}*/
b2e465d6
AL
28
29struct ARArchive::MemberHeader
30{
31 char Name[16];
32 char MTime[12];
33 char UID[6];
34 char GID[6];
35 char Mode[8];
36 char Size[10];
37 char Magic[2];
38};
39
40// ARArchive::ARArchive - Constructor /*{{{*/
41// ---------------------------------------------------------------------
42/* */
43ARArchive::ARArchive(FileFd &File) : List(0), File(File)
44{
45 LoadHeaders();
46}
47 /*}}}*/
48// ARArchive::~ARArchive - Destructor /*{{{*/
49// ---------------------------------------------------------------------
50/* */
51ARArchive::~ARArchive()
52{
53 while (List != 0)
54 {
55 Member *Tmp = List;
56 List = List->Next;
57 delete Tmp;
58 }
59}
60 /*}}}*/
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 */
65bool ARArchive::LoadHeaders()
66{
3286ad13 67 off_t Left = File.Size();
b2e465d6
AL
68
69 // Check the magic byte
70 char Magic[8];
71 if (File.Read(Magic,sizeof(Magic)) == false)
72 return false;
73 if (memcmp(Magic,"!<arch>\012",sizeof(Magic)) != 0)
05eb7df0 74 return _error->Error(_("Invalid archive signature"));
b2e465d6
AL
75 Left -= sizeof(Magic);
76
77 // Read the member list
78 while (Left > 0)
79 {
80 MemberHeader Head;
81 if (File.Read(&Head,sizeof(Head)) == false)
05eb7df0 82 return _error->Error(_("Error reading archive member header"));
b2e465d6
AL
83 Left -= sizeof(Head);
84
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)
92 {
93 delete Memb;
07b2db9b 94 return _error->Error(_("Invalid archive member header %s"), Head.Name);
b2e465d6
AL
95 }
96
97 // Check for an extra long name string
98 if (memcmp(Head.Name,"#1/",3) == 0)
99 {
100 char S[300];
101 unsigned long Len;
102 if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
472e2c3a 103 Len >= sizeof(S))
b2e465d6
AL
104 {
105 delete Memb;
05eb7df0 106 return _error->Error(_("Invalid archive member header"));
b2e465d6
AL
107 }
108 if (File.Read(S,Len) == false)
24a67e09
NT
109 {
110 delete Memb;
b2e465d6 111 return false;
24a67e09 112 }
b2e465d6
AL
113 S[Len] = 0;
114 Memb->Name = S;
115 Memb->Size -= Len;
116 Left -= Len;
117 }
118 else
119 {
120 unsigned int I = sizeof(Head.Name) - 1;
6f388ec3 121 for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--);
8f3ba4e8 122 Memb->Name = std::string(Head.Name,I+1);
b2e465d6
AL
123 }
124
125 // Account for the AR header alignment
3286ad13 126 off_t Skip = Memb->Size % 2;
b2e465d6
AL
127
128 // Add it to the list
129 Memb->Next = List;
130 List = Memb;
131 Memb->Start = File.Tell();
132 if (File.Skip(Memb->Size + Skip) == false)
133 return false;
3286ad13 134 if (Left < (off_t)(Memb->Size + Skip))
05eb7df0 135 return _error->Error(_("Archive is too short"));
b2e465d6
AL
136 Left -= Memb->Size + Skip;
137 }
138 if (Left != 0)
05eb7df0 139 return _error->Error(_("Failed to read the archive headers"));
b2e465d6
AL
140
141 return true;
142}
143 /*}}}*/
144// ARArchive::FindMember - Find a name in the member list /*{{{*/
145// ---------------------------------------------------------------------
146/* Find a member with the given name */
147const ARArchive::Member *ARArchive::FindMember(const char *Name) const
148{
149 const Member *Res = List;
150 while (Res != 0)
151 {
152 if (Res->Name == Name)
153 return Res;
154 Res = Res->Next;
155 }
156
157 return 0;
158}
159 /*}}}*/