]> git.saurik.com Git - apt.git/blame - apt-inst/deb/debfile.cc
Use baz instead of tla
[apt.git] / apt-inst / deb / debfile.cc
CommitLineData
b2e465d6
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
d77559ac 3// $Id: debfile.cc,v 1.4 2004/01/07 20:39:37 mdz Exp $
b2e465d6
AL
4/* ######################################################################
5
6 Debian Archive File (.deb)
7
8 .DEB archives are AR files containing two tars and an empty marker
9 member called 'debian-binary'. The two tars contain the meta data and
10 the actual archive contents. Thus this class is a very simple wrapper
11 around ar/tar to simply extract the right tar files.
12
13 It also uses the deb package list parser to parse the control file
14 into the cache.
15
16 ##################################################################### */
17 /*}}}*/
18// Include Files /*{{{*/
19#ifdef __GNUG__
20#pragma implementation "apt-pkg/debfile.h"
21#endif
22
23#include <apt-pkg/debfile.h>
24#include <apt-pkg/extracttar.h>
25#include <apt-pkg/error.h>
26#include <apt-pkg/deblistparser.h>
27
28#include <sys/stat.h>
29#include <unistd.h>
d77559ac 30#include <apti18n.h>
b2e465d6
AL
31 /*}}}*/
32
33// DebFile::debDebFile - Constructor /*{{{*/
34// ---------------------------------------------------------------------
35/* Open the AR file and check for consistency */
36debDebFile::debDebFile(FileFd &File) : File(File), AR(File)
37{
38 if (_error->PendingError() == true)
39 return;
40
41 // Check the members for validity
42 if (CheckMember("debian-binary") == false ||
43 CheckMember("control.tar.gz") == false ||
44 CheckMember("data.tar.gz") == false)
45 return;
46}
47 /*}}}*/
48// DebFile::CheckMember - Check if a named member is in the archive /*{{{*/
49// ---------------------------------------------------------------------
50/* This is used to check for a correct deb and to give nicer error messages
51 for people playing around. */
52bool debDebFile::CheckMember(const char *Name)
53{
54 if (AR.FindMember(Name) == 0)
05eb7df0 55 return _error->Error(_("This is not a valid DEB archive, missing '%s' member"),Name);
b2e465d6
AL
56 return true;
57}
58 /*}}}*/
59// DebFile::GotoMember - Jump to a Member /*{{{*/
60// ---------------------------------------------------------------------
61/* Jump in the file to the start of a named member and return the information
62 about that member. The caller can then read from the file up to the
63 returned size. Note, since this relies on the file position this is
64 a destructive operation, it also changes the last returned Member
65 structure - so don't nest them! */
66const ARArchive::Member *debDebFile::GotoMember(const char *Name)
67{
68 // Get the archive member and positition the file
69 const ARArchive::Member *Member = AR.FindMember(Name);
70 if (Member == 0)
71 {
05eb7df0 72 _error->Error(_("Internal Error, could not locate member %s"),Name);
b2e465d6
AL
73 return 0;
74 }
75 if (File.Seek(Member->Start) == false)
76 return 0;
77
78 return Member;
79}
80 /*}}}*/
81// DebFile::ExtractControl - Extract Control information /*{{{*/
82// ---------------------------------------------------------------------
83/* Extract the control information into the Database's temporary
84 directory. */
85bool debDebFile::ExtractControl(pkgDataBase &DB)
86{
87 // Get the archive member and positition the file
88 const ARArchive::Member *Member = GotoMember("control.tar.gz");
89 if (Member == 0)
90 return false;
91
92 // Prepare Tar
93 ControlExtract Extract;
94 ExtractTar Tar(File,Member->Size);
95 if (_error->PendingError() == true)
96 return false;
97
98 // Get into the temporary directory
99 string Cwd = SafeGetCWD();
100 string Tmp;
101 if (DB.GetMetaTmp(Tmp) == false)
102 return false;
103 if (chdir(Tmp.c_str()) != 0)
05eb7df0 104 return _error->Errno("chdir",_("Couldn't change to %s"),Tmp.c_str());
b2e465d6
AL
105
106 // Do extraction
107 if (Tar.Go(Extract) == false)
108 return false;
109
110 // Switch out of the tmp directory.
111 if (chdir(Cwd.c_str()) != 0)
112 chdir("/");
113
114 return true;
115}
116 /*}}}*/
117// DebFile::ExtractArchive - Extract the archive data itself /*{{{*/
118// ---------------------------------------------------------------------
119/* Simple wrapper around tar.. */
120bool debDebFile::ExtractArchive(pkgDirStream &Stream)
121{
122 // Get the archive member and positition the file
123 const ARArchive::Member *Member = AR.FindMember("data.tar.gz");
124 if (Member == 0)
05eb7df0 125 return _error->Error(_("Internal Error, could not locate member"));
b2e465d6
AL
126 if (File.Seek(Member->Start) == false)
127 return false;
128
129 // Prepare Tar
130 ExtractTar Tar(File,Member->Size);
131 if (_error->PendingError() == true)
132 return false;
133 return Tar.Go(Stream);
134}
135 /*}}}*/
136// DebFile::MergeControl - Merge the control information /*{{{*/
137// ---------------------------------------------------------------------
138/* This reads the extracted control file into the cache and returns the
139 version that was parsed. All this really does is select the correct
140 parser and correct file to parse. */
141pkgCache::VerIterator debDebFile::MergeControl(pkgDataBase &DB)
142{
143 // Open the control file
144 string Tmp;
145 if (DB.GetMetaTmp(Tmp) == false)
146 return pkgCache::VerIterator(DB.GetCache());
147 FileFd Fd(Tmp + "control",FileFd::ReadOnly);
148 if (_error->PendingError() == true)
149 return pkgCache::VerIterator(DB.GetCache());
150
151 // Parse it
152 debListParser Parse(&Fd);
153 pkgCache::VerIterator Ver(DB.GetCache());
154 if (DB.GetGenerator().MergeList(Parse,&Ver) == false)
155 return pkgCache::VerIterator(DB.GetCache());
156
157 if (Ver.end() == true)
05eb7df0 158 _error->Error(_("Failed to locate a valid control file"));
b2e465d6
AL
159 return Ver;
160}
161 /*}}}*/
162
163// DebFile::ControlExtract::DoItem - Control Tar Extraction /*{{{*/
164// ---------------------------------------------------------------------
165/* This directory stream handler for the control tar handles extracting
166 it into the temporary meta directory. It only extracts files, it does
167 not create directories, links or anything else. */
168bool debDebFile::ControlExtract::DoItem(Item &Itm,int &Fd)
169{
170 if (Itm.Type != Item::File)
171 return true;
172
173 /* Cleanse the file name, prevent people from trying to unpack into
174 absolute paths, .., etc */
175 for (char *I = Itm.Name; *I != 0; I++)
176 if (*I == '/')
177 *I = '_';
178
179 /* Force the ownership to be root and ensure correct permissions,
180 go-w, the rest are left untouched */
181 Itm.UID = 0;
182 Itm.GID = 0;
183 Itm.Mode &= ~(S_IWGRP | S_IWOTH);
184
185 return pkgDirStream::DoItem(Itm,Fd);
186}
187 /*}}}*/
188
189// MemControlExtract::DoItem - Check if it is the control file /*{{{*/
190// ---------------------------------------------------------------------
191/* This sets up to extract the control block member file into a memory
192 block of just the right size. All other files go into the bit bucket. */
193bool debDebFile::MemControlExtract::DoItem(Item &Itm,int &Fd)
194{
195 // At the control file, allocate buffer memory.
196 if (Member == Itm.Name)
197 {
198 delete [] Control;
199 Control = new char[Itm.Size+2];
200 IsControl = true;
201 Fd = -2; // Signal to pass to Process
202 Length = Itm.Size;
203 }
204 else
205 IsControl = false;
206
207 return true;
208}
209 /*}}}*/
210// MemControlExtract::Process - Process extracting the control file /*{{{*/
211// ---------------------------------------------------------------------
212/* Just memcopy the block from the tar extractor and put it in the right
213 place in the pre-allocated memory block. */
214bool debDebFile::MemControlExtract::Process(Item &Itm,const unsigned char *Data,
215 unsigned long Size,unsigned long Pos)
216{
217 memcpy(Control + Pos, Data,Size);
218 return true;
219}
220 /*}}}*/
221// MemControlExtract::Read - Read the control information from the deb /*{{{*/
222// ---------------------------------------------------------------------
223/* This uses the internal tar extractor to fetch the control file, and then
224 it parses it into a tag section parser. */
225bool debDebFile::MemControlExtract::Read(debDebFile &Deb)
226{
227 // Get the archive member and positition the file
228 const ARArchive::Member *Member = Deb.GotoMember("control.tar.gz");
229 if (Member == 0)
230 return false;
231
232 // Extract it.
233 ExtractTar Tar(Deb.GetFile(),Member->Size);
234 if (Tar.Go(*this) == false)
235 return false;
236
237 if (Control == 0)
238 return true;
239
240 Control[Length] = '\n';
241 Control[Length+1] = '\n';
242 if (Section.Scan(Control,Length+2) == false)
05eb7df0 243 return _error->Error(_("Unparsible control file"));
b2e465d6
AL
244 return true;
245}
246 /*}}}*/
247// MemControlExtract::TakeControl - Parse a memory block /*{{{*/
248// ---------------------------------------------------------------------
249/* The given memory block is loaded into the parser and parsed as a control
250 record. */
251bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long Size)
252{
253 delete [] Control;
254 Control = new char[Size+2];
255 Length = Size;
256 memcpy(Control,Data,Size);
257
258 Control[Length] = '\n';
259 Control[Length+1] = '\n';
260 return Section.Scan(Control,Length+2);
261}
262 /*}}}*/
263