]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
lxc: use hand-rolled code in place of unlockpt and grantpt
authorSerge E. Hallyn <serge.hallyn@canonical.com>
Wed, 19 Oct 2011 01:39:57 +0000 (20:39 -0500)
committerEric Blake <eblake@redhat.com>
Wed, 19 Oct 2011 20:47:16 +0000 (14:47 -0600)
The glibc ones (intentionally) cannot handle ptys opened in a
devpts not mounted at /dev/pts.

Drop the (un-exported, unused) virFileOpenTtyAt.

Signed-off-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric Blake <eblake@redhat.com>
src/lxc/lxc_controller.c
src/util/util.c

index 89ce7f54a443a012db2f3443b7443b38dcaa7baa..c4e78325257ef9ae24361827963e17520f880298 100644 (file)
@@ -41,6 +41,8 @@
 #include <locale.h>
 #include <linux/loop.h>
 #include <dirent.h>
+#include <grp.h>
+#include <sys/stat.h>
 
 #if HAVE_CAPNG
 # include <cap-ng.h>
@@ -780,6 +782,50 @@ static int lxcSetPersonality(virDomainDefPtr def)
 # define MS_SLAVE              (1<<19)
 #endif
 
+/* Create a private tty using the private devpts at PTMX, returning
+ * the master in *TTYMASTER and the name of the slave, _from the
+ * perspective of the guest after remounting file systems_, in
+ * *TTYNAME.  Heavily borrowed from glibc, but doesn't require that
+ * devpts == "/dev/pts" */
+static int
+lxcCreateTty(char *ptmx, int *ttymaster, char **ttyName)
+{
+    int ret = -1;
+    int ptyno;
+    int unlock = 0;
+
+    if ((*ttymaster = open(ptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
+        goto cleanup;
+
+    if (ioctl(*ttymaster, TIOCSPTLCK, &unlock) < 0)
+        goto cleanup;
+
+    if (ioctl(*ttymaster, TIOCGPTN, &ptyno) < 0)
+        goto cleanup;
+
+    /* If mount() succeeded at honoring newinstance, then the kernel
+     * was new enough to also honor the mode=0620,gid=5 options, which
+     * guarantee that the new pty already has correct permissions; so
+     * while glibc has to fstat(), fchmod(), and fchown() for older
+     * kernels, we can skip those steps.  ptyno shouldn't currently be
+     * anything other than 0, but let's play it safe.  */
+    if (virAsprintf(ttyName, "/dev/pts/%d", ptyno) < 0) {
+        virReportOOMError();
+        errno = ENOMEM;
+        goto cleanup;
+    }
+
+    ret = 0;
+
+cleanup:
+    if (ret != 0) {
+        VIR_FORCE_CLOSE(*ttymaster);
+        VIR_FREE(*ttyName);
+    }
+
+    return ret;
+}
+
 static int
 lxcControllerRun(virDomainDefPtr def,
                  unsigned int nveths,
@@ -877,6 +923,8 @@ lxcControllerRun(virDomainDefPtr def,
             goto cleanup;
         }
 
+        /* XXX should we support gid=X for X!=5 for distros which use
+         * a different gid for tty?  */
         VIR_DEBUG("Mounting 'devpts' on %s", devpts);
         if (mount("devpts", devpts, "devpts", 0,
                   "newinstance,ptmxmode=0666,mode=0620,gid=5") < 0) {
@@ -894,10 +942,7 @@ lxcControllerRun(virDomainDefPtr def,
 
     if (devptmx) {
         VIR_DEBUG("Opening tty on private %s", devptmx);
-        if (virFileOpenTtyAt(devptmx,
-                             &containerPty,
-                             &containerPtyPath,
-                             0) < 0) {
+        if (lxcCreateTty(devptmx, &containerPty, &containerPtyPath) < 0) {
             virReportSystemError(errno, "%s",
                                  _("Failed to allocate tty"));
             goto cleanup;
index dac616bdb9d4a32a6878669e6a24ef9bf53ef277..01146f5a020f6b25cdf4c6eed33da5bc3c150b21 100644 (file)
@@ -1103,22 +1103,17 @@ virFileBuildPath(const char *dir, const char *name, const char *ext)
 int virFileOpenTty(int *ttymaster,
                    char **ttyName,
                    int rawmode)
-{
-    return virFileOpenTtyAt("/dev/ptmx",
-                            ttymaster,
-                            ttyName,
-                            rawmode);
-}
-
-#ifdef __linux__
-int virFileOpenTtyAt(const char *ptmx,
-                     int *ttymaster,
-                     char **ttyName,
-                     int rawmode)
 {
     int rc = -1;
 
-    if ((*ttymaster = open(ptmx, O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
+#ifdef WIN32
+    /* mingw completely lacks pseudo-terminals, and the gnulib
+     * replacements are not (yet) license compatible.  */
+    errno = ENOSYS;
+
+#else /* !WIN32 */
+
+    if ((*ttymaster = posix_openpt(O_RDWR|O_NOCTTY|O_NONBLOCK)) < 0)
         goto cleanup;
 
     if (unlockpt(*ttymaster) < 0)
@@ -1156,19 +1151,9 @@ cleanup:
     if (rc != 0)
         VIR_FORCE_CLOSE(*ttymaster);
 
+#endif /* !WIN32 */
     return rc;
-
 }
-#else
-int virFileOpenTtyAt(const char *ptmx ATTRIBUTE_UNUSED,
-                     int *ttymaster ATTRIBUTE_UNUSED,
-                     char **ttyName ATTRIBUTE_UNUSED,
-                     int rawmode ATTRIBUTE_UNUSED)
-{
-    return -1;
-}
-#endif
-
 
 /*
  * Creates an absolute path for a potentially relative path.