int FS_FCloseFile(fileHandle_t handle) { if (handle == 0) return 0; FS_CheckHandle(handle, false); handleTable[handle].isOpen = false; if (handleTable[handle].isPakFile) { handleTable[handle].fileData.clear(); return 0; } else { try { handleTable[handle].file.Close(); if (handleTable[handle].renameTo) { std::string renameTo = std::move(*handleTable[handle].renameTo); handleTable[handle].renameTo = Util::nullopt; // tidy up after abusing std::move try { FS::RawPath::MoveFile(renameTo, renameTo + TEMP_SUFFIX); } catch (std::system_error& err) { Log::Notice("Failed to replace file %s: %s\n", renameTo.c_str(), err.what()); return -1; } } return 0; } catch (std::system_error& err) { Log::Notice("Failed to close file: %s\n", err.what()); return -1; } } }
int FS_FTell(fileHandle_t handle) { FS_CheckHandle(handle, false); if (handleTable[handle].isPakFile) return handleTable[handle].filePos; else return handleTable[handle].file.Tell(); }
void FS_Flush(fileHandle_t handle) { FS_CheckHandle(handle, true); try { handleTable[handle].file.Flush(); } catch (std::system_error& err) { Log::Notice("FS_Flush failed: %s\n", err.what()); } }
s32 FS_GetStats( s32 FileHandle, FDStat *Stats ) { if( FS_CheckHandle(FileHandle) == 0 ) return FS_EINVAL; Stats->file_length = fd_stack[FileHandle].fsize; Stats->file_pos = fd_stack[FileHandle].fptr; return FS_SUCCESS; }
int FS_Write(const void* buffer, int len, fileHandle_t handle) { FS_CheckHandle(handle, true); try { handleTable[handle].file.Write(buffer, len); if (handleTable[handle].forceFlush) handleTable[handle].file.Flush(); return len; } catch (std::system_error& err) { Log::Notice("FS_Write failed: %s\n", err.what()); return 0; } }
int FS_filelength(fileHandle_t handle) { FS_CheckHandle(handle, false); if (handleTable[handle].isPakFile) return handleTable[handle].fileData.size(); else { std::error_code err; int length = handleTable[handle].file.Length(err); if (err) { Log::Notice("Failed to get file length: %s\n", err.message().c_str()); return 0; } return length; } }
int FS_Seek(fileHandle_t handle, long offset, fsOrigin_t origin) { FS_CheckHandle(handle, false); if (handleTable[handle].isPakFile) { switch (origin) { case fsOrigin_t::FS_SEEK_CUR: handleTable[handle].filePos += offset; break; case fsOrigin_t::FS_SEEK_SET: handleTable[handle].filePos = offset; break; case fsOrigin_t::FS_SEEK_END: handleTable[handle].filePos = handleTable[handle].fileData.size() + offset; break; default: Com_Error(errorParm_t::ERR_DROP, "Bad origin in FS_Seek"); } return 0; } else { try { switch (origin) { case fsOrigin_t::FS_SEEK_CUR: handleTable[handle].file.SeekCur(offset); break; case fsOrigin_t::FS_SEEK_SET: handleTable[handle].file.SeekSet(offset); break; case fsOrigin_t::FS_SEEK_END: handleTable[handle].file.SeekEnd(offset); break; default: Com_Error(errorParm_t::ERR_DROP, "Bad origin in FS_Seek"); } return 0; } catch (std::system_error& err) { Log::Notice("FS_Seek failed: %s\n", err.what()); return -1; } } }
s32 FS_Read( s32 FileHandle, u8 *Data, u32 Length ) { if( FS_CheckHandle(FileHandle) == 0) return FS_EINVAL; u32 read = 0; s32 r = f_read( &fd_stack[FileHandle], Data, Length, &read ); switch( r ) { case FR_OK: return read; case FR_DENIED: return FS_EACCESS; default: dbgprintf("f_read( %p, %p, %d, %p):%d\n", &fd_stack[FileHandle], Data, Length, &read, r ); break; } return FS_EFATAL; }
s32 FS_Write( s32 FileHandle, u8 *Data, u32 Length ) { if( FS_CheckHandle(FileHandle) == 0) return FS_EINVAL; u32 wrote = 0; s32 ret = f_write( &fd_stack[FileHandle], Data, Length, &wrote ); switch( ret ) { case FR_OK: return wrote; case FR_DENIED: return FS_EACCESS; default: dbgprintf("f_write( %p, %p, %d, %p):%d\n", &fd_stack[FileHandle], Data, Length, &wrote, ret ); break; } return FS_EFATAL; }
int FS_Read(void* buffer, int len, fileHandle_t handle) { FS_CheckHandle(handle, false); if (handleTable[handle].isPakFile) { if (len < 0) Com_Error(errorParm_t::ERR_DROP, "FS_Read: invalid length"); if (handleTable[handle].filePos >= handleTable[handle].fileData.size()) return 0; len = std::min<size_t>(len, handleTable[handle].fileData.size() - handleTable[handle].filePos); memcpy(buffer, handleTable[handle].fileData.data() + handleTable[handle].filePos, len); handleTable[handle].filePos += len; return len; } else { try { return handleTable[handle].file.Read(buffer, len); } catch (std::system_error& err) { Log::Notice("FS_Read failed: %s\n", err.what()); return 0; } } }
s32 FS_Close( s32 FileHandle ) { if( FileHandle == FS_FD || FileHandle == SD_FD ) return FS_SUCCESS; if( FS_CheckHandle(FileHandle) == 0 ) return FS_EINVAL; if( f_close( &fd_stack[FileHandle] ) != FR_OK ) { memset32( &fd_stack[FileHandle], 0, sizeof(FIL) ); return FS_EFATAL; } else { memset32( &fd_stack[FileHandle], 0, sizeof(FIL) ); return FS_SUCCESS; } return FS_EFATAL; }
/* SEEK_SET returns the seeked amount SEEK_END returns the new offset, but returns -101 when you seek out of the file SEEK_CUR " */ s32 FS_Seek( s32 FileHandle, s32 Where, u32 Whence ) { if( FS_CheckHandle(FileHandle) == 0) return FS_EINVAL; switch( Whence ) { case SEEK_SET: { if( Where > fd_stack[FileHandle].fsize ) break; if( f_lseek( &fd_stack[FileHandle], Where ) == FR_OK ) { if( Where == 0 ) return 0; return fd_stack[FileHandle].fptr; } } break; case SEEK_CUR: if( f_lseek(&fd_stack[FileHandle], Where + fd_stack[FileHandle].fptr) == FR_OK ) return fd_stack[FileHandle].fptr; break; case SEEK_END: if( f_lseek(&fd_stack[FileHandle], Where + fd_stack[FileHandle].fsize) == FR_OK ) return fd_stack[FileHandle].fptr; break; default: break; } return FS_EFATAL; }
void FS_ForceFlush(fileHandle_t handle) { FS_CheckHandle(handle, true); handleTable[handle].forceFlush = true; }