| 1996 | /************************************************************************/ |
| 1997 | |
| 1998 | CPLVirtualMem *CPLVirtualMemFileMapNew( |
| 1999 | VSILFILE *fp, vsi_l_offset nOffset, vsi_l_offset nLength, |
| 2000 | CPLVirtualMemAccessMode eAccessMode, |
| 2001 | CPLVirtualMemFreeUserData pfnFreeUserData, void *pCbkUserData) |
| 2002 | { |
| 2003 | #if SIZEOF_VOIDP == 4 |
| 2004 | if (nLength != static_cast<size_t>(nLength)) |
| 2005 | { |
| 2006 | CPLError(CE_Failure, CPLE_AppDefined, |
| 2007 | "nLength = " CPL_FRMT_GUIB |
| 2008 | " incompatible with 32 bit architecture", |
| 2009 | nLength); |
| 2010 | return nullptr; |
| 2011 | } |
| 2012 | if (nOffset + CPLGetPageSize() != |
| 2013 | static_cast<vsi_l_offset>( |
| 2014 | static_cast<off_t>(nOffset + CPLGetPageSize()))) |
| 2015 | { |
| 2016 | CPLError(CE_Failure, CPLE_AppDefined, |
| 2017 | "nOffset = " CPL_FRMT_GUIB |
| 2018 | " incompatible with 32 bit architecture", |
| 2019 | nOffset); |
| 2020 | return nullptr; |
| 2021 | } |
| 2022 | #endif |
| 2023 | |
| 2024 | int fd = static_cast<int>( |
| 2025 | reinterpret_cast<GUIntptr_t>(VSIFGetNativeFileDescriptorL(fp))); |
| 2026 | if (fd == 0) |
| 2027 | { |
| 2028 | CPLError(CE_Failure, CPLE_AppDefined, |
| 2029 | "Cannot operate on a virtual file"); |
| 2030 | return nullptr; |
| 2031 | } |
| 2032 | |
| 2033 | const off_t nAlignedOffset = |
| 2034 | static_cast<off_t>((nOffset / CPLGetPageSize()) * CPLGetPageSize()); |
| 2035 | size_t nAlignment = static_cast<size_t>(nOffset - nAlignedOffset); |
| 2036 | size_t nMappingSize = static_cast<size_t>(nLength + nAlignment); |
| 2037 | |
| 2038 | // Need to ensure that the requested extent fits into the file size |
| 2039 | // otherwise SIGBUS errors will occur when using the mapping. |
| 2040 | vsi_l_offset nCurPos = VSIFTellL(fp); |
| 2041 | if (VSIFSeekL(fp, 0, SEEK_END) != 0) |
| 2042 | return nullptr; |
| 2043 | vsi_l_offset nFileSize = VSIFTellL(fp); |
| 2044 | if (nFileSize < nOffset + nLength) |
| 2045 | { |
| 2046 | if (eAccessMode != VIRTUALMEM_READWRITE) |
| 2047 | { |
| 2048 | CPLError(CE_Failure, CPLE_AppDefined, |
| 2049 | "Trying to map an extent outside of the file"); |
| 2050 | CPL_IGNORE_RET_VAL(VSIFSeekL(fp, nCurPos, SEEK_SET)); |
| 2051 | return nullptr; |
| 2052 | } |
| 2053 | else |
| 2054 | { |
| 2055 | char ch = 0; |