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