1 /* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
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
[])
45 azio_stream reader_handle
;
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
)
64 azio_stream writer_handle
;
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");
145 /* If we read nothing we are at the end of the file */
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;
196 azio_stream writer_handle
;
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
);
219 my_free(ptr
, MYF(0));
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
);
228 my_free(ptr
, MYF(0));
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");
240 /* If we read nothing we are at the end of the file */
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));
283 my_free(ptr
, 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 load_defaults("my", load_default_groups
, argc
, argv
);
410 handle_options(argc
, argv
, my_long_options
, get_one_option
);