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
), Fd(File
,FileFd::ReadOnly
, FileFd::Extension
), Tags(&Fd
,102400),
37 iOffset(0), Buffer(NULL
) {}
39 // SrcRecordParser::Binaries - Return the binaries field /*{{{*/
40 // ---------------------------------------------------------------------
41 /* This member parses the binaries field into a pair of class arrays and
42 returns a list of strings representing all of the components of the
43 binaries field. The returned array need not be freed and will be
44 reused by the next Binaries function call. This function is commonly
45 used during scanning to find the right package */
46 const char **debSrcRecordParser::Binaries()
48 const char *Start
, *End
;
49 if (Sect
.Find("Binary", Start
, End
) == false)
51 for (; isspace(*Start
) != 0; ++Start
);
55 StaticBinList
.clear();
57 Buffer
= strndup(Start
, End
- Start
);
61 char* binStartNext
= strchrnul(bin
, ',');
62 char* binEnd
= binStartNext
- 1;
63 for (; isspace(*binEnd
) != 0; --binEnd
)
65 StaticBinList
.push_back(bin
);
66 if (*binStartNext
!= ',')
69 for (bin
= binStartNext
+ 1; isspace(*bin
) != 0; ++bin
)
71 } while (*bin
!= '\0');
72 StaticBinList
.push_back(NULL
);
74 return &StaticBinList
[0];
77 // SrcRecordParser::BuildDepends - Return the Build-Depends information /*{{{*/
78 // ---------------------------------------------------------------------
79 /* This member parses the build-depends information and returns a list of
80 package/version records representing the build dependency. The returned
81 array need not be freed and will be reused by the next call to this
83 bool debSrcRecordParser::BuildDepends(std::vector
<pkgSrcRecords::Parser::BuildDepRec
> &BuildDeps
,
84 bool const &ArchOnly
, bool const &StripMultiArch
)
87 const char *Start
, *Stop
;
89 const char *fields
[] = {"Build-Depends",
90 "Build-Depends-Indep",
92 "Build-Conflicts-Indep"};
96 for (I
= 0; I
< 4; I
++)
98 if (ArchOnly
&& (I
== 1 || I
== 3))
101 if (Sect
.Find(fields
[I
], Start
, Stop
) == false)
106 Start
= debListParser::ParseDepends(Start
, Stop
,
107 rec
.Package
,rec
.Version
,rec
.Op
,true,StripMultiArch
,true);
110 return _error
->Error("Problem parsing dependency: %s", fields
[I
]);
113 if (rec
.Package
!= "")
114 BuildDeps
.push_back(rec
);
124 // SrcRecordParser::Files - Return a list of files for this source /*{{{*/
125 // ---------------------------------------------------------------------
126 /* This parses the list of files and returns it, each file is required to have
127 a complete source package */
128 bool debSrcRecordParser::Files(std::vector
<pkgSrcRecords::File
> &F
)
130 std::vector
<pkgSrcRecords::File2
> F2
;
131 if (Files2(F2
) == false)
133 for (std::vector
<pkgSrcRecords::File2
>::const_iterator f2
= F2
.begin(); f2
!= F2
.end(); ++f2
)
135 pkgSrcRecords::File2 f
;
137 #pragma GCC diagnostic push
138 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
140 f
.MD5Hash
= f2
->MD5Hash
;
143 #pragma GCC diagnostic pop
151 bool debSrcRecordParser::Files2(std::vector
<pkgSrcRecords::File2
> &List
)
155 // Stash the / terminated directory prefix
156 string Base
= Sect
.FindS("Directory");
157 if (Base
.empty() == false && Base
[Base
.length()-1] != '/')
160 std::vector
<std::string
> const compExts
= APT::Configuration::getCompressorExtensions();
162 for (char const * const * type
= HashString::SupportedHashes(); *type
!= NULL
; ++type
)
164 // derive field from checksum type
165 std::string
checksumField("Checksums-");
166 if (strcmp(*type
, "MD5Sum") == 0)
167 checksumField
= "Files"; // historic name for MD5 checksums
169 checksumField
.append(*type
);
171 string
const Files
= Sect
.FindS(checksumField
.c_str());
172 if (Files
.empty() == true)
175 // Iterate over the entire list grabbing each triplet
176 const char *C
= Files
.c_str();
179 string hash
, size
, path
;
181 // Parse each of the elements
182 if (ParseQuoteWord(C
, hash
) == false ||
183 ParseQuoteWord(C
, size
) == false ||
184 ParseQuoteWord(C
, path
) == false)
185 return _error
->Error("Error parsing file record in %s of source package %s", checksumField
.c_str(), Package().c_str());
187 HashString
const hashString(*type
, hash
);
188 if (Base
.empty() == false)
191 // look if we have a record for this file already
192 std::vector
<pkgSrcRecords::File2
>::iterator file
= List
.begin();
193 for (; file
!= List
.end(); ++file
)
194 if (file
->Path
== path
)
197 // we have it already, store the new hash and be done
198 if (file
!= List
.end())
200 if (checksumField
== "Files")
201 APT_IGNORE_DEPRECATED(file
->MD5Hash
= hash
;)
202 // an error here indicates that we have two different hashes for the same file
203 if (file
->Hashes
.push_back(hashString
) == false)
204 return _error
->Error("Error parsing checksum in %s of source package %s", checksumField
.c_str(), Package().c_str());
208 // we haven't seen this file yet
209 pkgSrcRecords::File2 F
;
211 F
.FileSize
= strtoull(size
.c_str(), NULL
, 10);
212 F
.Hashes
.push_back(hashString
);
214 APT_IGNORE_DEPRECATED_PUSH
216 if (checksumField
== "Files")
218 APT_IGNORE_DEPRECATED_POP
220 // Try to guess what sort of file it is we are getting.
221 string::size_type Pos
= F
.Path
.length()-1;
224 string::size_type Tmp
= F
.Path
.rfind('.',Pos
);
225 if (Tmp
== string::npos
)
227 if (F
.Type
== "tar") {
228 // source v3 has extension 'debian.tar.*' instead of 'diff.*'
229 if (string(F
.Path
, Tmp
+1, Pos
-Tmp
) == "debian")
233 F
.Type
= string(F
.Path
,Tmp
+1,Pos
-Tmp
);
235 if (std::find(compExts
.begin(), compExts
.end(), std::string(".").append(F
.Type
)) != compExts
.end() ||
251 // SrcRecordParser::~SrcRecordParser - Destructor /*{{{*/
252 // ---------------------------------------------------------------------
254 debSrcRecordParser::~debSrcRecordParser()
256 // was allocated via strndup()
262 debDscRecordParser::debDscRecordParser(std::string
const &DscFile
, pkgIndexFile
const *Index
)
263 : debSrcRecordParser(DscFile
, Index
)
265 // support clear signed files
266 if (OpenMaybeClearSignedFile(DscFile
, Fd
) == false)
268 _error
->Error("Failed to open %s", DscFile
.c_str());
272 // re-init to ensure the updated Fd is used
274 // read the first (and only) record