From: "Daniel P. Berrange" <berrange(a)redhat.com>
Add some APIs for acquiring namespace file descriptors and
switching namespaces
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
src/libvirt_private.syms | 2 +
src/util/virprocess.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++
src/util/virprocess.h | 7 +++
3 files changed, 127 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 497d5d3..a422839 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1790,9 +1790,11 @@ virPidFileWritePath;
# virprocess.h
virProcessAbort;
virProcessGetAffinity;
+virProcessGetNamespaces;
virProcessKill;
virProcessKillPainfully;
virProcessSetAffinity;
+virProcessSetNamespaces;
virProcessTranslateStatus;
virProcessWait;
diff --git a/src/util/virprocess.c b/src/util/virprocess.c
index 0858553..b6da47a 100644
--- a/src/util/virprocess.c
+++ b/src/util/virprocess.c
@@ -22,6 +22,8 @@
#include <config.h>
+#include <dirent.h>
+#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <sys/wait.h>
@@ -30,6 +32,7 @@
#include "virprocess.h"
#include "virerror.h"
#include "viralloc.h"
+#include "virfile.h"
#include "virlog.h"
#include "virutil.h"
@@ -489,3 +492,118 @@ int virProcessGetAffinity(pid_t pid ATTRIBUTE_UNUSED,
return -1;
}
#endif /* HAVE_SCHED_GETAFFINITY */
+
+
+#if HAVE_SETNS
+int virProcessGetNamespaces(pid_t pid,
+ size_t *nfdlist,
+ int **fdlist)
+{
+ int ret = -1;
+ DIR *dh = NULL;
+ struct dirent *de;
+ char *nsdir = NULL;
+ char *nsfile = NULL;
+ size_t i;
+
+ *nfdlist = 0;
+ *fdlist = NULL;
+
+ if (virAsprintf(&nsdir, "/proc/%llu/ns",
+ (unsigned long long)pid) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (!(dh = opendir(nsdir))) {
+ virReportSystemError(errno,
+ _("Cannot read directory %s"),
+ nsdir);
+ goto cleanup;
+ }
+
+ while ((de = readdir(dh))) {
+ int fd;
+ if (de->d_name[0] == '.')
+ continue;
+
+ if (VIR_EXPAND_N(*fdlist, *nfdlist, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virAsprintf(&nsfile, "%s/%s", nsdir, de->d_name) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if ((fd = open(nsfile, O_RDWR)) < 0) {
+ virReportSystemError(errno,
+ _("Unable to open %s"),
+ nsfile);
+ goto cleanup;
+ }
+
+ (*fdlist)[(*nfdlist)-1] = fd;
+
+ VIR_FREE(nsfile);
+ }
+
+ ret = 0;
+
+cleanup:
+ if (dh)
+ closedir(dh);
+ VIR_FREE(nsdir);
+ VIR_FREE(nsfile);
+ if (ret < 0) {
+ for (i = 0 ; i < *nfdlist ; i++) {
+ VIR_FORCE_CLOSE((*fdlist)[i]);
+ }
+ VIR_FREE(*fdlist);
+ }
+ return ret;
+}
+
+
+int virProcessSetNamespaces(size_t nfdlist,
+ int *fdlist)
+{
+ size_t i;
+
+ if (nfdlist == 0) {
+ virReportInvalidArg(nfdlist, "%s",
+ _("Expected at least one file descriptor"));
+ return -1;
+ }
+ for (i = 0 ; i < nfdlist ; i++) {
+ if (setns(fdlist[i], 0) < 0) {
+ virReportSystemError(errno, "%s",
+ _("Unable to join domain namespace"));
+ return -1;
+ }
+ }
+ return 0;
+}
+#else /* ! HAVE_SETNS */
+int virProcessGetNamespaces(pid_t pid,
+ size_t *nfdlist ATTRIBUTE_UNUSED,
+ int **fdlist ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS,
+ _("Cannot get namespaces for %llu"),
+ (unsigned long long)pid);
+ return -1;
+}
+
+
+int virProcessSetNamespaces(pid_t pid,
+ size_t *nfdlist ATTRIBUTE_UNUSED,
+ int **fdlist ATTRIBUTE_UNUSED)
+{
+ virReportSystemError(ENOSYS,
+ _("Cannot set namespaces for %llu"),
+ (unsigned long long)pid);
+ return -1;
+}
+#endif /* ! HAVE_SETNS */
diff --git a/src/util/virprocess.h b/src/util/virprocess.h
index 8724f64..53475d3 100644
--- a/src/util/virprocess.h
+++ b/src/util/virprocess.h
@@ -47,4 +47,11 @@ int virProcessGetAffinity(pid_t pid,
virBitmapPtr *map,
int maxcpu);
+int virProcessGetNamespaces(pid_t pid,
+ size_t *nfdlist,
+ int **fdlist);
+
+int virProcessSetNamespaces(size_t nfdlist,
+ int *fdlist);
+
#endif /* __VIR_PROCESS_H__ */
--
1.7.11.7