merge lp:~mvo/apt/sha512-template to add support for sha512
[ntk/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
9 section. The headers are aligned on a 2 byte boundry.
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 /*{{{*/
b2e465d6
AL
17#include <apt-pkg/arfile.h>
18#include <apt-pkg/strutl.h>
19#include <apt-pkg/error.h>
20
21#include <stdlib.h>
22 /*}}}*/
d77559ac 23#include <apti18n.h>
b2e465d6
AL
24
25struct ARArchive::MemberHeader
26{
27 char Name[16];
28 char MTime[12];
29 char UID[6];
30 char GID[6];
31 char Mode[8];
32 char Size[10];
33 char Magic[2];
34};
35
36// ARArchive::ARArchive - Constructor /*{{{*/
37// ---------------------------------------------------------------------
38/* */
39ARArchive::ARArchive(FileFd &File) : List(0), File(File)
40{
41 LoadHeaders();
42}
43 /*}}}*/
44// ARArchive::~ARArchive - Destructor /*{{{*/
45// ---------------------------------------------------------------------
46/* */
47ARArchive::~ARArchive()
48{
49 while (List != 0)
50 {
51 Member *Tmp = List;
52 List = List->Next;
53 delete Tmp;
54 }
55}
56 /*}}}*/
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 */
61bool ARArchive::LoadHeaders()
62{
63 signed long Left = File.Size();
64
65 // Check the magic byte
66 char Magic[8];
67 if (File.Read(Magic,sizeof(Magic)) == false)
68 return false;
69 if (memcmp(Magic,"!<arch>\012",sizeof(Magic)) != 0)
05eb7df0 70 return _error->Error(_("Invalid archive signature"));
b2e465d6
AL
71 Left -= sizeof(Magic);
72
73 // Read the member list
74 while (Left > 0)
75 {
76 MemberHeader Head;
77 if (File.Read(&Head,sizeof(Head)) == false)
05eb7df0 78 return _error->Error(_("Error reading archive member header"));
b2e465d6
AL
79 Left -= sizeof(Head);
80
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)
88 {
89 delete Memb;
07b2db9b 90 return _error->Error(_("Invalid archive member header %s"), Head.Name);
b2e465d6
AL
91 }
92
93 // Check for an extra long name string
94 if (memcmp(Head.Name,"#1/",3) == 0)
95 {
96 char S[300];
97 unsigned long Len;
98 if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
472e2c3a 99 Len >= sizeof(S))
b2e465d6
AL
100 {
101 delete Memb;
05eb7df0 102 return _error->Error(_("Invalid archive member header"));
b2e465d6
AL
103 }
104 if (File.Read(S,Len) == false)
105 return false;
106 S[Len] = 0;
107 Memb->Name = S;
108 Memb->Size -= Len;
109 Left -= Len;
110 }
111 else
112 {
113 unsigned int I = sizeof(Head.Name) - 1;
6f388ec3 114 for (; Head.Name[I] == ' ' || Head.Name[I] == '/'; I--);
d48c6a7d 115 Memb->Name = string(Head.Name,I+1);
b2e465d6
AL
116 }
117
118 // Account for the AR header alignment
119 unsigned Skip = Memb->Size % 2;
120
121 // Add it to the list
122 Memb->Next = List;
123 List = Memb;
124 Memb->Start = File.Tell();
125 if (File.Skip(Memb->Size + Skip) == false)
126 return false;
127 if (Left < (signed)(Memb->Size + Skip))
05eb7df0 128 return _error->Error(_("Archive is too short"));
b2e465d6
AL
129 Left -= Memb->Size + Skip;
130 }
131 if (Left != 0)
05eb7df0 132 return _error->Error(_("Failed to read the archive headers"));
b2e465d6
AL
133
134 return true;
135}
136 /*}}}*/
137// ARArchive::FindMember - Find a name in the member list /*{{{*/
138// ---------------------------------------------------------------------
139/* Find a member with the given name */
140const ARArchive::Member *ARArchive::FindMember(const char *Name) const
141{
142 const Member *Res = List;
143 while (Res != 0)
144 {
145 if (Res->Name == Name)
146 return Res;
147 Res = Res->Next;
148 }
149
150 return 0;
151}
152 /*}}}*/