RarVolume.cs 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using SharpCompress.Common.Rar.Headers;
  6. using SharpCompress.IO;
  7. using SharpCompress.Readers;
  8. namespace SharpCompress.Common.Rar
  9. {
  10. /// <summary>
  11. /// A RarArchiveVolume is a single rar file that may or may not be a split RarArchive. A Rar Archive is one to many Rar Parts
  12. /// </summary>
  13. public abstract class RarVolume : Volume
  14. {
  15. private readonly RarHeaderFactory _headerFactory;
  16. internal RarVolume(StreamingMode mode, Stream stream, ReaderOptions options)
  17. : base(stream, options)
  18. {
  19. _headerFactory = new RarHeaderFactory(mode, options);
  20. }
  21. internal ArchiveHeader ArchiveHeader { get; private set; }
  22. internal StreamingMode Mode => _headerFactory.StreamingMode;
  23. internal abstract IEnumerable<RarFilePart> ReadFileParts();
  24. internal abstract RarFilePart CreateFilePart(MarkHeader markHeader, FileHeader fileHeader);
  25. internal IEnumerable<RarFilePart> GetVolumeFileParts()
  26. {
  27. MarkHeader lastMarkHeader = null;
  28. foreach (var header in _headerFactory.ReadHeaders(Stream))
  29. {
  30. switch (header.HeaderType)
  31. {
  32. case HeaderType.Mark:
  33. {
  34. lastMarkHeader = header as MarkHeader;
  35. }
  36. break;
  37. case HeaderType.Archive:
  38. {
  39. ArchiveHeader = header as ArchiveHeader;
  40. }
  41. break;
  42. case HeaderType.File:
  43. {
  44. var fh = header as FileHeader;
  45. yield return CreateFilePart(lastMarkHeader, fh);
  46. }
  47. break;
  48. }
  49. }
  50. }
  51. private void EnsureArchiveHeaderLoaded()
  52. {
  53. if (ArchiveHeader == null)
  54. {
  55. if (Mode == StreamingMode.Streaming)
  56. {
  57. throw new InvalidOperationException("ArchiveHeader should never been null in a streaming read.");
  58. }
  59. // we only want to load the archive header to avoid overhead but have to do the nasty thing and reset the stream
  60. GetVolumeFileParts().First();
  61. Stream.Position = 0;
  62. }
  63. }
  64. /// <summary>
  65. /// RarArchive is the first volume of a multi-part archive.
  66. /// Only Rar 3.0 format and higher
  67. /// </summary>
  68. public override bool IsFirstVolume
  69. {
  70. get
  71. {
  72. EnsureArchiveHeaderLoaded();
  73. return ArchiveHeader.IsFirstVolume;
  74. }
  75. }
  76. /// <summary>
  77. /// RarArchive is part of a multi-part archive.
  78. /// </summary>
  79. public override bool IsMultiVolume
  80. {
  81. get
  82. {
  83. EnsureArchiveHeaderLoaded();
  84. return ArchiveHeader.IsVolume;
  85. }
  86. }
  87. /// <summary>
  88. /// RarArchive is SOLID (this means the Archive saved bytes by reusing information which helps for archives containing many small files).
  89. /// Currently, SharpCompress cannot decompress SOLID archives.
  90. /// </summary>
  91. public bool IsSolidArchive
  92. {
  93. get
  94. {
  95. EnsureArchiveHeaderLoaded();
  96. return ArchiveHeader.IsSolid;
  97. }
  98. }
  99. }
  100. }