1package copyfile
2
3import (
4	"context"
5	"fmt"
6	"syscall"
7	"unsafe"
8
9	"github.com/Microsoft/hcsshim/internal/oc"
10	"go.opencensus.io/trace"
11)
12
13var (
14	modkernel32   = syscall.NewLazyDLL("kernel32.dll")
15	procCopyFileW = modkernel32.NewProc("CopyFileW")
16)
17
18// CopyFile is a utility for copying a file using CopyFileW win32 API for
19// performance.
20func CopyFile(ctx context.Context, srcFile, destFile string, overwrite bool) (err error) {
21	ctx, span := trace.StartSpan(ctx, "copyfile::CopyFile")
22	defer span.End()
23	defer func() { oc.SetSpanStatus(span, err) }()
24	span.AddAttributes(
25		trace.StringAttribute("srcFile", srcFile),
26		trace.StringAttribute("destFile", destFile),
27		trace.BoolAttribute("overwrite", overwrite))
28
29	var bFailIfExists uint32 = 1
30	if overwrite {
31		bFailIfExists = 0
32	}
33
34	lpExistingFileName, err := syscall.UTF16PtrFromString(srcFile)
35	if err != nil {
36		return err
37	}
38	lpNewFileName, err := syscall.UTF16PtrFromString(destFile)
39	if err != nil {
40		return err
41	}
42	r1, _, err := syscall.Syscall(
43		procCopyFileW.Addr(),
44		3,
45		uintptr(unsafe.Pointer(lpExistingFileName)),
46		uintptr(unsafe.Pointer(lpNewFileName)),
47		uintptr(bFailIfExists))
48	if r1 == 0 {
49		return fmt.Errorf("failed CopyFileW Win32 call from '%s' to '%s': %s", srcFile, destFile, err)
50	}
51	return nil
52}
53