]>
git.saurik.com Git - apt.git/blob - apt-inst/deb/debfile.cc
1 // -*- mode: cpp; mode: fold -*-
3 // $Id: debfile.cc,v 1.3.2.1 2004/01/16 18:58:50 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 /*{{{*/
19 #include <apt-pkg/debfile.h>
20 #include <apt-pkg/extracttar.h>
21 #include <apt-pkg/error.h>
22 #include <apt-pkg/deblistparser.h>
23 #include <apt-pkg/aptconfiguration.h>
30 // DebFile::debDebFile - Constructor /*{{{*/
31 // ---------------------------------------------------------------------
32 /* Open the AR file and check for consistency */
33 debDebFile::debDebFile(FileFd
&File
) : File(File
), AR(File
)
35 if (_error
->PendingError() == true)
38 if (!CheckMember("debian-binary")) {
39 _error
->Error(_("This is not a valid DEB archive, missing '%s' member"), "debian-binary");
43 if (!CheckMember("control.tar.gz")) {
44 _error
->Error(_("This is not a valid DEB archive, missing '%s' member"), "control.tar.gz");
48 if (!CheckMember("data.tar.gz") &&
49 !CheckMember("data.tar.bz2") &&
50 !CheckMember("data.tar.lzma") &&
51 !CheckMember("data.tar.xz")) {
52 // FIXME: add data.tar.xz here - adding it now would require a Translation round for a very small gain
53 _error
->Error(_("This is not a valid DEB archive, it has no '%s', '%s' or '%s' member"), "data.tar.gz", "data.tar.bz2", "data.tar.lzma");
58 // DebFile::CheckMember - Check if a named member is in the archive /*{{{*/
59 // ---------------------------------------------------------------------
60 /* This is used to check for a correct deb and to give nicer error messages
61 for people playing around. */
62 bool debDebFile::CheckMember(const char *Name
)
64 if (AR
.FindMember(Name
) == 0)
69 // DebFile::GotoMember - Jump to a Member /*{{{*/
70 // ---------------------------------------------------------------------
71 /* Jump in the file to the start of a named member and return the information
72 about that member. The caller can then read from the file up to the
73 returned size. Note, since this relies on the file position this is
74 a destructive operation, it also changes the last returned Member
75 structure - so don't nest them! */
76 const ARArchive::Member
*debDebFile::GotoMember(const char *Name
)
78 // Get the archive member and positition the file
79 const ARArchive::Member
*Member
= AR
.FindMember(Name
);
84 if (File
.Seek(Member
->Start
) == false)
90 // DebFile::ExtractControl - Extract Control information /*{{{*/
91 // ---------------------------------------------------------------------
92 /* Extract the control information into the Database's temporary
94 bool debDebFile::ExtractControl(pkgDataBase
&DB
)
96 // Get the archive member and positition the file
97 const ARArchive::Member
*Member
= GotoMember("control.tar.gz");
102 ControlExtract Extract
;
103 ExtractTar
Tar(File
,Member
->Size
,"gzip");
104 if (_error
->PendingError() == true)
107 // Get into the temporary directory
108 string Cwd
= SafeGetCWD();
110 if (DB
.GetMetaTmp(Tmp
) == false)
112 if (chdir(Tmp
.c_str()) != 0)
113 return _error
->Errno("chdir",_("Couldn't change to %s"),Tmp
.c_str());
116 if (Tar
.Go(Extract
) == false)
119 // Switch out of the tmp directory.
120 if (chdir(Cwd
.c_str()) != 0)
126 // DebFile::ExtractArchive - Extract the archive data itself /*{{{*/
127 // ---------------------------------------------------------------------
128 /* Simple wrapper around tar.. */
129 bool debDebFile::ExtractArchive(pkgDirStream
&Stream
)
131 // Get the archive member
132 const ARArchive::Member
*Member
= NULL
;
133 std::string Compressor
;
135 std::string
const data
= "data.tar";
136 std::vector
<APT::Configuration::Compressor
> compressor
= APT::Configuration::getCompressors();
137 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
138 c
!= compressor
.end(); ++c
)
140 Member
= AR
.FindMember(std::string(data
).append(c
->Extension
).c_str());
143 Compressor
= c
->Binary
;
149 std::string ext
= "data.tar.{";
150 for (std::vector
<APT::Configuration::Compressor
>::const_iterator c
= compressor
.begin();
151 c
!= compressor
.end(); ++c
)
152 ext
.append(c
->Extension
.substr(1));
154 return _error
->Error(_("Internal error, could not locate member %s"), ext
.c_str());
157 if (File
.Seek(Member
->Start
) == false)
161 ExtractTar
Tar(File
,Member
->Size
,Compressor
);
162 if (_error
->PendingError() == true)
164 return Tar
.Go(Stream
);
167 // DebFile::MergeControl - Merge the control information /*{{{*/
168 // ---------------------------------------------------------------------
169 /* This reads the extracted control file into the cache and returns the
170 version that was parsed. All this really does is select the correct
171 parser and correct file to parse. */
172 pkgCache::VerIterator
debDebFile::MergeControl(pkgDataBase
&DB
)
174 // Open the control file
176 if (DB
.GetMetaTmp(Tmp
) == false)
177 return pkgCache::VerIterator(DB
.GetCache());
178 FileFd
Fd(Tmp
+ "control",FileFd::ReadOnly
);
179 if (_error
->PendingError() == true)
180 return pkgCache::VerIterator(DB
.GetCache());
183 debListParser
Parse(&Fd
);
184 pkgCache::VerIterator
Ver(DB
.GetCache());
185 if (DB
.GetGenerator().MergeList(Parse
,&Ver
) == false)
186 return pkgCache::VerIterator(DB
.GetCache());
188 if (Ver
.end() == true)
189 _error
->Error(_("Failed to locate a valid control file"));
194 // DebFile::ControlExtract::DoItem - Control Tar Extraction /*{{{*/
195 // ---------------------------------------------------------------------
196 /* This directory stream handler for the control tar handles extracting
197 it into the temporary meta directory. It only extracts files, it does
198 not create directories, links or anything else. */
199 bool debDebFile::ControlExtract::DoItem(Item
&Itm
,int &Fd
)
201 if (Itm
.Type
!= Item::File
)
204 /* Cleanse the file name, prevent people from trying to unpack into
205 absolute paths, .., etc */
206 for (char *I
= Itm
.Name
; *I
!= 0; I
++)
210 /* Force the ownership to be root and ensure correct permissions,
211 go-w, the rest are left untouched */
214 Itm
.Mode
&= ~(S_IWGRP
| S_IWOTH
);
216 return pkgDirStream::DoItem(Itm
,Fd
);
220 // MemControlExtract::DoItem - Check if it is the control file /*{{{*/
221 // ---------------------------------------------------------------------
222 /* This sets up to extract the control block member file into a memory
223 block of just the right size. All other files go into the bit bucket. */
224 bool debDebFile::MemControlExtract::DoItem(Item
&Itm
,int &Fd
)
226 // At the control file, allocate buffer memory.
227 if (Member
== Itm
.Name
)
230 Control
= new char[Itm
.Size
+2];
232 Fd
= -2; // Signal to pass to Process
241 // MemControlExtract::Process - Process extracting the control file /*{{{*/
242 // ---------------------------------------------------------------------
243 /* Just memcopy the block from the tar extractor and put it in the right
244 place in the pre-allocated memory block. */
245 bool debDebFile::MemControlExtract::Process(Item
&Itm
,const unsigned char *Data
,
246 unsigned long Size
,unsigned long Pos
)
248 memcpy(Control
+ Pos
, Data
,Size
);
252 // MemControlExtract::Read - Read the control information from the deb /*{{{*/
253 // ---------------------------------------------------------------------
254 /* This uses the internal tar extractor to fetch the control file, and then
255 it parses it into a tag section parser. */
256 bool debDebFile::MemControlExtract::Read(debDebFile
&Deb
)
258 // Get the archive member and positition the file
259 const ARArchive::Member
*Member
= Deb
.GotoMember("control.tar.gz");
264 ExtractTar
Tar(Deb
.GetFile(),Member
->Size
,"gzip");
265 if (Tar
.Go(*this) == false)
271 Control
[Length
] = '\n';
272 Control
[Length
+1] = '\n';
273 if (Section
.Scan(Control
,Length
+2) == false)
274 return _error
->Error(_("Unparsable control file"));
278 // MemControlExtract::TakeControl - Parse a memory block /*{{{*/
279 // ---------------------------------------------------------------------
280 /* The given memory block is loaded into the parser and parsed as a control
282 bool debDebFile::MemControlExtract::TakeControl(const void *Data
,unsigned long Size
)
285 Control
= new char[Size
+2];
287 memcpy(Control
,Data
,Size
);
289 Control
[Length
] = '\n';
290 Control
[Length
+1] = '\n';
291 return Section
.Scan(Control
,Length
+2);