]>
git.saurik.com Git - apt.git/blob - cmdline/apt-dump-solver.cc
1 // -*- mode: cpp; mode: fold -*-
3 /* #####################################################################
5 dummy solver to get quickly a scenario file out of APT
7 ##################################################################### */
9 // Include Files /*{{{*/
12 #include <apt-pkg/cmndline.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/edsp.h>
15 #include <apt-pkg/fileutl.h>
16 #include <apt-pkg/strutl.h>
18 #include <apt-private/private-cmndline.h>
25 #include <sys/types.h>
34 static bool ShowHelp(CommandLine
&) /*{{{*/
37 _("Usage: apt-dump-solver\n"
39 "apt-dump-solver is an interface to store an EDSP scenario in\n"
40 "a file and optionally forwards it to another solver.\n");
44 static std::vector
<aptDispatchWithHelp
> GetCommands() /*{{{*/
49 static int WriteError(char const * const uid
, std::ostringstream
&out
, FileFd
&stdoutfd
, pid_t
const &Solver
)/*{{{*/
51 _error
->DumpErrors(out
);
52 // ensure the solver isn't printing into "our" error message, too
54 ExecWait(Solver
, "dump", true);
55 EDSP::WriteError(uid
, out
.str(), stdoutfd
);
59 int main(int argc
,const char *argv
[]) /*{{{*/
62 ParseCommandLine(CmdL
, APT_CMD::APT_DUMP_SOLVER
, &_config
, nullptr, argc
, argv
, &ShowHelp
, &GetCommands
);
63 _config
->Clear("Dir::Log");
65 bool const is_forwarding_dumper
= (CmdL
.FileSize() != 0);
68 if (stdoutfd
.OpenDescriptor(STDOUT_FILENO
, FileFd::WriteOnly
| FileFd::BufferedWrite
, true) == false)
72 char const * const filename
= is_forwarding_dumper
? CmdL
.FileList
[0] : getenv("APT_EDSP_DUMP_FILENAME");
73 if (filename
== nullptr || strlen(filename
) == 0)
75 if (is_forwarding_dumper
== false)
77 EDSP::WriteError("ERR_NO_FILENAME", "You have to set the environment variable APT_EDSP_DUMP_FILENAME\n"
78 "to a valid filename to store the dump of EDSP solver input in.\n"
79 "For example with: export APT_EDSP_DUMP_FILENAME=/tmp/dump.edsp", stdoutfd
);
85 // ignore errors here as logging isn't really critical
86 _error
->PushToStack();
87 if (dump
.Open(filename
, FileFd::WriteOnly
| FileFd::Exclusive
| FileFd::Create
, FileFd::Extension
, 0644) == false &&
88 is_forwarding_dumper
== false)
90 _error
->MergeWithStack();
91 std::ostringstream out
;
92 out
<< "Writing EDSP solver input to file '" << filename
<< "' failed as it couldn't be created!\n";
93 return WriteError("ERR_CREATE_FILE", out
, stdoutfd
, 0);
95 _error
->RevertToStack();
100 if (is_forwarding_dumper
)
102 int external
[] = {-1, -1};
103 if (pipe(external
) != 0)
105 for (int i
= 0; i
< 2; ++i
)
106 SetCloseExec(external
[i
], true);
110 _config
->Set("APT::Sandbox::User", _config
->Find("APT::Solver::RunAsUser", _config
->Find("APT::Sandbox::User")));
112 dup2(external
[0], STDIN_FILENO
);
113 execv(CmdL
.FileList
[1], const_cast<char**>(CmdL
.FileList
+ 1));
114 std::cerr
<< "Failed to execute '" << CmdL
.FileList
[1] << "'!" << std::endl
;
119 if (WaitFd(external
[1], true, 5) == false)
122 if (forward
.OpenDescriptor(external
[1], FileFd::WriteOnly
| FileFd::BufferedWrite
, true) == false)
129 if (input
.OpenDescriptor(STDIN_FILENO
, FileFd::ReadOnly
) == false)
131 std::ostringstream out
;
132 out
<< "Writing EDSP solver input to file '" << filename
<< "' failed as stdin couldn't be opened!\n";
133 return WriteError("ERR_READ_ERROR", out
, stdoutfd
, Solver
);
136 constexpr size_t BufSize
= 64 * 1024;
137 std::unique_ptr
<char[]> Buf(new char[BufSize
]);
138 unsigned long long ToRead
= 0;
140 if (input
.Read(Buf
.get(),BufSize
, &ToRead
) == false)
142 std::ostringstream out
;
143 out
<< "Writing EDSP solver input to file '" << filename
<< "' failed as reading from stdin failed!\n";
144 return WriteError("ERR_READ_ERROR", out
, stdoutfd
, Solver
);
148 if (forward
.IsOpen() && forward
.Failed() == false && forward
.Write(Buf
.get(),ToRead
) == false)
150 if (dump
.IsOpen() && dump
.Failed() == false && dump
.Write(Buf
.get(),ToRead
) == false)
157 if (_error
->PendingError())
159 std::ostringstream out
;
160 out
<< "Writing EDSP solver input to file '" << filename
<< "' failed due to write errors!\n";
161 return WriteError("ERR_WRITE_ERROR", out
, stdoutfd
, Solver
);
164 if (is_forwarding_dumper
)
166 // Wait and collect the error code
168 while (waitpid(Solver
, &Status
, 0) != Solver
)
173 std::ostringstream out
;
174 ioprintf(out
, _("Waited for %s but it wasn't there"), CmdL
.FileList
[1]);
175 return WriteError("ERR_FORWARD", out
, stdoutfd
, 0);
177 if (WIFEXITED(Status
))
178 return WEXITSTATUS(Status
);
183 EDSP::WriteError("ERR_JUST_DUMPING", "I am too dumb, i can just dump!\nPlease use one of my friends instead!", stdoutfd
);