Move apt-all.pot out of build/po, and into po/, and che...
[ntk/apt.git] / apt-inst / contrib / arfile.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
00ec615a 3// $Id: arfile.cc,v 1.4 2002/09/20 05:30:33 tausq 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 /*{{{*/
17#ifdef __GNUG__
18#pragma implementation "apt-pkg/arfile.h"
19#endif
20#include <apt-pkg/arfile.h>
21#include <apt-pkg/strutl.h>
22#include <apt-pkg/error.h>
23
24#include <stdlib.h>
25 /*}}}*/
26
27struct ARArchive::MemberHeader
28{
29 char Name[16];
30 char MTime[12];
31 char UID[6];
32 char GID[6];
33 char Mode[8];
34 char Size[10];
35 char Magic[2];
36};
37
38// ARArchive::ARArchive - Constructor /*{{{*/
39// ---------------------------------------------------------------------
40/* */
41ARArchive::ARArchive(FileFd &File) : List(0), File(File)
42{
43 LoadHeaders();
44}
45 /*}}}*/
46// ARArchive::~ARArchive - Destructor /*{{{*/
47// ---------------------------------------------------------------------
48/* */
49ARArchive::~ARArchive()
50{
51 while (List != 0)
52 {
53 Member *Tmp = List;
54 List = List->Next;
55 delete Tmp;
56 }
57}
58 /*}}}*/
59// ARArchive::LoadHeaders - Load the headers from each file /*{{{*/
60// ---------------------------------------------------------------------
61/* AR files are structured with a 8 byte magic string followed by a 60
62 byte plain text header then the file data, another header, data, etc */
63bool ARArchive::LoadHeaders()
64{
65 signed long Left = File.Size();
66
67 // Check the magic byte
68 char Magic[8];
69 if (File.Read(Magic,sizeof(Magic)) == false)
70 return false;
71 if (memcmp(Magic,"!<arch>\012",sizeof(Magic)) != 0)
72 return _error->Error("Invalid archive signature");
73 Left -= sizeof(Magic);
74
75 // Read the member list
76 while (Left > 0)
77 {
78 MemberHeader Head;
79 if (File.Read(&Head,sizeof(Head)) == false)
80 return _error->Error("Error reading archive member header");
81 Left -= sizeof(Head);
82
83 // Convert all of the integer members
84 Member *Memb = new Member();
85 if (StrToNum(Head.MTime,Memb->MTime,sizeof(Head.MTime)) == false ||
86 StrToNum(Head.UID,Memb->UID,sizeof(Head.UID)) == false ||
87 StrToNum(Head.GID,Memb->GID,sizeof(Head.GID)) == false ||
88 StrToNum(Head.Mode,Memb->Mode,sizeof(Head.Mode),8) == false ||
89 StrToNum(Head.Size,Memb->Size,sizeof(Head.Size)) == false)
90 {
91 delete Memb;
92 return _error->Error("Invalid archive member header");
93 }
94
95 // Check for an extra long name string
96 if (memcmp(Head.Name,"#1/",3) == 0)
97 {
98 char S[300];
99 unsigned long Len;
100 if (StrToNum(Head.Name+3,Len,sizeof(Head.Size)-3) == false ||
101 Len >= strlen(S))
102 {
103 delete Memb;
104 return _error->Error("Invalid archive member header");
105 }
106 if (File.Read(S,Len) == false)
107 return false;
108 S[Len] = 0;
109 Memb->Name = S;
110 Memb->Size -= Len;
111 Left -= Len;
112 }
113 else
114 {
115 unsigned int I = sizeof(Head.Name) - 1;
00ec615a 116 for (; Head.Name[I] == ' '; I--);
b2e465d6
AL
117 Memb->Name = string(Head.Name,0,I+1);
118 }
119
120 // Account for the AR header alignment
121 unsigned Skip = Memb->Size % 2;
122
123 // Add it to the list
124 Memb->Next = List;
125 List = Memb;
126 Memb->Start = File.Tell();
127 if (File.Skip(Memb->Size + Skip) == false)
128 return false;
129 if (Left < (signed)(Memb->Size + Skip))
130 return _error->Error("Archive is too short");
131 Left -= Memb->Size + Skip;
132 }
133 if (Left != 0)
134 return _error->Error("Failed to read the archive headers");
135
136 return true;
137}
138 /*}}}*/
139// ARArchive::FindMember - Find a name in the member list /*{{{*/
140// ---------------------------------------------------------------------
141/* Find a member with the given name */
142const ARArchive::Member *ARArchive::FindMember(const char *Name) const
143{
144 const Member *Res = List;
145 while (Res != 0)
146 {
147 if (Res->Name == Name)
148 return Res;
149 Res = Res->Next;
150 }
151
152 return 0;
153}
154 /*}}}*/