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