~gaul/percona-data-recovery-tool-for-innodb/strncpy-warning

« back to all changes in this revision

Viewing changes to ibd_rename_ids.c

  • Committer: aleksandr.kuzminsky
  • Date: 2012-09-05 10:09:17 UTC
  • mfrom: (68.2.1 ibd_rename_ids)
  • Revision ID: aleksandr.kuzminsky@bm-smm01-20120905100917-tp84zmco2xohdgjh
* Added tool ibd_rename_ids:


    InnoDB tablespace, table, and index id renamer

    This utility allows renaming InnoDB ids, useful for recovering ibd
    files without corresponding frm files. This initial commit requires
    innodb_file_per_table due to confusion between tablespace and table
    ids.


* Changed name of tool innochecksum to innochecksum_changer to prevent conflicts with the similar tool from MySQL distribution

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA */
 
15
 
 
16
/*
 
17
  InnoDB tablespace, table, and index id renamer.
 
18
 
 
19
  Written by Andrew Gaul <andrew@gaul.org>.
 
20
 
 
21
  Published with permission.
 
22
*/
 
23
 
 
24
/* TODO: batch IO */
 
25
/* TODO: requires innodb_file_per_table; confused tablespace and table id */
 
26
 
 
27
#include <inttypes.h>
 
28
#include <stdint.h>
 
29
#include <unistd.h>
 
30
#include "page0page.h"
 
31
#include "innochecksum.h"
 
32
 
 
33
static void usage(const char *progname)
 
34
{
 
35
  printf("InnoDB tablespace, table, and index id renamer.\n"
 
36
         "usage: %s [OPTIONS]... FILENAME\n"
 
37
         "\t-t ID\tset new tablespace id\n"
 
38
         "\t-I ID\tmap from this index id\n"
 
39
         "\t-i ID\tmap to this index id\n"
 
40
         "\t-v\tverbose output\n",
 
41
         progname);
 
42
}
 
43
 
 
44
static uint64_t dulint_to_uint64_t(dulint x)
 
45
{
 
46
  return (((uint64_t) x.high) << 32) | x.low;
 
47
}
 
48
 
 
49
static void write_page(FILE *file, fpos_t pos, const uchar *page)
 
50
{
 
51
  if (0 != fsetpos(file, &pos)) {
 
52
    perror("couldn't set a position to the start of the page");
 
53
    exit(1);
 
54
  }
 
55
  if (1 != fwrite(page, UNIV_PAGE_SIZE, 1, file)) {
 
56
    perror("couldn't update the page");
 
57
    exit(1);
 
58
  }
 
59
}
 
60
 
 
61
int main(int argc, char **argv)
 
