graph/graph_unix.go
52f4d09f
 // +build !windows
 
 package graph
 
 import (
 	"encoding/json"
 	"fmt"
 	"os"
 	"path/filepath"
 	"strings"
 	"syscall"
 
5a00326d
 	"github.com/Sirupsen/logrus"
9001ea26
 	"github.com/docker/docker/image"
52f4d09f
 	"github.com/docker/docker/pkg/archive"
 	"github.com/docker/docker/pkg/system"
 )
 
 // setupInitLayer populates a directory with mountpoints suitable
 // for bind-mounting dockerinit into the container. The mountpoint is simply an
 // empty file at /.dockerinit
 //
 // This extra layer is used by all containers as the top-most ro layer. It protects
 // the container from unwanted side-effects on the rw layer.
 func SetupInitLayer(initLayer string) error {
 	for pth, typ := range map[string]string{
 		"/dev/pts":         "dir",
 		"/dev/shm":         "dir",
 		"/proc":            "dir",
 		"/sys":             "dir",
 		"/.dockerinit":     "file",
 		"/.dockerenv":      "file",
 		"/etc/resolv.conf": "file",
 		"/etc/hosts":       "file",
 		"/etc/hostname":    "file",
 		"/dev/console":     "file",
 		"/etc/mtab":        "/proc/mounts",
 	} {
 		parts := strings.Split(pth, "/")
 		prev := "/"
 		for _, p := range parts[1:] {
 			prev = filepath.Join(prev, p)
 			syscall.Unlink(filepath.Join(initLayer, prev))
 		}
 
 		if _, err := os.Stat(filepath.Join(initLayer, pth)); err != nil {
 			if os.IsNotExist(err) {
 				if err := system.MkdirAll(filepath.Join(initLayer, filepath.Dir(pth)), 0755); err != nil {
 					return err
 				}
 				switch typ {
 				case "dir":
 					if err := system.MkdirAll(filepath.Join(initLayer, pth), 0755); err != nil {
 						return err
 					}
 				case "file":
 					f, err := os.OpenFile(filepath.Join(initLayer, pth), os.O_CREATE, 0755)
 					if err != nil {
 						return err
 					}
 					f.Close()
 				default:
 					if err := os.Symlink(typ, filepath.Join(initLayer, pth)); err != nil {
 						return err
 					}
 				}
 			} else {
 				return err
 			}
 		}
 	}
 
 	// Layer is ready to use, if it wasn't before.
 	return nil
 }
 
9001ea26
 func createRootFilesystemInDriver(graph *Graph, img *image.Image, layerData archive.ArchiveReader) error {
52f4d09f
 	if err := graph.driver.Create(img.ID, img.Parent); err != nil {
 		return fmt.Errorf("Driver %s failed to create image rootfs %s: %s", graph.driver, img.ID, err)
 	}
 	return nil
 }
 
 func (graph *Graph) restoreBaseImages() ([]string, error) {
 	return nil, nil
 }
 
 // storeImage stores file system layer data for the given image to the
 // graph's storage driver. Image metadata is stored in a file
 // at the specified root directory.
9001ea26
 func (graph *Graph) storeImage(img *image.Image, layerData archive.ArchiveReader, root string) (err error) {
52f4d09f
 	// Store the layer. If layerData is not nil, unpack it into the new layer
 	if layerData != nil {
22347fdb
 		if err := graph.disassembleAndApplyTarLayer(img, layerData, root); err != nil {
52f4d09f
 			return err
 		}
 	}
 
 	if err := graph.saveSize(root, int(img.Size)); err != nil {
 		return err
 	}
 
 	f, err := os.OpenFile(jsonPath(root), os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.FileMode(0600))
 	if err != nil {
 		return err
 	}
 
 	defer f.Close()
 
 	return json.NewEncoder(f).Encode(img)
 }
 
 // TarLayer returns a tar archive of the image's filesystem layer.
9001ea26
 func (graph *Graph) TarLayer(img *image.Image) (arch archive.Archive, err error) {
22347fdb
 	rdr, err := graph.assembleTarLayer(img)
5a00326d
 	if err != nil {
 		logrus.Debugf("[graph] TarLayer with traditional differ: %s", img.ID)
 		return graph.driver.Diff(img.ID, img.Parent)
 	}
22347fdb
 	return rdr, nil
52f4d09f
 }