port unionFs from filters to filesystems
diff --git a/union.go b/union.go
index 828cf0c..7cce83e 100644
--- a/union.go
+++ b/union.go
@@ -7,63 +7,6 @@
 	"syscall"
 )
 
-type UnionFs func(Fs) FilterFs
-
-// Create a new UnionFs:
-//
-//    ufs := NewUnionFs(baseFs, layerFs, NewCoWUnionFs())
-//    cfs := NewUnionFs(baseFs, layerFs, NewCacheUnionFs(cacheTime))
-func NewUnionFs(base Fs, overlay Fs, impl UnionFs) Fs {
-	ufs := impl(overlay)
-	ufs.SetSource(base)
-	return ufs
-}
-
-func copyToLayer(base Fs, layer Fs, name string) error {
-	bfh, err := base.Open(name)
-	if err != nil {
-		return err
-	}
-	defer bfh.Close()
-
-	exists, err := Exists(layer, filepath.Dir(name))
-	if err != nil {
-		return err
-	}
-	if !exists {
-		err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME?
-		if err != nil {
-			return err
-		}
-	}
-
-	lfh, err := layer.Create(name)
-	if err != nil {
-		return err
-	}
-	n, err := io.Copy(lfh, bfh)
-	if err != nil {
-		layer.Remove(name)
-		lfh.Close()
-		return err
-	}
-
-	bfi, err := bfh.Stat()
-	if err != nil || bfi.Size() != n {
-		layer.Remove(name)
-		lfh.Close()
-		return syscall.EIO
-	}
-
-	err = lfh.Close()
-	if err != nil {
-		layer.Remove(name)
-		lfh.Close()
-		return err
-	}
-	return layer.Chtimes(name, bfi.ModTime(), bfi.ModTime())
-}
-
 // The UnionFile implements the afero.File interface and will be returned
 // when reading a directory present at least in the overlay or opening a file
 // for writing.
@@ -278,3 +221,48 @@
 	}
 	return 0, BADFD
 }
+
+func copyToLayer(base Fs, layer Fs, name string) error {
+	bfh, err := base.Open(name)
+	if err != nil {
+		return err
+	}
+	defer bfh.Close()
+
+	exists, err := Exists(layer, filepath.Dir(name))
+	if err != nil {
+		return err
+	}
+	if !exists {
+		err = layer.MkdirAll(filepath.Dir(name), 0777) // FIXME?
+		if err != nil {
+			return err
+		}
+	}
+
+	lfh, err := layer.Create(name)
+	if err != nil {
+		return err
+	}
+	n, err := io.Copy(lfh, bfh)
+	if err != nil {
+		layer.Remove(name)
+		lfh.Close()
+		return err
+	}
+
+	bfi, err := bfh.Stat()
+	if err != nil || bfi.Size() != n {
+		layer.Remove(name)
+		lfh.Close()
+		return syscall.EIO
+	}
+
+	err = lfh.Close()
+	if err != nil {
+		layer.Remove(name)
+		lfh.Close()
+		return err
+	}
+	return layer.Chtimes(name, bfi.ModTime(), bfi.ModTime())
+}
diff --git a/union_cache.go b/union_cache.go
index bae895b..aa227f0 100644
--- a/union_cache.go
+++ b/union_cache.go
@@ -25,21 +25,6 @@
 	cacheTime time.Duration
 }
 
-func NewCacheUnionFs(t time.Duration) UnionFs {
-	return func(layer Fs) FilterFs {
-		return &CacheUnionFs{cacheTime: t, layer: layer}
-	}
-}
-
-func (u *CacheUnionFs) AddFilter(fs FilterFs) {
-	fs.SetSource(u.base)
-	u.base = fs
-}
-
-func (u *CacheUnionFs) SetSource(fs Fs) {
-	u.base = fs
-}
-
 type cacheState int
 
 const (
diff --git a/union_cow.go b/union_cow.go
index 0c75e2b..8c9d9dc 100644
--- a/union_cow.go
+++ b/union_cow.go
@@ -6,7 +6,7 @@
 	"time"
 )
 
