ab3b073ef6 2015-04-30 kinaba: import win32.windows; ab3b073ef6 2015-04-30 kinaba: import std.c.stdio; ab3b073ef6 2015-04-30 kinaba: import std.file; ab3b073ef6 2015-04-30 kinaba: import std.string; ab3b073ef6 2015-04-30 kinaba: import etc.c.zlib; ab3b073ef6 2015-04-30 kinaba: import libbz2.bzlib; ab3b073ef6 2015-04-30 kinaba: import util; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: // Bga書庫のファイルヘッダ形式 c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: align(1) struct BgaHeader c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: int checksum; // type~fname のsigned charでの和 c2b7a98c21 2011-02-23 kinaba: char method[4]; // "GZIP" または "BZ2\0" c2b7a98c21 2011-02-23 kinaba: uint compressed_size; // 圧縮後のデータサイズ( ヘッダは含まない ) c2b7a98c21 2011-02-23 kinaba: uint original_size; // 元のファイルサイズ c2b7a98c21 2011-02-23 kinaba: ushort date; // ファイルの更新日付( DOS形式 ) c2b7a98c21 2011-02-23 kinaba: ushort time; // ファイルの更新時刻( DOS形式 ) c2b7a98c21 2011-02-23 kinaba: ubyte attrib; // ファイルの属性 c2b7a98c21 2011-02-23 kinaba: // ( 1:RO 2:Hid 4:Sys 8:Vol 16:Dir 32:Arc ) c2b7a98c21 2011-02-23 kinaba: ubyte header_type; // ヘッダの種類( 現在は常に 0 ) c2b7a98c21 2011-02-23 kinaba: ushort arc_type; // アーカイブタイプ c2b7a98c21 2011-02-23 kinaba: // 0:(ext==↓?非圧縮:圧縮) 1:圧縮 2:非圧縮 c2b7a98c21 2011-02-23 kinaba: // .ARC, .ARJ, .BZ2, .BZA, .CAB, .GZ, .GZA, .LZH, c2b7a98c21 2011-02-23 kinaba: // .LZS, .PAK, .RAR, .TAZ, .TBZ, .TGZ, .Z, .ZIP, .ZOO c2b7a98c21 2011-02-23 kinaba: ushort dir_name_len; // ディレクトリ名の長さ c2b7a98c21 2011-02-23 kinaba: ushort file_name_len; // ファイル名の長さ 4e2933c620 2015-04-21 kinaba: string fname; // dir_name_len + file_name_len ( no '\0' ) c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: // エラー発生時に投げる例外 c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: class BgaMelterError : Error c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: int errcode; c2b7a98c21 2011-02-23 kinaba: this( int e ) { super("BgaMelterError"); errcode=e; } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: enum c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: ERROR_FILE_OPEN=0x800D,// ファイルを開けませんでした。 c2b7a98c21 2011-02-23 kinaba: ERROR_MAKEDIRECTORY=0x8012,// ディレクトリが作成できません。 c2b7a98c21 2011-02-23 kinaba: ERROR_CANNOT_WRITE=0x8013,// 書き込みエラーが生じました。 c2b7a98c21 2011-02-23 kinaba: ERROR_HEADER_CRC=0x8016,// 書庫のヘッダのチェックサムが合っていません。 c2b7a98c21 2011-02-23 kinaba: ERROR_ARC_FILE_OPEN=0x8018,// 書庫を開く事が出来ません。 c2b7a98c21 2011-02-23 kinaba: ERROR_NOT_ARC_FILE=0x8019,// 書庫のファイル名が指定されていません。 c2b7a98c21 2011-02-23 kinaba: ERROR_CANNOT_READ=0x801A,// ファイルの読み込み時にエラーが生じました。 c2b7a98c21 2011-02-23 kinaba: ERROR_FILE_STYLE=0x801B,// 指定されたファイルは有効な書庫ではありません。 c2b7a98c21 2011-02-23 kinaba: ERROR_COMMAND_NAME=0x801C,// コマンド指定が間違っています。 c2b7a98c21 2011-02-23 kinaba: ERROR_MORE_HEAP_MEMORY=0x801D,// 作業用のためのヒープメモリが不足しています。 c2b7a98c21 2011-02-23 kinaba: ERROR_ALREADY_RUNNING=0x801F,// 既に BGA32.DLL が動作中です。 c2b7a98c21 2011-02-23 kinaba: ERROR_USER_CANCEL=0x8020,// ユーザーによって処理を中断されました。 c2b7a98c21 2011-02-23 kinaba: ERROR_TMP_OPEN=0x8025,// 作業ファイルが作成できません。 c2b7a98c21 2011-02-23 kinaba: ERROR_ARC_READ_ONLY=0x8027,// 書き込み専用属性の書庫に対する操作はできません。 c2b7a98c21 2011-02-23 kinaba: ERROR_NOT_FIND_ARC_FILE=0x8029,// 指定されたディレクトリには書庫がありませんでした。 c2b7a98c21 2011-02-23 kinaba: ERROR_RESPONSE_READ=0x802A,// レスポンスファイルの読み込み時にエラーが生じました。 c2b7a98c21 2011-02-23 kinaba: ERROR_TMP_COPY=0x802C,// 作業ファイルの書庫への書き戻しができませんでした。 c2b7a98c21 2011-02-23 kinaba: ERROR_NOT_FIND_FILE=0x8031,// ファイルが見つかりません。 c2b7a98c21 2011-02-23 kinaba: ERROR_GET_ATTRIBUTES=0x8034,// ファイル属性が取得できません。 c2b7a98c21 2011-02-23 kinaba: ERROR_GET_INFORMATION=0x8036,// ファイル情報が取得できません。 c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: // コールバック関数の返答用型 c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: enum BgaAnswer c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: MeltIt, SkipIt, Abort c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: // Filep c2b7a98c21 2011-02-23 kinaba: // D言語らしからぬのですがzlibやlibbz2と簡単に連携する c2b7a98c21 2011-02-23 kinaba: // 都合上std.c.stdio.FILE*でファイルを読み書きします。 c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: extern(C) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // stdio.h c2b7a98c21 2011-02-23 kinaba: int fileno( FILE *fp ) { return fp._file; } c2b7a98c21 2011-02-23 kinaba: // io.h c2b7a98c21 2011-02-23 kinaba: int lseek( int fd, int offset, int mode ); c2b7a98c21 2011-02-23 kinaba: int dup( int fd ); c2b7a98c21 2011-02-23 kinaba: int close( int fd ); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: class Filep c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: private FILE* fp; c2b7a98c21 2011-02-23 kinaba: private this( FILE* p ) { fp = p; } c2b7a98c21 2011-02-23 kinaba: 4e2933c620 2015-04-21 kinaba: static Filep open( string filename, bool read ) c2b7a98c21 2011-02-23 kinaba: { ab3b073ef6 2015-04-30 kinaba: FILE* fp = fopen(filename.toStringz(), read?"rb":"wb"); c2b7a98c21 2011-02-23 kinaba: return (fp ? new Filep(fp) : null); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int dup_han() c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: int fd = dup( fileno(fp) ); c2b7a98c21 2011-02-23 kinaba: lseek( fd, cur(), 0 ); c2b7a98c21 2011-02-23 kinaba: return fd; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void[] read( int siz ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: char[] buf; buf.length = siz; 4e2933c620 2015-04-21 kinaba: int rsiz = fread( buf.ptr, 1, siz, fp ); c2b7a98c21 2011-02-23 kinaba: if( rsiz < 0 ) c2b7a98c21 2011-02-23 kinaba: throw new BgaMelterError(ERROR_FILE_OPEN); c2b7a98c21 2011-02-23 kinaba: buf.length = rsiz; c2b7a98c21 2011-02-23 kinaba: return buf; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void write( void[] buf ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: while( buf.length > 0 ) c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: int rsiz = fwrite( buf.ptr, 1, buf.length, fp ); c2b7a98c21 2011-02-23 kinaba: if( rsiz < 0 ) return; 4e2933c620 2015-04-21 kinaba: buf = buf[rsiz .. $]; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int cur() c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: return ftell(fp); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void seek_to( int i ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: fseek( fp, i, std.c.stdio.SEEK_SET ); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void close() c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: fclose(fp); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: FILE* get_fp() c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: return fp; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: // メインクラス c2b7a98c21 2011-02-23 kinaba: //---------------------------------------------------------------- c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: class BgaMelter c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: alias BgaAnswer delegate(ref BgaHeader) FileHandler; ab3b073ef6 2015-04-30 kinaba: alias BgaAnswer delegate(int, int) ProgressHandler; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private Filep fp = null; c2b7a98c21 2011-02-23 kinaba: 4e2933c620 2015-04-21 kinaba: this( string arc_name ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: fp = Filep.open( arc_name, true ); c2b7a98c21 2011-02-23 kinaba: if( fp is null ) c2b7a98c21 2011-02-23 kinaba: throw new BgaMelterError(ERROR_FILE_OPEN); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void close() c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: if( fp ) { fp.close(); fp = null; } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: void start( FileHandler fh, ProgressHandler ph ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: try c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // ヘッダを探す c2b7a98c21 2011-02-23 kinaba: int hpos = find_header(); c2b7a98c21 2011-02-23 kinaba: if( hpos == -1 ) c2b7a98c21 2011-02-23 kinaba: throw new BgaMelterError(ERROR_NOT_ARC_FILE); c2b7a98c21 2011-02-23 kinaba: fp.seek_to(hpos); c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // ループ: c2b7a98c21 2011-02-23 kinaba: // ヘッダ読みとり c2b7a98c21 2011-02-23 kinaba: BgaHeader hdr; c2b7a98c21 2011-02-23 kinaba: while( read_header(hdr) ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // 次のヘッダ位置を計算しておく c2b7a98c21 2011-02-23 kinaba: uint nextpos = fp.cur() + hdr.compressed_size; c2b7a98c21 2011-02-23 kinaba: try c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // callback c2b7a98c21 2011-02-23 kinaba: BgaAnswer a = fh(hdr); c2b7a98c21 2011-02-23 kinaba: if( a == BgaAnswer.Abort ) return; c2b7a98c21 2011-02-23 kinaba: if( a == BgaAnswer.SkipIt ) continue; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 出力先ファイルを開く c2b7a98c21 2011-02-23 kinaba: if( lastChar(hdr.fname)=='\\' ) c2b7a98c21 2011-02-23 kinaba: { pathMake(hdr.fname); continue; } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: Filep outf = Filep.open( pathMake(hdr.fname), false ); c2b7a98c21 2011-02-23 kinaba: if( outf is null ) c2b7a98c21 2011-02-23 kinaba: throw new BgaMelterError(ERROR_FILE_OPEN); c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 解凍処理 c2b7a98c21 2011-02-23 kinaba: bool bContinue = true; c2b7a98c21 2011-02-23 kinaba: if( !is_compressed(hdr) ) c2b7a98c21 2011-02-23 kinaba: bContinue = NcDec( hdr.original_size, outf, ph ); c2b7a98c21 2011-02-23 kinaba: else if( hdr.method == "GZIP" ) c2b7a98c21 2011-02-23 kinaba: bContinue = GzDec( hdr.compressed_size, hdr.original_size, outf, ph ); c2b7a98c21 2011-02-23 kinaba: else if( hdr.method == "BZ2\0" ) c2b7a98c21 2011-02-23 kinaba: bContinue = BzDec( hdr.original_size, outf, ph ); c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 閉じて属性設定 c2b7a98c21 2011-02-23 kinaba: outf.close(); c2b7a98c21 2011-02-23 kinaba: dosSetFTime( hdr.fname, hdr.date, hdr.time ); ab3b073ef6 2015-04-30 kinaba: SetFileAttributesA( hdr.fname.toStringz(), hdr.attrib ); c2b7a98c21 2011-02-23 kinaba: if( !bContinue ) c2b7a98c21 2011-02-23 kinaba: return; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: finally { fp.seek_to(nextpos); } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: finally { close(); } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: static int signed_char( char c ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: int cn = c; c2b7a98c21 2011-02-23 kinaba: return (cn>=0x80 ? cn|0xffffff00 : cn); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private int find_header() c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: string dat = cast(string) fp.read(0x10000); c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: for( int i=0; i<dat.length-28; ++i ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: if( dat[i+4]!='G' && dat[i+4]!='B' ) continue; c2b7a98c21 2011-02-23 kinaba: if( dat[i+5]!='Z' ) continue; c2b7a98c21 2011-02-23 kinaba: if( dat[i+6]!='I' && dat[i+6]!='2' ) continue; c2b7a98c21 2011-02-23 kinaba: if( dat[i+7]!='P' && dat[i+7]!='\0') continue; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int checksum = dat[i+0]+(dat[i+1]<<8)+(dat[i+2]<<16)+(dat[i+3]<<24); c2b7a98c21 2011-02-23 kinaba: uint fnlen = dat[i+24]+(dat[i+25]<<8)+dat[i+26]+(dat[i+27]<<8); c2b7a98c21 2011-02-23 kinaba: if( i+28+fnlen > dat.length ) continue; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int sum = 0; c2b7a98c21 2011-02-23 kinaba: for( int j=i+4; j!=i+28+fnlen; ++j ) c2b7a98c21 2011-02-23 kinaba: sum += signed_char(dat[j]); c2b7a98c21 2011-02-23 kinaba: if( checksum == sum ) c2b7a98c21 2011-02-23 kinaba: return i; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: return -1; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private bool read_header( out BgaHeader hdr ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // リトルエンディアンを仮定。ヘッダ読み込み 9b639cf2d6 2015-05-05 kinaba: void[] buf = fp.read(28); c2b7a98c21 2011-02-23 kinaba: if( buf.length < 28 ) return false; c2b7a98c21 2011-02-23 kinaba: buf.length = BgaHeader.sizeof; c2b7a98c21 2011-02-23 kinaba: hdr = (cast(BgaHeader[]) buf)[0]; c2b7a98c21 2011-02-23 kinaba: hdr.fname = ""; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // ファイル名 4e2933c620 2015-04-21 kinaba: hdr.fname = cast(string) fp.read(hdr.dir_name_len + hdr.file_name_len); c2b7a98c21 2011-02-23 kinaba: if( hdr.fname.length < hdr.dir_name_len + hdr.file_name_len ) return false; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // チェックサム c2b7a98c21 2011-02-23 kinaba: int sum = 0; 9b639cf2d6 2015-05-05 kinaba: for( int i=4; i!=28; ++i ) sum += signed_char((cast(char[])buf)[i]); c2b7a98c21 2011-02-23 kinaba: foreach( char c ; hdr.fname ) sum += signed_char(c); c2b7a98c21 2011-02-23 kinaba: return (sum == hdr.checksum); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: 4e2933c620 2015-04-21 kinaba: private bool is_compressed( ref BgaHeader hdr ) // ref=just for optimization c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: // ヘッダから、ファイルが圧縮格納されているかどうかを判定 c2b7a98c21 2011-02-23 kinaba: if( hdr.arc_type==2 ) c2b7a98c21 2011-02-23 kinaba: return false; c2b7a98c21 2011-02-23 kinaba: if( hdr.arc_type==0 && hdr.compressed_size==hdr.original_size ) c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: int x = hdr.fname.lastIndexOf('.'); c2b7a98c21 2011-02-23 kinaba: if( x == -1 ) c2b7a98c21 2011-02-23 kinaba: return true; ab3b073ef6 2015-04-30 kinaba: string ext = hdr.fname[x+1 .. $].toLower(); c2b7a98c21 2011-02-23 kinaba: if( ext=="arc" || ext=="arj" || ext=="bz2" || ext=="bza" c2b7a98c21 2011-02-23 kinaba: || ext=="cab" || ext=="gz" || ext=="gza" || ext=="lzh" c2b7a98c21 2011-02-23 kinaba: || ext=="lzs" || ext=="pak" || ext=="rar" || ext=="taz" c2b7a98c21 2011-02-23 kinaba: || ext=="tbz" || ext=="tgz" || ext=="z" || ext=="zip" c2b7a98c21 2011-02-23 kinaba: || ext=="zoo" ) c2b7a98c21 2011-02-23 kinaba: return false; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: return true; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: 4e2933c620 2015-04-21 kinaba: static string pathMake( string path ) c2b7a98c21 2011-02-23 kinaba: { ab3b073ef6 2015-04-30 kinaba: char* ps = cast(char*)path.toStringz(); ab3b073ef6 2015-04-30 kinaba: for(char* p=ps;; ++p) c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: for(; *p!=0&&*p!='\\'&&*p!='/'; p=CharNextA(p)) {} c2b7a98c21 2011-02-23 kinaba: if( *p==0 ) c2b7a98c21 2011-02-23 kinaba: break; ab3b073ef6 2015-04-30 kinaba: CreateDirectoryA( ps[0..(p-ps)].toStringz(), null ); c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: return path; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: ab3b073ef6 2015-04-30 kinaba: enum BUFSIZ = 65536; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private bool NcDec( uint usiz, Filep outf, ProgressHandler ph ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: uint init_usiz = usiz; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 非圧縮。コピーするだけ c2b7a98c21 2011-02-23 kinaba: while( usiz ) c2b7a98c21 2011-02-23 kinaba: { 4e2933c620 2015-04-21 kinaba: string r = cast(string) fp.read( BUFSIZ<usiz?BUFSIZ:usiz ); c2b7a98c21 2011-02-23 kinaba: usiz -= r.length; 4e2933c620 2015-04-21 kinaba: outf.write(cast(char[])r); c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: return true; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private bool GzDec( uint csiz, uint usiz, Filep outf, ProgressHandler ph ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: uint init_usiz = usiz; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // zlibで展開 c2b7a98c21 2011-02-23 kinaba: fp.read(10); csiz -= 10; // ヘッダ,フッタスキップ c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: ubyte[] inbuf; inbuf.length = 65536; c2b7a98c21 2011-02-23 kinaba: ubyte[] outbuf; outbuf.length = 65536; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // zlib準備 c2b7a98c21 2011-02-23 kinaba: z_stream zs; c2b7a98c21 2011-02-23 kinaba: zs.zalloc = null; c2b7a98c21 2011-02-23 kinaba: zs.zfree = null; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 出力バッファ 4e2933c620 2015-04-21 kinaba: zs.next_out = outbuf.ptr; c2b7a98c21 2011-02-23 kinaba: zs.avail_out = outbuf.length; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 入力バッファ c2b7a98c21 2011-02-23 kinaba: inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 ); c2b7a98c21 2011-02-23 kinaba: csiz -= inbuf.length; 4e2933c620 2015-04-21 kinaba: zs.next_in = inbuf.ptr; c2b7a98c21 2011-02-23 kinaba: zs.avail_in = inbuf.length; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // スタート c2b7a98c21 2011-02-23 kinaba: inflateInit2( &zs, -15 ); c2b7a98c21 2011-02-23 kinaba: try { c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 書庫から入力し終わるまでループ c2b7a98c21 2011-02-23 kinaba: int err = Z_OK; c2b7a98c21 2011-02-23 kinaba: while( csiz&&usiz ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: while( zs.avail_out > 0 ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: err = etc.c.zlib.inflate( &zs, Z_PARTIAL_FLUSH ); c2b7a98c21 2011-02-23 kinaba: if( err!=Z_STREAM_END && err!=Z_OK ) c2b7a98c21 2011-02-23 kinaba: csiz=0; c2b7a98c21 2011-02-23 kinaba: if( !csiz ) c2b7a98c21 2011-02-23 kinaba: break; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: if( zs.avail_in<=0 ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: inbuf = cast(ubyte[]) fp.read( csiz<65536 ? csiz : 65536 ); c2b7a98c21 2011-02-23 kinaba: csiz -= inbuf.length; 4e2933c620 2015-04-21 kinaba: zs.next_in = inbuf.ptr; c2b7a98c21 2011-02-23 kinaba: zs.avail_in = inbuf.length; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: if( inbuf.length==0 ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: err = Z_STREAM_END; c2b7a98c21 2011-02-23 kinaba: csiz = 0; c2b7a98c21 2011-02-23 kinaba: break; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int written = outbuf.length - zs.avail_out; c2b7a98c21 2011-02-23 kinaba: if( usiz < written ) written = usiz; c2b7a98c21 2011-02-23 kinaba: usiz -= written; c2b7a98c21 2011-02-23 kinaba: outf.write( outbuf[0..written] ); 4e2933c620 2015-04-21 kinaba: zs.next_out = outbuf.ptr; c2b7a98c21 2011-02-23 kinaba: zs.avail_out = outbuf.length; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 出力残しを無くす。 c2b7a98c21 2011-02-23 kinaba: while( err!=Z_STREAM_END&&usiz ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: err = etc.c.zlib.inflate(&zs,Z_PARTIAL_FLUSH); c2b7a98c21 2011-02-23 kinaba: if( err!=Z_STREAM_END && err!=Z_OK ) c2b7a98c21 2011-02-23 kinaba: break; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: int written = outbuf.length - zs.avail_out; c2b7a98c21 2011-02-23 kinaba: if( usiz < written ) written = usiz; c2b7a98c21 2011-02-23 kinaba: usiz -= written; c2b7a98c21 2011-02-23 kinaba: outf.write( outbuf[0..written] ); 4e2933c620 2015-04-21 kinaba: zs.next_out = outbuf.ptr; c2b7a98c21 2011-02-23 kinaba: zs.avail_out = outbuf.length; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // 終了 c2b7a98c21 2011-02-23 kinaba: } finally { inflateEnd(&zs); } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: return true; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: private bool BzDec( uint usiz, Filep outf, ProgressHandler ph ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: uint init_usiz = usiz; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // libbz2で展開 c2b7a98c21 2011-02-23 kinaba: int err; 4e2933c620 2015-04-21 kinaba: BZFILE* b = BZ2_bzReadOpen( &err, fp.get_fp(), 0, 0, null, 0 ); c2b7a98c21 2011-02-23 kinaba: if( err!=BZ_OK || b is null ) c2b7a98c21 2011-02-23 kinaba: return true; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: try c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: char[] buf; buf.length = BUFSIZ; c2b7a98c21 2011-02-23 kinaba: int len; 4e2933c620 2015-04-21 kinaba: while( 0<(len=BZ2_bzRead( &err, b, buf.ptr, BUFSIZ<usiz?BUFSIZ:usiz )) ) c2b7a98c21 2011-02-23 kinaba: { c2b7a98c21 2011-02-23 kinaba: outf.write( buf[0..len] ); c2b7a98c21 2011-02-23 kinaba: usiz -= len; c2b7a98c21 2011-02-23 kinaba: if( err != BZ_OK ) c2b7a98c21 2011-02-23 kinaba: break; c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: } finally { BZ2_bzReadClose( &err, b ); } c2b7a98c21 2011-02-23 kinaba: c2b7a98c21 2011-02-23 kinaba: // dlg c2b7a98c21 2011-02-23 kinaba: if( BgaAnswer.Abort==ph(init_usiz-usiz,usiz) ) return false; c2b7a98c21 2011-02-23 kinaba: return true; c2b7a98c21 2011-02-23 kinaba: } c2b7a98c21 2011-02-23 kinaba: }