2020 _winapi = None
2121
2222
23- def get_copy_blocksize (infd ):
23+ def _get_copy_blocksize (infd ):
2424 """Determine blocksize for fastcopying on Linux.
2525 Hopefully the whole file will be copied in a single call.
2626 The copying itself should be performed in a loop 'till EOF is
@@ -40,56 +40,64 @@ def get_copy_blocksize(infd):
4040
4141
4242if fcntl and hasattr (fcntl , 'FICLONE' ):
43- def clonefd (source_fd , target_fd ):
43+ def _ficlone (source_fd , target_fd ):
4444 """
4545 Perform a lightweight copy of two files, where the data blocks are
4646 copied only when modified. This is known as Copy on Write (CoW),
4747 instantaneous copy or reflink.
4848 """
4949 fcntl .ioctl (target_fd , fcntl .FICLONE , source_fd )
5050else :
51- clonefd = None
51+ _ficlone = None
5252
5353
5454if posix and hasattr (posix , '_fcopyfile' ):
55- def copyfd (source_fd , target_fd ):
55+ def _fcopyfile (source_fd , target_fd ):
5656 """
5757 Copy a regular file content using high-performance fcopyfile(3)
5858 syscall (macOS).
5959 """
6060 posix ._fcopyfile (source_fd , target_fd , posix ._COPYFILE_DATA )
61- elif hasattr (os , 'copy_file_range' ):
62- def copyfd (source_fd , target_fd ):
61+ else :
62+ _fcopyfile = None
63+
64+
65+ if hasattr (os , 'copy_file_range' ):
66+ def _copy_file_range (source_fd , target_fd ):
6367 """
6468 Copy data from one regular mmap-like fd to another by using a
6569 high-performance copy_file_range(2) syscall that gives filesystems
6670 an opportunity to implement the use of reflinks or server-side
6771 copy.
6872 This should work on Linux >= 4.5 only.
6973 """
70- blocksize = get_copy_blocksize (source_fd )
74+ blocksize = _get_copy_blocksize (source_fd )
7175 offset = 0
7276 while True :
7377 sent = os .copy_file_range (source_fd , target_fd , blocksize ,
7478 offset_dst = offset )
7579 if sent == 0 :
7680 break # EOF
7781 offset += sent
78- elif hasattr (os , 'sendfile' ):
79- def copyfd (source_fd , target_fd ):
82+ else :
83+ _copy_file_range = None
84+
85+
86+ if hasattr (os , 'sendfile' ):
87+ def _sendfile (source_fd , target_fd ):
8088 """Copy data from one regular mmap-like fd to another by using
8189 high-performance sendfile(2) syscall.
8290 This should work on Linux >= 2.6.33 only.
8391 """
84- blocksize = get_copy_blocksize (source_fd )
92+ blocksize = _get_copy_blocksize (source_fd )
8593 offset = 0
8694 while True :
8795 sent = os .sendfile (target_fd , source_fd , offset , blocksize )
8896 if sent == 0 :
8997 break # EOF
9098 offset += sent
9199else :
92- copyfd = None
100+ _sendfile = None
93101
94102
95103if _winapi and hasattr (_winapi , 'CopyFile2' ):
@@ -114,18 +122,36 @@ def copyfileobj(source_f, target_f):
114122 else :
115123 try :
116124 # Use OS copy-on-write where available.
117- if clonefd :
125+ if _ficlone :
118126 try :
119- clonefd (source_fd , target_fd )
127+ _ficlone (source_fd , target_fd )
120128 return
121129 except OSError as err :
122130 if err .errno not in (EBADF , EOPNOTSUPP , ETXTBSY , EXDEV ):
123131 raise err
124132
125133 # Use OS copy where available.
126- if copyfd :
127- copyfd (source_fd , target_fd )
128- return
134+ if _fcopyfile :
135+ try :
136+ _fcopyfile (source_fd , target_fd )
137+ return
138+ except OSError as err :
139+ if err .errno not in (EINVAL , ENOTSUP ):
140+ raise err
141+ if _copy_file_range :
142+ try :
143+ _copy_file_range (source_fd , target_fd )
144+ return
145+ except OSError as err :
146+ if err .errno not in (ETXTBSY , EXDEV ):
147+ raise err
148+ if _sendfile :
149+ try :
150+ _sendfile (source_fd , target_fd )
151+ return
152+ except OSError as err :
153+ if err .errno != ENOTSOCK :
154+ raise err
129155 except OSError as err :
130156 # Produce more useful error messages.
131157 err .filename = source_f .name
0 commit comments