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