func (fs *MemFS) sync() {
	start := time.Now()
	block := make(chan interface{}, 1)
	go func() {
		<-time.After(1 * time.Second)
		close(block)
	}()
	syscall.Sync()
	<-block
	duration := time.Since(start).Round(time.Millisecond)
	log.Infow("* Synchronized file system", "duration", duration)
}
sync flushes filesystem cache, so mtime would be guaranteed to be updated.
It also waits at least one sec, in case mtime doesn't have sub-second
resolution.
package snapshot
import (
	"archive/tar"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"
	"syscall"
	"time"
	"github.com/andres-erbsen/clock"
	"github.com/uber/makisu/lib/docker/image"
	"github.com/uber/makisu/lib/fileio"
	"github.com/uber/makisu/lib/log"
	"github.com/uber/makisu/lib/mountutils"
	"github.com/uber/makisu/lib/pathutils"
	"github.com/uber/makisu/lib/tario"
	"github.com/uber/makisu/lib/utils"
)
type memFSNode struct {
	*contentMemFile                        
	children        map[string]*memFSNode  
}
func newMemFSNode(mf *contentMemFile) *memFSNode {
	return &memFSNode{mf, make(map[string]*memFSNode)}
}
func (n *memFSNode) isOnDisk() (bool, error) {
	if _, err := os.Lstat(n.src); err == nil {
		return true, nil
	} else if os.IsNotExist(err) {
		return false, nil
	} else {
		return false, err
	}
}
type MemFS struct {
	clk  clock.Clock
	tree *memFSNode
	blacklist []string
	layers    []*memLayer
}
func NewMemFS(clk clock.Clock, root string, blacklist []string) (*MemFS, error) {
	fi, err := os.Lstat(root)
	if err != nil {
		return nil, fmt.Errorf("unable to stat root dir: %s", root)
	}
	hdr, err := newMemLayer().createHeader(root, root, "/", fi)
	if err != nil {
		return nil, fmt.Errorf("unable to create root header")
	}
	return &MemFS{
		clk:       clk,
		tree:      newMemFSNode(newContentMemFile(root, "/", hdr)),
		blacklist: blacklist,
	}, nil
}
func (fs *MemFS) Reset() {
	fs.tree.children = make(map[string]*memFSNode)
}
func (fs *MemFS) Checkpoint(newRoot string, sources []string) error {
	if len(sources) == 0 {
		return nil
	}
	resolvedSources := []string{}
	for _, src := range sources {
		if matches, err := filepath.Glob(src); err != nil || len(matches) == 0 {
			resolvedSources = append(resolvedSources, src)
		} else {
			resolvedSources = append(resolvedSources, matches...)
		}
	}
	log.Infof("* Moving directories %v to %s", sources, newRoot)
	for _, src := range resolvedSources {
		if !filepath.IsAbs(src) {
			src = filepath.Join(fs.tree.src, src)
		}
		trimmedSrc, err := pathutils.TrimRoot(src, fs.tree.src)
		if err != nil {
			return fmt.Errorf("trim src %s: %s", src, err)
		}
		dst := filepath.Join(newRoot, trimmedSrc)
		sourceInfo, err := os.Stat(src)
		if err != nil {
			return fmt.Errorf("stat %s: %s", src, err)
		}
		fi, err := os.Lstat(src)
		if err != nil {
			return fmt.Errorf("lstat %s: %s", src, err)
		}
		stat := utils.FileInfoStat(fi)
		copier := fileio.NewCopier(fs.blacklist,
			fileio.WithDstDirOwner(int(stat.Uid), int(stat.Gid), false))
		if sourceInfo.IsDir() {
			if err := copier.CopyDir(src, dst); err != nil {
				return fmt.Errorf("copy dir %s: %s", src, err)
			}
		} else {
			if err := copier.CopyFile(src, dst); err != nil {
				return fmt.Errorf("copy file %s: %s", src, err)
			}
		}
	}
	return nil
}
func (fs *MemFS) Remove() error {
	return removeAllChildren(fs.tree.src, fs.blacklist)
}
func (fs *MemFS) UpdateFromTarPath(source string, untar bool) error {
	reader, err := os.Open(source)
	if err != nil {
		return fmt.Errorf("open tar file: %s", err)
	}
	defer reader.Close()
	gzipReader, err := tario.NewGzipReader(reader)
	if err != nil {
		return fmt.Errorf("new gzip reader: %s", err)
	}
	return fs.UpdateFromTarReader(tar.NewReader(gzipReader), untar)
}
func (fs *MemFS) UpdateFromTarReader(r *tar.Reader, untar bool) error {
	start := time.Now()
	hardlinks := make(map[string]*tar.Header)
	modtimes := make(map[string]time.Time)
	var count int
	l := newMemLayer()
	for {
		hdr, err := r.Next()
		if err == io.EOF {
			duration := time.Since(start).Round(time.Millisecond)
			if untar {
				log.Infow(fmt.Sprintf("* Untarred %d files to %s", count, fs.tree.src), "duration", duration)
			}
			break
		} else if err != nil {
			return fmt.Errorf("read header: %s", err)
		}
		path := filepath.Join(fs.tree.src, hdr.Name)
		if skip, err := shouldSkip(path, hdr.FileInfo(), fs.blacklist); err != nil {
			return fmt.Errorf("check if should skip %s: %s", path, err)
		} else if skip {
			continue
		} else if isMounted, err := mountutils.IsMounted(path); err != nil {
			return fmt.Errorf("check if mounted %s: %s", path, err)
		} else if isMounted {
			continue
		}
		if untar {
			parentDir := filepath.Dir(path)
			if _, found := modtimes[parentDir]; !found {
				parentFi, err := os.Lstat(parentDir)
				if err != nil {
					return fmt.Errorf("stat parent dir of %s: %s", path, err)
				}
				modtimes[parentDir] = parentFi.ModTime()
			}
		}
		hdr.Name = pathutils.RelPath(hdr.Name)
		if hdr.Typeflag == tar.TypeLink {
			hdr.Linkname = pathutils.AbsPath(hdr.Linkname)
			hardlinks[path] = hdr
		} else {
			if untar {
				if err := fs.untarOneItem(path, hdr, r); err != nil {
					return fmt.Errorf("untar one item %s: %s", path, err)
				}
			}
			if err := fs.maybeAddToLayer(l, pathutils.AbsPath(hdr.Name), pathutils.AbsPath(hdr.Name), hdr, false); err != nil {
				return fmt.Errorf("add hdr from tar to layer: %s", err)
			}
		}
		count++
	}
	for path, hdr := range hardlinks {
		if untar {
			if err := fs.untarOneItem(path, hdr, nil); err != nil {
				return fmt.Errorf("untar one item %s: %s", path, err)
			}
		}
		if err := fs.maybeAddToLayer(l, pathutils.AbsPath(hdr.Name), pathutils.AbsPath(hdr.Name), hdr, false); err != nil {
			return fmt.Errorf("add hdr from tar to layer: %s", err)
		}
	}
	for path, modtime := range modtimes {
		if err := os.Chtimes(path, modtime, modtime); err != nil {
			return fmt.Errorf("chtimes on parent directory %s: %s", path, err)
		}
	}
	fs.layers = append(fs.layers, l)
	log.Infof("* Merged %d headers from tar to memfs", l.count())
	return nil
}
func (fs *MemFS) AddLayerByScan(w *tar.Writer) error {
	fs.sync()
	if l, err := fs.createLayerByScan(); err != nil {
		return fmt.Errorf("create layer by scan: %s", err)
	} else if err := fs.commitLayer(l, w); err != nil {
		return fmt.Errorf("commit layer by scan: %s", err)
	} else {
		log.Infof("* Created layer by scanning filesystem; %d files found", l.count())
	}
	return nil
}
func (fs *MemFS) AddLayerByCopyOps(cs []*CopyOperation, w *tar.Writer) error {
	fs.sync()
	l := newMemLayer()
	for _, c := range cs {
		if err := fs.addToLayer(l, c); err != nil {
			return fmt.Errorf("create layer by copy ops: %s", err)
		}
	}
	if err := fs.commitLayer(l, w); err != nil {
		return fmt.Errorf("commit layer by copy ops: %s", err)
	}
	log.Infof("* Created copy layer with %d files", l.count())
	return nil
}