]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debsrcrecords.cc
merge sources.list lines based on Release filename
[apt.git] / apt-pkg / deb / debsrcrecords.cc
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
32 using std::max;
33 using std::string;
34
35 debSrcRecordParser::debSrcRecordParser(std::string const &File,pkgIndexFile const *Index)
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 }
44
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
50 reused by the next Binaries function call. This function is commonly
51 used during scanning to find the right package */
52 const char **debSrcRecordParser::Binaries()
53 {
54 const char *Start, *End;
55 if (Sect.Find("Binary", Start, End) == false)
56 return NULL;
57 for (; isspace_ascii(*Start) != 0; ++Start);
58 if (Start >= End)
59 return NULL;
60
61 StaticBinList.clear();
62 free(Buffer);
63 Buffer = strndup(Start, End - Start);
64
65 char* bin = Buffer;
66 do {
67 char* binStartNext = strchrnul(bin, ',');
68 char* binEnd = binStartNext - 1;
69 for (; isspace_ascii(*binEnd) != 0; --binEnd)
70 binEnd = 0;
71 StaticBinList.push_back(bin);
72 if (*binStartNext != ',')
73 break;
74 *binStartNext = '\0';
75 for (bin = binStartNext + 1; isspace_ascii(*bin) != 0; ++bin)
76 ;
77 } while (*bin != '\0');
78 StaticBinList.push_back(NULL);
79
80 return &StaticBinList[0];
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 */
89 bool debSrcRecordParser::BuildDepends(std::vector<pkgSrcRecords::Parser::BuildDepRec> &BuildDeps,
90 bool const &ArchOnly, bool const &StripMultiArch)
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();
101
102 for (I = 0; I < 4; I++)
103 {
104 if (ArchOnly && (I == 1 || I == 3))
105 continue;
106
107 if (Sect.Find(fields[I], Start, Stop) == false)
108 continue;
109
110 while (1)
111 {
112 Start = debListParser::ParseDepends(Start, Stop,
113 rec.Package,rec.Version,rec.Op,true,StripMultiArch,true);
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 }
125 }
126
127 return true;
128 }
129 /*}}}*/
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 */
134 bool debSrcRecordParser::Files(std::vector<pkgSrcRecords::File> &F)
135 {
136 std::vector<pkgSrcRecords::File2> F2;
137 if (Files2(F2) == false)
138 return false;
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 }
157 bool debSrcRecordParser::Files2(std::vector<pkgSrcRecords::File2> &List)
158 {
159 List.clear();
160
161 // Stash the / terminated directory prefix
162 string Base = Sect.FindS("Directory");
163 if (Base.empty() == false && Base[Base.length()-1] != '/')
164 Base += '/';
165
166 std::vector<std::string> const compExts = APT::Configuration::getCompressorExtensions();
167
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;
180
181 // Iterate over the entire list grabbing each triplet
182 const char *C = Files.c_str();
183 while (*C != 0)
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
198 std::vector<pkgSrcRecords::File2>::iterator file = List.begin();
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 {
206 if (checksumField == "Files")
207 APT_IGNORE_DEPRECATED(file->MD5Hash = hash;)
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
215 pkgSrcRecords::File2 F;
216 F.Path = path;
217 F.FileSize = strtoull(size.c_str(), NULL, 10);
218 F.Hashes.push_back(hashString);
219 F.Hashes.FileSize(F.FileSize);
220
221 APT_IGNORE_DEPRECATED_PUSH
222 F.Size = F.FileSize;
223 if (checksumField == "Files")
224 F.MD5Hash = hash;
225 APT_IGNORE_DEPRECATED_POP
226
227 // Try to guess what sort of file it is we are getting.
228 string::size_type Pos = F.Path.length()-1;
229 while (1)
230 {
231 string::size_type Tmp = F.Path.rfind('.',Pos);
232 if (Tmp == string::npos)
233 break;
234 if (F.Type == "tar") {
235 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
236 if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
237 F.Type = "diff";
238 break;
239 }
240 F.Type = string(F.Path,Tmp+1,Pos-Tmp);
241
242 if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
243 F.Type == "tar")
244 {
245 Pos = Tmp-1;
246 continue;
247 }
248
249 break;
250 }
251 List.push_back(F);
252 }
253 }
254
255 return true;
256 }
257 /*}}}*/
258 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
259 // ---------------------------------------------------------------------
260 /* */
261 debSrcRecordParser::~debSrcRecordParser()
262 {
263 // was allocated via strndup()
264 free(Buffer);
265 }
266 /*}}}*/
267
268
269 debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index)
270 : debSrcRecordParser("", Index)
271 {
272 // support clear signed files
273 if (OpenMaybeClearSignedFile(DscFile, Fd) == false)
274 {
275 _error->Error("Failed to open %s", DscFile.c_str());
276 return;
277 }
278
279 // re-init to ensure the updated Fd is used
280 Tags.Init(&Fd, pkgTagFile::SUPPORT_COMMENTS);
281 // read the first (and only) record
282 Step();
283
284 }