22using System . IO ;
33using System . Linq ;
44using System . Reflection ;
5+ using System . Text ;
56
67using Force . Blazer . Algorithms ;
78using Force . Blazer . Exe . CommandLine ;
@@ -81,7 +82,7 @@ private static int ProcessCompress(CommandLineParser<BlazerCommandLineOptions> o
8182 {
8283 var opt = options . Get ( ) ;
8384
84- var fileName = options . GetNonParamOptions ( 0 ) ?? string . Empty ;
85+ string [ ] fileNamesMultiple = new [ ] { options . GetNonParamOptions ( 0 ) ?? string . Empty } ;
8586 string archiveName = null ;
8687
8788 var listFile = options . GetNonParamOptions ( ) . FirstOrDefault ( x => x [ 0 ] == '@' ) ;
@@ -94,25 +95,26 @@ private static int ProcessCompress(CommandLineParser<BlazerCommandLineOptions> o
9495 return 1 ;
9596 }
9697
97- archiveName = fileName ;
98- // currently we support only one file
99- fileName = File . ReadAllLines ( listFile ) . FirstOrDefault ( ) ;
98+ archiveName = fileNamesMultiple [ 0 ] ;
99+ fileNamesMultiple = File . ReadAllLines ( listFile ) . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) . Select ( x => x . Trim ( ) ) . ToArray ( ) ;
100100 }
101101
102- if ( ! opt . Stdin && ! File . Exists ( fileName ) )
102+ if ( ! opt . Stdin && fileNamesMultiple . Any ( x => ! File . Exists ( x ) && ! Directory . Exists ( x ) ) )
103103 {
104- if ( fileName == string . Empty )
104+ if ( fileNamesMultiple [ 0 ] == string . Empty )
105105 {
106106 Console . WriteLine ( options . GenerateHelp ( ) ) ;
107107 return 0 ;
108108 }
109109
110- Console . Error . WriteLine ( "Source file " + fileName + " does not exist" ) ;
110+ if ( fileNamesMultiple . Length == 1 )
111+ Console . Error . WriteLine ( "Source file " + fileNamesMultiple [ 0 ] + " does not exist" ) ;
112+ else Console . Error . WriteLine ( "One or more of files to compress does not exist" ) ;
111113 return 1 ;
112114 }
113115
114116 if ( archiveName == null )
115- archiveName = fileName + ".blz" ;
117+ archiveName = fileNamesMultiple [ 0 ] + ".blz" ;
116118 var truncateOutFile = false ;
117119 if ( ! opt . Stdout && File . Exists ( archiveName ) )
118120 {
@@ -134,7 +136,18 @@ private static int ProcessCompress(CommandLineParser<BlazerCommandLineOptions> o
134136 compressionOptions . Comment = opt . Comment ;
135137
136138 if ( ! opt . NoFileName )
137- compressionOptions . FileInfo = BlazerFileInfo . FromFileName ( fileName , false ) ;
139+ {
140+ if ( fileNamesMultiple . Length == 1 ) compressionOptions . FileInfo = BlazerFileInfo . FromFileName ( fileNamesMultiple [ 0 ] , false ) ;
141+ else compressionOptions . MultipleFiles = true ;
142+ }
143+ else
144+ {
145+ if ( fileNamesMultiple . Length > 1 )
146+ {
147+ Console . Error . WriteLine ( "No File Name option cannot be used with multiple files" ) ;
148+ return 1 ;
149+ }
150+ }
138151
139152 if ( mode == "none" )
140153 compressionOptions . SetEncoderByAlgorithm ( BlazerAlgorithm . NoCompress ) ;
@@ -165,25 +178,52 @@ private static int ProcessCompress(CommandLineParser<BlazerCommandLineOptions> o
165178
166179 var outStream = opt . Stdout ? Console . OpenStandardOutput ( ) : new FileStream ( archiveName , FileMode . OpenOrCreate , FileAccess . Write , FileShare . Read ) ;
167180
168- Stream blazerStream = opt . DataArray ? ( Stream ) new MemoryStream ( ) : new BlazerInputStream ( outStream , compressionOptions ) ;
169-
170- using ( var inFile = new StatStream ( opt . Stdin ? Console . OpenStandardInput ( ) : File . OpenRead ( fileName ) , ! opt . Stdout ) )
171- using ( var outFile = blazerStream )
172- {
173- inFile . CopyTo ( outFile ) ;
174- }
175-
176181 if ( opt . DataArray )
177182 {
178- var sourceData = ( blazerStream as MemoryStream ) . ToArray ( ) ;
183+ byte [ ] sourceData ;
184+ using ( var sourceStream = opt . Stdin ? Console . OpenStandardInput ( ) : File . OpenRead ( fileNamesMultiple [ 0 ] ) )
185+ {
186+ var tmpOutStream = new MemoryStream ( ) ;
187+ sourceStream . CopyTo ( tmpOutStream ) ;
188+ sourceData = tmpOutStream . ToArray ( ) ;
189+ }
190+
179191 var encoder = compressionOptions . Encoder ;
180192 encoder . Init ( sourceData . Length ) ;
181193 var res = encoder . Encode ( sourceData , 0 , sourceData . Length ) ;
182194 outStream . Write ( new [ ] { ( byte ) sourceData . Length , ( byte ) ( sourceData . Length >> 8 ) , ( byte ) ( sourceData . Length >> 16 ) , ( byte ) ( sourceData . Length >> 24 ) } , 0 , 4 ) ;
183195 outStream . Write ( res . Buffer , res . Offset , res . Count ) ;
184196 outStream . Close ( ) ;
185197 }
186-
198+ else
199+ {
200+ using ( var outFile = new BlazerInputStream ( outStream , compressionOptions ) )
201+ {
202+ if ( opt . Stdin )
203+ {
204+ using ( var inFile = new StatStream ( Console . OpenStandardInput ( ) , ! opt . Stdout ) ) inFile . CopyTo ( outFile ) ;
205+ }
206+ else
207+ {
208+ foreach ( var fileName in fileNamesMultiple )
209+ {
210+ if ( fileNamesMultiple . Length > 1 )
211+ {
212+ var blazerFileInfo = BlazerFileInfo . FromFileName ( fileName , ! opt . NoPathName ) ;
213+ outFile . WriteFileInfo ( blazerFileInfo ) ;
214+ if ( ( blazerFileInfo . Attributes & FileAttributes . Directory ) != 0 )
215+ continue ;
216+ }
217+
218+ using ( var inFile = new StatStream ( File . OpenRead ( fileName ) , ! opt . Stdout ) )
219+ {
220+ inFile . CopyTo ( outFile ) ;
221+ }
222+ }
223+ }
224+ }
225+ }
226+
187227 return 0 ;
188228 }
189229
@@ -193,7 +233,7 @@ private static int ProcessDecompress(CommandLineParser<BlazerCommandLineOptions>
193233
194234 var archiveName = options . GetNonParamOptions ( 0 ) ?? string . Empty ;
195235
196- string customOutFileName = null ;
236+ string [ ] customOutFileNames = null ;
197237
198238 var listFile = options . GetNonParamOptions ( ) . FirstOrDefault ( x => x [ 0 ] == '@' ) ;
199239 if ( listFile != null )
@@ -205,8 +245,7 @@ private static int ProcessDecompress(CommandLineParser<BlazerCommandLineOptions>
205245 return 1 ;
206246 }
207247
208- // currently we support only one file
209- customOutFileName = File . ReadAllLines ( listFile ) . FirstOrDefault ( ) ;
248+ customOutFileNames = File . ReadAllLines ( listFile ) . Where ( x => ! string . IsNullOrWhiteSpace ( x ) ) . Select ( x => x . Trim ( ) ) . ToArray ( ) ;
210249 }
211250
212251 if ( ! opt . Stdin && ! File . Exists ( archiveName ) )
@@ -226,7 +265,50 @@ private static int ProcessDecompress(CommandLineParser<BlazerCommandLineOptions>
226265 var decOptions = new BlazerDecompressionOptions ( opt . Password ) { EncyptFull = opt . EncryptFull } ;
227266
228267 BlazerOutputStream outBlazerStream = null ;
229- Stream outStream = null ;
268+ Stream outStream ;
269+ BlazerFileInfo prevFile = null ;
270+ Stream [ ] outFile = { null } ;
271+ decOptions . FileInfoCallback = fInfo =>
272+ {
273+ if ( prevFile != null )
274+ {
275+ outFile [ 0 ] . Flush ( ) ;
276+ outFile [ 0 ] . Close ( ) ;
277+ outFile [ 0 ] = null ;
278+ prevFile . ApplyToFile ( ) ;
279+ prevFile = null ;
280+ }
281+
282+ var fInfoFileName = fInfo . FileName ;
283+ if ( customOutFileNames != null && ! customOutFileNames . Contains ( fInfoFileName ) )
284+ return ;
285+
286+ prevFile = fInfo ;
287+ if ( ( fInfo . Attributes & FileAttributes . Directory ) != 0 )
288+ {
289+ if ( ! opt . NoPathName && ! Directory . Exists ( fInfoFileName ) ) Directory . CreateDirectory ( fInfoFileName ) ;
290+ }
291+ else
292+ {
293+ if ( opt . NoPathName ) fInfoFileName = Path . GetFileName ( fInfoFileName ) ;
294+
295+ if ( File . Exists ( fInfoFileName ) )
296+ {
297+ if ( ! opt . Force )
298+ {
299+ Console . WriteLine ( "Target " + fInfoFileName + " already exists. Overwrite? (Y)es (N)o" ) ;
300+ var readLine = Console . ReadLine ( ) ;
301+ if ( readLine . Trim ( ) . ToLowerInvariant ( ) . IndexOf ( 'y' ) != 0 ) return ;
302+ }
303+
304+ new FileStream ( fInfoFileName , FileMode . Truncate , FileAccess . Write ) . Close ( ) ;
305+ }
306+
307+ var directoryName = Path . GetDirectoryName ( fInfoFileName ) ;
308+ if ( ! string . IsNullOrEmpty ( directoryName ) ) Directory . CreateDirectory ( directoryName ) ;
309+ outFile [ 0 ] = new StatStream ( new FileStream ( fInfoFileName , FileMode . OpenOrCreate , FileAccess . Write , FileShare . Read ) , true ) ;
310+ }
311+ } ;
230312
231313 if ( opt . DataArray )
232314 {
@@ -251,38 +333,38 @@ private static int ProcessDecompress(CommandLineParser<BlazerCommandLineOptions>
251333 }
252334
253335 var fileName = archiveName ;
254- var applyFileInfoAfterComplete = false ;
255336 if ( archiveName . EndsWith ( ".blz" ) ) fileName = fileName . Substring ( 0 , fileName . Length - 4 ) ;
256337 else fileName += ".unpacked" ;
257338
258339 if ( outBlazerStream != null && outBlazerStream . FileInfo != null && ! opt . NoFileName )
259340 {
260341 fileName = outBlazerStream . FileInfo . FileName ;
261- applyFileInfoAfterComplete = true ;
262342 }
263343
264- if ( customOutFileName != null ) fileName = customOutFileName ;
344+ if ( opt . Stdout ) outFile [ 0 ] = Console . OpenStandardOutput ( ) ;
345+ // we haven't received an file info from callback
346+ if ( outFile [ 0 ] == null )
347+ outFile [ 0 ] = new StatStream ( new FileStream ( fileName , FileMode . OpenOrCreate , FileAccess . Write , FileShare . Read ) , true ) ;
265348
266- if ( ! opt . Stdout && File . Exists ( fileName ) )
349+ using ( var inFile = outStream )
267350 {
268- if ( ! opt . Force )
351+ var buf = new byte [ 81920 ] ;
352+ int cnt = 1 ;
353+ while ( cnt > 0 )
269354 {
270- Console . WriteLine ( "Target " + fileName + " already exists. Overwrite? (Y)es (N)o" ) ;
271- var readLine = Console . ReadLine ( ) ;
272- if ( readLine . Trim ( ) . ToLowerInvariant ( ) . IndexOf ( 'y' ) != 0 ) return 1 ;
355+ cnt = inFile . Read ( buf , 0 , buf . Length ) ;
356+ if ( outFile [ 0 ] != null )
357+ outFile [ 0 ] . Write ( buf , 0 , cnt ) ;
273358 }
274-
275- new FileStream ( fileName , FileMode . Truncate , FileAccess . Write ) . Close ( ) ;
276359 }
277360
278- using ( var inFile = outStream )
279- using ( var outFile = opt . Stdout ? Console . OpenStandardOutput ( ) : new StatStream ( new FileStream ( fileName , FileMode . OpenOrCreate , FileAccess . Write , FileShare . Read ) , true ) )
361+ if ( prevFile != null )
280362 {
281- inFile . CopyTo ( outFile ) ;
363+ outFile [ 0 ] . Flush ( ) ;
364+ outFile [ 0 ] . Close ( ) ;
365+ prevFile . ApplyToFile ( ) ;
282366 }
283367
284- if ( applyFileInfoAfterComplete ) outBlazerStream . FileInfo . ApplyToFile ( ) ;
285-
286368 return 0 ;
287369 }
288370
@@ -367,6 +449,26 @@ private static int ProcessList(CommandLineParser<BlazerCommandLineOptions> optio
367449 Stream inStreamSource = opt . Stdin ? Console . OpenStandardInput ( ) : File . OpenRead ( archiveName ) ;
368450
369451 var decOptions = new BlazerDecompressionOptions ( opt . Password ) { EncyptFull = opt . EncryptFull } ;
452+ StringBuilder header = new StringBuilder ( ) ;
453+ header . AppendLine ( " Date Time Attr Size Name" ) ;
454+ header . AppendLine ( "------------------- ----- ------------ ------------------------" ) ;
455+ bool [ ] headerWritten = { false } ;
456+ decOptions . FileInfoCallback = fi =>
457+ {
458+ var s = string . Format (
459+ "{0:yyyy-MM-dd} {1:HH:mm:ss} {2}{3}{4}{5}{6} {7,12} {8}" ,
460+ fi . CreationTimeUtc . ToLocalTime ( ) ,
461+ fi . CreationTimeUtc . ToLocalTime ( ) ,
462+ ( fi . Attributes & FileAttributes . Directory ) != 0 ? "D" : "." ,
463+ ( fi . Attributes & FileAttributes . ReadOnly ) != 0 ? "R" : "." ,
464+ ( fi . Attributes & FileAttributes . Hidden ) != 0 ? "H" : "." ,
465+ ( fi . Attributes & FileAttributes . System ) != 0 ? "S" : "." ,
466+ ( fi . Attributes & FileAttributes . Archive ) != 0 ? "A" : "." ,
467+ fi . Length ,
468+ fi . FileName ) ;
469+ if ( ! headerWritten [ 0 ] ) header . AppendLine ( s ) ;
470+ else Console . WriteLine ( s ) ;
471+ } ;
370472
371473 if ( opt . DataArray )
372474 {
@@ -386,29 +488,21 @@ private static int ProcessList(CommandLineParser<BlazerCommandLineOptions> optio
386488 }
387489
388490 Console . WriteLine ( ) ;
491+ Console . Write ( header ) ;
492+ headerWritten [ 0 ] = true ;
389493 var fi = outStream . FileInfo ;
390- if ( fi == null )
494+ if ( fi == null && ! outStream . HaveMultipleFiles )
391495 {
392496 Console . WriteLine ( "Missing file information in archive." ) ;
393497 return 1 ;
394498 }
395499 else
396500 {
397- Console . WriteLine ( " Date Time Attr Size Name" ) ;
398- Console . WriteLine ( "------------------- ----- ------------ ------------------------" ) ;
399- Console . WriteLine (
400- "{0:yyyy-MM-dd} {1:HH:mm:ss} {2}{3}{4}{5}{6} {7,12} {8}" ,
401- fi . CreationTimeUtc . ToLocalTime ( ) ,
402- fi . CreationTimeUtc . ToLocalTime ( ) ,
403- ( fi . Attributes & FileAttributes . Directory ) != 0 ? "D" : "." ,
404- ( fi . Attributes & FileAttributes . ReadOnly ) != 0 ? "R" : "." ,
405- ( fi . Attributes & FileAttributes . Hidden ) != 0 ? "H" : "." ,
406- ( fi . Attributes & FileAttributes . System ) != 0 ? "S" : "." ,
407- ( fi . Attributes & FileAttributes . Archive ) != 0 ? "A" : "." ,
408- fi . Length ,
409- fi . FileName ) ;
501+ // while we read, we will write info
502+ if ( outStream . HaveMultipleFiles )
503+ outStream . CopyTo ( new NullStream ( ) ) ;
410504 Console . WriteLine ( "------------------- ----- ------------ ------------------------" ) ;
411- // now, we have only one file, so there are no sense to write total
505+ // todo: think about total line
412506 // 4854 1018 2 files, 1 folders
413507 }
414508 }
0 commit comments