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