summaryrefslogtreecommitdiff
path: root/apt-private/private-json-hooks.cc
diff options
context:
space:
mode:
authorJulian Andres Klode <julian.klode@canonical.com>2021-04-23 11:37:28 +0200
committerJulian Andres Klode <julian.klode@canonical.com>2021-04-23 12:26:46 +0200
commit80dd1447595c536d31912c486ac5e96f983ccc7a (patch)
tree1253ecca8e3d9c609ce0a09417f2a1b900358f2a /apt-private/private-json-hooks.cc
parentdc11a4422d99cb49817c827b9f827617b5880600 (diff)
json: Hook protocol 0.2 (added upgrade,downgrade,reinstall modes)
Hook protocol 0.2 makes the new fields we added mandatory, and replaces `install` mode with `upgrade`, `downgrade`, `reinstall` where appropriate. Hook negotiation is hacky, but it's the best we can do for now. Users are advised to upgrade to 0.2
Diffstat (limited to 'apt-private/private-json-hooks.cc')
-rw-r--r--apt-private/private-json-hooks.cc49
1 files changed, 40 insertions, 9 deletions
diff --git a/apt-private/private-json-hooks.cc b/apt-private/private-json-hooks.cc
index a40597e0a..957140525 100644
--- a/apt-private/private-json-hooks.cc
+++ b/apt-private/private-json-hooks.cc
@@ -17,6 +17,7 @@
#include <ostream>
#include <sstream>
#include <stack>
+#include <unordered_map>
#include <signal.h>
#include <sys/socket.h>
@@ -265,7 +266,7 @@ static void DpkgChrootDirectory()
/**
* @brief Send a notification to the hook's stream
*/
-static void NotifyHook(std::ostream &os, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages)
+static void NotifyHook(std::ostream &os, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages, int hookVersion)
{
SortedPackageUniverse Universe(Cache);
JsonWriter jsonWriter{os};
@@ -311,7 +312,14 @@ static void NotifyHook(std::ostream &os, std::string const &method, const char *
switch (Cache[Pkg].Mode)
{
case pkgDepCache::ModeInstall:
- jsonWriter.name("mode").value("install");
+ if (Pkg->CurrentVer != 0 && Cache[Pkg].Upgrade() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("upgrade");
+ else if (Pkg->CurrentVer != 0 && Cache[Pkg].Downgrade() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("downgrade");
+ else if (Pkg->CurrentVer != 0 && Cache[Pkg].ReInstall() && hookVersion >= 0x020)
+ jsonWriter.name("mode").value("reinstall");
+ else
+ jsonWriter.name("mode").value("install");
break;
case pkgDepCache::ModeDelete:
jsonWriter.name("mode").value(Cache[Pkg].Purge() ? "purge" : "deinstall");
@@ -344,7 +352,7 @@ static void NotifyHook(std::ostream &os, std::string const &method, const char *
static std::string BuildHelloMessage()
{
std::stringstream Hello;
- JsonWriter(Hello).beginObject().name("jsonrpc").value("2.0").name("method").value("org.debian.apt.hooks.hello").name("id").value(0).name("params").beginObject().name("versions").beginArray().value("0.1").endArray().endObject().endObject();
+ JsonWriter(Hello).beginObject().name("jsonrpc").value("2.0").name("method").value("org.debian.apt.hooks.hello").name("id").value(0).name("params").beginObject().name("versions").beginArray().value("0.1").value("0.2").endArray().endObject().endObject();
return Hello.str();
}
@@ -361,11 +369,10 @@ static std::string BuildByeMessage()
/// @brief Run the Json hook processes in the given option.
bool RunJsonHook(std::string const &option, std::string const &method, const char **FileList, CacheFile &Cache, std::set<std::string> const &UnknownPackages)
{
- std::stringstream ss;
- NotifyHook(ss, method, FileList, Cache, UnknownPackages);
- std::string TheData = ss.str();
+ std::unordered_map<int, std::string> notifications;
std::string HelloData = BuildHelloMessage();
std::string ByeData = BuildByeMessage();
+ int hookVersion;
bool result = true;
@@ -465,6 +472,20 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
goto out;
}
+ if (strstr(line, "\"0.1\""))
+ {
+ hookVersion = 0x010;
+ }
+ else if (strstr(line, "\"0.2\""))
+ {
+ hookVersion = 0x020;
+ }
+ else
+ {
+ _error->Error("Unknown hook version in handshake from hook %s: %s", Opts->Value.c_str(), line);
+ goto out;
+ }
+
size = getline(&line, &linesize, F);
if (size < 0)
{
@@ -476,9 +497,18 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
_error->Error("Expected empty line after handshake from %s, received %s", Opts->Value.c_str(), line);
goto out;
}
-
- fwrite(TheData.data(), TheData.size(), 1, F);
- fwrite("\n\n", 2, 1, F);
+ {
+ std::string &data = notifications[hookVersion];
+ if (data.empty())
+ {
+ std::stringstream ss;
+ NotifyHook(ss, method, FileList, Cache, UnknownPackages, hookVersion);
+ ;
+ data = ss.str();
+ }
+ fwrite(data.data(), data.size(), 1, F);
+ fwrite("\n\n", 2, 1, F);
+ }
fwrite(ByeData.data(), ByeData.size(), 1, F);
fwrite("\n\n", 2, 1, F);
@@ -490,6 +520,7 @@ bool RunJsonHook(std::string const &option, std::string const &method, const cha
result = _error->Error("Failure running hook %s", Opts->Value.c_str());
break;
}
+
}
signal(SIGINT, old_sigint);
signal(SIGPIPE, old_sigpipe);