File tar4ibd_libtar-1.2.11.patch of Package xtrabackup
diff -ru a/libtar-1.2.11/lib/Makefile.in b/libtar-1.2.11/lib/Makefile.in
--- a/libtar-1.2.11/lib/Makefile.in 2002-12-16 03:02:30.000000000 +0900
+++ b/libtar-1.2.11/lib/Makefile.in 2009-08-21 18:10:44.000000000 +0900
@@ -29,7 +29,7 @@
-I${top_srcdir}/compat \
-I../listhash \
@CPPFLAGS@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
LIBOBJS = @LIBOBJS@
diff -ru a/libtar-1.2.11/lib/append.c b/libtar-1.2.11/lib/append.c
--- a/libtar-1.2.11/lib/append.c 2003-01-07 10:40:59.000000000 +0900
+++ b/libtar-1.2.11/lib/append.c 2009-07-09 17:49:26.000000000 +0900
@@ -27,6 +27,215 @@
# include <unistd.h>
#endif
+#ifdef POSIX_FADV_NORMAL
+#define USE_POSIX_FADVISE
+#endif
+
+/* all of these ripped from InnoDB code from MySQL 4.0.22 */
+#define UT_HASH_RANDOM_MASK 1463735687
+#define UT_HASH_RANDOM_MASK2 1653893711
+#define FIL_PAGE_LSN 16
+#define FIL_PAGE_FILE_FLUSH_LSN 26
+#define FIL_PAGE_OFFSET 4
+#define FIL_PAGE_DATA 38
+#define FIL_PAGE_DATA_ALIGN_32 40
+#define FIL_PAGE_END_LSN_OLD_CHKSUM 8
+#define FIL_PAGE_SPACE_OR_CHKSUM 0
+//#define UNIV_PAGE_SIZE (2 * 8192)
+#define BUF_NO_CHECKSUM_MAGIC 0xDEADBEEFUL
+
+/* command line argument to do page checks (that's it) */
+/* another argument to specify page ranges... seek to right spot and go from there */
+
+typedef unsigned long int ulint;
+typedef unsigned char byte;
+
+/* innodb function in name; modified slightly to not have the ASM version (lots of #ifs that didn't apply) */
+ulint mach_read_from_4(byte *b)
+{
+ return( ((ulint)(b[0]) << 24)
+ + ((ulint)(b[1]) << 16)
+ + ((ulint)(b[2]) << 8)
+ + (ulint)(b[3])
+ );
+}
+
+ulint
+ut_fold_ulint_pair(
+/*===============*/
+ /* out: folded value */
+ ulint n1, /* in: ulint */
+ ulint n2) /* in: ulint */
+{
+ return(((((n1 ^ n2 ^ UT_HASH_RANDOM_MASK2) << 8) + n1)
+ ^ UT_HASH_RANDOM_MASK) + n2);
+}
+
+ulint
+ut_fold_binary(
+/*===========*/
+ /* out: folded value */
+ byte* str, /* in: string of bytes */
+ ulint len) /* in: length */
+{
+ ulint i;
+ ulint fold= 0;
+
+ for (i= 0; i < len; i++)
+ {
+ fold= ut_fold_ulint_pair(fold, (ulint)(*str));
+
+ str++;
+ }
+
+ return(fold);
+}
+
+ulint
+ut_fold_binary_32(
+/*==============*/
+ byte* str,
+ ulint len)
+{
+ unsigned int* str_end = (unsigned int*) (str + len);
+ unsigned int* str_32 = (unsigned int*) str;
+ ulint fold = 0;
+
+ if (sizeof(unsigned int) != 4) {
+ fprintf(stderr,
+ "size of int is not 32bit.\n");
+ exit(-1);
+ }
+
+ while (str_32 < str_end) {
+ fold = ut_fold_ulint_pair(fold, (ulint)(*str_32));
+
+ str_32++;
+ }
+
+ return(fold);
+}
+
+ulint
+buf_calc_page_new_checksum(
+/*=======================*/
+ /* out: checksum */
+ byte* page, /* in: buffer page */
+ ulint page_size)
+{
+ ulint checksum;
+
+ /* Since the fields FIL_PAGE_FILE_FLUSH_LSN and ..._ARCH_LOG_NO
+ are written outside the buffer pool to the first pages of data
+ files, we have to skip them in the page checksum calculation.
+ We must also skip the field FIL_PAGE_SPACE_OR_CHKSUM where the
+ checksum is stored, and also the last 8 bytes of page because
+ there we store the old formula checksum. */
+
+ checksum= ut_fold_binary(page + FIL_PAGE_OFFSET,
+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ + ut_fold_binary(page + FIL_PAGE_DATA,
+ page_size - FIL_PAGE_DATA
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ checksum= checksum & 0xFFFFFFFF;
+
+ return(checksum);
+}
+
+ulint
+buf_calc_page_new_checksum_32(
+/*==========================*/
+ byte* page,
+ ulint page_size)
+{
+ ulint checksum;
+
+ checksum = ut_fold_binary(page + FIL_PAGE_OFFSET,
+ FIL_PAGE_FILE_FLUSH_LSN - FIL_PAGE_OFFSET)
+ + ut_fold_binary(page + FIL_PAGE_DATA,
+ FIL_PAGE_DATA_ALIGN_32 - FIL_PAGE_DATA)
+ + ut_fold_binary_32(page + FIL_PAGE_DATA_ALIGN_32,
+ page_size - FIL_PAGE_DATA_ALIGN_32
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+ checksum= checksum & 0xFFFFFFFF;
+
+ return(checksum);
+}
+
+ulint
+buf_calc_page_old_checksum(
+/*=======================*/
+ /* out: checksum */
+ byte* page) /* in: buffer page */
+{
+ ulint checksum;
+
+ checksum= ut_fold_binary(page, FIL_PAGE_FILE_FLUSH_LSN);
+
+ checksum= checksum & 0xFFFFFFFF;
+
+ return(checksum);
+}
+
+int
+buf_page_is_corrupted(
+/*==================*/
+ /* out: TRUE if corrupted */
+ byte* read_buf, /* in: a database page */
+ ulint page_size)
+{
+ ulint checksum;
+ ulint old_checksum;
+ ulint checksum_field;
+ ulint old_checksum_field;
+
+ if (mach_read_from_4(read_buf + FIL_PAGE_LSN + 4)
+ != mach_read_from_4(read_buf + page_size
+ - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) {
+
+ /* Stored log sequence numbers at the start and the end
+ of page do not match */
+
+ return(1);
+ }
+
+ /* If we use checksums validation, make additional check before returning
+ TRUE to ensure that the checksum is not equal to BUF_NO_CHECKSUM_MAGIC which
+ might be stored by InnoDB with checksums disabled.
+ Otherwise, skip checksum calculation and return FALSE */
+
+ old_checksum = buf_calc_page_old_checksum(read_buf);
+
+ old_checksum_field = mach_read_from_4(read_buf + page_size
+ - FIL_PAGE_END_LSN_OLD_CHKSUM);
+
+ /* There are 2 valid formulas for old_checksum_field:
+ 1. Very old versions of InnoDB only stored 8 byte lsn to the start
+ and the end of the page.
+ 2. Newer InnoDB versions store the old formula checksum there. */
+
+ if (old_checksum_field != mach_read_from_4(read_buf + FIL_PAGE_LSN)
+ && old_checksum_field != old_checksum
+ && old_checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(1);
+ }
+
+ checksum = buf_calc_page_new_checksum(read_buf, page_size);
+ checksum_field = mach_read_from_4(read_buf + FIL_PAGE_SPACE_OR_CHKSUM);
+
+ /* InnoDB versions < 4.0.14 and < 4.1.1 stored the space id
+ (always equal to 0), to FIL_PAGE_SPACE_SPACE_OR_CHKSUM */
+
+ if (checksum_field != 0 && checksum_field != checksum
+ && checksum_field != buf_calc_page_new_checksum_32(read_buf, page_size)
+ && checksum_field != BUF_NO_CHECKSUM_MAGIC) {
+
+ return(1);
+ }
+
+ return(0);
+}
struct tar_dev
{
@@ -210,10 +419,11 @@
int
tar_append_regfile(TAR *t, char *realname)
{
- char block[T_BLOCKSIZE];
+ unsigned char block[T_BLOCKSIZE * 32]; /* 16KB is MAX */
int filefd;
- int i, j;
- size_t size;
+ int j, k, n_retry;
+ size_t i, size;
+ int page_size = 4 * 1024; /* check 4K, 8K and 16K */
filefd = open(realname, O_RDONLY);
if (filefd == -1)
@@ -224,28 +434,61 @@
return -1;
}
+#ifdef USE_POSIX_FADVISE
+ posix_fadvise(filefd, 0, 0, POSIX_FADV_SEQUENTIAL);
+ posix_fadvise(filefd, 0, 0, POSIX_FADV_DONTNEED);
+#endif
+
+ n_retry = 0;
size = th_get_size(t);
- for (i = size; i > T_BLOCKSIZE; i -= T_BLOCKSIZE)
+ for (i = size; i >= page_size; i -= page_size)
{
- j = read(filefd, &block, T_BLOCKSIZE);
- if (j != T_BLOCKSIZE)
+ j = read(filefd, &block[0], page_size);
+ if (j != page_size)
{
if (j != -1)
errno = EINVAL;
return -1;
}
- if (tar_block_write(t, &block) == -1)
- return -1;
+ if (buf_page_is_corrupted(block, (ulint)page_size)) {
+ if (n_retry > 9) {
+ fprintf(stderr,
+"The file '%s' may not be InnoDB datafile or may be corrupted.\n",
+ realname);
+ errno = EIO;
+ return -1;
+ }
+
+ /* retry */
+ if (lseek(filefd, - page_size, SEEK_CUR) == -1)
+ return -1;
+
+ if (i == size
+ && page_size < 16 * 1024) {
+ page_size *= 2;
+ } else {
+ n_retry++;
+ }
+
+ i += page_size;
+
+ continue;
+ }
+ for (k = 0; k < page_size / T_BLOCKSIZE; k++)
+ if (tar_block_write(t, &block[T_BLOCKSIZE * k]) == -1)
+ return -1;
+ n_retry = 0;
}
if (i > 0)
{
- j = read(filefd, &block, i);
+ j = read(filefd, &block[0], i);
if (j == -1)
return -1;
- memset(&(block[i]), 0, T_BLOCKSIZE - i);
- if (tar_block_write(t, &block) == -1)
- return -1;
+ memset(&(block[i]), 0, T_BLOCKSIZE * 32 - i);
+ for (k = 0; k < ((j - 1) / T_BLOCKSIZE + 1); k++)
+ if (tar_block_write(t, &block[T_BLOCKSIZE * k]) == -1)
+ return -1;
}
close(filefd);
diff -ru a/libtar-1.2.11/lib/extract.c b/libtar-1.2.11/lib/extract.c
--- a/libtar-1.2.11/lib/extract.c 2003-03-03 08:58:07.000000000 +0900
+++ b/libtar-1.2.11/lib/extract.c 2009-07-09 17:49:26.000000000 +0900
@@ -158,11 +158,11 @@
tar_extract_regfile(TAR *t, char *realname)
{
mode_t mode;
- size_t size;
+ size_t i, size;
uid_t uid;
gid_t gid;
int fdout;
- int i, k;
+ int k;
char buf[T_BLOCKSIZE];
char *filename;
diff -ru a/libtar-1.2.11/lib/libtar.h b/libtar-1.2.11/lib/libtar.h
--- a/libtar-1.2.11/lib/libtar.h 2003-01-07 10:40:59.000000000 +0900
+++ b/libtar-1.2.11/lib/libtar.h 2010-02-03 17:03:22.000000000 +0900
@@ -180,7 +180,7 @@
/* decode tar header info */
#define th_get_crc(t) oct_to_int((t)->th_buf.chksum)
-#define th_get_size(t) oct_to_int((t)->th_buf.size)
+#define th_get_size(t) oct_to_longlong((t)->th_buf.size)
#define th_get_mtime(t) oct_to_int((t)->th_buf.mtime)
#define th_get_devmajor(t) oct_to_int((t)->th_buf.devmajor)
#define th_get_devminor(t) oct_to_int((t)->th_buf.devminor)
@@ -204,9 +204,9 @@
void th_set_group(TAR *t, gid_t gid);
void th_set_mode(TAR *t, mode_t fmode);
#define th_set_mtime(t, fmtime) \
- int_to_oct_nonull((fmtime), (t)->th_buf.mtime, 12)
+ int_to_oct((fmtime), (t)->th_buf.mtime, 12)
#define th_set_size(t, fsize) \
- int_to_oct_nonull((fsize), (t)->th_buf.size, 12)
+ longlong_to_oct_nonull((fsize), (t)->th_buf.size, 12)
/* encode everything at once (except the pathname and linkname) */
void th_set_from_stat(TAR *t, struct stat *s);
@@ -268,13 +268,16 @@
/* string-octal to integer conversion */
int oct_to_int(char *oct);
+long oct_to_long(char *oct);
+long long oct_to_longlong(char *oct);
/* integer to NULL-terminated string-octal conversion */
#define int_to_oct(num, oct, octlen) \
- snprintf((oct), (octlen), "%*lo ", (octlen) - 2, (unsigned long)(num))
+ snprintf((oct), (octlen), "%0*lo", (octlen) - 1, (unsigned long)(num))
/* integer to string-octal conversion, no NULL */
void int_to_oct_nonull(int num, char *oct, size_t octlen);
+void longlong_to_oct_nonull(long long num, char *oct, size_t octlen);
/***** wrapper.c **********************************************************/
diff -ru a/libtar-1.2.11/lib/util.c b/libtar-1.2.11/lib/util.c
--- a/libtar-1.2.11_orig/lib/util.c 2003-01-07 10:41:00.000000000 +0900
+++ b/libtar-1.2.11/lib/util.c 2009-07-09 17:56:31.000000000 +0900
@@ -138,6 +138,14 @@
return i;
}
+long
+oct_to_long(char *oct)
+{
+ long i;
+ sscanf(oct, "%12lo", &i);
+ return i;
+}
+
/* integer to string-octal conversion, no NULL */
void
@@ -147,4 +155,46 @@
oct[octlen - 1] = ' ';
}
+void
+longlong_to_oct_nonull(long long num, char *oct, size_t octlen)
+{
+ char buf[100];
+
+ if (num >= (long long)64 * 1024 * 1024 * 1024) {
+ oct[0] = 0x80;
+ oct[1] = 0;
+ oct[2] = 0;
+ oct[3] = 0;
+ oct[4] = (char)((num >> 56) & 0xFF);
+ oct[5] = (char)((num >> 48) & 0xFF);
+ oct[6] = (char)((num >> 40) & 0xFF);
+ oct[7] = (char)((num >> 32) & 0xFF);
+ oct[8] = (char)((num >> 24) & 0xFF);
+ oct[9] = (char)((num >> 16) & 0xFF);
+ oct[10] = (char)((num >> 8) & 0xFF);
+ oct[11] = (char)((num) & 0xFF);
+ } else {
+ snprintf(buf, octlen + 1, "%0*llo", octlen, num);
+ strncpy(oct, buf, octlen);
+ }
+}
+
+long long
+oct_to_longlong(char *oct)
+{
+ long long i;
+ if (oct[0] & 0x80) {
+ i = ((long long)((unsigned char)oct[4]) << 56)
+ | ((long long)((unsigned char)oct[5]) << 48)
+ | ((long long)((unsigned char)oct[6]) << 40)
+ | ((long long)((unsigned char)oct[7]) << 32)
+ | ((long long)((unsigned char)oct[8]) << 24)
+ | ((long long)((unsigned char)oct[9]) << 16)
+ | ((long long)((unsigned char)oct[10]) << 8)
+ | ((long long)((unsigned char)oct[11]));
+ } else {
+ sscanf(oct, "%12llo", &i);
+ }
+ return i;
+}
diff -ru a/libtar-1.2.11/libtar/Makefile.in b/libtar-1.2.11/libtar/Makefile.in
--- a/libtar-1.2.11/libtar/Makefile.in 2002-12-16 03:02:30.000000000 +0900
+++ b/libtar-1.2.11/libtar/Makefile.in 2009-08-21 18:14:52.000000000 +0900
@@ -29,7 +29,7 @@
-I${top_srcdir}/lib \
-I${top_srcdir}/compat \
@CPPFLAGS@
-CFLAGS = @CFLAGS@
+CFLAGS = @CFLAGS@ -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64
LDFLAGS = @LDFLAGS@
LIBS = @LIBS@
LIBOBJS = @LIBOBJS@
@@ -46,15 +46,15 @@
${top_srcdir}/lib/libtar.h \
../listhash/libtar_listhash.h
LIBTAR_LIBS = ../lib/libtar.a
-ALL = libtar
+ALL = tar4ibd
all: ${ALL}
.PHONY: clean distclean install
-libtar: ${LIBTAR_OBJS} ${LIBTAR_LIBS} ${LIBTAR_HDRS}
- ${CC} ${CFLAGS} ${LDFLAGS} -o libtar libtar.o ${LIBTAR_LIBS} ${LIBS}
+tar4ibd: ${LIBTAR_OBJS} ${LIBTAR_LIBS} ${LIBTAR_HDRS}
+ ${CC} ${CFLAGS} ${LDFLAGS} -o tar4ibd libtar.o ${LIBTAR_LIBS} ${LIBS}
${LIBTAR_OBJS}: ${LIBTAR_HDRS}
@@ -69,5 +69,5 @@
install: ${ALL}
${MKDIR} ${DESTDIR}${bindir}
- ${INSTALL_PROGRAM} libtar ${DESTDIR}${bindir}
+ ${INSTALL_PROGRAM} tar4ibd ${DESTDIR}${bindir}
diff -ru a/libtar-1.2.11/libtar/libtar.c b/libtar-1.2.11/libtar/libtar.c
--- a/libtar-1.2.11/libtar/libtar.c 2003-01-07 10:41:00.000000000 +0900
+++ b/libtar-1.2.11/libtar/libtar.c 2009-07-09 17:49:26.000000000 +0900
@@ -109,7 +109,7 @@
char buf[MAXPATHLEN];
libtar_listptr_t lp;
- if (tar_open(&t, tarfile,
+ if (tar_fdopen(&t, fileno(stdout), tarfile,
#ifdef HAVE_LIBZ
(use_zlib ? &gztype : NULL),
#else
@@ -164,7 +164,7 @@
TAR *t;
int i;
- if (tar_open(&t, tarfile,
+ if (tar_fdopen(&t, fileno(stdin), tarfile,
#ifdef HAVE_LIBZ
(use_zlib ? &gztype : NULL),
#else
@@ -225,7 +225,7 @@
#ifdef DEBUG
puts("opening tarfile...");
#endif
- if (tar_open(&t, tarfile,
+ if (tar_fdopen(&t, fileno(stdin), tarfile,
#ifdef HAVE_LIBZ
(use_zlib ? &gztype : NULL),
#else
@@ -264,9 +264,9 @@
void
usage()
{
- printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
+ printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t < filename.tar\n",
progname);
- printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
+ printf(" %s [-C rootdir] [-g] [-z] -c ... > filename.tar\n",
progname);
exit(-1);
}
@@ -327,7 +327,7 @@
usage();
}
- if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
+ if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 1 : 0)))
{
#ifdef DEBUG
printf("argc - optind == %d\tmode == %d\n", argc - optind,
@@ -343,15 +343,14 @@
switch (mode)
{
case MODE_EXTRACT:
- return extract(argv[optind], rootdir);
+ return extract("<stdin>", rootdir);
case MODE_CREATE:
- tarfile = argv[optind];
l = libtar_list_new(LIST_QUEUE, NULL);
- for (c = optind + 1; c < argc; c++)
+ for (c = optind; c < argc; c++)
libtar_list_add(l, argv[c]);
- return create(tarfile, rootdir, l);
+ return create("<stdout>", rootdir, l);
case MODE_LIST:
- return list(argv[optind]);
+ return list("<stdin>");
default:
break;
}