23 #include <my_getopt.h> 
   24 #include <mysql_version.h> 
   26 #define BUFFER_LEN 1024 
   27 #define ARCHIVE_ROW_HEADER_SIZE 4 
   29 #define SHOW_VERSION "0.1" 
   31 static void get_options(
int *argc,
char * * *argv);
 
   32 static void print_version(
void);
 
   33 static void usage(
void);
 
   34 static const char *opt_tmpdir;
 
   35 static const char *new_auto_increment;
 
   36 unsigned long long new_auto_increment_value;
 
   37 static const char *load_default_groups[]= { 
"archive_reader", 0 };
 
   38 static char **default_argv;
 
   39 int opt_check, opt_force, opt_quiet, opt_backup= 0, opt_extract_frm;
 
   40 int opt_autoincrement;
 
   42 int main(
int argc, 
char *argv[])
 
   48   get_options(&argc, &argv);
 
   52     printf(
"No file specified. \n");
 
   56   if (!(ret= azopen(&reader_handle, argv[0], O_RDONLY|O_BINARY)))
 
   58     printf(
"Could not open Archive file\n");
 
   62   if (opt_autoincrement)
 
   66     if (new_auto_increment_value)
 
   68       if (reader_handle.auto_increment >= new_auto_increment_value)
 
   70         printf(
"Value is lower then current value\n");
 
   76       new_auto_increment_value= reader_handle.auto_increment + 1;
 
   79     if (!(ret= azopen(&writer_handle, argv[0], O_CREAT|O_RDWR|O_BINARY)))
 
   81       printf(
"Could not open file for update: %s\n", argv[0]);
 
   85     writer_handle.auto_increment= new_auto_increment_value;
 
   87     azclose(&writer_handle);
 
   88     azflush(&reader_handle, Z_SYNC_FLUSH);
 
   91   printf(
"Version %u\n", reader_handle.version);
 
   92   if (reader_handle.version > 2)
 
   94     printf(
"\tMinor version %u\n", reader_handle.minor_version);
 
   95     printf(
"\tStart position %llu\n", (
unsigned long long)reader_handle.start);
 
   96     printf(
"\tBlock size %u\n", reader_handle.block_size);
 
   97     printf(
"\tRows %llu\n", reader_handle.rows);
 
   98     printf(
"\tAutoincrement %llu\n", reader_handle.auto_increment);
 
   99     printf(
"\tCheck Point %llu\n", reader_handle.check_point);
 
  100     printf(
"\tForced Flushes %llu\n", reader_handle.forced_flushes);
 
  101     printf(
"\tLongest Row %u\n", reader_handle.longest_row);
 
  102     printf(
"\tShortest Row %u\n", reader_handle.shortest_row);
 
  103     printf(
"\tState %s\n", ( reader_handle.dirty ? 
"dirty" : 
"clean"));
 
  104     printf(
"\tFRM stored at %u\n", reader_handle.frm_start_pos);
 
  105     printf(
"\tComment stored at %u\n", reader_handle.comment_start_pos);
 
  106     printf(
"\tData starts at %u\n", (
unsigned int)reader_handle.start);
 
  107     if (reader_handle.frm_start_pos)
 
  108       printf(
"\tFRM length %u\n", reader_handle.frm_length);
 
  109     if (reader_handle.comment_start_pos)
 
  112         (
char *) malloc(
sizeof(
char) * reader_handle.comment_length);
 
  113       azread_comment(&reader_handle, comment);
 
  114       printf(
"\tComment length %u\n\t\t%.*s\n", reader_handle.comment_length, 
 
  115              reader_handle.comment_length, comment);
 
  128     uchar size_buffer[ARCHIVE_ROW_HEADER_SIZE];
 
  132     unsigned int row_len;
 
  133     unsigned long long row_count= 0;
 
  136     while ((read= azread(&reader_handle, (uchar *)size_buffer, 
 
  137                         ARCHIVE_ROW_HEADER_SIZE, &error)))
 
  139       if (error == Z_STREAM_ERROR ||  (read && read < ARCHIVE_ROW_HEADER_SIZE))
 
  141         printf(
"Table is damaged\n");
 
  146       if (read == 0 || read != ARCHIVE_ROW_HEADER_SIZE)
 
  149       row_len=  uint4korr(size_buffer);
 
  152       if (row_len > reader_handle.longest_row)
 
  154         printf(
"Table is damaged, row %llu is invalid\n", 
 
  160       for (read= x= 0; x < row_len ; x++) 
 
  162         read+= (
unsigned int)azread(&reader_handle, &buffer, 
sizeof(
char), &error); 
 
  170         printf(
"Row length did not match row (at %llu). %u != %u \n", 
 
  171                row_count, row_len, read);
 
  178       printf(
"Table is damaged\n");
 
  183       printf(
"Found %llu rows\n", row_count);
 
  189     uchar size_buffer[ARCHIVE_ROW_HEADER_SIZE];
 
  192     unsigned int row_len;
 
  193     unsigned long long row_count= 0;
 
  198     buffer= (
char *)malloc(reader_handle.longest_row);
 
  201       printf(
"Could not allocate memory for row %llu\n", row_count);
 
  206     if (!(ret= azopen(&writer_handle, argv[1], O_CREAT|O_RDWR|O_BINARY)))
 
  208       printf(
"Could not open file for backup: %s\n", argv[1]);
 
  212     writer_handle.auto_increment= reader_handle.auto_increment;
 
  213     if (reader_handle.frm_length)
 
  216       ptr= (
char *)my_malloc(
sizeof(
char) * reader_handle.frm_length, MYF(0));
 
  217       azread_frm(&reader_handle, ptr);
 
  218       azwrite_frm(&writer_handle, ptr, reader_handle.frm_length);
 
  222     if (reader_handle.comment_length)
 
  225       ptr= (
char *)my_malloc(
sizeof(
char) * reader_handle.comment_length, MYF(0));
 
  226       azread_comment(&reader_handle, ptr);
 
  227       azwrite_comment(&writer_handle, ptr, reader_handle.comment_length);
 
  231     while ((read= azread(&reader_handle, (uchar *)size_buffer, 
 
  232                         ARCHIVE_ROW_HEADER_SIZE, &error)))
 
  234       if (error == Z_STREAM_ERROR ||  (read && read < ARCHIVE_ROW_HEADER_SIZE))
 
  236         printf(
"Table is damaged\n");
 
  241       if (read == 0 || read != ARCHIVE_ROW_HEADER_SIZE)
 
  244       row_len=  uint4korr(size_buffer);
 
  248       memcpy(buffer, size_buffer, ARCHIVE_ROW_HEADER_SIZE);
 
  250       read= (
unsigned int)azread(&reader_handle, buffer + ARCHIVE_ROW_HEADER_SIZE, 
 
  253       DBUG_ASSERT(read == row_len);
 
  255       azwrite(&writer_handle, buffer, row_len + ARCHIVE_ROW_HEADER_SIZE);
 
  260         printf(
"Row length did not match row (at %llu). %u != %u \n", 
 
  261                row_count, row_len, read);
 
  265       if (reader_handle.rows == writer_handle.rows)
 
  271     azclose(&writer_handle);
 
  278     frm_file= my_open(argv[1], O_CREAT|O_RDWR|O_BINARY, MYF(0));
 
  279     ptr= (
char *)my_malloc(
sizeof(
char) * reader_handle.frm_length, MYF(0));
 
  280     azread_frm(&reader_handle, ptr);
 
  281     my_write(frm_file, (uchar*) ptr, reader_handle.frm_length, MYF(0));
 
  282     my_close(frm_file, MYF(0));
 
  288   azclose(&reader_handle);
 
  294 get_one_option(
int optid,
 
  295                const struct my_option *opt __attribute__((unused)),
 
  310     printf(
"Not implemented yet\n");
 
  314     printf(
"Not implemented yet\n");
 
  320     printf(
"Not implemented yet\n");
 
  323     opt_autoincrement= 1;
 
  325       new_auto_increment_value= strtoull(argument, NULL, 0);
 
  327       new_auto_increment_value= 0;
 
  333     if (argument == disabled_my_option)
 
  339       DBUG_PUSH(argument ? argument : 
"d:t:o,/tmp/archive_reader.trace");
 
  346 static struct my_option my_long_options[] =
 
  349    "Make a backup of an archive table.",
 
  350    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  351   {
"check", 
'c', 
"Check table for errors.",
 
  352    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  355    "Output debug log. Often this is 'd:t:o,filename'.",
 
  356    0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
  359    "Extract the frm file.",
 
  360    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  362    "Restart with -r if there are any errors in the table.",
 
  363    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  365    "Display this help and exit.",
 
  366    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  367   {
"quick", 
'q', 
"Faster repair by not modifying the data file.",
 
  368    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  369   {
"repair", 
'r', 
"Repair a damaged Archive version 3 or above file.",
 
  370    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  371   {
"set-auto-increment", 
'A',
 
  372    "Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.",
 
  373    &new_auto_increment, &new_auto_increment,
 
  374    0, GET_ULL, OPT_ARG, 0, 0, 0, 0, 0, 0},
 
  376    "Only print errors. One can use two -s to make archive_reader very silent.",
 
  377    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  379    "Path for temporary files.",
 
  381    0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
 
  383    "Print version and exit.",
 
  384    0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
 
  385   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 
  388 static void usage(
void)
 
  391   puts(
"Copyright 2007-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
 
  392   puts(
"This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
 
  393   puts(
"Read and modify Archive files directly\n");
 
  394   printf(
"Usage: %s [OPTIONS] file_to_be_looked_at [file_for_backup]\n", my_progname);
 
  395   print_defaults(
"my", load_default_groups);
 
  396   my_print_help(my_long_options);
 
  399 static void print_version(
void)
 
  401   printf(
"%s  Ver %s Distrib %s, for %s (%s)\n", my_progname, SHOW_VERSION,
 
  402          MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
 
  405 static void get_options(
int *argc, 
char ***argv)
 
  407   if (load_defaults(
"my", load_default_groups, argc, argv))
 
  411   handle_options(argc, argv, my_long_options, get_one_option);