]>
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 std::set
<string
> Releases
;
69 for (pkgCache::VerFileIterator I
= Ver
.FileList(); I
.end() == false; ++I
) {
70 pkgCache::PkgFileIterator File
= I
.File();
71 if (File
.Flagged(pkgCache::Flag::NotSource
) == false) {
72 string Release
= File
.RelStr();
74 Releases
.insert(Release
);
77 if (!Releases
.empty()) {
78 fprintf(output
, "APT-Release:\n");
79 for (std::set
<string
>::iterator R
= Releases
.begin(); R
!= Releases
.end(); ++R
)
80 fprintf(output
, " %s\n", R
->c_str());
82 fprintf(output
, "APT-Pin: %d\n", Cache
.GetPolicy().GetPriority(Ver
));
83 if (Cache
.GetCandidateVersion(Pkg
) == Ver
)
84 fprintf(output
, "APT-Candidate: yes\n");
85 if ((Cache
[Pkg
].Flags
& pkgCache::Flag::Auto
) == pkgCache::Flag::Auto
)
86 fprintf(output
, "APT-Automatic: yes\n");
89 // WriteScenarioDependency /*{{{*/
90 static void WriteScenarioDependency( FILE* output
, pkgCache::VerIterator
const &Ver
)
92 std::string dependencies
[pkgCache::Dep::Enhances
+ 1];
94 for (pkgCache::DepIterator Dep
= Ver
.DependsList(); Dep
.end() == false; ++Dep
)
96 if (Dep
.IsImplicit() == true)
99 dependencies
[Dep
->Type
].append(", ");
100 dependencies
[Dep
->Type
].append(Dep
.TargetPkg().Name());
101 if (Dep
->Version
!= 0)
102 dependencies
[Dep
->Type
].append(" (").append(pkgCache::CompTypeDeb(Dep
->CompareOp
)).append(" ").append(Dep
.TargetVer()).append(")");
103 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
105 dependencies
[Dep
->Type
].append(" | ");
111 for (int i
= 1; i
< pkgCache::Dep::Enhances
+ 1; ++i
)
112 if (dependencies
[i
].empty() == false)
113 fprintf(output
, "%s: %s\n", DepMap
[i
], dependencies
[i
].c_str()+2);
115 for (pkgCache::PrvIterator Prv
= Ver
.ProvidesList(); Prv
.end() == false; ++Prv
)
117 if (Prv
.IsMultiArchImplicit() == true)
119 provides
.append(", ").append(Prv
.Name());
120 if (Prv
->ProvideVersion
!= 0)
121 provides
.append(" (= ").append(Prv
.ProvideVersion()).append(")");
123 if (provides
.empty() == false)
124 fprintf(output
, "Provides: %s\n", provides
.c_str()+2);
127 // WriteScenarioLimitedDependency /*{{{*/
128 static void WriteScenarioLimitedDependency(FILE* output
,
129 pkgCache::VerIterator
const &Ver
,
130 APT::PackageSet
const &pkgset
)
132 std::string dependencies
[pkgCache::Dep::Enhances
+ 1];
133 bool orGroup
= false;
134 for (pkgCache::DepIterator Dep
= Ver
.DependsList(); Dep
.end() == false; ++Dep
)
136 if (Dep
.IsImplicit() == true)
138 if (orGroup
== false)
140 if (pkgset
.find(Dep
.TargetPkg()) == pkgset
.end())
142 dependencies
[Dep
->Type
].append(", ");
144 else if (pkgset
.find(Dep
.TargetPkg()) == pkgset
.end())
146 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
148 dependencies
[Dep
->Type
].erase(dependencies
[Dep
->Type
].end()-3, dependencies
[Dep
->Type
].end());
152 dependencies
[Dep
->Type
].append(Dep
.TargetPkg().Name());
153 if (Dep
->Version
!= 0)
154 dependencies
[Dep
->Type
].append(" (").append(pkgCache::CompTypeDeb(Dep
->CompareOp
)).append(" ").append(Dep
.TargetVer()).append(")");
155 if ((Dep
->CompareOp
& pkgCache::Dep::Or
) == pkgCache::Dep::Or
)
157 dependencies
[Dep
->Type
].append(" | ");
163 for (int i
= 1; i
< pkgCache::Dep::Enhances
+ 1; ++i
)
164 if (dependencies
[i
].empty() == false)
165 fprintf(output
, "%s: %s\n", DepMap
[i
], dependencies
[i
].c_str()+2);
167 for (pkgCache::PrvIterator Prv
= Ver
.ProvidesList(); Prv
.end() == false; ++Prv
)
169 if (Prv
.IsMultiArchImplicit() == true)
171 if (pkgset
.find(Prv
.ParentPkg()) == pkgset
.end())
173 provides
.append(", ").append(Prv
.Name());
175 if (provides
.empty() == false)
176 fprintf(output
, "Provides: %s\n", provides
.c_str()+2);
179 static bool SkipUnavailableVersions(pkgDepCache
&Cache
, pkgCache::PkgIterator
const &Pkg
, pkgCache::VerIterator
const &Ver
)/*{{{*/
181 /* versions which aren't current and aren't available in
182 any "online" source file are bad, expect if they are the choosen
183 candidate: The exception is for build-dep implementation as it creates
184 such pseudo (package) versions and removes them later on again.
185 We filter out versions at all so packages in 'rc' state only available
186 in dpkg/status aren't passed to solvers as they can't be installed. */
187 if (Pkg
->CurrentVer
!= 0)
189 if (Cache
.GetCandidateVersion(Pkg
) == Ver
)
191 for (pkgCache::VerFileIterator I
= Ver
.FileList(); I
.end() == false; ++I
)
192 if (I
.File().Flagged(pkgCache::Flag::NotSource
) == false)
197 // EDSP::WriteScenario - to the given file descriptor /*{{{*/
198 bool EDSP::WriteScenario(pkgDepCache
&Cache
, FILE* output
, OpProgress
*Progress
)
200 if (Progress
!= NULL
)
201 Progress
->SubProgress(Cache
.Head().VersionCount
, _("Send scenario to solver"));
203 std::vector
<std::string
> archs
= APT::Configuration::getArchitectures();
204 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
206 std::string
const arch
= Pkg
.Arch();
207 if (std::find(archs
.begin(), archs
.end(), arch
) == archs
.end())
209 for (pkgCache::VerIterator Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
, ++p
)
211 if (SkipUnavailableVersions(Cache
, Pkg
, Ver
))
213 WriteScenarioVersion(Cache
, output
, Pkg
, Ver
);
214 WriteScenarioDependency(output
, Ver
);
215 fprintf(output
, "\n");
216 if (Progress
!= NULL
&& p
% 100 == 0)
217 Progress
->Progress(p
);
223 // EDSP::WriteLimitedScenario - to the given file descriptor /*{{{*/
224 bool EDSP::WriteLimitedScenario(pkgDepCache
&Cache
, FILE* output
,
225 APT::PackageSet
const &pkgset
,
226 OpProgress
*Progress
)
228 if (Progress
!= NULL
)
229 Progress
->SubProgress(Cache
.Head().VersionCount
, _("Send scenario to solver"));
231 for (APT::PackageSet::const_iterator Pkg
= pkgset
.begin(); Pkg
!= pkgset
.end(); ++Pkg
, ++p
)
232 for (pkgCache::VerIterator Ver
= Pkg
.VersionList(); Ver
.end() == false; ++Ver
)
234 if (SkipUnavailableVersions(Cache
, Pkg
, Ver
))
236 WriteScenarioVersion(Cache
, output
, Pkg
, Ver
);
237 WriteScenarioLimitedDependency(output
, Ver
, pkgset
);
238 fprintf(output
, "\n");
239 if (Progress
!= NULL
&& p
% 100 == 0)
240 Progress
->Progress(p
);
242 if (Progress
!= NULL
)
247 // EDSP::WriteRequest - to the given file descriptor /*{{{*/
248 bool EDSP::WriteRequest(pkgDepCache
&Cache
, FILE* output
, bool const Upgrade
,
249 bool const DistUpgrade
, bool const AutoRemove
,
250 OpProgress
*Progress
)
252 if (Progress
!= NULL
)
253 Progress
->SubProgress(Cache
.Head().PackageCount
, _("Send request to solver"));
256 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
, ++p
)
258 if (Progress
!= NULL
&& p
% 100 == 0)
259 Progress
->Progress(p
);
261 pkgDepCache::StateCache
&P
= Cache
[Pkg
];
262 if (P
.Delete() == true)
264 else if (P
.NewInstall() == true || P
.Upgrade() == true || P
.ReInstall() == true ||
265 (P
.Mode
== pkgDepCache::ModeKeep
&& (P
.iFlags
& pkgDepCache::Protected
) == pkgDepCache::Protected
))
269 req
->append(" ").append(Pkg
.FullName());
271 fprintf(output
, "Request: EDSP 0.5\n");
273 const char *arch
= _config
->Find("APT::Architecture").c_str();
274 std::vector
<string
> archs
= APT::Configuration::getArchitectures();
275 fprintf(output
, "Architecture: %s\n", arch
);
276 fprintf(output
, "Architectures:");
277 for (std::vector
<string
>::const_iterator a
= archs
.begin(); a
!= archs
.end(); ++a
)
278 fprintf(output
, " %s", a
->c_str());
279 fprintf(output
, "\n");
281 if (del
.empty() == false)
282 fprintf(output
, "Remove: %s\n", del
.c_str()+1);
283 if (inst
.empty() == false)
284 fprintf(output
, "Install: %s\n", inst
.c_str()+1);
286 fprintf(output
, "Upgrade: yes\n");
287 if (DistUpgrade
== true)
288 fprintf(output
, "Dist-Upgrade: yes\n");
289 if (AutoRemove
== true)
290 fprintf(output
, "Autoremove: yes\n");
291 if (_config
->FindB("APT::Solver::Strict-Pinning", true) == false)
292 fprintf(output
, "Strict-Pinning: no\n");
293 string
solverpref("APT::Solver::");
294 solverpref
.append(_config
->Find("APT::Solver", "internal")).append("::Preferences");
295 if (_config
->Exists(solverpref
) == true)
296 fprintf(output
, "Preferences: %s\n", _config
->Find(solverpref
,"").c_str());
297 fprintf(output
, "\n");
302 // EDSP::ReadResponse - from the given file descriptor /*{{{*/
303 bool EDSP::ReadResponse(int const input
, pkgDepCache
&Cache
, OpProgress
*Progress
) {
304 /* We build an map id to mmap offset here
305 In theory we could use the offset as ID, but then VersionCount
306 couldn't be used to create other versionmappings anymore and it
307 would be too easy for a (buggy) solver to segfault APTā¦ */
308 unsigned long long const VersionCount
= Cache
.Head().VersionCount
;
309 unsigned long VerIdx
[VersionCount
];
310 for (pkgCache::PkgIterator P
= Cache
.PkgBegin(); P
.end() == false; ++P
) {
311 for (pkgCache::VerIterator V
= P
.VersionList(); V
.end() == false; ++V
)
312 VerIdx
[V
->ID
] = V
.Index();
313 Cache
[P
].Marked
= true;
314 Cache
[P
].Garbage
= false;
318 in
.OpenDescriptor(input
, FileFd::ReadOnly
);
319 pkgTagFile
response(&in
, 100);
320 pkgTagSection section
;
322 while (response
.Step(section
) == true) {
324 if (section
.Exists("Install") == true)
326 else if (section
.Exists("Remove") == true)
328 else if (section
.Exists("Progress") == true) {
329 if (Progress
!= NULL
) {
330 string msg
= section
.FindS("Message");
331 if (msg
.empty() == true)
332 msg
= _("Prepare for receiving solution");
333 Progress
->SubProgress(100, msg
, section
.FindI("Percentage", 0));
336 } else if (section
.Exists("Error") == true) {
337 std::string msg
= SubstVar(SubstVar(section
.FindS("Message"), "\n .\n", "\n\n"), "\n ", "\n");
338 if (msg
.empty() == true) {
339 msg
= _("External solver failed without a proper error message");
340 _error
->Error("%s", msg
.c_str());
342 _error
->Error("External solver failed with: %s", msg
.substr(0,msg
.find('\n')).c_str());
343 if (Progress
!= NULL
)
345 std::cerr
<< "The solver encountered an error of type: " << section
.FindS("Error") << std::endl
;
346 std::cerr
<< "The following information might help you to understand what is wrong:" << std::endl
;
347 std::cerr
<< msg
<< std::endl
<< std::endl
;
349 } else if (section
.Exists("Autoremove") == true)
354 size_t const id
= section
.FindULL(type
.c_str(), VersionCount
);
355 if (id
== VersionCount
) {
356 _error
->Warning("Unable to parse %s request with id value '%s'!", type
.c_str(), section
.FindS(type
.c_str()).c_str());
358 } else if (id
> Cache
.Head().VersionCount
) {
359 _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());
363 pkgCache::VerIterator
Ver(Cache
.GetCache(), Cache
.GetCache().VerP
+ VerIdx
[id
]);
364 Cache
.SetCandidateVersion(Ver
);
365 if (type
== "Install")
367 pkgCache::PkgIterator
const P
= Ver
.ParentPkg();
368 if (Cache
[P
].Mode
!= pkgDepCache::ModeInstall
)
369 Cache
.MarkInstall(P
, false, 0, false);
371 else if (type
== "Remove")
372 Cache
.MarkDelete(Ver
.ParentPkg(), false);
373 else if (type
== "Autoremove") {
374 Cache
[Ver
.ParentPkg()].Marked
= false;
375 Cache
[Ver
.ParentPkg()].Garbage
= true;
381 // ReadLine - first line from the given file descriptor /*{{{*/
382 // ---------------------------------------------------------------------
383 /* Little helper method to read a complete line into a string. Similar to
384 fgets but we need to use the low-level read() here as otherwise the
385 listparser will be confused later on as mixing of fgets and read isn't
386 a supported action according to the manpages and results are undefined */
387 static bool ReadLine(int const input
, std::string
&line
) {
392 while ((data
= read(input
, &one
, sizeof(one
))) != -1) {
399 if (line
.empty() == true && isblank(one
) != 0)
406 // StringToBool - convert yes/no to bool /*{{{*/
407 // ---------------------------------------------------------------------
408 /* we are not as lazy as we are in the global StringToBool as we really
409 only accept yes/no here - but we will ignore leading spaces */
410 static bool StringToBool(char const *answer
, bool const defValue
) {
411 for (; isspace(*answer
) != 0; ++answer
);
412 if (strncasecmp(answer
, "yes", 3) == 0)
414 else if (strncasecmp(answer
, "no", 2) == 0)
417 _error
->Warning("Value '%s' is not a boolean 'yes' or 'no'!", answer
);
421 // EDSP::ReadRequest - first stanza from the given file descriptor /*{{{*/
422 bool EDSP::ReadRequest(int const input
, std::list
<std::string
> &install
,
423 std::list
<std::string
> &remove
, bool &upgrade
,
424 bool &distUpgrade
, bool &autoRemove
)
432 while (ReadLine(input
, line
) == true)
434 // Skip empty lines before request
435 if (line
.empty() == true)
437 // The first Tag must be a request, so search for it
438 if (line
.compare(0, 8, "Request:") != 0)
441 while (ReadLine(input
, line
) == true)
443 // empty lines are the end of the request
444 if (line
.empty() == true)
447 std::list
<std::string
> *request
= NULL
;
448 if (line
.compare(0, 8, "Install:") == 0)
453 else if (line
.compare(0, 7, "Remove:") == 0)
458 else if (line
.compare(0, 8, "Upgrade:") == 0)
459 upgrade
= StringToBool(line
.c_str() + 9, false);
460 else if (line
.compare(0, 13, "Dist-Upgrade:") == 0)
461 distUpgrade
= StringToBool(line
.c_str() + 14, false);
462 else if (line
.compare(0, 11, "Autoremove:") == 0)
463 autoRemove
= StringToBool(line
.c_str() + 12, false);
464 else if (line
.compare(0, 13, "Architecture:") == 0)
465 _config
->Set("APT::Architecture", line
.c_str() + 14);
466 else if (line
.compare(0, 14, "Architectures:") == 0)
468 std::string
const archs
= line
.c_str() + 15;
469 _config
->Set("APT::Architectures", SubstVar(archs
, " ", ","));
472 _error
->Warning("Unknown line in EDSP Request stanza: %s", line
.c_str());
476 size_t end
= line
.length();
478 size_t begin
= line
.rfind(' ');
479 if (begin
== std::string::npos
)
481 request
->push_back(line
.substr(0, end
));
484 else if (begin
< end
)
485 request
->push_back(line
.substr(begin
+ 1, end
));
487 end
= line
.find_last_not_of(' ');
488 } while (end
!= std::string::npos
);
494 // EDSP::ApplyRequest - first stanza from the given file descriptor /*{{{*/
495 bool EDSP::ApplyRequest(std::list
<std::string
> const &install
,
496 std::list
<std::string
> const &remove
,
499 for (std::list
<std::string
>::const_iterator i
= install
.begin();
500 i
!= install
.end(); ++i
) {
501 pkgCache::PkgIterator P
= Cache
.FindPkg(*i
);
503 _error
->Warning("Package %s is not known, so can't be installed", i
->c_str());
505 Cache
.MarkInstall(P
, false);
508 for (std::list
<std::string
>::const_iterator i
= remove
.begin();
509 i
!= remove
.end(); ++i
) {
510 pkgCache::PkgIterator P
= Cache
.FindPkg(*i
);
512 _error
->Warning("Package %s is not known, so can't be installed", i
->c_str());
519 // EDSP::WriteSolution - to the given file descriptor /*{{{*/
520 bool EDSP::WriteSolution(pkgDepCache
&Cache
, FILE* output
)
522 bool const Debug
= _config
->FindB("Debug::EDSP::WriteSolution", false);
523 for (pkgCache::PkgIterator Pkg
= Cache
.PkgBegin(); Pkg
.end() == false; ++Pkg
)
525 if (Cache
[Pkg
].Delete() == true)
527 fprintf(output
, "Remove: %d\n", Pkg
.CurrentVer()->ID
);
529 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), Pkg
.CurrentVer().VerStr());
531 else if (Cache
[Pkg
].NewInstall() == true || Cache
[Pkg
].Upgrade() == true)
533 pkgCache::VerIterator
const CandVer
= Cache
.GetCandidateVersion(Pkg
);
534 fprintf(output
, "Install: %d\n", CandVer
->ID
);
536 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), CandVer
.VerStr());
538 else if (Cache
[Pkg
].Garbage
== true)
540 fprintf(output
, "Autoremove: %d\n", Pkg
.CurrentVer()->ID
);
542 fprintf(output
, "Package: %s\nVersion: %s\n", Pkg
.FullName().c_str(), Pkg
.CurrentVer().VerStr());
546 fprintf(output
, "\n");
552 // EDSP::WriteProgess - pulse to the given file descriptor /*{{{*/
553 bool EDSP::WriteProgress(unsigned short const percent
, const char* const message
, FILE* output
) {
554 fprintf(output
, "Progress: %s\n", TimeRFC1123(time(NULL
)).c_str());
555 fprintf(output
, "Percentage: %d\n", percent
);
556 fprintf(output
, "Message: %s\n\n", message
);
561 // EDSP::WriteError - format an error message to be send to file descriptor /*{{{*/
562 bool EDSP::WriteError(char const * const uuid
, std::string
const &message
, FILE* output
) {
563 fprintf(output
, "Error: %s\n", uuid
);
564 fprintf(output
, "Message: %s\n\n", SubstVar(SubstVar(message
, "\n\n", "\n.\n"), "\n", "\n ").c_str());
568 // EDSP::ExecuteSolver - fork requested solver and setup ipc pipes {{{*/
569 pid_t
EDSP::ExecuteSolver(const char* const solver
, int * const solver_in
, int * const solver_out
, bool) {
570 std::vector
<std::string
> const solverDirs
= _config
->FindVector("Dir::Bin::Solvers");
572 for (std::vector
<std::string
>::const_iterator dir
= solverDirs
.begin();
573 dir
!= solverDirs
.end(); ++dir
) {
574 file
= flCombine(*dir
, solver
);
575 if (RealFileExists(file
.c_str()) == true)
580 if (file
.empty() == true)
582 _error
->Error("Can't call external solver '%s' as it is not in a configured directory!", solver
);
585 int external
[4] = {-1, -1, -1, -1};
586 if (pipe(external
) != 0 || pipe(external
+ 2) != 0)
588 _error
->Errno("Resolve", "Can't create needed IPC pipes for EDSP");
591 for (int i
= 0; i
< 4; ++i
)
592 SetCloseExec(external
[i
], true);
594 pid_t Solver
= ExecFork();
596 dup2(external
[0], STDIN_FILENO
);
597 dup2(external
[3], STDOUT_FILENO
);
598 const char* calling
[2] = { file
.c_str(), 0 };
599 execv(calling
[0], (char**) calling
);
600 std::cerr
<< "Failed to execute solver '" << solver
<< "'!" << std::endl
;
606 if (WaitFd(external
[1], true, 5) == false)
608 _error
->Errno("Resolve", "Timed out while Waiting on availability of solver stdin");
612 *solver_in
= external
[1];
613 *solver_out
= external
[2];
616 bool EDSP::ExecuteSolver(const char* const solver
, int *solver_in
, int *solver_out
) {
617 if (ExecuteSolver(solver
, solver_in
, solver_out
, true) == 0)
622 // EDSP::ResolveExternal - resolve problems by asking external for help {{{*/
623 bool EDSP::ResolveExternal(const char* const solver
, pkgDepCache
&Cache
,
624 bool const upgrade
, bool const distUpgrade
,
625 bool const autoRemove
, OpProgress
*Progress
) {
626 int solver_in
, solver_out
;
627 pid_t
const solver_pid
= EDSP::ExecuteSolver(solver
, &solver_in
, &solver_out
, true);
631 FILE* output
= fdopen(solver_in
, "w");
633 return _error
->Errno("Resolve", "fdopen on solver stdin failed");
635 if (Progress
!= NULL
)
636 Progress
->OverallProgress(0, 100, 5, _("Execute external solver"));
637 EDSP::WriteRequest(Cache
, output
, upgrade
, distUpgrade
, autoRemove
, Progress
);
638 if (Progress
!= NULL
)
639 Progress
->OverallProgress(5, 100, 20, _("Execute external solver"));
640 EDSP::WriteScenario(Cache
, output
, Progress
);
643 if (Progress
!= NULL
)
644 Progress
->OverallProgress(25, 100, 75, _("Execute external solver"));
645 if (EDSP::ReadResponse(solver_out
, Cache
, Progress
) == false)
648 return ExecWait(solver_pid
, solver
);