MCPcopy
hub / github.com/git-lfs/git-lfs / CloneFile

Function CloneFile

tools/util_windows.go:85–129  ·  view source on GitHub ↗
(writer io.Writer, reader io.Reader)

Source from the content-addressed store, hash-verified

83}
84
85func CloneFile(writer io.Writer, reader io.Reader) (success bool, err error) {
86 dst, dstIsFile := writer.(*os.File)
87 src, srcIsFile := reader.(*os.File)
88 if !(dstIsFile && srcIsFile) {
89 return false, nil
90 }
91
92 srcStat, err := src.Stat()
93 if err != nil {
94 return
95 }
96
97 fileSize := srcStat.Size()
98
99 err = dst.Truncate(fileSize) // set file size. There is a requirement "The destination region must not extend past the end of file."
100 if err != nil {
101 return
102 }
103
104 offset := int64(0)
105
106 // Requirement
107 // * The source and destination regions must begin and end at a cluster boundary. (4KiB or 64KiB)
108 // * cloneRegionSize less than 4GiB.
109 // see https://docs.microsoft.com/windows/win32/fileio/block-cloning
110
111 // Clone first xGiB region.
112 for ; offset+GiB < fileSize; offset += GiB {
113 err = callDuplicateExtentsToFile(dst, src, offset, GiB)
114 if err != nil {
115 return false, err
116 }
117 }
118
119 // Clone tail. First try with 64KiB round up, then fallback to 4KiB.
120 for _, cloneRegionSize := range availableClusterSize {
121 err = callDuplicateExtentsToFile(dst, src, offset, roundUp(fileSize-offset, cloneRegionSize))
122 if err != nil {
123 continue
124 }
125 break
126 }
127
128 return err == nil, err
129}
130
131// call FSCTL_DUPLICATE_EXTENTS_TO_FILE IOCTL
132// see https://docs.microsoft.com/en-us/windows/win32/api/winioctl/ni-winioctl-fsctl_duplicate_extents_to_file

Callers 2

CheckCloneFileSupportedFunction · 0.70
CloneFileByPathFunction · 0.70

Calls 3

roundUpFunction · 0.85
SizeMethod · 0.80

Tested by

no test coverage detected