2014-09-23 12:06:15 -07:00
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ROMVault2 is written by Gordon J . *
* Contact gordon @romvault . com *
* Copyright 2014 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
using System ;
using System.ComponentModel ;
using System.Diagnostics ;
2015-03-18 08:48:48 -05:00
using System.Drawing ;
using System.IO ;
2014-09-23 12:06:15 -07:00
using System.Security.Cryptography ;
using ROMVault2.RvDB ;
using ROMVault2.SupportedFiles ;
2015-03-18 08:48:48 -05:00
using ROMVault2.SupportedFiles.SevenZip ;
2014-09-23 12:06:15 -07:00
using ROMVault2.SupportedFiles.Zip ;
using ROMVault2.SupportedFiles.Zip.ZLib ;
using ROMVault2.Utils ;
namespace ROMVault2
{
public enum ReturnCode { Good , RescanNeeded , FindFixes , LogicError , FileSystemError , SourceCRCCheckSumError , SourceCheckSumError , DestinationCheckSumError , StartOver }
public static class FixFileCopy
{
private const int BufferSize = 4096 * 128 ;
private static byte [ ] _buffer ;
// This Function returns:
// Good : Everything Worked Correctly
// RescanNeeded : Something unexpectidly changed in the files, so Stop prompt user to rescan.
// LogicError : This Should never happen and is a logic problem in the code
// FileSystemError : Something is wrong with the files
/// <summary>
/// Performs the RomVault File Copy, with the source and destination being files or zipped files
/// </summary>
/// <param name="fileIn">This is the file being copied, it may be a zipped file or a regular file system file</param>
/// <param name="zipFileOut">This is the zip file that is being writen to, if it is null a new zip file will be made if we are coping to a zip</param>
/// <param name="zipFilenameOut">This is the name of the .zip file to be made that will be created in zipFileOut</param>
/// <param name="fileOut">This is the actual output filename</param>
/// <param name="forceRaw">if true then we will do a raw copy, this is so that we can copy corrupt zips</param>
/// <param name="error">This is the returned error message if this copy fails</param>
/// <param name="foundFile">If we are SHA1/MD5 checking the source file for the first time, and it is different from what we expected the correct values for this file are returned in foundFile</param>
/// <returns>ReturnCode.Good is the valid return code otherwire we have an error</returns>
2015-03-18 08:48:48 -05:00
public static ReturnCode CopyFile ( RvFile fileIn , ref ICompress zipFileOut , string zipFilenameOut , RvFile fileOut , bool forceRaw , out string error , out RvFile foundFile )
2014-09-23 12:06:15 -07:00
{
foundFile = null ;
error = "" ;
if ( _buffer = = null )
_buffer = new byte [ BufferSize ] ;
bool rawCopy = RawCopy ( fileIn , fileOut , forceRaw ) ;
ulong streamSize = 0 ;
ushort compressionMethod = 8 ;
bool sourceTrrntzip = false ;
2015-03-18 08:48:48 -05:00
ICompress zipFileIn = null ;
Stream readStream = null ;
ReturnCode retC ;
2014-09-23 12:06:15 -07:00
bool isZeroLengthFile = DBHelper . IsZeroLengthFile ( fileOut ) ;
if ( ! isZeroLengthFile )
{
2015-03-18 08:48:48 -05:00
retC = CheckInputAndOutputFile ( fileIn , fileOut , out error ) ;
if ( retC ! = ReturnCode . Good )
return retC ;
2014-09-23 12:06:15 -07:00
2015-03-18 08:48:48 -05:00
retC = OpenInputStream ( fileIn , rawCopy , out zipFileIn , out sourceTrrntzip , out readStream , out streamSize , out compressionMethod , out error ) ;
if ( retC ! = ReturnCode . Good )
return retC ;
2014-09-23 12:06:15 -07:00
}
else
{
sourceTrrntzip = true ;
}
if ( ! rawCopy & & ( Settings . FixLevel = = eFixLevel . TrrntZipLevel1 | | Settings . FixLevel = = eFixLevel . TrrntZipLevel2 | | Settings . FixLevel = = eFixLevel . TrrntZipLevel3 ) )
compressionMethod = 8 ;
#region Find and Check / Open Output Files
2015-03-18 08:48:48 -05:00
Stream writeStream ;
2014-09-23 12:06:15 -07:00
2015-03-18 08:48:48 -05:00
retC = OpenOutputStream ( fileOut , fileIn , ref zipFileOut , zipFilenameOut , compressionMethod , rawCopy , sourceTrrntzip , out writeStream , out error ) ;
if ( retC ! = ReturnCode . Good )
return retC ;
2014-09-23 12:06:15 -07:00
#endregion
byte [ ] bCRC ;
byte [ ] bMD5 = null ;
byte [ ] bSHA1 = null ;
if ( ! isZeroLengthFile )
{
#region Do Data Tranfer
CRC32Hash crc32 = null ;
MD5 md5 = null ;
SHA1 sha1 = null ;
if ( ! rawCopy )
{
crc32 = new CRC32Hash ( ) ;
md5 = MD5 . Create ( ) ;
sha1 = SHA1 . Create ( ) ;
}
ulong sizetogo = streamSize ;
while ( sizetogo > 0 )
{
int sizenow = sizetogo > BufferSize ? BufferSize : ( int ) sizetogo ;
try
{
readStream . Read ( _buffer , 0 , sizenow ) ;
}
catch ( ZlibException )
{
if ( fileIn . FileType = = FileType . ZipFile & & zipFileIn ! = null )
{
ZipReturn zr = zipFileIn . ZipFileCloseReadStream ( ) ;
if ( zr ! = ZipReturn . ZipGood )
{
error = "Error Closing " + zr + " Stream :" + zipFileIn . Filename ( fileIn . ReportIndex ) ;
return ReturnCode . FileSystemError ;
}
zipFileIn . ZipFileClose ( ) ;
}
else
{
readStream . Close ( ) ;
}
if ( fileOut . FileType = = FileType . ZipFile )
{
ZipReturn zr = zipFileOut . ZipFileCloseWriteStream ( new byte [ ] { 0 , 0 , 0 , 0 } ) ;
if ( zr ! = ZipReturn . ZipGood )
{
error = "Error Closing Stream " + zr ;
return ReturnCode . FileSystemError ;
}
zipFileOut . ZipFileRollBack ( ) ;
}
else
{
writeStream . Flush ( ) ;
writeStream . Close ( ) ;
IO . File . Delete ( zipFilenameOut ) ;
}
error = "Error in Data Stream" ;
return ReturnCode . SourceCRCCheckSumError ;
}
catch ( Exception e )
{
error = "Error reading Source File " + e . Message ;
return ReturnCode . FileSystemError ;
}
if ( ! rawCopy )
{
crc32 . TransformBlock ( _buffer , 0 , sizenow , null , 0 ) ;
md5 . TransformBlock ( _buffer , 0 , sizenow , null , 0 ) ;
sha1 . TransformBlock ( _buffer , 0 , sizenow , null , 0 ) ;
}
try
{
writeStream . Write ( _buffer , 0 , sizenow ) ;
}
catch ( Exception e )
{
Debug . WriteLine ( e . Message ) ;
error = "Error writing out file. " + Environment . NewLine + e . Message ;
return ReturnCode . FileSystemError ;
}
sizetogo = sizetogo - ( ulong ) sizenow ;
}
writeStream . Flush ( ) ;
#endregion
#region Collect Checksums
// if we did a full copy then we just calculated all the checksums while doing the copy
if ( ! rawCopy )
{
crc32 . TransformFinalBlock ( _buffer , 0 , 0 ) ;
md5 . TransformFinalBlock ( _buffer , 0 , 0 ) ;
sha1 . TransformFinalBlock ( _buffer , 0 , 0 ) ;
bCRC = crc32 . Hash ;
bMD5 = md5 . Hash ;
bSHA1 = sha1 . Hash ;
}
// if we raw copied and the source file has been FileChecked then we can trust the checksums in the source file
else
{
bCRC = ArrByte . Copy ( fileIn . CRC ) ;
if ( fileIn . FileStatusIs ( FileStatus . MD5Verified ) ) bMD5 = ArrByte . Copy ( fileIn . MD5 ) ;
if ( fileIn . FileStatusIs ( FileStatus . SHA1Verified ) ) bSHA1 = ArrByte . Copy ( fileIn . SHA1 ) ;
}
#endregion
#region close the ReadStream
2015-03-18 08:48:48 -05:00
if ( ( fileIn . FileType = = FileType . ZipFile | | fileIn . FileType = = FileType . SevenZipFile ) & & zipFileIn ! = null )
2014-09-23 12:06:15 -07:00
{
ZipReturn zr = zipFileIn . ZipFileCloseReadStream ( ) ;
if ( zr ! = ZipReturn . ZipGood )
{
error = "Error Closing " + zr + " Stream :" + zipFileIn . Filename ( fileIn . ReportIndex ) ;
return ReturnCode . FileSystemError ;
}
zipFileIn . ZipFileClose ( ) ;
}
else
{
readStream . Close ( ) ;
//if (IO.File.Exists(tmpFilename))
// IO.File.Delete(tmpFilename);
}
#endregion
}
else
{
// Zero Length File (Directory in a Zip)
if ( fileOut . FileType = = FileType . ZipFile )
{
zipFileOut . ZipFileAddDirectory ( ) ;
}
bCRC = VarFix . CleanMD5SHA1 ( "00000000" , 8 ) ;
bMD5 = VarFix . CleanMD5SHA1 ( "d41d8cd98f00b204e9800998ecf8427e" , 32 ) ;
bSHA1 = VarFix . CleanMD5SHA1 ( "da39a3ee5e6b4b0d3255bfef95601890afd80709" , 40 ) ;
}
#region close the WriteStream
2015-03-18 08:48:48 -05:00
if ( fileOut . FileType = = FileType . ZipFile | | fileOut . FileType = = FileType . SevenZipFile )
2014-09-23 12:06:15 -07:00
{
ZipReturn zr = zipFileOut . ZipFileCloseWriteStream ( bCRC ) ;
if ( zr ! = ZipReturn . ZipGood )
{
error = "Error Closing Stream " + zr ;
return ReturnCode . FileSystemError ;
}
fileOut . ZipFileIndex = zipFileOut . LocalFilesCount ( ) - 1 ;
fileOut . ZipFileHeaderPosition = zipFileOut . LocalHeader ( fileOut . ZipFileIndex ) ;
}
else
{
writeStream . Flush ( ) ;
writeStream . Close ( ) ;
IO . FileInfo fi = new IO . FileInfo ( zipFilenameOut ) ;
fileOut . TimeStamp = fi . LastWriteTime ;
}
#endregion
if ( ! isZeroLengthFile )
{
if ( ! rawCopy )
{
if ( ! ArrByte . bCompare ( bCRC , fileIn . CRC ) )
{
fileIn . GotStatus = GotStatus . Corrupt ;
error = "Source CRC does not match Source Data stream, corrupt Zip" ;
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut . ZipFileRollBack ( ) ;
else
IO . File . Delete ( zipFilenameOut ) ;
return ReturnCode . SourceCRCCheckSumError ;
}
fileIn . FileStatusSet ( FileStatus . CRCVerified | FileStatus . SizeVerified ) ;
bool sourceFailed = false ;
// check to see if we have a MD5 from the DAT file
if ( fileIn . FileStatusIs ( FileStatus . MD5FromDAT ) )
{
if ( fileIn . MD5 = = null )
{
error = "Should have an filein MD5 from Dat but not found. Logic Error." ;
return ReturnCode . LogicError ;
}
if ( ! ArrByte . bCompare ( fileIn . MD5 , bMD5 ) )
sourceFailed = true ;
else
fileIn . FileStatusSet ( FileStatus . MD5Verified ) ;
}
// check to see if we have an MD5 (not from the DAT) so must be from previously scanning this file.
else if ( fileIn . MD5 ! = null )
{
if ( ! ArrByte . bCompare ( fileIn . MD5 , bMD5 ) )
{
// if we had an MD5 from a preview scan and it now does not match, something has gone really bad.
error = "The MD5 found does not match a previously scanned MD5, this should not happen, unless something got corrupt." ;
return ReturnCode . LogicError ;
}
}
else // (FileIn.MD5 == null)
{
fileIn . MD5 = bMD5 ;
fileIn . FileStatusSet ( FileStatus . MD5Verified ) ;
}
// check to see if we have a SHA1 from the DAT file
if ( fileIn . FileStatusIs ( FileStatus . SHA1FromDAT ) )
{
if ( fileIn . SHA1 = = null )
{
error = "Should have an filein SHA1 from Dat but not found. Logic Error." ;
return ReturnCode . LogicError ;
}
if ( ! ArrByte . bCompare ( fileIn . SHA1 , bSHA1 ) )
sourceFailed = true ;
else
fileIn . FileStatusSet ( FileStatus . SHA1Verified ) ;
}
// check to see if we have an SHA1 (not from the DAT) so must be from previously scanning this file.
else if ( fileIn . SHA1 ! = null )
{
if ( ! ArrByte . bCompare ( fileIn . SHA1 , bSHA1 ) )
{
// if we had an SHA1 from a preview scan and it now does not match, something has gone really bad.
error = "The SHA1 found does not match a previously scanned SHA1, this should not happen, unless something got corrupt." ;
return ReturnCode . LogicError ;
}
}
else // (FileIn.SHA1 == null)
{
fileIn . SHA1 = bSHA1 ;
fileIn . FileStatusSet ( FileStatus . SHA1Verified ) ;
}
if ( sourceFailed )
{
2015-03-18 08:48:48 -05:00
if ( fileIn . FileType = = FileType . ZipFile | | fileIn . FileType = = FileType . SevenZipFile )
2014-09-23 12:06:15 -07:00
{
RvFile tZFile = new RvFile ( FileType . ZipFile ) ;
foundFile = tZFile ;
tZFile . ZipFileIndex = fileIn . ZipFileIndex ;
tZFile . ZipFileHeaderPosition = fileIn . ZipFileHeaderPosition ;
}
else
{
foundFile = new RvFile ( fileIn . FileType ) ;
}
foundFile . Name = fileIn . Name ;
foundFile . Size = fileIn . Size ;
foundFile . CRC = bCRC ;
foundFile . MD5 = bMD5 ;
foundFile . SHA1 = bSHA1 ;
foundFile . TimeStamp = fileIn . TimeStamp ;
foundFile . SetStatus ( DatStatus . NotInDat , GotStatus . Got ) ;
foundFile . FileStatusSet ( FileStatus . SizeVerified | FileStatus . CRCVerified | FileStatus . MD5Verified | FileStatus . SHA1Verified ) ;
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut . ZipFileRollBack ( ) ;
else
IO . File . Delete ( zipFilenameOut ) ;
return ReturnCode . SourceCheckSumError ;
}
}
}
2015-03-18 08:48:48 -05:00
if ( fileOut . FileType = = FileType . ZipFile | | fileOut . FileType = = FileType . SevenZipFile )
2014-09-23 12:06:15 -07:00
{
fileOut . FileStatusSet ( FileStatus . SizeFromHeader | FileStatus . CRCFromHeader ) ;
}
if ( fileOut . FileStatusIs ( FileStatus . CRCFromDAT ) & & fileOut . CRC ! = null & & ! ArrByte . bCompare ( fileOut . CRC , bCRC ) )
{
//Rollback the file
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut . ZipFileRollBack ( ) ;
else
IO . File . Delete ( zipFilenameOut ) ;
return ReturnCode . DestinationCheckSumError ;
}
fileOut . CRC = bCRC ;
if ( ! rawCopy | | fileIn . FileStatusIs ( FileStatus . CRCVerified ) )
fileOut . FileStatusSet ( FileStatus . CRCVerified ) ;
if ( bSHA1 ! = null )
{
if ( fileOut . FileStatusIs ( FileStatus . SHA1FromDAT ) & & fileOut . SHA1 ! = null & & ! ArrByte . bCompare ( fileOut . SHA1 , bSHA1 ) )
{
//Rollback the file
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut . ZipFileRollBack ( ) ;
else
IO . File . Delete ( zipFilenameOut ) ;
return ReturnCode . DestinationCheckSumError ;
}
fileOut . SHA1 = bSHA1 ;
fileOut . FileStatusSet ( FileStatus . SHA1Verified ) ;
}
if ( bMD5 ! = null )
{
if ( fileOut . FileStatusIs ( FileStatus . MD5FromDAT ) & & fileOut . MD5 ! = null & & ! ArrByte . bCompare ( fileOut . MD5 , bMD5 ) )
{
//Rollback the file
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut . ZipFileRollBack ( ) ;
else
IO . File . Delete ( zipFilenameOut ) ;
return ReturnCode . DestinationCheckSumError ;
}
fileOut . MD5 = bMD5 ;
fileOut . FileStatusSet ( FileStatus . MD5Verified ) ;
}
if ( fileIn . Size ! = null )
{
fileOut . Size = fileIn . Size ;
fileOut . FileStatusSet ( FileStatus . SizeVerified ) ;
}
if ( fileIn . GotStatus = = GotStatus . Corrupt )
fileOut . GotStatus = GotStatus . Corrupt ;
else
fileOut . GotStatus = GotStatus . Got ; // Changes RepStatus to Correct
fileOut . FileStatusSet ( FileStatus . SizeVerified ) ;
if ( fileOut . SHA1CHD = = null & & fileIn . SHA1CHD ! = null ) fileOut . SHA1CHD = fileIn . SHA1CHD ;
if ( fileOut . MD5CHD = = null & & fileIn . MD5CHD ! = null ) fileOut . MD5CHD = fileIn . MD5CHD ;
fileOut . CHDVersion = fileIn . CHDVersion ;
fileOut . FileStatusSet ( FileStatus . SHA1CHDFromHeader | FileStatus . MD5CHDFromHeader | FileStatus . SHA1CHDVerified | FileStatus . MD5CHDVerified , fileIn ) ;
return ReturnCode . Good ;
}
//Raw Copy
// Returns True is a raw copy can be used
// Returns False is a full recompression is required
private static bool RawCopy ( RvFile fileIn , RvFile fileOut , bool forceRaw )
{
if ( fileIn = = null | | fileOut = = null )
return false ;
if ( ( fileIn . FileType ! = FileType . ZipFile ) | | ( fileOut . FileType ! = FileType . ZipFile ) )
return false ;
if ( fileIn . Parent = = null )
return false ;
if ( forceRaw ) return true ;
bool trrntzipped = ( fileIn . Parent . ZipStatus & ZipStatus . TrrntZip ) = = ZipStatus . TrrntZip ;
bool deepchecked = fileIn . FileStatusIs ( FileStatus . SHA1Verified ) & & fileIn . FileStatusIs ( FileStatus . MD5Verified ) ;
switch ( Settings . FixLevel )
{
case eFixLevel . TrrntZipLevel1 :
return trrntzipped ;
case eFixLevel . TrrntZipLevel2 :
return trrntzipped & & deepchecked ;
case eFixLevel . TrrntZipLevel3 :
return false ;
case eFixLevel . Level1 :
return true ;
case eFixLevel . Level2 :
return deepchecked ;
case eFixLevel . Level3 :
return false ;
}
return false ;
}
2015-03-18 08:48:48 -05:00
private static ReturnCode CheckInputAndOutputFile ( RvFile fileIn , RvFile fileOut , out string error )
{
if ( fileOut . FileStatusIs ( FileStatus . SizeFromDAT ) & & fileOut . Size ! = null & & fileIn . Size ! = fileOut . Size )
{
error = "Source and destination Size does not match. Logic Error." ;
return ReturnCode . LogicError ;
}
if ( fileOut . FileStatusIs ( FileStatus . CRCFromDAT ) & & fileOut . CRC ! = null & & ! ArrByte . bCompare ( fileIn . CRC , fileOut . CRC ) )
{
error = "Source and destination CRC does not match. Logic Error." ;
return ReturnCode . LogicError ;
}
if ( fileOut . FileStatusIs ( FileStatus . SHA1FromDAT ) & & fileIn . FileStatusIs ( FileStatus . SHA1Verified ) )
{
if ( fileIn . SHA1 ! = null & & fileOut . SHA1 ! = null & & ! ArrByte . bCompare ( fileIn . SHA1 , fileOut . SHA1 ) )
{
error = "Source and destination SHA1 does not match. Logic Error." ;
return ReturnCode . LogicError ;
}
}
if ( fileOut . FileStatusIs ( FileStatus . MD5CHDFromDAT ) & & fileIn . FileStatusIs ( FileStatus . MD5Verified ) )
{
if ( fileIn . MD5 ! = null & & fileOut . MD5 ! = null & & ! ArrByte . bCompare ( fileIn . MD5 , fileOut . MD5 ) )
{
error = "Source and destination SHA1 does not match. Logic Error." ;
return ReturnCode . LogicError ;
}
}
error = "" ;
return ReturnCode . Good ;
}
private static ReturnCode OpenInputStream ( RvFile fileIn , bool rawCopy , out ICompress zipFileIn , out bool sourceTrrntzip , out Stream readStream , out ulong streamSize , out ushort compressionMethod , out string error )
{
zipFileIn = null ;
sourceTrrntzip = false ;
readStream = null ;
streamSize = 0 ;
compressionMethod = 0 ;
switch ( fileIn . FileType )
{
case FileType . SevenZipFile :
case FileType . ZipFile :
{
RvDir zZipFileIn = fileIn . Parent ;
if ( zZipFileIn . FileType ! = DBTypeGet . DirFromFile ( fileIn . FileType ) )
{
error = "SevenZip File Open but Source File is not a SevenZip, Logic Error." ;
return ReturnCode . LogicError ;
}
string fileNameIn = zZipFileIn . FullName ;
ZipReturn zr1 ;
if ( fileIn . FileType = = FileType . SevenZipFile )
{
sourceTrrntzip = false ;
zipFileIn = new SevenZ ( ) ;
zr1 = zipFileIn . ZipFileOpen ( fileNameIn , zZipFileIn . TimeStamp , true ) ;
}
else
{
sourceTrrntzip = ( zZipFileIn . ZipStatus & ZipStatus . TrrntZip ) = = ZipStatus . TrrntZip ;
zipFileIn = new ZipFile ( ) ;
zr1 = zipFileIn . ZipFileOpen ( fileNameIn , zZipFileIn . TimeStamp , fileIn . ZipFileHeaderPosition = = null ) ;
}
switch ( zr1 )
{
case ZipReturn . ZipGood :
break ;
case ZipReturn . ZipErrorFileNotFound :
error = "File not found, Rescan required before fixing " + fileIn . Name ;
return ReturnCode . FileSystemError ;
case ZipReturn . ZipErrorTimeStamp :
error = "File has changed, Rescan required before fixing " + fileIn . Name ;
return ReturnCode . FileSystemError ;
default :
error = "Error Open Zip" + zr1 + ", with File " + fileIn . DatFullName ;
return ReturnCode . FileSystemError ;
}
if ( fileIn . FileType = = FileType . SevenZipFile )
{
SevenZ z = zipFileIn as SevenZ ;
z . ZipFileOpenReadStream ( fileIn . ZipFileIndex , out readStream , out streamSize ) ;
}
else
{
ZipFile z = zipFileIn as ZipFile ;
if ( fileIn . ZipFileHeaderPosition ! = null )
z . ZipFileOpenReadStreamQuick ( ( ulong ) fileIn . ZipFileHeaderPosition , rawCopy , out readStream , out streamSize , out compressionMethod ) ;
else
z . ZipFileOpenReadStream ( fileIn . ZipFileIndex , rawCopy , out readStream , out streamSize , out compressionMethod ) ;
}
}
break ;
default :
{
string fileNameIn = fileIn . FullName ;
if ( ! IO . File . Exists ( fileNameIn ) )
{
error = "Rescan needed, File Changed :" + fileNameIn ;
return ReturnCode . RescanNeeded ;
}
IO . FileInfo fileInInfo = new IO . FileInfo ( fileNameIn ) ;
if ( fileInInfo . LastWriteTime ! = fileIn . TimeStamp )
{
error = "Rescan needed, File Changed :" + fileNameIn ;
return ReturnCode . RescanNeeded ;
}
int errorCode = IO . FileStream . OpenFileRead ( fileNameIn , out readStream ) ;
if ( errorCode ! = 0 )
{
error = new Win32Exception ( errorCode ) . Message + ". " + fileNameIn ;
return ReturnCode . FileSystemError ;
}
if ( fileIn . Size = = null )
{
error = "Null File Size found in Fixing File :" + fileNameIn ;
return ReturnCode . LogicError ;
}
streamSize = ( ulong ) fileIn . Size ;
if ( ( ulong ) readStream . Length ! = streamSize )
{
error = "Rescan needed, File Length Changed :" + fileNameIn ;
return ReturnCode . RescanNeeded ;
}
}
break ;
}
error = "" ;
return ReturnCode . Good ;
}
private static ReturnCode OpenOutputStream ( RvFile fileOut , RvFile fileIn , ref ICompress zipFileOut , string zipFilenameOut , ushort compressionMethod , bool rawCopy , bool sourceTrrntzip , out System . IO . Stream writeStream , out string error )
{
writeStream = null ;
switch ( fileOut . FileType )
{
case FileType . ZipFile :
case FileType . SevenZipFile :
{
// if ZipFileOut == null then we have not open the output zip yet so open it from writing.
if ( zipFileOut = = null )
{
if ( IO . Path . GetFileName ( zipFilenameOut ) = = "__RomVault.tmp" )
{
if ( IO . File . Exists ( zipFilenameOut ) )
IO . File . Delete ( zipFilenameOut ) ;
}
else if ( IO . File . Exists ( zipFilenameOut ) )
{
error = "Rescan needed, File Changed :" + zipFilenameOut ;
return ReturnCode . RescanNeeded ;
}
if ( fileOut . FileType = = FileType . ZipFile )
zipFileOut = new ZipFile ( ) ;
else
zipFileOut = new SevenZ ( ) ;
ZipReturn zrf = zipFileOut . ZipFileCreate ( zipFilenameOut ) ;
if ( zrf ! = ZipReturn . ZipGood )
{
error = "Error Opening Write Stream " + zrf ;
return ReturnCode . FileSystemError ;
}
}
else
{
if ( zipFileOut . ZipOpen ! = ZipOpenType . OpenWrite )
{
error = "Output Zip File is not set to OpenWrite, Logic Error." ;
return ReturnCode . LogicError ;
}
if ( zipFileOut . ZipFilename ! = ( new IO . FileInfo ( zipFilenameOut ) . FullName ) )
{
error = "Output Zip file has changed name from " + zipFileOut . ZipFilename + " to " + zipFilenameOut + ". Logic Error" ;
return ReturnCode . LogicError ;
}
}
if ( fileIn . Size = = null )
{
error = "Null File Size found in Fixing File :" + fileIn . FullName ;
return ReturnCode . LogicError ;
}
ZipReturn zr = zipFileOut . ZipFileOpenWriteStream ( rawCopy , sourceTrrntzip , fileOut . Name , ( ulong ) fileIn . Size , compressionMethod , out writeStream ) ;
if ( zr ! = ZipReturn . ZipGood )
{
error = "Error Opening Write Stream " + zr ;
return ReturnCode . FileSystemError ;
}
}
break ;
default :
{
if ( IO . File . Exists ( zipFilenameOut ) & & fileOut . GotStatus ! = GotStatus . Corrupt )
{
error = "Rescan needed, File Changed :" + zipFilenameOut ;
return ReturnCode . RescanNeeded ;
}
int errorCode = IO . FileStream . OpenFileWrite ( zipFilenameOut , out writeStream ) ;
if ( errorCode ! = 0 )
{
error = new Win32Exception ( errorCode ) . Message + ". " + zipFilenameOut ;
return ReturnCode . FileSystemError ;
}
}
break ;
}
error = "" ;
return ReturnCode . Good ;
}
2014-09-23 12:06:15 -07:00
}
}