From 5f1651ab91b1dca78cb9a0f6b6dc26103fa08da1 Mon Sep 17 00:00:00 2001 From: anders_k Date: Thu, 5 Oct 2017 18:11:03 +0000 Subject: [PATCH] Avoid using SEEK_END when possible git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6917 212acab6-be3b-0410-9dea-997c60f758d6 --- Source/build.cpp | 28 +++++----------------------- Source/script.cpp | 28 +++++++--------------------- Source/util.cpp | 37 +++++++++++++++++++++++++++++-------- Source/util.h | 4 +++- 4 files changed, 44 insertions(+), 53 deletions(-) diff --git a/Source/build.cpp b/Source/build.cpp index bd0c2f30..353f1958 100644 --- a/Source/build.cpp +++ b/Source/build.cpp @@ -3974,34 +3974,16 @@ int CEXEBuild::load_stub() } int CEXEBuild::update_exehead(const tstring& file, size_t *size/*=NULL*/) { - FILE *tmpfile = FOPEN(file.c_str(), ("rb")); - if (!tmpfile) - { - ERROR_MSG(_T("Error: opening stub \"%") NPRIs _T("\"\n"), file.c_str()); - return PS_ERROR; - } - - fseek(tmpfile, 0, SEEK_END); - size_t exehead_size = ftell(tmpfile); - - unsigned char *exehead = new unsigned char[exehead_size]; - fseek(tmpfile, 0, SEEK_SET); - if (fread(exehead, 1, exehead_size, tmpfile) != exehead_size) + unsigned long exehead_size; + unsigned char *exehead = alloc_and_read_file(file.c_str(), exehead_size); + if (!exehead) { ERROR_MSG(_T("Error: reading stub \"%") NPRIs _T("\"\n"), file.c_str()); - fclose(tmpfile); - delete [] exehead; return PS_ERROR; } - fclose(tmpfile); - update_exehead(exehead, exehead_size); - - if (size) - *size = exehead_size; - - delete [] exehead; - + if (size) *size = exehead_size; + free(exehead); return PS_OK; } diff --git a/Source/script.cpp b/Source/script.cpp index 6715db3d..fcc2e557 100644 --- a/Source/script.cpp +++ b/Source/script.cpp @@ -721,9 +721,8 @@ int CEXEBuild::LoadLicenseFile(const TCHAR *file, TCHAR** pdata, const TCHAR *cm } FILE *f=strm.GetHandle(); UINT cbBOMOffset=ftell(f); // We might be positioned after a BOM - fseek(f,0,SEEK_END); - UINT cbFileData=ftell(f)-cbBOMOffset; // Size of file in bytes! - + UINT32 cbFileSize=get_file_size32(f); + UINT cbFileData=(invalid_file_size32 == cbFileSize) ? 0 : cbFileSize - cbBOMOffset; if (!cbFileData) { warning_fl(DW_LICENSE_EMPTY, _T("%") NPRIs _T(": empty license file \"%") NPRIs _T("\"\n"),cmdname,file); @@ -1972,28 +1971,15 @@ int CEXEBuild::doCommand(int which_token, LineParser &line) int k=line.gettoken_enum(1, _T("all\0IDD_LICENSE\0IDD_DIR\0IDD_SELCOM\0IDD_INST\0IDD_INSTFILES\0IDD_UNINST\0IDD_VERIFY\0IDD_LICENSE_FSRB\0IDD_LICENSE_FSCB\0")); if (k<0) PRINTHELP(); - FILE *fui = FOPEN(line.gettoken_str(2), ("rb")); - if (!fui) { - ERROR_MSG(_T("Error: Can't open \"%") NPRIs _T("\"!\n"), line.gettoken_str(2)); - return PS_ERROR; - } - MANAGE_WITH(fui, fclose); - - fseek(fui, 0, SEEK_END); - unsigned int len = ftell(fui); - fseek(fui, 0, SEEK_SET); - LPBYTE ui = (LPBYTE) malloc(len); - if (!ui) { - ERROR_MSG(_T("Internal compiler error #12345: malloc(%d) failed\n"), len); - extern void quit(); quit(); - } - MANAGE_WITH(ui, free); - if (fread(ui, 1, len, fui) != len) { + unsigned long uifilesize; + BYTE *uifiledata = alloc_and_read_file(line.gettoken_str(2), uifilesize); + if (!uifiledata) { ERROR_MSG(_T("Error: Can't read \"%") NPRIs _T("\"!\n"), line.gettoken_str(2)); return PS_ERROR; } + MANAGE_WITH(uifiledata, free); - CResourceEditor *uire = new CResourceEditor(ui, len); + CResourceEditor *uire = new CResourceEditor(uifiledata, uifilesize); init_res_editor(); // Search for required items diff --git a/Source/util.cpp b/Source/util.cpp index 1909f21e..bfeeef63 100644 --- a/Source/util.cpp +++ b/Source/util.cpp @@ -609,16 +609,37 @@ FILE* my_fopen(const TCHAR *path, const char *mode) return f; } -unsigned long get_file_size32(FILE *f) +#if (defined(_MSC_VER) && (_MSC_VER >= 1200)) || defined(__MINGW32__) +#include +static UINT64 get_file_size64(FILE *f) { - unsigned long error = ~(0UL), result = error; + INT64 s = _filelengthi64(_fileno(f)); // Could also use _get_osfhandle+GetFileSize64 + return (INT64) -1L != s ? s : invalid_file_size64; +} +#endif + +#include +#include +UINT32 get_file_size32(FILE *f) +{ + UINT32 result = invalid_file_size32; +#if (defined(_MSC_VER) && (_MSC_VER >= 1200)) || defined(__MINGW32__) + UINT64 size64 = get_file_size64(f); + if (invalid_file_size64 != size64 && size64 <= 0xffffffffUL) + result = (UINT32) size64; +#elif _XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200112L + struct stat st; + if (0 == fstat(fileno(f), &st) && st.st_size <= (sizeof(st.st_size) >= 8 ? 0xffffffffUL : LONG_MAX)) + result = (UINT32) st.st_size; +#else long cb, restoreseek = true; fpos_t orgpos; - if (restoreseek ? 0 == fgetpos(f, &orgpos) : true) - if (0 == fseek(f, 0, SEEK_END)) - if ((cb = ftell(f)) != -1L) - if (restoreseek ? 0 == fsetpos(f, &orgpos) : true) + if (!restoreseek || 0 == fgetpos(f, &orgpos)) + if (0 == fseek(f, 0, SEEK_END)) // Not fully portable! + if ((cb = ftell(f)) != -1L) // This might not be correct for files in text mode! + if (!restoreseek || 0 == fsetpos(f, &orgpos)) result = cb; +#endif return result; } @@ -626,8 +647,8 @@ BYTE* alloc_and_read_file(FILE *f, unsigned long &size) { BYTE *result = 0, *mem = 0; if (!f) return result; - size = get_file_size32(f); - mem = (~(0UL) != size) ? (BYTE*) malloc(size) : 0; + UINT32 size32 = get_file_size32(f); + mem = (invalid_file_size32 != size32) ? (BYTE*) malloc(size = size32) : 0; if (mem) if (0 == fseek(f, 0, SEEK_SET)) if (fread(mem, 1, size, f) == size) diff --git a/Source/util.h b/Source/util.h index ee6424eb..97f03df4 100644 --- a/Source/util.h +++ b/Source/util.h @@ -273,7 +273,9 @@ int my_open(const TCHAR *pathname, int flags); FILE* my_fopen(const TCHAR *path, const char *mode); #define FOPEN(a, b) my_fopen((a), (b)) -unsigned long get_file_size32(FILE *f); +const UINT32 invalid_file_size32 = ~ (UINT32) 0; +UINT32 get_file_size32(FILE *f); +const UINT64 invalid_file_size64 = ~ (UINT64) 0; BYTE* alloc_and_read_file(FILE *f, unsigned long &size); BYTE* alloc_and_read_file(const TCHAR *filepath, unsigned long &size);