1 /*
2    Copyright (c) 2000, 2014, Oracle and/or its affiliates.
3    Copyright (c) 2009, 2020, MariaDB
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; version 2 of the License.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA
17 */
18 
19 /*
20 
21    TODO: print the catalog (some USE catalog.db ????).
22 
23    Standalone program to read a MySQL binary log (or relay log).
24 
25    Should be able to read any file of these categories, even with
26    --start-position.
27    An important fact: the Format_desc event of the log is at most the 3rd event
28    of the log; if it is the 3rd then there is this combination:
29    Format_desc_of_slave, Rotate_of_master, Format_desc_of_master.
30 */
31 
32 #define MYSQL_CLIENT
33 #undef MYSQL_SERVER
34 #define TABLE TABLE_CLIENT
35 /* This hack is here to avoid adding COMPRESSED data types to libmariadb. */
36 #define MYSQL_TYPE_TIME2 MYSQL_TYPE_TIME2,MYSQL_TYPE_BLOB_COMPRESSED=140,MYSQL_TYPE_VARCHAR_COMPRESSED=141
37 #include "client_priv.h"
38 #undef MYSQL_TYPE_TIME2
39 #include <my_time.h>
40 #include <sslopt-vars.h>
41 /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
42 #include "sql_priv.h"
43 #include "sql_basic_types.h"
44 #include "log_event.h"
45 #include "compat56.h"
46 #include "sql_common.h"
47 #include "my_dir.h"
48 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
49 #include "sql_string.h"   // needed for Rpl_filter
50 #include "sql_list.h"     // needed for Rpl_filter
51 #include "rpl_filter.h"
52 
53 #include "mysqld.h"
54 
55 #include <algorithm>
56 
57 #define my_net_write ma_net_write
58 #define net_flush ma_net_flush
59 #define cli_safe_read mysql_net_read_packet
60 #define my_net_read ma_net_read
61 extern "C" unsigned char *mysql_net_store_length(unsigned char *packet, size_t length);
62 #define net_store_length mysql_net_store_length
63 
64 Rpl_filter *binlog_filter= 0;
65 
66 #define BIN_LOG_HEADER_SIZE	4
67 #define PROBE_HEADER_LEN	(EVENT_LEN_OFFSET+4)
68 
69 /* Needed for Rpl_filter */
70 CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
71 
72 /* Needed for Flashback */
73 DYNAMIC_ARRAY binlog_events; // Storing the events output string
74 DYNAMIC_ARRAY events_in_stmt; // Storing the events that in one statement
75 String stop_event_string; // Storing the STOP_EVENT output string
76 
77 char server_version[SERVER_VERSION_LENGTH];
78 ulong server_id = 0;
79 
80 // needed by net_serv.c
81 ulong bytes_sent = 0L, bytes_received = 0L;
82 ulong mysqld_net_retry_count = 10L;
83 ulong open_files_limit;
84 ulong opt_binlog_rows_event_max_size;
85 ulonglong test_flags = 0;
86 ulong opt_binlog_rows_event_max_encoded_size= MAX_MAX_ALLOWED_PACKET;
87 static uint opt_protocol= 0;
88 static FILE *result_file;
89 static char *result_file_name= 0;
90 static const char *output_prefix= "";
91 
92 #ifndef DBUG_OFF
93 static const char *default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
94 const char *current_dbug_option= default_dbug_option;
95 #endif
96 static const char *load_groups[]=
97 { "mysqlbinlog", "client", "client-server", "client-mariadb", 0 };
98 
99 static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
100 static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
101 
102 static bool one_database=0, one_table=0, to_last_remote_log= 0, disable_log_bin= 0;
103 static bool opt_hexdump= 0, opt_version= 0;
104 const char *base64_output_mode_names[]=
105 {"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS};
106 TYPELIB base64_output_mode_typelib=
107   { array_elements(base64_output_mode_names) - 1, "",
108     base64_output_mode_names, NULL };
109 static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
110 static char *opt_base64_output_mode_str= NullS;
111 static char* database= 0;
112 static char* table= 0;
113 static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
114 static my_bool print_row_count= 0, print_row_event_positions= 0;
115 static my_bool print_row_count_used= 0, print_row_event_positions_used= 0;
116 static my_bool debug_info_flag, debug_check_flag;
117 static my_bool force_if_open_opt= 1;
118 static my_bool opt_raw_mode= 0, opt_stop_never= 0;
119 static ulong opt_stop_never_slave_server_id= 0;
120 static my_bool opt_verify_binlog_checksum= 1;
121 static ulonglong offset = 0;
122 static char* host = 0;
123 static int port= 0;
124 static uint my_end_arg;
125 static const char* sock= 0;
126 static char *opt_plugindir= 0, *opt_default_auth= 0;
127 
128 #ifdef HAVE_SMEM
129 static const char *shared_memory_base_name= 0;
130 #endif
131 static char* user = 0;
132 static char* pass = 0;
133 static char *charset= 0;
134 
135 static uint verbose= 0;
136 
137 static ulonglong start_position, stop_position;
138 #define start_position_mot ((my_off_t)start_position)
139 #define stop_position_mot  ((my_off_t)stop_position)
140 
141 static char *start_datetime_str, *stop_datetime_str;
142 static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
143 static ulonglong rec_count= 0;
144 static MYSQL* mysql = NULL;
145 static const char* dirname_for_local_load= 0;
146 static bool opt_skip_annotate_row_events= 0;
147 
148 static my_bool opt_flashback;
149 #ifdef WHEN_FLASHBACK_REVIEW_READY
150 static my_bool opt_flashback_review;
151 static char *flashback_review_dbname, *flashback_review_tablename;
152 #endif
153 
154 /**
155   Pointer to the Format_description_log_event of the currently active binlog.
156 
157   This will be changed each time a new Format_description_log_event is
158   found in the binlog. It is finally destroyed at program termination.
159 */
160 static Format_description_log_event* glob_description_event= NULL;
161 
162 /**
163   Exit status for functions in this file.
164 */
165 enum Exit_status {
166   /** No error occurred and execution should continue. */
167   OK_CONTINUE= 0,
168   /** An error occurred and execution should stop. */
169   ERROR_STOP,
170   /** No error occurred but execution should stop. */
171   OK_STOP,
172   /** No error occurred - end of file reached. */
173   OK_EOF,
174 };
175 
176 /**
177   Pointer to the last read Annotate_rows_log_event. Having read an
178   Annotate_rows event, we should not print it immediatedly because all
179   subsequent rbr events can be filtered away, and have to keep it for a while.
180   Also because of that when reading a remote Annotate event we have to keep
181   its binary log representation in a separately allocated buffer.
182 */
183 static Annotate_rows_log_event *annotate_event= NULL;
184 
free_annotate_event()185 static void free_annotate_event()
186 {
187   if (annotate_event)
188   {
189     delete annotate_event;
190     annotate_event= 0;
191   }
192 }
193 
read_remote_annotate_event(uchar * net_buf,ulong event_len,const char ** error_msg)194 Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
195                                       const char **error_msg)
196 {
197   uchar *event_buf;
198   Log_event* event;
199 
200   if (!(event_buf= (uchar*) my_malloc(event_len + 1, MYF(MY_WME))))
201   {
202     error("Out of memory");
203     return 0;
204   }
205 
206   memcpy(event_buf, net_buf, event_len);
207   event_buf[event_len]= 0;
208 
209   if (!(event= Log_event::read_log_event((const char*) event_buf, event_len,
210                                          error_msg, glob_description_event,
211                                          opt_verify_binlog_checksum)))
212   {
213     my_free(event_buf);
214     return 0;
215   }
216   /*
217     Ensure the event->temp_buf is pointing to the allocated buffer.
218     (TRUE = free temp_buf on the event deletion)
219   */
220   event->register_temp_buf((char*)event_buf, TRUE);
221 
222   return event;
223 }
224 
keep_annotate_event(Annotate_rows_log_event * event)225 void keep_annotate_event(Annotate_rows_log_event* event)
226 {
227   free_annotate_event();
228   annotate_event= event;
229 }
230 
print_annotate_event(PRINT_EVENT_INFO * print_event_info)231 bool print_annotate_event(PRINT_EVENT_INFO *print_event_info)
232 {
233   bool error= 0;
234   if (annotate_event)
235   {
236     annotate_event->print(result_file, print_event_info);
237     free_annotate_event();
238   }
239   return error;
240 }
241 
242 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *, const char*);
243 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *, const char*);
244 static Exit_status dump_log_entries(const char* logname);
245 static Exit_status safe_connect();
246 
247 
248 class Load_log_processor
249 {
250   char target_dir_name[FN_REFLEN];
251   size_t target_dir_name_len;
252 
253   /*
254     When we see first event corresponding to some LOAD DATA statement in
255     binlog, we create temporary file to store data to be loaded.
256     We add name of this file to file_names array using its file_id as index.
257     If we have Create_file event (i.e. we have binary log in pre-5.0.3
258     format) we also store save event object to be able which is needed to
259     emit LOAD DATA statement when we will meet Exec_load_data event.
260     If we have Begin_load_query event we simply store 0 in
261     File_name_record::event field.
262   */
263   struct File_name_record
264   {
265     char *fname;
266     Create_file_log_event *event;
267   };
268   /*
269     @todo Should be a map (e.g., a hash map), not an array.  With the
270     present implementation, the number of elements in this array is
271     about the number of files loaded since the server started, which
272     may be big after a few years.  We should be able to use existing
273     library data structures for this. /Sven
274   */
275   DYNAMIC_ARRAY file_names;
276 
277   /**
278     Looks for a non-existing filename by adding a numerical suffix to
279     the given base name, creates the generated file, and returns the
280     filename by modifying the filename argument.
281 
282     @param[in,out] filename Base filename
283 
284     @param[in,out] file_name_end Pointer to last character of
285     filename.  The numerical suffix will be written to this position.
286     Note that there must be a least five bytes of allocated memory
287     after file_name_end.
288 
289     @retval -1 Error (can't find new filename).
290     @retval >=0 Found file.
291   */
create_unique_file(char * filename,char * file_name_end)292   File create_unique_file(char *filename, char *file_name_end)
293     {
294       File res;
295       /* If we have to try more than 1000 times, something is seriously wrong */
296       for (uint version= 0; version<1000; version++)
297       {
298 	sprintf(file_name_end,"-%x",version);
299 	if ((res= my_create(filename,0,
300 			    O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
301 	  return res;
302       }
303       return -1;
304     }
305 
306 public:
Load_log_processor()307   Load_log_processor() {}
~Load_log_processor()308   ~Load_log_processor() {}
309 
init()310   int init()
311   {
312     return my_init_dynamic_array(&file_names, sizeof(File_name_record),
313                                  100, 100, MYF(0));
314   }
315 
init_by_dir_name(const char * dir)316   void init_by_dir_name(const char *dir)
317     {
318       target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
319 			    target_dir_name);
320     }
init_by_cur_dir()321   void init_by_cur_dir()
322     {
323       if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
324 	exit(1);
325       target_dir_name_len= strlen(target_dir_name);
326     }
destroy()327   void destroy()
328   {
329     File_name_record *ptr= (File_name_record *)file_names.buffer;
330     File_name_record *end= ptr + file_names.elements;
331     for (; ptr < end; ptr++)
332     {
333       if (ptr->fname)
334       {
335         my_free(ptr->fname);
336         delete ptr->event;
337         bzero((char *)ptr, sizeof(File_name_record));
338       }
339     }
340 
341     delete_dynamic(&file_names);
342   }
343 
344   /**
345     Obtain Create_file event for LOAD DATA statement by its file_id
346     and remove it from this Load_log_processor's list of events.
347 
348     Checks whether we have already seen a Create_file_log_event with
349     the given file_id.  If yes, returns a pointer to the event and
350     removes the event from array describing active temporary files.
351     From this moment, the caller is responsible for freeing the memory
352     occupied by the event.
353 
354     @param[in] file_id File id identifying LOAD DATA statement.
355 
356     @return Pointer to Create_file_log_event, or NULL if we have not
357     seen any Create_file_log_event with this file_id.
358   */
grab_event(uint file_id)359   Create_file_log_event *grab_event(uint file_id)
360     {
361       File_name_record *ptr;
362       Create_file_log_event *res;
363 
364       if (file_id >= file_names.elements)
365         return 0;
366       ptr= dynamic_element(&file_names, file_id, File_name_record*);
367       if ((res= ptr->event))
368         bzero((char *)ptr, sizeof(File_name_record));
369       return res;
370     }
371 
372   /**
373     Obtain file name of temporary file for LOAD DATA statement by its
374     file_id and remove it from this Load_log_processor's list of events.
375 
376     @param[in] file_id Identifier for the LOAD DATA statement.
377 
378     Checks whether we have already seen Begin_load_query event for
379     this file_id. If yes, returns the file name of the corresponding
380     temporary file and removes the filename from the array of active
381     temporary files.  From this moment, the caller is responsible for
382     freeing the memory occupied by this name.
383 
384     @return String with the name of the temporary file, or NULL if we
385     have not seen any Begin_load_query_event with this file_id.
386   */
grab_fname(uint file_id)387   char *grab_fname(uint file_id)
388     {
389       File_name_record *ptr;
390       char *res= 0;
391 
392       if (file_id >= file_names.elements)
393         return 0;
394       ptr= dynamic_element(&file_names, file_id, File_name_record*);
395       if (!ptr->event)
396       {
397         res= ptr->fname;
398         bzero((char *)ptr, sizeof(File_name_record));
399       }
400       return res;
401     }
402   Exit_status process(Create_file_log_event *ce);
403   Exit_status process(Begin_load_query_log_event *ce);
404   Exit_status process(Append_block_log_event *ae);
405   File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
406   Exit_status load_old_format_file(NET* net, const char *server_fname,
407                                    uint server_fname_len, File file);
408   Exit_status process_first_event(const char *bname, size_t blen,
409                                   const uchar *block,
410                                   size_t block_len, uint file_id,
411                                   Create_file_log_event *ce);
412 };
413 
414 
415 /**
416   Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir().
417 
418   @param[in] le The basename of the created file will start with the
419   basename of the file pointed to by this Load_log_event.
420 
421   @param[out] filename Buffer to save the filename in.
422 
423   @return File handle >= 0 on success, -1 on error.
424 */
prepare_new_file_for_old_format(Load_log_event * le,char * filename)425 File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le,
426 							 char *filename)
427 {
428   size_t len;
429   char *tail;
430   File file;
431 
432   fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
433   len= strlen(filename);
434   tail= filename + len;
435 
436   if ((file= create_unique_file(filename,tail)) < 0)
437   {
438     error("Could not construct local filename %s.",filename);
439     return -1;
440   }
441 
442   le->set_fname_outside_temp_buf(filename,len+strlen(tail));
443 
444   return file;
445 }
446 
447 
448 /**
449   Reads a file from a server and saves it locally.
450 
451   @param[in,out] net The server to read from.
452 
453   @param[in] server_fname The name of the file that the server should
454   read.
455 
456   @param[in] server_fname_len The length of server_fname.
457 
458   @param[in,out] file The file to write to.
459 
460   @retval ERROR_STOP An error occurred - the program should terminate.
461   @retval OK_CONTINUE No error, the program should continue.
462 */
load_old_format_file(NET * net,const char * server_fname,uint server_fname_len,File file)463 Exit_status Load_log_processor::load_old_format_file(NET* net,
464                                                      const char*server_fname,
465                                                      uint server_fname_len,
466                                                      File file)
467 {
468   uchar buf[FN_REFLEN+1];
469   buf[0] = 0;
470   memcpy(buf + 1, server_fname, server_fname_len + 1);
471   if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
472   {
473     error("Failed requesting the remote dump of %s.", server_fname);
474     return ERROR_STOP;
475   }
476 
477   for (;;)
478   {
479     ulong packet_len = my_net_read(net);
480     if (packet_len == 0)
481     {
482       if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
483       {
484         error("Failed sending the ack packet.");
485         return ERROR_STOP;
486       }
487       /*
488 	we just need to send something, as the server will read but
489 	not examine the packet - this is because mysql_load() sends
490 	an OK when it is done
491       */
492       break;
493     }
494     else if (packet_len == packet_error)
495     {
496       error("Failed reading a packet during the dump of %s.", server_fname);
497       return ERROR_STOP;
498     }
499 
500     if (packet_len > UINT_MAX)
501     {
502       error("Illegal length of packet read from net.");
503       return ERROR_STOP;
504     }
505     if (my_write(file, (uchar*) net->read_pos,
506 		 (uint) packet_len, MYF(MY_WME|MY_NABP)))
507       return ERROR_STOP;
508   }
509 
510   return OK_CONTINUE;
511 }
512 
513 
514 /**
515   Process the first event in the sequence of events representing a
516   LOAD DATA statement.
517 
518   Creates a temporary file to be used in LOAD DATA and writes first
519   block of data to it. Registers its file name (and optional
520   Create_file event) in the array of active temporary files.
521 
522   @param bname Base name for temporary file to be created.
523   @param blen Base name length.
524   @param block First block of data to be loaded.
525   @param block_len First block length.
526   @param file_id Identifies the LOAD DATA statement.
527   @param ce Pointer to Create_file event object if we are processing
528   this type of event.
529 
530   @retval ERROR_STOP An error occurred - the program should terminate.
531   @retval OK_CONTINUE No error, the program should continue.
532 */
process_first_event(const char * bname,size_t blen,const uchar * block,size_t block_len,uint file_id,Create_file_log_event * ce)533 Exit_status Load_log_processor::process_first_event(const char *bname,
534                                                     size_t blen,
535                                                     const uchar *block,
536                                                     size_t block_len,
537                                                     uint file_id,
538                                                     Create_file_log_event *ce)
539 {
540   size_t full_len= target_dir_name_len + blen + 9 + 9 + 1;
541   Exit_status retval= OK_CONTINUE;
542   char *fname, *ptr;
543   File file;
544   File_name_record rec;
545   DBUG_ENTER("Load_log_processor::process_first_event");
546 
547   if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
548   {
549     error("Out of memory.");
550     delete ce;
551     DBUG_RETURN(ERROR_STOP);
552   }
553 
554   memcpy(fname, target_dir_name, target_dir_name_len);
555   ptr= fname + target_dir_name_len;
556   memcpy(ptr,bname,blen);
557   ptr+= blen;
558   ptr+= sprintf(ptr, "-%x", file_id);
559 
560   if ((file= create_unique_file(fname,ptr)) < 0)
561   {
562     error("Could not construct local filename %s%s.",
563           target_dir_name,bname);
564     my_free(fname);
565     delete ce;
566     DBUG_RETURN(ERROR_STOP);
567   }
568 
569   rec.fname= fname;
570   rec.event= ce;
571 
572   /*
573      fname is freed in process_event()
574      after Execute_load_query_log_event or Execute_load_log_event
575      will have been processed, otherwise in Load_log_processor::destroy()
576   */
577   if (set_dynamic(&file_names, (uchar*)&rec, file_id))
578   {
579     error("Out of memory.");
580     my_free(fname);
581     delete ce;
582     DBUG_RETURN(ERROR_STOP);
583   }
584 
585   if (ce)
586     ce->set_fname_outside_temp_buf(fname, strlen(fname));
587 
588   if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
589   {
590     error("Failed writing to file.");
591     retval= ERROR_STOP;
592   }
593   if (my_close(file, MYF(MY_WME)))
594   {
595     error("Failed closing file.");
596     retval= ERROR_STOP;
597   }
598   DBUG_RETURN(retval);
599 }
600 
601 
602 /**
603   Process the given Create_file_log_event.
604 
605   @see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
606 
607   @param ce Create_file_log_event to process.
608 
609   @retval ERROR_STOP An error occurred - the program should terminate.
610   @retval OK_CONTINUE No error, the program should continue.
611 */
process(Create_file_log_event * ce)612 Exit_status  Load_log_processor::process(Create_file_log_event *ce)
613 {
614   const char *bname= ce->fname + dirname_length(ce->fname);
615   size_t blen= ce->fname_len - (bname-ce->fname);
616 
617   return process_first_event(bname, blen, ce->block, ce->block_len,
618                              ce->file_id, ce);
619 }
620 
621 
622 /**
623   Process the given Begin_load_query_log_event.
624 
625   @see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
626 
627   @param ce Begin_load_query_log_event to process.
628 
629   @retval ERROR_STOP An error occurred - the program should terminate.
630   @retval OK_CONTINUE No error, the program should continue.
631 */
process(Begin_load_query_log_event * blqe)632 Exit_status Load_log_processor::process(Begin_load_query_log_event *blqe)
633 {
634   return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
635                              blqe->file_id, 0);
636 }
637 
638 
639 /**
640   Process the given Append_block_log_event.
641 
642   Appends the chunk of the file contents specified by the event to the
643   file created by a previous Begin_load_query_log_event or
644   Create_file_log_event.
645 
646   If the file_id for the event does not correspond to any file
647   previously registered through a Begin_load_query_log_event or
648   Create_file_log_event, this member function will print a warning and
649   return OK_CONTINUE.  It is safe to return OK_CONTINUE, because no
650   query will be written for this event.  We should not print an error
651   and fail, since the missing file_id could be because a (valid)
652   --start-position has been specified after the Begin/Create event but
653   before this Append event.
654 
655   @param ae Append_block_log_event to process.
656 
657   @retval ERROR_STOP An error occurred - the program should terminate.
658 
659   @retval OK_CONTINUE No error, the program should continue.
660 */
process(Append_block_log_event * ae)661 Exit_status Load_log_processor::process(Append_block_log_event *ae)
662 {
663   DBUG_ENTER("Load_log_processor::process");
664   const char* fname= ((ae->file_id < file_names.elements) ?
665                        dynamic_element(&file_names, ae->file_id,
666                                        File_name_record*)->fname : 0);
667 
668   if (fname)
669   {
670     File file;
671     Exit_status retval= OK_CONTINUE;
672     if (((file= my_open(fname,
673 			O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
674     {
675       error("Failed opening file %s", fname);
676       DBUG_RETURN(ERROR_STOP);
677     }
678     if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
679     {
680       error("Failed writing to file %s", fname);
681       retval= ERROR_STOP;
682     }
683     if (my_close(file,MYF(MY_WME)))
684     {
685       error("Failed closing file %s", fname);
686       retval= ERROR_STOP;
687     }
688     DBUG_RETURN(retval);
689   }
690 
691   /*
692     There is no Create_file event (a bad binlog or a big
693     --start-position). Assuming it's a big --start-position, we just do
694     nothing and print a warning.
695   */
696   warning("Ignoring Append_block as there is no "
697           "Create_file event for file_id: %u", ae->file_id);
698   DBUG_RETURN(OK_CONTINUE);
699 }
700 
701 
702 static Load_log_processor load_processor;
703 
704 
705 /**
706   Replace windows-style backslashes by forward slashes so it can be
707   consumed by the mysql client, which requires Unix path.
708 
709   @todo This is only useful under windows, so may be ifdef'ed out on
710   other systems.  /Sven
711 
712   @todo If a Create_file_log_event contains a filename with a
713   backslash (valid under unix), then we have problems under windows.
714   /Sven
715 
716   @param[in,out] fname Filename to modify. The filename is modified
717   in-place.
718 */
convert_path_to_forward_slashes(char * fname)719 static void convert_path_to_forward_slashes(char *fname)
720 {
721   while (*fname)
722   {
723     if (*fname == '\\')
724       *fname= '/';
725     fname++;
726   }
727 }
728 
729 
730 /**
731   Indicates whether the given database should be filtered out,
732   according to the --database=X option.
733 
734   @param log_dbname Name of database.
735 
736   @return nonzero if the database with the given name should be
737   filtered out, 0 otherwise.
738 */
shall_skip_database(const char * log_dbname)739 static bool shall_skip_database(const char *log_dbname)
740 {
741   return one_database &&
742          (log_dbname != NULL) &&
743          strcmp(log_dbname, database);
744 }
745 
746 
747 /**
748   Print "use <db>" statement when current db is to be changed.
749 
750   We have to control emitting USE statements according to rewrite-db options.
751   We have to do it here (see process_event() below) and to suppress
752   producing USE statements by corresponding log event print-functions.
753 */
754 
755 static void
print_use_stmt(PRINT_EVENT_INFO * pinfo,const Query_log_event * ev)756 print_use_stmt(PRINT_EVENT_INFO* pinfo, const Query_log_event *ev)
757 {
758   const char* db= ev->db;
759   const size_t db_len= ev->db_len;
760 
761   // pinfo->db is the current db.
762   // If current db is the same as required db, do nothing.
763   if ((ev->flags & LOG_EVENT_SUPPRESS_USE_F) || !db ||
764       !memcmp(pinfo->db, db, db_len + 1))
765     return;
766 
767   // Current db and required db are different.
768   // Check for rewrite rule for required db. (Note that in a rewrite rule
769   // neither db_from nor db_to part can be empty).
770   size_t len_to= 0;
771   const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
772 
773   // If there is no rewrite rule for db (in this case len_to is left = 0),
774   // printing of the corresponding USE statement is left for log event
775   // print-function.
776   if (!len_to)
777     return;
778 
779   // In case of rewrite rule print USE statement for db_to
780   my_fprintf(result_file, "use %`s%s\n", db_to, pinfo->delimiter);
781 
782   // Copy the *original* db to pinfo to suppress emitting
783   // of USE stmts by log_event print-functions.
784   memcpy(pinfo->db, db, db_len + 1);
785 }
786 
787 
788 /**
789    Print "SET skip_replication=..." statement when needed.
790 
791    Not all servers support this (only MariaDB from some version on). So we
792    mark the SET to only execute from the version of MariaDB that supports it,
793    and also only output it if we actually see events with the flag set, to not
794    get spurious errors on MySQL@Oracle servers of higher version that do not
795    support the flag.
796 
797    So we start out assuming @@skip_replication is 0, and only output a SET
798    statement when it changes.
799 */
800 static void
print_skip_replication_statement(PRINT_EVENT_INFO * pinfo,const Log_event * ev)801 print_skip_replication_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev)
802 {
803   bool cur_val;
804 
805   cur_val= (ev->flags & LOG_EVENT_SKIP_REPLICATION_F) != 0;
806   if (cur_val == pinfo->skip_replication)
807     return;                                     /* Not changed. */
808   fprintf(result_file, "/*!50521 SET skip_replication=%d*/%s\n",
809           cur_val, pinfo->delimiter);
810   pinfo->skip_replication= cur_val;
811 }
812 
813 /**
814   Indicates whether the given table should be filtered out,
815   according to the --table=X option.
816 
817   @param log_tblname Name of table.
818 
819   @return nonzero if the table with the given name should be
820   filtered out, 0 otherwise.
821 */
shall_skip_table(const char * log_tblname)822 static bool shall_skip_table(const char *log_tblname)
823 {
824   return one_table &&
825          (log_tblname != NULL) &&
826          strcmp(log_tblname, table);
827 }
828 
829 
830 /**
831   Prints the given event in base64 format.
832 
833   The header is printed to the head cache and the body is printed to
834   the body cache of the print_event_info structure.  This allows all
835   base64 events corresponding to the same statement to be joined into
836   one BINLOG statement.
837 
838   @param[in] ev Log_event to print.
839   @param[in,out] result_file FILE to which the output will be written.
840   @param[in,out] print_event_info Parameters and context state
841   determining how to print.
842 
843   @retval ERROR_STOP An error occurred - the program should terminate.
844   @retval OK_CONTINUE No error, the program should continue.
845 */
846 static Exit_status
write_event_header_and_base64(Log_event * ev,FILE * result_file,PRINT_EVENT_INFO * print_event_info)847 write_event_header_and_base64(Log_event *ev, FILE *result_file,
848                               PRINT_EVENT_INFO *print_event_info)
849 {
850   IO_CACHE *head= &print_event_info->head_cache;
851   IO_CACHE *body= &print_event_info->body_cache;
852   DBUG_ENTER("write_event_header_and_base64");
853 
854   /* Write header and base64 output to cache */
855   if (ev->print_header(head, print_event_info, FALSE))
856     DBUG_RETURN(ERROR_STOP);
857 
858   DBUG_ASSERT(print_event_info->base64_output_mode == BASE64_OUTPUT_ALWAYS);
859 
860   if (ev->print_base64(body, print_event_info,
861                        print_event_info->base64_output_mode !=
862                        BASE64_OUTPUT_DECODE_ROWS))
863     DBUG_RETURN(ERROR_STOP);
864 
865   /* Read data from cache and write to result file */
866   if (copy_event_cache_to_file_and_reinit(head, result_file) ||
867       copy_event_cache_to_file_and_reinit(body, result_file))
868   {
869     error("Error writing event to file.");
870     DBUG_RETURN(ERROR_STOP);
871   }
872   DBUG_RETURN(OK_CONTINUE);
873 }
874 
875 
print_base64(PRINT_EVENT_INFO * print_event_info,Log_event * ev)876 static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
877 {
878   /*
879     These events must be printed in base64 format, if printed.
880     base64 format requires a FD event to be safe, so if no FD
881     event has been printed, we give an error.  Except if user
882     passed --short-form, because --short-form disables printing
883     row events.
884   */
885 
886   if (!print_event_info->printed_fd_event && !short_form &&
887       opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
888       opt_base64_output_mode != BASE64_OUTPUT_NEVER)
889   {
890     const char* type_str= ev->get_type_str();
891     error("malformed binlog: it does not contain any "
892             "Format_description_log_event. Found a %s event, which "
893             "is not safe to process without a "
894             "Format_description_log_event.",
895             type_str);
896     return 1;
897   }
898 
899   return ev->print(result_file, print_event_info);
900 }
901 
902 
print_row_event(PRINT_EVENT_INFO * print_event_info,Log_event * ev,ulonglong table_id,bool is_stmt_end)903 static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
904                             ulonglong table_id, bool is_stmt_end)
905 {
906   Table_map_log_event *ignored_map=
907     print_event_info->m_table_map_ignored.get_table(table_id);
908   bool skip_event= (ignored_map != NULL);
909   char ll_buff[21];
910   bool result= 0;
911 
912   if (opt_flashback)
913   {
914     Rows_log_event *e= (Rows_log_event*) ev;
915     // The last Row_log_event will be the first event in Flashback
916     if (is_stmt_end)
917       e->clear_flags(Rows_log_event::STMT_END_F);
918     // The first Row_log_event will be the last event in Flashback
919     if (events_in_stmt.elements == 0)
920       e->set_flags(Rows_log_event::STMT_END_F);
921     // Update the temp_buf
922     e->update_flags();
923 
924     if (insert_dynamic(&events_in_stmt, (uchar *) &ev))
925     {
926       error("Out of memory: can't allocate memory to store the flashback events.");
927       exit(1);
928     }
929   }
930 
931   /*
932      end of statement check:
933        i) destroy/free ignored maps
934       ii) if skip event
935             a) since we are skipping the last event,
936                append END-MARKER(') to body cache (if required)
937 
938             b) flush cache now
939    */
940   if (is_stmt_end)
941   {
942     /*
943       Now is safe to clear ignored map (clear_tables will also
944       delete original table map events stored in the map).
945     */
946     if (print_event_info->m_table_map_ignored.count() > 0)
947       print_event_info->m_table_map_ignored.clear_tables();
948 
949     /*
950       If there is a kept Annotate event and all corresponding
951       rbr-events were filtered away, the Annotate event was not
952       freed and it is just the time to do it.
953     */
954     free_annotate_event();
955 
956     /*
957        One needs to take into account an event that gets
958        filtered but was last event in the statement. If this is
959        the case, previous rows events that were written into
960        IO_CACHEs still need to be copied from cache to
961        result_file (as it would happen in ev->print(...) if
962        event was not skipped).
963     */
964     if (skip_event)
965     {
966       // append END-MARKER(') with delimiter
967       IO_CACHE *const body_cache= &print_event_info->body_cache;
968       if (my_b_tell(body_cache))
969         my_b_printf(body_cache, "'%s\n", print_event_info->delimiter);
970 
971       // flush cache
972       if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
973                                                result_file) ||
974            copy_event_cache_to_file_and_reinit(&print_event_info->body_cache,
975                                                result_file) ||
976            copy_event_cache_to_file_and_reinit(&print_event_info->tail_cache,
977                                                result_file)))
978         return 1;
979     }
980   }
981 
982   /* skip the event check */
983   if (skip_event)
984     return 0;
985 
986   if (!opt_flashback)
987     result= print_base64(print_event_info, ev);
988   else
989   {
990     if (is_stmt_end)
991     {
992       Log_event *e= NULL;
993 
994       // Print the row_event from the last one to the first one
995       for (uint i= events_in_stmt.elements; i > 0; --i)
996       {
997         e= *(dynamic_element(&events_in_stmt, i - 1, Log_event**));
998         result= result || print_base64(print_event_info, e);
999       }
1000       // Copy all output into the Log_event
1001       ev->output_buf.copy(e->output_buf);
1002       // Delete Log_event
1003       for (uint i= 0; i < events_in_stmt.elements-1; ++i)
1004       {
1005         e= *(dynamic_element(&events_in_stmt, i, Log_event**));
1006         delete e;
1007       }
1008       reset_dynamic(&events_in_stmt);
1009     }
1010   }
1011 
1012   if (is_stmt_end && !result)
1013   {
1014     if (print_event_info->print_row_count)
1015       fprintf(result_file, "# Number of rows: %s\n",
1016               llstr(print_event_info->row_events, ll_buff));
1017     print_event_info->row_events= 0;
1018   }
1019   return result;
1020 }
1021 
1022 
1023 /**
1024   Print the given event, and either delete it or delegate the deletion
1025   to someone else.
1026 
1027   The deletion may be delegated in two cases: (1) the event is a
1028   Format_description_log_event, and is saved in
1029   glob_description_event; (2) the event is a Create_file_log_event,
1030   and is saved in load_processor.
1031 
1032   @param[in,out] print_event_info Parameters and context state
1033   determining how to print.
1034   @param[in] ev Log_event to process.
1035   @param[in] pos Offset from beginning of binlog file.
1036   @param[in] logname Name of input binlog.
1037 
1038   @retval ERROR_STOP An error occurred - the program should terminate.
1039   @retval OK_CONTINUE No error, the program should continue.
1040   @retval OK_STOP No error, but the end of the specified range of
1041   events to process has been reached and the program should terminate.
1042 */
process_event(PRINT_EVENT_INFO * print_event_info,Log_event * ev,my_off_t pos,const char * logname)1043 Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
1044                           my_off_t pos, const char *logname)
1045 {
1046   char ll_buff[21];
1047   Log_event_type ev_type= ev->get_type_code();
1048   my_bool destroy_evt= TRUE;
1049   DBUG_ENTER("process_event");
1050   Exit_status retval= OK_CONTINUE;
1051   IO_CACHE *const head= &print_event_info->head_cache;
1052 
1053   /* Bypass flashback settings to event */
1054   ev->is_flashback= opt_flashback;
1055 #ifdef WHEN_FLASHBACK_REVIEW_READY
1056   ev->need_flashback_review= opt_flashback_review;
1057 #endif
1058 
1059   /*
1060     Format events are not concerned by --offset and such, we always need to
1061     read them to be able to process the wanted events.
1062   */
1063   if (((rec_count >= offset) &&
1064        (ev->when >= start_datetime)) ||
1065       (ev_type == FORMAT_DESCRIPTION_EVENT))
1066   {
1067     if (ev_type != FORMAT_DESCRIPTION_EVENT)
1068     {
1069       /*
1070         We have found an event after start_datetime, from now on print
1071         everything (in case the binlog has timestamps increasing and
1072         decreasing, we do this to avoid cutting the middle).
1073       */
1074       start_datetime= 0;
1075       offset= 0; // print everything and protect against cycling rec_count
1076       /*
1077         Skip events according to the --server-id flag.  However, don't
1078         skip format_description or rotate events, because they they
1079         are really "global" events that are relevant for the entire
1080         binlog, even if they have a server_id.  Also, we have to read
1081         the format_description event so that we can parse subsequent
1082         events.
1083       */
1084       if (ev_type != ROTATE_EVENT &&
1085           server_id && (server_id != ev->server_id))
1086         goto end;
1087     }
1088     if ((ev->when >= stop_datetime)
1089         || (pos >= stop_position_mot))
1090     {
1091       /* end the program */
1092       retval= OK_STOP;
1093       goto end;
1094     }
1095     if (print_row_event_positions)
1096       fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
1097 
1098     if (!opt_hexdump)
1099       print_event_info->hexdump_from= 0; /* Disabled */
1100     else
1101       print_event_info->hexdump_from= pos;
1102 
1103     print_event_info->base64_output_mode= opt_base64_output_mode;
1104 
1105     DBUG_PRINT("debug", ("event_type: %s", ev->get_type_str()));
1106 
1107     switch (ev_type) {
1108     case QUERY_EVENT:
1109     case QUERY_COMPRESSED_EVENT:
1110     {
1111       Query_log_event *qe= (Query_log_event*)ev;
1112       if (!qe->is_trans_keyword())
1113       {
1114         if (shall_skip_database(qe->db))
1115           goto end;
1116       }
1117       else
1118       {
1119         /*
1120           In case the event for one of these statements is obtained
1121           from binary log 5.0, make it compatible with 5.1
1122         */
1123         qe->flags|= LOG_EVENT_SUPPRESS_USE_F;
1124       }
1125       print_use_stmt(print_event_info, qe);
1126       if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1127       {
1128         if ((retval= write_event_header_and_base64(ev, result_file,
1129                                                    print_event_info)) !=
1130             OK_CONTINUE)
1131           goto end;
1132       }
1133       else
1134       {
1135         print_skip_replication_statement(print_event_info, ev);
1136         if (ev->print(result_file, print_event_info))
1137           goto err;
1138       }
1139       if (head->error == -1)
1140         goto err;
1141       break;
1142     }
1143 
1144     case CREATE_FILE_EVENT:
1145     {
1146       Create_file_log_event* ce= (Create_file_log_event*)ev;
1147       /*
1148         We test if this event has to be ignored. If yes, we don't save
1149         this event; this will have the good side-effect of ignoring all
1150         related Append_block and Exec_load.
1151         Note that Load event from 3.23 is not tested.
1152       */
1153       if (shall_skip_database(ce->db))
1154         goto end;                // Next event
1155       /*
1156 	We print the event, but with a leading '#': this is just to inform
1157 	the user of the original command; the command we want to execute
1158 	will be a derivation of this original command (we will change the
1159 	filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
1160 	below.
1161       */
1162       if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1163       {
1164         if ((retval= write_event_header_and_base64(ce, result_file,
1165                                                    print_event_info)) !=
1166             OK_CONTINUE)
1167           goto end;
1168       }
1169       else
1170       {
1171         print_skip_replication_statement(print_event_info, ev);
1172         if (ce->print(result_file, print_event_info, TRUE))
1173           goto err;
1174       }
1175       // If this binlog is not 3.23 ; why this test??
1176       if (glob_description_event->binlog_version >= 3)
1177       {
1178         /*
1179           transfer the responsibility for destroying the event to
1180           load_processor
1181         */
1182         ev= NULL;
1183         if ((retval= load_processor.process(ce)) != OK_CONTINUE)
1184           goto end;
1185       }
1186       break;
1187     }
1188 
1189     case APPEND_BLOCK_EVENT:
1190       /*
1191         Append_block_log_events can safely print themselves even if
1192         the subsequent call load_processor.process fails, because the
1193         output of Append_block_log_event::print is only a comment.
1194       */
1195       if (ev->print(result_file, print_event_info))
1196         goto err;
1197       if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
1198           OK_CONTINUE)
1199         goto end;
1200       break;
1201 
1202     case EXEC_LOAD_EVENT:
1203     {
1204       if (ev->print(result_file, print_event_info))
1205         goto err;
1206       Execute_load_log_event *exv= (Execute_load_log_event*)ev;
1207       Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
1208       /*
1209 	if ce is 0, it probably means that we have not seen the Create_file
1210 	event (a bad binlog, or most probably --start-position is after the
1211 	Create_file event). Print a warning comment.
1212       */
1213       if (ce)
1214       {
1215         bool error;
1216         /*
1217           We must not convert earlier, since the file is used by
1218           my_open() in Load_log_processor::append().
1219         */
1220         convert_path_to_forward_slashes((char*) ce->fname);
1221 	error= ce->print(result_file, print_event_info, TRUE);
1222 	my_free((void*)ce->fname);
1223 	delete ce;
1224         if (error)
1225           goto err;
1226       }
1227       else
1228         warning("Ignoring Execute_load_log_event as there is no "
1229                 "Create_file event for file_id: %u", exv->file_id);
1230       break;
1231     }
1232     case FORMAT_DESCRIPTION_EVENT:
1233       delete glob_description_event;
1234       glob_description_event= (Format_description_log_event*) ev;
1235       destroy_evt= 0;
1236       print_event_info->common_header_len=
1237         glob_description_event->common_header_len;
1238       if (ev->print(result_file, print_event_info))
1239         goto err;
1240       if (!remote_opt)
1241       {
1242         ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
1243       }
1244       else
1245       {
1246         /*
1247           disassociate but not free dump_remote_log_entries time memory
1248         */
1249         ev->temp_buf= 0;
1250       }
1251       /*
1252         We don't want this event to be deleted now, so let's hide it (I
1253         (Guilhem) should later see if this triggers a non-serious Valgrind
1254         error). Not serious error, because we will free description_event
1255         later.
1256       */
1257       ev= 0;
1258       if (!force_if_open_opt &&
1259           (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
1260       {
1261         error("Attempting to dump binlog '%s', which was not closed properly. "
1262               "Most probably, mysqld is still writing it, or it crashed. "
1263               "Rerun with --force-if-open to ignore this problem.", logname);
1264         DBUG_RETURN(ERROR_STOP);
1265       }
1266       break;
1267     case BEGIN_LOAD_QUERY_EVENT:
1268       if (ev->print(result_file, print_event_info))
1269         goto err;
1270       if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
1271           OK_CONTINUE)
1272         goto end;
1273       break;
1274     case EXECUTE_LOAD_QUERY_EVENT:
1275     {
1276       Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
1277       char *fname= load_processor.grab_fname(exlq->file_id);
1278 
1279       if (!shall_skip_database(exlq->db))
1280       {
1281         print_use_stmt(print_event_info, exlq);
1282         if (fname)
1283         {
1284           convert_path_to_forward_slashes(fname);
1285           print_skip_replication_statement(print_event_info, ev);
1286           if (exlq->print(result_file, print_event_info, fname))
1287           {
1288             my_free(fname);
1289             goto err;
1290           }
1291         }
1292         else
1293           warning("Ignoring Execute_load_query since there is no "
1294                   "Begin_load_query event for file_id: %u", exlq->file_id);
1295       }
1296       my_free(fname);
1297       break;
1298     }
1299     case ANNOTATE_ROWS_EVENT:
1300       if (!opt_skip_annotate_row_events)
1301       {
1302         /*
1303           We don't print Annotate event just now because all subsequent
1304           rbr-events can be filtered away. Instead we'll keep the event
1305           till it will be printed together with the first not filtered
1306           away Table map or the last rbr will be processed.
1307         */
1308         keep_annotate_event((Annotate_rows_log_event*) ev);
1309         destroy_evt= FALSE;
1310       }
1311       break;
1312     case TABLE_MAP_EVENT:
1313     {
1314       Table_map_log_event *map= ((Table_map_log_event *)ev);
1315       if (shall_skip_database(map->get_db_name()) ||
1316           shall_skip_table(map->get_table_name()))
1317       {
1318         print_event_info->m_table_map_ignored.set_table(map->get_table_id(), map);
1319         destroy_evt= FALSE;
1320         goto end;
1321       }
1322 #ifdef WHEN_FLASHBACK_REVIEW_READY
1323       /* Create review table for Flashback */
1324       if (opt_flashback_review)
1325       {
1326         // Check if the table was already created?
1327         Table_map_log_event *exist_table;
1328         exist_table= print_event_info->m_table_map.get_table(map->get_table_id());
1329 
1330         if (!exist_table)
1331         {
1332 
1333           MYSQL *conn;
1334           MYSQL_RES *res;
1335           MYSQL_ROW row;
1336           char tmp_sql[8096];
1337           int  tmp_sql_offset;
1338 
1339           conn = mysql_init(NULL);
1340           if (!mysql_real_connect(conn, host, user, pass,
1341                 map->get_db_name(), port, sock, 0))
1342           {
1343             fprintf(stderr, "%s\n", mysql_error(conn));
1344             exit(1);
1345           }
1346 
1347           if (mysql_query(conn, "SET group_concat_max_len=10000;"))
1348           {
1349             fprintf(stderr, "%s\n", mysql_error(conn));
1350             exit(1);
1351           }
1352 
1353           memset(tmp_sql, 0, sizeof(tmp_sql));
1354           sprintf(tmp_sql, " "
1355                   "SELECT Group_concat(cols) "
1356                   "FROM   (SELECT 'op_type char(1)' cols "
1357                   "  UNION ALL "
1358                   "  SELECT Concat('`', column_name, '_old` ', column_type, ' ', "
1359                   "    IF(character_set_name IS NOT NULL, "
1360                   "      Concat('character set ', character_set_name, ' '), ' '), "
1361                   "    IF(collation_name IS NOT NULL, "
1362                   "      Concat('collate ', collation_name, ' '), ' ')) cols "
1363                   "  FROM   information_schema.columns "
1364                   "  WHERE  table_schema = '%s' "
1365                   "  AND table_name = '%s' "
1366                   "  UNION ALL "
1367                   "  SELECT Concat('`', column_name, '_new` ', column_type, ' ', "
1368                   "    IF(character_set_name IS NOT NULL, "
1369                   "      Concat('character set ', character_set_name, ' '), ' '), "
1370                   "    IF(collation_name IS NOT NULL, "
1371                   "      Concat('collate ', collation_name, ' '), ' ')) cols "
1372                   "  FROM   information_schema.columns "
1373                   "  WHERE  table_schema = '%s' "
1374                   "  AND table_name = '%s') tmp;",
1375             map->get_db_name(), map->get_table_name(),
1376             map->get_db_name(), map->get_table_name());
1377 
1378           if (mysql_query(conn, tmp_sql))
1379           {
1380             fprintf(stderr, "%s\n", mysql_error(conn));
1381             exit(1);
1382           }
1383           res = mysql_use_result(conn);
1384           if ((row = mysql_fetch_row(res)) != NULL)  // only one row
1385           {
1386             if (flashback_review_dbname)
1387             {
1388               ev->set_flashback_review_dbname(flashback_review_dbname);
1389             }
1390             else
1391             {
1392               ev->set_flashback_review_dbname(map->get_db_name());
1393             }
1394             if (flashback_review_tablename)
1395             {
1396               ev->set_flashback_review_tablename(flashback_review_tablename);
1397             }
1398             else
1399             {
1400               memset(tmp_sql, 0, sizeof(tmp_sql));
1401               sprintf(tmp_sql, "__%s", map->get_table_name());
1402               ev->set_flashback_review_tablename(tmp_sql);
1403             }
1404             memset(tmp_sql, 0, sizeof(tmp_sql));
1405             tmp_sql_offset= sprintf(tmp_sql, "CREATE TABLE IF NOT EXISTS");
1406             tmp_sql_offset+= sprintf(tmp_sql + tmp_sql_offset, " `%s`.`%s` (%s) %s",
1407                                      ev->get_flashback_review_dbname(),
1408                                      ev->get_flashback_review_tablename(),
1409                                      row[0],
1410                                      print_event_info->delimiter);
1411           }
1412           fprintf(result_file, "%s\n", tmp_sql);
1413           mysql_free_result(res);
1414           mysql_close(conn);
1415         }
1416         else
1417         {
1418           char tmp_str[128];
1419 
1420           if (flashback_review_dbname)
1421             ev->set_flashback_review_dbname(flashback_review_dbname);
1422           else
1423             ev->set_flashback_review_dbname(map->get_db_name());
1424 
1425           if (flashback_review_tablename)
1426             ev->set_flashback_review_tablename(flashback_review_tablename);
1427           else
1428           {
1429             memset(tmp_str, 0, sizeof(tmp_str));
1430             sprintf(tmp_str, "__%s", map->get_table_name());
1431             ev->set_flashback_review_tablename(tmp_str);
1432           }
1433         }
1434       }
1435 #endif
1436 
1437       /*
1438         The Table map is to be printed, so it's just the time when we may
1439         print the kept Annotate event (if there is any).
1440         print_annotate_event() also deletes the kept Annotate event.
1441       */
1442       if (print_annotate_event(print_event_info))
1443         goto err;
1444 
1445       size_t len_to= 0;
1446       const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
1447       if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
1448       {
1449         error("Could not rewrite database name");
1450         goto err;
1451       }
1452       if (print_base64(print_event_info, ev))
1453         goto err;
1454       if (opt_flashback)
1455         reset_dynamic(&events_in_stmt);
1456       break;
1457     }
1458     case WRITE_ROWS_EVENT:
1459     case DELETE_ROWS_EVENT:
1460     case UPDATE_ROWS_EVENT:
1461     case WRITE_ROWS_EVENT_V1:
1462     case UPDATE_ROWS_EVENT_V1:
1463     case DELETE_ROWS_EVENT_V1:
1464     case WRITE_ROWS_COMPRESSED_EVENT:
1465     case DELETE_ROWS_COMPRESSED_EVENT:
1466     case UPDATE_ROWS_COMPRESSED_EVENT:
1467     case WRITE_ROWS_COMPRESSED_EVENT_V1:
1468     case UPDATE_ROWS_COMPRESSED_EVENT_V1:
1469     case DELETE_ROWS_COMPRESSED_EVENT_V1:
1470     {
1471       Rows_log_event *e= (Rows_log_event*) ev;
1472       bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
1473       if (!print_event_info->found_row_event)
1474       {
1475         print_event_info->found_row_event= 1;
1476         print_event_info->row_events= 0;
1477       }
1478       if (print_row_event(print_event_info, ev, e->get_table_id(),
1479                           e->get_flags(Rows_log_event::STMT_END_F)))
1480         goto err;
1481       DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end));
1482       if (is_stmt_end)
1483         print_event_info->found_row_event= 0;
1484       else if (opt_flashback)
1485         destroy_evt= FALSE;
1486       break;
1487     }
1488     case PRE_GA_WRITE_ROWS_EVENT:
1489     case PRE_GA_DELETE_ROWS_EVENT:
1490     case PRE_GA_UPDATE_ROWS_EVENT:
1491     {
1492       Old_rows_log_event *e= (Old_rows_log_event*) ev;
1493       bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
1494       if (print_row_event(print_event_info, ev, e->get_table_id(),
1495                           e->get_flags(Old_rows_log_event::STMT_END_F)))
1496         goto err;
1497       DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end));
1498       if (!is_stmt_end && opt_flashback)
1499         destroy_evt= FALSE;
1500       break;
1501     }
1502     case START_ENCRYPTION_EVENT:
1503       glob_description_event->start_decryption((Start_encryption_log_event*)ev);
1504       /* fall through */
1505     default:
1506       print_skip_replication_statement(print_event_info, ev);
1507       if (ev->print(result_file, print_event_info))
1508         goto err;
1509     }
1510   }
1511 
1512   goto end;
1513 
1514 err:
1515   retval= ERROR_STOP;
1516 end:
1517   rec_count++;
1518 
1519   DBUG_PRINT("info", ("end event processing"));
1520   /*
1521     Destroy the log_event object.
1522     MariaDB MWL#36: mainline does this:
1523       If reading from a remote host,
1524       set the temp_buf to NULL so that memory isn't freed twice.
1525     We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
1526   */
1527   if (ev)
1528   {
1529     /* Holding event output if needed */
1530     if (!ev->output_buf.is_empty())
1531     {
1532       LEX_STRING tmp_str;
1533 
1534       tmp_str.length= ev->output_buf.length();
1535       tmp_str.str=    ev->output_buf.release();
1536 
1537       if (opt_flashback)
1538       {
1539         if (ev_type == STOP_EVENT)
1540           stop_event_string.reset(tmp_str.str, tmp_str.length, tmp_str.length,
1541                                   &my_charset_bin);
1542         else
1543         {
1544           if (insert_dynamic(&binlog_events, (uchar *) &tmp_str))
1545           {
1546             error("Out of memory: can't allocate memory to store the flashback events.");
1547             exit(1);
1548           }
1549         }
1550       }
1551       else
1552       {
1553         my_fwrite(result_file, (const uchar *) tmp_str.str, tmp_str.length,
1554                   MYF(MY_NABP));
1555         fflush(result_file);
1556         my_free(tmp_str.str);
1557       }
1558     }
1559 
1560     if (destroy_evt) /* destroy it later if not set (ignored table map) */
1561       delete ev;
1562   }
1563   DBUG_PRINT("exit",("return: %d", retval));
1564   DBUG_RETURN(retval);
1565 }
1566 
1567 
1568 static struct my_option my_options[] =
1569 {
1570   {"help", '?', "Display this help and exit.",
1571    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1572   {"base64-output", OPT_BASE64_OUTPUT_MODE,
1573     /* 'unspec' is not mentioned because it is just a placeholder. */
1574    "Determine when the output statements should be base64-encoded BINLOG "
1575    "statements: 'never' doesn't print binlog row events and should not be "
1576    "used when directing output to a MariaDB master; "
1577    "'decode-rows' decodes row events into commented SQL statements if the "
1578    "--verbose option is also given; "
1579    "'auto' prints base64 only when necessary (i.e., for row-based events and "
1580    "format description events); "
1581    "'always' prints base64 whenever possible. "
1582    "--base64-output with no 'name' argument is equivalent to "
1583    "--base64-output=always and is also deprecated.  If no "
1584    "--base64-output[=name] option is given at all, the default is 'auto'.",
1585    &opt_base64_output_mode_str, &opt_base64_output_mode_str,
1586    0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1587   /*
1588     mysqlbinlog needs charsets knowledge, to be able to convert a charset
1589     number found in binlog to a charset name (to be able to print things
1590     like this:
1591     SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
1592   */
1593   {"character-sets-dir", OPT_CHARSETS_DIR,
1594    "Directory for character set files.", &charsets_dir,
1595    &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1596   {"database", 'd', "List entries for just this database (local log only).",
1597    &database, &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
1598    0, 0, 0, 0, 0, 0},
1599 #ifndef DBUG_OFF
1600   {"debug", '#', "Output debug log.", &current_dbug_option,
1601    &current_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1602 #endif
1603   {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
1604    &debug_check_flag, &debug_check_flag, 0,
1605    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1606   {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
1607    &debug_info_flag, &debug_info_flag,
1608    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1609   {"default_auth", OPT_DEFAULT_AUTH,
1610    "Default authentication client-side plugin to use.",
1611    &opt_default_auth, &opt_default_auth, 0,
1612    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1613   {"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
1614     "enabled --to-last-log and are sending the output to the same MySQL server. "
1615     "This way you could avoid an endless loop. You would also like to use it "
1616     "when restoring after a crash to avoid duplication of the statements you "
1617     "already have. NOTE: you will need a SUPER privilege to use this option.",
1618    &disable_log_bin, &disable_log_bin, 0, GET_BOOL,
1619    NO_ARG, 0, 0, 0, 0, 0, 0},
1620   {"flashback", 'B', "Flashback feature can rollback you committed data to a special time point.",
1621 #ifdef WHEN_FLASHBACK_REVIEW_READY
1622    "before Flashback feature writing a row, original row can insert to review-dbname.review-tablename,"
1623    "and mysqlbinlog will login mysql by user(-u) and password(-p) and host(-h).",
1624 #endif
1625    &opt_flashback, &opt_flashback, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1626    0, 0},
1627   {"force-if-open", 'F', "Force if binlog was not closed properly.",
1628    &force_if_open_opt, &force_if_open_opt, 0, GET_BOOL, NO_ARG,
1629    1, 0, 0, 0, 0, 0},
1630   {"force-read", 'f', "Force reading unknown binlog events.",
1631    &force_opt, &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1632    0, 0},
1633   {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
1634    &opt_hexdump, &opt_hexdump, 0, GET_BOOL, NO_ARG,
1635    0, 0, 0, 0, 0, 0},
1636   {"host", 'h', "Get the binlog from server.", &host, &host,
1637    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1638   {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
1639    &dirname_for_local_load, &dirname_for_local_load, 0,
1640    GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1641   {"offset", 'o', "Skip the first N entries.", &offset, &offset,
1642    0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1643   {"password", 'p', "Password to connect to remote server.",
1644    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1645   {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
1646     &opt_plugindir, &opt_plugindir, 0,
1647    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1648   {"port", 'P', "Port number to use for connection or 0 for default to, in "
1649    "order of preference, my.cnf, $MYSQL_TCP_PORT, "
1650 #if MYSQL_PORT_DEFAULT == 0
1651    "/etc/services, "
1652 #endif
1653    "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
1654    &port, &port, 0, GET_INT, REQUIRED_ARG,
1655    0, 0, 0, 0, 0, 0},
1656   {"protocol", OPT_MYSQL_PROTOCOL,
1657    "The protocol to use for connection (tcp, socket, pipe, memory).",
1658    0, 0, 0, GET_STR,  REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1659   {"read-from-remote-server", 'R', "Read binary logs from a MySQL server.",
1660    &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1661    0, 0},
1662   {"raw", 0, "Requires -R. Output raw binlog data instead of SQL "
1663    "statements. Output files named after server logs.",
1664    &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1665    0, 0},
1666   {"result-file", 'r', "Direct output to a given file. With --raw this is a "
1667    "prefix for the file names.",
1668    &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG,
1669    0, 0, 0, 0, 0, 0},
1670 #ifdef WHEN_FLASHBACK_REVIEW_READY
1671   {"review", opt_flashback_review, "Print review sql in output file.",
1672    &opt_flashback_review, &opt_flashback_review, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1673    0, 0},
1674   {"review-dbname", opt_flashback_flashback_review_dbname,
1675    "Writing flashback original row data into this db",
1676    &flashback_review_dbname, &flashback_review_dbname,
1677    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1678   {"review-tablename", opt_flashback_flashback_review_tablename,
1679    "Writing flashback original row data into this table",
1680    &flashback_review_tablename, &flashback_review_tablename,
1681    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1682 #endif
1683   {"print-row-count", OPT_PRINT_ROW_COUNT,
1684    "Print row counts for each row events",
1685    &print_row_count, &print_row_count, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1686    0, 0},
1687   {"print-row-event-positions", OPT_PRINT_ROW_EVENT_POSITIONS,
1688    "Print row event positions",
1689    &print_row_event_positions, &print_row_event_positions, 0, GET_BOOL,
1690    NO_ARG, 1, 0, 0, 0, 0, 0},
1691   {"server-id", 0,
1692    "Extract only binlog entries created by the server having the given id.",
1693    &server_id, &server_id, 0, GET_ULONG,
1694    REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1695   {"set-charset", OPT_SET_CHARSET,
1696    "Add 'SET NAMES character_set' to the output.", &charset,
1697    &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1698 #ifdef HAVE_SMEM
1699   {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
1700    "Base name of shared memory.", &shared_memory_base_name,
1701    &shared_memory_base_name,
1702    0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1703 #endif
1704   {"short-form", 's', "Just show regular queries: no extra info, no "
1705    "row-based events and no row counts. This is mainly for testing only, "
1706    "and should not be used to feed to the MariaDB server. "
1707    "If you want to just suppress base64-output, you can instead "
1708    "use --base64-output=never",
1709    &short_form, &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1710    0, 0},
1711   {"socket", 'S', "The socket file to use for connection.",
1712    &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1713    0, 0},
1714 #include <sslopt-longopts.h>
1715   {"start-datetime", OPT_START_DATETIME,
1716    "Start reading the binlog at first event having a datetime equal or "
1717    "posterior to the argument; the argument must be a date and time "
1718    "in the local time zone, in any format accepted by the MySQL server "
1719    "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1720    "(you should probably use quotes for your shell to set it properly).",
1721    &start_datetime_str, &start_datetime_str,
1722    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1723   {"start-position", 'j',
1724    "Start reading the binlog at position N. Applies to the first binlog "
1725    "passed on the command line.",
1726    &start_position, &start_position, 0, GET_ULL,
1727    REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1728    /*
1729      COM_BINLOG_DUMP accepts only 4 bytes for the position
1730      so remote log reading has lower limit.
1731    */
1732    (ulonglong)(0xffffffffffffffffULL), 0, 0, 0},
1733   {"stop-datetime", OPT_STOP_DATETIME,
1734    "Stop reading the binlog at first event having a datetime equal or "
1735    "posterior to the argument; the argument must be a date and time "
1736    "in the local time zone, in any format accepted by the MySQL server "
1737    "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1738    "(you should probably use quotes for your shell to set it properly).",
1739    &stop_datetime_str, &stop_datetime_str,
1740    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1741   {"stop-never", 0, "Wait for more data from the server "
1742    "instead of stopping at the end of the last log. Implies --to-last-log.",
1743    &opt_stop_never, &opt_stop_never, 0,
1744    GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1745   {"stop-never-slave-server-id", 0,
1746    "The slave server_id used for --read-from-remote-server --stop-never.",
1747    &opt_stop_never_slave_server_id, &opt_stop_never_slave_server_id, 0,
1748    GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1749   {"stop-position", OPT_STOP_POSITION,
1750    "Stop reading the binlog at position N. Applies to the last binlog "
1751    "passed on the command line.",
1752    &stop_position, &stop_position, 0, GET_ULL,
1753    REQUIRED_ARG, (longlong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1754    (ulonglong)(~(my_off_t)0), 0, 0, 0},
1755   {"table", 'T', "List entries for just this table (local log only).",
1756    &table, &table, 0, GET_STR_ALLOC, REQUIRED_ARG,
1757    0, 0, 0, 0, 0, 0},
1758   {"to-last-log", 't', "Requires -R. Will not stop at the end of the \
1759 requested binlog but rather continue printing until the end of the last \
1760 binlog of the MySQL server. If you send the output to the same MySQL server, \
1761 that may lead to an endless loop.",
1762    &to_last_remote_log, &to_last_remote_log, 0, GET_BOOL,
1763    NO_ARG, 0, 0, 0, 0, 0, 0},
1764   {"user", 'u', "Connect to the remote server as username.",
1765    &user, &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1766    0, 0},
1767   {"verbose", 'v', "Reconstruct SQL statements out of row events. "
1768                    "-v -v adds comments on column data types.",
1769    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1770   {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1771    0, 0, 0, 0, 0},
1772   {"open_files_limit", OPT_OPEN_FILES_LIMIT,
1773    "Used to reserve file descriptors for use by this program.",
1774    &open_files_limit, &open_files_limit, 0, GET_ULONG,
1775    REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1776   {"binlog-row-event-max-size", 0,
1777    "The maximum size of a row-based binary log event in bytes. Rows will be "
1778    "grouped into events smaller than this size if possible. "
1779    "This value must be a multiple of 256.",
1780    &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
1781    GET_ULONG, REQUIRED_ARG, UINT_MAX,  256, ULONG_MAX,  0, 256,  0},
1782 #ifndef DBUG_OFF
1783   {"debug-binlog-row-event-max-encoded-size", 0,
1784    "The maximum size of base64-encoded rows-event in one BINLOG pseudo-query "
1785    "instance. When the computed actual size exceeds the limit "
1786    "the BINLOG's argument string is fragmented in two.",
1787    &opt_binlog_rows_event_max_encoded_size,
1788    &opt_binlog_rows_event_max_encoded_size, 0,
1789    GET_ULONG, REQUIRED_ARG, UINT_MAX/4,  256, ULONG_MAX,  0, 256,  0},
1790 #endif
1791   {"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
1792    (uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
1793    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1794   {"rewrite-db", OPT_REWRITE_DB,
1795    "Updates to a database with a different name than the original. \
1796 Example: rewrite-db='from->to'.",
1797    0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1798   {"skip-annotate-row-events", OPT_SKIP_ANNOTATE_ROWS_EVENTS,
1799    "Don't print Annotate_rows events stored in the binary log.",
1800    (uchar**) &opt_skip_annotate_row_events,
1801    (uchar**) &opt_skip_annotate_row_events,
1802    0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1803   {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1804 };
1805 
1806 
1807 /**
1808   Auxiliary function used by error() and warning().
1809 
1810   Prints the given text (normally "WARNING: " or "ERROR: "), followed
1811   by the given vprintf-style string, followed by a newline.
1812 
1813   @param format Printf-style format string.
1814   @param args List of arguments for the format string.
1815   @param msg Text to print before the string.
1816 */
error_or_warning(const char * format,va_list args,const char * msg)1817 static void error_or_warning(const char *format, va_list args, const char *msg)
1818 {
1819   if (result_file)
1820     fflush(result_file);
1821   fprintf(stderr, "%s: ", msg);
1822   vfprintf(stderr, format, args);
1823   fprintf(stderr, "\n");
1824   fflush(stderr);
1825 }
1826 
1827 /**
1828   Prints a message to stderr, prefixed with the text "ERROR: " and
1829   suffixed with a newline.
1830 
1831   @param format Printf-style format string, followed by printf
1832   varargs.
1833 */
error(const char * format,...)1834 static void error(const char *format,...)
1835 {
1836   va_list args;
1837   va_start(args, format);
1838   error_or_warning(format, args, "ERROR");
1839   va_end(args);
1840 }
1841 
1842 
1843 /**
1844   This function is used in log_event.cc to report errors.
1845 
1846   @param format Printf-style format string, followed by printf
1847   varargs.
1848 */
sql_print_error(const char * format,...)1849 static void sql_print_error(const char *format,...)
1850 {
1851   va_list args;
1852   va_start(args, format);
1853   error_or_warning(format, args, "ERROR");
1854   va_end(args);
1855 }
1856 
1857 /**
1858   Prints a message to stderr, prefixed with the text "WARNING: " and
1859   suffixed with a newline.
1860 
1861   @param format Printf-style format string, followed by printf
1862   varargs.
1863 */
warning(const char * format,...)1864 static void warning(const char *format,...)
1865 {
1866   va_list args;
1867   va_start(args, format);
1868   error_or_warning(format, args, "WARNING");
1869   va_end(args);
1870 }
1871 
1872 /**
1873   Frees memory for global variables in this file.
1874 */
cleanup()1875 static void cleanup()
1876 {
1877   DBUG_ENTER("cleanup");
1878   my_free(pass);
1879   my_free(database);
1880   my_free(table);
1881   my_free(host);
1882   my_free(user);
1883   my_free(const_cast<char*>(dirname_for_local_load));
1884   my_free(start_datetime_str);
1885   my_free(stop_datetime_str);
1886 
1887   delete binlog_filter;
1888   delete glob_description_event;
1889   if (mysql)
1890     mysql_close(mysql);
1891   DBUG_VOID_RETURN;
1892 }
1893 
1894 
print_version()1895 static void print_version()
1896 {
1897   printf("%s Ver 3.4 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1898 }
1899 
1900 
usage()1901 static void usage()
1902 {
1903   print_version();
1904   puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
1905   printf("\
1906 Dumps a MySQL binary log in a format usable for viewing or for piping to\n\
1907 the mysql command line client.\n\n");
1908   printf("Usage: %s [options] log-files\n", my_progname);
1909   print_defaults("my",load_groups);
1910   puts("");
1911   my_print_help(my_options);
1912   my_print_variables(my_options);
1913 }
1914 
1915 
convert_str_to_timestamp(const char * str)1916 static my_time_t convert_str_to_timestamp(const char* str)
1917 {
1918   MYSQL_TIME_STATUS status;
1919   MYSQL_TIME l_time;
1920   long dummy_my_timezone;
1921   uint dummy_in_dst_time_gap;
1922 
1923   /* We require a total specification (date AND time) */
1924   if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) ||
1925       l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
1926   {
1927     error("Incorrect date and time argument: %s", str);
1928     exit(1);
1929   }
1930   /*
1931     Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1932     the next existing day, like in mysqld. Maybe this could be changed when
1933     mysqld is changed too (with its "strict" mode?).
1934   */
1935   return
1936     my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1937 }
1938 
1939 
1940 extern "C" my_bool
get_one_option(int optid,const struct my_option * opt,char * argument)1941 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1942 	       char *argument)
1943 {
1944   bool tty_password=0;
1945   switch (optid) {
1946 #ifndef DBUG_OFF
1947   case '#':
1948     if (!argument)
1949       argument= (char*) default_dbug_option;
1950     current_dbug_option= argument;
1951     DBUG_PUSH(argument);
1952     break;
1953 #endif
1954 #include <sslopt-case.h>
1955   case 'B':
1956     opt_flashback= 1;
1957     break;
1958   case 'd':
1959     one_database = 1;
1960     break;
1961   case 'p':
1962     if (argument == disabled_my_option)
1963       argument= (char*) "";                     // Don't require password
1964     if (argument)
1965     {
1966       my_free(pass);
1967       char *start=argument;
1968       pass= my_strdup(argument,MYF(MY_FAE));
1969       while (*argument) *argument++= 'x';		/* Destroy argument */
1970       if (*start)
1971         start[1]=0;				/* Cut length of argument */
1972     }
1973     else
1974       tty_password=1;
1975     break;
1976   case 'R':
1977     remote_opt= 1;
1978     break;
1979   case 'T':
1980     one_table= 1;
1981     break;
1982   case OPT_MYSQL_PROTOCOL:
1983     if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
1984                                               opt->name)) <= 0)
1985     {
1986       sf_leaking_memory= 1; /* no memory leak reports here */
1987       exit(1);
1988     }
1989     break;
1990 #ifdef WHEN_FLASHBACK_REVIEW_READY
1991   case opt_flashback_review:
1992     opt_flashback_review= 1;
1993     break;
1994 #endif
1995   case OPT_START_DATETIME:
1996     start_datetime= convert_str_to_timestamp(start_datetime_str);
1997     break;
1998   case OPT_STOP_DATETIME:
1999     stop_datetime= convert_str_to_timestamp(stop_datetime_str);
2000     break;
2001   case OPT_BASE64_OUTPUT_MODE:
2002     if (argument == NULL)
2003       opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
2004     else
2005     {
2006       int val;
2007 
2008       if ((val= find_type_with_warning(argument, &base64_output_mode_typelib,
2009                                        opt->name)) <= 0)
2010       {
2011         sf_leaking_memory= 1; /* no memory leak reports here */
2012         exit(1);
2013       }
2014       opt_base64_output_mode= (enum_base64_output_mode) (val - 1);
2015     }
2016     break;
2017   case OPT_REWRITE_DB:    // db_from->db_to
2018   {
2019     /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
2020     char* ptr;
2021     char* key= argument;  // db-from
2022     char* val;            // db-to
2023 
2024     // Where key begins
2025     while (*key && my_isspace(&my_charset_latin1, *key))
2026       key++;
2027 
2028     // Where val begins
2029     if (!(ptr= strstr(argument, "->")))
2030     {
2031       sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
2032       return 1;
2033     }
2034     val= ptr + 2;
2035     while (*val && my_isspace(&my_charset_latin1, *val))
2036       val++;
2037 
2038     // Write \0 and skip blanks at the end of key
2039     *ptr-- = 0;
2040     while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
2041       *ptr-- = 0;
2042 
2043     if (!*key)
2044     {
2045       sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
2046       return 1;
2047     }
2048 
2049     // Skip blanks at the end of val
2050     ptr= val;
2051     while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
2052       ptr++;
2053     *ptr= 0;
2054 
2055     if (!*val)
2056     {
2057       sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
2058       return 1;
2059     }
2060 
2061     binlog_filter->add_db_rewrite(key, val);
2062     break;
2063   }
2064   case OPT_PRINT_ROW_COUNT:
2065     print_row_count_used= 1;
2066     break;
2067   case OPT_PRINT_ROW_EVENT_POSITIONS:
2068     print_row_event_positions_used= 1;
2069     break;
2070   case 'v':
2071     if (argument == disabled_my_option)
2072       verbose= 0;
2073     else
2074       verbose++;
2075     break;
2076   case 'V':
2077     print_version();
2078     opt_version= 1;
2079     break;
2080   case '?':
2081     usage();
2082     opt_version= 1;
2083     break;
2084   }
2085   if (tty_password)
2086     pass= get_tty_password(NullS);
2087 
2088   return 0;
2089 }
2090 
2091 
parse_args(int * argc,char *** argv)2092 static int parse_args(int *argc, char*** argv)
2093 {
2094   int ho_error;
2095 
2096   if ((ho_error=handle_options(argc, argv, my_options, get_one_option)))
2097     exit(ho_error);
2098   if (debug_info_flag)
2099     my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
2100   else if (debug_check_flag)
2101     my_end_arg= MY_CHECK_ERROR;
2102   if (start_position > UINT_MAX32 && remote_opt)
2103   {
2104     /* Here we just emulate old behaviour of option limit handling */
2105     fprintf(stderr, "Warning: option 'start-position': unsigned value %llu "
2106             "adjusted to 4294967295 (limitation of the client-server protocol)",
2107             start_position);
2108     start_position= UINT_MAX32;
2109   }
2110   return 0;
2111 }
2112 
2113 
2114 /**
2115   Create and initialize the global mysql object, and connect to the
2116   server.
2117 
2118   @retval ERROR_STOP An error occurred - the program should terminate.
2119   @retval OK_CONTINUE No error, the program should continue.
2120 */
safe_connect()2121 static Exit_status safe_connect()
2122 {
2123   my_bool reconnect= 1;
2124   /* Close any old connections to MySQL */
2125   if (mysql)
2126     mysql_close(mysql);
2127 
2128   mysql= mysql_init(NULL);
2129 
2130   if (!mysql)
2131   {
2132     error("Failed on mysql_init.");
2133     return ERROR_STOP;
2134   }
2135 
2136 #ifdef HAVE_OPENSSL
2137   if (opt_use_ssl)
2138   {
2139     mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
2140                   opt_ssl_capath, opt_ssl_cipher);
2141     mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
2142     mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
2143   }
2144   mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
2145                 (char*)&opt_ssl_verify_server_cert);
2146 #endif /*HAVE_OPENSSL*/
2147 
2148   if (opt_plugindir && *opt_plugindir)
2149     mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
2150 
2151   if (opt_default_auth && *opt_default_auth)
2152     mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
2153 
2154   if (opt_protocol)
2155     mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
2156 #ifdef HAVE_SMEM
2157   if (shared_memory_base_name)
2158     mysql_options(mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
2159                   shared_memory_base_name);
2160 #endif
2161   mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
2162   mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
2163                  "program_name", "mysqlbinlog");
2164   if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
2165   {
2166     error("Failed on connect: %s", mysql_error(mysql));
2167     return ERROR_STOP;
2168   }
2169   mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
2170   return OK_CONTINUE;
2171 }
2172 
2173 
2174 /**
2175   High-level function for dumping a named binlog.
2176 
2177   This function calls dump_remote_log_entries() or
2178   dump_local_log_entries() to do the job.
2179 
2180   @param[in] logname Name of input binlog.
2181 
2182   @retval ERROR_STOP An error occurred - the program should terminate.
2183   @retval OK_CONTINUE No error, the program should continue.
2184   @retval OK_STOP No error, but the end of the specified range of
2185   events to process has been reached and the program should terminate.
2186 */
dump_log_entries(const char * logname)2187 static Exit_status dump_log_entries(const char* logname)
2188 {
2189   Exit_status rc;
2190   PRINT_EVENT_INFO print_event_info;
2191 
2192   if (!print_event_info.init_ok())
2193     return ERROR_STOP;
2194   /*
2195      Set safe delimiter, to dump things
2196      like CREATE PROCEDURE safely
2197   */
2198   if (!opt_raw_mode)
2199     fprintf(result_file, "DELIMITER /*!*/;\n");
2200   strmov(print_event_info.delimiter, "/*!*/;");
2201 
2202   if (short_form)
2203   {
2204     if (!print_row_event_positions_used)
2205       print_row_event_positions= 0;
2206     if (!print_row_count_used)
2207       print_row_count = 0;
2208   }
2209   if (opt_flashback)
2210   {
2211     if (!print_row_event_positions_used)
2212       print_row_event_positions= 0;
2213   }
2214 
2215   print_event_info.verbose= short_form ? 0 : verbose;
2216   print_event_info.short_form= short_form;
2217   print_event_info.print_row_count= print_row_count;
2218   print_event_info.file= result_file;
2219   fflush(result_file);
2220   rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
2221        dump_local_log_entries(&print_event_info, logname));
2222 
2223   if (rc == ERROR_STOP)
2224     return rc;
2225 
2226   /* Set delimiter back to semicolon */
2227   if (!opt_raw_mode && !opt_flashback)
2228     fprintf(result_file, "DELIMITER ;\n");
2229   strmov(print_event_info.delimiter, ";");
2230   return rc;
2231 }
2232 
2233 
2234 /**
2235   When reading a remote binlog, this function is used to grab the
2236   Format_description_log_event in the beginning of the stream.
2237 
2238   This is not as smart as check_header() (used for local log); it will
2239   not work for a binlog which mixes format. TODO: fix this.
2240 
2241   @retval ERROR_STOP An error occurred - the program should terminate.
2242   @retval OK_CONTINUE No error, the program should continue.
2243 */
check_master_version()2244 static Exit_status check_master_version()
2245 {
2246   MYSQL_RES* res = 0;
2247   MYSQL_ROW row;
2248   uint version;
2249 
2250   if (mysql_query(mysql, "SELECT VERSION()") ||
2251       !(res = mysql_store_result(mysql)))
2252   {
2253     error("Could not find server version: "
2254           "Query failed when checking master version: %s", mysql_error(mysql));
2255     return ERROR_STOP;
2256   }
2257   if (!(row = mysql_fetch_row(res)))
2258   {
2259     error("Could not find server version: "
2260           "Master returned no rows for SELECT VERSION().");
2261     goto err;
2262   }
2263 
2264   if (!(version = atoi(row[0])))
2265   {
2266     error("Could not find server version: "
2267           "Master reported NULL for the version.");
2268     goto err;
2269   }
2270   /*
2271      Make a notice to the server that this client
2272      is checksum-aware. It does not need the first fake Rotate
2273      necessary checksummed.
2274      That preference is specified below.
2275   */
2276   if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'"))
2277   {
2278     error("Could not notify master about checksum awareness."
2279           "Master returned '%s'", mysql_error(mysql));
2280     goto err;
2281   }
2282 
2283   /*
2284     Announce our capabilities to the server, so it will send us all the events
2285     that we know about.
2286   */
2287   if (mysql_query(mysql, "SET @mariadb_slave_capability="
2288                   STRINGIFY_ARG(MARIA_SLAVE_CAPABILITY_MINE)))
2289   {
2290     error("Could not inform master about capability. Master returned '%s'",
2291           mysql_error(mysql));
2292     goto err;
2293   }
2294 
2295   delete glob_description_event;
2296   glob_description_event= NULL;
2297 
2298   switch (version) {
2299   case 3:
2300     glob_description_event= new Format_description_log_event(1);
2301     break;
2302   case 4:
2303     glob_description_event= new Format_description_log_event(3);
2304     break;
2305   case 5:
2306   case 10:
2307     /*
2308       The server is soon going to send us its Format_description log
2309       event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
2310       So we first assume that this is 4.0 (which is enough to read the
2311       Format_desc event if one comes).
2312     */
2313     glob_description_event= new Format_description_log_event(3);
2314     break;
2315   default:
2316     error("Could not find server version: "
2317           "Master reported unrecognized MySQL version '%s'.", row[0]);
2318     goto err;
2319   }
2320   if (!glob_description_event || !glob_description_event->is_valid())
2321   {
2322     error("Failed creating Format_description_log_event; out of memory?");
2323     goto err;
2324   }
2325 
2326   mysql_free_result(res);
2327   return OK_CONTINUE;
2328 
2329 err:
2330   mysql_free_result(res);
2331   return ERROR_STOP;
2332 }
2333 
2334 
handle_event_text_mode(PRINT_EVENT_INFO * print_event_info,ulong * len,const char * logname,uint logname_len,my_off_t old_off)2335 static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info,
2336                                           ulong *len,
2337                                           const char* logname,
2338                                           uint logname_len, my_off_t old_off)
2339 {
2340   const char *error_msg;
2341   Log_event *ev;
2342   NET *net= &mysql->net;
2343   DBUG_ENTER("handle_event_text_mode");
2344 
2345   if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
2346   {
2347     if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1,
2348                                          &error_msg)))
2349     {
2350       error("Could not construct annotate event object: %s", error_msg);
2351       DBUG_RETURN(ERROR_STOP);
2352     }
2353   }
2354   else
2355   {
2356     if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
2357                                         *len - 1, &error_msg,
2358                                         glob_description_event,
2359                                         opt_verify_binlog_checksum)))
2360     {
2361       error("Could not construct log event object: %s", error_msg);
2362       DBUG_RETURN(ERROR_STOP);
2363     }
2364     /*
2365       If reading from a remote host, ensure the temp_buf for the
2366       Log_event class is pointing to the incoming stream.
2367     */
2368     ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
2369   }
2370 
2371   Log_event_type type= ev->get_type_code();
2372   if (glob_description_event->binlog_version >= 3 ||
2373       (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
2374   {
2375     /*
2376       If this is a Rotate event, maybe it's the end of the requested binlog;
2377       in this case we are done (stop transfer).
2378       This is suitable for binlogs, not relay logs (but for now we don't read
2379       relay logs remotely because the server is not able to do that). If one
2380       day we read relay logs remotely, then we will have a problem with the
2381       detection below: relay logs contain Rotate events which are about the
2382       binlogs, so which would trigger the end-detection below.
2383     */
2384     if (type == ROTATE_EVENT)
2385     {
2386       Rotate_log_event *rev= (Rotate_log_event *)ev;
2387       /*
2388         If this is a fake Rotate event, and not about our log, we can stop
2389         transfer. If this a real Rotate event (so it's not about our log,
2390         it's in our log describing the next log), we print it (because it's
2391         part of our log) and then we will stop when we receive the fake one
2392         soon.
2393       */
2394       if (rev->when == 0)
2395       {
2396         *len= 1; // fake Rotate, so don't increment old_off
2397         if (!to_last_remote_log)
2398         {
2399           if ((rev->ident_len != logname_len) ||
2400               memcmp(rev->new_log_ident, logname, logname_len))
2401           {
2402             delete ev;
2403             DBUG_RETURN(OK_EOF);
2404           }
2405           /*
2406             Otherwise, this is a fake Rotate for our log, at the very
2407             beginning for sure. Skip it, because it was not in the original
2408             log. If we are running with to_last_remote_log, we print it,
2409             because it serves as a useful marker between binlogs then.
2410           */
2411           delete ev;
2412           DBUG_RETURN(OK_CONTINUE);
2413         }
2414       }
2415     }
2416     else if (type == FORMAT_DESCRIPTION_EVENT)
2417     {
2418       /*
2419         This could be an fake Format_description_log_event that server
2420         (5.0+) automatically sends to a slave on connect, before sending
2421         a first event at the requested position.  If this is the case,
2422         don't increment old_off. Real Format_description_log_event always
2423         starts from BIN_LOG_HEADER_SIZE position.
2424       */
2425       if (old_off != BIN_LOG_HEADER_SIZE)
2426         *len= 1;         // fake event, don't increment old_off
2427     }
2428     Exit_status retval= process_event(print_event_info, ev, old_off, logname);
2429     if (retval != OK_CONTINUE)
2430       DBUG_RETURN(retval);
2431   }
2432   else
2433   {
2434     Load_log_event *le= (Load_log_event*)ev;
2435     const char *old_fname= le->fname;
2436     uint old_len= le->fname_len;
2437     File file;
2438     Exit_status retval;
2439     char fname[FN_REFLEN+1];
2440 
2441     if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
2442     {
2443       DBUG_RETURN(ERROR_STOP);
2444     }
2445 
2446     retval= process_event(print_event_info, ev, old_off, logname);
2447     if (retval != OK_CONTINUE)
2448     {
2449       my_close(file,MYF(MY_WME));
2450       DBUG_RETURN(retval);
2451     }
2452     retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
2453     my_close(file,MYF(MY_WME));
2454     if (retval != OK_CONTINUE)
2455       DBUG_RETURN(retval);
2456   }
2457 
2458   DBUG_RETURN(OK_CONTINUE);
2459 }
2460 
2461 
2462 static char out_file_name[FN_REFLEN + 1];
2463 
handle_event_raw_mode(PRINT_EVENT_INFO * print_event_info,ulong * len,const char * logname,uint logname_len)2464 static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
2465                                          ulong *len,
2466                                          const char* logname, uint logname_len)
2467 {
2468   const char *error_msg;
2469   const unsigned char *read_pos= mysql->net.read_pos + 1;
2470   Log_event_type type;
2471   DBUG_ENTER("handle_event_raw_mode");
2472   DBUG_ASSERT(opt_raw_mode && remote_opt);
2473 
2474   type= (Log_event_type) read_pos[EVENT_TYPE_OFFSET];
2475 
2476   if (type == HEARTBEAT_LOG_EVENT)
2477     DBUG_RETURN(OK_CONTINUE);
2478 
2479   if (type == ROTATE_EVENT || type == FORMAT_DESCRIPTION_EVENT)
2480   {
2481     Log_event *ev;
2482     if (!(ev= Log_event::read_log_event((const char*) read_pos ,
2483                                         *len - 1, &error_msg,
2484                                         glob_description_event,
2485                                         opt_verify_binlog_checksum)))
2486     {
2487       error("Could not construct %s event object: %s",
2488             type == ROTATE_EVENT ? "rotate" : "format description", error_msg);
2489       DBUG_RETURN(ERROR_STOP);
2490     }
2491     /*
2492       If reading from a remote host, ensure the temp_buf for the
2493       Log_event class is pointing to the incoming stream.
2494     */
2495     ev->register_temp_buf((char *) read_pos, FALSE);
2496 
2497     if (type == ROTATE_EVENT)
2498     {
2499       Exit_status ret_val= OK_CONTINUE;
2500       Rotate_log_event *rev= (Rotate_log_event *)ev;
2501       char *pe= strmake(out_file_name, output_prefix, sizeof(out_file_name)-1);
2502       strmake(pe, rev->new_log_ident, sizeof(out_file_name) - (pe-out_file_name));
2503 
2504       /*
2505         If this is a fake Rotate event, and not about our log, we can stop
2506         transfer. If this a real Rotate event (so it's not about our log,
2507         it's in our log describing the next log), we print it (because it's
2508         part of our log) and then we will stop when we receive the fake one
2509         soon.
2510       */
2511       if (rev->when == 0)
2512       {
2513         if (!to_last_remote_log)
2514         {
2515           if ((rev->ident_len != logname_len) ||
2516               memcmp(rev->new_log_ident, logname, logname_len))
2517           {
2518             ret_val= OK_EOF;
2519           }
2520           /*
2521             Otherwise, this is a fake Rotate for our log, at the very
2522             beginning for sure. Skip it, because it was not in the original
2523             log. If we are running with to_last_remote_log, we print it,
2524             because it serves as a useful marker between binlogs then.
2525           */
2526         }
2527         *len= 1; // fake Rotate, so don't increment old_off
2528         ev->temp_buf= 0;
2529         delete ev;
2530         DBUG_RETURN(ret_val);
2531       }
2532       ev->temp_buf= 0;
2533       delete ev;
2534     }
2535     else /* if (type == FORMAT_DESCRIPTION_EVENT) */
2536     {
2537       DBUG_ASSERT(type == FORMAT_DESCRIPTION_EVENT);
2538 
2539       if (result_file)
2540         my_fclose(result_file, MYF(0));
2541 
2542       if (!(result_file= my_fopen(out_file_name,
2543                                   O_WRONLY | O_BINARY, MYF(MY_WME))))
2544       {
2545         error("Could not create output log file: %s", out_file_name);
2546         DBUG_RETURN(ERROR_STOP);
2547       }
2548       /* TODO - add write error simulation here */
2549 
2550       if (my_fwrite(result_file, (const uchar *) BINLOG_MAGIC,
2551                     BIN_LOG_HEADER_SIZE, MYF(MY_NABP)))
2552       {
2553         error("Could not write into log file '%s'", out_file_name);
2554         DBUG_RETURN(ERROR_STOP);
2555       }
2556       print_event_info->file= result_file;
2557 
2558       delete glob_description_event;
2559       glob_description_event= (Format_description_log_event*) ev;
2560       print_event_info->common_header_len=
2561         glob_description_event->common_header_len;
2562       ev->temp_buf= 0;
2563       /* We do not want to delete the event here. */
2564     }
2565   }
2566 
2567   if (my_fwrite(result_file, read_pos, *len - 1, MYF(MY_NABP)))
2568   {
2569     error("Could not write into log file '%s'", out_file_name);
2570     DBUG_RETURN(ERROR_STOP);
2571   }
2572 
2573   DBUG_RETURN(OK_CONTINUE);
2574 }
2575 
2576 
2577 /**
2578   Requests binlog dump from a remote server and prints the events it
2579   receives.
2580 
2581   @param[in,out] print_event_info Parameters and context state
2582   determining how to print.
2583   @param[in] logname Name of input binlog.
2584 
2585   @retval ERROR_STOP An error occurred - the program should terminate.
2586   @retval OK_CONTINUE No error, the program should continue.
2587   @retval OK_STOP No error, but the end of the specified range of
2588   events to process has been reached and the program should terminate.
2589 */
dump_remote_log_entries(PRINT_EVENT_INFO * print_event_info,const char * logname)2590 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
2591                                            const char* logname)
2592 
2593 {
2594   uchar buf[128];
2595   ulong len;
2596   uint logname_len;
2597   NET* net;
2598   my_off_t old_off= start_position_mot;
2599   Exit_status retval= OK_CONTINUE;
2600   short binlog_flags = 0;
2601   ulong slave_id;
2602   DBUG_ENTER("dump_remote_log_entries");
2603 
2604   /*
2605     Even if we already read one binlog (case of >=2 binlogs on command line),
2606     we cannot re-use the same connection as before, because it is now dead
2607     (COM_BINLOG_DUMP kills the thread when it finishes).
2608   */
2609   if ((retval= safe_connect()) != OK_CONTINUE)
2610     DBUG_RETURN(retval);
2611   net= &mysql->net;
2612 
2613   if ((retval= check_master_version()) != OK_CONTINUE)
2614     DBUG_RETURN(retval);
2615 
2616   /*
2617     COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
2618     cast to uint32.
2619   */
2620   DBUG_ASSERT(start_position <= UINT_MAX32);
2621   int4store(buf, (uint32)start_position);
2622   if (!opt_skip_annotate_row_events)
2623     binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
2624   if (!opt_stop_never)
2625     binlog_flags|= BINLOG_DUMP_NON_BLOCK;
2626 
2627   int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
2628 
2629   size_t tlen = strlen(logname);
2630   if (tlen > sizeof(buf) - 10)
2631   {
2632     error("Log name too long.");
2633     DBUG_RETURN(ERROR_STOP);
2634   }
2635   logname_len = (uint) tlen;
2636   if (opt_stop_never)
2637   {
2638     DBUG_ASSERT(to_last_remote_log);
2639     slave_id= (opt_stop_never_slave_server_id == 0) ?
2640                 1 : opt_stop_never_slave_server_id;
2641   }
2642   else
2643     slave_id= 0;
2644   int4store(buf + 6, slave_id);
2645   memcpy(buf + 10, logname, logname_len);
2646   if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
2647   {
2648     error("Got fatal error sending the log dump command.");
2649     DBUG_RETURN(ERROR_STOP);
2650   }
2651 
2652   for (;;)
2653   {
2654     len= cli_safe_read(mysql);
2655     if (len == packet_error)
2656     {
2657       error("Got error reading packet from server: %s", mysql_error(mysql));
2658       DBUG_RETURN(ERROR_STOP);
2659     }
2660     if (len < 8 && net->read_pos[0] == 254)
2661       break; // end of data
2662     DBUG_PRINT("info",( "len: %lu  net->read_pos[5]: %d\n",
2663 			len, net->read_pos[5]));
2664     if (opt_raw_mode)
2665     {
2666       retval= handle_event_raw_mode(print_event_info, &len,
2667                                     logname, logname_len);
2668     }
2669     else
2670     {
2671       retval= handle_event_text_mode(print_event_info, &len,
2672                                      logname, logname_len, old_off);
2673     }
2674     if (retval != OK_CONTINUE)
2675     {
2676       if (retval == OK_EOF)
2677         break;
2678       DBUG_RETURN(retval);
2679     }
2680 
2681     /*
2682       Let's adjust offset for remote log as for local log to produce
2683       similar text and to have --stop-position to work identically.
2684     */
2685     old_off+= len-1;
2686   }
2687 
2688   DBUG_RETURN(OK_CONTINUE);
2689 }
2690 
2691 
2692 /**
2693   Reads the @c Format_description_log_event from the beginning of a
2694   local input file.
2695 
2696   The @c Format_description_log_event is only read if it is outside
2697   the range specified with @c --start-position; otherwise, it will be
2698   seen later.  If this is an old binlog, a fake @c
2699   Format_description_event is created.  This also prints a @c
2700   Format_description_log_event to the output, unless we reach the
2701   --start-position range.  In this case, it is assumed that a @c
2702   Format_description_log_event will be found when reading events the
2703   usual way.
2704 
2705   @param file The file to which a @c Format_description_log_event will
2706   be printed.
2707 
2708   @param[in,out] print_event_info Parameters and context state
2709   determining how to print.
2710 
2711   @param[in] logname Name of input binlog.
2712 
2713   @retval ERROR_STOP An error occurred - the program should terminate.
2714   @retval OK_CONTINUE No error, the program should continue.
2715   @retval OK_STOP No error, but the end of the specified range of
2716   events to process has been reached and the program should terminate.
2717 */
check_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,const char * logname)2718 static Exit_status check_header(IO_CACHE* file,
2719                                 PRINT_EVENT_INFO *print_event_info,
2720                                 const char* logname)
2721 {
2722   uchar header[BIN_LOG_HEADER_SIZE];
2723   uchar buf[PROBE_HEADER_LEN];
2724   my_off_t tmp_pos, pos;
2725   MY_STAT my_file_stat;
2726 
2727   delete glob_description_event;
2728   if (!(glob_description_event= new Format_description_log_event(3)))
2729   {
2730     error("Failed creating Format_description_log_event; out of memory?");
2731     return ERROR_STOP;
2732   }
2733 
2734   pos= my_b_tell(file);
2735 
2736   /* fstat the file to check if the file is a regular file. */
2737   if (my_fstat(file->file, &my_file_stat, MYF(0)) == -1)
2738   {
2739     error("Unable to stat the file.");
2740     return ERROR_STOP;
2741   }
2742   if ((my_file_stat.st_mode & S_IFMT) == S_IFREG)
2743     my_b_seek(file, (my_off_t)0);
2744 
2745   if (my_b_read(file, header, sizeof(header)))
2746   {
2747     error("Failed reading header; probably an empty file.");
2748     return ERROR_STOP;
2749   }
2750   if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
2751   {
2752     error("File is not a binary log file.");
2753     return ERROR_STOP;
2754   }
2755 
2756   /*
2757     Imagine we are running with --start-position=1000. We still need
2758     to know the binlog format's. So we still need to find, if there is
2759     one, the Format_desc event, or to know if this is a 3.23
2760     binlog. So we need to first read the first events of the log,
2761     those around offset 4.  Even if we are reading a 3.23 binlog from
2762     the start (no --start-position): we need to know the header length
2763     (which is 13 in 3.23, 19 in 4.x) to be able to successfully print
2764     the first event (Start_log_event_v3). So even in this case, we
2765     need to "probe" the first bytes of the log *before* we do a real
2766     read_log_event(). Because read_log_event() needs to know the
2767     header's length to work fine.
2768   */
2769   for(;;)
2770   {
2771     tmp_pos= my_b_tell(file); /* should be 4 the first time */
2772     if (my_b_read(file, buf, sizeof(buf)))
2773     {
2774       if (file->error)
2775       {
2776         error("Could not read entry at offset %llu: "
2777               "Error in log format or read error.", (ulonglong)tmp_pos);
2778         return ERROR_STOP;
2779       }
2780       /*
2781         Otherwise this is just EOF : this log currently contains 0-2
2782         events.  Maybe it's going to be filled in the next
2783         milliseconds; then we are going to have a problem if this a
2784         3.23 log (imagine we are locally reading a 3.23 binlog which
2785         is being written presently): we won't know it in
2786         read_log_event() and will fail().  Similar problems could
2787         happen with hot relay logs if --start-position is used (but a
2788         --start-position which is posterior to the current size of the log).
2789         These are rare problems anyway (reading a hot log + when we
2790         read the first events there are not all there yet + when we
2791         read a bit later there are more events + using a strange
2792         --start-position).
2793       */
2794       break;
2795     }
2796     else
2797     {
2798       DBUG_PRINT("info",("buf[EVENT_TYPE_OFFSET=%d]=%d",
2799                          EVENT_TYPE_OFFSET, buf[EVENT_TYPE_OFFSET]));
2800       /* always test for a Start_v3, even if no --start-position */
2801       if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
2802       {
2803         /* This is 3.23 or 4.x */
2804         if (uint4korr(buf + EVENT_LEN_OFFSET) <
2805             (LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
2806         {
2807           /* This is 3.23 (format 1) */
2808           delete glob_description_event;
2809           if (!(glob_description_event= new Format_description_log_event(1)))
2810           {
2811             error("Failed creating Format_description_log_event; "
2812                   "out of memory?");
2813             return ERROR_STOP;
2814           }
2815         }
2816         break;
2817       }
2818       else if (tmp_pos >= start_position)
2819         break;
2820       else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
2821       {
2822         /* This is 5.0 */
2823         Format_description_log_event *new_description_event;
2824         my_b_seek(file, tmp_pos); /* seek back to event's start */
2825         if (!(new_description_event= (Format_description_log_event*)
2826               Log_event::read_log_event(file, glob_description_event,
2827                                         opt_verify_binlog_checksum)))
2828           /* EOF can't be hit here normally, so it's a real error */
2829         {
2830           error("Could not read a Format_description_log_event event at "
2831                 "offset %llu; this could be a log format error or read error.",
2832                 (ulonglong)tmp_pos);
2833           return ERROR_STOP;
2834         }
2835         if (opt_base64_output_mode == BASE64_OUTPUT_AUTO
2836             || opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
2837         {
2838           /*
2839             process_event will delete *description_event and set it to
2840             the new one, so we should not do it ourselves in this
2841             case.
2842           */
2843           Exit_status retval= process_event(print_event_info,
2844                                             new_description_event, tmp_pos,
2845                                             logname);
2846           if (retval != OK_CONTINUE)
2847             return retval;
2848         }
2849         else
2850         {
2851           delete glob_description_event;
2852           glob_description_event= new_description_event;
2853         }
2854         DBUG_PRINT("info",("Setting description_event"));
2855       }
2856       else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
2857       {
2858         Log_event *ev;
2859         my_b_seek(file, tmp_pos); /* seek back to event's start */
2860         if (!(ev= Log_event::read_log_event(file, glob_description_event,
2861                                             opt_verify_binlog_checksum)))
2862         {
2863           /* EOF can't be hit here normally, so it's a real error */
2864           error("Could not read a Rotate_log_event event at offset %llu;"
2865                 " this could be a log format error or read error.",
2866                 (ulonglong)tmp_pos);
2867           return ERROR_STOP;
2868         }
2869         delete ev;
2870       }
2871       else
2872         break;
2873     }
2874   }
2875   my_b_seek(file, pos);
2876   return OK_CONTINUE;
2877 }
2878 
2879 
2880 /**
2881   Reads a local binlog and prints the events it sees.
2882 
2883   @param[in] logname Name of input binlog.
2884 
2885   @param[in,out] print_event_info Parameters and context state
2886   determining how to print.
2887 
2888   @retval ERROR_STOP An error occurred - the program should terminate.
2889   @retval OK_CONTINUE No error, the program should continue.
2890   @retval OK_STOP No error, but the end of the specified range of
2891   events to process has been reached and the program should terminate.
2892 */
dump_local_log_entries(PRINT_EVENT_INFO * print_event_info,const char * logname)2893 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
2894                                           const char* logname)
2895 {
2896   File fd = -1;
2897   IO_CACHE cache,*file= &cache;
2898   uchar tmp_buff[BIN_LOG_HEADER_SIZE];
2899   Exit_status retval= OK_CONTINUE;
2900 
2901   if (logname && strcmp(logname, "-") != 0)
2902   {
2903     /* read from normal file */
2904     if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
2905       return ERROR_STOP;
2906     if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
2907 		      MYF(MY_WME | MY_NABP)))
2908     {
2909       my_close(fd, MYF(MY_WME));
2910       return ERROR_STOP;
2911     }
2912     if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2913       goto end;
2914   }
2915   else
2916   {
2917     /* read from stdin */
2918     /*
2919       Windows opens stdin in text mode by default. Certain characters
2920       such as CTRL-Z are interpreted as events and the read() method
2921       will stop. CTRL-Z is the EOF marker in Windows. to get past this
2922       you have to open stdin in binary mode. Setmode() is used to set
2923       stdin in binary mode. Errors on setting this mode result in
2924       halting the function and printing an error message to stderr.
2925     */
2926 #if defined (__WIN__) || defined(_WIN64)
2927     if (_setmode(fileno(stdin), O_BINARY) == -1)
2928     {
2929       error("Could not set binary mode on stdin.");
2930       return ERROR_STOP;
2931     }
2932 #endif
2933     if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
2934 		      0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
2935     {
2936       error("Failed to init IO cache.");
2937       return ERROR_STOP;
2938     }
2939     if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2940       goto end;
2941     if (start_position)
2942     {
2943       /* skip 'start_position' characters from stdin */
2944       uchar buff[IO_SIZE];
2945       my_off_t length,tmp;
2946       for (length= start_position_mot ; length > 0 ; length-=tmp)
2947       {
2948 	tmp= MY_MIN(length,sizeof(buff));
2949 	if (my_b_read(file, buff, (uint) tmp))
2950         {
2951           error("Failed reading from file.");
2952           goto err;
2953         }
2954       }
2955     }
2956   }
2957 
2958   if (!glob_description_event || !glob_description_event->is_valid())
2959   {
2960     error("Invalid Format_description log event; could be out of memory.");
2961     goto err;
2962   }
2963 
2964   if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
2965   {
2966     error("Failed reading from file.");
2967     goto err;
2968   }
2969   for (;;)
2970   {
2971     char llbuff[21];
2972     my_off_t old_off = my_b_tell(file);
2973 
2974     Log_event* ev = Log_event::read_log_event(file, glob_description_event,
2975                                               opt_verify_binlog_checksum);
2976     if (!ev)
2977     {
2978       /*
2979         if binlog wasn't closed properly ("in use" flag is set) don't complain
2980         about a corruption, but treat it as EOF and move to the next binlog.
2981       */
2982       if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
2983         file->error= 0;
2984       else if (file->error)
2985       {
2986         error("Could not read entry at offset %s: "
2987               "Error in log format or read error.",
2988               llstr(old_off,llbuff));
2989         goto err;
2990       }
2991       // file->error == 0 means EOF, that's OK, we break in this case
2992       goto end;
2993     }
2994     if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
2995         OK_CONTINUE)
2996       goto end;
2997   }
2998 
2999   /* NOTREACHED */
3000 
3001 err:
3002   retval= ERROR_STOP;
3003 
3004 end:
3005   if (fd >= 0)
3006     my_close(fd, MYF(MY_WME));
3007   /*
3008     Since the end_io_cache() writes to the
3009     file errors may happen.
3010    */
3011   if (end_io_cache(file))
3012     retval= ERROR_STOP;
3013 
3014   return retval;
3015 }
3016 
3017 
main(int argc,char ** argv)3018 int main(int argc, char** argv)
3019 {
3020   char **defaults_argv;
3021   Exit_status retval= OK_CONTINUE;
3022   ulonglong save_stop_position;
3023   MY_INIT(argv[0]);
3024   DBUG_ENTER("main");
3025   DBUG_PROCESS(argv[0]);
3026 
3027   my_init_time(); // for time functions
3028   tzset(); // set tzname
3029 
3030   load_defaults_or_exit("my", load_groups, &argc, &argv);
3031   defaults_argv= argv;
3032 
3033   if (!(binlog_filter= new Rpl_filter))
3034   {
3035     error("Failed to create Rpl_filter");
3036     goto err;
3037   }
3038 
3039   parse_args(&argc, (char***)&argv);
3040 
3041   if (!argc || opt_version)
3042   {
3043     if (!opt_version)
3044     {
3045       usage();
3046       retval= ERROR_STOP;
3047     }
3048     goto err;
3049   }
3050 
3051   if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
3052     opt_base64_output_mode= BASE64_OUTPUT_AUTO;
3053 
3054   my_set_max_open_files(open_files_limit);
3055 
3056   if (opt_flashback)
3057   {
3058     my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024,
3059                           MYF(0));
3060     my_init_dynamic_array(&events_in_stmt, sizeof(Rows_log_event*), 1024, 1024,
3061                           MYF(0));
3062   }
3063   if (opt_stop_never)
3064     to_last_remote_log= TRUE;
3065 
3066   if (opt_raw_mode)
3067   {
3068     if (!remote_opt)
3069     {
3070       error("The --raw mode only works with --read-from-remote-server");
3071       exit(1);
3072     }
3073     if (one_database)
3074       warning("The --database option is ignored in raw mode");
3075 
3076     if (stop_position != (ulonglong)(~(my_off_t)0))
3077       warning("The --stop-position option is ignored in raw mode");
3078 
3079     if (stop_datetime != MY_TIME_T_MAX)
3080       warning("The --stop-datetime option is ignored in raw mode");
3081     result_file= 0;
3082     if (result_file_name)
3083       output_prefix= result_file_name;
3084   }
3085   else
3086   {
3087     if (result_file_name)
3088     {
3089       if (!(result_file= my_fopen(result_file_name,
3090                                   O_WRONLY | O_BINARY, MYF(MY_WME))))
3091       {
3092         error("Could not create log file '%s'", result_file_name);
3093         exit(1);
3094       }
3095     }
3096     else
3097       result_file= stdout;
3098   }
3099 
3100   MY_TMPDIR tmpdir;
3101   tmpdir.list= 0;
3102   if (!dirname_for_local_load)
3103   {
3104     if (init_tmpdir(&tmpdir, 0))
3105     {
3106       retval= ERROR_STOP;
3107       goto err;
3108     }
3109     dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
3110   }
3111 
3112   if (load_processor.init())
3113   {
3114     retval= ERROR_STOP;
3115     goto err;
3116   }
3117   if (dirname_for_local_load)
3118     load_processor.init_by_dir_name(dirname_for_local_load);
3119   else
3120     load_processor.init_by_cur_dir();
3121 
3122   if (!opt_raw_mode)
3123   {
3124     fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
3125 
3126     fprintf(result_file,
3127 	    "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
3128 
3129     if (disable_log_bin)
3130       fprintf(result_file,
3131               "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
3132 
3133     /*
3134       In mysqlbinlog|mysql, don't want mysql to be disconnected after each
3135       transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
3136     */
3137     fprintf(result_file,
3138             "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
3139             "COMPLETION_TYPE=0*/;\n");
3140 
3141     if (charset)
3142       fprintf(result_file,
3143               "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
3144               "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
3145               "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
3146               "\n/*!40101 SET NAMES %s */;\n", charset);
3147   }
3148 
3149   for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
3150        (--argc >= 0) ; )
3151   {
3152     if (argc == 0) // last log, --stop-position applies
3153       stop_position= save_stop_position;
3154     if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
3155       break;
3156 
3157     // For next log, --start-position does not apply
3158     start_position= BIN_LOG_HEADER_SIZE;
3159   }
3160 
3161   /*
3162     If enable flashback, need to print the events from the end to the
3163     beginning
3164   */
3165   if (opt_flashback && retval != ERROR_STOP)
3166   {
3167     for (uint i= binlog_events.elements; i > 0; --i)
3168     {
3169       LEX_STRING *event_str= dynamic_element(&binlog_events, i - 1,
3170                                              LEX_STRING*);
3171       fprintf(result_file, "%s", event_str->str);
3172       my_free(event_str->str);
3173     }
3174     fprintf(result_file, "COMMIT\n/*!*/;\n");
3175     delete_dynamic(&binlog_events);
3176     delete_dynamic(&events_in_stmt);
3177   }
3178 
3179   /* Set delimiter back to semicolon */
3180   if (retval != ERROR_STOP)
3181   {
3182     if (!stop_event_string.is_empty())
3183       fprintf(result_file, "%s", stop_event_string.ptr());
3184     if (!opt_raw_mode && opt_flashback)
3185       fprintf(result_file, "DELIMITER ;\n");
3186   }
3187 
3188   if (retval != ERROR_STOP && !opt_raw_mode)
3189   {
3190     /*
3191       Issue a ROLLBACK in case the last printed binlog was crashed and had half
3192       of transaction.
3193     */
3194     fprintf(result_file,
3195             "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
3196             "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
3197     if (disable_log_bin)
3198       fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
3199 
3200     if (charset)
3201       fprintf(result_file,
3202               "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
3203               "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
3204               "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
3205 
3206     fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
3207   }
3208 
3209   if (tmpdir.list)
3210     free_tmpdir(&tmpdir);
3211   if (result_file && result_file != stdout)
3212     my_fclose(result_file, MYF(0));
3213   cleanup();
3214   free_annotate_event();
3215   free_defaults(defaults_argv);
3216   my_free_open_file_info();
3217   load_processor.destroy();
3218   mysql_server_end();
3219   /* We cannot free DBUG, it is used in global destructors after exit(). */
3220   my_end(my_end_arg | MY_DONT_FREE_DBUG);
3221 
3222   exit(retval == ERROR_STOP ? 1 : 0);
3223   /* Keep compilers happy. */
3224   DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
3225 
3226 err:
3227   cleanup();
3228   free_defaults(defaults_argv);
3229   my_end(my_end_arg);
3230   exit(retval == ERROR_STOP ? 1 : 0);
3231   DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
3232 }
3233 
e_key_get_latest_version_func(uint)3234 uint e_key_get_latest_version_func(uint) { return 1; }
e_key_get_func(uint,uint,uchar *,uint *)3235 uint e_key_get_func(uint, uint, uchar*, uint*) { return 1; }
e_ctx_size_func(uint,uint)3236 uint e_ctx_size_func(uint, uint) { return 1; }
e_ctx_init_func(void *,const uchar *,uint,const uchar *,uint,int,uint,uint)3237 int e_ctx_init_func(void *, const uchar*, uint, const uchar*, uint,
3238                     int, uint, uint) { return 1; }
e_ctx_update_func(void *,const uchar *,uint,uchar *,uint *)3239 int e_ctx_update_func(void *, const uchar*, uint, uchar*, uint*) { return 1; }
e_ctx_finish_func(void *,uchar *,uint *)3240 int e_ctx_finish_func(void *, uchar*, uint*) { return 1; }
e_encrypted_length_func(uint,uint,uint)3241 uint e_encrypted_length_func(uint, uint, uint) { return 1; }
3242 
3243 struct encryption_service_st encryption_handler=
3244 {
3245   e_key_get_latest_version_func,
3246   e_key_get_func,
3247   e_ctx_size_func,
3248   e_ctx_init_func,
3249   e_ctx_update_func,
3250   e_ctx_finish_func,
3251   e_encrypted_length_func
3252 };
3253 
3254 /*
3255   We must include this here as it's compiled with different options for
3256   the server
3257 */
3258 
3259 #include "rpl_tblmap.cc"
3260 #undef TABLE
3261 #include "my_decimal.h"
3262 #include "decimal.c"
3263 #include "my_decimal.cc"
3264 #include "../sql-common/my_time.c"
3265 #include "password.c"
3266 #include "log_event.cc"
3267 #include "log_event_old.cc"
3268 #include "rpl_utility.cc"
3269 #include "sql_string.cc"
3270 #include "sql_list.cc"
3271 #include "rpl_filter.cc"
3272 #include "compat56.cc"
3273