bool WinMoveFile( RString sOldPath, RString sNewPath ) { if( WinMoveFileInternal( DoPathReplace(sOldPath), DoPathReplace(sNewPath) ) ) return true; if( GetLastError() != ERROR_ACCESS_DENIED ) return false; /* Try turning off the read-only bit on the file we're overwriting. */ SetFileAttributes( DoPathReplace(sNewPath), FILE_ATTRIBUTE_NORMAL ); return WinMoveFileInternal( DoPathReplace(sOldPath), DoPathReplace(sNewPath) ); }
HANDLE DoFindFirstFile( const RString &sPath, WIN32_FIND_DATA *fd ) { return FindFirstFile( DoPathReplace(sPath), fd ); }
int DoRmdir( const RString &sPath ) { return rmdir( DoPathReplace(sPath) ); }
int DoRemove( const RString &sPath ) { return remove( DoPathReplace(sPath) ); }
int DoRename( const RString &sOldPath, const RString &sNewPath ) { return rename( DoPathReplace(sOldPath), DoPathReplace(sNewPath) ); }
int DoStat( const RString &sPath, struct stat *st ) { return stat( DoPathReplace(sPath), st ); }
int DoOpen( const RString &sPath, int flags, int perm ) { return open( DoPathReplace(sPath), flags, perm ); }
/* Wrappers for low-level file functions, to work around Xbox issues: */ int DoMkdir( const RString &sPath, int perm ) { return mkdir( DoPathReplace(sPath), perm ); }
RageFileObjDirect::~RageFileObjDirect() { bool bFailed = !FinalFlush(); if( m_iFD != -1 ) { if( close( m_iFD ) == -1 ) { WARN( ssprintf("Error closing %s: %s", this->m_sPath.c_str(), strerror(errno)) ); SetError( strerror(errno) ); bFailed = true; } } if( !(m_iMode & RageFile::WRITE) || (m_iMode & RageFile::STREAMED) ) return; /* We now have path written to MakeTempFilename(m_sPath). * Rename the temporary file over the real path. */ do { if( bFailed || WriteFailed() ) break; /* We now have path written to MakeTempFilename(m_sPath). Rename the * temporary file over the real path. This should be an atomic operation * with a journalling filesystem. That is, there should be no * intermediate state a JFS might restore the file we're writing (in the * case of a crash/powerdown) to an empty or partial file. */ RString sOldPath = MakeTempFilename(m_sPath); RString sNewPath = m_sPath; #if defined(WIN32) if( WinMoveFile(DoPathReplace(sOldPath), DoPathReplace(sNewPath)) ) return; /* We failed. */ int err = GetLastError(); const RString error = werr_ssprintf( err, "Error renaming \"%s\" to \"%s\"", sOldPath.c_str(), sNewPath.c_str() ); WARN( ssprintf("%s", error.c_str()) ); SetError( error ); break; #else if( rename( sOldPath, sNewPath ) == -1 ) { WARN( ssprintf("Error renaming \"%s\" to \"%s\": %s", sOldPath.c_str(), sNewPath.c_str(), strerror(errno)) ); SetError( strerror(errno) ); break; } if( m_iMode & RageFile::SLOW_FLUSH ) { RString sError; if( !FlushDir(Dirname(m_sPath), sError) ) { WARN( ssprintf("Error synchronizing fsync(%s dir): %s", this->m_sPath.c_str(), sError.c_str()) ); SetError( sError ); } } // Success. return; #endif } while(0); // The write or the rename failed. Delete the incomplete temporary file. DoRemove( MakeTempFilename(m_sPath) ); }