1 // -*- mode: cpp; mode: fold -*-
3 // $Id: debsrcrecords.cc,v 1.6 2004/03/17 05:58:54 mdz Exp $
4 /* ######################################################################
6 Debian Source Package Records - Parser implementation for Debian style
9 ##################################################################### */
11 // Include Files /*{{{*/
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>
35 debSrcRecordParser::debSrcRecordParser(std::string
const &File
,pkgIndexFile
const *Index
)
36 : Parser(Index
), d(NULL
), Tags(&Fd
), iOffset(0), Buffer(NULL
)
38 if (File
.empty() == false)
40 if (Fd
.Open(File
, FileFd::ReadOnly
, FileFd::Extension
))
44 std::string
debSrcRecordParser::Package() const /*{{{*/
46 auto const name
= Sect
.FindS("Package");
47 if (iIndex
== nullptr)
48 return name
.empty() ? Sect
.FindS("Source") : name
;
53 // SrcRecordParser::Binaries - Return the binaries field /*{{{*/
54 // ---------------------------------------------------------------------
55 /* This member parses the binaries field into a pair of class arrays and
56 returns a list of strings representing all of the components of the
57 binaries field. The returned array need not be freed and will be
58 reused by the next Binaries function call. This function is commonly
59 used during scanning to find the right package */
60 const char **debSrcRecordParser::Binaries()
62 const char *Start
, *End
;
63 if (Sect
.Find("Binary", Start
, End
) == false)
65 for (; isspace_ascii(*Start
) != 0; ++Start
);
69 StaticBinList
.clear();
71 Buffer
= strndup(Start
, End
- Start
);
75 char* binStartNext
= strchrnul(bin
, ',');
76 // Found a comma, clean up any space before it
77 if (binStartNext
> Buffer
) {
78 char* binEnd
= binStartNext
- 1;
79 for (; binEnd
> Buffer
&& isspace_ascii(*binEnd
) != 0; --binEnd
)
82 StaticBinList
.push_back(bin
);
83 if (*binStartNext
!= ',')
86 for (bin
= binStartNext
+ 1; isspace_ascii(*bin
) != 0; ++bin
)
88 } while (*bin
!= '\0');
89 StaticBinList
.push_back(NULL
);
91 return &StaticBinList
[0];
94 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
95 // ---------------------------------------------------------------------
96 /* This member parses the build-depends information and returns a list of
97 package/version records representing the build dependency. The returned
98 array need not be freed and will be reused by the next call to this
100 bool debSrcRecordParser::BuildDepends(std::vector
<pkgSrcRecords::Parser::BuildDepRec
> &BuildDeps
,
101 bool const &ArchOnly
, bool const &StripMultiArch
)
104 const char *Start
, *Stop
;
106 const char *fields
[] = {"Build-Depends",
107 "Build-Depends-Indep",
109 "Build-Conflicts-Indep",
110 "Build-Depends-Arch",
111 "Build-Conflicts-Arch"};
115 for (I
= 0; I
< 6; I
++)
117 if (ArchOnly
&& (I
== 1 || I
== 3))
120 if (Sect
.Find(fields
[I
], Start
, Stop
) == false)
125 Start
= debListParser::ParseDepends(Start
, Stop
,
126 rec
.Package
,rec
.Version
,rec
.Op
,true,StripMultiArch
,true);
129 return _error
->Error("Problem parsing dependency: %s", fields
[I
]);
132 if (rec
.Package
!= "")
133 BuildDeps
.push_back(rec
);
143 // SrcRecordParser::Files - Return a list of files for this source /*{{{*/
144 // ---------------------------------------------------------------------
145 /* This parses the list of files and returns it, each file is required to have
146 a complete source package */
147 bool debSrcRecordParser::Files(std::vector
<pkgSrcRecords::File
> &F
)
149 std::vector
<pkgSrcRecords::File2
> F2
;
150 if (Files2(F2
) == false)
152 for (std::vector
<pkgSrcRecords::File2
>::const_iterator f2
= F2
.begin(); f2
!= F2
.end(); ++f2
)
154 pkgSrcRecords::File2 f
;
156 #pragma GCC diagnostic push
157 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
159 f
.MD5Hash
= f2
->MD5Hash
;
162 #pragma GCC diagnostic pop
170 bool debSrcRecordParser::Files2(std::vector
<pkgSrcRecords::File2
> &List
)
174 // Stash the / terminated directory prefix
175 string Base
= Sect
.FindS("Directory");
176 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
179 std::vector
<std::string
> const compExts
= APT::Configuration::getCompressorExtensions();
181 for (char const * const * type
= HashString::SupportedHashes(); *type
!= NULL
; ++type
)
183 // derive field from checksum type
184 std::string
checksumField("Checksums-");
185 if (strcmp(*type
, "MD5Sum") == 0)
186 checksumField
= "Files"; // historic name for MD5 checksums
188 checksumField
.append(*type
);
190 string
const Files
= Sect
.FindS(checksumField
.c_str());
191 if (Files
.empty() == true)
194 // Iterate over the entire list grabbing each triplet
195 const char *C
= Files
.c_str();
198 string hash
, size
, path
;
200 // Parse each of the elements
201 if (ParseQuoteWord(C
, hash
) == false ||
202 ParseQuoteWord(C
, size
) == false ||
203 ParseQuoteWord(C
, path
) == false)
204 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
206 if (iIndex
== nullptr && checksumField
== "Files")
208 // the Files field has a different format than the rest in deb-changes files
210 if (ParseQuoteWord(C
, ignore
) == false ||
211 ParseQuoteWord(C
, path
) == false)
212 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
215 HashString
const hashString(*type
, hash
);
216 if (Base
.empty() == false)
219 // look if we have a record for this file already
220 std::vector
<pkgSrcRecords::File2
>::iterator file
= List
.begin();
221 for (; file
!= List
.end(); ++file
)
222 if (file
->Path
== path
)
225 // we have it already, store the new hash and be done
226 if (file
!= List
.end())
228 if (checksumField
== "Files")
229 APT_IGNORE_DEPRECATED(file
->MD5Hash
= hash
;)
230 // an error here indicates that we have two different hashes for the same file
231 if (file
->Hashes
.push_back(hashString
) == false)
232 return _error
->Error("Error parsing checksum in %s of source package %s", checksumField
.c_str(), Package().c_str());
236 // we haven't seen this file yet
237 pkgSrcRecords::File2 F
;
239 F
.FileSize
= strtoull(size
.c_str(), NULL
, 10);
240 F
.Hashes
.push_back(hashString
);
241 F
.Hashes
.FileSize(F
.FileSize
);
243 APT_IGNORE_DEPRECATED_PUSH
245 if (checksumField
== "Files")
247 APT_IGNORE_DEPRECATED_POP
249 // Try to guess what sort of file it is we are getting.
250 string::size_type Pos
= F
.Path
.length()-1;
253 string::size_type Tmp
= F
.Path
.rfind('.',Pos
);
254 if (Tmp
== string::npos
)
256 if (F
.Type
== "tar") {
257 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
258 if (string(F
.Path
, Tmp
+1, Pos
-Tmp
) == "debian")
262 F
.Type
= string(F
.Path
,Tmp
+1,Pos
-Tmp
);
264 if (std::find(compExts
.begin(), compExts
.end(), std::string(".").append(F
.Type
)) != compExts
.end() ||
280 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
281 // ---------------------------------------------------------------------
283 debSrcRecordParser::~debSrcRecordParser()
285 // was allocated via strndup()
291 debDscRecordParser::debDscRecordParser(std::string
const &DscFile
, pkgIndexFile
const *Index
)
292 : debSrcRecordParser("", Index
)
294 // support clear signed files
295 if (OpenMaybeClearSignedFile(DscFile
, Fd
) == false)
297 _error
->Error("Failed to open %s", DscFile
.c_str());
301 // re-init to ensure the updated Fd is used
302 Tags
.Init(&Fd
, pkgTagFile::SUPPORT_COMMENTS
);
303 // read the first (and only) record