-// The CoWUnionFs is a union filesystem: a read only base file system with
+// The CopyOnWriteUnionFs is a union filesystem: a read only base file system with
 // a possibly writeable layer on top. Changes to the file system will only
 // be made in the overlay: Changing an existing file in the base layer which
 // is not present in the overlay will copy the file to the overlay ("changing"
@@ -17,28 +17,12 @@
 //    can handle this).
 //
 // Reading directories is currently only supported via Open(), not OpenFile().
-type CoWUnionFs struct {
+type CopyOnWriteUnionFs struct {
 	base  Fs
 	layer Fs
 }
 
-func NewCoWUnionFs() UnionFs {
-	// returns a function to have it the same as other implemtations
-	return func(layer Fs) FilterFs {
-		return &CoWUnionFs{layer: layer}
-	}
-}
-
-func (u *CoWUnionFs) AddFilter(fs FilterFs) {
-	fs.SetSource(u.base)
-	u.base = fs
-}
-
-func (u *CoWUnionFs) SetSource(fs Fs) {
-	u.base = fs
-}
-
-func (u *CoWUnionFs) isBaseFile(name string) (bool, error) {
+func (u *CopyOnWriteUnionFs) isBaseFile(name string) (bool, error) {
 	if _, err := u.layer.Stat(name); err == nil {
 		return false, nil
 	}
@@ -46,11 +30,11 @@
 	return true, err
 }
 
-func (u *CoWUnionFs) copyToLayer(name string) error {
+func (u *CopyOnWriteUnionFs) copyToLayer(name string) error {
 	return copyToLayer(u.base, u.layer, name)
 }
 
-func (u *CoWUnionFs) Chtimes(name string, atime, mtime time.Time) error {
+func (u *CopyOnWriteUnionFs) Chtimes(name string, atime, mtime time.Time) error {
 	b, err := u.isBaseFile(name)
 	if err != nil {
 		return err
@@ -63,7 +47,7 @@
 	return u.layer.Chtimes(name, atime, mtime)
 }
 
-func (u *CoWUnionFs) Chmod(name string, mode os.FileMode) error {
+func (u *CopyOnWriteUnionFs) Chmod(name string, mode os.FileMode) error {
 	b, err := u.isBaseFile(name)
 	if err != nil {
 		return err
@@ -76,7 +60,7 @@
 	return u.layer.Chmod(name, mode)
 }
 
-func (u *CoWUnionFs) Stat(name string) (os.FileInfo, error) {
+func (u *CopyOnWriteUnionFs) Stat(name string) (os.FileInfo, error) {
 	fi, err := u.layer.Stat(name)
 	switch err {
 	case nil:
@@ -89,7 +73,7 @@
 }
 
 // Renaming files present only in the base layer is not permitted
-func (u *CoWUnionFs) Rename(oldname, newname string) error {
+func (u *CopyOnWriteUnionFs) Rename(oldname, newname string) error {
 	b, err := u.isBaseFile(oldname)
 	if err != nil {
 		return err
@@ -103,7 +87,7 @@
 // Removing files present only in the base layer is not permitted. If
 // a file is present in the base layer and the overlay, only the overlay
 // will be removed.
-func (u *CoWUnionFs) Remove(name string) error {
+func (u *CopyOnWriteUnionFs) Remove(name string) error {
 	err := u.layer.Remove(name)
 	switch err {
 	case syscall.ENOENT:
@@ -117,7 +101,7 @@
 	}
 }
 
-func (u *CoWUnionFs) RemoveAll(name string) error {
+func (u *CopyOnWriteUnionFs) RemoveAll(name string) error {
 	err := u.layer.RemoveAll(name)
 	switch err {
 	case syscall.ENOENT:
@@ -131,7 +115,7 @@
 	}
 }
 
-func (u *CoWUnionFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
+func (u *CopyOnWriteUnionFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
 	b, err := u.isBaseFile(name)
 	if err != nil {
 		return nil, err
@@ -151,7 +135,7 @@
 	return u.layer.OpenFile(name, flag, perm)
 }
 
-func (u *CoWUnionFs) Open(name string) (File, error) {
+func (u *CopyOnWriteUnionFs) Open(name string) (File, error) {
 	b, err := u.isBaseFile(name)
 	if err != nil {
 		return nil, err
@@ -176,7 +160,7 @@
 	return &UnionFile{base: bfile, layer: lfile}, nil
 }
 
-func (u *CoWUnionFs) Mkdir(name string, perm os.FileMode) error {
+func (u *CopyOnWriteUnionFs) Mkdir(name string, perm os.FileMode) error {
 	dir, err := IsDir(u.base, name)
 	if err != nil {
 		return u.layer.MkdirAll(name, perm)
@@ -187,11 +171,11 @@
 	return u.layer.MkdirAll(name, perm)
 }
 
-func (u *CoWUnionFs) Name() string {
-	return "CoWUnionFs"
+func (u *CopyOnWriteUnionFs) Name() string {
+	return "CopyOnWriteUnionFs"
 }
 
-func (u *CoWUnionFs) MkdirAll(name string, perm os.FileMode) error {
+func (u *CopyOnWriteUnionFs) MkdirAll(name string, perm os.FileMode) error {
 	dir, err := IsDir(u.base, name)
 	if err != nil {
 		return u.layer.MkdirAll(name, perm)
@@ -202,7 +186,7 @@
 	return u.layer.MkdirAll(name, perm)
 }
 
-func (u *CoWUnionFs) Create(name string) (File, error) {
+func (u *CopyOnWriteUnionFs) Create(name string) (File, error) {
 	b, err := u.isBaseFile(name)
 	if err == nil && b {
 		if err = u.copyToLayer(name); err != nil {
diff --git a/union_test.go b/union_test.go
index 24f93cd..9c3fb0d 100644
--- a/union_test.go
+++ b/union_test.go
@@ -11,7 +11,7 @@
 	base := &MemMapFs{}
 	roBase := &ReadOnlyFs{source: base}
 
-	ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())
+	ufs := &CopyOnWriteUnionFs{base: roBase, layer: &MemMapFs{}}
 
 	base.MkdirAll("/home/test", 0777)
 	fh, _ := base.Create("/home/test/file.txt")
@@ -61,7 +61,7 @@
 	base := &MemMapFs{}
 	roBase := &ReadOnlyFs{source: base}
 
-	ufs := NewUnionFs(roBase, &MemMapFs{}, NewCoWUnionFs())
+	ufs := &CopyOnWriteUnionFs{base: roBase, layer: &MemMapFs{}}
 
 	base.MkdirAll("/home/test", 0777)
 	fh, _ := base.Create("/home/test/file.txt")
@@ -85,7 +85,8 @@
 func TestUnionCacheWrite(t *testing.T) {
 	base := &MemMapFs{}
 	layer := &MemMapFs{}
-	ufs := NewUnionFs(base, layer, NewCacheUnionFs(0))
+
+	ufs := &CacheUnionFs{base: base, layer: layer, cacheTime: 0}
 
 	base.Mkdir("/data", 0777)
 
@@ -114,7 +115,7 @@
 func TestUnionCacheExpire(t *testing.T) {
 	base := &MemMapFs{}
 	layer := &MemMapFs{}
-	ufs := NewUnionFs(base, layer, NewCacheUnionFs(1*time.Second))
+	ufs := &CacheUnionFs{base: base, layer: layer, cacheTime: 1 * time.Second}
 
 	base.Mkdir("/data", 0777)