]>
git.saurik.com Git - apt.git/blob - apt-inst/deb/debfile.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: debfile.cc,v 1.4 2004/01/07 20:39:37 mdz Exp $
4 /* ######################################################################
6 Debian Archive File (.deb)
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.
13 It also uses the deb package list parser to parse the control file
16 ##################################################################### */
18 // Include Files /*{{{*/
20 #pragma implementation "apt-pkg/debfile.h"
23 #include <apt-pkg/debfile.h>
24 #include <apt-pkg/extracttar.h>
25 #include <apt-pkg/error.h>
26 #include <apt-pkg/deblistparser.h>
33 // DebFile::debDebFile - Constructor /*{{{*/
34 // ---------------------------------------------------------------------
35 /* Open the AR file and check for consistency */
36 debDebFile::debDebFile(FileFd
&File
) : File(File
), AR(File
)
38 if (_error
->PendingError() == true)
41 // Check the members for validity
42 if (CheckMember("debian-binary") == false ||
43 CheckMember("control.tar.gz") == false ||
44 CheckMember("data.tar.gz") == false)
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. */
52 bool debDebFile::CheckMember(const char *Name
)
54 if (AR
.FindMember(Name
) == 0)
55 return _error
->Error(_("This is not a valid DEB archive, missing '%s' member"),Name
);
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! */
66 const ARArchive::Member
*debDebFile::GotoMember(const char *Name
)
68 // Get the archive member and positition the file
69 const ARArchive::Member
*Member
= AR
.FindMember(Name
);
72 _error
->Error(_("Internal Error, could not locate member %s"),Name
);
75 if (File
.Seek(Member
->Start
) == false)
81 // DebFile::ExtractControl - Extract Control information /*{{{*/
82 // ---------------------------------------------------------------------
83 /* Extract the control information into the Database's temporary
85 bool debDebFile::ExtractControl(pkgDataBase
&DB
)
87 // Get the archive member and positition the file
88 const ARArchive::Member
*Member
= GotoMember("control.tar.gz");
93 ControlExtract Extract
;
94 ExtractTar
Tar(File
,Member
->Size
);
95 if (_error
->PendingError() == true)
98 // Get into the temporary directory
99 string Cwd
= SafeGetCWD();
101 if (DB
.GetMetaTmp(Tmp
) == false)
103 if (chdir(Tmp
.c_str()) != 0)
104 return _error
->Errno("chdir",_("Couldn't change to %s"),Tmp
.c_str());
107 if (Tar
.Go(Extract
) == false)
110 // Switch out of the tmp directory.
111 if (chdir(Cwd
.c_str()) != 0)
117 // DebFile::ExtractArchive - Extract the archive data itself /*{{{*/
118 // ---------------------------------------------------------------------
119 /* Simple wrapper around tar.. */
120 bool debDebFile::ExtractArchive(pkgDirStream
&Stream
)
122 // Get the archive member and positition the file
123 const ARArchive::Member
*Member
= AR
.FindMember("data.tar.gz");
125 return _error
->Error(_("Internal Error, could not locate member"));
126 if (File
.Seek(Member
->Start
) == false)
130 ExtractTar
Tar(File
,Member
->Size
);
131 if (_error
->PendingError() == true)
133 return Tar
.Go(Stream
);
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. */
141 pkgCache::VerIterator
debDebFile::MergeControl(pkgDataBase
&DB
)
143 // Open the control file
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());
152 debListParser
Parse(&Fd
);
153 pkgCache::VerIterator
Ver(DB
.GetCache());
154 if (DB
.GetGenerator().MergeList(Parse
,&Ver
) == false)
155 return pkgCache::VerIterator(DB
.GetCache());
157 if (Ver
.end() == true)
158 _error
->Error(_("Failed to locate a valid control file"));
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. */
168 bool debDebFile::ControlExtract::DoItem(Item
&Itm
,int &Fd
)
170 if (Itm
.Type
!= Item::File
)
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
++)
179 /* Force the ownership to be root and ensure correct permissions,
180 go-w, the rest are left untouched */
183 Itm
.Mode
&= ~(S_IWGRP
| S_IWOTH
);
185 return pkgDirStream::DoItem(Itm
,Fd
);
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. */
193 bool debDebFile::MemControlExtract::DoItem(Item
&Itm
,int &Fd
)
195 // At the control file, allocate buffer memory.
196 if (Member
== Itm
.Name
)
199 Control
= new char[Itm
.Size
+2];
201 Fd
= -2; // Signal to pass to Process
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. */
214 bool debDebFile::MemControlExtract::Process(Item
&Itm
,const unsigned char *Data
,
215 unsigned long Size
,unsigned long Pos
)
217 memcpy(Control
+ Pos
, Data
,Size
);
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. */
225 bool debDebFile::MemControlExtract::Read(debDebFile
&Deb
)
227 // Get the archive member and positition the file
228 const ARArchive::Member
*Member
= Deb
.GotoMember("control.tar.gz");
233 ExtractTar
Tar(Deb
.GetFile(),Member
->Size
);
234 if (Tar
.Go(*this) == false)
240 Control
[Length
] = '\n';
241 Control
[Length
+1] = '\n';
242 if (Section
.Scan(Control
,Length
+2) == false)
243 return _error
->Error(_("Unparsible control file"));
247 // MemControlExtract::TakeControl - Parse a memory block /*{{{*/
248 // ---------------------------------------------------------------------
249 /* The given memory block is loaded into the parser and parsed as a control
251 bool debDebFile::MemControlExtract::TakeControl(const void *Data
,unsigned long Size
)
254 Control
= new char[Size
+2];
256 memcpy(Control
,Data
,Size
);
258 Control
[Length
] = '\n';
259 Control
[Length
+1] = '\n';
260 return Section
.Scan(Control
,Length
+2);