fix seeking 2GB+ files under Windows
Replace fseek() in FIO_fwriteSparse() and FIO_fwriteSparseEnd() with macro expanding to 64-bit fseek version provided by the platform (includes fallback workaround using Win32 API).
This commit is contained in:
+30
-4
@@ -91,6 +91,32 @@ static clock_t g_time = 0;
|
|||||||
|
|
||||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1400
|
||||||
|
# define LONG_SEEK _fseeki64
|
||||||
|
#elif defined(__MINGW32__) && !defined(__STRICT_ANSI__) && !defined(__NO_MINGW_LFS) && defined(__MSVCRT__)
|
||||||
|
# define LONG_SEEK fseeko64
|
||||||
|
#elif defined(_WIN32) && !defined(__DJGPP__)
|
||||||
|
# include <windows.h>
|
||||||
|
static int LONG_SEEK(FILE* file, __int64 offset, int origin) {
|
||||||
|
LARGE_INTEGER off;
|
||||||
|
DWORD method;
|
||||||
|
off.QuadPart = offset;
|
||||||
|
if (origin == SEEK_END)
|
||||||
|
method = FILE_END;
|
||||||
|
else if (origin == SEEK_CUR)
|
||||||
|
method = FILE_CURRENT;
|
||||||
|
else
|
||||||
|
method = FILE_BEGIN;
|
||||||
|
|
||||||
|
if (SetFilePointerEx((HANDLE) _get_osfhandle(_fileno(file)), off, NULL, method))
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define LONG_SEEK fseek
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*-*************************************
|
/*-*************************************
|
||||||
* Local Parameters - Not thread safe
|
* Local Parameters - Not thread safe
|
||||||
@@ -598,7 +624,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
|||||||
|
|
||||||
/* avoid int overflow */
|
/* avoid int overflow */
|
||||||
if (storedSkips > 1 GB) {
|
if (storedSkips > 1 GB) {
|
||||||
int const seekResult = fseek(file, 1 GB, SEEK_CUR);
|
int const seekResult = LONG_SEEK(file, 1 GB, SEEK_CUR);
|
||||||
if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)");
|
if (seekResult != 0) EXM_THROW(71, "1 GB skip error (sparse file support)");
|
||||||
storedSkips -= 1 GB;
|
storedSkips -= 1 GB;
|
||||||
}
|
}
|
||||||
@@ -614,7 +640,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
|||||||
storedSkips += (unsigned)(nb0T * sizeof(size_t));
|
storedSkips += (unsigned)(nb0T * sizeof(size_t));
|
||||||
|
|
||||||
if (nb0T != seg0SizeT) { /* not all 0s */
|
if (nb0T != seg0SizeT) { /* not all 0s */
|
||||||
int const seekResult = fseek(file, storedSkips, SEEK_CUR);
|
int const seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR);
|
||||||
if (seekResult) EXM_THROW(72, "Sparse skip error ; try --no-sparse");
|
if (seekResult) EXM_THROW(72, "Sparse skip error ; try --no-sparse");
|
||||||
storedSkips = 0;
|
storedSkips = 0;
|
||||||
seg0SizeT -= nb0T;
|
seg0SizeT -= nb0T;
|
||||||
@@ -634,7 +660,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
|||||||
for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;
|
for ( ; (restPtr < restEnd) && (*restPtr == 0); restPtr++) ;
|
||||||
storedSkips += (unsigned) (restPtr - restStart);
|
storedSkips += (unsigned) (restPtr - restStart);
|
||||||
if (restPtr != restEnd) {
|
if (restPtr != restEnd) {
|
||||||
int seekResult = fseek(file, storedSkips, SEEK_CUR);
|
int seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR);
|
||||||
if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse");
|
if (seekResult) EXM_THROW(74, "Sparse skip error ; try --no-sparse");
|
||||||
storedSkips = 0;
|
storedSkips = 0;
|
||||||
{ size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file);
|
{ size_t const sizeCheck = fwrite(restPtr, 1, restEnd - restPtr, file);
|
||||||
@@ -647,7 +673,7 @@ static unsigned FIO_fwriteSparse(FILE* file, const void* buffer, size_t bufferSi
|
|||||||
static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips)
|
static void FIO_fwriteSparseEnd(FILE* file, unsigned storedSkips)
|
||||||
{
|
{
|
||||||
if (storedSkips-->0) { /* implies g_sparseFileSupport>0 */
|
if (storedSkips-->0) { /* implies g_sparseFileSupport>0 */
|
||||||
int const seekResult = fseek(file, storedSkips, SEEK_CUR);
|
int const seekResult = LONG_SEEK(file, storedSkips, SEEK_CUR);
|
||||||
if (seekResult != 0) EXM_THROW(69, "Final skip error (sparse file)\n");
|
if (seekResult != 0) EXM_THROW(69, "Final skip error (sparse file)\n");
|
||||||
{ const char lastZeroByte[1] = { 0 };
|
{ const char lastZeroByte[1] = { 0 };
|
||||||
size_t const sizeCheck = fwrite(lastZeroByte, 1, 1, file);
|
size_t const sizeCheck = fwrite(lastZeroByte, 1, 1, file);
|
||||||
|
|||||||
Reference in New Issue
Block a user