To enable attaching to externally launched QEMU, we need
to be able to reverse engineer a guest XML config based
on the argv for a PID in /proc
* src/qemu/qemu_command.c, src/qemu/qemu_command.h: Add
qemuParseCommandLinePid which extracts QEMU config from
argv in /proc, given a PID number
---
src/qemu/qemu_command.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++
src/qemu/qemu_command.h | 5 ++
2 files changed, 111 insertions(+), 0 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index e711f0e..dbc9e0c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6604,3 +6604,109 @@ cleanup:
return def;
}
+
+
+static int qemuParseProcFileStrings(unsigned long long pid,
+ const char *name,
+ const char ***list)
+{
+ char *path = NULL;
+ int ret = -1;
+ char *data = NULL;
+ ssize_t len;
+ char *tmp;
+ size_t nstr = 0;
+ const char **str = NULL;
+ int i;
+
+ if (virAsprintf(&path, "/proc/%llu/%s", pid, name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if ((len = virFileReadAll(path, 1024*128, &data)) < 0)
+ goto cleanup;
+
+ tmp = data;
+ while (tmp < (data + len)) {
+ if (VIR_EXPAND_N(str, nstr, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (!(str[nstr-1] = strdup(tmp))) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ /* Skip arg */
+ tmp += strlen(tmp);
+ /* Skip \0 separator */
+ tmp++;
+ }
+
+ if (VIR_EXPAND_N(str, nstr, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ str[nstr-1] = NULL;
+
+ ret = nstr-1;
+ *list = str;
+
+cleanup:
+ if (ret < 0) {
+ for (i = 0 ; str && str[i] ; i++)
+ VIR_FREE(str[i]);
+ VIR_FREE(str);
+ }
+ VIR_FREE(data);
+ VIR_FREE(path);
+ return ret;
+}
+
+virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps,
+ unsigned long long pid,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON)
+{
+ virDomainDefPtr def = NULL;
+ const char **progargv = NULL;
+ const char **progenv = NULL;
+ char *exepath = NULL;
+ char *emulator;
+ int i;
+
+ if (qemuParseProcFileStrings(pid, "cmdline", &progargv) < 0 ||
+ qemuParseProcFileStrings(pid, "environ", &progenv) < 0)
+ goto cleanup;
+
+ if (!(def = qemuParseCommandLine(caps, progenv, progargv,
+ pidfile, monConfig, monJSON)))
+ goto cleanup;
+
+ if (virAsprintf(&exepath, "/proc/%llu/exe", pid) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virFileResolveLink(exepath, &emulator) < 0) {
+ virReportSystemError(errno,
+ _("Unable to resolve %s for pid %llu"),
+ exepath, pid);
+ goto cleanup;
+ }
+ VIR_FREE(def->emulator);
+ def->emulator = emulator;
+
+cleanup:
+ VIR_FREE(exepath);
+ for (i = 0 ; progargv && progargv[i] ; i++)
+ VIR_FREE(progargv[i]);
+ VIR_FREE(progargv);
+ for (i = 0 ; progenv && progenv[i] ; i++)
+ VIR_FREE(progenv[i]);
+ VIR_FREE(progenv);
+ return def;
+}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index 89502b7..928b53e 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -151,6 +151,11 @@ virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps,
char **pidfile,
virDomainChrSourceDefPtr *monConfig,
bool *monJSON);
+virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps,
+ unsigned long long pid,
+ char **pidfile,
+ virDomainChrSourceDefPtr *monConfig,
+ bool *monJSON);
int qemuDomainAssignPCIAddresses(virDomainDefPtr def);
qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def);
--
1.7.4.4