public RarStream(string rarPath) { bool oldNameFormat = true; RarBlock block = null; using (RarReader rdr = new RarReader(rarPath, RarReadMode.RAR)) while ((block = rdr.Read()) != null) { if (block is RarVolumeHeaderBlock && ((block.Flags & (ushort)RarVolumeHeaderBlock.FlagValues.Volume) != 0)) { oldNameFormat = (block.Flags & (ushort)RarVolumeHeaderBlock.FlagValues.NewNumbering) == 0; } else if (block is RarPackedFileBlock) { if ((block.Flags & (ushort)RarPackedFileBlock.FlagValues.SplitBefore) != 0) { throw new InvalidDataException("You must start with the first volume from a RAR set"); } break; } } // this constructor implementation picks the first packed file encountered in the archive and sets up to read it // an alternate constructor might have a parameter to specify the packed file to read. string packedFileName = null; string nextFileName = rarPath; while (File.Exists(nextFileName)) { using (RarReader rdr = new RarReader(nextFileName, RarReadMode.RAR)) while ((block = rdr.Read()) != null) { RarPackedFileBlock fblock = block as RarPackedFileBlock; if (fblock != null) { if (string.IsNullOrEmpty(packedFileName)) { packedFileName = fblock.FileName; } if (packedFileName == fblock.FileName) { if (fblock.CompressionMethod != 0x30) { throw new InvalidDataException("Compressed RARs are not supported"); } currentVol = new RarVolume(); currentVol.FilePath = nextFileName; currentVol.PackedFileRangeStart = packedFileLength; currentVol.PackedFileRangeEnd = packedFileLength + (long)fblock.PackedSize - 1; currentVol.PackedFileOffset = fblock.BlockPosition + fblock.RawData.LongLength; rarVolumes.Add(currentVol); packedFileLength += (long)fblock.PackedSize; } } } nextFileName = RarFileNameFinder.FindNextFileName(nextFileName, oldNameFormat); } currentVol = rarVolumes[0]; }
static int CreateReconstructionFile(List <FileInfo> inFiles, DirectoryInfo inFolder, List <string> storeFiles, string srrName, bool savePaths) { using (FileStream srrfs = new FileStream(srrName, FileMode.Create)) { BinaryWriter bw = new BinaryWriter(srrfs, Encoding.ASCII); bw.Write(new SrrHeaderBlock(appName).RawData); // we store copies of any files included in the storeFiles list in the .srr using a "store block". any SFV files used are also included. foreach (FileInfo fi in inFiles) { if (fi.Extension.ToLower() == ".sfv") { storeFiles.Add(fi.FullName); } } SrrStoredFileBlock storeBlock = null; foreach (string fileName in storeFiles) { string searchName = fileName; if (!Path.IsPathRooted(searchName)) { searchName = Path.Combine(inFolder.FullName, fileName); } DirectoryInfo searchDir = new DirectoryInfo(Path.GetDirectoryName(searchName)); if (searchDir.Exists) { foreach (FileInfo storeFile in searchDir.GetFiles(Path.GetFileName(searchName))) { string fName = savePaths ? MakePathRelative(storeFile.FullName, inFolder.FullName) : storeFile.Name; Console.WriteLine("Storing file: {0}", fName); storeBlock = new SrrStoredFileBlock(fName, (int)storeFile.Length); if (savePaths) { storeBlock.Flags |= (ushort)SrrStoredFileBlock.FlagValues.PathsSaved; } using (FileStream storefs = storeFile.OpenRead()) storefs.Read(storeBlock.RawData, storeBlock.FileOffset, (int)storeFile.Length); bw.Write(storeBlock.RawData); } } } List <string> rarFiles = new List <string>(); foreach (FileInfo inFile in inFiles) { if (inFile.Extension.ToLower() == ".sfv") { using (SfvReader sfvReader = new SfvReader(inFile.FullName)) { List <string> sfvRarFiles = new List <string>(); SfvEntry sfvEntry; while ((sfvEntry = sfvReader.Read()) != null) { if (RarFileNameComparer.IsRarFile(sfvEntry.FileName)) { sfvRarFiles.Add(Path.Combine(inFile.DirectoryName, sfvEntry.FileName)); } else { ReportError(string.Format("Warning: Non-RAR file referenced in SFV: {0}\n\tThis file cannot be recreated unless it is stored using -s", sfvEntry.FileName)); continue; } } sfvRarFiles.Sort(new RarFileNameComparer()); rarFiles.AddRange(sfvRarFiles); } } else { bool oldNameFormat = false; RarBlock block = null; using (RarReader rdr = new RarReader(inFile.FullName, RarReadMode.RAR)) while ((block = rdr.Read()) != null) { if (block is RarVolumeHeaderBlock && ((block.Flags & (ushort)RarVolumeHeaderBlock.FlagValues.Volume) != 0)) { if ((block.Flags & (ushort)RarVolumeHeaderBlock.FlagValues.FirstVolume) == 0) { throw new InvalidDataException("You must start with the first volume from a RAR set"); } oldNameFormat = (block.Flags & (ushort)RarVolumeHeaderBlock.FlagValues.NewNumbering) == 0; } } string nextFileName = inFile.FullName; while (File.Exists(nextFileName)) { rarFiles.Add(Path.Combine(inFile.DirectoryName, nextFileName)); nextFileName = RarFileNameFinder.FindNextFileName(nextFileName, oldNameFormat); } } } foreach (string fileName in rarFiles) { if (!File.Exists(fileName)) { ReportError(string.Format("Referenced file not found: {0}", fileName)); srrfs.Close(); File.Delete(srrName); return(2); } string fName = savePaths ? MakePathRelative(fileName, inFolder.FullName) : Path.GetFileName(fileName); Console.WriteLine("Processing file: {0}", fName); SrrRarFileBlock rarBlock = new SrrRarFileBlock(fName); if (savePaths) { rarBlock.Flags |= (ushort)SrrRarFileBlock.FlagValues.PathsSaved; } bw.Write(rarBlock.RawData); using (RarReader rarReader = new RarReader(fileName, RarReadMode.RAR)) { RarBlock block; while ((block = rarReader.Read()) != null) { if (verbose) { Console.WriteLine("\tBlock Type: 0x{0:x2}", block.RawType); Console.WriteLine("\tBlock Size: {0}", block.RawData.Length); } if (block is RarPackedFileBlock) { RarPackedFileBlock fileData = (RarPackedFileBlock)block; if (verbose) { Console.WriteLine("\t\tCompression Type: 0x{0:x2}", fileData.CompressionMethod); Console.WriteLine("\t\tPacked Data Size: {0:n0}", fileData.PackedSize); Console.WriteLine("\t\tFile Size: {0:n0}", fileData.UnpackedSize); Console.WriteLine("\t\tFile Name: {0}", fileData.FileName); } if (fileData.CompressionMethod != 0x30) { ReportError(string.Format("Archive uses unsupported compression method: {0}", fileName)); srrfs.Close(); File.Delete(srrName); return(3); } } else if (block is RarRecoveryBlock) { RarRecoveryBlock subData = (RarRecoveryBlock)block; if (verbose & subData.RecoverySectors > 0) { Console.WriteLine("\t\tRecovery Record Size: {0:n0}", subData.PackedSize); Console.WriteLine("\t\tRecovery Sectors: {0:n0}", subData.RecoverySectors); Console.WriteLine("\t\tProtected Sectors: {0:n0}", subData.DataSectors); } } // store the raw data for any blocks found bw.Write(block.RawData); } } } } Console.WriteLine("\nReconstruction file successfully created: {0}", srrName); return(0); }