From f06ca4fdd2f234557c4b7f8c50ade33d555392b3 Mon Sep 17 00:00:00 2001
From: Michael Crosby <michael@crosbymichael.com>
Date: Mon, 19 May 2014 20:46:59 +0000
Subject: [PATCH] Make sure dev/fuse is created in container

Fixes #5849

If the host system does not have fuse enabled in the kernel config we
will ignore the is not exist errors when trying to copy the device node
from the host system into the container.
Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@crosbymichael.com> (github: crosbymichael)
---
 libcontainer/mount/init.go        |  5 ++++-
 libcontainer/mount/nodes/nodes.go | 24 +++++++++++++++++++-----
 2 files changed, 23 insertions(+), 6 deletions(-)

diff --git a/libcontainer/mount/init.go b/libcontainer/mount/init.go
index 6f3080c..c414813 100644
--- a/libcontainer/mount/init.go
+++ b/libcontainer/mount/init.go
@@ -48,9 +48,12 @@ func InitializeMountNamespace(rootfs, console string, container *libcontainer.Co
 	if err := setupBindmounts(rootfs, container.Mounts); err != nil {
 		return fmt.Errorf("bind mounts %s", err)
 	}
-	if err := nodes.CopyN(rootfs, nodes.DefaultNodes); err != nil {
+	if err := nodes.CopyN(rootfs, nodes.DefaultNodes, true); err != nil {
 		return fmt.Errorf("copy dev nodes %s", err)
 	}
+	if err := nodes.CopyN(rootfs, nodes.AdditionalNodes, false); err != nil {
+		return fmt.Errorf("copy additional dev nodes %s", err)
+	}
 	if err := SetupPtmx(rootfs, console, container.Context["mount_label"]); err != nil {
 		return err
 	}
diff --git a/libcontainer/mount/nodes/nodes.go b/libcontainer/mount/nodes/nodes.go
index 5022f85..1384682 100644
--- a/libcontainer/mount/nodes/nodes.go
+++ b/libcontainer/mount/nodes/nodes.go
@@ -4,10 +4,11 @@ package nodes
 
 import (
 	"fmt"
-	"github.com/dotcloud/docker/pkg/system"
 	"os"
 	"path/filepath"
 	"syscall"
+
+	"github.com/dotcloud/docker/pkg/system"
 )
 
 // Default list of device nodes to copy
@@ -20,30 +21,43 @@ var DefaultNodes = []string{
 	"tty",
 }
 
+// AdditionalNodes includes nodes that are not required
+var AdditionalNodes = []string{
+	"fuse",
+}
+
 // CopyN copies the device node from the host into the rootfs
-func CopyN(rootfs string, nodesToCopy []string) error {
+func CopyN(rootfs string, nodesToCopy []string, shouldExist bool) error {
 	oldMask := system.Umask(0000)
 	defer system.Umask(oldMask)
 
 	for _, node := range nodesToCopy {
-		if err := Copy(rootfs, node); err != nil {
+		if err := Copy(rootfs, node, shouldExist); err != nil {
 			return err
 		}
 	}
 	return nil
 }
 
-func Copy(rootfs, node string) error {
+// Copy copies the device node into the rootfs.  If the node
+// on the host system does not exist and the boolean flag is passed
+// an error will be returned
+func Copy(rootfs, node string, shouldExist bool) error {
 	stat, err := os.Stat(filepath.Join("/dev", node))
 	if err != nil {
+		if os.IsNotExist(err) && !shouldExist {
+			return nil
+		}
 		return err
 	}
+
 	var (
 		dest = filepath.Join(rootfs, "dev", node)
 		st   = stat.Sys().(*syscall.Stat_t)
 	)
+
 	if err := system.Mknod(dest, st.Mode, int(st.Rdev)); err != nil && !os.IsExist(err) {
-		return fmt.Errorf("copy %s %s", node, err)
+		return fmt.Errorf("mknod %s %s", node, err)
 	}
 	return nil
 }