size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { if( !bUpdate ) { errno = EACCES; return 0; } if( bExtendFileAtNextWrite ) { bExtendFileAtNextWrite = FALSE; if( !poFile->SetLength( nOffset ) ) return 0; } // FIXME: Integer overflow check should be placed here: const size_t nBytesToWrite = nSize * nCount; if( nBytesToWrite + nOffset > poFile->nLength ) { if( !poFile->SetLength( nBytesToWrite + nOffset ) ) return 0; } if( nBytesToWrite ) memcpy( poFile->pabyData + nOffset, pBuffer, nBytesToWrite ); nOffset += nBytesToWrite; time(&poFile->mTime); return nCount; }
size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { if( !bUpdate ) { errno = EACCES; return 0; } if( bExtendFileAtNextWrite ) { bExtendFileAtNextWrite = FALSE; if( !poFile->SetLength( nOffset ) ) return 0; } // FIXME: Integer overflow check should be placed here: size_t nBytesToWrite = nSize * nCount; //if( CSLTestBoolean(CPLGetConfigOption("VERBOSE_IO", "FALSE")) ) // CPLDebug("MEM", "Write(%d bytes in [%d,%d[)", (int)nBytesToWrite, (int)nOffset, (int)(nOffset+nBytesToWrite)); if( nBytesToWrite + nOffset > poFile->nLength ) { if( !poFile->SetLength( nBytesToWrite + nOffset ) ) return 0; } memcpy( poFile->pabyData + nOffset, pBuffer, nBytesToWrite ); nOffset += nBytesToWrite; time(&poFile->mTime); return nCount; }
int VSIMemHandle::Truncate( vsi_l_offset nNewSize ) { if( !bUpdate ) { errno = EACCES; return -1; } if (poFile->SetLength( nNewSize )) return 0; else return -1; }
size_t VSIMemHandle::Write( const void * pBuffer, size_t nSize, size_t nCount ) { if( !bUpdate ) { errno = EACCES; return 0; } if( bExtendFileAtNextWrite ) { bExtendFileAtNextWrite = false; if( !poFile->SetLength( m_nOffset ) ) return 0; } const size_t nBytesToWrite = nSize * nCount; if( nCount > 0 && nBytesToWrite / nCount != nSize ) { return 0; } if( nBytesToWrite + m_nOffset < nBytesToWrite ) { return 0; } if( nBytesToWrite + m_nOffset > poFile->nLength ) { if( !poFile->SetLength( nBytesToWrite + m_nOffset ) ) return 0; } if( nBytesToWrite ) memcpy( poFile->pabyData + m_nOffset, pBuffer, nBytesToWrite ); m_nOffset += nBytesToWrite; time(&poFile->mTime); return nCount; }
int VSIMemHandle::Truncate( vsi_l_offset nNewSize ) { if( !bUpdate ) { errno = EACCES; return -1; } bExtendFileAtNextWrite = FALSE; if (poFile->SetLength( nNewSize )) return 0; else return -1; }
int VSIMemHandle::Seek( vsi_l_offset nOffset, int nWhence ) { if( nWhence == SEEK_CUR ) this->nOffset += nOffset; else if( nWhence == SEEK_SET ) this->nOffset = nOffset; else if( nWhence == SEEK_END ) this->nOffset = poFile->nLength + nOffset; else { errno = EINVAL; return -1; } if( this->nOffset < 0 ) { this->nOffset = 0; return -1; } if( this->nOffset > poFile->nLength ) { if( !bUpdate ) // Read-only files cannot be extended by seek. { CPLDebug( "VSIMemHandle", "Attempt to extend read-only file '%s' to length %d from %d, .", poFile->osFilename.c_str(), (int) this->nOffset, (int) poFile->nLength ); this->nOffset = poFile->nLength; errno = EACCES; return -1; } else // Writeable files are zero-extended by seek past end. { if( !poFile->SetLength( this->nOffset ) ) return -1; } } return 0; }
VSIVirtualHandle * VSIMemFilesystemHandler::Open( const char *pszFilename, const char *pszAccess ) { CPLMutexHolder oHolder( &hMutex ); VSIMemFile *poFile; CPLString osFilename = pszFilename; NormalizePath( osFilename ); /* -------------------------------------------------------------------- */ /* Get the filename we are opening, create if needed. */ /* -------------------------------------------------------------------- */ if( oFileList.find(osFilename) == oFileList.end() ) poFile = NULL; else poFile = oFileList[osFilename]; if( strstr(pszAccess,"w") == NULL && poFile == NULL ) { errno = ENOENT; return NULL; } if( strstr(pszAccess,"w") ) { if( poFile ) poFile->SetLength( 0 ); else { poFile = new VSIMemFile; poFile->osFilename = osFilename; oFileList[poFile->osFilename] = poFile; poFile->nRefCount++; // for file list } } if( poFile->bIsDirectory ) { errno = EISDIR; return NULL; } /* -------------------------------------------------------------------- */ /* Setup the file handle on this file. */ /* -------------------------------------------------------------------- */ VSIMemHandle *poHandle = new VSIMemHandle; poHandle->poFile = poFile; poHandle->nOffset = 0; if( strstr(pszAccess,"w") || strstr(pszAccess,"+") || strstr(pszAccess,"a") ) poHandle->bUpdate = TRUE; else poHandle->bUpdate = FALSE; poFile->nRefCount++; if( strstr(pszAccess,"a") ) poHandle->nOffset = poFile->nLength; return poHandle; }
VSIVirtualHandle * VSIMemFilesystemHandler::Open( const char *pszFilename, const char *pszAccess, bool bSetError ) { CPLMutexHolder oHolder( &hMutex ); CPLString osFilename = pszFilename; NormalizePath( osFilename ); if( osFilename.empty() ) return nullptr; vsi_l_offset nMaxLength = GUINTBIG_MAX; const size_t iPos = osFilename.find("||maxlength="); if( iPos != std::string::npos ) { nMaxLength = static_cast<vsi_l_offset>(CPLAtoGIntBig( osFilename.substr(iPos + strlen("||maxlength=")).c_str())); } /* -------------------------------------------------------------------- */ /* Get the filename we are opening, create if needed. */ /* -------------------------------------------------------------------- */ VSIMemFile *poFile = nullptr; if( oFileList.find(osFilename) != oFileList.end() ) poFile = oFileList[osFilename]; // If no file and opening in read, error out. if( strstr(pszAccess, "w") == nullptr && strstr(pszAccess, "a") == nullptr && poFile == nullptr ) { if( bSetError ) { VSIError(VSIE_FileError, "No such file or directory"); } errno = ENOENT; return nullptr; } // Create. if( poFile == nullptr ) { poFile = new VSIMemFile; poFile->osFilename = osFilename; oFileList[poFile->osFilename] = poFile; CPLAtomicInc(&(poFile->nRefCount)); // For file list. poFile->nMaxLength = nMaxLength; } // Overwrite else if( strstr(pszAccess, "w") ) { poFile->SetLength(0); poFile->nMaxLength = nMaxLength; } if( poFile->bIsDirectory ) { errno = EISDIR; return nullptr; } /* -------------------------------------------------------------------- */ /* Setup the file handle on this file. */ /* -------------------------------------------------------------------- */ VSIMemHandle *poHandle = new VSIMemHandle; poHandle->poFile = poFile; poHandle->m_nOffset = 0; poHandle->bEOF = false; poHandle->bUpdate = strstr(pszAccess, "w") || strstr(pszAccess, "+") || strstr(pszAccess, "a"); CPLAtomicInc(&(poFile->nRefCount)); if( strstr(pszAccess, "a") ) poHandle->m_nOffset = poFile->nLength; return poHandle; }