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