~mvo/apt/mvo

« back to all changes in this revision

Viewing changes to apt-inst/contrib/arfile.cc

  • Committer: Arch Librarian
  • Date: 2004-09-20 16:56:32 UTC
  • Revision ID: Arch-1:apt@arch.ubuntu.com%apt--MAIN--0--patch-614
Join with aliencode
Author: jgg
Date: 2001-02-20 07:03:16 GMT
Join with aliencode

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// -*- mode: cpp; mode: fold -*-
 
2
// Description                                                          /*{{{*/
 
3
// $Id: arfile.cc,v 1.2 2001/02/20 07:03:16 jgg Exp $
 
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
 
 
27
struct 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
/* */
 
41
ARArchive::ARArchive(FileFd &File) : List(0), File(File)
 
42
{
 
43
   LoadHeaders();
 
44
}
 
45
                                                                        /*}}}*/
 
46
// ARArchive::~ARArchive - Destructor                                   /*{{{*/
 
47
// ---------------------------------------------------------------------
 
48
/* */
 
49
ARArchive::~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 */
 
63
bool 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;
 
116
         for (; Head.Name[I] == ' '; I--);
 
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 */
 
142
const 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
                                                                        /*}}}*/