]>
Commit | Line | Data |
---|---|---|
1 | // -*- mode: cpp; mode: fold -*- | |
2 | // Description /*{{{*/ | |
3 | // $Id: debindexfile.cc,v 1.5.2.3 2004/01/04 19:11:00 mdz Exp $ | |
4 | /* ###################################################################### | |
5 | ||
6 | Debian Specific sources.list types and the three sorts of Debian | |
7 | index files. | |
8 | ||
9 | ##################################################################### */ | |
10 | /*}}}*/ | |
11 | // Include Files /*{{{*/ | |
12 | #include <config.h> | |
13 | ||
14 | #include <apt-pkg/debindexfile.h> | |
15 | #include <apt-pkg/debsrcrecords.h> | |
16 | #include <apt-pkg/deblistparser.h> | |
17 | #include <apt-pkg/debrecords.h> | |
18 | #include <apt-pkg/configuration.h> | |
19 | #include <apt-pkg/error.h> | |
20 | #include <apt-pkg/fileutl.h> | |
21 | #include <apt-pkg/indexfile.h> | |
22 | #include <apt-pkg/pkgcache.h> | |
23 | #include <apt-pkg/cacheiterators.h> | |
24 | #include <apt-pkg/pkgrecords.h> | |
25 | #include <apt-pkg/srcrecords.h> | |
26 | ||
27 | #include <stdio.h> | |
28 | #include <iostream> | |
29 | #include <string> | |
30 | #include <sstream> | |
31 | ||
32 | #include <sys/stat.h> | |
33 | #include <unistd.h> | |
34 | /*}}}*/ | |
35 | ||
36 | // Sources Index /*{{{*/ | |
37 | debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) : | |
38 | pkgDebianIndexTargetFile(Target, Trusted), d(NULL) | |
39 | { | |
40 | } | |
41 | std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, | |
42 | pkgSrcRecords::File const &File) const | |
43 | { | |
44 | // The result looks like: http://foo/debian/ stable/main src 1.1.1 (dsc) | |
45 | std::string Res = Target.Description; | |
46 | Res.erase(Target.Description.rfind(' ')); | |
47 | ||
48 | Res += " "; | |
49 | Res += Record.Package(); | |
50 | Res += " "; | |
51 | Res += Record.Version(); | |
52 | if (File.Type.empty() == false) | |
53 | Res += " (" + File.Type + ")"; | |
54 | return Res; | |
55 | } | |
56 | pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const | |
57 | { | |
58 | std::string const SourcesURI = IndexFileName(); | |
59 | if (FileExists(SourcesURI)) | |
60 | return new debSrcRecordParser(SourcesURI, this); | |
61 | return NULL; | |
62 | } | |
63 | bool debSourcesIndex::OpenListFile(FileFd &, std::string const &) | |
64 | { | |
65 | return true; | |
66 | } | |
67 | pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &) | |
68 | { | |
69 | return NULL; | |
70 | } | |
71 | uint8_t debSourcesIndex::GetIndexFlags() const | |
72 | { | |
73 | return 0; | |
74 | } | |
75 | /*}}}*/ | |
76 | // Packages Index /*{{{*/ | |
77 | debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) : | |
78 | pkgDebianIndexTargetFile(Target, Trusted), d(NULL) | |
79 | { | |
80 | } | |
81 | std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const | |
82 | { | |
83 | std::string Res = Target.Description; | |
84 | { | |
85 | auto const space = Target.Description.rfind(' '); | |
86 | if (space != std::string::npos) | |
87 | Res.erase(space); | |
88 | } | |
89 | ||
90 | Res += " "; | |
91 | Res += Ver.ParentPkg().Name(); | |
92 | Res += " "; | |
93 | std::string const Dist = Target.Option(IndexTarget::RELEASE); | |
94 | if (Dist.empty() == false && Dist[Dist.size() - 1] != '/') | |
95 | Res.append(Ver.Arch()).append(" "); | |
96 | Res += Ver.VerStr(); | |
97 | return Res; | |
98 | } | |
99 | uint8_t debPackagesIndex::GetIndexFlags() const | |
100 | { | |
101 | return 0; | |
102 | } | |
103 | /*}}}*/ | |
104 | // Translation-* Index /*{{{*/ | |
105 | debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) : | |
106 | pkgDebianIndexTargetFile(Target, true), d(NULL) | |
107 | {} | |
108 | bool debTranslationsIndex::HasPackages() const | |
109 | { | |
110 | return Exists(); | |
111 | } | |
112 | bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) | |
113 | { | |
114 | if (FileExists(FileName)) | |
115 | return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName); | |
116 | return true; | |
117 | } | |
118 | uint8_t debTranslationsIndex::GetIndexFlags() const | |
119 | { | |
120 | return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages; | |
121 | } | |
122 | std::string debTranslationsIndex::GetArchitecture() const | |
123 | { | |
124 | return std::string(); | |
125 | } | |
126 | pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg) | |
127 | { | |
128 | if (Pkg.IsOpen() == false) | |
129 | return nullptr; | |
130 | _error->PushToStack(); | |
131 | pkgCacheListParser * const Parser = new debTranslationsParser(&Pkg); | |
132 | bool const newError = _error->PendingError(); | |
133 | _error->MergeWithStack(); | |
134 | if (newError) | |
135 | { | |
136 | delete Parser; | |
137 | return nullptr; | |
138 | } | |
139 | else | |
140 | return Parser; | |
141 | } | |
142 | /*}}}*/ | |
143 | // dpkg/status Index /*{{{*/ | |
144 | debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) | |
145 | { | |
146 | } | |
147 | std::string debStatusIndex::GetArchitecture() const | |
148 | { | |
149 | return std::string(); | |
150 | } | |
151 | std::string debStatusIndex::GetComponent() const | |
152 | { | |
153 | return "now"; | |
154 | } | |
155 | uint8_t debStatusIndex::GetIndexFlags() const | |
156 | { | |
157 | return pkgCache::Flag::NotSource; | |
158 | } | |
159 | ||
160 | pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg) | |
161 | { | |
162 | if (Pkg.IsOpen() == false) | |
163 | return nullptr; | |
164 | _error->PushToStack(); | |
165 | pkgCacheListParser * const Parser = new debStatusListParser(&Pkg); | |
166 | bool const newError = _error->PendingError(); | |
167 | _error->MergeWithStack(); | |
168 | if (newError) | |
169 | { | |
170 | delete Parser; | |
171 | return nullptr; | |
172 | } | |
173 | else | |
174 | return Parser; | |
175 | } | |
176 | /*}}}*/ | |
177 | // DebPkgFile Index - a single .deb file as an index /*{{{*/ | |
178 | debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) | |
179 | : pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile) | |
180 | { | |
181 | } | |
182 | bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile) | |
183 | { | |
184 | struct stat Buf; | |
185 | if (stat(debfile.c_str(), &Buf) != 0) | |
186 | return false; | |
187 | ||
188 | // get the control data out of the deb file via dpkg-deb -I | |
189 | std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb"); | |
190 | std::vector<const char *> Args; | |
191 | Args.push_back(dpkg.c_str()); | |
192 | Args.push_back("-I"); | |
193 | Args.push_back(debfile.c_str()); | |
194 | Args.push_back("control"); | |
195 | Args.push_back(NULL); | |
196 | FileFd PipeFd; | |
197 | pid_t Child; | |
198 | if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false) | |
199 | return _error->Error("Popen failed"); | |
200 | ||
201 | content << "Filename: " << debfile << "\n"; | |
202 | content << "Size: " << std::to_string(Buf.st_size) << "\n"; | |
203 | bool first_line_seen = false; | |
204 | char buffer[1024]; | |
205 | do { | |
206 | unsigned long long actual = 0; | |
207 | if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false) | |
208 | return _error->Errno("read", "Failed to read dpkg pipe"); | |
209 | if (actual == 0) | |
210 | break; | |
211 | buffer[actual] = '\0'; | |
212 | char const * b = buffer; | |
213 | if (first_line_seen == false) | |
214 | { | |
215 | for (; *b != '\0' && (*b == '\n' || *b == '\r'); ++b) | |
216 | /* skip over leading newlines */; | |
217 | if (*b == '\0') | |
218 | continue; | |
219 | first_line_seen = true; | |
220 | } | |
221 | content << b; | |
222 | } while(true); | |
223 | ExecWait(Child, "Popen"); | |
224 | ||
225 | return true; | |
226 | } | |
227 | bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) | |
228 | { | |
229 | // write the control data to a tempfile | |
230 | if (GetTempFile("deb-file-" + flNotDir(FileName), true, &Pkg) == NULL) | |
231 | return false; | |
232 | std::ostringstream content; | |
233 | if (GetContent(content, FileName) == false) | |
234 | return false; | |
235 | std::string const contentstr = content.str(); | |
236 | if (contentstr.empty()) | |
237 | return true; | |
238 | if (Pkg.Write(contentstr.c_str(), contentstr.length()) == false || Pkg.Seek(0) == false) | |
239 | return false; | |
240 | return true; | |
241 | } | |
242 | pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg) | |
243 | { | |
244 | if (Pkg.IsOpen() == false) | |
245 | return nullptr; | |
246 | _error->PushToStack(); | |
247 | pkgCacheListParser * const Parser = new debDebFileParser(&Pkg, DebFile); | |
248 | bool const newError = _error->PendingError(); | |
249 | _error->MergeWithStack(); | |
250 | if (newError) | |
251 | { | |
252 | delete Parser; | |
253 | return nullptr; | |
254 | } | |
255 | else | |
256 | return Parser; | |
257 | } | |
258 | uint8_t debDebPkgFileIndex::GetIndexFlags() const | |
259 | { | |
260 | return pkgCache::Flag::LocalSource; | |
261 | } | |
262 | std::string debDebPkgFileIndex::GetArchitecture() const | |
263 | { | |
264 | return std::string(); | |
265 | } | |
266 | std::string debDebPkgFileIndex::GetComponent() const | |
267 | { | |
268 | return "local-deb"; | |
269 | } | |
270 | pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const | |
271 | { | |
272 | std::string const FileName = IndexFileName(); | |
273 | pkgCache::PkgFileIterator File = Cache.FileBegin(); | |
274 | for (; File.end() == false; ++File) | |
275 | { | |
276 | if (File.FileName() == NULL || FileName != File.FileName()) | |
277 | continue; | |
278 | // we can't do size checks here as file size != content size | |
279 | return File; | |
280 | } | |
281 | ||
282 | return File; | |
283 | } | |
284 | std::string debDebPkgFileIndex::ArchiveInfo_impl(pkgCache::VerIterator const &Ver) const | |
285 | { | |
286 | std::string Res = IndexFileName() + " "; | |
287 | Res.append(Ver.ParentPkg().Name()).append(" "); | |
288 | Res.append(Ver.Arch()).append(" "); | |
289 | Res.append(Ver.VerStr()); | |
290 | return Res; | |
291 | } | |
292 | /*}}}*/ | |
293 | // DscFile Index - a single .dsc file as an index /*{{{*/ | |
294 | debDscFileIndex::debDscFileIndex(std::string const &DscFile) | |
295 | : pkgDebianIndexRealFile(DscFile, true), d(NULL) | |
296 | { | |
297 | } | |
298 | pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const | |
299 | { | |
300 | if (Exists() == false) | |
301 | return NULL; | |
302 | return new debDscRecordParser(File, this); | |
303 | } | |
304 | std::string debDscFileIndex::GetComponent() const | |
305 | { | |
306 | return "local-dsc"; | |
307 | } | |
308 | std::string debDscFileIndex::GetArchitecture() const | |
309 | { | |
310 | return "source"; | |
311 | } | |
312 | uint8_t debDscFileIndex::GetIndexFlags() const | |
313 | { | |
314 | return pkgCache::Flag::LocalSource; | |
315 | } | |
316 | /*}}}*/ | |
317 | // ControlFile Index - a directory with a debian/control file /*{{{*/ | |
318 | std::string debDebianSourceDirIndex::GetComponent() const | |
319 | { | |
320 | return "local-control"; | |
321 | } | |
322 | /*}}}*/ | |
323 | // String Package Index - a string of Packages file content /*{{{*/ | |
324 | std::string debStringPackageIndex::GetArchitecture() const | |
325 | { | |
326 | return std::string(); | |
327 | } | |
328 | std::string debStringPackageIndex::GetComponent() const | |
329 | { | |
330 | return "apt-tmp-index"; | |
331 | } | |
332 | uint8_t debStringPackageIndex::GetIndexFlags() const | |
333 | { | |
334 | return pkgCache::Flag::NotSource; | |
335 | } | |
336 | const pkgIndexFile::Type *debStringPackageIndex::GetType() const | |
337 | { | |
338 | return pkgIndexFile::Type::GetType("Debian Package Index"); | |
339 | } | |
340 | debStringPackageIndex::debStringPackageIndex(std::string const &content) : | |
341 | pkgDebianIndexRealFile("", false), d(NULL) | |
342 | { | |
343 | char fn[1024]; | |
344 | std::string const tempdir = GetTempDir(); | |
345 | snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), "apt-tmp-index"); | |
346 | int const fd = mkstemp(fn); | |
347 | File = fn; | |
348 | FileFd::Write(fd, content.data(), content.length()); | |
349 | close(fd); | |
350 | } | |
351 | debStringPackageIndex::~debStringPackageIndex() | |
352 | { | |
353 | RemoveFile("~debStringPackageIndex", File); | |
354 | } | |
355 | /*}}}*/ | |
356 | ||
357 | // Index File types for Debian /*{{{*/ | |
358 | class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type | |
359 | { | |
360 | public: | |
361 | debIFTypeSrc() {Label = "Debian Source Index";}; | |
362 | }; | |
363 | class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type | |
364 | { | |
365 | public: | |
366 | virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE | |
367 | { | |
368 | return new debRecordParser(File.FileName(),*File.Cache()); | |
369 | }; | |
370 | debIFTypePkg() {Label = "Debian Package Index";}; | |
371 | }; | |
372 | class APT_HIDDEN debIFTypeTrans : public debIFTypePkg | |
373 | { | |
374 | public: | |
375 | debIFTypeTrans() {Label = "Debian Translation Index";}; | |
376 | }; | |
377 | class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type | |
378 | { | |
379 | public: | |
380 | virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE | |
381 | { | |
382 | return new debRecordParser(File.FileName(),*File.Cache()); | |
383 | }; | |
384 | debIFTypeStatus() {Label = "Debian dpkg status file";}; | |
385 | }; | |
386 | class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type | |
387 | { | |
388 | public: | |
389 | virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE | |
390 | { | |
391 | return new debDebFileRecordParser(File.FileName()); | |
392 | }; | |
393 | debIFTypeDebPkgFile() {Label = "Debian deb file";}; | |
394 | }; | |
395 | class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type | |
396 | { | |
397 | public: | |
398 | virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const APT_OVERRIDE | |
399 | { | |
400 | return new debDscRecordParser(DscFile, NULL); | |
401 | }; | |
402 | debIFTypeDscFile() {Label = "Debian dsc file";}; | |
403 | }; | |
404 | class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type | |
405 | { | |
406 | public: | |
407 | virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const APT_OVERRIDE | |
408 | { | |
409 | return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL); | |
410 | }; | |
411 | debIFTypeDebianSourceDir() {Label = "Debian control file";}; | |
412 | }; | |
413 | ||
414 | APT_HIDDEN debIFTypeSrc _apt_Src; | |
415 | APT_HIDDEN debIFTypePkg _apt_Pkg; | |
416 | APT_HIDDEN debIFTypeTrans _apt_Trans; | |
417 | APT_HIDDEN debIFTypeStatus _apt_Status; | |
418 | APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile; | |
419 | // file based pseudo indexes | |
420 | APT_HIDDEN debIFTypeDscFile _apt_DscFile; | |
421 | APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir; | |
422 | ||
423 | const pkgIndexFile::Type *debSourcesIndex::GetType() const | |
424 | { | |
425 | return &_apt_Src; | |
426 | } | |
427 | const pkgIndexFile::Type *debPackagesIndex::GetType() const | |
428 | { | |
429 | return &_apt_Pkg; | |
430 | } | |
431 | const pkgIndexFile::Type *debTranslationsIndex::GetType() const | |
432 | { | |
433 | return &_apt_Trans; | |
434 | } | |
435 | const pkgIndexFile::Type *debStatusIndex::GetType() const | |
436 | { | |
437 | return &_apt_Status; | |
438 | } | |
439 | const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const | |
440 | { | |
441 | return &_apt_DebPkgFile; | |
442 | } | |
443 | const pkgIndexFile::Type *debDscFileIndex::GetType() const | |
444 | { | |
445 | return &_apt_DscFile; | |
446 | } | |
447 | const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const | |
448 | { | |
449 | return &_apt_DebianSourceDir; | |
450 | } | |
451 | /*}}}*/ | |
452 | ||
453 | debStatusIndex::~debStatusIndex() {} | |
454 | debPackagesIndex::~debPackagesIndex() {} | |
455 | debTranslationsIndex::~debTranslationsIndex() {} | |
456 | debSourcesIndex::~debSourcesIndex() {} | |
457 | ||
458 | debDebPkgFileIndex::~debDebPkgFileIndex() {} | |
459 | debDscFileIndex::~debDscFileIndex() {} |