]> git.saurik.com Git - apt.git/blame - apt-pkg/deb/debsrcrecords.cc
ensure FileFd doesn't try to open /dev/null as atomic and co
[apt.git] / apt-pkg / deb / debsrcrecords.cc
CommitLineData
11e7af84
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
c33b707e 3// $Id: debsrcrecords.cc,v 1.6 2004/03/17 05:58:54 mdz Exp $
11e7af84
AL
4/* ######################################################################
5
6 Debian Source Package Records - Parser implementation for Debian style
7 source indexes
8
9 ##################################################################### */
10 /*}}}*/
11// Include Files /*{{{*/
ea542140
DK
12#include <config.h>
13
b2e465d6 14#include <apt-pkg/deblistparser.h>
11e7af84
AL
15#include <apt-pkg/debsrcrecords.h>
16#include <apt-pkg/error.h>
36f610f1 17#include <apt-pkg/strutl.h>
b0e1a43f 18#include <apt-pkg/aptconfiguration.h>
453b82a3
DK
19#include <apt-pkg/srcrecords.h>
20#include <apt-pkg/tagfile.h>
cb6a2b3e 21#include <apt-pkg/hashes.h>
feab34c5 22#include <apt-pkg/gpgv.h>
4ab24e53 23
453b82a3
DK
24#include <ctype.h>
25#include <stdlib.h>
26#include <string.h>
27#include <algorithm>
28#include <string>
29#include <vector>
11e7af84
AL
30 /*}}}*/
31
453b82a3 32using std::max;
8f3ba4e8
DK
33using std::string;
34
c8a4ce6c 35debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index)
6c55f07a 36 : Parser(Index), d(NULL), Fd(File,FileFd::ReadOnly, FileFd::Extension), Tags(&Fd,102400),
c8a4ce6c
DK
37 iOffset(0), Buffer(NULL) {}
38
11e7af84
AL
39// SrcRecordParser::Binaries - Return the binaries field /*{{{*/
40// ---------------------------------------------------------------------
41/* This member parses the binaries field into a pair of class arrays and
42 returns a list of strings representing all of the components of the
43 binaries field. The returned array need not be freed and will be
b2e465d6
AL
44 reused by the next Binaries function call. This function is commonly
45 used during scanning to find the right package */
11e7af84
AL
46const char **debSrcRecordParser::Binaries()
47{
39fb1e24
DK
48 const char *Start, *End;
49 if (Sect.Find("Binary", Start, End) == false)
50 return NULL;
51 for (; isspace(*Start) != 0; ++Start);
52 if (Start >= End)
53 return NULL;
54
55 StaticBinList.clear();
56 free(Buffer);
57 Buffer = strndup(Start, End - Start);
c33b707e 58
39fb1e24
DK
59 char* bin = Buffer;
60 do {
61 char* binStartNext = strchrnul(bin, ',');
62 char* binEnd = binStartNext - 1;
63 for (; isspace(*binEnd) != 0; --binEnd)
80624be7 64 binEnd = 0;
39fb1e24
DK
65 StaticBinList.push_back(bin);
66 if (*binStartNext != ',')
67 break;
68 *binStartNext = '\0';
80624be7
MV
69 for (bin = binStartNext + 1; isspace(*bin) != 0; ++bin)
70 ;
39fb1e24
DK
71 } while (*bin != '\0');
72 StaticBinList.push_back(NULL);
c33b707e 73
e788a834 74 return &StaticBinList[0];
b2e465d6
AL
75}
76 /*}}}*/
77// SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
78// ---------------------------------------------------------------------
79/* This member parses the build-depends information and returns a list of
80 package/version records representing the build dependency. The returned
81 array need not be freed and will be reused by the next call to this
82 function */
8f3ba4e8 83bool debSrcRecordParser::BuildDepends(std::vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps,
41c81fd8 84 bool const &ArchOnly, bool const &StripMultiArch)
b2e465d6
AL
85{
86 unsigned int I;
87 const char *Start, *Stop;
88 BuildDepRec rec;
89 const char *fields[] = {"Build-Depends",
90 "Build-Depends-Indep",
91 "Build-Conflicts",
92 "Build-Conflicts-Indep"};
93
94 BuildDeps.clear();
11e7af84 95
b2e465d6 96 for (I = 0; I < 4; I++)
11e7af84 97 {
45430cbf
AL
98 if (ArchOnly && (I == 1 || I == 3))
99 continue;
100
b2e465d6
AL
101 if (Sect.Find(fields[I], Start, Stop) == false)
102 continue;
11e7af84 103
b2e465d6
AL
104 while (1)
105 {
106 Start = debListParser::ParseDepends(Start, Stop,
565ded7b 107 rec.Package,rec.Version,rec.Op,true,StripMultiArch,true);
b2e465d6
AL
108
109 if (Start == 0)
110 return _error->Error("Problem parsing dependency: %s", fields[I]);
111 rec.Type = I;
112
113 if (rec.Package != "")
114 BuildDeps.push_back(rec);
115
116 if (Start == Stop)
117 break;
118 }
11e7af84
AL
119 }
120
b2e465d6 121 return true;
11e7af84
AL
122}
123 /*}}}*/
36f610f1
AL
124// SrcRecordParser::Files - Return a list of files for this source /*{{{*/
125// ---------------------------------------------------------------------
126/* This parses the list of files and returns it, each file is required to have
127 a complete source package */
3a2b39ee 128bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &F)
36f610f1 129{
3a2b39ee
DK
130 std::vector<pkgSrcRecords::File2> F2;
131 if (Files2(F2) == false)
36f610f1 132 return false;
3a2b39ee
DK
133 for (std::vector<pkgSrcRecords::File2>::const_iterator f2 = F2.begin(); f2 != F2.end(); ++f2)
134 {
135 pkgSrcRecords::File2 f;
136#if __GNUC__ >= 4
137 #pragma GCC diagnostic push
138 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
139#endif
140 f.MD5Hash = f2->MD5Hash;
141 f.Size = f2->Size;
142#if __GNUC__ >= 4
143 #pragma GCC diagnostic pop
144#endif
145 f.Path = f2->Path;
146 f.Type = f2->Type;
147 F.push_back(f);
148 }
149 return true;
150}
151bool debSrcRecordParser::Files2(std::vector<pkgSrcRecords::File2> &List)
152{
153 List.clear();
cb6a2b3e 154
1262d358
DK
155 // Stash the / terminated directory prefix
156 string Base = Sect.FindS("Directory");
157 if (Base.empty() == false && Base[Base.length()-1] != '/')
158 Base += '/';
cb6a2b3e 159
1262d358 160 std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
cb6a2b3e 161
1262d358
DK
162 for (char const * const * type = HashString::SupportedHashes(); *type != NULL; ++type)
163 {
164 // derive field from checksum type
165 std::string checksumField("Checksums-");
166 if (strcmp(*type, "MD5Sum") == 0)
167 checksumField = "Files"; // historic name for MD5 checksums
168 else
169 checksumField.append(*type);
170
171 string const Files = Sect.FindS(checksumField.c_str());
172 if (Files.empty() == true)
173 continue;
cb6a2b3e
MV
174
175 // Iterate over the entire list grabbing each triplet
176 const char *C = Files.c_str();
177 while (*C != 0)
1262d358
DK
178 {
179 string hash, size, path;
180
181 // Parse each of the elements
182 if (ParseQuoteWord(C, hash) == false ||
183 ParseQuoteWord(C, size) == false ||
184 ParseQuoteWord(C, path) == false)
185 return _error->Error("Error parsing file record in %s of source package %s", checksumField.c_str(), Package().c_str());
186
187 HashString const hashString(*type, hash);
188 if (Base.empty() == false)
189 path = Base + path;
190
191 // look if we have a record for this file already
3a2b39ee 192 std::vector<pkgSrcRecords::File2>::iterator file = List.begin();
1262d358
DK
193 for (; file != List.end(); ++file)
194 if (file->Path == path)
195 break;
196
197 // we have it already, store the new hash and be done
198 if (file != List.end())
199 {
1262d358 200 if (checksumField == "Files")
586d8704 201 APT_IGNORE_DEPRECATED(file->MD5Hash = hash;)
1262d358
DK
202 // an error here indicates that we have two different hashes for the same file
203 if (file->Hashes.push_back(hashString) == false)
204 return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
205 continue;
206 }
207
208 // we haven't seen this file yet
3a2b39ee 209 pkgSrcRecords::File2 F;
1262d358 210 F.Path = path;
3a2b39ee 211 F.FileSize = strtoull(size.c_str(), NULL, 10);
1262d358
DK
212 F.Hashes.push_back(hashString);
213
d61960d9 214 APT_IGNORE_DEPRECATED_PUSH
3a2b39ee 215 F.Size = F.FileSize;
1262d358 216 if (checksumField == "Files")
3a2b39ee 217 F.MD5Hash = hash;
d61960d9 218 APT_IGNORE_DEPRECATED_POP
1262d358
DK
219
220 // Try to guess what sort of file it is we are getting.
221 string::size_type Pos = F.Path.length()-1;
222 while (1)
223 {
224 string::size_type Tmp = F.Path.rfind('.',Pos);
225 if (Tmp == string::npos)
226 break;
227 if (F.Type == "tar") {
228 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
229 if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
230 F.Type = "diff";
231 break;
232 }
233 F.Type = string(F.Path,Tmp+1,Pos-Tmp);
234
235 if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
236 F.Type == "tar")
237 {
238 Pos = Tmp-1;
239 continue;
240 }
241
242 break;
243 }
244 List.push_back(F);
cb6a2b3e 245 }
36f610f1 246 }
1262d358
DK
247
248 return true;
36f610f1
AL
249}
250 /*}}}*/
7a9f09bd
MV
251// SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
252// ---------------------------------------------------------------------
253/* */
254debSrcRecordParser::~debSrcRecordParser()
255{
7f48c4df
MV
256 // was allocated via strndup()
257 free(Buffer);
7a9f09bd
MV
258}
259 /*}}}*/
feab34c5
MV
260
261
a49e7948
MV
262debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index)
263 : debSrcRecordParser(DscFile, Index)
feab34c5
MV
264{
265 // support clear signed files
266 if (OpenMaybeClearSignedFile(DscFile, Fd) == false)
267 {
268 _error->Error("Failed to open %s", DscFile.c_str());
269 return;
270 }
271
272 // re-init to ensure the updated Fd is used
273 Tags.Init(&Fd);
274 // read the first (and only) record
275 Step();
276
277}