]>
Commit | Line | Data |
---|---|---|
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 __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 | /* */ | |
240 | debSrcRecordParser::~debSrcRecordParser() | |
241 | { | |
242 | // was allocated via strndup() | |
243 | free(Buffer); | |
244 | } | |
245 | /*}}}*/ | |
246 | ||
247 | ||
248 | debDscRecordParser::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 | } |