github.com/bir3/gocompiler@v0.9.2202/src/cmd/cgo/internal/cgotest/overlaydir.go (about) 1 // Copyright 2019 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package cgotest 6 7 import ( 8 "io" 9 "os" 10 "path/filepath" 11 "strings" 12 ) 13 14 // OverlayDir makes a minimal-overhead copy of srcRoot in which new files may be added. 15 func OverlayDir(dstRoot, srcRoot string) error { 16 dstRoot = filepath.Clean(dstRoot) 17 if err := os.MkdirAll(dstRoot, 0777); err != nil { 18 return err 19 } 20 21 srcRoot, err := filepath.Abs(srcRoot) 22 if err != nil { 23 return err 24 } 25 26 return filepath.Walk(srcRoot, func(srcPath string, info os.FileInfo, err error) error { 27 if err != nil || srcPath == srcRoot { 28 return err 29 } 30 31 suffix := strings.TrimPrefix(srcPath, srcRoot) 32 for len(suffix) > 0 && suffix[0] == filepath.Separator { 33 suffix = suffix[1:] 34 } 35 dstPath := filepath.Join(dstRoot, suffix) 36 37 perm := info.Mode() & os.ModePerm 38 if info.Mode()&os.ModeSymlink != 0 { 39 info, err = os.Stat(srcPath) 40 if err != nil { 41 return err 42 } 43 perm = info.Mode() & os.ModePerm 44 } 45 46 // Always copy directories (don't symlink them). 47 // If we add a file in the overlay, we don't want to add it in the original. 48 if info.IsDir() { 49 return os.MkdirAll(dstPath, perm|0200) 50 } 51 52 // If the OS supports symlinks, use them instead of copying bytes. 53 if err := os.Symlink(srcPath, dstPath); err == nil { 54 return nil 55 } 56 57 // Otherwise, copy the bytes. 58 src, err := os.Open(srcPath) 59 if err != nil { 60 return err 61 } 62 defer src.Close() 63 64 dst, err := os.OpenFile(dstPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, perm) 65 if err != nil { 66 return err 67 } 68 69 _, err = io.Copy(dst, src) 70 if closeErr := dst.Close(); err == nil { 71 err = closeErr 72 } 73 return err 74 }) 75 }