int VSISubFileFilesystemHandler::Stat( const char * pszFilename, VSIStatBufL * psStatBuf ) { CPLString osSubFilePath; vsi_l_offset nOff, nSize; if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) ) { errno = ENOENT; return -1; } int nResult = VSIStatL( osSubFilePath, psStatBuf ); if( nResult == 0 ) { if( nSize != 0 ) psStatBuf->st_size = (long)nSize; else psStatBuf->st_size -= (long)nOff; } return nResult; }
VSIVirtualHandle * VSISubFileFilesystemHandler::Open( const char *pszFilename, const char *pszAccess ) { CPLString osSubFilePath; vsi_l_offset nOff, nSize; if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) ) { errno = ENOENT; return NULL; } /* -------------------------------------------------------------------- */ /* Open the underlying file. */ /* -------------------------------------------------------------------- */ FILE *fp = VSIFOpenL( osSubFilePath, pszAccess ); if( fp == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Setup the file handle on this file. */ /* -------------------------------------------------------------------- */ VSISubFileHandle *poHandle = new VSISubFileHandle; poHandle->fp = fp; poHandle->nSubregionOffset = nOff; poHandle->nSubregionSize = nSize; VSIFSeekL( fp, nOff, SEEK_SET ); return poHandle; }
int VSISubFileFilesystemHandler::Stat( const char * pszFilename, VSIStatBufL * psStatBuf, int nFlags ) { if( !STARTS_WITH_CI(pszFilename, "/vsisubfile/") ) return -1; CPLString osSubFilePath; vsi_l_offset nOff = 0; vsi_l_offset nSize = 0; memset( psStatBuf, 0, sizeof(VSIStatBufL) ); if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) ) { errno = ENOENT; return -1; } const int nResult = VSIStatExL( osSubFilePath, psStatBuf, nFlags ); if( nResult == 0 ) { if( nSize != 0 ) psStatBuf->st_size = nSize; else psStatBuf->st_size -= nOff; } return nResult; }
VSIVirtualHandle * VSISubFileFilesystemHandler::Open( const char *pszFilename, const char *pszAccess ) { CPLString osSubFilePath; vsi_l_offset nOff, nSize; if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) ) { errno = ENOENT; return NULL; } /* -------------------------------------------------------------------- */ /* We can't open the containing file with "w" access, so if tht */ /* is requested use "r+" instead to update in place. */ /* -------------------------------------------------------------------- */ if( pszAccess[0] == 'w' ) pszAccess = "r+"; /* -------------------------------------------------------------------- */ /* Open the underlying file. */ /* -------------------------------------------------------------------- */ VSILFILE *fp = VSIFOpenL( osSubFilePath, pszAccess ); if( fp == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Setup the file handle on this file. */ /* -------------------------------------------------------------------- */ VSISubFileHandle *poHandle = new VSISubFileHandle; poHandle->fp = fp; poHandle->nSubregionOffset = nOff; poHandle->nSubregionSize = nSize; VSIFSeekL( fp, nOff, SEEK_SET ); return poHandle; }
VSIVirtualHandle * VSISubFileFilesystemHandler::Open( const char *pszFilename, const char *pszAccess, bool /* bSetError */ ) { if( !STARTS_WITH_CI(pszFilename, "/vsisubfile/") ) return nullptr; CPLString osSubFilePath; vsi_l_offset nOff = 0; vsi_l_offset nSize = 0; if( !DecomposePath( pszFilename, osSubFilePath, nOff, nSize ) ) { errno = ENOENT; return nullptr; } if( nOff + nSize < nOff ) { return nullptr; } /* -------------------------------------------------------------------- */ /* We can't open the containing file with "w" access, so if tht */ /* is requested use "r+" instead to update in place. */ /* -------------------------------------------------------------------- */ if( pszAccess[0] == 'w' ) pszAccess = "r+"; /* -------------------------------------------------------------------- */ /* Open the underlying file. */ /* -------------------------------------------------------------------- */ VSILFILE *fp = VSIFOpenL( osSubFilePath, pszAccess ); if( fp == nullptr ) return nullptr; /* -------------------------------------------------------------------- */ /* Setup the file handle on this file. */ /* -------------------------------------------------------------------- */ VSISubFileHandle *poHandle = new VSISubFileHandle; poHandle->fp = fp; poHandle->nSubregionOffset = nOff; poHandle->nSubregionSize = nSize; // In read-only mode validate (offset, size) against underlying file size if( strchr(pszAccess, 'r') != nullptr && strchr(pszAccess, '+') == nullptr ) { if( VSIFSeekL( fp, 0, SEEK_END ) != 0 ) { poHandle->Close(); delete poHandle; return nullptr; } vsi_l_offset nFpSize = VSIFTellL(fp); // For a directory, the size will be max(vsi_l_offset) / 2 if( nFpSize == ~(static_cast<vsi_l_offset>(0)) / 2 || nOff > nFpSize ) { poHandle->Close(); delete poHandle; return nullptr; } if( nOff + nSize > nFpSize ) { nSize = nFpSize - nOff; poHandle->nSubregionSize = nSize; } } if( VSIFSeekL( fp, nOff, SEEK_SET ) != 0 ) { poHandle->Close(); delete poHandle; poHandle = nullptr; } return poHandle; }