1+ // source https://gist.github.com/Su-s/438be493ae692318c73e30367cbc5c2a
2+
3+ using System ;
4+ using System . IO ;
5+ using System . IO . Compression ;
6+ using System . Text ;
7+
8+ namespace TarLib
9+ {
10+ public class Tar
11+ {
12+ /// <summary>
13+ /// Extracts a <i>.tar.gz</i> archive to the specified directory.
14+ /// </summary>
15+ /// <param name="filename">The <i>.tar.gz</i> to decompress and extract.</param>
16+ /// <param name="outputDir">Output directory to write the files.</param>
17+ public static void ExtractTarGz ( string filename , string outputDir )
18+ {
19+ using ( var stream = File . OpenRead ( filename ) ) ExtractTarGz ( stream , outputDir ) ;
20+ }
21+
22+ /// <summary>
23+ /// Extracts a <i>.tar.gz</i> archive stream to the specified directory.
24+ /// </summary>
25+ /// <param name="stream">The <i>.tar.gz</i> to decompress and extract.</param>
26+ /// <param name="outputDir">Output directory to write the files.</param>
27+ public static void ExtractTarGz ( Stream stream , string outputDir )
28+ {
29+ using ( var gzip = new GZipStream ( stream , CompressionMode . Decompress ) )
30+ {
31+ ExtractTar ( gzip , outputDir ) ;
32+ }
33+ }
34+
35+ /// <summary>
36+ /// Extractes a <c>tar</c> archive to the specified directory.
37+ /// </summary>
38+ /// <param name="filename">The <i>.tar</i> to extract.</param>
39+ /// <param name="outputDir">Output directory to write the files.</param>
40+ public static void ExtractTar ( string filename , string outputDir )
41+ {
42+ using ( var stream = File . OpenRead ( filename ) )
43+ ExtractTar ( stream , outputDir ) ;
44+ }
45+
46+ /// <summary>
47+ /// Extractes a <c>tar</c> archive to the specified directory.
48+ /// </summary>
49+ /// <param name="stream">The <i>.tar</i> to extract.</param>
50+ /// <param name="outputDir">Output directory to write the files.</param>
51+ public static void ExtractTar ( Stream stream , string outputDir )
52+ {
53+ var buffer = new byte [ 100 ] ;
54+ // store current position here
55+ long pos = 0 ;
56+ while ( true )
57+ {
58+ pos += stream . Read ( buffer , 0 , 100 ) ;
59+ var name = Encoding . ASCII . GetString ( buffer ) . Trim ( '\0 ' ) ;
60+ if ( String . IsNullOrWhiteSpace ( name ) ) break ;
61+ FakeSeekForward ( stream , 24 ) ;
62+ pos += 24 ;
63+
64+ pos += stream . Read ( buffer , 0 , 12 ) ;
65+ var size = Convert . ToInt64 ( Encoding . UTF8 . GetString ( buffer , 0 , 12 ) . Trim ( '\0 ' ) . Trim ( ) , 8 ) ;
66+ FakeSeekForward ( stream , 376 ) ;
67+ pos += 376 ;
68+
69+ var output = Path . Combine ( outputDir , name ) ;
70+
71+ // only include these folders
72+ var include = ( output . IndexOf ( "package/ProjectData~/Assets/" ) > - 1 ) ;
73+ include |= ( output . IndexOf ( "package/ProjectData~/ProjectSettings/" ) > - 1 ) ;
74+ include |= ( output . IndexOf ( "package/ProjectData~/Packages/" ) > - 1 ) ;
75+
76+ // rename output path from "package/ProjectData~/Assets/" into "Assets/"
77+ output = output . Replace ( "package/ProjectData~/" , "" ) ;
78+
79+ if ( include == true && ! Directory . Exists ( Path . GetDirectoryName ( output ) ) ) Directory . CreateDirectory ( Path . GetDirectoryName ( output ) ) ;
80+
81+ if ( ! name . Equals ( "./" , StringComparison . InvariantCulture ) )
82+ {
83+ if ( include == true )
84+ {
85+ //Console.WriteLine("output=" + output);
86+ using ( var str = File . Open ( output , FileMode . OpenOrCreate , FileAccess . Write ) )
87+ {
88+ var buf = new byte [ size ] ;
89+ pos += stream . Read ( buf , 0 , buf . Length ) ;
90+ // take only data from this folder
91+ str . Write ( buf , 0 , buf . Length ) ;
92+ }
93+ }
94+ else
95+ {
96+ //pos += size;
97+ var buf = new byte [ size ] ;
98+ pos += stream . Read ( buf , 0 , buf . Length ) ;
99+ //FakeSeekForward(stream, (int)size);
100+ }
101+ }
102+
103+ var offset = ( int ) ( 512 - ( pos % 512 ) ) ;
104+ if ( offset == 512 ) offset = 0 ;
105+ FakeSeekForward ( stream , offset ) ;
106+ pos += offset ;
107+ }
108+ }
109+
110+ private static void FakeSeekForward ( Stream stream , int offset )
111+ {
112+ if ( stream . CanSeek )
113+ stream . Seek ( offset , SeekOrigin . Current ) ;
114+ else
115+ {
116+ int bytesRead = 0 ;
117+ var buffer = new byte [ offset ] ;
118+ while ( bytesRead < offset )
119+ {
120+ int read = stream . Read ( buffer , bytesRead , offset - bytesRead ) ;
121+ if ( read == 0 )
122+ throw new EndOfStreamException ( ) ;
123+ bytesRead += read ;
124+ }
125+ }
126+ }
127+ }
128+ }
0 commit comments