Skip to content

Commit ba11dd6

Browse files
committed
MDEV-11127 : Fix innochecksum to work with large files on Windows.
- don't use stat() for file size, it doesn not handle large size use GetFileSizeEx() instead - don't use lseek(), it can't handle large files, use _lseeki64() instead. - Also, switch off OS file buffering for innochecksum on Windows, to avoid thrashing file cache.
1 parent 3321f1a commit ba11dd6

File tree

1 file changed

+50
-5
lines changed

1 file changed

+50
-5
lines changed

extra/innochecksum.cc

Lines changed: 50 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,9 @@ int main(int argc, char **argv)
243243
time_t lastt; /* last time */
244244
ulint oldcsum, oldcsumfield, csum, csumfield, crc32, logseq, logseqfield;
245245
/* ulints for checksum storage */
246-
struct stat st; /* for stat, if you couldn't guess */
247246
unsigned long long int size; /* size of file (has to be 64 bits) */
248247
ulint pages; /* number of pages in file */
249-
off_t offset= 0;
248+
unsigned long long offset= 0;
250249
int fd;
251250

252251
printf("InnoDB offline file checksum utility.\n");
@@ -269,6 +268,47 @@ int main(int argc, char **argv)
269268
goto error;
270269
}
271270

271+
#ifdef _WIN32
272+
/* Switch off OS file buffering for the file. */
273+
274+
HANDLE h = CreateFile(filename, GENERIC_READ,
275+
FILE_SHARE_READ|FILE_SHARE_WRITE, 0,
276+
OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, 0);
277+
278+
if (!h)
279+
{
280+
fprintf(stderr, "Error; cant open file\n");
281+
goto error;
282+
}
283+
284+
if (!GetFileSizeEx(h, (LARGE_INTEGER *)&size))
285+
{
286+
fprintf(stderr, "Error; GetFileSize() failed\n");
287+
goto error;
288+
}
289+
290+
fd = _open_osfhandle ((intptr_t) h, _O_RDONLY);
291+
if (fd < 0)
292+
{
293+
fprintf(stderr, "Error; _open_osfhandle() failed\n");
294+
goto error;
295+
}
296+
297+
f = _fdopen(fd, "rb");
298+
if (!f)
299+
{
300+
fprintf(stderr, "Error; fdopen() failed\n");
301+
goto error;
302+
}
303+
304+
/*
305+
Disable stdio buffering (FILE_FLAG_NO_BUFFERING requires properly IO buffers
306+
which stdio does not guarantee.
307+
*/
308+
setvbuf(f, NULL, _IONBF, 0);
309+
310+
#else
311+
struct stat st;
272312
/* stat the file to get size and page count */
273313
if (stat(filename, &st))
274314
{
@@ -279,6 +319,8 @@ int main(int argc, char **argv)
279319

280320
/* Open the file for reading */
281321
f= fopen(filename, "rb");
322+
#endif
323+
282324
if (f == NULL)
283325
{
284326
fprintf(stderr, "Error; %s cannot be opened", filename);
@@ -323,7 +365,7 @@ int main(int argc, char **argv)
323365
}
324366
else if (verbose)
325367
{
326-
printf("file %s = %llu bytes (%lu pages)...\n", filename, size, pages);
368+
printf("file %s = %llu bytes (%lu pages)...\n", filename, size, (ulong)pages);
327369
if (do_one_page)
328370
printf("InnoChecksum; checking page %lu\n", do_page);
329371
else
@@ -348,9 +390,12 @@ int main(int argc, char **argv)
348390
goto error;
349391
}
350392

351-
offset= (off_t)start_page * (off_t)physical_page_size;
352-
393+
offset= (ulonglong)start_page * (ulonglong)physical_page_size;
394+
#ifdef _WIN32
395+
if (_lseeki64(fd, offset, SEEK_SET) != offset)
396+
#else
353397
if (lseek(fd, offset, SEEK_SET) != offset)
398+
#endif
354399
{
355400
perror("Error; Unable to seek to necessary offset");
356401
goto error;

0 commit comments

Comments
 (0)