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