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);
45 // SrcRecordParser::Binaries - Return the binaries field /*{{{*/
46 // ---------------------------------------------------------------------
47 /* This member parses the binaries field into a pair of class arrays and
48 returns a list of strings representing all of the components of the
49 binaries field. The returned array need not be freed and will be
50 reused by the next Binaries function call. This function is commonly
51 used during scanning to find the right package */
52 const char **debSrcRecordParser::Binaries()
54 const char *Start
, *End
;
55 if (Sect
.Find("Binary", Start
, End
) == false)
57 for (; isspace_ascii(*Start
) != 0; ++Start
);
61 StaticBinList
.clear();
63 Buffer
= strndup(Start
, End
- Start
);
67 char* binStartNext
= strchrnul(bin
, ',');
68 char* binEnd
= binStartNext
- 1;
69 for (; isspace_ascii(*binEnd
) != 0; --binEnd
)
71 StaticBinList
.push_back(bin
);
72 if (*binStartNext
!= ',')
75 for (bin
= binStartNext
+ 1; isspace_ascii(*bin
) != 0; ++bin
)
77 } while (*bin
!= '\0');
78 StaticBinList
.push_back(NULL
);
80 return &StaticBinList
[0];
83 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
84 // ---------------------------------------------------------------------
85 /* This member parses the build-depends information and returns a list of
86 package/version records representing the build dependency. The returned
87 array need not be freed and will be reused by the next call to this
89 bool debSrcRecordParser::BuildDepends(std::vector
<pkgSrcRecords::Parser::BuildDepRec
> &BuildDeps
,
90 bool const &ArchOnly
, bool const &StripMultiArch
)
93 const char *Start
, *Stop
;
95 const char *fields
[] = {"Build-Depends",
96 "Build-Depends-Indep",
98 "Build-Conflicts-Indep"};
102 for (I
= 0; I
< 4; I
++)
104 if (ArchOnly
&& (I
== 1 || I
== 3))
107 if (Sect
.Find(fields
[I
], Start
, Stop
) == false)
112 Start
= debListParser::ParseDepends(Start
, Stop
,
113 rec
.Package
,rec
.Version
,rec
.Op
,true,StripMultiArch
,true);
116 return _error
->Error("Problem parsing dependency: %s", fields
[I
]);
119 if (rec
.Package
!= "")
120 BuildDeps
.push_back(rec
);
130 // SrcRecordParser::Files - Return a list of files for this source /*{{{*/
131 // ---------------------------------------------------------------------
132 /* This parses the list of files and returns it, each file is required to have
133 a complete source package */
134 bool debSrcRecordParser::Files(std::vector
<pkgSrcRecords::File
> &F
)
136 std::vector
<pkgSrcRecords::File2
> F2
;
137 if (Files2(F2
) == false)
139 for (std::vector
<pkgSrcRecords::File2
>::const_iterator f2
= F2
.begin(); f2
!= F2
.end(); ++f2
)
141 pkgSrcRecords::File2 f
;
143 #pragma GCC diagnostic push
144 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
146 f
.MD5Hash
= f2
->MD5Hash
;
149 #pragma GCC diagnostic pop
157 bool debSrcRecordParser::Files2(std::vector
<pkgSrcRecords::File2
> &List
)
161 // Stash the / terminated directory prefix
162 string Base
= Sect
.FindS("Directory");
163 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
166 std::vector
<std::string
> const compExts
= APT::Configuration::getCompressorExtensions();
168 for (char const * const * type
= HashString::SupportedHashes(); *type
!= NULL
; ++type
)
170 // derive field from checksum type
171 std::string
checksumField("Checksums-");
172 if (strcmp(*type
, "MD5Sum") == 0)
173 checksumField
= "Files"; // historic name for MD5 checksums
175 checksumField
.append(*type
);
177 string
const Files
= Sect
.FindS(checksumField
.c_str());
178 if (Files
.empty() == true)
181 // Iterate over the entire list grabbing each triplet
182 const char *C
= Files
.c_str();
185 string hash
, size
, path
;
187 // Parse each of the elements
188 if (ParseQuoteWord(C
, hash
) == false ||
189 ParseQuoteWord(C
, size
) == false ||
190 ParseQuoteWord(C
, path
) == false)
191 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
193 HashString
const hashString(*type
, hash
);
194 if (Base
.empty() == false)
197 // look if we have a record for this file already
198 std::vector
<pkgSrcRecords::File2
>::iterator file
= List
.begin();
199 for (; file
!= List
.end(); ++file
)
200 if (file
->Path
== path
)
203 // we have it already, store the new hash and be done
204 if (file
!= List
.end())
206 if (checksumField
== "Files")
207 APT_IGNORE_DEPRECATED(file
->MD5Hash
= hash
;)
208 // an error here indicates that we have two different hashes for the same file
209 if (file
->Hashes
.push_back(hashString
) == false)
210 return _error
->Error("Error parsing checksum in %s of source package %s", checksumField
.c_str(), Package().c_str());
214 // we haven't seen this file yet
215 pkgSrcRecords::File2 F
;
217 F
.FileSize
= strtoull(size
.c_str(), NULL
, 10);
218 F
.Hashes
.push_back(hashString
);
219 F
.Hashes
.FileSize(F
.FileSize
);
221 APT_IGNORE_DEPRECATED_PUSH
223 if (checksumField
== "Files")
225 APT_IGNORE_DEPRECATED_POP
227 // Try to guess what sort of file it is we are getting.
228 string::size_type Pos
= F
.Path
.length()-1;
231 string::size_type Tmp
= F
.Path
.rfind('.',Pos
);
232 if (Tmp
== string::npos
)
234 if (F
.Type
== "tar") {
235 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
236 if (string(F
.Path
, Tmp
+1, Pos
-Tmp
) == "debian")
240 F
.Type
= string(F
.Path
,Tmp
+1,Pos
-Tmp
);
242 if (std::find(compExts
.begin(), compExts
.end(), std::string(".").append(F
.Type
)) != compExts
.end() ||
258 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
259 // ---------------------------------------------------------------------
261 debSrcRecordParser::~debSrcRecordParser()
263 // was allocated via strndup()
269 debDscRecordParser::debDscRecordParser(std::string
const &DscFile
, pkgIndexFile
const *Index
)
270 : debSrcRecordParser("", Index
)
272 // support clear signed files
273 if (OpenMaybeClearSignedFile(DscFile
, Fd
) == false)
275 _error
->Error("Failed to open %s", DscFile
.c_str());
279 // re-init to ensure the updated Fd is used
280 Tags
.Init(&Fd
, pkgTagFile::SUPPORT_COMMENTS
);
281 // read the first (and only) record