]>
git.saurik.com Git - apt.git/blob - apt-pkg/edsp.cc
1 // -*- mode: cpp; mode: fold -*-
3 /* ######################################################################
4 Set of methods to help writing and reading everything needed for EDSP
5 ##################################################################### */
7 // Include Files /*{{{*/
10 #include <apt-pkg/error.h>
11 #include <apt-pkg/cacheset.h>
12 #include <apt-pkg/depcache.h>
13 #include <apt-pkg/pkgcache.h>
14 #include <apt-pkg/cacheiterators.h>
15 #include <apt-pkg/progress.h>
16 #include <apt-pkg/fileutl.h>
17 #include <apt-pkg/edsp.h>
18 #include <apt-pkg/tagfile.h>
19 #include <apt-pkg/strutl.h>
35 // we could use pkgCache::DepType and ::Priority, but these would be localized stringsā¦
36 const char * const PrioMap
[] = {0, "important", "required", "standard",
38 const char * const DepMap
[] = {"", "Depends", "Pre-Depends", "Suggests",
39 "Recommends" , "Conflicts", "Replaces",
40 "Obsoletes", "Breaks", "Enhances"};
43 // WriteScenarioVersion /*{{{*/
44 static void WriteScenarioVersion(pkgDepCache
&Cache
, FILE* output
, pkgCache::PkgIterator
const &Pkg
,
45 pkgCache::VerIterator
const &Ver
)
47 fprintf(output
, "Package: %s\n", Pkg
.Name());
48 fprintf(output
, "Source: %s\n", Ver
.SourcePkgName());
49 fprintf(output
, "Architecture: %s\n", Ver
.Arch());
50 fprintf(output
, "Version: %s\n", Ver
.VerStr());
51 fprintf(output
, "Source-Version: %s\n", Ver
.SourceVerStr());
52 if (Pkg
.CurrentVer() == Ver
)
53 fprintf(output
, "Installed: yes\n");
54 if (Pkg
->SelectedState
== pkgCache::State::Hold
||
55 (Cache
[Pkg
].Keep() == true && Cache
[Pkg
].Protect() == true))
56 fprintf(output
, "Hold: yes\n");
57 fprintf(output
, "APT-ID: %d\n", Ver
->ID
);
58 fprintf(output
, "Priority: %s\n", PrioMap
[Ver
->Priority
]);
59 if ((Pkg
->Flags
& pkgCache::Flag::Essential
) == pkgCache::Flag::Essential
)
60 fprintf(output
, "Essential: yes\n");
61 fprintf(output
, "Section: %s\n", Ver
.Section());
62 if ((Ver
->MultiArch
& pkgCache::Version::Allowed
) == pkgCache::Version::Allowed
)
63 fprintf(output
, "Multi-Arch: allowed\n");
64 else if ((Ver
->MultiArch
& pkgCache::Version::Foreign
) == pkgCache::Version::Foreign
)
65 fprintf(output
, "Multi-Arch: foreign\n");
66 else if ((Ver
->MultiArch
& pkgCache::Version::Same
) == pkgCache::Version::Same
)
67 fprintf(output
, "Multi-Arch: same\n");
68 signed short Pin
= std::numeric_limits
<signed short>::min();
69 std::set
<string
> Releases
;
70 for (pkgCache::VerFileIterator I
= Ver
.FileList(); I
.end() == false; ++I
) {
71 pkgCache::PkgFileIterator File
= I
.File();
72 signed short const p
= Cache
.GetPolicy().GetPriority(File
);
75 if (File
.Flagged(pkgCache::Flag::NotSource
) == false) {
76 string Release
= File
.RelStr();
78 Releases
.insert(Release
);
81 if (!Releases
.empty()) {
82 fprintf(output
, "APT-Release:\n");
83 for (std::set
<string
>::iterator R
= Releases
.begin(); R
!= Releases
.end(); ++R
)
84 fprintf(output
, " %s\n", R
->c_str());
86 fprintf(output
, "APT-Pin: %d\n", Pin
);
87 if (Cache
.GetCandidateVersion(Pkg
) == Ver
)
88 fprintf(output
, "APT-Candidate: yes\n");
89 if ((Cache
[Pkg
].Flags
& pkgCache::Flag::Auto
) == pkgCache::Flag::Auto
)
90 fprintf(output
, "APT-Automatic: yes\n");
93 // WriteScenarioDependency /*{{{*/
94 static void WriteScenarioDependency( FILE* output
, pkgCache::VerIterator
const &Ver
)
96 std::string dependencies
[pkgCache::Dep::Enhances
+ 1];
98 for (pkgCache::DepIterator Dep
= Ver
.DependsList(); Dep
.end() == false; ++Dep
)
100 if (Dep
.IsImplicit() == true)
102 if (orGroup
== false)
103 dependencies
[Dep
->Type
].append(", ");
104 dependencies
[Dep
->Type
].append(Dep
.TargetPkg().Name());
105 if (Dep
->Version
!= 0)
106 dependencies
[Dep
->Type
].append(" (").append(pkgCache::CompTypeDeb(Dep
->CompareOp
)).append(" ").append(Dep
.TargetVer()).append(")");
107 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
109 dependencies
[Dep
->Type
].append(" | ");
115 for (int i
= 1; i
< pkgCache::Dep::Enhances
+ 1; ++i
)
116 if (dependencies
[i
].empty() == false)
117 fprintf(output
, "%s: %s\n", DepMap
[i
], dependencies
[i
].c_str()+2);
119 for (pkgCache::PrvIterator Prv
= Ver
.ProvidesList(); Prv
.end() == false; ++Prv
)
121 if (Prv
.IsMultiArchImplicit() == true)
123 provides
.append(", ").append(Prv
.Name());
124 if (Prv
->ProvideVersion
!= 0)
125 provides
.append(" (= ").append(Prv
.ProvideVersion()).append(")");
127 if (provides
.empty() == false)
128 fprintf(output
, "Provides: %s\n", provides
.c_str()+2);
131 // WriteScenarioLimitedDependency /*{{{*/
132 static void WriteScenarioLimitedDependency(FILE* output
,
133 pkgCache::VerIterator
const &Ver
,
134 APT::PackageSet
const &pkgset
)
136 std::string dependencies
[pkgCache::Dep::Enhances
+ 1];
137 bool orGroup
= false;
138 for (pkgCache::DepIterator Dep
= Ver
.DependsList(); Dep
.end() == false; ++Dep
)
140 if (Dep
.IsImplicit() == true)
142 if (orGroup
== false)
144 if (pkgset
.find(Dep
.TargetPkg()) == pkgset
.end())
146 dependencies
[Dep
->Type
].append(", ");
148 else if (pkgset
.find(Dep
.TargetPkg()) == pkgset
.end())
150 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
152 dependencies
[Dep
->Type
].erase(dependencies
[Dep
->Type
].end()-3, dependencies
[Dep
->Type
].end());
156 dependencies
[Dep
->Type
].append(Dep
.TargetPkg().Name());
157 if (Dep
->Version
!= 0)
158 dependencies
[Dep
->Type
].append(" (").append(pkgCache::CompTypeDeb(Dep
->CompareOp
)).append(" ").append(Dep
.TargetVer()).append(")");
159 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
161 dependencies
[Dep
->Type
].append(" | ");
167 for (int i
= 1; i
< pkgCache::Dep::Enhances
+ 1; ++i
)
168 if (dependencies
[i
].empty() == false)
169 fprintf(output
, "%s: %s\n", DepMap
[i
], dependencies
[i
].c_str()+2);
171 for (pkgCache::PrvIterator Prv
= Ver
.ProvidesList(); Prv
.end() == false; ++Prv
)
173 if (Prv
.IsMultiArchImplicit() == true)
175 if (pkgset
.find(Prv
.ParentPkg()) == pkgset
.end())
177 provides
.append(", ").append(Prv
.Name());
179 if (provides
.empty() == false)
180 fprintf(output
, "Provides: %s\n", provides
.c_str()+2);
183 static bool SkipUnavailableVersions(pkgDepCache
&Cache
, pkgCache::PkgIterator
const &Pkg
, pkgCache::VerIterator
const &Ver
)/*{{{*/
185 /* versions which aren't current and aren't available in
186 any "online" source file are bad, expect if they are the choosen
187 candidate: The exception is for build-dep implementation as it creates
188 such pseudo (package) versions and removes them later on again.
189 We filter out versions at all so packages in 'rc' state only available
190 in dpkg/status aren't passed to solvers as they can't be installed. */
191 if (Pkg
->CurrentVer
!= 0)
193 if (Cache
.GetCandidateVersion(Pkg
) == Ver
)
195 for (pkgCache::VerFileIterator I
= Ver
.FileList(); I
.end() == false; ++I
)
196 if (I
.File().Flagged(pkgCache::Flag::NotSource
) == false)
201 // EDSP::WriteScenario - to the given file descriptor /*{{{*/
202 bool EDSP::WriteScenario(pkgDepCache
&Cache
, FILE* output
, OpProgress
*Progress
)
204 if (Progress
!= NULL
)
205 Progress
->SubProgress(Cache
.Head().VersionCount
, _("Send scenario to solver"));
207 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
208 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
210 std::string
const arch
= Pkg
.Arch();
211 if (std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
213 for (pkgCache::VerIterator Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
, ++p
)
215 if (SkipUnavailableVersions(Cache
, Pkg
, Ver
))
217 WriteScenarioVersion(Cache
, output
, Pkg
, Ver
);
218 WriteScenarioDependency(output
, Ver
);
219 fprintf(output
, "\n");
220 if (Progress
!= NULL
&& p
% 100 == 0)
221 Progress
->Progress(p
);
227 // EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/
228 bool EDSP::WriteLimitedScenario(pkgDepCache
&Cache
, FILE* output
,
229 APT::PackageSet
const &pkgset
,
230 OpProgress
*Progress
)
232 if (Progress
!= NULL
)
233 Progress
->SubProgress(Cache
.Head().VersionCount
, _("Send scenario to solver"));
235 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
, ++p
)
236 for (pkgCache::VerIterator Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
238 if (SkipUnavailableVersions(Cache
, Pkg
, Ver
))
240 WriteScenarioVersion(Cache
, output
, Pkg
, Ver
);
241 WriteScenarioLimitedDependency(output
, Ver
, pkgset
);
242 fprintf(output
, "\n");
243 if (Progress
!= NULL
&& p
% 100 == 0)
244 Progress
->Progress(p
);
246 if (Progress
!= NULL
)
251 // EDSP::WriteRequest - to the given file descriptor /*{{{*/
252 bool EDSP::WriteRequest(pkgDepCache
&Cache
, FILE* output
, bool const Upgrade
,
253 bool const DistUpgrade
, bool const AutoRemove
,
254 OpProgress
*Progress
)
256 if (Progress
!= NULL
)
257 Progress
->SubProgress(Cache
.Head().PackageCount
, _("Send request to solver"));
260 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
, ++p
)
262 if (Progress
!= NULL
&& p
% 100 == 0)
263 Progress
->Progress(p
);
265 pkgDepCache::StateCache
&P
= Cache
[Pkg
];
266 if (P
.Delete() == true)
268 else if (P
.NewInstall() == true || P
.Upgrade() == true || P
.ReInstall() == true ||
269 (P
.Mode
== pkgDepCache::ModeKeep
&& (P
.iFlags
& pkgDepCache::Protected
) == pkgDepCache::Protected
))
273 req
->append(" ").append(Pkg
.FullName());
275 fprintf(output
, "Request: EDSP 0.5\n");
277 const char *arch
= _config
->Find("APT::Architecture").c_str();
278 std::vector
<string
> archs
= APT::Configuration::getArchitectures();
279 fprintf(output
, "Architecture: %s\n", arch
);
280 fprintf(output
, "Architectures:");
281 for (std::vector
<string
>::const_iterator a
= archs
.begin(); a
!= archs
.end(); ++a
)
282 fprintf(output
, " %s", a
->c_str());
283 fprintf(output
, "\n");
285 if (del
.empty() == false)
286 fprintf(output
, "Remove: %s\n", del
.c_str()+1);
287 if (inst
.empty() == false)
288 fprintf(output
, "Install: %s\n", inst
.c_str()+1);
290 fprintf(output
, "Upgrade: yes\n");
291 if (DistUpgrade
== true)
292 fprintf(output
, "Dist-Upgrade: yes\n");
293 if (AutoRemove
== true)
294 fprintf(output
, "Autoremove: yes\n");
295 if (_config
->FindB("APT::Solver::Strict-Pinning", true) == false)
296 fprintf(output
, "Strict-Pinning: no\n");
297 string
solverpref("APT::Solver::");
298 solverpref
.append(_config
->Find("APT::Solver", "internal")).append("::Preferences");
299 if (_config
->Exists(solverpref
) == true)
300 fprintf(output
, "Preferences: %s\n", _config
->Find(solverpref
,"").c_str());
301 fprintf(output
, "\n");
306 // EDSP::ReadResponse - from the given file descriptor /*{{{*/
307 bool EDSP::ReadResponse(int const input
, pkgDepCache
&Cache
, OpProgress
*Progress
) {
308 /* We build an map id to mmap offset here
309 In theory we could use the offset as ID, but then VersionCount
310 couldn't be used to create other versionmappings anymore and it
311 would be too easy for a (buggy) solver to segfault APT⦠*/
312 unsigned long long const VersionCount
= Cache
.Head().VersionCount
;
313 unsigned long VerIdx
[VersionCount
];
314 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; ++P
) {
315 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
316 VerIdx
[V
->ID
] = V
.Index();
317 Cache
[P
].Marked
= true;
318 Cache
[P
].Garbage
= false;
322 in
.OpenDescriptor(input
, FileFd::ReadOnly
);
323 pkgTagFile
response(&in
, 100);
324 pkgTagSection section
;
326 while (response
.Step(section
) == true) {
328 if (section
.Exists("Install") == true)
330 else if (section
.Exists("Remove") == true)
332 else if (section
.Exists("Progress") == true) {
333 if (Progress
!= NULL
) {
334 string msg
= section
.FindS("Message");
335 if (msg
.empty() == true)
336 msg
= _("Prepare for receiving solution");
337 Progress
->SubProgress(100, msg
, section
.FindI("Percentage", 0));
340 } else if (section
.Exists("Error") == true) {
341 std::string msg
= SubstVar(SubstVar(section
.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n");
342 if (msg
.empty() == true) {
343 msg
= _("External solver failed without a proper error message");
344 _error
->Error("%s", msg
.c_str());
346 _error
->Error("External solver failed with: %s", msg
.substr(0,msg
.find('\n')).c_str());
347 if (Progress
!= NULL
)
349 std::cerr
<< "The solver encountered an error of type: " << section
.FindS("Error") << std::endl
;
350 std::cerr
<< "The following information might help you to understand what is wrong:" << std::endl
;
351 std::cerr
<< msg
<< std::endl
<< std::endl
;
353 } else if (section
.Exists("Autoremove") == true)
358 size_t const id
= section
.FindULL(type
.c_str(), VersionCount
);
359 if (id
== VersionCount
) {
360 _error
->Warning("Unable to parse %s request with id value '%s'!", type
.c_str(), section
.FindS(type
.c_str()).c_str());
362 } else if (id
> Cache
.Head().VersionCount
) {
363 _error
->Warning("ID value '%s' in %s request stanza is to high to refer to a known version!", section
.FindS(type
.c_str()).c_str(), type
.c_str());
367 pkgCache::VerIterator
Ver(Cache
.GetCache(), Cache
.GetCache().VerP
+ VerIdx
[id
]);
368 Cache
.SetCandidateVersion(Ver
);
369 if (type
== "Install")
371 pkgCache::PkgIterator
const P
= Ver
.ParentPkg();
372 if (Cache
[P
].Mode
!= pkgDepCache::ModeInstall
)
373 Cache
.MarkInstall(P
, false, 0, false);
375 else if (type
== "Remove")
376 Cache
.MarkDelete(Ver
.ParentPkg(), false);
377 else if (type
== "Autoremove") {
378 Cache
[Ver
.ParentPkg()].Marked
= false;
379 Cache
[Ver
.ParentPkg()].Garbage
= true;
385 // ReadLine - first line from the given file descriptor /*{{{*/
386 // ---------------------------------------------------------------------
387 /* Little helper method to read a complete line into a string. Similar to
388 fgets but we need to use the low-level read() here as otherwise the
389 listparser will be confused later on as mixing of fgets and read isn't
390 a supported action according to the manpages and results are undefined */
391 static bool ReadLine(int const input
, std::string
&line
) {
396 while ((data
= read(input
, &one
, sizeof(one
))) != -1) {
403 if (line
.empty() == true && isblank(one
) != 0)
410 // StringToBool - convert yes/no to bool /*{{{*/
411 // ---------------------------------------------------------------------
412 /* we are not as lazy as we are in the global StringToBool as we really
413 only accept yes/no here - but we will ignore leading spaces */
414 static bool StringToBool(char const *answer
, bool const defValue
) {
415 for (; isspace(*answer
) != 0; ++answer
);
416 if (strncasecmp(answer
, "yes", 3) == 0)
418 else if (strncasecmp(answer
, "no", 2) == 0)
421 _error
->Warning("Value '%s' is not a boolean 'yes' or 'no'!", answer
);
425 // EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/
426 bool EDSP::ReadRequest(int const input
, std::list
<std::string
> &install
,
427 std::list
<std::string
> &remove
, bool &upgrade
,
428 bool &distUpgrade
, bool &autoRemove
)
436 while (ReadLine(input
, line
) == true)
438 // Skip empty lines before request
439 if (line
.empty() == true)
441 // The first Tag must be a request, so search for it
442 if (line
.compare(0, 8, "Request:") != 0)
445 while (ReadLine(input
, line
) == true)
447 // empty lines are the end of the request
448 if (line
.empty() == true)
451 std::list
<std::string
> *request
= NULL
;
452 if (line
.compare(0, 8, "Install:") == 0)
457 else if (line
.compare(0, 7, "Remove:") == 0)
462 else if (line
.compare(0, 8, "Upgrade:") == 0)
463 upgrade
= StringToBool(line
.c_str() + 9, false);
464 else if (line
.compare(0, 13, "Dist-Upgrade:") == 0)
465 distUpgrade
= StringToBool(line
.c_str() + 14, false);
466 else if (line
.compare(0, 11, "Autoremove:") == 0)
467 autoRemove
= StringToBool(line
.c_str() + 12, false);
468 else if (line
.compare(0, 13, "Architecture:") == 0)
469 _config
->Set("APT::Architecture", line
.c_str() + 14);
470 else if (line
.compare(0, 14, "Architectures:") == 0)
472 std::string
const archs
= line
.c_str() + 15;
473 _config
->Set("APT::Architectures", SubstVar(archs
, " ", ","));
476 _error
->Warning("Unknown line in EDSP Request stanza: %s", line
.c_str());
480 size_t end
= line
.length();
482 size_t begin
= line
.rfind(' ');
483 if (begin
== std::string::npos
)
485 request
->push_back(line
.substr(0, end
));
488 else if (begin
< end
)
489 request
->push_back(line
.substr(begin
+ 1, end
));
491 end
= line
.find_last_not_of(' ');
492 } while (end
!= std::string::npos
);
498 // EDSP::ApplyRequest - first stanza from the given file descriptor /*{{{*/
499 bool EDSP::ApplyRequest(std::list
<std::string
> const &install
,
500 std::list
<std::string
> const &remove
,
503 for (std::list
<std::string
>::const_iterator i
= install
.begin();
504 i
!= install
.end(); ++i
) {
505 pkgCache::PkgIterator P
= Cache
.FindPkg(*i
);
507 _error
->Warning("Package %s is not known, so can't be installed", i
->c_str());
509 Cache
.MarkInstall(P
, false);
512 for (std::list
<std::string
>::const_iterator i
= remove
.begin();
513 i
!= remove
.end(); ++i
) {
514 pkgCache::PkgIterator P
= Cache
.FindPkg(*i
);
516 _error
->Warning("Package %s is not known, so can't be installed", i
->c_str());
523 // EDSP::WriteSolution - to the given file descriptor /*{{{*/
524 bool EDSP::WriteSolution(pkgDepCache
&Cache
, FILE* output
)
526 bool const Debug
= _config
->FindB("Debug::EDSP::WriteSolution", false);
527 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
529 if (Cache
[Pkg
].Delete() == true)
531 fprintf(output
, "Remove: %d\n", Pkg
.CurrentVer()->ID
);
533 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), Pkg
.CurrentVer().VerStr());
535 else if (Cache
[Pkg
].NewInstall() == true || Cache
[Pkg
].Upgrade() == true)
537 pkgCache::VerIterator
const CandVer
= Cache
.GetCandidateVersion(Pkg
);
538 fprintf(output
, "Install: %d\n", CandVer
->ID
);
540 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), CandVer
.VerStr());
542 else if (Cache
[Pkg
].Garbage
== true)
544 fprintf(output
, "Autoremove: %d\n", Pkg
.CurrentVer()->ID
);
546 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), Pkg
.CurrentVer().VerStr());
550 fprintf(output
, "\n");
556 // EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/
557 bool EDSP::WriteProgress(unsigned short const percent
, const char* const message
, FILE* output
) {
558 fprintf(output
, "Progress: %s\n", TimeRFC1123(time(NULL
)).c_str());
559 fprintf(output
, "Percentage: %d\n", percent
);
560 fprintf(output
, "Message: %s\n\n", message
);
565 // EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/
566 bool EDSP::WriteError(char const * const uuid
, std::string
const &message
, FILE* output
) {
567 fprintf(output
, "Error: %s\n", uuid
);
568 fprintf(output
, "Message: %s\n\n", SubstVar(SubstVar(message
, "\n\n", "\n.\n"), "\n", "\n ").c_str());
572 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/
573 pid_t
EDSP::ExecuteSolver(const char* const solver
, int * const solver_in
, int * const solver_out
, bool) {
574 std::vector
<std::string
> const solverDirs
= _config
->FindVector("Dir::Bin::Solvers");
576 for (std::vector
<std::string
>::const_iterator dir
= solverDirs
.begin();
577 dir
!= solverDirs
.end(); ++dir
) {
578 file
= flCombine(*dir
, solver
);
579 if (RealFileExists(file
.c_str()) == true)
584 if (file
.empty() == true)
586 _error
->Error("Can't call external solver '%s' as it is not in a configured directory!", solver
);
589 int external
[4] = {-1, -1, -1, -1};
590 if (pipe(external
) != 0 || pipe(external
+ 2) != 0)
592 _error
->Errno("Resolve", "Can't create needed IPC pipes for EDSP");
595 for (int i
= 0; i
< 4; ++i
)
596 SetCloseExec(external
[i
], true);
598 pid_t Solver
= ExecFork();
600 dup2(external
[0], STDIN_FILENO
);
601 dup2(external
[3], STDOUT_FILENO
);
602 const char* calling
[2] = { file
.c_str(), 0 };
603 execv(calling
[0], (char**) calling
);
604 std::cerr
<< "Failed to execute solver '" << solver
<< "'!" << std::endl
;
610 if (WaitFd(external
[1], true, 5) == false)
612 _error
->Errno("Resolve", "Timed out while Waiting on availability of solver stdin");
616 *solver_in
= external
[1];
617 *solver_out
= external
[2];
620 bool EDSP::ExecuteSolver(const char* const solver
, int *solver_in
, int *solver_out
) {
621 if (ExecuteSolver(solver
, solver_in
, solver_out
, true) == 0)
626 // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/
627 bool EDSP::ResolveExternal(const char* const solver
, pkgDepCache
&Cache
,
628 bool const upgrade
, bool const distUpgrade
,
629 bool const autoRemove
, OpProgress
*Progress
) {
630 int solver_in
, solver_out
;
631 pid_t
const solver_pid
= EDSP::ExecuteSolver(solver
, &solver_in
, &solver_out
, true);
635 FILE* output
= fdopen(solver_in
, "w");
637 return _error
->Errno("Resolve", "fdopen on solver stdin failed");
639 if (Progress
!= NULL
)
640 Progress
->OverallProgress(0, 100, 5, _("Execute external solver"));
641 EDSP::WriteRequest(Cache
, output
, upgrade
, distUpgrade
, autoRemove
, Progress
);
642 if (Progress
!= NULL
)
643 Progress
->OverallProgress(5, 100, 20, _("Execute external solver"));
644 EDSP::WriteScenario(Cache
, output
, Progress
);
647 if (Progress
!= NULL
)
648 Progress
->OverallProgress(25, 100, 75, _("Execute external solver"));
649 if (EDSP::ReadResponse(solver_out
, Cache
, Progress
) == false)
652 return ExecWait(solver_pid
, solver
);