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