]> git.saurik.com Git - apt.git/blob - apt-pkg/deb/debsrcrecords.cc
rework dpkg-wrapping in test framework
[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 // 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 */
42 const 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 */
79 bool 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 */
124 bool 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 (checksumField == "Files")
174 APT_IGNORE_DEPRECATED(file->MD5Hash = hash;)
175 // an error here indicates that we have two different hashes for the same file
176 if (file->Hashes.push_back(hashString) == false)
177 return _error->Error("Error parsing checksum in %s of source package %s", checksumField.c_str(), Package().c_str());
178 continue;
179 }
180
181 // we haven't seen this file yet
182 pkgSrcRecords::File F;
183 F.Path = path;
184 F.Size = strtoull(size.c_str(), NULL, 10);
185 F.Hashes.push_back(hashString);
186
187 if (checksumField == "Files")
188 APT_IGNORE_DEPRECATED(F.MD5Hash = hash;)
189
190 // Try to guess what sort of file it is we are getting.
191 string::size_type Pos = F.Path.length()-1;
192 while (1)
193 {
194 string::size_type Tmp = F.Path.rfind('.',Pos);
195 if (Tmp == string::npos)
196 break;
197 if (F.Type == "tar") {
198 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
199 if (string(F.Path, Tmp+1, Pos-Tmp) == "debian")
200 F.Type = "diff";
201 break;
202 }
203 F.Type = string(F.Path,Tmp+1,Pos-Tmp);
204
205 if (std::find(compExts.begin(), compExts.end(), std::string(".").append(F.Type)) != compExts.end() ||
206 F.Type == "tar")
207 {
208 Pos = Tmp-1;
209 continue;
210 }
211
212 break;
213 }
214 List.push_back(F);
215 }
216 }
217
218 return true;
219 }
220 /*}}}*/
221 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
222 // ---------------------------------------------------------------------
223 /* */
224 debSrcRecordParser::~debSrcRecordParser()
225 {
226 // was allocated via strndup()
227 free(Buffer);
228 }
229 /*}}}*/
230
231
232 debDscRecordParser::debDscRecordParser(std::string const &DscFile, pkgIndexFile const *Index)
233 : debSrcRecordParser(DscFile, Index)
234 {
235 // support clear signed files
236 if (OpenMaybeClearSignedFile(DscFile, Fd) == false)
237 {
238 _error->Error("Failed to open %s", DscFile.c_str());
239 return;
240 }
241
242 // re-init to ensure the updated Fd is used
243 Tags.Init(&Fd);
244 // read the first (and only) record
245 Step();
246
247 }