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
))
41 Tags
.Init(&Fd
, 102400);
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 char* binEnd
= binStartNext
- 1;
77 for (; isspace_ascii(*binEnd
) != 0; --binEnd
)
79 StaticBinList
.push_back(bin
);
80 if (*binStartNext
!= ',')
83 for (bin
= binStartNext
+ 1; isspace_ascii(*bin
) != 0; ++bin
)
85 } while (*bin
!= '\0');
86 StaticBinList
.push_back(NULL
);
88 return &StaticBinList
[0];
91 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
92 // ---------------------------------------------------------------------
93 /* This member parses the build-depends information and returns a list of
94 package/version records representing the build dependency. The returned
95 array need not be freed and will be reused by the next call to this
97 bool debSrcRecordParser::BuildDepends(std::vector
<pkgSrcRecords::Parser::BuildDepRec
> &BuildDeps
,
98 bool const &ArchOnly
, bool const &StripMultiArch
)
101 const char *Start
, *Stop
;
103 const char *fields
[] = {"Build-Depends",
104 "Build-Depends-Indep",
106 "Build-Conflicts-Indep"};
110 for (I
= 0; I
< 4; I
++)
112 if (ArchOnly
&& (I
== 1 || I
== 3))
115 if (Sect
.Find(fields
[I
], Start
, Stop
) == false)
120 Start
= debListParser::ParseDepends(Start
, Stop
,
121 rec
.Package
,rec
.Version
,rec
.Op
,true,StripMultiArch
,true);
124 return _error
->Error("Problem parsing dependency: %s", fields
[I
]);
127 if (rec
.Package
!= "")
128 BuildDeps
.push_back(rec
);
138 // SrcRecordParser::Files - Return a list of files for this source /*{{{*/
139 // ---------------------------------------------------------------------
140 /* This parses the list of files and returns it, each file is required to have
141 a complete source package */
142 bool debSrcRecordParser::Files(std::vector
<pkgSrcRecords::File
> &F
)
144 std::vector
<pkgSrcRecords::File2
> F2
;
145 if (Files2(F2
) == false)
147 for (std::vector
<pkgSrcRecords::File2
>::const_iterator f2
= F2
.begin(); f2
!= F2
.end(); ++f2
)
149 pkgSrcRecords::File2 f
;
151 #pragma GCC diagnostic push
152 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
154 f
.MD5Hash
= f2
->MD5Hash
;
157 #pragma GCC diagnostic pop
165 bool debSrcRecordParser::Files2(std::vector
<pkgSrcRecords::File2
> &List
)
169 // Stash the / terminated directory prefix
170 string Base
= Sect
.FindS("Directory");
171 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
174 std::vector
<std::string
> const compExts
= APT::Configuration::getCompressorExtensions();
176 for (char const * const * type
= HashString::SupportedHashes(); *type
!= NULL
; ++type
)
178 // derive field from checksum type
179 std::string
checksumField("Checksums-");
180 if (strcmp(*type
, "MD5Sum") == 0)
181 checksumField
= "Files"; // historic name for MD5 checksums
183 checksumField
.append(*type
);
185 string
const Files
= Sect
.FindS(checksumField
.c_str());
186 if (Files
.empty() == true)
189 // Iterate over the entire list grabbing each triplet
190 const char *C
= Files
.c_str();
193 string hash
, size
, path
;
195 // Parse each of the elements
196 if (ParseQuoteWord(C
, hash
) == false ||
197 ParseQuoteWord(C
, size
) == false ||
198 ParseQuoteWord(C
, path
) == false)
199 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
201 if (iIndex
== nullptr && checksumField
== "Files")
203 // the Files field has a different format than the rest in deb-changes files
205 if (ParseQuoteWord(C
, ignore
) == false ||
206 ParseQuoteWord(C
, path
) == false)
207 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
210 HashString
const hashString(*type
, hash
);
211 if (Base
.empty() == false)
214 // look if we have a record for this file already
215 std::vector
<pkgSrcRecords::File2
>::iterator file
= List
.begin();
216 for (; file
!= List
.end(); ++file
)
217 if (file
->Path
== path
)
220 // we have it already, store the new hash and be done
221 if (file
!= List
.end())
223 if (checksumField
== "Files")
224 APT_IGNORE_DEPRECATED(file
->MD5Hash
= hash
;)
225 // an error here indicates that we have two different hashes for the same file
226 if (file
->Hashes
.push_back(hashString
) == false)
227 return _error
->Error("Error parsing checksum in %s of source package %s", checksumField
.c_str(), Package().c_str());
231 // we haven't seen this file yet
232 pkgSrcRecords::File2 F
;
234 F
.FileSize
= strtoull(size
.c_str(), NULL
, 10);
235 F
.Hashes
.push_back(hashString
);
236 F
.Hashes
.FileSize(F
.FileSize
);
238 APT_IGNORE_DEPRECATED_PUSH
240 if (checksumField
== "Files")
242 APT_IGNORE_DEPRECATED_POP
244 // Try to guess what sort of file it is we are getting.
245 string::size_type Pos
= F
.Path
.length()-1;
248 string::size_type Tmp
= F
.Path
.rfind('.',Pos
);
249 if (Tmp
== string::npos
)
251 if (F
.Type
== "tar") {
252 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
253 if (string(F
.Path
, Tmp
+1, Pos
-Tmp
) == "debian")
257 F
.Type
= string(F
.Path
,Tmp
+1,Pos
-Tmp
);
259 if (std::find(compExts
.begin(), compExts
.end(), std::string(".").append(F
.Type
)) != compExts
.end() ||
275 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
276 // ---------------------------------------------------------------------
278 debSrcRecordParser::~debSrcRecordParser()
280 // was allocated via strndup()
286 debDscRecordParser::debDscRecordParser(std::string
const &DscFile
, pkgIndexFile
const *Index
)
287 : debSrcRecordParser("", Index
)
289 // support clear signed files
290 if (OpenMaybeClearSignedFile(DscFile
, Fd
) == false)
292 _error
->Error("Failed to open %s", DscFile
.c_str());
296 // re-init to ensure the updated Fd is used
297 Tags
.Init(&Fd
, pkgTagFile::SUPPORT_COMMENTS
);
298 // read the first (and only) record