62
{
 
63
  FILE *file = NULL;           /* input file */
 
64
  uchar *page = (uchar *)malloc(UNIV_PAGE_SIZE);  /* storage for pages read */
 
65
  int bytes;                   /* bytes read count */
 
66
  ulint page_no = 0;           /* current page number (0-based) */
 
67
  int32_t tablespace_id_to = -1;
 
68
  int64_t *index_id_from = malloc(0);
 
69
  size_t index_id_from_size = 0;
 
70
  int64_t *index_id_to = malloc(0);
 
71
  size_t index_id_to_size = 0;
 
72
  int64_t index_id;
 
73
  size_t i;
 
74
  int verbose = 0;
 
75
  int c;
 
76
  char *endptr;
 
77
  fpos_t pos;
 
78
  int retval = EXIT_FAILURE;
 
79
 
 
80
  /* parse arguments */
 
81
  while ((c = getopt(argc, argv, "hvt:I:i:")) != -1) {
 
82
    switch (c) {
 
83
    case 'v':
 
84
      verbose = 1;
 
85
      break;
 
86
    case 't':
 
87
      tablespace_id_to = strtol(optarg, &endptr, 10);
 
88
      if (*endptr != '\0') {
 
89
        fprintf(stderr, "invalid value %s\n", optarg);
 
90
        goto out;
 
91
      }
 
92
      break;
 
93
    case 'I':
 
94
      index_id = strtoll(optarg, &endptr, 10);
 
95
      if (*endptr != '\0') {
 
96
        fprintf(stderr, "invalid value %s\n", optarg);
 
97
        goto out;
 
98
      }
 
99
      index_id_from = realloc(index_id_from,
 
100
              sizeof(*index_id_from) * (index_id_from_size + 1));
 
101
      index_id_from[index_id_from_size++] = index_id;
 
102
      break;
 
103
    case 'i':
 
104
      index_id = strtoll(optarg, &endptr, 10);
 
105
      if (*endptr != '\0') {
 
106
        fprintf(stderr, "invalid value %s\n", optarg);
 
107
        goto out;
 
108
      }
 
109
      index_id_to = realloc(index_id_to,
 
110
              sizeof(*index_id_to) * (index_id_to_size + 1));
 
111
      index_id_to[index_id_to_size++] = index_id;
 
112
      break;
 
113
    case ':':
 
114
      fprintf(stderr, "option -%c requires an argument\n", optopt);
 
115
      goto out;
 
116
    case '?':
 
117
      fprintf(stderr, "unrecognized option: -%c\n", optopt);
 
118
      goto out;
 
119
    case 'h':
 
120
    default:
 
121
      usage(argv[0]);
 
122
      goto out;
 
123
    }
 
124
  }
 
125
 
 
126
  /* make sure we have the right arguments */
 
127
  if (optind >= argc) {
 
128
    usage(argv[0]);
 
129
    goto out;
 
130
  }
 
131
 
 
132
  if (index_id_from_size != index_id_to_size) {
 
133
    fprintf(stderr, "Mismatched -T and -t parameters.\n");
 
134
    goto out;
 
135
  }
 
136
 
 
137
  file = fopen(argv[optind], "r+");
 
138
  if (!file) {
 
139
    perror("error opening file");
 
140
    goto out;
 
141
  }
 
142
 
 
143
  while (!feof(file)) {
 
144
    fgetpos(file, &pos);
 
145
    bytes = fread(page, 1, UNIV_PAGE_SIZE, file);
 
146
    if (!bytes && feof(file)) break;
 
147
    if (bytes != UNIV_PAGE_SIZE) {
 
148
      fprintf(stderr,
 
149
              "bytes read (%d) does not match universal page size (%d)\n",
 
150
              bytes, UNIV_PAGE_SIZE);
 
151
      goto out;
 
152
    }
 
153
 
 
154
    uint16_t type = mach_read_from_2(page + FIL_PAGE_TYPE);
 
155
    uint32_t id = mach_read_from_4((uchar*)&tablespace_id_to);
 
156
    int modified = FALSE;
 
157
    if (type != FIL_PAGE_TYPE_ALLOCATED) {
 
158
      if (tablespace_id_to != -1) {
 
159
        if (verbose) {
 
160
          printf("changing tablespace id from %lu to %u at page %lu\n",
 
161
                 mach_read_from_4(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID),
 
162
                 tablespace_id_to, page_no);
 
163
        }
 
164
        memcpy(page + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID, &id, sizeof(id));
 
165
        modified = TRUE;
 
166
      }
 
167
    }
 
168
    if (type == FIL_PAGE_TYPE_FSP_HDR) {
 
169
      if (tablespace_id_to != -1) {
 
170
        memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE, &id, sizeof(id));
 
171
        modified = TRUE;
 
172
      }
 
173
    } else if (type == FIL_PAGE_INDEX) {
 
174
      uint64_t on_disk_index_id = dulint_to_uint64_t(mach_read_from_8(
 
175
           page + FIL_PAGE_DATA + PAGE_INDEX_ID));
 
176
      for (i = 0; i < index_id_from_size; ++i) {
 
177
        if (on_disk_index_id == index_id_from[i]) {
 
178
          if (verbose) {
 
179
            printf("changing index id from %" PRIu64 " to %" PRIi64
 
180
                   " at page %lu\n", index_id_from[i], index_id_to[i], page_no);
 
181
          }
 
182
          uint64_t index_id_to_swapped = dulint_to_uint64_t(mach_read_from_8(
 
183
                (uchar*)&index_id_to[i]));
 
184
          memcpy(page + FIL_PAGE_DATA + PAGE_INDEX_ID, &index_id_to_swapped,
 
185
                 sizeof(index_id_to_swapped));
 
186
          modified = TRUE;
 
187
          break;
 
188
        }
 
189
      }
 
190
 
 
191
      if (tablespace_id_to != -1) {
 
192
        memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_LEAF, &id,
 
193
               sizeof(id));
 
194
        memcpy(page + FIL_PAGE_DATA + FSEG_HDR_SPACE + PAGE_BTR_SEG_TOP, &id,
 
195
               sizeof(id));
 
196
        modified = TRUE;
 
197
      }
 
198
    }
 
199
 
 
200
    if (modified) {
 
201
      /* recalculate new-style checksum */
 
202
      uint32_t new_checksum = buf_calc_page_new_checksum(page);
 
203
      new_checksum = mach_read_from_4((uchar *)&new_checksum);
 
204
      memcpy(page + FIL_PAGE_SPACE_OR_CHKSUM, &new_checksum,
 
205
             sizeof(new_checksum));
 
206
 
 
207
      /* recalculate old-style checksum */
 
208
      uint32_t old_checksum = buf_calc_page_old_checksum(page);
 
209
      old_checksum = mach_read_from_4((uchar *)&old_checksum);
 
210
      memcpy(page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM, &old_checksum,
 
211
             sizeof(old_checksum));
 
212
 
 
213
      write_page(file, pos, page);
 
214
    }
 
215
 
 
216
    ++page_no;
 
217
  }
 
218
 
 
219
  retval = EXIT_SUCCESS;
 
220
 
 
221
out:
 
222
  free(index_id_from);
 
223
  free(index_id_to);
 
224
  free(page);
 
225
  if (file != NULL) {
 
226
    fclose(file);
 
227
  }
 
228
  return retval;
 
229
}