1818#include " mysys_err.h"
1919#include " sql_class.h"
2020#include " sql_backup.h"
21+ #include " sql_backup_interface.h"
2122#include " sql_parse.h"
2223
24+ #ifdef _WIN32
25+ #elif defined __APPLE__
26+ # include < sys/attr.h>
27+ # include < sys/clonefile.h>
28+ # include < copyfile.h>
29+ # define copy_file (src, dst, off ) \
30+ fcopyfile (src, dst, nullptr , COPYFILE_ALL | COPYFILE_CLONE )
31+ #else
32+ using copying_step= ssize_t (int ,int ,size_t ,off_t *);
33+ template <copying_step step>
34+ static ssize_t copy (int in_fd, int out_fd, off_t c) noexcept
35+ {
36+ ssize_t ret;
37+ for (off_t offset{0 };;)
38+ {
39+ off_t count= c;
40+ if (count > INT_MAX >> 20 << 20 )
41+ count = INT_MAX >> 20 << 20 ;
42+ ret= step (in_fd, out_fd, size_t (count), &offset);
43+ if (ret < 0 )
44+ break ;
45+ c-= ret;
46+ if (!c)
47+ return 0 ;
48+ if (!ret)
49+ return -1 ;
50+ }
51+ return ret;
52+ }
53+ # if defined __linux__ || defined __FreeBSD__
54+ /* Copy between files in a single (type of) file system */
55+ static inline ssize_t
56+ copy_step (int in_fd, int out_fd, size_t count, off_t *offset) noexcept
57+ {
58+ return copy_file_range (in_fd, offset, out_fd, nullptr , count, 0 );
59+ }
60+ # define cfr (src,dst,size ) copy<copy_step>(src, dst, size)
61+ # endif
62+ # ifdef __linux__
63+ # include < sys/sendfile.h>
64+ /* Copy a file to a stream or to a regular file. */
65+ static inline ssize_t
66+ send_step (int in_fd, int out_fd, size_t count, off_t *offset) noexcept
67+ {
68+ return sendfile (out_fd, in_fd, offset, count);
69+ }
70+ # else
71+ # include < sys/mman.h>
72+ /* * Copy a file using a memory mapping.
73+ @param in_fd source file
74+ @param out_fd destination
75+ @param count number of bytes to copy
76+ @return error code
77+ @retval 0 on success
78+ @retval 1 if a memory mapping failed */
79+ static ssize_t mmap_copy (int in_fd, int out_fd, off_t count)
80+ {
81+ #if SIZEOF_SIZE_T < 8
82+ if (count != ssize_t (count))
83+ return 1 ;
84+ #endif
85+ void *p= mmap (nullptr , count, PROT_READ , MAP_SHARED , in_fd, 0 );
86+ if (p == MAP_FAILED )
87+ return 1 ;
88+ ssize_t ret;
89+ size_t c= size_t (count);
90+ for (const char *b= static_cast <const char *>(p);; b+= ret)
91+ {
92+ ret= write (out_fd, b, std::min (c, size_t (INT_MAX >> 20 << 20 )));
93+ if (ret < 0 )
94+ break ;
95+ c-= ret;
96+ if (!c)
97+ {
98+ ret= 0 ;
99+ break ;
100+ }
101+ if (!ret)
102+ {
103+ ret= -1 ;
104+ break ;
105+ }
106+ }
107+ munmap (p, count);
108+ return ret;
109+ }
110+
111+ static ssize_t pread_write (int in_fd, int out_fd, off_t count) noexcept
112+ {
113+ constexpr size_t READ_WRITE_SIZE = 65536 ;
114+ char *b= static_cast <char *>(aligned_malloc (READ_WRITE_SIZE , 4096 ));
115+ if (!b)
116+ return -1 ;
117+ ssize_t ret;
118+ for (off_t o= 0 ;; o+= ret)
119+ {
120+ ret= pread (in_fd, b, ssize_t (std::min (count, off_t {READ_WRITE_SIZE })), o);
121+ if (ret > 0 )
122+ ret= write (out_fd, b, ret);
123+ if (ret < 0 )
124+ break ;
125+ count-= ret;
126+ if (!count)
127+ {
128+ ret= 0 ;
129+ break ;
130+ }
131+ if (!ret)
132+ {
133+ ret= -1 ;
134+ break ;
135+ }
136+ }
137+ aligned_free (b);
138+ return ret;
139+ }
140+ # endif
141+
142+ /* * Copy a file.
143+ @param src source file descriptor
144+ @param dst target to append src to
145+ @param size amount of data to be copied
146+ @return error code (negative)
147+ @retval 0 on success */
148+ extern " C" int copy_file (int src, int dst, off_t size)
149+ {
150+ ssize_t ret;
151+ # ifdef cfr
152+ if (!(ret= cfr (src, dst, size)))
153+ return int (ret);
154+ # ifdef __linux__
155+ if (errno == EOPNOTSUPP )
156+ # endif
157+ # endif
158+ # ifdef __linux__ // starting with Linux 2.6.33, we can rely on sendfile(2)
159+ ret= copy<send_step>(src, dst, size);
160+ # else
161+ if ((ret= mmap_copy (src, dst, size)) == 1 )
162+ ret= pread_write (src, dst, size);
163+ # endif
164+ assert (ret <= 0 );
165+ return int (ret);
166+ }
167+ #endif
168+
23169static my_bool backup_start (THD *thd, plugin_ref plugin, void *dst) noexcept
24170{
25171 handlerton *hton= plugin_hton (plugin);
26172 if (hton->backup_start )
27- return hton->backup_start (thd,
28- IF_WIN (static_cast <const char *>(dst),
29- int (reinterpret_cast <uintptr_t >(dst))));
173+ return hton->backup_start (thd, *static_cast <backup_target*>(dst));
30174 return false ;
31175}
32176
@@ -53,9 +197,7 @@ static my_bool backup_finalize(THD *thd, plugin_ref plugin, void *dst) noexcept
53197{
54198 handlerton *hton= plugin_hton (plugin);
55199 if (hton->backup_step )
56- return hton->backup_finalize
57- (thd, IF_WIN (static_cast <const char *>(dst),
58- int (reinterpret_cast <uintptr_t >(dst))));
200+ return hton->backup_finalize (thd, *static_cast <backup_target*>(dst));
59201 return 0 ;
60202}
61203
@@ -90,9 +232,11 @@ bool Sql_cmd_backup::execute(THD *thd)
90232 return true ;
91233 }
92234
93- #ifndef _WIN32
94- int dir= open (target.str , O_DIRECTORY );
95- if (dir < 0 )
235+ #ifdef _WIN32
236+ backup_target dir{target.str , INVALID_HANDLE_VALUE };
237+ #else
238+ backup_target dir{open (target.str , O_DIRECTORY ), true };
239+ if (dir.fd < 0 )
96240 {
97241 my_error (EE_CANT_MKDIR , MYF (ME_BELL ), target.str , errno);
98242 goto err_exit;
@@ -101,9 +245,7 @@ bool Sql_cmd_backup::execute(THD *thd)
101245
102246 bool fail= plugin_foreach_with_mask (thd, backup_start,
103247 MYSQL_STORAGE_ENGINE_PLUGIN ,
104- PLUGIN_IS_DELETED |PLUGIN_IS_READY ,
105- IF_WIN (const_cast <char *>(target.str ),
106- reinterpret_cast <void *>(dir)));
248+ PLUGIN_IS_DELETED |PLUGIN_IS_READY , &dir);
107249
108250 /* The backup_step may be invoked in multiple concurrent threads.
109251 At the time backup_end is invoked, all backup_step will have to complete. */
@@ -122,11 +264,9 @@ bool Sql_cmd_backup::execute(THD *thd)
122264 Release the locks. */
123265 thd->mdl_context .release_lock (mdl_request.ticket );
124266 plugin_foreach_with_mask (thd, backup_finalize, MYSQL_STORAGE_ENGINE_PLUGIN ,
125- PLUGIN_IS_DELETED |PLUGIN_IS_READY ,
126- IF_WIN (const_cast <char *>(target.str ),
127- reinterpret_cast <void *>(dir)));
267+ PLUGIN_IS_DELETED |PLUGIN_IS_READY , &dir);
128268#ifndef _WIN32
129- close (dir);
269+ close (dir. fd );
130270#endif
131271
132272 if (!fail)
0 commit comments